aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/util/lua_serialization_util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sword25/util/lua_serialization_util.cpp')
-rw-r--r--engines/sword25/util/lua_serialization_util.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/engines/sword25/util/lua_serialization_util.cpp b/engines/sword25/util/lua_serialization_util.cpp
index 80c5f86b20..fc3f73eca6 100644
--- a/engines/sword25/util/lua_serialization_util.cpp
+++ b/engines/sword25/util/lua_serialization_util.cpp
@@ -27,10 +27,20 @@
#include "lua/lobject.h"
#include "lua/lstate.h"
#include "lua/lgc.h"
+#include "lua/lopcodes.h"
namespace Lua {
+void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) {
+ global_State *globalState = G(luaState);
+
+ block = (*globalState->frealloc)(globalState->ud, block, osize, nsize);
+ globalState->totalbytes = (globalState->totalbytes - osize) + nsize;
+
+ return block;
+}
+
void pushObject(lua_State *luaState, TValue *obj) {
setobj2s(luaState, luaState->top, obj);
@@ -74,4 +84,263 @@ StkId getObject(lua_State *luaState, int stackpos) {
}
}
+void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) {
+ global_State *globalState = G(luaState);
+
+ obj->gch.next = globalState->rootgc;
+ globalState->rootgc = obj;
+ obj->gch.marked = luaC_white(globalState);
+ obj->gch.tt = type;
+}
+
+Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) {
+ Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements));
+ lua_linkObjToGC(luaState, obj2gco(c), LUA_TFUNCTION);
+
+ c->l.isC = 0;
+ c->l.env = elementTable;
+ c->l.nupvalues = cast_byte(numElements);
+
+ while (numElements--) {
+ c->l.upvals[numElements] = NULL;
+ }
+
+ return c;
+}
+
+void pushClosure(lua_State *luaState, Closure *closure) {
+ TValue obj;
+ setclvalue(luaState, &obj, closure);
+ pushObject(luaState, &obj);
+}
+
+Proto *createProto(lua_State *luaState) {
+ Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto));
+ lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO);
+
+ newProto->k = NULL;
+ newProto->sizek = 0;
+ newProto->p = NULL;
+ newProto->sizep = 0;
+ newProto->code = NULL;
+ newProto->sizecode = 0;
+ newProto->sizelineinfo = 0;
+ newProto->sizeupvalues = 0;
+ newProto->nups = 0;
+ newProto->upvalues = NULL;
+ newProto->numparams = 0;
+ newProto->is_vararg = 0;
+ newProto->maxstacksize = 0;
+ newProto->lineinfo = NULL;
+ newProto->sizelocvars = 0;
+ newProto->locvars = NULL;
+ newProto->linedefined = 0;
+ newProto->lastlinedefined = 0;
+ newProto->source = NULL;
+
+ return newProto;
+}
+
+TString *createString(lua_State *luaState, const char *str, size_t len) {
+ TString *res;
+ lua_pushlstring(luaState, str, len);
+
+ res = rawtsvalue(luaState->top - 1);
+ lua_pop(luaState, 1);
+
+ return res;
+}
+
+Proto *makeFakeProto(lua_State *L, lu_byte nups) {
+ Proto *p = createProto(L);
+
+ p->sizelineinfo = 1;
+ p->lineinfo = lua_newVector(L, 1, int);
+ p->lineinfo[0] = 1;
+ p->sizecode = 1;
+ p->code = lua_newVector(L, 1, Instruction);
+ p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0);
+ p->source = createString(L, "", 0);
+ p->maxstacksize = 2;
+ p->nups = nups;
+ p->sizek = 0;
+ p->sizep = 0;
+
+ return p;
+}
+
+UpVal *createUpValue(lua_State *luaState, int stackpos) {
+ UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal));
+ lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL);
+ upValue->tt = LUA_TUPVAL;
+ upValue->v = &upValue->u.value;
+ upValue->u.l.prev = NULL;
+ upValue->u.l.next = NULL;
+
+ const TValue *o2 = (TValue *)getObject(luaState, stackpos);
+ upValue->v->value = o2->value;
+ upValue->v->tt = o2->tt;
+ checkliveness(G(L), upValue->v);
+
+ return upValue;
+}
+
+void unboxUpValue(lua_State *luaState) {
+ // >>>>> ...... func
+ LClosure *lcl;
+ UpVal *uv;
+
+ lcl = (LClosure *)clvalue(getObject(luaState, -1));
+ uv = lcl->upvals[0];
+
+ lua_pop(luaState, 1);
+ // >>>>> ......
+
+ pushUpValue(luaState, uv);
+ // >>>>> ...... upValue
+}
+
+size_t appendStackToStack_reverse(lua_State *from, lua_State *to) {
+ for (StkId id = from->top - 1; id >= from->stack; --id) {
+ setobj2s(to, to->top, id);
+ to->top++;
+ }
+
+ return from->top - from->stack;
+}
+
+void correctStack(lua_State *L, TValue *oldstack) {
+ CallInfo *ci;
+ GCObject *up;
+ L->top = (L->top - oldstack) + L->stack;
+ for (up = L->openupval; up != NULL; up = up->gch.next)
+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
+ for (ci = L->base_ci; ci <= L->ci; ci++) {
+ ci->top = (ci->top - oldstack) + L->stack;
+ ci->base = (ci->base - oldstack) + L->stack;
+ ci->func = (ci->func - oldstack) + L->stack;
+ }
+ L->base = (L->base - oldstack) + L->stack;
+}
+
+void lua_reallocstack(lua_State *L, int newsize) {
+ TValue *oldstack = L->stack;
+ int realsize = newsize + 1 + EXTRA_STACK;
+
+ lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
+ L->stacksize = realsize;
+ L->stack_last = L->stack + newsize;
+ correctStack(L, oldstack);
+}
+
+void lua_growstack(lua_State *L, int n) {
+ // Double size is enough?
+ if (n <= L->stacksize) {
+ lua_reallocstack(L, 2 * L->stacksize);
+ } else {
+ lua_reallocstack(L, L->stacksize + n);
+ }
+}
+
+void lua_reallocCallInfo(lua_State *lauState, int newsize) {
+ CallInfo *oldci = lauState->base_ci;
+ lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo);
+
+ lauState->size_ci = newsize;
+ lauState->ci = (lauState->ci - oldci) + lauState->base_ci;
+ lauState->end_ci = lauState->base_ci + lauState->size_ci - 1;
+}
+
+void GCUnlink(lua_State *luaState, GCObject *gco) {
+ GCObject *prevslot;
+ if (G(luaState)->rootgc == gco) {
+ G(luaState)->rootgc = G(luaState)->rootgc->gch.next;
+ return;
+ }
+
+ prevslot = G(luaState)->rootgc;
+ while (prevslot->gch.next != gco) {
+ prevslot = prevslot->gch.next;
+ }
+
+ prevslot->gch.next = prevslot->gch.next->gch.next;
+}
+
+TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) {
+ lua_pushlstring(luaState, str, len);
+ TString *luaStr = &(luaState->top - 1)->value.gc->ts;
+
+ lua_pop(luaState, 1);
+
+ return luaStr;
+}
+
+void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) {
+ global_State *g = G(luaState);
+ o->gch.next = g->rootgc;
+ g->rootgc = o;
+ o->gch.marked = luaC_white(g);
+ o->gch.tt = tt;
+}
+
+Proto *lua_newproto(lua_State *luaState) {
+ Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto));
+ lua_link(luaState, obj2gco(f), LUA_TPROTO);
+ f->k = NULL;
+ f->sizek = 0;
+ f->p = NULL;
+ f->sizep = 0;
+ f->code = NULL;
+ f->sizecode = 0;
+ f->sizelineinfo = 0;
+ f->sizeupvalues = 0;
+ f->nups = 0;
+ f->upvalues = NULL;
+ f->numparams = 0;
+ f->is_vararg = 0;
+ f->maxstacksize = 0;
+ f->lineinfo = NULL;
+ f->sizelocvars = 0;
+ f->locvars = NULL;
+ f->linedefined = 0;
+ f->lastlinedefined = 0;
+ f->source = NULL;
+ return f;
+}
+
+UpVal *makeUpValue(lua_State *luaState, int stackPos) {
+ UpVal *uv = lua_new(luaState, UpVal);
+ lua_link(luaState, (GCObject *)uv, LUA_TUPVAL);
+ uv->tt = LUA_TUPVAL;
+ uv->v = &uv->u.value;
+ uv->u.l.prev = NULL;
+ uv->u.l.next = NULL;
+
+ setobj(luaState, uv->v, getObject(luaState, stackPos));
+
+ return uv;
+}
+
+void boxUpValue_start(lua_State *luaState) {
+ LClosure *closure;
+ closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt));
+ pushClosure(luaState, (Closure *)closure);
+ // >>>>> ...... func
+ closure->p = makeFakeProto(luaState, 1);
+
+ // Temporarily initialize the upvalue to nil
+ lua_pushnil(luaState);
+ closure->upvals[0] = makeUpValue(luaState, -1);
+ lua_pop(luaState, 1);
+}
+
+void boxUpValue_finish(lua_State *luaState) {
+ // >>>>> ...... func obj
+ LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2));
+
+ lcl->upvals[0]->u.value = *getObject(luaState, -1);
+ lua_pop(luaState, 1);
+ // >>>>> ...... func
+}
+
} // End of namespace Lua