diff --git a/section/GetTableSize.cpp b/section/GetTableSize.cpp index 7430f0b..716878c 100644 --- a/section/GetTableSize.cpp +++ b/section/GetTableSize.cpp @@ -1,109 +1,133 @@ -void GetTableSize() +#include "include/LuaAPI.h" +namespace lua +{ + struct TObject + { + int tt; + void *value; + }; + + struct Node + { + TObject i_key; + TObject i_val; + Node *next; + }; + + struct Table + { + /* lua::GCObject*/ void *next; + uint8_t tt; + uint8_t marked; + uint16_t gap; + uint8_t flags; + uint8_t lsizenode; + // padding byte + // padding byte + Table *metatable; + TObject *array; + lua::Node *node; + lua::Node *firstfree; + /*lua::GCObject*/ void *gclist; + int sizearray; + }; + +} // namespace lua + +VALIDATE_SIZE(lua::Table, 0x24); + +int lua_tablesize(lua_State *L) { - asm( - "PushNumber = 0x0090CD40;" - "MOV EAX,[ESI+0xC];" - "CMP EAX,[ESI+0x8];" - "JAE Err;" - "CMP DWORD PTR [EAX],0x5;" - "JNE Err;" - "MOV EAX,[EAX+0x4];" - "XOR EBX,EBX;" - "MOV CL,[EAX+0x9];" - "TEST CL,CL;" - "JZ GTS_L2;" - "MOV EDX,1;" - "SHL EDX,CL;" - "MOV ECX,[EAX+0x14];" - "GTS_L3:;" - "CMP DWORD PTR [ECX+0x8],0x0;" - "JE GTS_L4;" - "ADD EBX,0x1;" - "GTS_L4:;" - "ADD ECX,0x14;" - "DEC EDX;" - "JNZ GTS_L3;" - "GTS_L2:;" - "MOV EDX,[EAX+0x20];" - "TEST EDX,EDX;" - "JZ GTS_L7;" - "MOV ECX,[EAX+0x10];" - "GTS_L5:;" - "CMP DWORD PTR [ECX],0x0;" - "JE GTS_L6;" - "ADD EBX,0x1;" - "GTS_L6:;" - "ADD ECX,0x8;" - "DEC EDX;" - "JNZ GTS_L5;" - "GTS_L7:;" - "CVTSI2SS XMM0,EBX;" - "SUB ESP,0x4;" - "MOVSS [ESP],XMM0;" - "PUSH ESI;" - "CALL PushNumber;" - "ADD ESP,0x8;" - "MOV EAX,0x1;" - "RET;" - "Err:;" - "SUB ESP,0x4;" - "XORPS XMM0, XMM0;" - "MOVSS [ESP],XMM0;" - "PUSH ESI;" - "CALL PushNumber;" - "ADD ESP,0x8;" - "MOV EAX,0x1;" - "RET;" - ); + int size = 0; + auto base = GetField(L, 0xC); + auto top = GetField(L, 0x8); + if (base >= top || base->tt != LUA_TTABLE) + { + lua_pushnumber(L, size); + return 1; + } + + auto table = (lua::Table *)base->value; + uint8_t lsizenode = table->lsizenode; + if (lsizenode) + { + uint32_t num_nodes = 1 << lsizenode; + auto node = table->node; + do + { + if (node->i_val.tt) + ++size; + ++node; + --num_nodes; + } while (num_nodes); + } + int sizearray = table->sizearray; + if (sizearray) + { + auto array = table->array; + do + { + if (array->tt) + ++size; + ++array; + --sizearray; + } while (sizearray); + } + + lua_pushnumber(L, size); + return 1; } -void IsTableEmpty() +int lua_tableempty(lua_State *L) { - asm( - "MOV EAX,[ESI+0xC];" - "CMP EAX,[ESI+0x8];" - "JAE ITE_L72;" - "CMP DWORD PTR [EAX],0x5;" - "JNE ITE_L72;" - "MOV EAX,[EAX+0x4];" - "MOV CL,[EAX+0x9];" - "TEST CL,CL;" - "JZ ITE_L22;" - "MOV EDX,1;" - "SHL EDX,CL;" - "MOV ECX,[EAX+0x14];" - "ITE_L32:;" - "CMP DWORD PTR [ECX+0x8],0x0;" - "JNE ITE_L62;" - "ADD ECX,0x14;" - "DEC EDX;" - "JNZ ITE_L32;" - "ITE_L22:;" - "MOV EDX,[EAX+0x20];" - "TEST EDX,EDX;" - "JZ ITE_L72;" - "MOV ECX,[EAX+0x10];" - "ITE_L5:;" - "CMP DWORD PTR [ECX],0x0;" - "JNE ITE_L62;" - "ADD ECX,0x8;" - "DEC EDX;" - "JNZ ITE_L5;" - "ITE_L72:;" - "PUSH 0x1;" - "JMP ITE_L12;" - "ITE_L62:;" - "PUSH 0x0;" - "ITE_L12:;" - "PUSH ESI;" - "CALL 0x0090CF80;" //PushBool - "ADD ESP,0x8;" - "MOV EAX,0x1;" - ); + auto base = GetField(L, 0xC); + auto top = GetField(L, 0x8); + if (base >= top || base->tt != LUA_TTABLE) + { + lua_pushboolean(L, true); + return 1; + } + + auto table = (lua::Table *)base->value; + constexpr auto has_nodes = [](lua::Table *t) + { + uint8_t lsizenode = t->lsizenode; + if (!lsizenode) + return false; + + uint32_t num_nodes = 1 << lsizenode; + auto node = t->node; + while (node->i_val.tt == LUA_TNIL) + { + ++node; + if (!--num_nodes) + return false; + } + return true; + }; + + constexpr auto has_array = [](lua::Table *t) + { + int sizearray = t->sizearray; + if (!sizearray) + return false; + + auto array = t->array; + while (array->tt == LUA_TNIL) + { + ++array; + if (!--sizearray) + return false; + } + return true; + }; + + lua_pushboolean(L, !(has_nodes(table) || has_array(table))); + return 1; } #include "include/LuaAPI.h" -int TableClone(lua_State* L) +int TableClone(lua_State *L) { LuaObject obj{L->LuaState, 1}; LuaObject cloned{}; @@ -119,32 +143,36 @@ int TableClone(lua_State* L) // UI_Lua reprsl({table.unpack2({1,2,3,4},-1000)}) // UI_Lua reprsl({table.unpack2({1,2,3,4},0, 1000000)}) //stack overflow -int lua_unpack(lua_State *l) { - luaL_checktype(l, 1, LUA_TTABLE); - const int n = lua_getn(l, 1); - const int start_i = luaL_optnumber(l, 2, 1); - const int end_i = luaL_optnumber(l, 3, n); - if(start_i > end_i) return 0; - - const int n_stack = end_i - start_i + 1; - luaL_checkstack(l, n_stack, "too many results to unpack"); - for (int i = start_i; i <= end_i; i++) { - lua_rawgeti(l, 1, i); - } - return n_stack; +int lua_unpack(lua_State *l) +{ + luaL_checktype(l, 1, LUA_TTABLE); + const int n = lua_getn(l, 1); + const int start_i = luaL_optnumber(l, 2, 1); + const int end_i = luaL_optnumber(l, 3, n); + if (start_i > end_i) + return 0; + + const int n_stack = end_i - start_i + 1; + luaL_checkstack(l, n_stack, "too many results to unpack"); + for (int i = start_i; i <= end_i; i++) + { + lua_rawgeti(l, 1, i); + } + return n_stack; } -int RegTableFuncsDesc[] = {"getsize2",&GetTableSize, "empty2", &IsTableEmpty, - "getn2", 0x00927C20, "clone", &TableClone, - "unpack", &lua_unpack, 0, 0}; - -void RegTableFuncs() { - asm("CALL 0x0090DE00;" - "MOV DWORD PTR [ESP+0x8],%[RegTableFuncsDesc];" - "MOV DWORD PTR [ESP+0xC],0x0;" - "CALL 0x0090DE00;" - "JMP 0x009283B6;" - : - : [RegTableFuncsDesc] "i"(RegTableFuncsDesc) - :); +int RegTableFuncsDesc[] = {"getsize2", &lua_tablesize, "empty2", &lua_tableempty, + "getn2", 0x00927C20, "clone", &TableClone, + "unpack", &lua_unpack, 0, 0}; + +void RegTableFuncs() +{ + asm("CALL 0x0090DE00;" + "MOV DWORD PTR [ESP+0x8],%[RegTableFuncsDesc];" + "MOV DWORD PTR [ESP+0xC],0x0;" + "CALL 0x0090DE00;" + "JMP 0x009283B6;" + : + : [RegTableFuncsDesc] "i"(RegTableFuncsDesc) + :); } \ No newline at end of file