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

lsave.cpp

Go to the documentation of this file.
00001 #define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
00002 #define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
00003 
00004 #include "common/endian.h"
00005 #include "common/debug.h"
00006 
00007 #include "engines/grim/savegame.h"
00008 
00009 #include "engines/grim/lua/ltask.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/ltm.h"
00014 #include "engines/grim/lua/ltable.h"
00015 #include "engines/grim/lua/lvm.h"
00016 #include "engines/grim/lua/lopcodes.h"
00017 #include "engines/grim/lua/lstring.h"
00018 #include "engines/grim/lua/lua.h"
00019 
00020 namespace Grim {
00021 
00022 PointerId makeIdFromPointer(void *ptr) {
00023     PointerId pointer;
00024     pointer.id = (uintptr)ptr;
00025 
00026     return pointer;
00027 }
00028 
00029 void *makePointerFromId(PointerId ptr) {
00030     return (void *)ptr.id;
00031 }
00032 
00033 static void saveObjectValue(TObject *object, SaveGame *savedState) {
00034     savedState->writeLESint32(object->ttype);
00035 
00036     switch (object->ttype) {
00037         case LUA_T_CPROTO:
00038         case LUA_T_CMARK:
00039             {
00040                 luaL_libList *list = list_of_libs;
00041                 int32 idObj = 0;
00042                 while (list) {
00043                     for (int32 l = 0; l < list->number; l++) {
00044                         if (list->list[l].func == object->value.f) {
00045                             idObj = (idObj << 16) | l;
00046                             savedState->writeLESint32(idObj);
00047                             savedState->writeLESint32(0);
00048                             return;
00049                         }
00050                     }
00051                     list = list->next;
00052                     idObj++;
00053                 }
00054                 assert(0);
00055                 break;
00056             }
00057         case LUA_T_NUMBER:
00058         case LUA_T_TASK:
00059             {
00060                 savedState->writeFloat(object->value.n);
00061             }
00062             break;
00063         case LUA_T_NIL:
00064             break;
00065         case LUA_T_ARRAY:
00066             {
00067                 savedState->writeLEUint64(makeIdFromPointer(object->value.a).id);
00068             }
00069             break;
00070         case LUA_T_USERDATA:
00071             {
00072                 savedState->writeLESint32(object->value.ud.id);
00073                 savedState->writeLESint32(object->value.ud.tag);
00074             }
00075             break;
00076         case LUA_T_STRING:
00077             {
00078                 savedState->writeLEUint64(makeIdFromPointer(object->value.ts).id);
00079             }
00080             break;
00081         case LUA_T_PROTO:
00082         case LUA_T_PMARK:
00083             {
00084                 savedState->writeLEUint64(makeIdFromPointer(object->value.tf).id);
00085             }
00086             break;
00087         case LUA_T_CLOSURE:
00088         case LUA_T_CLMARK:
00089             {
00090                 savedState->writeLEUint64(makeIdFromPointer(object->value.cl).id);
00091             }
00092             break;
00093         case LUA_T_LINE:
00094             {
00095                 savedState->writeLESint32(object->value.i);
00096             }
00097             break;
00098         default:
00099             savedState->writeLEUint64(makeIdFromPointer(object->value.ts).id);
00100     }
00101 }
00102 
00103 static int32 opcodeSizeTable[] = {
00104     1, 2, 1, 2, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1,
00105     1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3,
00106     1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1,
00107     3, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1,
00108     1, 1, 1, 3, 1, 2, 3, 2, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00109     1, 1, 1, 1, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 1, 1,
00110     3, 2, 2, 2, 2, 3, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 3, 2, 1, 1,
00111     1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
00112     1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3,
00113     2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1,
00114     1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 3, 2, 4, 2, 1,
00115     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, 2, 3,
00116     2, 3, 2, 3, 2, 3, 2, 1, 1, 3, 2, 2, 2, 2, 3, 2, 1, 1
00117 };
00118 
00119 void lua_Save(SaveGame *savedState) {
00120     savedState->beginSection('LUAS');
00121 
00122     lua_collectgarbage(0);
00123     int32 i, l;
00124     int32 countElements = 0;
00125     int32 maxStringLength = 0;
00126 
00127 
00128     // Check for max length for strings and count them
00129     for (i = 0; i < NUM_HASHS; i++) {
00130         stringtable *tempStringTable = &string_root[i];
00131         for (l = 0; l < tempStringTable->size; l++) {
00132             if (tempStringTable->hash[l] && tempStringTable->hash[l] != &EMPTY) {
00133                 countElements++;
00134                 if (tempStringTable->hash[l]->constindex != -1) {
00135                     int len = strlen(tempStringTable->hash[l]->str);
00136                     if (maxStringLength < len) {
00137                         maxStringLength = len;
00138                     }
00139                 }
00140             }
00141         }
00142     }
00143     // save number of strings
00144     savedState->writeLESint32(countElements);
00145 
00146 
00147     // save number of closures
00148     countElements = 0;
00149     GCnode *tempNode;
00150     tempNode = rootcl.next;
00151     while (tempNode) {
00152         countElements++;
00153         tempNode = tempNode->next;
00154     }
00155     savedState->writeLESint32(countElements);
00156 
00157     // save number of tables
00158     countElements = 0;
00159     tempNode = roottable.next;
00160     while (tempNode) {
00161         countElements++;
00162         tempNode = tempNode->next;
00163     }
00164     savedState->writeLESint32(countElements);
00165 
00166     // save number of prototypes
00167     countElements = 0;
00168     tempNode = rootproto.next;
00169     while (tempNode) {
00170         countElements++;
00171         tempNode = tempNode->next;
00172     }
00173     savedState->writeLESint32(countElements);
00174 
00175     // save number of global strings
00176     countElements = 0;
00177     tempNode = rootglobal.next;
00178     while (tempNode) {
00179         countElements++;
00180         tempNode = tempNode->next;
00181     }
00182     savedState->writeLESint32(countElements);
00183 
00184     // save maximum length for string
00185     savedState->writeLESint32(maxStringLength);
00186 
00187     //printf("1: %d\n", g_grim->_savedState->getBufferPos());
00188 
00189     // save hash tables for strings and user data
00190     TaggedString *tempString;
00191     for (i = 0; i < NUM_HASHS; i++) {
00192         stringtable *tempStringTable = &string_root[i];
00193         for (l = 0; l < tempStringTable->size; l++) {
00194             if (tempStringTable->hash[l] && tempStringTable->hash[l] != &EMPTY) {
00195                 tempString = tempStringTable->hash[l];
00196                 savedState->writeLEUint64(makeIdFromPointer(tempString).id);
00197                 savedState->writeLESint32(tempString->constindex);
00198                 if (tempString->constindex != -1) {
00199                     saveObjectValue(&tempString->globalval, savedState);
00200                     int len = strlen(tempString->str);
00201                     savedState->writeLESint32(len);
00202                     savedState->write(tempString->str, len);
00203                 }
00204             }
00205         }
00206     }
00207 
00208     //printf("2: %d\n", g_grim->_savedState->getBufferPos());
00209 
00210     Closure *tempClosure = (Closure *)rootcl.next;
00211     while (tempClosure) {
00212         savedState->writeLEUint64(makeIdFromPointer(tempClosure).id);
00213         savedState->writeLESint32(tempClosure->nelems);
00214         for (i = 0; i <= tempClosure->nelems; i++) {
00215             saveObjectValue(&tempClosure->consts[i], savedState);
00216         }
00217         tempClosure = (Closure *)tempClosure->head.next;
00218     }
00219 
00220     Hash *tempHash = (Hash *)roottable.next;
00221     while (tempHash) {
00222         savedState->writeLEUint64(makeIdFromPointer(tempHash).id);
00223         savedState->writeLESint32(tempHash->nhash);
00224         int32 countUsedHash = 0;
00225         for (i = 0; i < tempHash->nhash; i++) {
00226             Node *newNode = &tempHash->node[i];
00227             if (newNode->ref.ttype != LUA_T_NIL && newNode->val.ttype != LUA_T_NIL) {
00228                 countUsedHash++;
00229             }
00230         }
00231         savedState->writeLESint32(countUsedHash);
00232         savedState->writeLESint32(tempHash->htag);
00233         for (i = 0; i < tempHash->nhash; i++) {
00234             Node *newNode = &tempHash->node[i];
00235             if (newNode->ref.ttype != LUA_T_NIL && newNode->val.ttype != LUA_T_NIL) {
00236                 saveObjectValue(&tempHash->node[i].ref, savedState);
00237                 saveObjectValue(&tempHash->node[i].val, savedState);
00238             }
00239         }
00240         tempHash = (Hash *)tempHash->head.next;
00241     }
00242 
00243     TProtoFunc *tempProtoFunc = (TProtoFunc *)rootproto.next;
00244     while (tempProtoFunc) {
00245         savedState->writeLEUint64(makeIdFromPointer(tempProtoFunc).id);
00246         savedState->writeLEUint64(makeIdFromPointer(tempProtoFunc->fileName).id);
00247         savedState->writeLESint32(tempProtoFunc->lineDefined);
00248         savedState->writeLESint32(tempProtoFunc->nconsts);
00249         for (i = 0; i < tempProtoFunc->nconsts; i++) {
00250             saveObjectValue(&tempProtoFunc->consts[i], savedState);
00251         }
00252         int32 countVariables = 0;
00253         if (tempProtoFunc->locvars) {
00254             for (; tempProtoFunc->locvars[countVariables++].line != -1;) { }
00255         }
00256 
00257         savedState->writeLESint32(countVariables);
00258         for (i = 0; i < countVariables; i++) {
00259             savedState->writeLEUint64(makeIdFromPointer(tempProtoFunc->locvars[i].varname).id);
00260             savedState->writeLESint32(tempProtoFunc->locvars[i].line);
00261         }
00262 
00263         byte *codePtr = tempProtoFunc->code + 2;
00264         byte *tmpPtr = codePtr;
00265         int32 opcodeId;
00266         do {
00267             opcodeId = *tmpPtr;
00268             tmpPtr += opcodeSizeTable[opcodeId];
00269         } while (opcodeId != ENDCODE);
00270         int32 codeSize = (tmpPtr - codePtr) + 2;
00271         savedState->writeLESint32(codeSize);
00272         savedState->write(tempProtoFunc->code, codeSize);
00273         tempProtoFunc = (TProtoFunc *)tempProtoFunc->head.next;
00274     }
00275 
00276     tempString = (TaggedString *)rootglobal.next;
00277     while (tempString) {
00278         savedState->writeLEUint64(makeIdFromPointer(tempString).id);
00279         tempString = (TaggedString *)tempString->head.next;
00280     }
00281 
00282     saveObjectValue(&errorim, savedState);
00283 
00284     IM *tempIm = IMtable;
00285     savedState->writeLESint32(IMtable_size);
00286     for (i = 0; i < IMtable_size; i++) {
00287         for (l = 0; l < IM_N; l++) {
00288             saveObjectValue(&tempIm->int_method[l], savedState);
00289         }
00290         tempIm++;
00291     }
00292 
00293     savedState->writeLESint32(last_tag);
00294     savedState->writeLESint32(refSize);
00295     for (i = 0 ; i < refSize; i++) {
00296         saveObjectValue(&refArray[i].o, savedState);
00297         savedState->writeLESint32(refArray[i].status);
00298     }
00299 
00300     savedState->writeLESint32(GCthreshold);
00301     savedState->writeLESint32(nblocks);
00302 
00303     savedState->writeLESint32(Mbuffsize);
00304     savedState->write(Mbuffer, Mbuffsize);
00305     int32 MbaseOffset = Mbuffbase - Mbuffer;
00306     savedState->writeLESint32(MbaseOffset);
00307     savedState->writeLESint32(Mbuffnext);
00308 
00309     savedState->writeLESint32(globalTaskSerialId);
00310 
00311     int32 countStates = 0, currentState = 0;
00312     LState *state = lua_rootState;
00313     while (state) {
00314         if (lua_state == state)
00315             currentState = countStates;
00316         countStates++;
00317         state = state->next;
00318     }
00319     savedState->writeLESint32(countStates);
00320     savedState->writeLESint32(currentState);
00321 
00322     state = lua_rootState;
00323     while (state) {
00324         lua_Task *task = state->task;
00325         int32 countTasks = 0, n = -1;
00326         while (task) {
00327             if (state->some_task && state->some_task == task)
00328                 n = countTasks;
00329             countTasks++;
00330             task = task->next;
00331         }
00332         savedState->writeLESint32(countTasks);
00333         task = state->task;
00334         while (task) {
00335             savedState->writeLEUint64(makeIdFromPointer(task->cl).id);
00336             savedState->writeLEUint64(makeIdFromPointer(task->tf).id);
00337             savedState->writeLESint32(task->base);
00338             savedState->writeLESint32(task->some_base);
00339             savedState->writeLESint32(task->some_results);
00340             savedState->writeBool(task->some_flag);
00341             int32 pcOffset = task->pc - task->tf->code;
00342             savedState->writeLESint32(pcOffset);
00343             savedState->writeLESint32(task->aux);
00344             task = task->next;
00345         }
00346 
00347         savedState->writeLESint32(n);
00348 
00349         savedState->writeBool(state->updated);
00350 
00351         byte pauseState = 0;
00352         pauseState = state->all_paused & LUA_SG_ALL_PAUSED;
00353         pauseState |= state->paused ? LUA_SG_PAUSED : 0;
00354         savedState->writeByte(pauseState);
00355 
00356         savedState->writeLESint32(state->state_counter1);
00357         savedState->writeLESint32(state->state_counter2);
00358 
00359         int32 stackLastSize = (state->stack.last - state->stack.stack) + 1;
00360         savedState->writeLESint32(stackLastSize);
00361         int32 stackTopSize = state->stack.top - state->stack.stack;
00362         savedState->writeLESint32(stackTopSize);
00363         for (i = 0; i < stackTopSize; i++) {
00364             saveObjectValue(&state->stack.stack[i], savedState);
00365         }
00366 
00367         savedState->writeLESint32(state->Cstack.base);
00368         savedState->writeLESint32(state->Cstack.lua2C);
00369         savedState->writeLESint32(state->Cstack.num);
00370 
00371         savedState->writeLESint32(state->numCblocks);
00372         for (i = 0; i < state->numCblocks; i++) {
00373             savedState->writeLESint32(state->Cblocks[i].base);
00374             savedState->writeLESint32(state->Cblocks[i].lua2C);
00375             savedState->writeLESint32(state->Cblocks[i].num);
00376         }
00377 
00378         savedState->writeLEUint32(state->sleepFor);
00379         savedState->writeLEUint32(state->id);
00380         saveObjectValue(&state->taskFunc, savedState);
00381 
00382         state = state->next;
00383     }
00384 
00385     savedState->endSection();
00386 }
00387 
00388 } // end of namespace Grim


Generated on Sat Feb 16 2019 05:00:56 for ResidualVM by doxygen 1.7.1
curved edge   curved edge