diff --git a/engine/engine.cpp b/engine/engine.cpp index 0e1ae127d5a..5053e2ad4e2 100644 --- a/engine/engine.cpp +++ b/engine/engine.cpp @@ -464,14 +464,30 @@ void Engine::mainLoop() { } } -void Engine::savegameRead(void *data, int size) { +void Engine::savegameReadStream(void *data, int32 size) { g_engine->_savedState->read(data, size); } -void Engine::savegameWrite(void *data, int size) { +void Engine::savegameWriteStream(void *data, int32 size) { g_engine->_savedState->write(data, size); } +int32 Engine::savegameReadSint32() { + return g_engine->_savedState->readLESint32(); +} + +void Engine::savegameWriteSint32(int32 val) { + g_engine->_savedState->writeLESint32(val); +} + +uint32 Engine::savegameReadUint32() { + return g_engine->_savedState->readLEUint32(); +} + +void Engine::savegameWriteUint32(uint32 val) { + g_engine->_savedState->writeLEUint32(val); +} + void Engine::savegameRestore() { printf("Engine::savegameRestore() started.\n"); _savegameLoadRequest = false; @@ -502,7 +518,7 @@ void Engine::savegameRestore() { //Smush_Restore(_savedState); g_imuse->restoreState(_savedState); _savedState->beginSection('LUAS'); - lua_Restore(savegameRead); + lua_Restore(savegameReadStream, savegameReadSint32, savegameReadUint32); _savedState->endSection(); // unlock resources delete _savedState; @@ -566,7 +582,7 @@ void Engine::savegameSave() { //Smush_Save(_savedState); g_imuse->saveState(_savedState); _savedState->beginSection('LUAS'); - lua_Save(savegameWrite); + lua_Save(savegameWriteStream, savegameWriteSint32, savegameWriteUint32); _savedState->endSection(); delete _savedState; diff --git a/engine/engine.h b/engine/engine.h index 95fd6d0b22f..7ba4118aff1 100644 --- a/engine/engine.h +++ b/engine/engine.h @@ -168,8 +168,13 @@ public: void savegameSave(); void savegameRestore(); void savegameCallback(); - static void savegameRead(void *data, int size); - static void savegameWrite(void *data, int size); + static void savegameReadStream(void *data, int32 size); + static void savegameWriteStream(void *data, int32 size); + static int32 savegameReadSint32(); + static void savegameWriteSint32(int32 val); + static uint32 savegameReadUint32(); + static void savegameWriteUint32(uint32 val); + void storeSaveGameImage(SaveGame *savedState); bool _savegameLoadRequest; diff --git a/engine/imuse/imuse.cpp b/engine/imuse/imuse.cpp index 18675ccbb1d..8ba25942d65 100644 --- a/engine/imuse/imuse.cpp +++ b/engine/imuse/imuse.cpp @@ -88,33 +88,35 @@ void Imuse::restoreState(SaveGame *savedState) { printf("Imuse::restoreState() started.\n"); savedState->beginSection('IMUS'); - savedState->read(&_curMusicState, sizeof(int32)); - savedState->read(&_curMusicSeq, sizeof(int32)); - savedState->read(_attributes, sizeof(int32) * 185); + _curMusicState = savedState->readLESint32(); + _curMusicSeq = savedState->readLESint32(); + for (int r = 0; r < 185; r++) { + _attributes[r] = savedState->readLESint32(); + } for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) { Track *track = _track[l]; memset(track, 0, sizeof(Track)); track->trackId = l; - savedState->read(&track->pan, sizeof(int32)); - savedState->read(&track->panFadeDest, sizeof(int32)); - savedState->read(&track->panFadeDelay, sizeof(int32)); - savedState->read(&track->panFadeUsed, sizeof(bool)); - savedState->read(&track->vol, sizeof(int32)); - savedState->read(&track->volFadeDest, sizeof(int32)); - savedState->read(&track->volFadeDelay, sizeof(int32)); - savedState->read(&track->volFadeUsed, sizeof(bool)); + track->pan = savedState->readLESint32(); + track->panFadeDest = savedState->readLESint32(); + track->panFadeDelay = savedState->readLESint32(); + track->panFadeUsed = savedState->readLEBool(); + track->vol = savedState->readLESint32(); + track->volFadeDest = savedState->readLESint32(); + track->volFadeDelay = savedState->readLESint32(); + track->volFadeUsed = savedState->readLEBool(); savedState->read(track->soundName, 32); - savedState->read(&track->used, sizeof(bool)); - savedState->read(&track->toBeRemoved, sizeof(bool)); - savedState->read(&track->priority, sizeof(int32)); - savedState->read(&track->regionOffset, sizeof(int32)); - savedState->read(&track->dataOffset, sizeof(int32)); - savedState->read(&track->curRegion, sizeof(int32)); - savedState->read(&track->curHookId, sizeof(int32)); - savedState->read(&track->volGroupId, sizeof(int32)); - savedState->read(&track->feedSize, sizeof(int32)); - savedState->read(&track->mixerFlags, sizeof(int32)); + track->used = savedState->readLEBool(); + track->toBeRemoved = savedState->readLEBool(); + track->priority = savedState->readLESint32(); + track->regionOffset = savedState->readLESint32(); + track->dataOffset = savedState->readLESint32(); + track->curRegion = savedState->readLESint32(); + track->curHookId = savedState->readLESint32(); + track->volGroupId = savedState->readLESint32(); + track->feedSize = savedState->readLESint32(); + track->mixerFlags = savedState->readLESint32(); if (!track->used) continue; @@ -152,31 +154,33 @@ void Imuse::saveState(SaveGame *savedState) { printf("Imuse::saveState() started.\n"); savedState->beginSection('IMUS'); - savedState->write(&_curMusicState, sizeof(int32)); - savedState->write(&_curMusicSeq, sizeof(int32)); - savedState->write(_attributes, sizeof(int32) * 185); + savedState->writeLESint32(_curMusicState); + savedState->writeLESint32(_curMusicSeq); + for (int r = 0; r < 185; r++) { + savedState->writeLESint32(_attributes[r]); + } for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) { Track *track = _track[l]; - savedState->write(&track->pan, sizeof(int32)); - savedState->write(&track->panFadeDest, sizeof(int32)); - savedState->write(&track->panFadeDelay, sizeof(int32)); - savedState->write(&track->panFadeUsed, sizeof(bool)); - savedState->write(&track->vol, sizeof(int32)); - savedState->write(&track->volFadeDest, sizeof(int32)); - savedState->write(&track->volFadeDelay, sizeof(int32)); - savedState->write(&track->volFadeUsed, sizeof(bool)); + savedState->writeLESint32(track->pan); + savedState->writeLESint32(track->panFadeDest); + savedState->writeLESint32(track->panFadeDelay); + savedState->writeLEBool(track->panFadeUsed); + savedState->writeLESint32(track->vol); + savedState->writeLESint32(track->volFadeDest); + savedState->writeLESint32(track->volFadeDelay); + savedState->writeLEBool(track->volFadeUsed); savedState->write(track->soundName, 32); - savedState->write(&track->used, sizeof(bool)); - savedState->write(&track->toBeRemoved, sizeof(bool)); - savedState->write(&track->priority, sizeof(int32)); - savedState->write(&track->regionOffset, sizeof(int32)); - savedState->write(&track->dataOffset, sizeof(int32)); - savedState->write(&track->curRegion, sizeof(int32)); - savedState->write(&track->curHookId, sizeof(int32)); - savedState->write(&track->volGroupId, sizeof(int32)); - savedState->write(&track->feedSize, sizeof(int32)); - savedState->write(&track->mixerFlags, sizeof(int32)); + savedState->writeLEBool(track->used); + savedState->writeLEBool(track->toBeRemoved); + savedState->writeLESint32(track->priority); + savedState->writeLESint32(track->regionOffset); + savedState->writeLESint32(track->dataOffset); + savedState->writeLESint32(track->curRegion); + savedState->writeLESint32(track->curHookId); + savedState->writeLESint32(track->volGroupId); + savedState->writeLESint32(track->feedSize); + savedState->writeLESint32(track->mixerFlags); } savedState->endSection(); printf("Imuse::saveState() finished.\n"); diff --git a/engine/lua.cpp b/engine/lua.cpp index 0dbaf1e4568..10f2187ccd2 100644 --- a/engine/lua.cpp +++ b/engine/lua.cpp @@ -3112,14 +3112,14 @@ static void Save() { g_engine->_savegameSaveRequest = true; } -static int SaveCallback(int /*tag*/, int value, SaveRestoreFunc /*savedState*/) { +static PointerId saveCallback(int32 /*tag*/, PointerId ptr, SaveSint32 /*savedState*/) { DEBUG_FUNCTION(); - return value; + return ptr; } -static int RestoreCallback(int /*tag*/, int value, SaveRestoreFunc /*savedState*/) { +static PointerId restoreCallback(int32 /*tag*/, PointerId ptr, RestoreSint32 /*savedState*/) { DEBUG_FUNCTION(); - return value; + return ptr; } static void LockFont() { @@ -3871,8 +3871,8 @@ void register_lua() { lua_pushnumber(0x8000); lua_setglobal("HOT"); - saveCallback = SaveCallback; - restoreCallback = RestoreCallback; + saveCallbackPtr = saveCallback; + restoreCallbackPtr = restoreCallback; } int bundle_dofile(const char *filename) { diff --git a/engine/lua/lrestore.cpp b/engine/lua/lrestore.cpp index 31b136ec790..26a2cf7fc1a 100644 --- a/engine/lua/lrestore.cpp +++ b/engine/lua/lrestore.cpp @@ -9,21 +9,132 @@ #include "lstring.h" #include "lua.h" -SaveRestoreCallback restoreCallback = NULL; +#include "common/endian.h" + +RestoreCallback restoreCallbackPtr = NULL; + +static void restoreObjectValue(TObject *object, RestoreSint32 restoreSint32, RestoreUint32 restoreUint32) { + object->ttype = (lua_Type)restoreSint32(); + + switch (object->ttype) { + case LUA_T_NUMBER: + case LUA_T_TASK: + { + byte *udata = (byte *)(&object->value.n); + uint32 v = restoreUint32(); + restoreUint32(); +#if defined(SYSTEM_LITTLE_ENDIAN) + byte b[4]; + *(uint32 *)&b = v; + udata[0] = b[3]; + udata[1] = b[2]; + udata[2] = b[1]; + udata[3] = b[0]; +#else + memcpy(&udata, v, 4); +#endif + } + break; + case LUA_T_NIL: + { + restoreUint32(); + restoreUint32(); + object->value.ts = NULL; + } + break; + case LUA_T_ARRAY: + { + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + object->value.a = (Hash *)makePointerFromId(ptr); + } + break; + case LUA_T_USERDATA: + case LUA_T_STRING: + { + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + object->value.ts = (TaggedString *)makePointerFromId(ptr); + } + break; + case LUA_T_PROTO: + case LUA_T_PMARK: + { + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + object->value.tf = (TProtoFunc *)makePointerFromId(ptr); + } + break; + case LUA_T_CPROTO: + case LUA_T_CMARK: + { + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + object->value.f = (lua_CFunction)makePointerFromId(ptr); + } + break; + case LUA_T_CLOSURE: + case LUA_T_CLMARK: + { + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + object->value.cl = (Closure *)makePointerFromId(ptr); + } + break; + case LUA_T_LINE: + { + object->value.i = restoreSint32(); + restoreSint32(); + } + break; + case MKID_BE('ACTR'): + case MKID_BE('COLR'): + case MKID_BE('STAT'): + case MKID_BE('FONT'): + case MKID_BE('VBUF'): + case MKID_BE('PRIM'): + case MKID_BE('TEXT'): + { // TODO + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + object->value.ts = (TaggedString *)makePointerFromId(ptr); + } + break; + default: + lua_error("saveObjectValue: Unsupported object type"); + } +} struct ArrayIDObj { void *object; - int32 idObj; + PointerId idObj; }; static int32 sortCallback(const void *id1, const void *id2) { - if (((ArrayIDObj *)id1)->idObj > ((ArrayIDObj *)id2)->idObj) { +#ifdef TARGET_64BITS + uint64 p1 = ((ArrayIDObj *)id1)->idObj.low | (uint64)(((ArrayIDObj *)id1)->idObj.hi << 32) + uint64 p2 = ((ArrayIDObj *)id1)->idObj.low | (uint64)(((ArrayIDObj *)id1)->idObj.hi << 32) + if (p1 > p2) { return 1; - } else if (((ArrayIDObj *)id1)->idObj < ((ArrayIDObj *)id2)->idObj) { + } else if (p1 < p2) { + return -1; + } else { + return 0; +#else + if (((ArrayIDObj *)id1)->idObj.low > ((ArrayIDObj *)id2)->idObj.low) { + return 1; + } else if (((ArrayIDObj *)id1)->idObj.low < ((ArrayIDObj *)id2)->idObj.low) { return -1; } else { return 0; } +#endif } int32 arrayHashTablesCount = 0; @@ -38,23 +149,31 @@ static bool arraysAllreadySort = false; static void recreateObj(TObject *obj) { if (obj->ttype == LUA_T_CPROTO) { - unsigned long some = ((unsigned long)(obj->value.f)) >> 16; +#ifdef TARGET_64BITS + uint64 id = ((uint64)(obj->value.f)) >> 16; +#else + uint32 id = ((uint32)(obj->value.f)) >> 16; +#endif luaL_libList *list = list_of_libs; - while (list != NULL) { - if (some == 0) + while (list) { + if (id == 0) break; - some--; + id--; list = list->next; } - long numberFunc = (long)(obj->value.f) & 0xffff; - if ((list != NULL) && (some == 0) && (numberFunc < list->number)) { +#ifdef TARGET_64BITS + int32 numberFunc = (uint64)(obj->value.f) & 0xffff; +#else + int32 numberFunc = (uint32)(obj->value.f) & 0xffff; +#endif + if (list && id == 0 && numberFunc < list->number) { obj->value.f = list->list[numberFunc].func; } else { obj->value.f = NULL; assert(obj->value.f); } - } else if ((obj->ttype == LUA_T_NIL) || (obj->ttype == LUA_T_LINE) || (obj->ttype == LUA_T_NUMBER) ) { + } else if (obj->ttype == LUA_T_NIL || obj->ttype == LUA_T_LINE || obj->ttype == LUA_T_NUMBER) { return; } else { if (obj->value.i == 0) @@ -70,83 +189,98 @@ static void recreateObj(TObject *obj) { ArrayIDObj *found; ArrayIDObj tmpId; - - tmpId.idObj = obj->value.i; tmpId.object = NULL; - obj->value.i = 0; switch (obj->ttype) { case LUA_T_PMARK: + tmpId.idObj = makeIdFromPointer(obj->value.tf); found = (ArrayIDObj *)bsearch(&tmpId, arrayProtoFuncs, arrayProtoFuncsCount, sizeof(ArrayIDObj), sortCallback); + assert(found); + obj->value.tf = (TProtoFunc *)found->object; break; case LUA_T_USERDATA: + tmpId.idObj = makeIdFromPointer(obj->value.ts); found = (ArrayIDObj *)bsearch(&tmpId, arrayStrings, arrayStringsCount, sizeof(ArrayIDObj), sortCallback); + assert(found); + obj->value.ts = (TaggedString *)found->object; break; case LUA_T_PROTO: + tmpId.idObj = makeIdFromPointer(obj->value.tf); found = (ArrayIDObj *)bsearch(&tmpId, arrayProtoFuncs, arrayProtoFuncsCount, sizeof(ArrayIDObj), sortCallback); + assert(found); + obj->value.tf = (TProtoFunc *)found->object; break; case LUA_T_CLOSURE: + tmpId.idObj = makeIdFromPointer(obj->value.cl); found = (ArrayIDObj *)bsearch(&tmpId, arrayClosures, arrayClosuresCount, sizeof(ArrayIDObj), sortCallback); + assert(found); + obj->value.cl = (Closure *)found->object; break; case LUA_T_ARRAY: + tmpId.idObj = makeIdFromPointer(obj->value.a); found = (ArrayIDObj *)bsearch(&tmpId, arrayHashTables, arrayHashTablesCount, sizeof(ArrayIDObj), sortCallback); + assert(found); + obj->value.a = (Hash *)found->object; break; case LUA_T_STRING: + tmpId.idObj = makeIdFromPointer(obj->value.ts); found = (ArrayIDObj *)bsearch(&tmpId, arrayStrings, arrayStringsCount, sizeof(ArrayIDObj), sortCallback); + assert(found); + obj->value.ts = (TaggedString *)found->object; break; default: + obj->value.i = 0; + obj->value.ts = 0; return; } - - //obj->value.i = (int32)found->object; } } -void lua_Restore(SaveRestoreFunc restoreFunc) { +void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, RestoreUint32 restoreUint32) { printf("lua_Restore() started.\n"); -/* + lua_close(); L = luaM_new(lua_State); lua_resetglobals(); - restoreFunc(&arrayStringsCount, sizeof(int32)); - restoreFunc(&arrayClosuresCount, sizeof(int32)); - restoreFunc(&arrayHashTablesCount, sizeof(int32)); - restoreFunc(&arrayProtoFuncsCount, sizeof(int32)); - int32 rootGlobalCount; - restoreFunc(&rootGlobalCount, sizeof(int32)); + arrayStringsCount = restoreSint32(); + arrayClosuresCount = restoreSint32(); + arrayHashTablesCount = restoreSint32(); + arrayProtoFuncsCount = restoreSint32(); + int32 rootGlobalCount = restoreSint32(); arrayStrings = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayStringsCount); ArrayIDObj *arraysObj = arrayStrings; int32 maxStringsLength; - restoreFunc(&maxStringsLength, sizeof(int32)); + maxStringsLength = restoreSint32(); char *tempStringBuffer = (char *)luaM_malloc(maxStringsLength); int32 i; for (i = 0; i < arrayStringsCount; i++) { - restoreFunc(&arraysObj->idObj, sizeof(int32)); - int32 constIndex; - restoreFunc(&constIndex, sizeof(int32)); - lua_Type tag; - restoreFunc(&tag, sizeof(int32)); - void *value; - restoreFunc(&value, sizeof(void *)); + arraysObj->idObj.low = restoreSint32(); + arraysObj->idObj.hi = restoreSint32(); + int32 constIndex = restoreSint32(); + lua_Type tag = (lua_Type)restoreSint32(); + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); TaggedString *tempString; if (constIndex != -1) { - int32 length; - restoreFunc(&length, sizeof(int32)); - restoreFunc(tempStringBuffer, length); + int32 length = restoreSint32(); + restoreStream(tempStringBuffer, length); tempString = luaS_newlstr(tempStringBuffer, length); tempString->u.s.globalval.ttype = tag; - tempString->u.s.globalval.value.ts = (TaggedString *)value; + tempString->u.s.globalval.value.ts = (TaggedString *)makePointerFromId(ptr); } else { if (tag == 0) - tempString = luaS_createudata(value, LUA_ANYTAG); + tempString = luaS_createudata((void *)makePointerFromId(ptr), LUA_ANYTAG); else - tempString = luaS_createudata(value, tag); - if (restoreCallback != NULL) { - tempString->u.s.globalval.value.ts = (TaggedString *)restoreCallback(tempString->u.s.globalval.ttype, (int32)tempString->u.s.globalval.value.ts, restoreFunc); + tempString = luaS_createudata((void *)makePointerFromId(ptr), tag); + if (restoreCallbackPtr) { + PointerId ptr = makeIdFromPointer(tempString->u.s.globalval.value.ts); + ptr = restoreCallbackPtr(tempString->u.s.globalval.ttype, ptr, restoreSint32); + tempString->u.s.globalval.value.ts = (TaggedString *)makePointerFromId(ptr); } } tempString->constindex = constIndex; @@ -160,16 +294,15 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayClosuresCount); arrayClosures = arraysObj; for (i = 0; i < arrayClosuresCount; i++) { - restoreFunc(&arraysObj->idObj, sizeof(int32)); - int32 countElements; - restoreFunc(&countElements, sizeof(int32)); + arraysObj->idObj.low = restoreSint32(); + arraysObj->idObj.hi = restoreSint32(); + int32 countElements = restoreSint32(); tempClosure = (Closure *)luaM_malloc((countElements * sizeof(TObject)) + sizeof(Closure)); luaO_insertlist(&L->rootcl, (GCnode *)tempClosure); tempClosure->nelems = countElements; for (l = 0; l <= tempClosure->nelems; l++) { - restoreFunc(&tempClosure->consts[l].ttype, sizeof(lua_Type)); - restoreFunc(&tempClosure->consts[l].value, sizeof(Value)); + restoreObjectValue(&tempClosure->consts[l], restoreSint32, restoreUint32); } arraysObj->object = tempClosure; arraysObj++; @@ -179,19 +312,18 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayHashTablesCount); arrayHashTables = arraysObj; for (i = 0; i < arrayHashTablesCount; i++) { - restoreFunc(&arraysObj->idObj, sizeof(int32)); + arraysObj->idObj.low = restoreSint32(); + arraysObj->idObj.hi = restoreSint32(); tempHash = luaM_new(Hash); - restoreFunc(&tempHash->nhash, sizeof(int32)); - restoreFunc(&tempHash->nuse, sizeof(int32)); - restoreFunc(&tempHash->htag, sizeof(int32)); + tempHash->nhash = restoreSint32(); + tempHash->nuse = restoreSint32(); + tempHash->htag = restoreSint32(); tempHash->node = hashnodecreate(tempHash->nhash); luaO_insertlist(&L->roottable, (GCnode *)tempHash); for (l = 0; l < tempHash->nuse; l++) { - restoreFunc(&tempHash->node[l].ref.ttype, sizeof(lua_Type)); - restoreFunc(&tempHash->node[l].ref.value, sizeof(Value)); - restoreFunc(&tempHash->node[l].val.ttype, sizeof(lua_Type)); - restoreFunc(&tempHash->node[l].val.value, sizeof(Value)); + restoreObjectValue(&tempHash->node[l].ref, restoreSint32, restoreUint32); + restoreObjectValue(&tempHash->node[l].val, restoreSint32, restoreUint32); } arraysObj->object = tempHash; arraysObj++; @@ -201,36 +333,40 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { arrayProtoFuncs = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayProtoFuncsCount); arraysObj = arrayProtoFuncs; for (i = 0; i < arrayProtoFuncsCount; i++) { - restoreFunc(&arraysObj->idObj, sizeof(int32)); + arraysObj->idObj.low = restoreSint32(); + arraysObj->idObj.hi = restoreSint32(); tempProtoFunc = luaM_new(TProtoFunc); luaO_insertlist(&L->rootproto, (GCnode *)tempProtoFunc); - restoreFunc(&tempProtoFunc->fileName, sizeof(TaggedString *)); - restoreFunc(&tempProtoFunc->lineDefined, sizeof(int32)); - restoreFunc(&tempProtoFunc->nconsts, sizeof(int32)); + PointerId ptr; + ptr.low = restoreSint32(); + ptr.hi = restoreSint32(); + tempProtoFunc->fileName = (TaggedString *)makePointerFromId(ptr); + tempProtoFunc->lineDefined = restoreSint32(); + tempProtoFunc->nconsts = restoreSint32(); tempProtoFunc->consts = (TObject *)luaM_malloc(tempProtoFunc->nconsts * sizeof(TObject)); for (l = 0; l < tempProtoFunc->nconsts; l++) { - restoreFunc(&tempProtoFunc->consts[l].ttype, sizeof(lua_Type)); - restoreFunc(&tempProtoFunc->consts[l].value, sizeof(Value)); + restoreObjectValue(&tempProtoFunc->consts[l], restoreSint32, restoreUint32); } - int32 countVariables; - restoreFunc(&countVariables, sizeof(int32)); - if (countVariables != 0) { + int32 countVariables = restoreSint32(); + if (countVariables) { tempProtoFunc->locvars = (LocVar *)luaM_malloc(countVariables * sizeof(LocVar)); } else { tempProtoFunc->locvars = NULL; } for (l = 0; l < countVariables; l++) { - restoreFunc(&tempProtoFunc->locvars[l].varname, sizeof(TaggedString *)); - restoreFunc(&tempProtoFunc->locvars[l].line, sizeof(int32)); + PointerId ptr; + ptr.low = restoreSint32(); + ptr.hi = restoreSint32(); + tempProtoFunc->locvars[l].varname = (TaggedString *)makePointerFromId(ptr); + tempProtoFunc->locvars[l].line = restoreSint32(); } - int32 codeSize; - restoreFunc(&codeSize, sizeof(int32)); + int32 codeSize = restoreSint32(); tempProtoFunc->code = (lua_Byte *)luaM_malloc(codeSize); - restoreFunc(tempProtoFunc->code, codeSize); + restoreStream(tempProtoFunc->code, codeSize); arraysObj->object = tempProtoFunc; arraysObj++; } @@ -239,14 +375,14 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { stringtable *tempStringTable = &L->string_root[i]; for (l = 0; l < tempStringTable->size; l++) { TaggedString *tempString = tempStringTable->hash[l]; - if ((tempString != NULL) && (tempString->constindex != -1) && (tempString != &EMPTY)) { + if (tempString && tempString->constindex != -1 && tempString != &EMPTY) { recreateObj(&tempString->u.s.globalval); } } } tempProtoFunc = (TProtoFunc *)L->rootproto.next; - while (tempProtoFunc != NULL) { + while (tempProtoFunc) { TObject tempObj; tempObj.value.ts = (TaggedString *)tempProtoFunc->fileName; tempObj.ttype = LUA_T_STRING; @@ -271,7 +407,7 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { } tempHash = (Hash *)L->roottable.next; - while (tempHash != NULL) { + while (tempHash) { for (i = 0; i < tempHash->nuse; i++) { recreateObj(&tempHash->node[i].ref); recreateObj(&tempHash->node[i].val); @@ -280,7 +416,7 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { tempHash->node = hashnodecreate(tempHash->nhash); for (i = 0; i < tempHash->nuse; i++) { Node *newNode = oldNode + i; - if ((newNode->val.ttype != LUA_T_NIL) && (newNode->ref.ttype != LUA_T_NIL)) { + if (newNode->ref.ttype != LUA_T_NIL && newNode->val.ttype != LUA_T_NIL) { *node(tempHash, present(tempHash, &newNode->ref)) = *newNode; } } @@ -289,7 +425,7 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { } tempClosure = (Closure *)L->rootcl.next; - while (tempClosure != NULL) { + while (tempClosure) { for (i = 0; i <= tempClosure->nelems; i++) { recreateObj(&tempClosure->consts[i]); } @@ -301,7 +437,10 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { TObject tempObj; TaggedString *tempString = NULL; tempObj.ttype = LUA_T_STRING; - restoreFunc(&tempObj.value, sizeof(TaggedString *)); + PointerId ptr; + ptr.low = restoreSint32(); + ptr.hi = restoreSint32(); + tempObj.value.ts = (TaggedString *)makePointerFromId(ptr); recreateObj(&tempObj); tempString = (TaggedString *)tempObj.value.ts; assert(tempString); @@ -310,81 +449,74 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { } tempListString->head.next = NULL; - restoreFunc(&L->errorim.ttype, sizeof(lua_Type)); - restoreFunc(&L->errorim.value, sizeof(Value)); + restoreObjectValue(&L->errorim, restoreSint32, restoreUint32); recreateObj(&L->errorim); - restoreFunc(&L->IMtable_size, sizeof(int32)); + L->IMtable_size = restoreSint32(); L->IMtable = (IM *)luaM_malloc(L->IMtable_size * sizeof(IM)); for (i = 0; i < L->IMtable_size; i++) { IM *im = &L->IMtable[i]; for (l = 0; l < IM_N; l++) { - restoreFunc(&im->int_method[l].ttype, sizeof(lua_Type)); - restoreFunc(&im->int_method[l].value, sizeof(Value)); + restoreObjectValue(&im->int_method[l], restoreSint32, restoreUint32); recreateObj(&im->int_method[l]); } } - restoreFunc(&L->last_tag, sizeof(int32)); - restoreFunc(&L->refSize, sizeof(int32)); + L->last_tag = restoreSint32(); + L->refSize = restoreSint32(); L->refArray = (ref *)luaM_malloc(L->refSize * sizeof(ref)); for (i = 0; i < L->refSize; i++) { - restoreFunc(&L->refArray[i].o.ttype, sizeof(lua_Type)); - restoreFunc(&L->refArray[i].o.value, sizeof(Value)); + restoreObjectValue(&L->refArray[i].o, restoreSint32, restoreUint32); recreateObj(&L->refArray[i].o); - restoreFunc(&L->refArray[i].status, sizeof(Status)); + L->refArray[i].status = (Status)restoreSint32(); } - restoreFunc(&L->GCthreshold, sizeof(int32)); - restoreFunc(&L->nblocks, sizeof(int32)); + L->GCthreshold = restoreSint32(); + L->nblocks = restoreSint32(); - restoreFunc(&L->Mbuffsize, sizeof(int32)); + L->Mbuffsize = restoreSint32(); L->Mbuffer = (char *)luaM_malloc(L->Mbuffsize); - restoreFunc(L->Mbuffer, L->Mbuffsize); + restoreStream(L->Mbuffer, L->Mbuffsize); int32 MbaseOffset; - restoreFunc(&MbaseOffset, sizeof(int32)); + MbaseOffset = restoreSint32(); L->Mbuffbase = MbaseOffset + L->Mbuffer; - restoreFunc(&L->Mbuffnext, sizeof(int32)); + L->Mbuffnext = restoreSint32(); - restoreFunc(&globalTaskSerialId, sizeof(int32)); + globalTaskSerialId = restoreSint32(); - int32 countTasks; lua_Task *tempTask = NULL; - restoreFunc(&countTasks, sizeof(int32)); lua_Task *prevTask = L->root_task; + int32 countTasks = restoreSint32(); for (l = 0; l < countTasks; l++) { tempTask = luaM_new(lua_Task); memset(tempTask, 0, sizeof(lua_Task)); prevTask->next = tempTask; prevTask = tempTask; - int32 stackLastSize; - restoreFunc(&stackLastSize, sizeof(int32)); + int32 stackLastSize = restoreSint32(); tempTask->stack.stack = (TObject *)luaM_malloc(stackLastSize * sizeof(TObject)); tempTask->stack.last = tempTask->stack.stack + stackLastSize - 1; - int32 stackTopSize; - restoreFunc(&stackTopSize, sizeof(int32)); + int32 stackTopSize = restoreSint32(); tempTask->stack.top = tempTask->stack.stack + stackTopSize; for (i = 0; i < stackTopSize; i++) { - restoreFunc(&tempTask->stack.stack[i].ttype, sizeof(lua_Type)); - restoreFunc(&tempTask->stack.stack[i].value, sizeof(Value)); + restoreObjectValue(&tempTask->stack.stack[i], restoreSint32, restoreUint32); recreateObj(&tempTask->stack.stack[i]); } - restoreFunc(&tempTask->Cstack.base, sizeof(StkId)); - restoreFunc(&tempTask->Cstack.lua2C, sizeof(StkId)); - restoreFunc(&tempTask->Cstack.num, sizeof(int32)); + tempTask->Cstack.base = restoreSint32(); + tempTask->Cstack.lua2C = restoreSint32(); + tempTask->Cstack.num = restoreSint32(); - restoreFunc(&tempTask->numCblocks, sizeof(int32)); + tempTask->numCblocks = restoreSint32(); for (i = 0; i < tempTask->numCblocks; i++) { - restoreFunc(&tempTask->Cblocks[i].base, sizeof(StkId)); - restoreFunc(&tempTask->Cblocks[i].lua2C, sizeof(StkId)); - restoreFunc(&tempTask->Cblocks[i].num, sizeof(int32)); + tempTask->Cblocks[i].base = restoreSint32(); + tempTask->Cblocks[i].lua2C = restoreSint32(); + tempTask->Cblocks[i].num = restoreSint32(); } int32 pcOffset, taskCi; - restoreFunc(&tempTask->base_ci_size, sizeof(int32)); + tempTask->base_ci_size = restoreSint32(); tempTask->base_ci = (CallInfo *)luaM_malloc(tempTask->base_ci_size * sizeof(CallInfo)); memset(tempTask->base_ci, 0, sizeof(CallInfo) * tempTask->base_ci_size); CallInfo *tempCi = tempTask->base_ci; @@ -392,35 +524,39 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { for (i = 0; i < countCi; i++) { TObject tempObj; tempObj.ttype = LUA_T_CLOSURE; - restoreFunc(&tempObj.value, sizeof(Closure *)); + PointerId ptr; + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + tempObj.value.cl = (Closure *)makePointerFromId(ptr); recreateObj(&tempObj); tempCi->c = (Closure *)tempObj.value.cl; tempObj.ttype = LUA_T_PROTO; - restoreFunc(&tempObj.value, sizeof(TProtoFunc *)); + ptr.low = restoreUint32(); + ptr.hi = restoreUint32(); + tempObj.value.tf = (TProtoFunc *)makePointerFromId(ptr); recreateObj(&tempObj); tempCi->tf = (TProtoFunc *)tempObj.value.tf; - restoreFunc(&pcOffset, sizeof(int32)); - if (pcOffset != 0) + pcOffset = restoreSint32(); + if (pcOffset) tempCi->pc = tempCi->tf->code + pcOffset; else tempCi->pc = NULL; - restoreFunc(&tempCi->base, sizeof(StkId)); - restoreFunc(&tempCi->nResults, sizeof(int32)); + tempCi->base = restoreSint32(); + tempCi->nResults = restoreSint32(); tempCi++; } - restoreFunc(&taskCi, sizeof(int32)); + taskCi = restoreSint32(); tempTask->ci = tempTask->base_ci + taskCi; tempTask->end_ci = tempTask->base_ci + countCi; - int32 Mbasepos; - restoreFunc(&Mbasepos, sizeof(int32)); + int32 Mbasepos = restoreSint32(); tempTask->Mbuffbase = Mbasepos + tempTask->Mbuffer; - restoreFunc(&tempTask->Mbuffnext, sizeof(int32)); + tempTask->Mbuffnext = restoreSint32(); - restoreFunc(&tempTask->Tstate, sizeof(TaskState)); - restoreFunc(&tempTask->id, sizeof(int32)); + tempTask->Tstate = (TaskState)restoreSint32(); + tempTask->id = restoreSint32(); } L->last_task = tempTask; @@ -437,6 +573,6 @@ void lua_Restore(SaveRestoreFunc restoreFunc) { arrayClosures = NULL; arrayProtoFuncs = NULL; arrayStrings = NULL; -*/ + printf("lua_Restore() finished.\n"); } diff --git a/engine/lua/lsave.cpp b/engine/lua/lsave.cpp index ec9f94296a3..577c94b039a 100644 --- a/engine/lua/lsave.cpp +++ b/engine/lua/lsave.cpp @@ -7,28 +7,136 @@ #include "lvm.h" #include "lopcodes.h" #include "lstring.h" +#include "lua.h" -SaveRestoreCallback saveCallback = NULL; +#include "common/endian.h" -static void saveObjectValue(TObject *object, SaveRestoreFunc saveFunc) { - saveFunc(&object->ttype, sizeof(lua_Type)); - if (object->ttype == LUA_T_CPROTO) { - luaL_libList *list = list_of_libs; - int32 idObj = 0; - while (list != NULL) { - for (int32 l = 0; l < list->number; l++) { - if (list->list[l].func == object->value.f) { - idObj = (idObj << 16) | l; - saveFunc(&idObj, sizeof(int32)); - return; +PointerId makeIdFromPointer(void *ptr) { + PointerId pointer; + +#ifdef TARGET_64BITS + uint64 v = (uint64)ptr; + pointer.low = v & 0xffffffff; + pointer.hi = v >> 32; +#else + pointer.low = (uint32)ptr; + pointer.hi = 0; +#endif + + return pointer; +} + +void *makePointerFromId(PointerId ptr) { + void *pointer; + +#ifdef TARGET_64BITS + uint64 v = ptr.low | ((uint64)ptr.hi << 32); + pointer = (void *)v; +#else + pointer = (void *)ptr.low; +#endif + + return pointer; +} + +SaveCallback saveCallbackPtr = NULL; + +static void saveObjectValue(TObject *object, SaveSint32 saveSint32, SaveUint32 saveUint32) { + saveSint32(object->ttype); + + switch (object->ttype) { + case LUA_T_CPROTO: + case LUA_T_CMARK: + { + luaL_libList *list = list_of_libs; + int32 idObj = 0; + while (list) { + for (int32 l = 0; l < list->number; l++) { + if (list->list[l].func == object->value.f) { + idObj = (idObj << 16) | l; + saveSint32(idObj); + saveSint32(0); + return; + } + } + list = list->next; + idObj++; } + assert(0); + break; } - list = list->next; - idObj++; - } - assert(0); - } else { - saveFunc(&object->value, sizeof(Value)); + case LUA_T_NUMBER: + case LUA_T_TASK: + { + byte *udata = (byte *)(&object->value.n); + uint32 v; +#if defined(SYSTEM_LITTLE_ENDIAN) + byte b[4]; + b[0] = udata[3]; + b[1] = udata[2]; + b[2] = udata[1]; + b[3] = udata[0]; + v = *(uint32 *)b; +#else + memcpy(&v, udata, 4); +#endif + saveUint32(v); + saveUint32(0); + } + break; + case LUA_T_NIL: + { + saveUint32(0); + saveUint32(0); + } + break; + case LUA_T_ARRAY: + { + saveUint32(makeIdFromPointer(object->value.a).low); + saveUint32(makeIdFromPointer(object->value.a).hi); + } + break; + case LUA_T_USERDATA: + case LUA_T_STRING: + { + saveUint32(makeIdFromPointer(object->value.ts).low); + saveUint32(makeIdFromPointer(object->value.ts).hi); + } + break; + case LUA_T_PROTO: + case LUA_T_PMARK: + { + saveUint32(makeIdFromPointer(object->value.tf).low); + saveUint32(makeIdFromPointer(object->value.tf).hi); + } + break; + case LUA_T_CLOSURE: + case LUA_T_CLMARK: + { + saveUint32(makeIdFromPointer(object->value.cl).low); + saveUint32(makeIdFromPointer(object->value.cl).hi); + } + break; + case LUA_T_LINE: + { + saveSint32(object->value.i); + saveSint32(0); + } + break; + case MKID_BE('ACTR'): + case MKID_BE('COLR'): + case MKID_BE('STAT'): + case MKID_BE('FONT'): + case MKID_BE('VBUF'): + case MKID_BE('PRIM'): + case MKID_BE('TEXT'): + { // TODO + saveUint32(makeIdFromPointer(object->value.ts).low); + saveUint32(makeIdFromPointer(object->value.ts).hi); + } + break; + default: + lua_error("saveObjectValue: Unsupported object type"); } } @@ -48,17 +156,20 @@ static int32 opcodeSizeTable[] = { 2, 3, 2, 3, 2, 3, 2, 1, 1, 3, 2, 2, 2, 2, 3, 2, 1, 1 }; -void lua_Save(SaveRestoreFunc saveFunc) { +void lua_Save(SaveStream saveStream, SaveSint32 saveSint32, SaveUint32 saveUint32) { printf("lua_Save() started.\n"); -/* + lua_collectgarbage(0); int32 i, l; int32 countElements = 0; int32 maxStringLength = 0; + + + // Check for max length for strings and count them for (i = 0; i < NUM_HASHS; i++) { stringtable *tempStringTable = &L->string_root[i]; for (int32 l = 0; l < tempStringTable->size; l++) { - if ((tempStringTable->hash[l] != NULL) && (tempStringTable->hash[l] != &EMPTY)) { + if (tempStringTable->hash[l] && tempStringTable->hash[l] != &EMPTY) { countElements++; if (tempStringTable->hash[l]->constindex != -1) { if (maxStringLength < tempStringTable->hash[l]->u.s.len) { @@ -68,117 +179,132 @@ void lua_Save(SaveRestoreFunc saveFunc) { } } } + // save number of strings + saveSint32(countElements); - saveFunc(&countElements, sizeof(int32)); + + // save number of closures countElements = 0; - GCnode *tempNode; tempNode = L->rootcl.next; - while (tempNode != NULL) { + while (tempNode) { countElements++; tempNode = tempNode->next; } - saveFunc(&countElements, sizeof(int32)); - countElements = 0; + saveSint32(countElements); + // save number of tables + countElements = 0; tempNode = L->roottable.next; - while (tempNode != NULL) { + while (tempNode) { countElements++; tempNode = tempNode->next; } - saveFunc(&countElements, sizeof(int32)); - countElements = 0; + saveSint32(countElements); + // save number of prototypes + countElements = 0; tempNode = L->rootproto.next; - while (tempNode != NULL) { + while (tempNode) { countElements++; tempNode = tempNode->next; } - saveFunc(&countElements, sizeof(int32)); + saveSint32(countElements); + + // save number of global strings countElements = 0; - tempNode = L->rootglobal.next; - while (tempNode != NULL) { + while (tempNode) { countElements++; tempNode = tempNode->next; } - saveFunc(&countElements, sizeof(int32)); + saveSint32(countElements); - saveFunc(&maxStringLength, sizeof(int32)); + // save maximum length for string + saveSint32(maxStringLength); + // save hash tables for strings and user data TaggedString *tempString; for (i = 0; i < NUM_HASHS; i++) { stringtable *tempStringTable = &L->string_root[i]; for (l = 0; l < tempStringTable->size; l++) { - if ((tempStringTable->hash[l] != NULL) && (tempStringTable->hash[l] != &EMPTY)) { + if (tempStringTable->hash[l] && tempStringTable->hash[l] != &EMPTY) { tempString = tempStringTable->hash[l]; - saveFunc(&tempString, sizeof(TaggedString *)); - saveFunc(&tempString->constindex, sizeof(int32)); + saveUint32(makeIdFromPointer(tempString).low); + saveUint32(makeIdFromPointer(tempString).hi); + saveSint32(tempString->constindex); if (tempString->constindex != -1) { - saveObjectValue(&tempString->u.s.globalval, saveFunc); - saveFunc(&tempString->u.s.len, sizeof(int32)); - saveFunc(tempString->str, tempString->u.s.len); - } else { - if (saveCallback != NULL) { - tempString->u.s.globalval.value.ts = (TaggedString *)saveCallback(tempString->u.s.globalval.ttype, (int32)tempString->u.s.globalval.value.ts, saveFunc); + saveObjectValue(&tempString->u.s.globalval, saveSint32, saveUint32); + saveSint32(tempString->u.s.len); + saveStream(tempString->str, tempString->u.s.len); + } else { + if (saveCallbackPtr) { + PointerId ptr = makeIdFromPointer(tempString->u.s.globalval.value.ts); + ptr = saveCallbackPtr(tempString->u.s.globalval.ttype, ptr, saveSint32); + tempString->u.s.globalval.value.ts = (TaggedString *)makePointerFromId(ptr); } - saveObjectValue(&tempString->u.s.globalval, saveFunc); + saveObjectValue(&tempString->u.s.globalval, saveSint32, saveUint32); } } } } Closure *tempClosure = (Closure *)L->rootcl.next; - while (tempClosure != NULL) { - saveFunc(&tempClosure, sizeof(Closure *)); - saveFunc(&tempClosure->nelems, sizeof(int32)); - for(i = 0; i <= tempClosure->nelems; i++) { - saveObjectValue(&tempClosure->consts[i], saveFunc); + while (tempClosure) { + saveUint32(makeIdFromPointer(tempClosure).low); + saveUint32(makeIdFromPointer(tempClosure).hi); + saveSint32(tempClosure->nelems); + for (i = 0; i <= tempClosure->nelems; i++) { + saveObjectValue(&tempClosure->consts[i], saveSint32, saveUint32); } tempClosure = (Closure *)tempClosure->head.next; } Hash *tempHash = (Hash *)L->roottable.next; - while (tempHash != NULL) { - saveFunc(&tempHash, sizeof(Hash *)); - saveFunc(&tempHash->nhash, sizeof(uint32)); + while (tempHash) { + saveUint32(makeIdFromPointer(tempHash).low); + saveUint32(makeIdFromPointer(tempHash).hi); + saveSint32(tempHash->nhash); int32 countUsedHash = 0; for(i = 0; i < tempHash->nhash; i++) { Node *newNode = &tempHash->node[i]; - if ((newNode->ref.ttype != LUA_T_NIL) && (newNode->val.ttype != LUA_T_NIL)) { + if (newNode->ref.ttype != LUA_T_NIL && newNode->val.ttype != LUA_T_NIL) { countUsedHash++; } } - saveFunc(&countUsedHash, sizeof(int32)); - saveFunc(&tempHash->htag, sizeof(int32)); + saveSint32(countUsedHash); + saveSint32(tempHash->htag); for (i = 0; i < tempHash->nhash; i++) { Node *newNode = &tempHash->node[i]; - if ((newNode->ref.ttype != LUA_T_NIL) && (newNode->val.ttype != LUA_T_NIL)) { - saveObjectValue(&tempHash->node[i].ref, saveFunc); - saveObjectValue(&tempHash->node[i].val, saveFunc); + if (newNode->ref.ttype != LUA_T_NIL && newNode->val.ttype != LUA_T_NIL) { + saveObjectValue(&tempHash->node[i].ref, saveSint32, saveUint32); + saveObjectValue(&tempHash->node[i].val, saveSint32, saveUint32); } } tempHash = (Hash *)tempHash->head.next; } TProtoFunc *tempProtoFunc = (TProtoFunc *)L->rootproto.next; - while (tempProtoFunc != NULL) { - saveFunc(&tempProtoFunc, sizeof(TProtoFunc *)); - saveFunc(&tempProtoFunc->fileName, sizeof(TaggedString *)); - saveFunc(&tempProtoFunc->lineDefined, sizeof(int32)); - saveFunc(&tempProtoFunc->nconsts, sizeof(int32)); + while (tempProtoFunc) { + saveUint32(makeIdFromPointer(tempProtoFunc).low); + saveUint32(makeIdFromPointer(tempProtoFunc).hi); + saveUint32(makeIdFromPointer(tempProtoFunc->fileName).low); + saveUint32(makeIdFromPointer(tempProtoFunc->fileName).hi); + saveSint32(tempProtoFunc->lineDefined); + saveSint32(tempProtoFunc->nconsts); for (i = 0; i < tempProtoFunc->nconsts; i++) { - saveObjectValue(&tempProtoFunc->consts[i], saveFunc); + saveObjectValue(&tempProtoFunc->consts[i], saveSint32, saveUint32); } int32 countVariables = 0; if (tempProtoFunc->locvars) { for (; tempProtoFunc->locvars[countVariables++].line != -1;) { } } - saveFunc(&countVariables, sizeof(int32)); + saveSint32(countVariables); for (i = 0; i < countVariables; i++) { - saveFunc(&tempProtoFunc->locvars[i].varname, sizeof(TaggedString *)); - saveFunc(&tempProtoFunc->locvars[i].line, sizeof(int32)); + saveUint32(makeIdFromPointer(tempProtoFunc->locvars[i].varname).low); + saveUint32(makeIdFromPointer(tempProtoFunc->locvars[i].varname).hi); + saveSint32(tempProtoFunc->locvars[i].line); } Byte *codePtr = tempProtoFunc->code + 2; @@ -189,106 +315,109 @@ void lua_Save(SaveRestoreFunc saveFunc) { tmpPtr += opcodeSizeTable[opcodeId]; } while (opcodeId != ENDCODE); int32 codeSize = (tmpPtr - codePtr) + 2; - saveFunc(&codeSize, sizeof(int32)); - saveFunc(tempProtoFunc->code, codeSize); + saveSint32(codeSize); + saveStream(tempProtoFunc->code, codeSize); tempProtoFunc = (TProtoFunc *)tempProtoFunc->head.next; } tempString = (TaggedString *)L->rootglobal.next; - while (tempString != NULL) { - saveFunc(&tempString, sizeof(TaggedString *)); + while (tempString) { + saveUint32(makeIdFromPointer(tempString).low); + saveUint32(makeIdFromPointer(tempString).hi); tempString = (TaggedString *)tempString->head.next; } - saveObjectValue(&L->errorim, saveFunc); + saveObjectValue(&L->errorim, saveSint32, saveUint32); IM *tempIm = L->IMtable; - saveFunc(&L->IMtable_size, sizeof(int32)); + saveSint32(L->IMtable_size); for (i = 0; i < L->IMtable_size; i++) { for (l = 0; l < IM_N; l++) { - saveObjectValue(&tempIm->int_method[l], saveFunc); + saveObjectValue(&tempIm->int_method[l], saveSint32, saveUint32); } tempIm++; } - saveFunc(&L->last_tag, sizeof(int32)); - saveFunc(&L->refSize, sizeof(int32)); + saveSint32(L->last_tag); + saveSint32(L->refSize); for (i = 0 ; i < L->refSize; i++) { - saveObjectValue(&L->refArray[i].o, saveFunc); - saveFunc(&L->refArray[i].status, sizeof(Status)); + saveObjectValue(&L->refArray[i].o, saveSint32, saveUint32); + saveSint32(L->refArray[i].status); } - saveFunc(&L->GCthreshold, sizeof(int32)); - saveFunc(&L->nblocks, sizeof(int32)); + saveSint32(L->GCthreshold); + saveSint32(L->nblocks); - saveFunc(&L->Mbuffsize, sizeof(int32)); - saveFunc(L->Mbuffer, L->Mbuffsize); + saveSint32(L->Mbuffsize); + saveStream(L->Mbuffer, L->Mbuffsize); int32 MbaseOffset = L->Mbuffbase - L->Mbuffer; - saveFunc(&MbaseOffset, sizeof(int32)); - saveFunc(&L->Mbuffnext, sizeof(int32)); + saveSint32(MbaseOffset); + saveSint32(L->Mbuffnext); - saveFunc(&globalTaskSerialId, sizeof(int32)); + saveSint32(globalTaskSerialId); int32 countTasks = 0; lua_Task *tempTask = L->root_task->next; - while (tempTask != NULL) { + while (tempTask) { countTasks++; tempTask = tempTask->next; } - saveFunc(&countTasks, sizeof(int32)); + saveSint32(countTasks); tempTask = L->root_task->next; - while (tempTask != NULL) { + while (tempTask) { int32 stackLastSize = (tempTask->stack.last - tempTask->stack.stack) + 1; - saveFunc(&stackLastSize, sizeof(int32)); + saveSint32(stackLastSize); int32 stackTopSize = tempTask->stack.top - tempTask->stack.stack; - saveFunc(&stackTopSize, sizeof(int32)); + saveSint32(stackTopSize); for (i = 0; i < stackTopSize; i++) { - saveObjectValue(&tempTask->stack.stack[i], saveFunc); + saveObjectValue(&tempTask->stack.stack[i], saveSint32, saveUint32); } - saveFunc(&tempTask->Cstack.base, sizeof(StkId)); - saveFunc(&tempTask->Cstack.lua2C, sizeof(StkId)); - saveFunc(&tempTask->Cstack.num, sizeof(int32)); + saveSint32(tempTask->Cstack.base); + saveSint32(tempTask->Cstack.lua2C); + saveSint32(tempTask->Cstack.num); - saveFunc(&tempTask->numCblocks, sizeof(int32)); + saveSint32(tempTask->numCblocks); for (i = 0; i < tempTask->numCblocks; i++) { - saveFunc(&tempTask->Cblocks[i].base, sizeof(StkId)); - saveFunc(&tempTask->Cblocks[i].lua2C, sizeof(StkId)); - saveFunc(&tempTask->Cblocks[i].num, sizeof(int32)); + saveSint32(tempTask->Cblocks[i].base); + saveSint32(tempTask->Cblocks[i].lua2C); + saveSint32(tempTask->Cblocks[i].num); } int32 pcOffset, taskCi = -1; - saveFunc(&tempTask->base_ci_size, sizeof(int32)); + saveSint32(tempTask->base_ci_size); assert(tempTask->base_ci); CallInfo *tempCi = tempTask->base_ci; int32 countCi = tempTask->base_ci_size / sizeof(CallInfo); for (i = 0; i < countCi; i++) { - saveFunc(&tempCi->c, sizeof(Closure *)); - saveFunc(&tempCi->tf, sizeof(TProtoFunc *)); - if ((tempCi->pc != NULL) && (tempTask->ci->tf != NULL)) + saveUint32(makeIdFromPointer(tempCi->c).low); + saveUint32(makeIdFromPointer(tempCi->c).hi); + saveUint32(makeIdFromPointer(tempCi->tf).low); + saveUint32(makeIdFromPointer(tempCi->tf).hi); + if (tempCi->pc && tempTask->ci->tf) pcOffset = tempCi->pc - tempCi->tf->code; else pcOffset = 0; - saveFunc(&pcOffset, sizeof(int32)); - saveFunc(&tempCi->base, sizeof(StkId)); - saveFunc(&tempCi->nResults, sizeof(int32)); + saveSint32(pcOffset); + saveSint32(tempCi->base); + saveSint32(tempCi->nResults); if (tempCi == tempTask->ci) taskCi = i; tempCi++; } assert(taskCi != -1); - saveFunc(&taskCi, sizeof(int32)); + saveSint32(taskCi); MbaseOffset = tempTask->Mbuffbase - tempTask->Mbuffer; - saveFunc(&MbaseOffset, sizeof(int32)); - saveFunc(&tempTask->Mbuffnext, sizeof(int32)); + saveSint32(MbaseOffset); + saveSint32(tempTask->Mbuffnext); - saveFunc(&tempTask->Tstate, sizeof(TaskState)); - saveFunc(&tempTask->id, sizeof(int32)); + saveSint32(tempTask->Tstate); + saveSint32(tempTask->id); tempTask = tempTask->next; } -*/ + printf("lua_Save() finished.\n"); } diff --git a/engine/lua/lua.h b/engine/lua/lua.h index d5085ef35a7..e9f95554c16 100644 --- a/engine/lua/lua.h +++ b/engine/lua/lua.h @@ -26,14 +26,28 @@ typedef uint32 lua_Object; typedef struct lua_State lua_State; extern lua_State *lua_state; -typedef void (*SaveRestoreFunc)(void *, int32); -typedef int32 (*SaveRestoreCallback)(int32, int32, SaveRestoreFunc); +struct PointerId { + uint32 low; + uint32 hi; +}; -extern SaveRestoreCallback saveCallback; -extern SaveRestoreCallback restoreCallback; +PointerId makeIdFromPointer(void *ptr); +void *makePointerFromId(PointerId ptr); -void lua_Save(SaveRestoreFunc); -void lua_Restore(SaveRestoreFunc); +typedef void (*SaveStream)(void *, int32); +typedef void (*SaveSint32)(int32); +typedef void (*SaveUint32)(uint32); +typedef void (*RestoreStream)(void *, int32); +typedef int32 (*RestoreSint32)(); +typedef uint32 (*RestoreUint32)(); +typedef PointerId (*SaveCallback)(int32, PointerId, SaveSint32); +typedef PointerId (*RestoreCallback)(int32, PointerId, RestoreSint32); + +extern SaveCallback saveCallbackPtr; +extern RestoreCallback restoreCallbackPtr; + +void lua_Save(SaveStream, SaveSint32, SaveUint32); +void lua_Restore(RestoreStream, RestoreSint32, RestoreUint32); void lua_removelibslists(void); diff --git a/engine/savegame.cpp b/engine/savegame.cpp index cb9373b7d84..9150ad0b002 100644 --- a/engine/savegame.cpp +++ b/engine/savegame.cpp @@ -25,6 +25,7 @@ #include "common/debug.h" #include "common/savefile.h" +#include "common/endian.h" #include "engine/savegame.h" @@ -79,7 +80,7 @@ uint32 SaveGame::beginSection(uint32 sectionTag) { _sectionBuffer = (byte *)malloc(_sectionSize); if (!_saving) { uint32 tag = 0; - + while (tag != sectionTag) { free(_sectionBuffer); tag = _inSaveFile->readUint32BE(); @@ -116,6 +117,46 @@ void SaveGame::read(void *data, int size) { _sectionPtr += size; } +uint32 SaveGame::readLEUint32() { + if (_saving) + error("SaveGame::readBlock called when storing a savegame!"); + if (_currentSection == 0) + error("Tried to read a block without starting a section!"); + uint32 data = READ_LE_UINT32(&_sectionBuffer[_sectionPtr]); + _sectionPtr += 4; + return data; +} + +int32 SaveGame::readLESint32() { + if (_saving) + error("SaveGame::readBlock called when storing a savegame!"); + if (_currentSection == 0) + error("Tried to read a block without starting a section!"); + int32 data = (int32)READ_LE_UINT32(&_sectionBuffer[_sectionPtr]); + _sectionPtr += 4; + return data; +} + +byte SaveGame::readByte() { + if (_saving) + error("SaveGame::readBlock called when storing a savegame!"); + if (_currentSection == 0) + error("Tried to read a block without starting a section!"); + byte data = _sectionBuffer[_sectionPtr]; + _sectionPtr++; + return data; +} + +bool SaveGame::readLEBool() { + if (_saving) + error("SaveGame::readBlock called when storing a savegame!"); + if (_currentSection == 0) + error("Tried to read a block without starting a section!"); + uint32 data = READ_LE_UINT32(&_sectionBuffer[_sectionPtr]); + _sectionPtr += 4; + return data != 0; +} + void SaveGame::write(const void *data, int size) { if (!_saving) error("SaveGame::writeBlock called when restoring a savegame!"); @@ -127,3 +168,55 @@ void SaveGame::write(const void *data, int size) { memcpy(&_sectionBuffer[_sectionSize], data, size); _sectionSize += size; } + +void SaveGame::writeLEUint32(uint32 data) { + if (!_saving) + error("SaveGame::writeBlock called when restoring a savegame!"); + if (_currentSection == 0) + error("Tried to write a block without starting a section!"); + _sectionBuffer = (byte *)realloc(_sectionBuffer, _sectionSize + 4); + if (!_sectionBuffer) + error("Failed to allocate space for buffer!"); + + WRITE_LE_UINT32(&_sectionBuffer[_sectionSize], data); + _sectionSize += 4; +} + +void SaveGame::writeLESint32(int32 data) { + if (!_saving) + error("SaveGame::writeBlock called when restoring a savegame!"); + if (_currentSection == 0) + error("Tried to write a block without starting a section!"); + _sectionBuffer = (byte *)realloc(_sectionBuffer, _sectionSize + 4); + if (!_sectionBuffer) + error("Failed to allocate space for buffer!"); + + WRITE_LE_UINT32(&_sectionBuffer[_sectionSize], (uint32)data); + _sectionSize += 4; +} + +void SaveGame::writeLEBool(bool data) { + if (!_saving) + error("SaveGame::writeBlock called when restoring a savegame!"); + if (_currentSection == 0) + error("Tried to write a block without starting a section!"); + _sectionBuffer = (byte *)realloc(_sectionBuffer, _sectionSize + 4); + if (!_sectionBuffer) + error("Failed to allocate space for buffer!"); + + WRITE_LE_UINT32(&_sectionBuffer[_sectionSize], (uint32)data); + _sectionSize += 4; +} + +void SaveGame::writeByte(byte data) { + if (!_saving) + error("SaveGame::writeBlock called when restoring a savegame!"); + if (_currentSection == 0) + error("Tried to write a block without starting a section!"); + _sectionBuffer = (byte *)realloc(_sectionBuffer, _sectionSize + 1); + if (!_sectionBuffer) + error("Failed to allocate space for buffer!"); + + _sectionBuffer[_sectionSize] = data; + _sectionSize++; +} diff --git a/engine/savegame.h b/engine/savegame.h index f279228b6c2..7f9ea8dd440 100644 --- a/engine/savegame.h +++ b/engine/savegame.h @@ -53,6 +53,14 @@ public: void endSection(); void read(void *data, int size); void write(const void *data, int size); + uint32 readLEUint32(); + int32 readLESint32(); + bool readLEBool(); + byte readByte(); + void writeLEUint32(uint32 data); + void writeLESint32(int32 data); + void writeLEBool(bool data); + void writeByte(byte data); protected: bool _saving;