From c17a5d5d8393bb65bc43a7c376045d9405a15305 Mon Sep 17 00:00:00 2001 From: qaate47 Date: Sat, 30 Dec 2023 00:03:16 +0100 Subject: [PATCH] wip cw --- .gitignore | 1 + src/cli/includes.hpp | 6 + src/cli/tools/gsc.cpp | 209 +++++++++--------- src/cli/tools/gsc.hpp | 5 +- src/cli/tools/gsc_opcodes.cpp | 341 +++++++++++++++++++++++++++-- src/cli/tools/gsc_opcodes_load.cpp | 150 ++++++++++++- src/cli/tools/gsc_opcodes_load.hpp | 12 + src/cli/tools/pool.cpp | 12 +- src/cli/tools/rosetta.cpp | 40 ++-- 9 files changed, 610 insertions(+), 166 deletions(-) diff --git a/.gitignore b/.gitignore index 547f213..284ad1b 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ scripts/antlr4.jar .antlr4 src/cli/tools/ps4/* +src/cli/tools/cw/* *.aps diff --git a/src/cli/includes.hpp b/src/cli/includes.hpp index ff380fd..4f0a151 100644 --- a/src/cli/includes.hpp +++ b/src/cli/includes.hpp @@ -27,4 +27,10 @@ #endif +#if __has_include("tools/cw/cw.hpp") + +#include "tools/cw/cw.hpp" + +#endif + extern LPCCH g_progPath; \ No newline at end of file diff --git a/src/cli/tools/gsc.cpp b/src/cli/tools/gsc.cpp index 3bc5292..9983d79 100644 --- a/src/cli/tools/gsc.cpp +++ b/src/cli/tools/gsc.cpp @@ -215,27 +215,26 @@ struct T9GSCOBJ { BYTE magic[8]; INT32 crc; INT32 pad; - // 10 UINT64 name; - UINT16 unk18; // 18 - UINT16 exports_count; // 1A - UINT32 unk1c; - // 20 - UINT32 unk20; + UINT16 string_count; + UINT16 exports_count; + UINT16 imports_count; + UINT16 unk1E; + UINT32 globalvar_count; UINT16 includes_count; UINT16 unk26; UINT32 loc_28; UINT32 loc_2C; - UINT32 loc_30; - UINT32 includes_table; // 34 - UINT32 exports_tables; // 38 + UINT32 string_offset; + UINT32 includes_table; + UINT32 exports_tables; UINT32 import_tables; - UINT32 unk_3C; - UINT32 unk_40; + UINT32 globalvar_offset; UINT32 file_size; UINT32 unk_48; UINT32 unk_4C; - UINT32 unk_50; + UINT16 unk_50; + UINT16 unk_52; UINT16 unk_54; UINT16 unk_56; }; @@ -253,25 +252,46 @@ void GSCOBJReader::PatchCode(T8GSCOBJContext& ctx) { const auto* imports = reinterpret_cast(&imp[1]); for (size_t j = 0; j < imp->num_address; j++) { UINT32* loc; - switch (imp->flags & 0xF) { - case 1: - loc = PtrAlign(imports[j] + 2ull); - break; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - // here the game fix function calls with a bad number of params, - // but for the decomp/dasm we don't care because we only mind about - // what we'll find on the stack. - Ref(imports[j] + 2ull) = imp->param_count; - loc = PtrAlign(imports[j] + 2ull + 1); - break; - default: - loc = nullptr; - break; + if (GetVM() == opcode::VM_T9) { + switch (imp->flags & 0xF) { + case 5: + loc = PtrAlign(imports[j] + 2ull); + break; + case 1: + case 2: + case 3: + case 4: + case 6: + case 7: + Ref(imports[j] + 2ull) = imp->param_count; + loc = PtrAlign(imports[j] + 2ull + 1); + break; + default: + loc = nullptr; + break; + } + } + else { + switch (imp->flags & 0xF) { + case 1: + loc = PtrAlign(imports[j] + 2ull); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // here the game fix function calls with a bad number of params, + // but for the decomp/dasm we don't care because we only mind about + // what we'll find on the stack. + Ref(imports[j] + 2ull) = imp->param_count; + loc = PtrAlign(imports[j] + 2ull + 1); + break; + default: + loc = nullptr; + break; + } } if (loc) { loc[0] = imp->name; @@ -308,7 +328,7 @@ void GSCOBJReader::PatchCode(T8GSCOBJContext& ctx) { for (size_t i = 0; i < string_count; i++) { const auto* str = reinterpret_cast(str_location); - LPCH cstr = decrypt::DecryptString(Ptr(str->string)); + LPCH cstr = DecryptString(Ptr(str->string)); UINT32 ref = ctx.AddStringValue(cstr); const auto* strings = reinterpret_cast(&str[1]); @@ -404,12 +424,17 @@ namespace { UINT32 GetStringsOffset() override { return Ptr()->string_offset; } + UINT32 GetFileSize() override { + return Ptr()->script_size; + } size_t GetHeaderSize() override { return sizeof(T8GSCOBJ); } + char* DecryptString(char* str) override { + return decrypt::DecryptString(str); + } }; - /* class T9GSCOBJReader : public GSCOBJReader { using GSCOBJReader::GSCOBJReader; @@ -419,14 +444,14 @@ namespace { << std::hex << "// crc: 0x" << std::hex << data->crc << "\n" << std::left << std::setfill(' ') - << "// size ..... " << std::dec << std::setw(3) << data->script_size << "\n" + << "// size ..... " << std::dec << std::setw(3) << data->file_size << "\n" << "// includes . " << std::dec << std::setw(3) << data->includes_count << " (offset: 0x" << std::hex << data->includes_table << ")\n" << "// strings .. " << std::dec << std::setw(3) << data->string_count << " (offset: 0x" << std::hex << data->string_offset << ")\n" - << "// exports .. " << std::dec << std::setw(3) << data->exports_count << " (offset: 0x" << std::hex << data->export_table_offset << ")\n" - << "// imports .. " << std::dec << std::setw(3) << data->imports_count << " (offset: 0x" << std::hex << data->imports_offset << ")\n" + << "// exports .. " << std::dec << std::setw(3) << data->exports_count << " (offset: 0x" << std::hex << data->exports_tables << ")\n" + << "// imports .. " << std::dec << std::setw(3) << data->imports_count << " (offset: 0x" << std::hex << data->import_tables << ")\n" << "// globals .. " << std::dec << std::setw(3) << data->globalvar_count << " (offset: 0x" << std::hex << data->globalvar_offset << ")\n" << std::right - << std::flush; + << std::flush; } void DumpExperimental(std::ostream& asmout, const GscInfoOption& opt) override { } @@ -438,19 +463,19 @@ namespace { return Ptr()->exports_count; } UINT32 GetExportsOffset() override { - return Ptr()->export_table_offset; + return Ptr()->exports_tables; } UINT16 GetIncludesCount() override { - return Ptr()->include_count; + return Ptr()->includes_count; } UINT32 GetIncludesOffset() override { - return Ptr()->include_offset; + return Ptr()->includes_table; } UINT16 GetImportsCount() override { return Ptr()->imports_count; } UINT32 GetImportsOffset() override { - return Ptr()->imports_offset; + return Ptr()->import_tables; } UINT16 GetGVarsCount() override { return Ptr()->globalvar_count; @@ -464,16 +489,24 @@ namespace { UINT32 GetStringsOffset() override { return Ptr()->string_offset; } + UINT32 GetFileSize() override { + return Ptr()->script_size; + } size_t GetHeaderSize() override { return sizeof(T9GSCOBJ); } + char* DecryptString(char* str) override { +#ifdef CW_INCLUDES + return cw::DecryptString(str); +#else + return str; +#endif + } }; - */ - std::unordered_map (BYTE*)>> gscReaders = { { tool::gsc::opcode::VM_T8,[](BYTE* file) { return std::make_shared(file); }}, - //{ tool::gsc::opcode::VM_T9,[](BYTE* file) { return std::make_shared(file); }}, + { tool::gsc::opcode::VM_T9,[](BYTE* file) { return std::make_shared(file); }}, }; } @@ -538,61 +571,6 @@ int GscInfoHandleData(BYTE* data, size_t size, const char* path, const GscInfoOp return -1; } - if (vm == opcode::VM_T9) { - auto* cw = reinterpret_cast(data); - - std::cout << "cw file\n" - << std::hex << hashutils::ExtractTmpScript(cw->name) << std::endl; - - std::cout << "unk18..........: 0x" << cw->unk18 << "\n"; - std::cout << "exports_count..: 0x" << cw->exports_count << "\n"; - std::cout << "unk1c..........: 0x" << cw->unk1c << "\n"; - std::cout << "unk20..........: 0x" << cw->unk20 << "\n"; - std::cout << "includes_count.: 0x" << cw->includes_count << "\n"; - std::cout << "unk26..........: 0x" << cw->unk26 << "\n"; - std::cout << "loc_28.........: 0x" << cw->loc_28 << "\n"; - std::cout << "loc_2C.........: 0x" << cw->loc_2C << "\n"; - std::cout << "loc_30.........: 0x" << cw->loc_30 << "\n"; - std::cout << "includes_table.: 0x" << cw->includes_table << "\n"; - std::cout << "exports_tables.: 0x" << cw->exports_tables << "\n"; - std::cout << "import_tables..: 0x" << cw->import_tables << "\n"; - std::cout << "unk_3C.........: 0x" << cw->unk_3C << "\n"; - std::cout << "unk_40.........: 0x" << cw->unk_40 << "\n"; - std::cout << "file_size......: 0x" << cw->file_size << "\n"; - std::cout << "unk_48.........: 0x" << cw->unk_48 << "\n"; - std::cout << "unk_4C.........: 0x" << cw->unk_4C << "\n"; - std::cout << "unk_50.........: 0x" << cw->unk_50 << "\n"; - std::cout << "unk_54.........: 0x" << cw->unk_54 << "\n"; - std::cout << "unk_56.........: 0x" << cw->unk_56 << "\n"; - - std::cout << "sizes..........: 0x" << sizeof(*cw) << "/0x" << size << "\n"; - - auto* imps = reinterpret_cast(cw->magic + cw->import_tables); - - for (size_t i = 0; i < 4; i++) { - std::cout << i << "-" << hashutils::ExtractTmp("namespace", imps->import_namespace) << std::flush << "::" - << hashutils::ExtractTmp("function", imps->name) - << " adds: " << std::dec << imps->num_address << " params:" << (int)imps->param_count - << "\nloc: "; - auto* offs = reinterpret_cast(imps + 1); - for (size_t i = 0; i < imps->num_address; i++) { - if (i) { - std::cout << ", "; - } - std::cout << std::hex << offs[i]; - } - std::cout << "\n"; - imps = reinterpret_cast(offs + imps->param_count); - } - - - - std::cout << hashutils::ExtractTmp("hash", reinterpret_cast(cw->magic + cw->unk_3C)->name) << "\n"; - std::cout << hashutils::ExtractTmp("hash", reinterpret_cast(cw->magic + cw->unk_40)->name) << "\n"; - - return 0; - } - auto readerBuilder = gscReaders.find(vm); if (readerBuilder == gscReaders.end()) { @@ -685,17 +663,29 @@ int GscInfoHandleData(BYTE* data, size_t size, const char* path, const GscInfoOp size_t len = (size_t)reinterpret_cast(encryptedString)[1] - 1; BYTE type = *reinterpret_cast(encryptedString); - asmout << "encryption: 0x" << std::hex << (int)type << " len: " << std::dec << len << " -> " << std::flush; + if (str->string + len + 1 > scriptfile->GetFileSize()) { + asmout << "bad string location\n"; + break; + } + + asmout << "encryption: "; + if ((type & 0xC0) != 0x80) { + asmout << "0x" << std::hex << (int)type; + } + else { + asmout << "none"; + } + asmout << " len: " << std::dec << len << " -> " << std::flush; - LPCH cstr = decrypt::DecryptString(encryptedString); + LPCH cstr = scriptfile->DecryptString(encryptedString); - asmout << '"' << cstr << "\""; + asmout << '"' << cstr << "\"" << std::flush; size_t lenAfterDecrypt = strnlen_s(cstr, len + 2); if (lenAfterDecrypt != len) { asmout << " ERROR LEN (" << std::dec << lenAfterDecrypt << " != " << len << " for type 0x" << std::hex << (int)type << ")"; - assert(false); + // assert(false); } asmout << "\n"; @@ -1218,9 +1208,9 @@ int tool::gsc::T8GSCExport::DumpAsm(std::ostream& out, BYTE* gscFile, T8GSCOBJCo const auto* handler = ctx.LookupOpCode(opCode); - out << "." << std::hex << std::setfill('0') << std::setw(sizeof(INT32) << 1) << loc.rloc << ": "; + out << "." << std::hex << std::setfill('0') << std::setw(sizeof(INT32) << 1) << loc.rloc << ": " << std::flush; - if (opCode & 0x1000) { + if (opCode & ~0xFFF) { out << std::hex << "FAILURE, FIND errec: " << handler->m_name << "(" << opCode << ")" << "\n"; opCode &= 0xFFF; break; @@ -1229,7 +1219,7 @@ int tool::gsc::T8GSCExport::DumpAsm(std::ostream& out, BYTE* gscFile, T8GSCOBJCo out << std::hex << std::setfill('0') << std::setw(sizeof(INT16) << 1) << opCode << " " << std::setfill(' ') << std::setw(25) << std::left << handler->m_name << std::right - << " "; + << " " << std::flush; // dump rosetta data RosettaAddOpCode((UINT32)(reinterpret_cast(base) - reinterpret_cast(gscFile)), handler->m_id); @@ -1606,8 +1596,13 @@ void tool::gsc::T8GSCExport::DumpFunctionHeader(std::ostream& asmout, BYTE* gscF asmout << hashutils::ExtractTmp("var", lvar.name) << std::flush; } + BYTE mask = ~(tool::gsc::opcode::T8GSCLocalVarFlag::VARIADIC | tool::gsc::opcode::T8GSCLocalVarFlag::ARRAY_REF); - if (lvar.flags & ~(tool::gsc::opcode::T8GSCLocalVarFlag::VARIADIC | tool::gsc::opcode::T8GSCLocalVarFlag::ARRAY_REF)) { + if (ctx.m_vm == opcode::VM_T9) { + mask &= ~tool::gsc::opcode::T8GSCLocalVarFlag::FLAG_UNK_4; + } + + if (lvar.flags & mask) { asmout << " (unk flags: " << std::hex << (int)lvar.flags << ")"; } if (lvar.defaultValueNode) { diff --git a/src/cli/tools/gsc.hpp b/src/cli/tools/gsc.hpp index 86efe42..c0b7b90 100644 --- a/src/cli/tools/gsc.hpp +++ b/src/cli/tools/gsc.hpp @@ -180,7 +180,8 @@ namespace tool::gsc { } enum T8GSCLocalVarFlag : UINT8 { ARRAY_REF = 0x01, - VARIADIC = 0x02 + VARIADIC = 0x02, + FLAG_UNK_4 = 0x04 // T9 }; class OPCodeInfo { @@ -698,7 +699,9 @@ namespace tool::gsc { virtual UINT32 GetStringsOffset() = 0; virtual UINT16 GetGVarsCount() = 0; virtual UINT32 GetGVarsOffset() = 0; + virtual UINT32 GetFileSize() = 0; virtual size_t GetHeaderSize() = 0; + virtual char* DecryptString(char* str) = 0; virtual void DumpHeader(std::ostream& asmout) = 0; void PatchCode(T8GSCOBJContext& ctx); diff --git a/src/cli/tools/gsc_opcodes.cpp b/src/cli/tools/gsc_opcodes.cpp index c76c287..66db7c0 100644 --- a/src/cli/tools/gsc_opcodes.cpp +++ b/src/cli/tools/gsc_opcodes.cpp @@ -1214,6 +1214,40 @@ class OPCodeInfounknown : public OPCodeInfo { int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { out << "Unknown operator: " << std::hex << value << "\n"; + + for (size_t j = 0; j < 0x4; j++) { + context.WritePadding(out); + for (size_t i = 0; i < 0x8; i++) { + if (i) { + out << " "; + } + out << std::setfill('0') << std::setw(2) << std::hex << (int)context.m_bcl[i + j * 0x8]; + } + out << "\n"; + } + + for (size_t i = 0; i < 0x3; i++) { + auto* loc = utils::Aligned(context.m_bcl); + + auto hash = *reinterpret_cast(loc + i * 4); + auto* str = hashutils::ExtractPtr(hash); + + if (str) { + context.WritePadding(out) << "#" << std::dec << i << ": " << str << " (var_" << std::hex << hash << ")\n"; + } + } + + for (size_t i = 0; i < 0x3; i++) { + auto* loc = utils::Aligned(context.m_bcl); + + auto hash = *reinterpret_cast(loc + i * 8); + auto* str = hashutils::ExtractPtr(hash); + + if (str) { + context.WritePadding(out) << "#" << std::dec << i << ": #\"" << str << "\" (hash_" << std::hex << hash << ")\n"; + } + } + return -1; } int Skip(UINT16 value, ASMSkipContext& ctx) const override { @@ -1275,8 +1309,18 @@ class OPCodeInfoSafeCreateLocalVariables : public OPCodeInfo { else if (flags & T8GSCLocalVarFlag::ARRAY_REF) { out << "&"; } + else if (context.m_vm == tool::gsc::opcode::VM_T9 && (flags & tool::gsc::opcode::T8GSCLocalVarFlag::FLAG_UNK_4)) { + out << "?"; // const? + } + + + BYTE mask = ~(tool::gsc::opcode::T8GSCLocalVarFlag::VARIADIC | tool::gsc::opcode::T8GSCLocalVarFlag::ARRAY_REF); + + if (context.m_vm == tool::gsc::opcode::VM_T9) { + mask &= ~tool::gsc::opcode::T8GSCLocalVarFlag::FLAG_UNK_4; + } - if (flags & ~(T8GSCLocalVarFlag::VARIADIC | T8GSCLocalVarFlag::ARRAY_REF)) { + if (flags & mask) { out << " unk flags: " << std::hex << (int)flags; } @@ -1356,7 +1400,7 @@ class OPCodeInfoGetNeg : public OPCodeInfo { int Dump(std::ostream& out, UINT16 v, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { auto& bytecode = context.Aligned(); - INT64 negv = -*(Type*)bytecode; + INT64 negv = -(INT64)*(Type*)bytecode; bytecode += sizeof(Type); @@ -1934,6 +1978,32 @@ class OPCodeInfoSetVariableField : public OPCodeInfo { } }; +class OPCodeT9SetVariableFieldFromEvalArrayRef : public OPCodeInfo { +public: + OPCodeT9SetVariableFieldFromEvalArrayRef() : OPCodeInfo(OPCODE_T9_SetVariableFieldFromEvalArrayRef, "SetVariableFieldFromEvalArrayRef") { + } + + int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { + out << "\n"; + + if (context.m_runDecompiler) { + context.SetObjectIdASMCNode(context.GetFieldIdASMCNode()); + ASMContextNode* arrayNode = context.GetObjectIdASMCNode(); + ASMContextNode* accessNode = new ASMContextNodeArrayAccess(arrayNode, context.PopASMCNode()); + context.SetFieldIdASMCNode(accessNode); + + context.PushASMCNode(new ASMContextNodeLeftRightOperator(context.GetFieldIdASMCNode(), context.PopASMCNode(), " = ", PRIORITY_SET, TYPE_SET)); + context.CompleteStatement(); + } + + return 0; + } + + int Skip(UINT16 value, ASMSkipContext& ctx) const override { + return 0; + } +}; + class OPCodeInfoEvalSelfFieldVariable : public OPCodeInfo { public: OPCodeInfoEvalSelfFieldVariable(OPCode id, LPCCH name) : OPCodeInfo(id, name) { @@ -2117,34 +2187,39 @@ class OPCodeInfoEvalFieldVariable : public OPCodeInfo { }; class OPCodeInfoEvalLocalVariableCached : public OPCodeInfo { + int count; public: - OPCodeInfoEvalLocalVariableCached(OPCode id, LPCCH name) : OPCodeInfo(id, name) { + OPCodeInfoEvalLocalVariableCached(OPCode id, LPCCH name, int count = 1) : OPCodeInfo(id, name), count(count) { } int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { - int lvar = (int)*(context.m_bcl++); - - UINT32 name; + for (size_t i = 0; i < count; i++) { + if (i) { + context.WritePadding(out); + } + int lvar = (int)*(context.m_bcl++); - if (lvar >= context.m_localvars.size()) { - name = hashutils::Hash32(""); - out << "bad lvar ref: 0x" << std::hex << (int)lvar << "\n"; - } - else { - name = context.m_localvars[lvar].name; - context.m_localvars_ref[name]++; - out << hashutils::ExtractTmp("var", name) << std::endl; - } + UINT32 name; + if (lvar >= context.m_localvars.size()) { + name = hashutils::Hash32(""); + out << "bad lvar ref: 0x" << std::hex << (int)lvar << "\n"; + } + else { + name = context.m_localvars[lvar].name; + context.m_localvars_ref[name]++; + out << hashutils::ExtractTmp("var", name) << std::endl; + } - if (context.m_runDecompiler) { - context.PushASMCNode(new ASMContextNodeIdentifier(name)); + if (context.m_runDecompiler) { + context.PushASMCNode(new ASMContextNodeIdentifier(name)); + } } return 0; } int Skip(UINT16 value, ASMSkipContext& ctx) const override { - ctx.m_bcl++; + ctx.m_bcl += count; return 0; } }; @@ -2677,6 +2752,133 @@ class OPCodeInfoStatement : public OPCodeInfo { } }; +class OPCodeInfoProfileNamed : public OPCodeInfo { +public: + OPCodeInfoProfileNamed(OPCode id) : OPCodeInfo(id, "ProfileNamedStart") { + } + using OPCodeInfo::OPCodeInfo; + + int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { + auto& bytecode = context.Aligned(); + + UINT64 hash = *(UINT64*)bytecode; + + bytecode += 8; + + if (context.m_runDecompiler) { + ASMContextNodeMultOp* node = new ASMContextNodeMultOp("profileNamedStart", false); + + // self + node->AddParam(context.PopASMCNode()); + + context.PushASMCNode(new ASMContextNodeHash(hash)); + // convert it to statement + node->m_priority = PRIORITY_INST; + node->m_type = TYPE_STATEMENT; + context.PushASMCNode(node); + context.CompleteStatement(); + } + + out << "#\"" << hashutils::ExtractTmp("hash", hash) << "\" (#" << std::hex << hash << ")" << std::endl; + return 0; + } + int Skip(UINT16 value, ASMSkipContext& ctx) const override { + ctx.Aligned() += 8; // name + return 0; + } +}; + +class OPCodeT9EvalFieldVariableFromObjectFromRef : public OPCodeInfo { +public: + OPCodeT9EvalFieldVariableFromObjectFromRef() : OPCodeInfo(OPCODE_T9_EvalFieldVariableFromObjectFromRef, "EvalFieldVariableFromObjectFromRef") { + } + using OPCodeInfo::OPCodeInfo; + + int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { + int lvar = (int)*(context.m_bcl++); + + auto& bytecode = context.Aligned(); + + UINT32 name; + + if (lvar >= context.m_localvars.size()) { + name = hashutils::Hash32(""); + out << "bad lvar ref: 0x" << std::hex << (int)lvar; + } + else { + name = context.m_localvars[lvar].name; + context.m_localvars_ref[name]++; + out << hashutils::ExtractTmp("var", name) << std::flush; + } + + UINT32 field = *(UINT32*)bytecode; + bytecode += 4; + + out << "." << hashutils::ExtractTmp("var", field) << std::endl; + + if (context.m_runDecompiler) { + auto* left = new ASMContextNodeIdentifier(name); + auto* right = new ASMContextNodeIdentifier(field); + + context.PushASMCNode(new ASMContextNodeLeftRightOperator(left, right, ".", PRIORITY_ACCESS, TYPE_ACCESS)); + } + return 0; + } + int Skip(UINT16 value, ASMSkipContext& ctx) const override { + ctx.m_bcl++; // lvar + ctx.Aligned() += 4; // field + return 0; + } +}; + +class OPCodeT9SetFieldVariableFromObjectFromRef : public OPCodeInfo { +public: + OPCodeT9SetFieldVariableFromObjectFromRef() : OPCodeInfo(OPCODE_T9_SetFieldVariableFromObjectFromRef, "SetFieldVariableFromObjectFromRef") { + } + + int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { + int lvar = (int)*(context.m_bcl++); + + auto& bytecode = context.Aligned(); + + UINT32 name; + + if (lvar >= context.m_localvars.size()) { + name = hashutils::Hash32(""); + out << "bad lvar ref: 0x" << std::hex << (int)lvar; + } + else { + name = context.m_localvars[lvar].name; + context.m_localvars_ref[name]++; + out << hashutils::ExtractTmp("var", name) << std::flush; + } + + UINT32 field = *(UINT32*)bytecode; + bytecode += 4; + + out << "." << hashutils::ExtractTmp("var", field) << std::endl; + + if (context.m_runDecompiler) { + auto* left = new ASMContextNodeIdentifier(name); + auto* right = new ASMContextNodeIdentifier(field); + + auto* objectNode = new ASMContextNodeLeftRightOperator(left, right, ".", PRIORITY_ACCESS, TYPE_ACCESS); + auto* node = new ASMContextNodeLeftRightOperator( + new ASMContextNodeLeftRightOperator(objectNode, new ASMContextNodeIdentifier(name), ".", PRIORITY_ACCESS, TYPE_ACCESS), + context.PopASMCNode(), " = ", PRIORITY_SET, TYPE_SET); + context.SetFieldIdASMCNode(node->Clone()); + context.PushASMCNode(node); + context.CompleteStatement(); + } + return 0; + } + int Skip(UINT16 value, ASMSkipContext& ctx) const override { + ctx.m_bcl++; // lvar + ctx.Aligned() += 4; // field + return 0; + } +}; + class OPCodeInfoFunctionOperator : public OPCodeInfo { LPCCH m_operatorName; bool m_hasSelf; @@ -3121,6 +3323,53 @@ class OPCodeInfoGetGlobal : public OPCodeInfo { } }; +class OPCodeT9EvalFieldVariableFromGlobalObject : public OPCodeInfo { +public: + OPCodeT9EvalFieldVariableFromGlobalObject() : OPCodeInfo(OPCODE_T9_EvalFieldVariableFromGlobalObject, "EvalFieldVariableFromGlobalObject") { + } + + int Dump(std::ostream& out, UINT16 v, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { + auto& base = context.Aligned(); + + UINT16 ref = *(UINT16*)base; + + UINT32 name = objctx.GetGlobalVarName(ref); + + base += 2; + + auto& baseField = context.Aligned(); + + UINT32 field = *(UINT32*)baseField; + + base += 4; + + if (name) { + out << hashutils::ExtractTmp("var", name) << std::flush; + } + else { + out << "bad gvar ref: 0x" << std::hex << ref; + } + + out << "." << hashutils::ExtractTmp("var", field) << std::endl; + + if (context.m_runDecompiler) { + auto* left = new ASMContextNodeIdentifier(name); + auto* right = new ASMContextNodeIdentifier(field); + + context.SetObjectIdASMCNode(left->Clone()); + context.SetFieldIdASMCNode(new ASMContextNodeLeftRightOperator(left, right, ".", PRIORITY_ACCESS, TYPE_ACCESS)); + } + + return 0; + } + + int Skip(UINT16 value, ASMSkipContext& ctx) const override { + ctx.Aligned() += 2; + ctx.Aligned() += 4; + return 0; + } +}; + class OPCodeInfoGetLocalVar : public OPCodeInfo { public: using OPCodeInfo::OPCodeInfo; @@ -3163,7 +3412,7 @@ class OPCodeInfoSwitch : public OPCodeInfo { auto& baseCases = context.Aligned(); - INT32 cases = *(INT32*)baseCases; + INT32 cases = (*(INT32*)baseCases) & 0x7FFFFFFF; baseCases += 4; @@ -3180,7 +3429,7 @@ class OPCodeInfoSwitch : public OPCodeInfo { context.WritePadding(out); - INT64 caseValue = *(INT64*)baseCaseValue; + UINT64 caseValue = *(UINT64*)baseCaseValue; baseCaseValue += 8; auto& baseCaseDelta = context.Aligned(); INT64 caseDelta = *(INT64*)baseCaseDelta; @@ -3466,7 +3715,6 @@ class OPCodeInfoT8CGetLazyFunction : public OPCodeInfo { } }; - class OPCodeInfoDeltaVal : public OPCodeInfo { public: LPCCH m_op; @@ -3489,6 +3737,44 @@ class OPCodeInfoDeltaVal : public OPCodeInfo { return 0; } }; + +class OPCodeT9DeltaLocalVariableCached : public OPCodeInfo { +public: + LPCCH m_op; + OPCodeT9DeltaLocalVariableCached(OPCode id, LPCCH name, LPCCH op) : OPCodeInfo(id, name), m_op(op) { + } + + int Dump(std::ostream& out, UINT16 value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override { + int lvar = (int)*(context.m_bcl++); + + UINT32 name; + + if (lvar >= context.m_localvars.size()) { + name = hashutils::Hash32(""); + out << "bad lvar ref: 0x" << std::hex << (int)lvar; + } + else { + name = context.m_localvars[lvar].name; + context.m_localvars_ref[name]++; + out << hashutils::ExtractTmp("var", name) << std::flush; + } + + out << m_op << "\n"; + + if (context.m_runDecompiler) { + auto* op = new ASMContextNodeIdentifier(name); + context.PushASMCNode(new ASMContextNodeOp1(m_op, false, op, TYPE_DELTA)); + context.CompleteStatement(); + } + return 0; + } + + int Skip(UINT16 value, ASMSkipContext& ctx) const override { + ctx.m_bcl++; + return 0; + } +}; + #pragma endregion #pragma region opcode_registry @@ -3537,6 +3823,8 @@ void tool::gsc::opcode::RegisterOpCodes() { // all op without params RegisterOpCodeHandler(new OPCodeInfoStatement(OPCODE_ProfileStart, "ProfileStart", "profilestart()")); RegisterOpCodeHandler(new OPCodeInfoStatement(OPCODE_ProfileStop, "ProfileStop", "profilestop()")); + RegisterOpCodeHandler(new OPCodeInfoProfileNamed(OPCODE_ProfileNamedStart)); + RegisterOpCodeHandler(new OPCodeInfoStatement(OPCODE_ProfileNamedEnd, "ProfileNamedEnd", "profileNamedStop()")); RegisterOpCodeHandler(new OPCodeInfoStatement(OPCODE_Unknown10e, "Unknown10e", "operator_Unknown10e()")); RegisterOpCodeHandler(new OPCodeInfoStatement(OPCODE_Unknown126, "Unknown126", "operator_Unknown126()")); @@ -3588,6 +3876,7 @@ void tool::gsc::opcode::RegisterOpCodes() { RegisterOpCodeHandler(new OPCodeInfoCheckClearParams()); RegisterOpCodeHandler(new OPCodeInfoSafeCreateLocalVariables()); RegisterOpCodeHandler(new OPCodeInfoEvalLocalVariableCached(OPCODE_EvalLocalVariableCached, "EvalLocalVariableCached")); + RegisterOpCodeHandler(new OPCodeInfoEvalLocalVariableCached(OPCODE_EvalLocalVariableCachedSafe, "EvalLocalVariableCachedSafe")); RegisterOpCodeHandler(new OPCodeInfoSetLocalVariableCached(OPCODE_SetLocalVariableCachedOnStack, "SetLocalVariableCachedOnStack", true)); RegisterOpCodeHandler(new OPCodeInfoSetLocalVariableCached(OPCODE_SetLocalVariableCached, "SetLocalVariableCached", false)); @@ -3652,6 +3941,7 @@ void tool::gsc::opcode::RegisterOpCodes() { RegisterOpCodeHandler(new OPCodeInfoGetConstant(OPCODE_GetTime, "GetTime", "gettime()")); RegisterOpCodeHandler(new OPCodeInfoGetHash()); RegisterOpCodeHandler(new OPCodeInfoGetConstant(OPCODE_GetZero, "GetZero", 0)); + RegisterOpCodeHandler(new OPCodeInfoGetNeg(OPCODE_GetNegUnsignedInteger, "OPCODE_GetNegUnsignedInteger")); RegisterOpCodeHandler(new OPCodeInfoGetNeg(OPCODE_GetNegUnsignedShort, "GetNegUnsignedShort")); RegisterOpCodeHandler(new OPCodeInfoGetNeg(OPCODE_GetNegByte, "GetNegByte")); RegisterOpCodeHandler(new OPCodeInfoGetNumber(OPCODE_GetByte, "GetByte")); @@ -3712,6 +4002,15 @@ void tool::gsc::opcode::RegisterOpCodes() { RegisterOpCodeHandler(new OPCodeInfoGetGlobal(OPCODE_GetGlobal, "GetGlobal")); RegisterOpCodeHandler(new OPCodeInfoGetGlobal(OPCODE_GetGlobalObject, "GetGlobalObject")); + // T9 + RegisterOpCodeHandler(new OPCodeT9EvalFieldVariableFromObjectFromRef()); + RegisterOpCodeHandler(new OPCodeT9SetFieldVariableFromObjectFromRef()); + RegisterOpCodeHandler(new OPCodeT9EvalFieldVariableFromGlobalObject()); + RegisterOpCodeHandler(new OPCodeT9SetVariableFieldFromEvalArrayRef()); + RegisterOpCodeHandler(new OPCodeT9DeltaLocalVariableCached(OPCODE_T9_IncLocalVariableCached, "T9IncLocalVariableCached", "++")); + + RegisterOpCodeHandler(new OPCodeInfoEvalLocalVariableCached(OPCODE_T9_EvalLocalVariableCachedDouble, "EvalLocalVariableCached2n", 2)); + // T8compiler custom opcode RegisterOpCodeHandler(new OPCodeInfoT8CGetLazyFunction()); diff --git a/src/cli/tools/gsc_opcodes_load.cpp b/src/cli/tools/gsc_opcodes_load.cpp index 5a8dff7..51b48ee 100644 --- a/src/cli/tools/gsc_opcodes_load.cpp +++ b/src/cli/tools/gsc_opcodes_load.cpp @@ -282,7 +282,7 @@ void tool::gsc::opcode::RegisterOpCodesMap() { RegisterOpCode(0x36, PLATFORM_PC, OPCODE_EvalSelfFieldVariable, 0xd3, 0x134, 0x1f7, 0x46f, 0x59c, 0x657, 0x66b, 0x774, 0x88b, 0x8a3, 0x93b, 0xaaf, 0xbb7, 0xc2e, 0xcca, 0xce8, 0xd91); RegisterOpCode(0x36, PLATFORM_PC, OPCODE_Minus, 0xd9, 0x13b, 0x22a, 0x395, 0x520, 0x536, 0x6ae, 0x6fe, 0x771, 0x86a, 0x963, 0xa97, 0xb1c, 0xb24, 0xbc3, 0xbc9, 0xe5c, 0xe7f, 0xf68, 0xfdf); RegisterOpCode(0x36, PLATFORM_PC, OPCODE_ProfileStop, 0xdc, 0x20d, 0x59b, 0x875, 0x99f, 0xa51, 0xc6d, 0xce0, 0xf50, 0xf60, 0xfcd); - RegisterOpCode(0x36, PLATFORM_PC, OPCODE_GetInteger, 0xe1, 0x1ec, 0x321, 0x3f2, 0x471, 0x4c9, 0x4df, 0x58b, 0x635, 0x749, 0x803, 0x837, 0x935, 0x95f, 0x9d2, 0xa0d, 0xa12, 0xa9a, + RegisterOpCode(0x36, PLATFORM_PC, OPCODE_GetNegUnsignedInteger, 0xe1, 0x1ec, 0x321, 0x3f2, 0x471, 0x4c9, 0x4df, 0x58b, 0x635, 0x749, 0x803, 0x837, 0x935, 0x95f, 0x9d2, 0xa0d, 0xa12, 0xa9a, 0xe97, 0xe9d, 0xeb4, 0xf65); RegisterOpCode(0x36, PLATFORM_PC, OPCODE_ClassFunctionThreadCall, 0xe3, 0x114, 0x1a1, 0x1d6, 0x3b5, 0x451, 0x50a, 0x53e, 0x5fd, 0x6b4, 0x709, 0x793, 0xa55, 0xa81, 0xaad, 0xb69, 0xbd0, 0xc46, 0xcbe, 0xd25, 0xd61, 0xd7f, 0xde8, 0xebf, 0xee8, 0xeed, 0xf6f); @@ -356,22 +356,155 @@ void tool::gsc::opcode::RegisterOpCodesMap() { RegisterVM(0x37, "Call of Duty 2020"); - RegisterVM(0x38, "Call of Duty: Black Ops Cold War"); - #ifdef PS4_INCLUDES ps4::RegisterPS4OpCodes(); #endif - RegisterVM(0x38, "Call of Duty: Black ops Cold War retail"); + RegisterVM(0x38, "Call of Duty: Black ops Cold War"); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown0, 0x0); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown1, 0x1); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown2, 0x2); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown3, 0x3); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown4, 0x4); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown5, 0x5); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown6, 0x6); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknown7, 0x7); + RegisterOpCode(0x36, PLATFORM_PC, OPCODE_EvalLocalVariableCachedDebug, 0x8); + RegisterOpCode(0x36, PLATFORM_PC, OPCODE_EvalLocalVariableRefCachedDebug, 0x9); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknowna, 0xa); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Unknownb, 0xb); RegisterOpCode(0x38, PLATFORM_PC, OPCODE_ClearParams, 0xc); RegisterOpCode(0x38, PLATFORM_PC, OPCODE_CheckClearParams, 0xd); RegisterOpCode(0x38, PLATFORM_PC, OPCODE_PreScriptCall, 0xe); RegisterOpCode(0x38, PLATFORM_PC, OPCODE_CallBuiltinFunction, 0xf); RegisterOpCode(0x38, PLATFORM_PC, OPCODE_CallBuiltinMethod, 0x10); RegisterOpCode(0x38, PLATFORM_PC, OPCODE_End, 0x11); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x13, 0x14, 0x18, 0x1b, 0x1e, 0x1f, 0x22, 0x24, + 0x25, 0x29, 0x2b, 0x2e, 0x2f, 0x30, 0x35, 0x38, 0x3b, 0x3c, 0x47, 0x48, 0x4b, 0x4c, 0x4e, + 0x52, 0x53, 0x56, 0x59, 0x5d, 0x60, 0x65, 0x76, 0x78, 0x7c, 0x83, 0x85, 0x87, 0x8a, 0x8e, + 0x95, 0x9a, 0x9f, 0xa0, 0xa4, 0xa6, 0xab, 0xad, 0xb0, 0xb3, 0xb4, 0xb9, 0xc3, 0xc5, 0xcc, + 0xcf, 0xd3, 0xd4, 0xd9, 0xda, 0xdf, 0xef, 0xf4, 0xf7, 0xf9, 0xfe, 0x102, 0x105, 0x106, + 0x10a, 0x10f, 0x114, 0x115, 0x118, 0x119, 0x11b, 0x11d, 0x12c, 0x12d, 0x131, 0x136, 0x13e, + 0x13f, 0x142, 0x14c, 0x14f, 0x154, 0x155, 0x159, 0x15b, 0x15c, 0x164, 0x165, 0x168, 0x16c + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x16d, 0x170, 0x17e, 0x17f, 0x180, 0x181, 0x184, 0x186, 0x187, 0x189, 0x18a, 0x18d, 0x18e, + 0x190, 0x192, 0x193, 0x195, 0x197, 0x199, 0x19c, 0x19e, 0x1a8, 0x1ab, 0x1ac, 0x1af, 0x1b0, + 0x1b3, 0x1b6, 0x1c5, 0x1c7, 0x1c8, 0x1ca, 0x1d5, 0x1d6, 0x1da, 0x1e4, 0x1e5, 0x1e6, 0x1e8, + 0x1ef, 0x1f2, 0x1f3, 0x1f5, 0x1f9, 0x1fb, 0x1fd, 0x202, 0x206, 0x207, 0x208, 0x20e, 0x20f, + 0x210, 0x215, 0x218, 0x219, 0x21a, 0x21b, 0x21c, 0x22e, 0x230, 0x239, 0x23c, 0x23e, 0x242, + 0x247, 0x249, 0x24c, 0x24e, 0x251, 0x25c, 0x25f, 0x260, 0x261, 0x262, 0x266, 0x267, 0x26c, + 0x26f, 0x272, 0x27c, 0x283, 0x284, 0x285, 0x286, 0x287, 0x289, 0x28e, 0x293, 0x294, 0x298 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x29a, 0x29b, 0x29e, 0x2a0, 0x2a7, 0x2ad, 0x2af, 0x2b5, 0x2b6, 0x2bb, 0x2c0, 0x2c5, 0x2c7, + 0x2cd, 0x2cf, 0x2d2, 0x2d4, 0x2da, 0x2dc, 0x2de, 0x2df, 0x2e1, 0x2e7, 0x2e9, 0x2ea, 0x2f3, + 0x2f4, 0x2fa, 0x2fb, 0x2fe, 0x2ff, 0x301, 0x303, 0x304, 0x307, 0x30a, 0x311, 0x315, 0x31d, + 0x320, 0x321, 0x324, 0x325, 0x32b, 0x32e, 0x330, 0x331, 0x334, 0x339, 0x341, 0x343, 0x348, + 0x34a, 0x34d, 0x34f, 0x352, 0x356, 0x357, 0x358, 0x35b, 0x35c, 0x362, 0x363, 0x36f, 0x370, + 0x371, 0x373, 0x374, 0x375, 0x378, 0x37d, 0x37e, 0x381, 0x382, 0x385, 0x387, 0x389, 0x391, + 0x393, 0x39a, 0x39e, 0x3a1, 0x3a2, 0x3a4, 0x3a6, 0x3b5, 0x3b6, 0x3b7, 0x3b9, 0x3bc, 0x3c2 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x3c5, 0x3c6, 0x3c8, 0x3c9, 0x3ca, 0x3d2, 0x3d4, 0x3e0, 0x3e2, 0x3e8, 0x3ed, 0x3ee, 0x3f0, + 0x3f1, 0x3f5, 0x3f8, 0x3fb, 0x3ff, 0x404, 0x405, 0x406, 0x40a, 0x40b, 0x415, 0x416, 0x419, + 0x41a, 0x420, 0x422, 0x423, 0x424, 0x429, 0x42e, 0x435, 0x436, 0x43a, 0x43b, 0x43c, 0x43e, + 0x440, 0x441, 0x443, 0x448, 0x452, 0x456, 0x459, 0x45d, 0x45f, 0x462, 0x464, 0x465, 0x469, + 0x46b, 0x46c, 0x46e, 0x471, 0x474, 0x477, 0x47a, 0x47d, 0x483, 0x484, 0x485, 0x486, 0x48c, + 0x496, 0x497, 0x49e, 0x4a0, 0x4a6, 0x4a8, 0x4aa, 0x4ab, 0x4ae, 0x4b4, 0x4be, 0x4c0, 0x4c3, + 0x4cf, 0x4d3, 0x4db, 0x4dd, 0x4e5, 0x4e8, 0x4ea, 0x4ec, 0x4ee, 0x4f3, 0x4f5, 0x500, 0x505 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x508, 0x509, 0x50d, 0x512, 0x51a, 0x51b, 0x51d, 0x51f, 0x522, 0x525, 0x527, 0x52a, 0x52c, + 0x52f, 0x530, 0x531, 0x532, 0x533, 0x536, 0x538, 0x53a, 0x53c, 0x53d, 0x540, 0x546, 0x547, + 0x548, 0x54b, 0x556, 0x557, 0x558, 0x55d, 0x55f, 0x560, 0x562, 0x565, 0x569, 0x56e, 0x571, + 0x572, 0x573, 0x57d, 0x581, 0x586, 0x58e, 0x59b, 0x59d, 0x5a2, 0x5a5, 0x5ab, 0x5ac, 0x5ae, + 0x5b2, 0x5b4, 0x5b5, 0x5b8, 0x5b9, 0x5bc, 0x5c7, 0x5cf, 0x5d1, 0x5d2, 0x5d6, 0x5d7, 0x5d9, + 0x5da, 0x5db, 0x5dd, 0x5de, 0x5df, 0x5e6, 0x5ec, 0x5ee, 0x5f3, 0x5f7, 0x5f8, 0x5fc, 0x5fd, + 0x601, 0x602, 0x606, 0x609, 0x60f, 0x61d, 0x61f, 0x624, 0x626, 0x627, 0x628, 0x629, 0x62c + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x631, 0x634, 0x635, 0x638, 0x63a, 0x63e, 0x641, 0x646, 0x649, 0x650, 0x656, 0x65d, 0x665, + 0x669, 0x66a, 0x66d, 0x66f, 0x674, 0x675, 0x67a, 0x67b, 0x680, 0x686, 0x68f, 0x695, 0x696, + 0x697, 0x698, 0x69a, 0x69b, 0x69c, 0x69e, 0x6a2, 0x6ab, 0x6ac, 0x6ae, 0x6af, 0x6b6, 0x6b9, + 0x6bd, 0x6bf, 0x6c3, 0x6c4, 0x6cd, 0x6d0, 0x6d3, 0x6d7, 0x6db, 0x6e2, 0x6e4, 0x6e5, 0x6e6, + 0x6e7, 0x6e9, 0x6ec, 0x6ef, 0x6f2, 0x6f4, 0x6f5, 0x6ff, 0x704, 0x706, 0x709, 0x70b, 0x70c, + 0x70e, 0x70f, 0x710, 0x711, 0x715, 0x717, 0x71a, 0x71c, 0x720, 0x725, 0x726, 0x72a, 0x72c, + 0x72f, 0x742, 0x748, 0x74b, 0x74d, 0x754, 0x755, 0x759, 0x75b, 0x75d, 0x75e, 0x763, 0x764 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x765, 0x769, 0x76a, 0x76c, 0x774, 0x777, 0x77c, 0x782, 0x783, 0x787, 0x78d, 0x78e, 0x791, + 0x792, 0x793, 0x795, 0x796, 0x79e, 0x7a5, 0x7a8, 0x7a9, 0x7ab, 0x7ae, 0x7af, 0x7b1, 0x7b3, + 0x7b7, 0x7bc, 0x7c1, 0x7c9, 0x7cb, 0x7cc, 0x7ce, 0x7d8, 0x7db, 0x7dc, 0x7e1, 0x7e4, 0x7f0, + 0x7f6, 0x7fb, 0x7fc, 0x7fe, 0x802, 0x804, 0x80b, 0x80f, 0x811, 0x812, 0x815, 0x816, 0x81b, + 0x81e, 0x829, 0x82e, 0x830, 0x832, 0x839, 0x842, 0x844, 0x848, 0x849, 0x84e, 0x84f, 0x85b, + 0x85c, 0x85e, 0x860, 0x864, 0x865, 0x867, 0x871, 0x873, 0x879, 0x87e, 0x87f, 0x883, 0x885, + 0x886, 0x88c, 0x88d, 0x88f, 0x894, 0x897, 0x89a, 0x89c, 0x8a0, 0x8a6, 0x8a9, 0x8ad, 0x8ae + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x8b1, 0x8b7, 0x8b8, 0x8b9, 0x8bc, 0x8be, 0x8c0, 0x8c3, 0x8c6, 0x8c8, 0x8ca, 0x8cb, 0x8d0, + 0x8d1, 0x8d5, 0x8d7, 0x8d8, 0x8db, 0x8df, 0x8e1, 0x8e2, 0x8e4, 0x8f1, 0x8f3, 0x8f5, 0x8fe, + 0x900, 0x902, 0x903, 0x905, 0x90c, 0x90e, 0x90f, 0x910, 0x91c, 0x91d, 0x926, 0x92a, 0x92d, + 0x93b, 0x93d, 0x944, 0x945, 0x946, 0x947, 0x948, 0x94d, 0x94e, 0x951, 0x956, 0x957, 0x95d, + 0x960, 0x968, 0x96a, 0x96e, 0x970, 0x975, 0x97c, 0x97e, 0x97f, 0x980, 0x983, 0x984, 0x987, + 0x988, 0x98f, 0x990, 0x993, 0x998, 0x999, 0x99f, 0x9a5, 0x9ad, 0x9af, 0x9b0, 0x9b1, 0x9bc, + 0x9bf, 0x9c7, 0x9c8, 0x9c9, 0x9cb, 0x9cd, 0x9ce, 0x9d1, 0x9d4, 0x9d8, 0x9d9, 0x9da, 0x9e4 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0x9e7, 0x9ea, 0x9ef, 0x9f5, 0x9f8, 0x9f9, 0x9fc, 0xa03, 0xa11, 0xa1b, 0xa1c, 0xa1d, 0xa1f, + 0xa24, 0xa25, 0xa2c, 0xa2f, 0xa37, 0xa40, 0xa42, 0xa43, 0xa45, 0xa47, 0xa4b, 0xa4f, 0xa50, + 0xa59, 0xa5b, 0xa5c, 0xa60, 0xa73, 0xa74, 0xa77, 0xa7d, 0xa80, 0xa81, 0xa82, 0xa86, 0xa88, + 0xa8c, 0xa8e, 0xa92, 0xa94, 0xa96, 0xa98, 0xa9b, 0xa9f, 0xaa1, 0xaa5, 0xaa6, 0xaa9, 0xaad, + 0xaae, 0xab1, 0xab5, 0xab7, 0xab8, 0xabe, 0xac0, 0xac2, 0xac5, 0xac6, 0xacf, 0xadb, 0xadc, + 0xae5, 0xae6, 0xae9, 0xaef, 0xaf1, 0xaf3, 0xafc, 0xb05, 0xb06, 0xb07, 0xb0b, 0xb0c, 0xb0e, + 0xb14, 0xb18, 0xb1a, 0xb1c, 0xb1d, 0xb1f, 0xb21, 0xb24, 0xb29, 0xb2e, 0xb33, 0xb36, 0xb3c + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0xb42, 0xb45, 0xb46, 0xb47, 0xb4a, 0xb4f, 0xb53, 0xb55, 0xb5a, 0xb61, 0xb68, 0xb6a, 0xb6e, + 0xb6f, 0xb70, 0xb71, 0xb74, 0xb76, 0xb80, 0xb83, 0xb85, 0xb8f, 0xb91, 0xb95, 0xb97, 0xb9a, + 0xb9d, 0xba2, 0xba6, 0xbac, 0xbad, 0xbaf, 0xbb1, 0xbb5, 0xbba, 0xbbd, 0xbbe, 0xbbf, 0xbc2, + 0xbc3, 0xbcb, 0xbcf, 0xbd3, 0xbdb, 0xbdf, 0xbe2, 0xbe4, 0xbe6, 0xbf0, 0xbf2, 0xbf3, 0xbf8, + 0xbfa, 0xbff, 0xc08, 0xc09, 0xc10, 0xc13, 0xc14, 0xc15, 0xc1d, 0xc1e, 0xc1f, 0xc26, 0xc2a, + 0xc30, 0xc32, 0xc33, 0xc34, 0xc45, 0xc46, 0xc49, 0xc4d, 0xc4f, 0xc53, 0xc54, 0xc5a, 0xc5b, + 0xc5d, 0xc5e, 0xc5f, 0xc60, 0xc63, 0xc64, 0xc65, 0xc66, 0xc67, 0xc6b, 0xc73, 0xc75, 0xc81 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0xc84, 0xc86, 0xc89, 0xc8d, 0xc91, 0xc94, 0xc97, 0xc98, 0xc9e, 0xca2, 0xca4, 0xca8, 0xca9, + 0xcac, 0xcb0, 0xcb1, 0xcb2, 0xcb6, 0xcb9, 0xcbb, 0xcbc, 0xcc3, 0xcc4, 0xcc8, 0xccd, 0xcd1, + 0xcd3, 0xce1, 0xce2, 0xce8, 0xced, 0xcf8, 0xcf9, 0xcfb, 0xcfd, 0xcff, 0xd00, 0xd05, 0xd0d, + 0xd18, 0xd1a, 0xd1b, 0xd1f, 0xd22, 0xd24, 0xd2e, 0xd31, 0xd34, 0xd35, 0xd38, 0xd3a, 0xd3d, + 0xd3e, 0xd42, 0xd44, 0xd46, 0xd4b, 0xd4d, 0xd4f, 0xd51, 0xd54, 0xd5f, 0xd62, 0xd66, 0xd69, + 0xd6b, 0xd6c, 0xd74, 0xd75, 0xd78, 0xd7a, 0xd7b, 0xd7c, 0xd7d, 0xd81, 0xd86, 0xd8e, 0xd8f, + 0xd9a, 0xda0, 0xdb4, 0xdbc, 0xdbd, 0xdbe, 0xdc1, 0xdd0, 0xdd2, 0xdd5, 0xdd6, 0xddc, 0xddd + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0xdde, 0xde2, 0xdeb, 0xdf6, 0xdfe, 0xe00, 0xe06, 0xe0b, 0xe12, 0xe14, 0xe18, 0xe19, 0xe1d, + 0xe1f, 0xe20, 0xe21, 0xe22, 0xe23, 0xe2b, 0xe2d, 0xe2f, 0xe30, 0xe33, 0xe38, 0xe39, 0xe3f, + 0xe40, 0xe41, 0xe48, 0xe4c, 0xe4d, 0xe50, 0xe55, 0xe5a, 0xe5f, 0xe62, 0xe63, 0xe6b, 0xe6e, + 0xe70, 0xe78, 0xe7c, 0xe7d, 0xe7e, 0xe7f, 0xe81, 0xe86, 0xe87, 0xe88, 0xe8c, 0xe92, 0xe93, + 0xe94, 0xe95, 0xe96, 0xe9b, 0xe9c, 0xe9e, 0xea2, 0xea5, 0xea6, 0xeb2, 0xebd, 0xec1, 0xec6, + 0xecb, 0xece, 0xed5, 0xedc, 0xee1, 0xee2, 0xee5, 0xee6, 0xee8, 0xee9, 0xeee, 0xeef, 0xef1 + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_Nop, + 0xef6, 0xefb, 0xefc, 0xefe, 0xf08, 0xf0a, 0xf10, 0xf14, 0xf15, 0xf16, 0xf1d, 0xf20, 0xf24, + 0xf29, 0xf2a, 0xf2e, 0xf33, 0xf34, 0xf36, 0xf37, 0xf38, 0xf39, 0xf3b, 0xf3f, 0xf41, 0xf43, + 0xf47, 0xf49, 0xf51, 0xf52, 0xf53, 0xf54, 0xf5b, 0xf5d, 0xf60, 0xf61, 0xf63, 0xf66, 0xf6d, + 0xf6e, 0xf70, 0xf72, 0xf75, 0xf76, 0xf7f, 0xf80, 0xf84, 0xf85, 0xf86, 0xf89, 0xf8a, 0xf8d, + 0xf8f, 0xf90, 0xf94, 0xf95, 0xf99, 0xf9a, 0xf9d, 0xf9f, 0xfa5, 0xfab, 0xfac, 0xfae, 0xfb1, + 0xfb2, 0xfb6, 0xfb7, 0xfb9, 0xfbb, 0xfcb, 0xfce, 0xfd0, 0xfd9, 0xfdb, 0xfe8, 0xfeb, 0xfed, + 0xff6, 0xff7, 0xff9, 0xffd, 0xffe, 0xfff + ); + RegisterOpCode(0x38, PLATFORM_PC, OPCODE_SafeCreateLocalVariables, + 0x6d, 0xe3, 0xe6, 0x1d7, 0x1db, 0x20d, 0x22a, 0x2a3, 0x2c8, 0x36e, 0x466, 0x576, 0x58c, + 0x6fc, 0x714, 0x72d, 0x837, 0x861, 0xb93, 0xbb6, 0xc20, 0xd17, 0xd84, 0xe0c, 0xe17 + ); +#ifdef CW_INCLUDES + cw::RegisterCWOpCodes(); +#endif }); } @@ -527,6 +660,15 @@ LPCCH tool::gsc::opcode::OpCodeName(OPCode op) { case OPCODE_EvalGlobalObjectFieldVariable: return "EvalGlobalObjectFieldVariable"; case OPCODE_EvalLocalVariableDefined: return "EvalLocalVariableDefined"; case OPCODE_T8C_GetLazyFunction: return "T8C_GetLazyFunction"; + case OPCODE_ProfileNamedStart: return "ProfileNamedStart"; + case OPCODE_ProfileNamedEnd: return "ProfileNamedEnd"; + case OPCODE_GetNegUnsignedInteger: return "GetNegUnsignedInteger"; + case OPCODE_T9_Unknown1de: return "Unknown1de"; + case OPCODE_T9_SetVariableFieldFromEvalArrayRef: return "SetVariableFieldFromEvalArrayRef"; + case OPCODE_T9_EvalFieldVariableFromObjectFromRef: return "EvalFieldVariableFromObjectFromRef"; + case OPCODE_T9_SetFieldVariableFromObjectFromRef: return "SetFieldVariableFromObjectFromRef"; + case OPCODE_T9_EvalLocalVariableCachedDouble: return "EvalLocalVariableCached2n"; + case OPCODE_T9_IncLocalVariableCached: return "IncLocalVariableCached"; default: return "UNKNOWN"; } } diff --git a/src/cli/tools/gsc_opcodes_load.hpp b/src/cli/tools/gsc_opcodes_load.hpp index 659023b..1d538a2 100644 --- a/src/cli/tools/gsc_opcodes_load.hpp +++ b/src/cli/tools/gsc_opcodes_load.hpp @@ -172,6 +172,18 @@ namespace tool::gsc::opcode { // T8-Compiler Custom opcodes OPCODE_T8C_GetLazyFunction, + // T9 + OPCODE_ProfileNamedStart, + OPCODE_ProfileNamedEnd, + OPCODE_GetNegUnsignedInteger, + OPCODE_T9_Unknown1de, + OPCODE_T9_EvalFieldVariableFromObjectFromRef, + OPCODE_T9_SetFieldVariableFromObjectFromRef, + OPCODE_T9_EvalLocalVariableCachedDouble, + OPCODE_T9_EvalFieldVariableFromGlobalObject, + OPCODE_T9_SetVariableFieldFromEvalArrayRef, + OPCODE_T9_IncLocalVariableCached, + OPCODE_COUNT, }; void RegisterOpCodesMap(); diff --git a/src/cli/tools/pool.cpp b/src/cli/tools/pool.cpp index 1b68967..f4d9b78 100644 --- a/src/cli/tools/pool.cpp +++ b/src/cli/tools/pool.cpp @@ -44,7 +44,7 @@ class PoolOption { struct XAssetTypeInfo { uintptr_t name; // const char* uint64_t size; - uint64_t unk20; + uint64_t globalvar_count; uintptr_t GetName; // const char* (__cdecl*)(const XAssetHeader*); uintptr_t SetName; // void(__cdecl* )(XAssetHeader*, uint64_t*); }; @@ -83,8 +83,8 @@ struct DDLEntry { UINT64 name; // 0x8 uintptr_t unk8; // 0x10 uintptr_t buffer; // 0x18 - uintptr_t unk18; // 0x20 - uintptr_t unk20; // 0x28 + uintptr_t string_count; // 0x20 + uintptr_t globalvar_count; // 0x28 uintptr_t unk28; // 0x30 uintptr_t unk30; // 0x38 uintptr_t unk38; // 0x40 @@ -109,7 +109,7 @@ struct BGCacheInfoDef { pool::BGCacheTypes type; uint64_t name; uint64_t pad10; - uint64_t unk18; + uint64_t string_count; }; struct BGCacheInfo { @@ -145,7 +145,7 @@ struct ScriptBundle { uint64_t hashnull; uint32_t count_sub; uint32_t unk14; - uint64_t unk18; + uint64_t string_count; SB_ObjectsArray sbObjectsArray; }; @@ -1010,7 +1010,7 @@ int pooltool(const Process& proc, int argc, const char* argv[]) { defout << "\n" << (p2.type >= 0 && p2.type < pool::BG_CACHE_TYPE_COUNT ? nameInfo[p2.type] : "") << "," << hashutils::ExtractTmp("hash", p2.name) << "," - << std::hex << p2.unk18 + << std::hex << p2.string_count << std::flush; } diff --git a/src/cli/tools/rosetta.cpp b/src/cli/tools/rosetta.cpp index 3fbdc2c..6a4fba6 100644 --- a/src/cli/tools/rosetta.cpp +++ b/src/cli/tools/rosetta.cpp @@ -242,36 +242,22 @@ namespace { return tool::BASIC_ERROR; } - struct OpCode { - uintptr_t val1; - uintptr_t val2; - uintptr_t val3; - uintptr_t val4; - }; - - struct OpCodeCount { - int val1; - int val2; - int val3; - int val4; - }; - - auto* codes = reinterpret_cast(buffer); + std::map> map{}; + auto* codes = reinterpret_cast(buffer); - std::map map{}; - - for (size_t i = 0; i < 0xFFF; i++) { - auto& c = codes[i]; - - map[c.val1].val1++; - map[c.val2].val2++; - map[c.val3].val3++; - map[c.val4].val4++; + for (size_t i = 0; i < 0x1000; i++) { + map[codes[i]].push_back(i); } - for (const auto& [loc, count] : map) { - std::cout << std::hex << loc << " -> " - << std::dec << count.val1 << "/" << count.val2 << "/" << count.val3 << "/" << count.val4 << "\n"; + for (const auto& [loc, map] : map) { + std::cout << std::hex << std::setfill('0') << std::setw(3) << map[0] << ":" << loc << " -> {"; + for (size_t i = 0; i < map.size(); i++) { + if (i) { + std::cout << ", "; + } + std::cout << std::hex << "0x" << map[i]; + } + std::cout << "}\n"; }