diff --git a/decompile/objdiff.json b/decompile/objdiff.json index de5fd0c..8000d87 100644 --- a/decompile/objdiff.json +++ b/decompile/objdiff.json @@ -30,8 +30,7 @@ }, "symbol_mappings": { "?Exec0Default__jumptable@CActSequence@@3EA": "$L1709", - "?Exec0Default__jumptargets@CActSequence@@3PAPAXA": "$L1710", - "?fSequenceMethods@CActSequence@@3PAP6EXPAU1@@ZA": "?fSequenceMethods@@3PAP8CActSequence@@AEXXZA" + "?Exec0Default__jumptargets@CActSequence@@3PAPAXA": "$L1710" } }, { @@ -59,8 +58,8 @@ "source_path": "src/JSRF/SaveData.cpp" }, "symbol_mappings": { - "?finalizeGameData@@YAXXZ": "_$E2", - "?initGameData@@YAXXZ": "_$E1" + "?finalizeSaveData@@YAXXZ": "_$E2", + "?initSaveData@@YAXXZ": "_$E1" } }, { diff --git a/ghidra/ghidra_scripts/MSVC7Mangle.java b/ghidra/ghidra_scripts/MSVC7Mangle.java index 317aba1..a7dba56 100644 --- a/ghidra/ghidra_scripts/MSVC7Mangle.java +++ b/ghidra/ghidra_scripts/MSVC7Mangle.java @@ -122,7 +122,7 @@ public class MSVC7Mangle extends GhidraScript { // Get mangled name final String mangled = switch (s.getObject()) { case Function f -> mangleFn (f); - case Data d -> mangleData(d, name); + case Data d -> mangleData(d, name, getClassNamespace(s)); default -> null; }; @@ -190,12 +190,12 @@ public class MSVC7Mangle extends GhidraScript { final ArrayList dict = new ArrayList<>(); - final List nameParts = Arrays.asList(nameRaw.split("::")); + final List nameParts = Arrays.asList(nameRaw.split("::")); Collections.reverse(nameParts); - final boolean isMethod = f.getCallingConventionName() - .equals("__thiscall") && - nameParts.size() >= 2; - final String name = mangleIdentifier(nameRaw, isMethod, f.getReturnType(), dict); + final boolean isMethod = f.getCallingConventionName() + .equals("__thiscall") && + nameParts.size() >= 2; + final String name = mangleIdentifier(nameRaw, isMethod, false, f.getReturnType(), dict); // Special methods with unique formats if (isMethod) { @@ -204,7 +204,7 @@ public class MSVC7Mangle extends GhidraScript { if (unqualified.equals( clsName)) { // Constructor return "?" + name + "QAE@" + - mangleArgs(f.getSignature(true), dict, nameRaw + "()") + + mangleArgs(f.getSignature(true), false, dict, nameRaw + "()") + "Z"; } else if (unqualified.equals("~" + clsName)) { // Destructor return "?" + name + (isVirtual(f) ? "UAE" : "QAE") + "@XZ"; @@ -218,6 +218,7 @@ public class MSVC7Mangle extends GhidraScript { private static String mangleIdentifier( final String ident, final boolean isMethod, + final boolean isMethodPtr, final DataType retType, // Function return type, nullable final List dict ) { @@ -231,7 +232,8 @@ public class MSVC7Mangle extends GhidraScript { names. */ // Break up names into their mangled order - final List parts = Arrays.asList(ident.split("::")); + List parts = Arrays.asList(ident.split("::")); + parts = parts.subList(isMethodPtr ? 1 : 0, parts.size()); Collections.reverse(parts); // Non-method special names @@ -386,8 +388,8 @@ public class MSVC7Mangle extends GhidraScript { ) throws Exception { /* Mangle everything in f but its name and visibility/linkage */ return mangleCallC(f) + - mangleType(f.getReturnType(), dict, loc) + - mangleArgs(f, dict, loc) + "Z"; + mangleType(f.getReturnType(), Optional.empty(), dict, loc) + + mangleArgs(f, false, dict, loc) + "Z"; } private static String mangleCallC(final FunctionSignature f) throws Exception { @@ -402,9 +404,10 @@ public class MSVC7Mangle extends GhidraScript { } private static String mangleType( - final DataType t, - final List dict, - final String loc + final DataType t, + final Optional classNamespace, + final List dict, + final String loc ) throws Exception { /* Mangle a data type in a function name All types are assumed to have no CV qualifiers. @@ -429,19 +432,23 @@ public class MSVC7Mangle extends GhidraScript { case DoubleDataType x -> "N"; case LongDoubleDataType x -> "O"; case Pointer p -> "P" + - (p.getDataType() instanceof FunctionSignature ? "6" : "A") + - mangleType(p.getDataType(), dict, loc); - case Union u -> "T" + mangleIdentifier(u.getName(), false, null, dict); - case Structure s -> "U" + mangleIdentifier(s.getName(), false, null, dict); - case Enum e -> "W4" + mangleIdentifier(e.getName(), false, null, dict); + (p.getDataType() instanceof FunctionSignature f ? ( + classNamespace.isPresent() ? "8" : "6" + ) : "A" + ) + mangleType(p.getDataType(), classNamespace, dict, loc); + case Union u -> "T" + mangleIdentifier(u.getName(), false, false, null, dict); + case Structure s -> "U" + mangleIdentifier(s.getName(), false, false, null, dict); + case Enum e -> "W4" + mangleIdentifier(e.getName(), false, false, null, dict); case VoidDataType x -> "X"; case LongLongDataType x -> "_J"; case UnsignedLongLongDataType x -> "_K"; case BooleanDataType x -> "_N"; case WideCharDataType x -> "_W"; - case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict, loc); - case FunctionSignature f -> mangleFnType(f, dict, "function typedef \"" + f.getName() + "\""); - case TypeDef d -> mangleType(d.getBaseDataType(), dict, "typedef \"" + d.getName() + "\""); + case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), classNamespace, dict, loc); + case FunctionSignature f -> classNamespace.isPresent() ? + mangleMethodPtr(f, classNamespace.get(), dict, loc) : + mangleFnType(f, dict, "function typedef \"" + f.getName() + "\""); + case TypeDef d -> mangleType(d.getBaseDataType(), classNamespace, dict, "typedef \"" + d.getName() + "\""); case DefaultDataType x -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined."); case Undefined x -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined."); default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\" at " + loc); @@ -490,19 +497,33 @@ public class MSVC7Mangle extends GhidraScript { return t instanceof Array a_ ? arrType(a_) : t; } + private static String mangleMethodPtr( + final FunctionSignature f, + final Namespace classNamespace, + final List dict, + final String loc + ) throws Exception { + /* Mangle pointed-to part of a method pointer (i.e. after "3PAP8") */ + return classNamespace.getName() + "@@AE" + + mangleType(f.getReturnType(), Optional.empty(), dict, loc) + + mangleArgs(f, true, dict, loc) + "Z"; + } + private static String mangleArgs( final FunctionSignature f, + final boolean isMethodPtr, final List dict, final String loc ) throws Exception { /* Mangle the arguments for a function */ - final DataType[] args = Arrays.stream(f.getArguments()) - .map(ParameterDefinition::getDataType) - .toArray(DataType[]::new); + List args = Arrays.stream(f.getArguments()) + .map(ParameterDefinition::getDataType) + .toList(); + args = args.subList(isMethodPtr ? 1 : 0, args.size()); final ArrayList argDict = new ArrayList<>(); - if (args.length == 0) return "X"; + if (args.size() == 0) return "X"; else { // I try to be more expression-oriented, but not being // able to throw in lambdas, not having an error sum @@ -518,7 +539,7 @@ public class MSVC7Mangle extends GhidraScript { // helped us out here) String mangledArgs = ""; for (final DataType arg : args) { - final String mangledArg = mangleType(arg, dict, loc); + final String mangledArg = mangleType(arg, Optional.empty(), dict, loc); mangledArgs += mangledArg.length() == 1 ? mangledArg : @@ -528,9 +549,17 @@ public class MSVC7Mangle extends GhidraScript { } } + private Optional getClassNamespace(final Symbol s) { + /* Return the namespace of the class containing s, if there is one */ + final Namespace ns = s.getParentNamespace(); + return ns.getType() == Namespace.Type.CLASS ? Optional.of(ns) + : Optional.empty(); + } + private String mangleData( - final Data d, - final String name + final Data d, + final String name, + final Optional classNamespace ) throws Exception { /* Set the data symbol's name to its mangled version */ // String constants @@ -547,13 +576,19 @@ public class MSVC7Mangle extends GhidraScript { } final ArrayList dict = new ArrayList<>(); - final String ident = mangleIdentifier(name, false, null, dict); + final String ident = mangleIdentifier( + name, + false, + classNamespace.isPresent() && isFnPtr(d.getDataType(), "0x" + d.getAddress().toString()), + null, + dict + ); // vtable if (ident.startsWith("?_7")) return "?" + ident + "6B@"; return "?" + ident + "3" + - mangleType(d.getDataType(), dict, "0x" + d.getAddress().toString()) + + mangleType(d.getDataType(), classNamespace, dict, "0x" + d.getAddress().toString()) + "A"; } @@ -625,6 +660,26 @@ public class MSVC7Mangle extends GhidraScript { return (int)crc.getValue() ^ 0xFFFFFFFF; } + private static boolean isFnPtr( + final DataType t, + final String loc + ) throws Exception { + /* Determine whether the type is a function pointer (or wraps one) */ + if (t == null) throw new Exception ( + "A data type at " + loc + " was reported as null. " + + "Ensure that all data types in the code/data to " + + "mangle have been defined." + ); + + return switch(t) { + case Pointer p -> isFnPtr(p.getDataType() , loc); + case Array a -> isFnPtr(arrType(a) , loc); + case TypeDef d -> isFnPtr(d.getBaseDataType(), loc); + case FunctionSignature f -> true; + default -> false; + }; + } + private void mangleRefs( final Function f, final Set seenSymbols diff --git a/ghidra/symboltable.tsv b/ghidra/symboltable.tsv index c2bca53..8463e2e 100644 --- a/ghidra/symboltable.tsv +++ b/ghidra/symboltable.tsv @@ -34,7 +34,7 @@ 0x00011ee0 func void __thiscall notinline nofixup CActBase::recursiveExec1FreezeCam 0x00011f80 func void __thiscall notinline nofixup CActBase::recursiveExec1UncoveredPause 0x00012020 func void __thiscall notinline nofixup CActBase::insertActionTree CActBase * lpParent -0x00012100 func CActBase * __thiscall notinline nofixup CActBase::CActBase CActBase * parent eACTID index eACTFLAG flags +0x00012100 func CActBase * __thiscall notinline nofixup CActBase::CActBase CActBase * lpParent eACTID ActID eACTFLAG Flags 0x00012170 func CDrawBase * __thiscall notinline nofixup CDrawBase::CDrawBase CActBase * parent eACTID index eACTFLAG flags 0x000121b0 func void * __thiscall notinline nofixup CDrawBase::`scalar_deleting_destructor' uint param_1 0x000121d0 func void __thiscall notinline nofixup CDrawBase::~CDrawBase @@ -341,7 +341,7 @@ 0x00046920 func undefined __stdcall notinline nofixup getUnknownStatic13PartDefault UnknownStatic13Part * out 0x00046b60 func undefined __stdcall notinline nofixup getBlocksNeeded uint param_1 0x00046e20 func BOOL __thiscall notinline nofixup SaveGame char cDriveLetter void * lpvSaveData -0x00047110 func BOOL __cdecl notinline nofixup SaveDataExists_MAYBE undefined * param_1 +0x00047110 func BOOL __cdecl notinline nofixup SaveDataExists_MAYBE void * unused 0x00047550 func undefined4 __thiscall notinline nofixup Progress::~Progress 0x00048100 func void __thiscall notinline nofixup Progress::Progress 0x0004a6c0 func Progress * __thiscall notinline nofixup Progress::`scalar_deleting_destructor' byte param_1 @@ -440,10 +440,10 @@ 0x00067310 func void __thiscall notinline nofixup CSaveMenu::DrawTreeDefault 0x000678b0 func BOOL __thiscall notinline nofixup CSaveMenu::Save 0x00067980 func void __thiscall notinline nofixup CSaveMenu::~CSaveMenu -0x00067b60 func CSaveMenu * __thiscall notinline nofixup CSaveMenu::CSaveMenu CActBase * parent eACTID index eACTFLAG flags undefined4 param_4 undefined4 * param_5 +0x00067b60 func CSaveMenu * __thiscall notinline nofixup CSaveMenu::CSaveMenu CActBase * parent eACTID index eACTFLAG flags undefined4 param_4 uint * param_5 0x00067e70 func void * __thiscall notinline nofixup CSaveMenu::`scalar_deleting_destructor' uint param_1 0x00067e90 func void __thiscall notinline nofixup CSaveMenu::Exec0Default -0x000681c0 func void __cdecl notinline nofixup CreateSaveMenu undefined4 param_1 undefined4 * param_2 +0x000681c0 func void __cdecl notinline nofixup CreateSaveMenu int param_1 void * param_2 0x000694a0 func float __thiscall notinline nofixup GraphicsSettings::getGraphicsSetting eGRAPHICSSETTINGTYPE setting 0x000694c0 func SGraphicsSettings * __thiscall notinline nofixup GraphicsSettings::GraphicsSettings 0x0006af00 func StageBin * __thiscall notinline nofixup StageBin::StageBin void * stgBinBuf @@ -484,11 +484,12 @@ 0x0006f6a0 func void __cdecl notinline nofixup showReconnectControllerMessage 0x0006f6d0 func void default notinline nofixup showCharacterJoinMessage ePLAYERCHARID character undefined4 controller 0x0006f730 func undefined unknown notinline nofixup ShowProblemWithDisc -0x0006f760 func undefined unknown notinline nofixup showSaveLoadErr +0x0006f760 func void __cdecl notinline nofixup ShowSaveLoadErr 0x0006f8c0 func void __thiscall notinline nofixup UnknownStatic27::calledDuringExec0Default 0x0006f9c0 func undefined4 * __thiscall notinline nofixup UnknownStatic27::`scalar_deleting_destructor' byte param_1 0x0006f9e0 func void __cdecl notinline nofixup main 0x00075a30 func undefined4 * __thiscall notinline nofixup CRoboyMenuFull::CRoboyMenuFull CActBase * param_1 eACTID param_2 uint param_3 +0x00075de0 func void __cdecl notinline nofixup CreateFullRoboyMenu void * unused DWORD param_2 0x00077400 func void __cdecl notinline nofixup resetHighScores 0x000780f0 func void __thiscall notinline nofixup UnknownObj_0x1167_2::~UnknownAllocated_0x1167_2 0x00078520 func UnknownAllocated_0x1167_2 * __thiscall notinline nofixup UnknownObj_0x1167_2::UnknownAllocated_0x1167_2 CActBase * parent eACTID index uint bitfieldValue undefined4 param_4 uint mssnId @@ -500,9 +501,11 @@ 0x0007af70 func void __thiscall notinline nofixup DemoInitializer::~DemoInitializer 0x0007b830 func DemoInitializer * __thiscall notinline nofixup DemoInitializer::`scalar_deleting_destructor' byte param_1 0x0007b8d0 func void __thiscall notinline nofixup DemoInitializer::execDefault -0x0007bc10 func CActSequence * __thiscall notinline nofixup CActSequence::CActSequence CActBase * parent eACTID index uint bitfieldValue +0x0007bc10 func CActSequence * __thiscall notinline nofixup CActSequence::CActSequence CActBase * lpParent eACTID ActID eACTFLAG ActFlag 0x0007bc90 func void __thiscall notinline nofixup CActSequence::~CActSequence 0x0007bdd0 func void __thiscall notinline nofixup CActSequence::Exec0Default +0x0007be08 data void *[2] CActSequence::Exec0Default__jumptargets +0x0007be10 data uchar CActSequence::Exec0Default__jumptable 0x0007be30 func void __thiscall notinline nofixup CActSequence::Init 0x0007bfd0 func void __thiscall notinline nofixup CActSequence::LoadSprNorm 0x0007c020 func void __thiscall notinline nofixup CActSequence::WaitLoadSprNorm @@ -562,7 +565,7 @@ 0x0007d460 func void __thiscall notinline nofixup CActSequence::PrepareStinger 0x0007d520 func void __thiscall notinline nofixup CActSequence::WaitEndStinger 0x0007d540 func void __thiscall notinline nofixup CActSequence::ReturnFromStinger -0x0007d5b0 func CActSequence * __thiscall notinline nofixup CActSequence::`scalar_deleting_constructor' byte param_1 +0x0007d5b0 func void * __thiscall notinline nofixup CActSequence::`scalar_deleting_destructor' uint param_1 0x0007e100 func BOOL default notinline nofixup 0x1DF3NotAllocated 0x0007e260 func void __stdcall notinline nofixup allocate0x1DF3 CActBase * parent 0x0007e2f0 func void __thiscall notinline nofixup Opening::~Opening @@ -1003,6 +1006,14 @@ 0x00186e38 func undefined unknown notinline nofixup ExceptionHandler 0x00187710 func void __cdecl notinline nofixup main_handler_unwind1 0x0018771b func void __cdecl notinline nofixup main_handler ExceptionRecord * param_1 EHRegistrationNode * param_2 void * param_3 EHDispatcherContext * param_4 +0x00187c70 func void __cdecl notinline nofixup CActSequence__CActSequence_handler_unwind1 +0x00187c78 func void __cdecl notinline nofixup CActSequence__CActSequence_handler ExceptionRecord * param_1 EHRegistrationNode * param_2 void * param_3 EHDispatcherContext * param_4 +0x00187c90 func void __cdecl notinline nofixup CActSequence__Init_handler_unwind1 +0x00187c9b func void __cdecl notinline nofixup CActSequence__Init_handler_unwind2 +0x00187ca6 func void __cdecl notinline nofixup CActSequence__Init_handler_unwind3 +0x00187cb1 func void __cdecl notinline nofixup CActSequence__Init_handler ExceptionRecord * param_1 EHRegistrationNode * param_2 void * param_3 EHDispatcherContext * param_4 +0x00187cc0 func void __cdecl notinline nofixup CActSequence__Prepare_common_unwind1 +0x00187ccb func void __cdecl notinline nofixup CActSequence__common_handler ExceptionRecord * param_1 EHRegistrationNode * param_2 void * param_3 EHDispatcherContext * param_4 0x0018acc0 func undefined unknown notinline nofixup initUnknownStatic01 0x0018acf0 func undefined unknown notinline nofixup initUnknownStatic02 0x0018ad00 func void __stdcall notinline nofixup initCollisionManager @@ -1124,7 +1135,7 @@ 0x001c4d58 data CActBaseVtbl CCacheBuilder::`vftable' 0x001c4f68 data CActBaseVtbl FileManager::`vftable' 0x001ca168 data pointer UnknownStatic07::vtable -0x001ca3d8 data pointer CSaveData::`vftable' +0x001ca3d8 data CSaveDataVtbl CSaveData::`vftable' 0x001ca440 data CActBaseVtbl TextRenderer_MAYBE::`vftable' 0x001ca4c8 data undefined * MissionManagerChild_0xE7::vtable 0x001ca508 data undefined * UnknownStatic09::vtable @@ -1208,6 +1219,32 @@ 0x001e5048 data EHFuncInfo initCache_funcinfo 0x001e620c data EHUnwindMapEntry[1] main_unwindmap 0x001e6214 data EHFuncInfo main_funcinfo +0x001e67ec data EHUnwindMapEntry[1] CActSequence__CActSequence_unwindmap +0x001e67f4 data EHFuncInfo CActSequence__CActSequence_funcinfo +0x001e6810 data EHUnwindMapEntry[1] CActSequence__~CActSequence_unwindmap_UNUSED +0x001e6818 data EHFuncInfo CActSequence__~CActSequence_funcinfo_UNUSED +0x001e6834 data EHUnwindMapEntry[3] CActSequence__Init_unwindmap +0x001e684c data EHFuncInfo CActSequence__Init_funcinfo +0x001e6868 data EHUnwindMapEntry[1] CActSequence__PrepareTitle_unwindmap_UNUSED +0x001e6870 data EHFuncInfo CActSequence__PrepareTitle_funcinfo_UNUSED +0x001e688c data EHUnwindMapEntry[1] CActSequence__StartFullRoboyMenu_unwindmap_UNUSED +0x001e6894 data EHFuncInfo CActSequence__StartFullRoboyMenu_funcinfo_UNUSED +0x001e68b0 data EHUnwindMapEntry[1] CActSequence__PrepareStoryOrVsMission_unwindmap_UNUSED +0x001e68b8 data EHFuncInfo CActSequence__PrepareStoryOrVsMission_funcinfo_UNUSD +0x001e68d4 data EHUnwindMapEntry[1] CActSequence__PrepareTutorial_unwindmap_UNUSED +0x001e68dc data EHFuncInfo CActSequence__PrepareTutorial_funcinfo_UNUSED +0x001e68f8 data EHUnwindMapEntry[1] CActSequence__PrepareTestRun__unwindmap_UNUSED +0x001e6900 data EHFuncInfo CActSequence__PrepareTestRun_funcinfo_UNUSED +0x001e691c data EHUnwindMapEntry[1] CActSequence__PrepareUnused_unwindmap_UNUSED +0x001e6924 data EHFuncInfo CActSequence__PrepareUnused_funcinfo_UNUSED +0x001e6940 data EHUnwindMapEntry[1] CActSequence__PrepareGraffitiMenu_unwindmap_UNUSED +0x001e6948 data EHFuncInfo CActSequence__PrepareGraffitiMenu_funcinfo_UNUSED +0x001e6964 data EHUnwindMapEntry[1] CActSequence__WaitLoadVsMenu_unwindmap_UNUSED +0x001e696c data EHFuncInfo CActSequence__WaitLoadVsMenu_funcinfo_UNUSED +0x001e6988 data EHUnwindMapEntry[1] CActSequence__WaitLoadEnding_unwindmap_UNUSED +0x001e6990 data EHFuncInfo CActSequence__WaitLoadEnding_funcinfo_UNUSED +0x001e69ac data EHUnwindMapEntry CActSequence__PrepareStinger_unwindmap +0x001e69b4 data EHFuncInfo CActSequence__PrepareStinger_funcinfo 0x001eb760 data voidFunc * __xri_a 0x001eb76c data voidFunc * __xri_z 0x001eb770 data voidFunc * __xc_a @@ -1241,7 +1278,7 @@ 0x001efdc8 data uint[40] g_defaultSpawnedSouls 0x001efe68 data uint[4][5] g_defaultSelectedTags 0x001efeb8 data char *[61] g_unusedDebugStrings -0x001effb0 data CSaveData g_gameData +0x001effb0 data CSaveData g_SaveData 0x001f8b30 data float someJaTextParameter 0x001f8b58 data float someSpaceTextParameter 0x001f8c38 data int[286] g_soullIdToStageIndex @@ -1274,7 +1311,7 @@ 0x0020cc48 data Timer g_timer 0x0020cc58 data UnknownStatic27 g_unknownStatic27 0x0020cf40 data char *[27] keyStrings -0x0020d2b8 data pointer *[64] CActSequence::switcherFuncs +0x0020d2b8 data ActSequenceFunc *[64] CActSequence::fSequenceMethods 0x0020d498 data D3DCOLOR[6] g_logoBgColours 0x0020d4b0 data undefined segaLogoBuf_ja 0x0020d510 data undefined segaLogoBuf_en