mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-11 03:01:01 +00:00
585 lines
17 KiB
C++
585 lines
17 KiB
C++
#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
|
|
|
|
#include "common/endian.h"
|
|
#include "common/debug.h"
|
|
|
|
#include "engines/grim/savegame.h"
|
|
|
|
#include "engines/grim/lua/ltask.h"
|
|
#include "engines/grim/lua/lauxlib.h"
|
|
#include "engines/grim/lua/lmem.h"
|
|
#include "engines/grim/lua/ldo.h"
|
|
#include "engines/grim/lua/ltm.h"
|
|
#include "engines/grim/lua/ltable.h"
|
|
#include "engines/grim/lua/lvm.h"
|
|
#include "engines/grim/lua/lopcodes.h"
|
|
#include "engines/grim/lua/lstring.h"
|
|
#include "engines/grim/lua/lstate.h"
|
|
#include "engines/grim/lua/lua.h"
|
|
|
|
namespace Grim {
|
|
|
|
static void restoreObjectValue(TObject *object, SaveGame *savedState) {
|
|
object->ttype = (lua_Type)savedState->readLESint32();
|
|
|
|
switch (object->ttype) {
|
|
case LUA_T_NUMBER:
|
|
case LUA_T_TASK:
|
|
{
|
|
object->value.n = savedState->readFloat();
|
|
}
|
|
break;
|
|
case LUA_T_NIL:
|
|
{
|
|
object->value.ts = nullptr;
|
|
}
|
|
break;
|
|
case LUA_T_ARRAY:
|
|
{
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
object->value.a = (Hash *)makePointerFromId(ptr);
|
|
}
|
|
break;
|
|
case LUA_T_USERDATA:
|
|
{
|
|
object->value.ud.id = savedState->readLESint32();
|
|
object->value.ud.tag = savedState->readLESint32();
|
|
if (savedState->saveMinorVersion() == 0) {
|
|
savedState->readLEUint32();
|
|
savedState->readLEUint32();
|
|
}
|
|
}
|
|
break;
|
|
case LUA_T_STRING:
|
|
{
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
object->value.ts = (TaggedString *)makePointerFromId(ptr);
|
|
}
|
|
break;
|
|
case LUA_T_PROTO:
|
|
case LUA_T_PMARK:
|
|
{
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
object->value.tf = (TProtoFunc *)makePointerFromId(ptr);
|
|
}
|
|
break;
|
|
case LUA_T_CPROTO:
|
|
case LUA_T_CMARK:
|
|
{
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
|
|
// WORKAROUND: C++ forbids casting from a pointer-to-function to a
|
|
// pointer-to-object. We use a union to work around that.
|
|
union {
|
|
void *objPtr;
|
|
lua_CFunction funcPtr;
|
|
} ptrUnion;
|
|
|
|
ptrUnion.objPtr = makePointerFromId(ptr);
|
|
object->value.f = ptrUnion.funcPtr;
|
|
}
|
|
break;
|
|
case LUA_T_CLOSURE:
|
|
case LUA_T_CLMARK:
|
|
{
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
object->value.cl = (Closure *)makePointerFromId(ptr);
|
|
}
|
|
break;
|
|
case LUA_T_LINE:
|
|
{
|
|
object->value.i = savedState->readLESint32();
|
|
}
|
|
break;
|
|
default:
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
object->value.ts = (TaggedString *)makePointerFromId(ptr);
|
|
}
|
|
}
|
|
|
|
struct ArrayIDObj {
|
|
void *object;
|
|
PointerId idObj;
|
|
};
|
|
|
|
static int sortCallback(const void *id1, const void *id2) {
|
|
if (((const ArrayIDObj *)id1)->idObj.id > ((const ArrayIDObj *)id2)->idObj.id) {
|
|
return 1;
|
|
} else if (((const ArrayIDObj *)id1)->idObj.id < ((const ArrayIDObj *)id2)->idObj.id) {
|
|
return -1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int32 arrayHashTablesCount = 0;
|
|
int32 arrayProtoFuncsCount = 0;
|
|
int32 arrayClosuresCount = 0;
|
|
int32 arrayStringsCount = 0;
|
|
ArrayIDObj *arrayStrings = nullptr;
|
|
ArrayIDObj *arrayHashTables = nullptr;
|
|
ArrayIDObj *arrayClosures = nullptr;
|
|
ArrayIDObj *arrayProtoFuncs = nullptr;
|
|
static bool arraysAllreadySort = false;
|
|
|
|
static void recreateObj(TObject *obj) {
|
|
if (obj->ttype == LUA_T_CPROTO) {
|
|
uintptr id = ((uintptr)(obj->value.f)) >> 16;
|
|
luaL_libList *list = list_of_libs;
|
|
while (list) {
|
|
if (id == 0)
|
|
break;
|
|
id--;
|
|
list = list->next;
|
|
}
|
|
|
|
int32 numberFunc = (uintptr)(obj->value.f) & 0xffff;
|
|
if (list && id == 0 && numberFunc < list->number) {
|
|
obj->value.f = list->list[numberFunc].func;
|
|
} else {
|
|
obj->value.f = nullptr;
|
|
assert(obj->value.f);
|
|
}
|
|
} else if (obj->ttype == LUA_T_NIL || obj->ttype == LUA_T_LINE || obj->ttype == LUA_T_NUMBER ||
|
|
obj->ttype == LUA_T_TASK || obj->ttype == LUA_T_USERDATA) {
|
|
return;
|
|
} else {
|
|
if (obj->value.i == 0)
|
|
return;
|
|
|
|
if (!arraysAllreadySort) {
|
|
arraysAllreadySort = true;
|
|
qsort(arrayHashTables, arrayHashTablesCount, sizeof(ArrayIDObj), sortCallback);
|
|
qsort(arrayProtoFuncs, arrayProtoFuncsCount, sizeof(ArrayIDObj), sortCallback);
|
|
qsort(arrayClosures, arrayClosuresCount, sizeof(ArrayIDObj), sortCallback);
|
|
qsort(arrayStrings, arrayStringsCount, sizeof(ArrayIDObj), sortCallback);
|
|
}
|
|
|
|
ArrayIDObj *found;
|
|
ArrayIDObj tmpId;
|
|
tmpId.object = nullptr;
|
|
|
|
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_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 = nullptr;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void lua_Restore(SaveGame *savedState) {
|
|
savedState->beginSection('LUAS');
|
|
|
|
lua_close();
|
|
lua_rootState = lua_state = luaM_new(LState);
|
|
lua_stateinit(lua_state);
|
|
lua_resetglobals();
|
|
|
|
arrayStringsCount = savedState->readLESint32();
|
|
arrayClosuresCount = savedState->readLESint32();
|
|
arrayHashTablesCount = savedState->readLESint32();
|
|
arrayProtoFuncsCount = savedState->readLESint32();
|
|
int32 rootGlobalCount = savedState->readLESint32();
|
|
|
|
arrayStrings = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayStringsCount);
|
|
ArrayIDObj *arraysObj = arrayStrings;
|
|
int32 maxStringsLength;
|
|
maxStringsLength = savedState->readLESint32();
|
|
char *tempStringBuffer = (char *)luaM_malloc(maxStringsLength + 1); // add extra char for 0 terminate string
|
|
|
|
//printf("1: %d\n", g_grim->_savedState->getBufferPos());
|
|
|
|
int32 i;
|
|
for (i = 0; i < arrayStringsCount; i++) {
|
|
arraysObj->idObj.id = savedState->readLEUint64();
|
|
int32 constIndex = savedState->readLESint32();
|
|
|
|
TaggedString *tempString = nullptr;
|
|
if (constIndex != -1) {
|
|
TObject obj;
|
|
restoreObjectValue(&obj, savedState);
|
|
int32 length = savedState->readLESint32();
|
|
savedState->read(tempStringBuffer, length);
|
|
tempStringBuffer[length] = '\0';
|
|
tempString = luaS_new(tempStringBuffer);
|
|
tempString->globalval = obj;
|
|
}
|
|
assert(tempString);
|
|
tempString->constindex = constIndex;
|
|
arraysObj->object = tempString;
|
|
arraysObj++;
|
|
}
|
|
luaM_free(tempStringBuffer);
|
|
|
|
//printf("2: %d\n", g_grim->_savedState->getBufferPos());
|
|
|
|
int32 l;
|
|
Closure *tempClosure;
|
|
GCnode *prevClosure = &rootcl;
|
|
arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayClosuresCount);
|
|
arrayClosures = arraysObj;
|
|
for (i = 0; i < arrayClosuresCount; i++) {
|
|
arraysObj->idObj.id = savedState->readLEUint64();
|
|
int32 countElements = savedState->readLESint32();
|
|
tempClosure = (Closure *)luaM_malloc((countElements * sizeof(TObject)) + sizeof(Closure));
|
|
luaO_insertlist(prevClosure, (GCnode *)tempClosure);
|
|
prevClosure = (GCnode *)tempClosure;
|
|
|
|
tempClosure->nelems = countElements;
|
|
for (l = 0; l <= tempClosure->nelems; l++) {
|
|
restoreObjectValue(&tempClosure->consts[l], savedState);
|
|
}
|
|
arraysObj->object = tempClosure;
|
|
arraysObj++;
|
|
}
|
|
|
|
Hash *tempHash;
|
|
GCnode *prevHash = &roottable;
|
|
arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayHashTablesCount);
|
|
arrayHashTables = arraysObj;
|
|
for (i = 0; i < arrayHashTablesCount; i++) {
|
|
arraysObj->idObj.id = savedState->readLEUint64();
|
|
tempHash = luaM_new(Hash);
|
|
tempHash->nhash = savedState->readLESint32();
|
|
tempHash->nuse = savedState->readLESint32();
|
|
tempHash->htag = savedState->readLESint32();
|
|
tempHash->node = hashnodecreate(tempHash->nhash);
|
|
luaO_insertlist(prevHash, (GCnode *)tempHash);
|
|
prevHash = (GCnode *)tempHash;
|
|
|
|
for (l = 0; l < tempHash->nuse; l++) {
|
|
restoreObjectValue(&tempHash->node[l].ref, savedState);
|
|
restoreObjectValue(&tempHash->node[l].val, savedState);
|
|
}
|
|
arraysObj->object = tempHash;
|
|
arraysObj++;
|
|
}
|
|
|
|
TProtoFunc *tempProtoFunc;
|
|
GCnode *oldProto = &rootproto;
|
|
arrayProtoFuncs = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayProtoFuncsCount);
|
|
arraysObj = arrayProtoFuncs;
|
|
for (i = 0; i < arrayProtoFuncsCount; i++) {
|
|
arraysObj->idObj.id = savedState->readLEUint64();
|
|
tempProtoFunc = luaM_new(TProtoFunc);
|
|
luaO_insertlist(oldProto, (GCnode *)tempProtoFunc);
|
|
oldProto = (GCnode *)tempProtoFunc;
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
tempProtoFunc->fileName = (TaggedString *)makePointerFromId(ptr);
|
|
tempProtoFunc->lineDefined = savedState->readLESint32();
|
|
tempProtoFunc->nconsts = savedState->readLESint32();
|
|
if (tempProtoFunc->nconsts > 0) {
|
|
tempProtoFunc->consts = (TObject *)luaM_malloc(tempProtoFunc->nconsts * sizeof(TObject));
|
|
} else {
|
|
tempProtoFunc->consts = nullptr;
|
|
}
|
|
|
|
for (l = 0; l < tempProtoFunc->nconsts; l++) {
|
|
restoreObjectValue(&tempProtoFunc->consts[l], savedState);
|
|
}
|
|
|
|
int32 countVariables = savedState->readLESint32();
|
|
if (countVariables) {
|
|
tempProtoFunc->locvars = (LocVar *)luaM_malloc(countVariables * sizeof(LocVar));
|
|
} else {
|
|
tempProtoFunc->locvars = nullptr;
|
|
}
|
|
|
|
for (l = 0; l < countVariables; l++) {
|
|
ptr.id = savedState->readLEUint64();
|
|
tempProtoFunc->locvars[l].varname = (TaggedString *)makePointerFromId(ptr);
|
|
tempProtoFunc->locvars[l].line = savedState->readLESint32();
|
|
}
|
|
|
|
int32 codeSize = savedState->readLESint32();
|
|
tempProtoFunc->code = (byte *)luaM_malloc(codeSize);
|
|
savedState->read(tempProtoFunc->code, codeSize);
|
|
arraysObj->object = tempProtoFunc;
|
|
arraysObj++;
|
|
}
|
|
|
|
for (i = 0; i < NUM_HASHS; i++) {
|
|
stringtable *tempStringTable = &string_root[i];
|
|
for (l = 0; l < tempStringTable->size; l++) {
|
|
TaggedString *tempString = tempStringTable->hash[l];
|
|
if (tempString && tempString->constindex != -1 && tempString != &EMPTY) {
|
|
recreateObj(&tempString->globalval);
|
|
}
|
|
}
|
|
}
|
|
|
|
tempProtoFunc = (TProtoFunc *)rootproto.next;
|
|
while (tempProtoFunc) {
|
|
TObject tempObj;
|
|
tempObj.value.ts = (TaggedString *)tempProtoFunc->fileName;
|
|
tempObj.ttype = LUA_T_STRING;
|
|
recreateObj(&tempObj);
|
|
tempProtoFunc->fileName = (TaggedString *)tempObj.value.ts;
|
|
for (i = 0; i < tempProtoFunc->nconsts; i++) {
|
|
recreateObj(&tempProtoFunc->consts[i]);
|
|
}
|
|
|
|
if (tempProtoFunc->locvars) {
|
|
for (i = 0; tempProtoFunc->locvars[i].line != -1; i++) {
|
|
TObject tempObj2;
|
|
tempObj2.value.ts = tempProtoFunc->locvars[i].varname;
|
|
tempObj2.ttype = LUA_T_STRING;
|
|
recreateObj(&tempObj2);
|
|
tempProtoFunc->locvars[i].varname = (TaggedString *)tempObj2.value.ts;
|
|
}
|
|
}
|
|
tempProtoFunc = (TProtoFunc *)tempProtoFunc->head.next;
|
|
}
|
|
|
|
tempHash = (Hash *)roottable.next;
|
|
while (tempHash) {
|
|
for (i = 0; i < tempHash->nuse; i++) {
|
|
recreateObj(&tempHash->node[i].ref);
|
|
recreateObj(&tempHash->node[i].val);
|
|
}
|
|
Node *oldNode = tempHash->node;
|
|
tempHash->node = hashnodecreate(tempHash->nhash);
|
|
for (i = 0; i < tempHash->nuse; i++) {
|
|
Node *newNode = oldNode + i;
|
|
if (newNode->ref.ttype != LUA_T_NIL && newNode->val.ttype != LUA_T_NIL) {
|
|
*node(tempHash, present(tempHash, &newNode->ref)) = *newNode;
|
|
}
|
|
}
|
|
luaM_free(oldNode);
|
|
tempHash = (Hash *)tempHash->head.next;
|
|
}
|
|
|
|
tempClosure = (Closure *)rootcl.next;
|
|
while (tempClosure) {
|
|
for (i = 0; i <= tempClosure->nelems; i++) {
|
|
recreateObj(&tempClosure->consts[i]);
|
|
}
|
|
tempClosure = (Closure *)tempClosure->head.next;
|
|
}
|
|
|
|
TaggedString *tempListString = (TaggedString *)&(rootglobal);
|
|
for (i = 0; i < rootGlobalCount; i++) {
|
|
TObject tempObj;
|
|
TaggedString *tempString = nullptr;
|
|
tempObj.ttype = LUA_T_STRING;
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
tempObj.value.ts = (TaggedString *)makePointerFromId(ptr);
|
|
recreateObj(&tempObj);
|
|
tempString = (TaggedString *)tempObj.value.ts;
|
|
assert(tempString);
|
|
tempListString->head.next = (GCnode *)tempString;
|
|
tempListString = tempString;
|
|
}
|
|
tempListString->head.next = nullptr;
|
|
|
|
restoreObjectValue(&errorim, savedState);
|
|
recreateObj(&errorim);
|
|
|
|
IMtable_size = savedState->readLESint32();
|
|
if (IMtable_size > 0) {
|
|
IMtable = (IM *)luaM_malloc(IMtable_size * sizeof(IM));
|
|
for (i = 0; i < IMtable_size; i++) {
|
|
IM *im = &IMtable[i];
|
|
for (l = 0; l < IM_N; l++) {
|
|
restoreObjectValue(&im->int_method[l], savedState);
|
|
recreateObj(&im->int_method[l]);
|
|
}
|
|
}
|
|
} else {
|
|
IMtable = nullptr;
|
|
}
|
|
|
|
last_tag = savedState->readLESint32();
|
|
refSize = savedState->readLESint32();
|
|
if (refSize > 0) {
|
|
refArray = (ref *)luaM_malloc(refSize * sizeof(ref));
|
|
for (i = 0; i < refSize; i++) {
|
|
restoreObjectValue(&refArray[i].o, savedState);
|
|
recreateObj(&refArray[i].o);
|
|
refArray[i].status = (Status)savedState->readLESint32();
|
|
}
|
|
} else {
|
|
refArray = nullptr;
|
|
}
|
|
|
|
GCthreshold = savedState->readLESint32();
|
|
nblocks = savedState->readLESint32();
|
|
|
|
Mbuffsize = savedState->readLESint32();
|
|
Mbuffer = (char *)luaM_malloc(Mbuffsize);
|
|
savedState->read(Mbuffer, Mbuffsize);
|
|
int32 MbaseOffset = savedState->readLESint32();
|
|
Mbuffbase = MbaseOffset + Mbuffer;
|
|
Mbuffnext = savedState->readLESint32();
|
|
|
|
globalTaskSerialId = savedState->readLESint32();
|
|
|
|
int32 countStates = savedState->readLESint32();
|
|
int32 currentState = savedState->readLESint32();
|
|
|
|
LState *state = lua_rootState;
|
|
for (l = 0; l < countStates; l++) {
|
|
if (l == 0)
|
|
state = lua_rootState;
|
|
else {
|
|
LState *s = luaM_new(LState);
|
|
lua_stateinit(s);
|
|
state->next = s;
|
|
s->prev = state;
|
|
state = s;
|
|
}
|
|
int32 countTasks = savedState->readLESint32();
|
|
if (countTasks) {
|
|
lua_Task *task = nullptr;
|
|
for (i = 0; i < countTasks; i++) {
|
|
if (i == 0) {
|
|
task = state->task = luaM_new(lua_Task);
|
|
lua_taskinit(task, nullptr, 0, 0);
|
|
} else {
|
|
lua_Task *t = luaM_new(lua_Task);
|
|
lua_taskinit(t, nullptr, 0, 0);
|
|
task->next = t;
|
|
task = t;
|
|
}
|
|
|
|
task->S = &state->stack;
|
|
|
|
TObject tempObj;
|
|
tempObj.ttype = LUA_T_CLOSURE;
|
|
PointerId ptr;
|
|
ptr.id = savedState->readLEUint64();
|
|
tempObj.value.cl = (Closure *)makePointerFromId(ptr);
|
|
recreateObj(&tempObj);
|
|
task->cl = (Closure *)tempObj.value.cl;
|
|
tempObj.ttype = LUA_T_PROTO;
|
|
ptr.id = savedState->readLEUint64();
|
|
tempObj.value.tf = (TProtoFunc *)makePointerFromId(ptr);
|
|
recreateObj(&tempObj);
|
|
task->tf = (TProtoFunc *)tempObj.value.tf;
|
|
|
|
task->base = savedState->readLESint32();
|
|
task->initBase = savedState->readLESint32();
|
|
task->initResults = savedState->readLESint32();
|
|
task->executed = savedState->readBool();
|
|
int32 pcOffset = savedState->readLESint32();
|
|
task->pc = task->tf->code + pcOffset;
|
|
task->aux = savedState->readLESint32();
|
|
task->consts = task->tf->consts;
|
|
}
|
|
} else {
|
|
state->task = nullptr;
|
|
}
|
|
int32 n = savedState->readLESint32();
|
|
if (n < 0) {
|
|
state->prevTask = nullptr;
|
|
} else {
|
|
state->prevTask = state->task;
|
|
for (; n; n--)
|
|
state->prevTask = state->prevTask->next;
|
|
}
|
|
|
|
state->updated = savedState->readBool();
|
|
|
|
byte pauseState = savedState->readByte();
|
|
state->all_paused = pauseState & LUA_SG_ALL_PAUSED;
|
|
state->paused = (pauseState & LUA_SG_PAUSED) ? true : false;
|
|
|
|
state->preventBreakCounter = savedState->readLESint32();
|
|
state->callLevelCounter = savedState->readLESint32();
|
|
|
|
int32 stackLastSize = savedState->readLESint32();
|
|
if (state->stack.stack)
|
|
luaM_free(state->stack.stack);
|
|
|
|
state->stack.stack = (TObject *)luaM_malloc(stackLastSize * sizeof(TObject));
|
|
state->stack.last = state->stack.stack + stackLastSize - 1;
|
|
|
|
int32 stackTopSize = savedState->readLESint32();
|
|
state->stack.top = state->stack.stack + stackTopSize;
|
|
for (i = 0; i < stackTopSize; i++) {
|
|
restoreObjectValue(&state->stack.stack[i], savedState);
|
|
recreateObj(&state->stack.stack[i]);
|
|
}
|
|
|
|
state->Cstack.base = savedState->readLESint32();
|
|
state->Cstack.lua2C = savedState->readLESint32();
|
|
state->Cstack.num = savedState->readLESint32();
|
|
|
|
state->numCblocks = savedState->readLESint32();
|
|
for (i = 0; i < state->numCblocks; i++) {
|
|
state->Cblocks[i].base = savedState->readLESint32();
|
|
state->Cblocks[i].lua2C = savedState->readLESint32();
|
|
state->Cblocks[i].num = savedState->readLESint32();
|
|
}
|
|
|
|
if (savedState->saveMinorVersion() >= 3) {
|
|
state->sleepFor = savedState->readLEUint32();
|
|
}
|
|
state->id = savedState->readLEUint32();
|
|
restoreObjectValue(&state->taskFunc, savedState);
|
|
if (state->taskFunc.ttype == LUA_T_PROTO || state->taskFunc.ttype == LUA_T_CPROTO)
|
|
recreateObj(&state->taskFunc);
|
|
}
|
|
|
|
for (; currentState; currentState--)
|
|
lua_state = lua_state->next;
|
|
|
|
arraysAllreadySort = false;
|
|
arrayStringsCount = 0;
|
|
arrayHashTablesCount = 0;
|
|
arrayClosuresCount = 0;
|
|
arrayProtoFuncsCount = 0;
|
|
luaM_free(arrayClosures);
|
|
luaM_free(arrayStrings);
|
|
luaM_free(arrayHashTables);
|
|
luaM_free(arrayProtoFuncs);
|
|
arrayHashTables = nullptr;
|
|
arrayClosures = nullptr;
|
|
arrayProtoFuncs = nullptr;
|
|
arrayStrings = nullptr;
|
|
|
|
savedState->endSection();
|
|
}
|
|
|
|
} // end of namespace Grim
|