From 20fecdd5fb6c2ac9dabb2af8accf692dd32d0ab6 Mon Sep 17 00:00:00 2001 From: KeybadeBlox Date: Sat, 2 May 2026 20:34:05 -0400 Subject: [PATCH] Fixes for delinking Fixes delink failures in Action.obj and ActSequence.obj. Some missing data types have been added to each corresponding header file, and entries have been added to the symbol table to fix errors from undefined types. The mangling script has also been amended to handle method pointers as they're currently imported into Ghidra (which are missing the calling convention, and likely behind a typedef). --- decompile/objdiff.json | 4 +-- decompile/src/JSRF/ActSequence.hpp | 5 +++ decompile/src/JSRF/Action.hpp | 46 ++++++++++++++++++++++++++ ghidra/ghidra_scripts/MSVC7Mangle.java | 12 +++++-- ghidra/make_header.sh | 2 +- ghidra/symboltable.tsv | 13 ++++++-- 6 files changed, 74 insertions(+), 8 deletions(-) diff --git a/decompile/objdiff.json b/decompile/objdiff.json index 8000d87..6fa5909 100644 --- a/decompile/objdiff.json +++ b/decompile/objdiff.json @@ -29,8 +29,8 @@ "source_path": "src/JSRF/ActSequence.cpp" }, "symbol_mappings": { - "?Exec0Default__jumptable@CActSequence@@3EA": "$L1709", - "?Exec0Default__jumptargets@CActSequence@@3PAPAXA": "$L1710" + "?Exec0Default__jumptable@CActSequence@@3EA": "$L1775", + "?Exec0Default__jumptargets@CActSequence@@3PAPAXA": "$L1776" } }, { diff --git a/decompile/src/JSRF/ActSequence.hpp b/decompile/src/JSRF/ActSequence.hpp index 10d4c66..df84ec3 100644 --- a/decompile/src/JSRF/ActSequence.hpp +++ b/decompile/src/JSRF/ActSequence.hpp @@ -86,5 +86,10 @@ struct CActSequence : CActBase { void ReturnFromStinger(); }; +// Signature of methods in fSequenceMethods array, minus namespace +// Not to be used in the decompilation, but for Ghidra to parse in jsrf.h +// (we should work out a way to communicate to Ghidra that this is __thiscall) +typedef void ActSequenceMethod(); + #endif diff --git a/decompile/src/JSRF/Action.hpp b/decompile/src/JSRF/Action.hpp index 38050a5..3d90142 100644 --- a/decompile/src/JSRF/Action.hpp +++ b/decompile/src/JSRF/Action.hpp @@ -60,6 +60,10 @@ struct UnknownStatic13 { void * unknown2; void * unknown3; }; +struct UnknownStatic15 { + UnknownStatic15(); + virtual ~UnknownStatic15(); +}; struct UnknownStatic16 { UnknownStatic16(); virtual ~UnknownStatic16(); @@ -198,6 +202,48 @@ enum eGRAPHICSSETTINGTYPE { eGRAPHICSSETTINGTYPE_OWARI = 0x5d, eGRAPHICSSETTINGTYPE_COUNT = 0x5e, }; +#pragma pack(4) +struct CTimer { + unsigned unknown; + LARGE_INTEGER m_Frequency; + + CTimer(); + virtual ~CTimer(); +}; +enum eFILETYPE { + eFILETYPE_MISSIONBIN, + eFILETYPE_CURRENT_PLAYER, + eFILETYPE_PLAYER, + eFILETYPE_STAGE1, + eFILETYPE_STAGE2, + eFILETYPE_ENEMY, + eFILETYPE_STAGEOBJ, + eFILETYPE_CAROBJ, + eFILETYPE_TALKEVENT, + eFILETYPE_EVENT, + eFILETYPE_SPRNORM, + eFILETYPE_MISC, + eFILETYPE_PEOPLE, + eFILETYPE_CHARICON, + eFILETYPE_EFFECT, + eFILETYPE_MAP, + eFILETYPE_CURRENT_CHARICON_MAYBE, + eFILETYPE_MARKFONTORDEFAULT, + eFILETYPE_GARAGE, + eFILETYPE_MARK, + eFILETYPE_TITLE, + eFILETYPE_ENDING, + eFILETYPE_LOGO, + eFILETYPE_PROGRESS, + eFILETYPE_MARKTEX, + eFILETYPE_MARKPRESSORTEX, + eFILETYPE_MARKDEFAULT, + eFILETYPE_MISSIONDAT, + eFILETYPE_CACHETABLEENTRY, + eFILETYPE_CACHE, + eFILETYPE_DMCACHE, + eFILETYPE_NUM +}; enum eACTFLAG { diff --git a/ghidra/ghidra_scripts/MSVC7Mangle.java b/ghidra/ghidra_scripts/MSVC7Mangle.java index a7dba56..119601f 100644 --- a/ghidra/ghidra_scripts/MSVC7Mangle.java +++ b/ghidra/ghidra_scripts/MSVC7Mangle.java @@ -432,7 +432,12 @@ public class MSVC7Mangle extends GhidraScript { case DoubleDataType x -> "N"; case LongDoubleDataType x -> "O"; case Pointer p -> "P" + - (p.getDataType() instanceof FunctionSignature f ? ( + (( + p.getDataType() instanceof FunctionSignature || ( + p.getDataType () instanceof TypeDef d && + d.getBaseDataType() instanceof FunctionSignature + ) + ) ? ( classNamespace.isPresent() ? "8" : "6" ) : "A" ) + mangleType(p.getDataType(), classNamespace, dict, loc); @@ -519,7 +524,10 @@ public class MSVC7Mangle extends GhidraScript { List args = Arrays.stream(f.getArguments()) .map(ParameterDefinition::getDataType) .toList(); - args = args.subList(isMethodPtr ? 1 : 0, args.size()); + if ( + isMethodPtr && + f.getCallingConventionName().equals("__thiscall") + ) args = args.subList(1, args.size()); final ArrayList argDict = new ArrayList<>(); diff --git a/ghidra/make_header.sh b/ghidra/make_header.sh index d0a3050..6535c77 100755 --- a/ghidra/make_header.sh +++ b/ghidra/make_header.sh @@ -1,5 +1,5 @@ #!/bin/sh -eu -# Merges all header files in the decompilation into a C header file called +# Merges all header files in the decompilation into a C header file called # jsrf.h for importing into Ghidra # Create output file diff --git a/ghidra/symboltable.tsv b/ghidra/symboltable.tsv index 8463e2e..a325cac 100644 --- a/ghidra/symboltable.tsv +++ b/ghidra/symboltable.tsv @@ -341,6 +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 +0x000470c0 func BOOL __cdecl notinline nofixup somethingWithSaveData_MAYBE void * 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 @@ -362,6 +363,7 @@ 0x0004ca20 func void __thiscall notinline nofixup Mission::setPauseOptions Call_SetPauseOptions * args 0x0004d5f0 func undefined __stdcall notinline nofixup populateSomeCharIdArray ePLAYERCHARID * buf 0x0004d880 func void __thiscall notinline nofixup Mission::setManyPlayerStateFieldsToOne +0x0004daa0 func void __thiscall notinline nofixup UnknownStatic15::FreeResources_MAYBE 0x0004db30 func void default notinline nofixup resolveMissionBinPtrs MissionBin * mssn 0x0004e930 func void __stdcall notinline nofixup MissionCreate uint chapter uint idDigits34 BOOL alwaysFalse 0x0004eac0 func undefined unknown notinline nofixup getSmthFromInactiveMssnStg undefined4 param_1 @@ -472,6 +474,7 @@ 0x0006ec80 func void __thiscall notinline nofixup UnknownObj_0x12B0::drawDefault 0x0006f100 func void __thiscall notinline nofixup UnknownObj_0x12B0::setMessage char * msg undefined4 param_2 undefined4 param_3 int controllerThatCanDismiss_MAYBE 0x0006f190 func BOOL default notinline nofixup allocated0x12b0 +0x0006f1b0 func BOOL __cdecl notinline nofixup somethingWithSaveLoadErr 0x0006f200 func UnknownObj_0x12B0 * __thiscall notinline nofixup UnknownObj_0x12B0::UnknownAllocated_0x12B0 CActBase * parent eACTID index eACTFLAG flags char * message int param_5 uint otherFlags undefined4 controllerThatCanDismiss 0x0006f380 func UnknownObj_0x12B0 * __thiscall notinline nofixup UnknownObj_0x12B0::ll`scalar_deleting_destructor' byte param_1 0x0006f3a0 func void __thiscall notinline nofixup UnknownObj_0x12B0::execDefault @@ -488,6 +491,7 @@ 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 +0x00070e30 func CDrawBase * __thiscall notinline nofixup AlsoRoboyMenuFull_MAYBE CActBase * param_1 eACTID param_2 eACTFLAG param_3 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 @@ -648,6 +652,7 @@ 0x00127e60 func void __thiscall notinline nofixup UnknownObj_0x1DE4::~UnknownAllocated_0x1DE4 0x00128fd0 func UnknownObj_0x1DE4 * __thiscall notinline nofixup UnknownObj_0x1DE4::UnknownAllocated_0x1DE4 CActBase * param_1 eACTID param_2 uint param_3 0x00129160 func UnknownObj_0x1DE4 * __thiscall notinline nofixup UnknownObj_0x1DE4::`scalar_deleting_destructor' uint param_1 +0x00137570 func CActBase * __thiscall notinline nofixup VsMenu_MAYBE CActBase * param_1 eACTID param_2 uint param_3 0x0013a6b0 func void default notinline nofixup CRI::ADXT_Stop ADXT adxt 0x0013a980 func undefined __stdcall notinline nofixup CRI::ADXT_SetOutVol ADXT adxt Sint32 vol 0x0013a9a0 func Sint32 default notinline nofixup CRI::ADXT_GetNumSmplObuf ADXT adxt Sint32 chno @@ -1144,6 +1149,7 @@ 0x001ca7d8 data undefined * EventChild1Child::vtable 0x001caa8c data ProgressVtbl Progress::`vftable' 0x001caab0 data CActBaseVtbl Mission::`vftable' +0x001caaf0 data UnknownStatic15Vtbl UnknownStatic15::`vftable' 0x001caaf8 data CActBaseVtbl CMissionManager::`vftable' 0x001cab98 data undefined * CharacterSelect::vtable 0x001caf70 data pointer CMusashi::vtable @@ -1162,7 +1168,7 @@ 0x001cc5d0 data undefined * UnknownObj_0x1DDE::vtable 0x001cc618 data pointer UnknownStatic24::vtable 0x001cc61c data pointer UnknownStatic25::vtable -0x001cc620 data pointer Timer::vtable +0x001cc620 data CTimerVtbl Timer::vtable 0x001cc660 data undefined * UnknownObj_0x12B0::vtable 0x001cc6a0 data pointer UnknownStatic27::vtable 0x001ccd18 data CActBaseVtbl UnknownObj_0x1167_2::`vftable' @@ -1291,6 +1297,7 @@ 0x001f9a68 data SwitcherMethod *[119] Mission::exec_5Funcs 0x001f9c48 data SwitcherMethod *[119] Mission::exec_3Funcs 0x001f9e28 data SwitcherMethod *[119] Mission::exec_2Funcs +0x001fa05c data UnknownStatic15 g_unknownStatic15 0x001fa0e0 data uint[13][4] g_profKModeSettings 0x001fa1cc data BOOL g_lighting 0x001fa1d0 data BOOL g_alphaBlendEnabled @@ -1308,10 +1315,10 @@ 0x001fc724 data Language g_language 0x0020c6c0 data UnknownStatic22 g_unknownStatic22 0x0020c750 data UnknownGlobal g_unknownGlobal -0x0020cc48 data Timer g_timer +0x0020cc48 data CTimer g_timer 0x0020cc58 data UnknownStatic27 g_unknownStatic27 0x0020cf40 data char *[27] keyStrings -0x0020d2b8 data ActSequenceFunc *[64] CActSequence::fSequenceMethods +0x0020d2b8 data ActSequenceMethod *[64] CActSequence::fSequenceMethods 0x0020d498 data D3DCOLOR[6] g_logoBgColours 0x0020d4b0 data undefined segaLogoBuf_ja 0x0020d510 data undefined segaLogoBuf_en