ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

ltask.cpp

Go to the documentation of this file.
00001 #define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
00002 #define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
00003 
00004 #ifdef _MSC_VER
00005 #pragma warning(disable:4611)
00006 #endif
00007 
00008 #include "engines/grim/lua/ltask.h"
00009 #include "engines/grim/lua/lapi.h"
00010 #include "engines/grim/lua/lauxlib.h"
00011 #include "engines/grim/lua/lmem.h"
00012 #include "engines/grim/lua/ldo.h"
00013 #include "engines/grim/lua/lvm.h"
00014 #include "engines/grim/grim.h"
00015 
00016 #include "common/textconsole.h"
00017 
00018 namespace Grim {
00019 
00020 void lua_taskinit(lua_Task *task, lua_Task *next, StkId tbase, int results) {
00021     task->some_flag = 0;
00022     task->next = next;
00023     task->some_base = tbase;
00024     task->some_results = results;
00025 }
00026 
00027 void lua_taskresume(lua_Task *task, Closure *closure, TProtoFunc *protofunc, StkId tbase) {
00028     task->cl = closure;
00029     task->tf = protofunc;
00030     task->base = tbase;
00031     task->pc = task->tf->code;
00032     task->consts = task->tf->consts;
00033     task->S = &lua_state->stack;
00034 }
00035 
00036 void start_script() {
00037     lua_Object paramObj = lua_getparam(1);
00038     lua_Type type = paramObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(paramObj));
00039 
00040     if (paramObj == LUA_NOOBJECT || (type != LUA_T_CPROTO && type != LUA_T_PROTO)) {
00041         if (g_grim->getGameType() == GType_MONKEY4) {
00042             /* In the discussion with meathook (dlg_meathook2.lua),
00043              * start_script is called as start_script(meathook:shake_head(...)).
00044              * But start_script expects start_script(meathook.shake_head, shake_head, ...). */
00045             warning("Bad argument to start_script, ignoring");
00046             lua_pushnil();
00047             return;
00048         } else {
00049             lua_error("Bad argument to start_script");
00050             return;
00051         }
00052     }
00053 
00054     LState *state = luaM_new(LState);
00055     lua_stateinit(state);
00056 
00057     state->next = lua_state->next;
00058     state->prev = lua_state;
00059     if (state->next)
00060         state->next->prev = state;
00061     lua_state->next = state;
00062 
00063     state->taskFunc.ttype = type;
00064     state->taskFunc.value = Address(paramObj)->value;
00065 
00066     int l = 2;
00067     for (lua_Object object = lua_getparam(l++); object != LUA_NOOBJECT; object = lua_getparam(l++)) {
00068         TObject ptr;
00069         ptr.ttype = Address(object)->ttype;
00070         ptr.value = Address(object)->value;
00071         LState *tmpState = lua_state;
00072         lua_state = state;
00073         luaA_pushobject(&ptr);
00074         lua_state = tmpState;
00075     }
00076 
00077     ttype(lua_state->stack.top) = LUA_T_TASK;
00078     nvalue(lua_state->stack.top) = (float)state->id;
00079     incr_top;
00080 }
00081 
00082 void next_script() {
00083     lua_Object paramObj = lua_getparam(1);
00084     lua_Type type = paramObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(paramObj));
00085 
00086     if (paramObj == LUA_NOOBJECT || (type != LUA_T_TASK && type != LUA_T_NIL))
00087         lua_error("Bad argument to next_script");
00088 
00089     if (type == LUA_T_TASK) {
00090         uint32 task = (uint32)nvalue(Address(paramObj));
00091         LState *state;
00092         for (state = lua_rootState->next; state != nullptr; state = state->next) {
00093             if (state->id == task) {
00094                 if (state->next) {
00095                     ttype(lua_state->stack.top) = LUA_T_TASK;
00096                     nvalue(lua_state->stack.top) = (float)state->next->id;
00097                     incr_top;
00098                 } else
00099                     lua_pushnil();
00100                 return;
00101             }
00102         }
00103     }
00104 
00105     if (lua_rootState->next) {
00106         ttype(lua_state->stack.top) = LUA_T_TASK;
00107         nvalue(lua_state->stack.top) = (float)lua_rootState->next->id;
00108         incr_top;
00109     } else
00110         lua_pushnil();
00111 }
00112 
00113 void stop_script() {
00114     lua_Object paramObj = lua_getparam(1);
00115     lua_Type type = paramObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(paramObj));
00116     LState *state;
00117 
00118     if (paramObj == LUA_NOOBJECT || (type != LUA_T_CPROTO && type != LUA_T_PROTO && type != LUA_T_TASK))
00119         lua_error("Bad argument to stop_script");
00120 
00121     if (type == LUA_T_TASK) {
00122         uint32 task = (uint32)nvalue(Address(paramObj));
00123         for (state = lua_rootState->next; state != nullptr; state = state->next) {
00124             if (state->id == task)
00125                 break;
00126         }
00127         if (state) {
00128             if (state != lua_state) {
00129                 lua_statedeinit(state);
00130                 luaM_free(state);
00131             }
00132         }
00133     } else if (type == LUA_T_PROTO || type == LUA_T_CPROTO) {
00134         for (state = lua_rootState->next; state != nullptr;) {
00135             bool match;
00136             if (type == LUA_T_PROTO) {
00137                 match = (state->taskFunc.ttype == type && tfvalue(&state->taskFunc) == tfvalue(Address(paramObj)));
00138             } else {
00139                 match = (state->taskFunc.ttype == type && fvalue(&state->taskFunc) == fvalue(Address(paramObj)));
00140             }
00141             if (match && state != lua_state) {
00142                 LState *tmp = state->next;
00143                 lua_statedeinit(state);
00144                 luaM_free(state);
00145                 state = tmp;
00146             } else {
00147                 state = state->next;
00148             }
00149         }
00150     }
00151 }
00152 
00153 void identify_script() {
00154     lua_Object paramObj = lua_getparam(1);
00155     lua_Type type = paramObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(paramObj));
00156 
00157     if (paramObj == LUA_NOOBJECT || type != LUA_T_TASK)
00158         lua_error("Bad argument to identify_script");
00159 
00160     uint32 task = (uint32)nvalue(Address(paramObj));
00161     LState *state;
00162     for (state = lua_rootState->next; state != nullptr; state = state->next) {
00163         if (state->id == task) {
00164             luaA_pushobject(&state->taskFunc);
00165             return;
00166         }
00167     }
00168 
00169     lua_pushnil();
00170 }
00171 
00172 void find_script() {
00173     lua_Object paramObj = lua_getparam(1);
00174     lua_Type type = paramObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(paramObj));
00175 
00176     if (paramObj == LUA_NOOBJECT || (type != LUA_T_CPROTO && type != LUA_T_PROTO && type != LUA_T_TASK)) {
00177         if (g_grim->getGameType() == GType_GRIM) {
00178             lua_error("Bad argument to find_script");
00179         } else {
00180             ttype(lua_state->stack.top) = LUA_T_TASK;
00181             nvalue(lua_state->stack.top) = lua_state->id;
00182             incr_top;
00183             lua_pushnumber(1.0f);
00184             return;
00185         }
00186     }
00187 
00188     if (type == LUA_T_TASK) {
00189         uint32 task = (uint32)nvalue(Address(paramObj));
00190         LState *state;
00191         for (state = lua_rootState->next; state != nullptr; state = state->next) {
00192             if (state->id == task) {
00193                 lua_pushobject(paramObj);
00194                 lua_pushnumber(1.0f);
00195                 return;
00196             }
00197         }
00198     } else if (type == LUA_T_PROTO || type == LUA_T_CPROTO) {
00199         int task = -1, countTasks = 0;
00200         bool match;
00201         LState *state;
00202         for (state = lua_rootState->next; state != nullptr; state = state->next) {
00203             if (type == LUA_T_PROTO) {
00204                 match = (state->taskFunc.ttype == type && tfvalue(&state->taskFunc) == tfvalue(Address(paramObj)));
00205             } else {
00206                 match = (state->taskFunc.ttype == type && fvalue(&state->taskFunc) == fvalue(Address(paramObj)));
00207             }
00208             if (match) {
00209                 task = state->id;
00210                 countTasks++;
00211             }
00212         }
00213         if (countTasks) {
00214             assert(task != -1);
00215             ttype(lua_state->stack.top) = LUA_T_TASK;
00216             nvalue(lua_state->stack.top) = (float)task;
00217             incr_top;
00218             lua_pushnumber((float)countTasks);
00219             return;
00220         }
00221     }
00222 
00223     lua_pushnil();
00224     lua_pushnumber(0.0f);
00225 }
00226 
00227 void pause_script() {
00228     lua_Object taskObj = lua_getparam(1);
00229     lua_Type type = taskObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(taskObj));
00230     if (type != LUA_T_TASK) {
00231         lua_error("Bad argument to pause_script");
00232         return;
00233     }
00234 
00235     uint32 task = (uint32)nvalue(Address(taskObj));
00236     LState *state;
00237     for (state = lua_rootState->next; state != nullptr; state = state->next) {
00238         if (state->id == task) {
00239             state->paused = true;
00240             return;
00241         }
00242     }
00243 }
00244 
00245 void pause_scripts() {
00246     LState *t;
00247     lua_Object boolObj = lua_getparam(1);
00248 
00249     bool p = false;
00250     if (!lua_isnil(boolObj))
00251         p = true;
00252 
00253 
00254     for (t = lua_rootState->next; t != nullptr; t = t->next) {
00255         if (lua_state != t) {
00256             if (p) {
00257                 t->all_paused++;
00258             } else {
00259                 t->all_paused = 1;
00260             }
00261         }
00262 
00263     }
00264 }
00265 
00266 void unpause_script() {
00267     lua_Object taskObj = lua_getparam(1);
00268     lua_Type type = taskObj == LUA_NOOBJECT ? LUA_T_NIL : ttype(Address(taskObj));
00269     if (type != LUA_T_TASK) {
00270         lua_error("Bad argument to unpause_script");
00271         return;
00272     }
00273 
00274     uint32 task = (uint32)nvalue(Address(taskObj));
00275     LState *state;
00276     for (state = lua_rootState->next; state != nullptr; state = state->next) {
00277         if (state->id == task) {
00278             state->paused = false;
00279             return;
00280         }
00281     }
00282 }
00283 
00284 void unpause_scripts() {
00285     LState *t;
00286     lua_Object boolObj = lua_getparam(1);
00287 
00288     bool p = false;
00289     if (!lua_isnil(boolObj))
00290         p = true;
00291 
00292     for (t = lua_rootState->next; t != nullptr; t = t->next) {
00293         if (lua_state != t) {
00294             if (p) {
00295                 if (t->all_paused > 0)
00296                     t->all_paused--;
00297             } else {
00298                 t->all_paused = 0;
00299             }
00300         }
00301     }
00302 }
00303 
00304 void current_script() {
00305     ttype(lua_state->stack.top) = LUA_T_TASK;
00306     nvalue(lua_state->stack.top) = (float)lua_state->id;
00307     incr_top;
00308 }
00309 
00310 void break_here() {}
00311 
00312 void sleep_for() {
00313     lua_Object msObj = lua_getparam(1);
00314 
00315     if (lua_isnumber(msObj)) {
00316         int ms = (int)lua_getnumber(msObj);
00317         lua_state->sleepFor = ms;
00318     }
00319 }
00320 
00321 void lua_runtasks() {
00322     if (!lua_state || !lua_state->next) {
00323         return;
00324     }
00325 
00326     // Mark all the states to be updated
00327     LState *state = lua_state->next;
00328     do {
00329         if (state->sleepFor > 0) {
00330             state->sleepFor -= g_grim->getFrameTime();
00331         } else {
00332             state->updated = false;
00333         }
00334         state = state->next;
00335     } while (state);
00336 
00337     // And run them
00338     runtasks(lua_state);
00339 }
00340 
00341 void runtasks(LState *const rootState) {
00342     lua_state = lua_state->next;
00343     while (lua_state) {
00344         LState *nextState = nullptr;
00345         bool stillRunning;
00346         if (!lua_state->all_paused && !lua_state->updated && !lua_state->paused) {
00347             jmp_buf errorJmp;
00348             lua_state->errorJmp = &errorJmp;
00349             if (setjmp(errorJmp)) {
00350                 lua_Task *t, *m;
00351                 for (t = lua_state->task; t != nullptr;) {
00352                     m = t->next;
00353                     luaM_free(t);
00354                     t = m;
00355                 }
00356                 stillRunning = false;
00357                 lua_state->task = nullptr;
00358             } else {
00359                 if (lua_state->task) {
00360                     stillRunning = luaD_call(lua_state->task->some_base, lua_state->task->some_results);
00361                 } else {
00362                     StkId base = lua_state->Cstack.base;
00363                     luaD_openstack((lua_state->stack.top - lua_state->stack.stack) - base);
00364                     set_normalized(lua_state->stack.stack + lua_state->Cstack.base, &lua_state->taskFunc);
00365                     stillRunning = luaD_call(base + 1, 255);
00366                 }
00367             }
00368             nextState = lua_state->next;
00369             // The state returned. Delete it
00370             if (!stillRunning) {
00371                 lua_statedeinit(lua_state);
00372                 luaM_free(lua_state);
00373             } else {
00374                 lua_state->updated = true;
00375             }
00376         } else {
00377             nextState = lua_state->next;
00378         }
00379         lua_state = nextState;
00380     }
00381 
00382     // Restore the value of lua_state to the main script
00383     lua_state = rootState;
00384     // Check for states that may have been created in this run.
00385     LState *state = lua_state->next;
00386     while (state) {
00387         if (!state->all_paused && !state->paused && !state->updated) {
00388             // New state! Run a new pass.
00389             runtasks(rootState);
00390             return;
00391         }
00392         state = state->next;
00393     }
00394 }
00395 
00396 } // end of namespace Grim


Generated on Sat May 18 2019 05:01:07 for ResidualVM by doxygen 1.7.1
curved edge   curved edge