Compare commits

..

No commits in common. "022582003d13c5f08a123a2ab7395720f760b7b8" and "05b4da2f786301ee4e03d574a4e11f9e67bce7d4" have entirely different histories.

6 changed files with 221 additions and 107 deletions

View file

@ -3,7 +3,7 @@ all: src/JSRF/Jet2.obj
# Simple inference rule for producing object files # Simple inference rule for producing object files
.SUFFIXES: .cpp .obj .SUFFIXES: .cpp .obj
.cpp.obj: .cpp.obj:
CL.EXE /nologo /Wall /W4 /Ogityb0 /GfX /Fo$@ /c $< CL.EXE /nologo /Wall /TP /W3 /Ogityb0 /MT /Gf /GX /Fo$@ /c $<
# Header files used for each object # Header files used for each object
src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/Std.hpp src/XDK/D3D.hpp\ src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/Std.hpp src/XDK/D3D.hpp\

View file

@ -14,11 +14,11 @@
"source_path": "src/JSRF/Jet2.cpp" "source_path": "src/JSRF/Jet2.cpp"
}, },
"symbol_mappings": { "symbol_mappings": {
"?main_funcinfo@@3UFuncInfo@@A": "$T754", "[.rdata-0]": "[.xdata$x-0]",
"?main_handler@@YAXPAUEHExceptionRecord@@PAKPAXPAU_xDISPATCHER_CONTEXT@@@Z": "$L758", "_main_funcinfo": "$T754",
"?main_handler_unwind1@@YAXXZ": "$L750", "_main_handler": "$L758",
"?main_unwindmap@@3PAUUnwindMapEntry@@A": "$T760", "_main_handler_unwind1": "$L750",
"[.rdata-0]": "[.xdata$x-0]" "_main_unwindmap": "$T760"
} }
}, },
{ {
@ -28,6 +28,94 @@
"metadata": { "metadata": {
"complete": false, "complete": false,
"source_path": "src/JSRF/Core.cpp" "source_path": "src/JSRF/Core.cpp"
},
"symbol_mappings": {
"DrawTree::DrawTree": "??0DrawTree@@QAE@PAUGameObj@@W4GameObjIndex@@W4GameObjFlags@@@Z",
"DrawTree::`scalar_deleting_destructor'": "??_GDrawTree@@UAEPAXI@Z",
"DrawTree::copySomeVectors": "?copySomeVectors@DrawTree@@QAEXXZ",
"DrawTree::~DrawTree": "??1DrawTree@@UAE@XZ",
"Game::Game": "??0Game@@QAE@PAII@Z",
"Game::`scalar_deleting_destructor'": "??_GGame@@UAEPAXI@Z",
"Game::addToDrawList": "?addToDrawList@Game@@QAEXPAUGameObj@@@Z",
"Game::allocObjIndex": "?allocObjIndex@Game@@QAEHW4GameObjIndex@@0@Z",
"Game::appendToDrawPriorityList": "?appendToDrawPriorityList@Game@@QAEXPAUGameObj@@@Z",
"Game::clearDrawPriorityList": "?clearDrawPriorityList@Game@@QAEXXZ",
"Game::clearScreen": "?clearScreen@Game@@QAEXXZ",
"Game::draw": "?draw@Game@@QAEXXZ",
"Game::drawList": "?drawList@Game@@QAEXW4GameObjFlags@@H@Z",
"Game::drawList_": "?drawList_@Game@@QAEXW4GameObjFlags@@HH0I00@Z",
"Game::drawObj": "?drawObj@Game@@QAEXPAUGameObj@@H@Z",
"Game::drawObjs": "?drawObjs@Game@@QAEXXZ",
"Game::drawTree1": "?drawTree1@Game@@QAEXPAUGameObj@@@Z",
"Game::enableDrawChildren": "?enableDrawChildren@Game@@QAEXXZ",
"Game::enableSkipDraw": "?enableSkipDraw@Game@@QAEXXZ",
"Game::enableSomeExtraDrawListCode": "?enableSomeExtraDrawListCode@Game@@QAEXXZ",
"Game::exec": "?exec@Game@@QAEXXZ",
"Game::fatal": "?fatal@Game@@QAEXXZ",
"Game::frame": "?frame@Game@@QAEXXZ",
"Game::getDrawPriorityListHead": "?getDrawPriorityListHead@Game@@QAEPAUGameObj@@XZ",
"Game::getGlobal": "?getGlobal@Game@@QAEIW4GlobalIndex@@@Z",
"Game::getObj": "?getObj@Game@@QAEPAUGameObj@@W4GameObjIndex@@@Z",
"Game::initRootExecObj": "?initRootExecObj@Game@@QAEXXZ",
"Game::mainLoop": "?mainLoop@Game@@QAEHXZ",
"Game::objIndexAvail": "?objIndexAvail@Game@@QAEHW4GameObjIndex@@@Z",
"Game::removeFromDrawList": "?removeFromDrawList@Game@@QAEXPAUGameObj@@@Z",
"Game::setCoveredPauseNextFrame": "?setCoveredPauseNextFrame@Game@@QAEXH@Z",
"Game::setDrawMode": "?setDrawMode@Game@@QAEXW4DrawMode@@@Z",
"Game::setEventNextFrame": "?setEventNextFrame@Game@@QAEXH@Z",
"Game::setFallbackBgColour": "?setFallbackBgColour@Game@@QAEXKH@Z",
"Game::setFreezeCamNextFrame": "?setFreezeCamNextFrame@Game@@QAEXH@Z",
"Game::setGlobal": "?setGlobal@Game@@QAEXW4GlobalIndex@@I@Z",
"Game::setLogosStarted": "?setLogosStarted@Game@@QAEXH@Z",
"Game::setObj": "?setObj@Game@@QAEXW4GameObjIndex@@PAUGameObj@@@Z",
"Game::setUncoveredPauseNextFrame": "?setUncoveredPauseNextFrame@Game@@QAEXH@Z",
"Game::sortDrawPriorityList": "?sortDrawPriorityList@Game@@QAEXXZ",
"Game::sortDrawPriorityListSingleLevel": "?sortDrawPriorityListSingleLevel@Game@@QAEXD@Z",
"Game::swapObjs": "?swapObjs@Game@@QAEXW4GameObjIndex@@0@Z",
"Game::unsetObj": "?unsetObj@Game@@QAEXW4GameObjIndex@@@Z",
"Game::~Game": "??1Game@@UAE@XZ",
"GameObj::GameObj": "??0GameObj@@QAE@PAU0@W4GameObjIndex@@W4GameObjFlags@@@Z",
"GameObj::`scalar_deleting_destructor'": "??_GGameObj@@UAEPAXI@Z",
"GameObj::`vftable'": "??_7GameObj@@6B@",
"GameObj::addToSiblings": "?addToSiblings@GameObj@@QAEXPAU1@0@Z",
"GameObj::destructChildren": "?destructChildren@GameObj@@QAEXPAU1@@Z",
"GameObj::drawListCoveredPause": "?drawListCoveredPause@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z",
"GameObj::drawListDefault": "?drawListDefault@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z",
"GameObj::drawListEvent": "?drawListEvent@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z",
"GameObj::drawListFreezeCam": "?drawListFreezeCam@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z",
"GameObj::drawListUncoveredPause": "?drawListUncoveredPause@GameObj@@QAEXW4GameObjFlags@@HH0I00@Z",
"GameObj::drawTreeCoveredPause1": "?drawTreeCoveredPause1@GameObj@@QAEXXZ",
"GameObj::drawTreeCoveredPause2": "?drawTreeCoveredPause2@GameObj@@QAEXXZ",
"GameObj::drawTreeDefault1": "?drawTreeDefault1@GameObj@@QAEXXZ",
"GameObj::drawTreeDefault2": "?drawTreeDefault2@GameObj@@QAEXXZ",
"GameObj::drawTreeEvent1": "?drawTreeEvent1@GameObj@@QAEXXZ",
"GameObj::drawTreeEvent2": "?drawTreeEvent2@GameObj@@QAEXXZ",
"GameObj::drawTreeFreezeCam1": "?drawTreeFreezeCam1@GameObj@@QAEXXZ",
"GameObj::drawTreeFreezeCam2": "?drawTreeFreezeCam2@GameObj@@QAEXXZ",
"GameObj::drawTreeUncoveredPause1": "?drawTreeUncoveredPause1@GameObj@@QAEXXZ",
"GameObj::drawTreeUncoveredPause2": "?drawTreeUncoveredPause2@GameObj@@QAEXXZ",
"GameObj::getParent": "?getParent@GameObj@@QAEPAU1@XZ",
"GameObj::nopDraw": "?drawDefault@GameObj@@UAEXH@Z",
"GameObj::nopExec": "?execDefault@GameObj@@UAEXXZ",
"GameObj::recursiveExecCoveredPause": "?recursiveExecCoveredPause@GameObj@@QAEXXZ",
"GameObj::recursiveExecDefault": "?recursiveExecDefault@GameObj@@QAEXXZ",
"GameObj::recursiveExecEvent": "?recursiveExecEvent@GameObj@@QAEXXZ",
"GameObj::recursiveExecFreezeCam": "?recursiveExecFreezeCam@GameObj@@QAEXXZ",
"GameObj::recursiveExecUncoveredPause": "?recursiveExecUncoveredPause@GameObj@@QAEXXZ",
"GameObj::recursivePostExecCoveredPause": "?recursivePostExecCoveredPause@GameObj@@QAEXXZ",
"GameObj::recursivePostExecDefault": "?recursivePostExecDefault@GameObj@@QAEXXZ",
"GameObj::recursivePostExecEvent": "?recursivePostExecEvent@GameObj@@QAEXXZ",
"GameObj::recursivePostExecFreezeCam": "?recursivePostExecFreezeCam@GameObj@@QAEXXZ",
"GameObj::recursivePostExecUncoveredPause": "?recursivePostExecUncoveredPause@GameObj@@QAEXXZ",
"GameObj::removeChildrenFromObjList": "?removeChildrenFromObjList@GameObj@@QAEXPAU1@@Z",
"GameObj::removeFromObjList": "?removeFromObjList@GameObj@@QAEXPAU1@@Z",
"GameObj::setParent": "?setParent@GameObj@@QAEXPAU1@@Z",
"GameObj::~GameObj": "??1GameObj@@UAE@XZ",
"PlayerObj::PlayerObj": "??0PlayerObj@@QAE@PAUGameObj@@W4GameObjIndex@@W4GameObjFlags@@@Z",
"RootExecObj::RootExecObj": "??0RootExecObj@@QAE@PAUGameObj@@W4GameObjIndex@@W4GameObjFlags@@@Z",
"RootExecObj::`scalar_deleting_destructor'": "??_GRootExecObj@@UAEPAXI@Z",
"RootExecObj::~RootExecObj": "??1RootExecObj@@UAE@XZ",
"removeFromObjListByIndex": "?removeFromObjListByIndex@@YAXW4GameObjIndex@@@Z"
} }
}, },
{ {
@ -39,9 +127,75 @@
"source_path": "src/JSRF/GameData.cpp" "source_path": "src/JSRF/GameData.cpp"
}, },
"symbol_mappings": { "symbol_mappings": {
"?finalizeGameData@@YAXXZ": "_$E2", "GameData::GameData": "??0GameData@@QAE@XZ",
"?initGameData@@YGXXZ": "_$E1" "GameData::`scalar_deleting_destructor'": "??_GGameData@@UAEPAXI@Z",
"GameData::addHighScore": "?addHighScore@GameData@@QAEXIW4TestRunType@@PAUTestRunScore@@@Z",
"GameData::characterUnlocked": "?characterUnlocked@GameData@@QAEHI@Z",
"GameData::checkFlagCondition": "?checkFlagCondition@GameData@@QAEHI@Z",
"GameData::checkFlagConditionUnpacked": "?checkFlagConditionUnpacked@GameData@@QAEHW4FlagList@@I@Z",
"GameData::checkFlagConditions": "?checkFlagConditions@GameData@@QAEHPAII@Z",
"GameData::clearHeldSouls": "?clearHeldSouls@GameData@@QAEXXZ",
"GameData::clearStateFlags": "?clearStateFlags@GameData@@QAEXTFlagListOrPtr@@@Z",
"GameData::countMiscObjectives": "?countMiscObjectives@GameData@@QAEIXZ",
"GameData::decrypt": "?decrypt@GameData@@QAEHPAD@Z",
"GameData::encrypt": "?encrypt@GameData@@QAEXPAD@Z",
"GameData::eventSeen": "?eventSeen@GameData@@QAEHI@Z",
"GameData::getCustomTagSelected": "?getCustomTagSelected@GameData@@QAEHIW4TagSize@@H@Z",
"GameData::getGarageMusic": "?getGarageMusic@GameData@@QAEIXZ",
"GameData::getHeldSoulsInStage": "?getHeldSoulsInStage@GameData@@QAEII@Z",
"GameData::getHighScore": "?getHighScore@GameData@@QAEHIW4TestRunType@@IPAUTestRunScore@@@Z",
"GameData::getMiscObjective": "?getMiscObjective@GameData@@QAEHI@Z",
"GameData::getRumbleEnabled": "?getRumbleEnabled@GameData@@QAEHXZ",
"GameData::getSaveDataSize": "?getSaveDataSize@GameData@@QAEIXZ",
"GameData::getSaveDescription": "?getSaveDescription@GameData@@QAEXPAUSaveDescription@@@Z",
"GameData::getSelectedTag": "?getSelectedTag@GameData@@QAEIIW4TagSize@@H@Z",
"GameData::getSoulCollectedBySize": "?getSoulCollectedBySize@GameData@@QAEHW4TagSize@@I@Z",
"GameData::getSoulCount": "?getSoulCount@GameData@@QAEIXZ",
"GameData::getSoulHeld": "?getSoulHeld@GameData@@QAEHI@Z",
"GameData::getSoulSpawned": "?getSoulSpawned@GameData@@QAEHI@Z",
"GameData::getSpawnPosIndex": "?getSpawnPosIndex@GameData@@QAEIXZ",
"GameData::getTagState": "?getTagState@GameData@@QAEHIIH@Z",
"GameData::getTimer": "?getTimer@GameData@@QAEIW4Timer@@@Z",
"GameData::getTotalSoulsInStage": "?getTotalSoulsInStage@GameData@@QAEII@Z",
"GameData::getVolumeSettings": "?getVolumeSettings@GameData@@QAEXPAM0@Z",
"GameData::incrementChapter": "?incrementChapter@GameData@@QAEXXZ",
"GameData::incrementPlaytime": "?incrementPlaytime@GameData@@QAEXXZ",
"GameData::incrementTimer": "?incrementTimer@GameData@@QAEXW4Timer@@@Z",
"GameData::lockCharacter": "?lockCharacter@GameData@@QAEXI@Z",
"GameData::resetExceptSettings": "?resetExceptSettings@GameData@@QAEXXZ",
"GameData::resetExceptSettingsAndHighScores": "?resetExceptSettingsAndHighScores@GameData@@QAEXXZ",
"GameData::resetExceptSettingsAndSouls": "?resetExceptSettingsAndSouls@GameData@@QAEXXZ",
"GameData::resetSelectedTags": "?resetSelectedTags@GameData@@QAEXXZ",
"GameData::resetTimer": "?resetTimer@GameData@@QAEXW4Timer@@@Z",
"GameData::restoreHeldSouls": "?restoreHeldSouls@GameData@@QAEXXZ",
"GameData::setCustomTagSelected": "?setCustomTagSelected@GameData@@QAEXIW4TagSize@@HH@Z",
"GameData::setEventSeen": "?setEventSeen@GameData@@QAEXI@Z",
"GameData::setGarageMusic": "?setGarageMusic@GameData@@QAEXI@Z",
"GameData::setMiscObjective": "?setMiscObjective@GameData@@QAEXI@Z",
"GameData::setMissionDigits34": "?setMissionDigits34@GameData@@QAEXI@Z",
"GameData::setRumbleEnabled": "?setRumbleEnabled@GameData@@QAEXH@Z",
"GameData::setSelectedTag": "?setSelectedTag@GameData@@QAEXIW4TagSize@@IH@Z",
"GameData::setSoulCollected": "?setSoulCollected@GameData@@QAEXI@Z",
"GameData::setSoulSpawned": "?setSoulSpawned@GameData@@QAEXI@Z",
"GameData::setSpawnPosIndex": "?setSpawnPosIndex@GameData@@QAEXI@Z",
"GameData::setTagCovered": "?setTagCovered@GameData@@QAEXIIHI@Z",
"GameData::setTagState": "?setTagState@GameData@@QAEXIIHI@Z",
"GameData::setTimer": "?setTimer@GameData@@QAEXW4Timer@@I@Z",
"GameData::setUnusedBitfield": "?setUnusedBitfield@GameData@@QAEXI@Z",
"GameData::setUnusedPerStageBitmask": "?setUnusedPerStageBitmask@GameData@@QAEXII@Z",
"GameData::setVolumeSettings": "?setVolumeSettings@GameData@@QAEXMM@Z",
"GameData::soulSpawnedUncollected": "?soulSpawnedUncollected@GameData@@QAEHI@Z",
"GameData::stash": "?stash@GameData@@QAEXXZ",
"GameData::stashRestore": "?stashRestore@GameData@@QAEXXZ",
"GameData::stashRestoreExceptHighScores": "?stashRestoreExceptHighScores@GameData@@QAEXXZ",
"GameData::stashRestoreExceptSpecialFlags": "?stashRestoreExceptSpecialFlags@GameData@@QAEXXZ",
"GameData::unlockCharacter": "?unlockCharacter@GameData@@QAEXI@Z",
"GameData::writeStateFlag": "?writeStateFlag@GameData@@QAEXI@Z",
"GameData::writeStateFlagUnpacked": "?writeStateFlagUnpacked@GameData@@QAEXW4FlagList@@II@Z",
"GameData::writeStateFlags": "?writeStateFlags@GameData@@QAEXPAII@Z",
"finalizeGameData": "_$E2",
"initGameData": "_$E1"
} }
} }
] ]
} }

View file

@ -196,7 +196,7 @@ void GameObj::removeChildrenFromObjList(GameObj * firstChild) {
// Address: 0x00011C80 // Address: 0x00011C80
// Matching: yes // Matching: yes
void GameObj::drawDefault(unsigned unknown) {} void GameObj::drawDefault(int unknown) {}
// Address: 0x00011C90 // Address: 0x00011C90
// Matching: yes // Matching: yes
@ -212,7 +212,7 @@ void GameObj::execEvent() {}
void GameObj::postExecEvent() {} void GameObj::postExecEvent() {}
// Eliminated by link time code generation (aliased with 0x00011C80) // Eliminated by link time code generation (aliased with 0x00011C80)
void GameObj::drawEvent(unsigned unknown) {} void GameObj::drawEvent(int unknown) {}
// Eliminated by link time code generation (aliased with 0x00011C90) // Eliminated by link time code generation (aliased with 0x00011C90)
void GameObj::execCoveredPause() {} void GameObj::execCoveredPause() {}
@ -221,7 +221,7 @@ void GameObj::execCoveredPause() {}
void GameObj::postExecCoveredPause() {} void GameObj::postExecCoveredPause() {}
// Eliminated by link time code generation (aliased with 0x00011C80) // Eliminated by link time code generation (aliased with 0x00011C80)
void GameObj::drawCoveredPause(unsigned unknown) {} void GameObj::drawCoveredPause(int unknown) {}
// Eliminated by link time code generation (aliased with 0x00011C90) // Eliminated by link time code generation (aliased with 0x00011C90)
void GameObj::execFreezeCam() {} void GameObj::execFreezeCam() {}
@ -230,7 +230,7 @@ void GameObj::execFreezeCam() {}
void GameObj::postExecFreezeCam() {} void GameObj::postExecFreezeCam() {}
// Eliminated by link time code generation (aliased with 0x00011C80) // Eliminated by link time code generation (aliased with 0x00011C80)
void GameObj::drawFreezeCam(unsigned unknown) {} void GameObj::drawFreezeCam(int unknown) {}
// Eliminated by link time code generation (aliased with 0x00011C90) // Eliminated by link time code generation (aliased with 0x00011C90)
void GameObj::execUncoveredPause() {} void GameObj::execUncoveredPause() {}
@ -239,7 +239,7 @@ void GameObj::execUncoveredPause() {}
void GameObj::postExecUncoveredPause() {} void GameObj::postExecUncoveredPause() {}
// Eliminated by link time code generation (aliased with 0x00011C80) // Eliminated by link time code generation (aliased with 0x00011C80)
void GameObj::drawUncoveredPause(unsigned unknown) {} void GameObj::drawUncoveredPause(int unknown) {}
// Address: 0x00011CA0 // Address: 0x00011CA0
// Matching: no // Matching: no
@ -336,7 +336,7 @@ void Game::exec() {
// Address: 0x00012580 // Address: 0x00012580
// Matching: no // Matching: no
void Game::drawObj(GameObj * obj, unsigned unknown) { void Game::drawObj(GameObj * obj, int unknown) {
} }
// Address: 0x000125E0 // Address: 0x000125E0
@ -510,7 +510,7 @@ void Game::appendToDrawPriorityList(GameObj * obj) {
// Address: 0x00012A20 // Address: 0x00012A20
// Matching: no // Matching: no
void Game::sortDrawPriorityListSingleLevel(unsigned char sortKeyBitOffset) { void Game::sortDrawPriorityListSingleLevel(char sortKeyBitOffset) {
for ( for (
unsigned i = 0; unsigned i = 0;
i < sizeof this->drawPriorityListsByKeyHeads/sizeof *this->drawPriorityListsByKeyHeads; i < sizeof this->drawPriorityListsByKeyHeads/sizeof *this->drawPriorityListsByKeyHeads;

View file

@ -146,23 +146,23 @@ struct GameObj {
// frame. // frame.
virtual void execDefault(); virtual void execDefault();
virtual void postExecDefault(); virtual void postExecDefault();
virtual void drawDefault(unsigned); virtual void drawDefault(int);
virtual void execEvent(); virtual void execEvent();
virtual void postExecEvent(); virtual void postExecEvent();
virtual void drawEvent(unsigned); virtual void drawEvent(int);
virtual void execCoveredPause(); virtual void execCoveredPause();
virtual void postExecCoveredPause(); virtual void postExecCoveredPause();
virtual void drawCoveredPause(unsigned); virtual void drawCoveredPause(int);
virtual void execFreezeCam(); virtual void execFreezeCam();
virtual void postExecFreezeCam(); virtual void postExecFreezeCam();
virtual void drawFreezeCam(unsigned); virtual void drawFreezeCam(int);
virtual void execUncoveredPause(); virtual void execUncoveredPause();
virtual void postExecUncoveredPause(); virtual void postExecUncoveredPause();
virtual void drawUncoveredPause(unsigned); virtual void drawUncoveredPause(int);
void recursivePostExecDefault(); void recursivePostExecDefault();
void recursivePostExecEvent(); void recursivePostExecEvent();
@ -297,7 +297,7 @@ struct Game {
Game(unsigned *, unsigned); Game(unsigned *, unsigned);
virtual ~Game(); virtual ~Game();
void exec(); void exec();
void drawObj(GameObj * obj, unsigned); void drawObj(GameObj * obj, int);
void drawList_( void drawList_(
GameObjFlags flagFilterAny1, GameObjFlags flagFilterAny1,
int drawArg1, int drawArg1,
@ -339,7 +339,7 @@ struct Game {
void clearDrawPriorityList(); void clearDrawPriorityList();
GameObj * getDrawPriorityListHead(); GameObj * getDrawPriorityListHead();
void appendToDrawPriorityList(GameObj * obj); void appendToDrawPriorityList(GameObj * obj);
void sortDrawPriorityListSingleLevel(unsigned char sortKeyBitOffset); void sortDrawPriorityListSingleLevel(char sortKeyBitOffset);
void setFallbackBgColour(D3DCOLOR colour, BOOL useFallback); void setFallbackBgColour(D3DCOLOR colour, BOOL useFallback);
void initRootExecObj(); void initRootExecObj();

View file

@ -3,21 +3,11 @@
# objects.csv and a Ghidra project via boricj's delinker extension # objects.csv and a Ghidra project via boricj's delinker extension
main() { main() {
if \ if [ $# -ne 3 ]; then usage; fi
[ $# -eq 0 ] &&\
[ -n "${GHIDRA_HOME-}" ] &&\ ghidra_path=$1
[ -n "${JSRFDECOMP_PROJECTPATH-}" ] &&\ project_path=$2
[ -n "${JSRFDECOMP_PROJECTNAME-}" ] project_name=$3
then
ghidra_path=$GHIDRA_HOME
project_path=$JSRFDECOMP_PROJECTPATH
project_name=$JSRFDECOMP_PROJECTNAME
elif [ $# -eq 3 ]; then
ghidra_path=$1
project_path=$2
project_name=$3
else usage
fi
printf '=== Delinking object files into ../decompile/target/ ===\n' printf '=== Delinking object files into ../decompile/target/ ===\n'
@ -49,9 +39,6 @@ usage() {
' GHIDRA_PATH is the path to your Ghidra installation'\ ' GHIDRA_PATH is the path to your Ghidra installation'\
' PROJECT_PATH is the path to your JSRF Ghidra project'\ ' PROJECT_PATH is the path to your JSRF Ghidra project'\
' PROJECT_NAME is the name of your JSRF Ghidra project'\ ' PROJECT_NAME is the name of your JSRF Ghidra project'\
'Alternatively, the environment variables $GHIDRA_HOME, $JSRFDECOMP_PROJECTPATH,'\
'and $JSRFDECOMP_PROJECTNAME can be set, and the script can be called with no'\
'arguments.'\
''\ ''\
'Populates the target/ directory with delinked object files using the address'\ 'Populates the target/ directory with delinked object files using the address'\
'ranges given in objects.csv.' >& 2 'ranges given in objects.csv.' >& 2

View file

@ -107,10 +107,7 @@ public class MSVC7Mangle extends GhidraScript{
final Reference[] refs = ins.getReferencesFrom(); final Reference[] refs = ins.getReferencesFrom();
for (int i = 0; i < refs.length; i++) { for (int i = 0; i < refs.length; i++) {
final Symbol symbol = getSymbolAt(refs[i].getToAddress()); final Symbol symbol = getSymbolAt(refs[i].getToAddress());
if ( // Guard against spurious references to nonexisting things if (symbol != null) mangle(symbol);
symbol != null &&
symbol.getObject() != null
) mangle(symbol);
} }
} }
} }
@ -119,17 +116,13 @@ public class MSVC7Mangle extends GhidraScript{
private void mangle(final Symbol s) throws Exception { private void mangle(final Symbol s) throws Exception {
/* Set the given symbol's name to its mangled version */ /* Set the given symbol's name to its mangled version */
// Skip if already mangled; skip jump tables // Skip if already mangled
final String name = s.getName(true); if (s.getName().charAt(0) == '?') return;
if (
name.charAt(0) == '?' ||
name.startsWith("switchD_")
) return;
// Get mangled name // Get mangled name
final String mangled = switch (s.getObject()) { final String mangled = switch (s.getObject()) {
case Function f -> mangleFn (f); case Function f -> mangleFn (f);
case Data d -> mangleData(d, name); case Data d -> mangleData(d, s.getName(true));
default -> null; default -> null;
}; };
@ -152,21 +145,17 @@ public class MSVC7Mangle extends GhidraScript{
private String mangleFn(final Function f) throws Exception { private String mangleFn(final Function f) throws Exception {
/* Generate a mangled name for a function */ /* Generate a mangled name for a function */
final String nameRaw = f.getName(true); // Special cases for main()
if (f.getName(true).equals("main" )) return "_main";
// Special case for main() if (f.getName(true).equals("___CxxFrameHandler")) return "___CxxFrameHandler";
if (nameRaw.equals("main")) return "_main";
// Special symbols like intrinsics aren't mangled
if (nameRaw.startsWith("__")) return nameRaw;
final ArrayList<String> dict = new ArrayList<>(); final ArrayList<String> dict = new ArrayList<>();
final List<String> nameParts = Arrays.asList(nameRaw.split("::")); final List<String> nameParts = Arrays.asList(f.getName(true).split("::"));
Collections.reverse(nameParts); Collections.reverse(nameParts);
final boolean isMethod = f.getCallingConventionName().equals("__thiscall") && final boolean isMethod = f.getCallingConventionName().equals("__thiscall") &&
nameParts.size() >= 2; nameParts.size() >= 2;
final String name = mangleIdentifier(nameRaw, isMethod, f.getReturnType(), dict); final String name = mangleIdentifier(f.getName(true), isMethod, f.getReturnType(), dict);
// Special methods with unique formats // Special methods with unique formats
if (isMethod) { if (isMethod) {
@ -174,16 +163,14 @@ public class MSVC7Mangle extends GhidraScript{
final String clsName = nameParts.get(1); final String clsName = nameParts.get(1);
if (unqualified.equals( clsName)) { // Constructor if (unqualified.equals( clsName)) { // Constructor
return "?" + name + "QAE@" + return "?" + name + "QAE@" + mangleArgs(f.getSignature(true), dict) + "Z";
mangleArgs(f.getSignature(true), dict, nameRaw + "()") +
"Z";
} else if (unqualified.equals("~" + clsName)) { // Destructor } else if (unqualified.equals("~" + clsName)) { // Destructor
return "?" + name + (isVirtual(f) ? "UAE" : "QAE") + "@XZ"; return "?" + name + (isVirtual(f) ? "UAE" : "QAE") + "@XZ";
} }
} }
return "?" + name + mangleFnAttrs(f, nameParts) + return "?" + name + mangleFnAttrs(f, nameParts) +
mangleFnType(f.getSignature(true), dict, nameRaw + "()"); mangleFnType(f.getSignature(true), dict);
} }
private static String mangleIdentifier( private static String mangleIdentifier(
@ -285,9 +272,7 @@ public class MSVC7Mangle extends GhidraScript{
final List<T> dict final List<T> dict
) { ) {
/* Produce a backreference string if x is found in dict */ /* Produce a backreference string if x is found in dict */
if (x instanceof String s && s.startsWith("?")) switch (Integer.valueOf(dict.indexOf(x))) {
return Optional.empty(); // No matching special names
else switch (Integer.valueOf(dict.indexOf(x))) {
case -1: case -1:
dict.add(x); dict.add(x);
return Optional.empty(); return Optional.empty();
@ -318,15 +303,12 @@ public class MSVC7Mangle extends GhidraScript{
final Function func = getFunctionContaining(refs[i].getFromAddress()); final Function func = getFunctionContaining(refs[i].getFromAddress());
if (data != null) { if (data != null) {
final Symbol s = getSymbolAt(data.getRoot() final String name = getSymbolAt(data.getRoot()
.getAddress()); .getAddress()).getName(false);
if (s != null) { if (
final String name = s.getName(false); name.equals("`vftable'") ||
if ( name.startsWith("??_7")
name.equals("`vftable'") || ) return true;
name.startsWith("??_7")
) return true;
}
} else if (func != null) { } else if (func != null) {
final String name = func.getName(false); final String name = func.getName(false);
if ( if (
@ -352,13 +334,12 @@ public class MSVC7Mangle extends GhidraScript{
private static String mangleFnType( private static String mangleFnType(
final FunctionSignature f, final FunctionSignature f,
final List<String> dict, final List<String> dict
final String loc
) throws Exception { ) throws Exception {
/* Mangle everything in f but its name and visibility/linkage */ /* Mangle everything in f but its name and visibility/linkage */
return mangleCallC(f) +
mangleType(f.getReturnType(), dict, loc) + return mangleCallC(f) + mangleType(f.getReturnType(), dict) +
mangleArgs(f, dict, loc) + "Z"; mangleArgs(f, dict) + "Z";
} }
private static String mangleCallC(final FunctionSignature f) throws Exception { private static String mangleCallC(final FunctionSignature f) throws Exception {
@ -377,16 +358,15 @@ public class MSVC7Mangle extends GhidraScript{
private static String mangleType( private static String mangleType(
final DataType t, final DataType t,
final List<String> dict, final List<String> dict
final String loc
) throws Exception { ) throws Exception {
/* Mangle a data type in a function name /* Mangle a data type in a function name
All types are assumed to have no CV qualifiers. All types are assumed to have no CV qualifiers.
*/ */
if (t == null) throw new Exception ( if (t == null) throw new Exception (
"A data type at " + loc + " was reported as null. " + "A data type was reported as null. Ensure that all " +
"Ensure that all data types in the code/data to " + "data types in the code/data to mangle have been " +
"mangle have been defined." "defined."
); );
return switch(t) { return switch(t) {
@ -404,7 +384,7 @@ public class MSVC7Mangle extends GhidraScript{
case LongDoubleDataType _ -> "O"; case LongDoubleDataType _ -> "O";
case Pointer p -> "P" + case Pointer p -> "P" +
(p.getDataType() instanceof FunctionSignature ? "6" : "A") + (p.getDataType() instanceof FunctionSignature ? "6" : "A") +
mangleType(p.getDataType(), dict, loc); mangleType(p.getDataType(), dict);
case Union u -> "T" + mangleIdentifier(u.getName(), false, null, dict); case Union u -> "T" + mangleIdentifier(u.getName(), false, null, dict);
case Structure s -> "U" + mangleIdentifier(s.getName(), false, null, dict); case Structure s -> "U" + mangleIdentifier(s.getName(), false, null, dict);
case Enum e -> "W4" + mangleIdentifier(e.getName(), false, null, dict); case Enum e -> "W4" + mangleIdentifier(e.getName(), false, null, dict);
@ -413,12 +393,12 @@ public class MSVC7Mangle extends GhidraScript{
case UnsignedLongLongDataType _ -> "_K"; case UnsignedLongLongDataType _ -> "_K";
case BooleanDataType _ -> "_N"; case BooleanDataType _ -> "_N";
case WideCharDataType _ -> "_W"; case WideCharDataType _ -> "_W";
case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict, loc); case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict);
case FunctionSignature f -> mangleFnType(f, dict, "function typedef \"" + f.getName() + "\""); case FunctionSignature f -> mangleFnType(f, dict);
case TypeDef d -> mangleType(d.getBaseDataType(), dict, "typedef \"" + d.getName() + "\""); case TypeDef d -> mangleType(d.getBaseDataType(), dict);
case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined."); case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined.");
case Undefined _ -> 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 _ -> throw new Exception ("Encountered data marked \"undefined\". 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); default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\"");
}; };
} }
@ -466,8 +446,7 @@ public class MSVC7Mangle extends GhidraScript{
private static String mangleArgs( private static String mangleArgs(
final FunctionSignature f, final FunctionSignature f,
final List<String> dict, final List<String> dict
final String loc
) throws Exception { ) throws Exception {
/* Mangle the arguments for a function */ /* Mangle the arguments for a function */
final DataType[] args = Arrays.stream(f.getArguments()) final DataType[] args = Arrays.stream(f.getArguments())
@ -490,15 +469,10 @@ public class MSVC7Mangle extends GhidraScript{
// It turns out that academic-sounding stuff everyone // It turns out that academic-sounding stuff everyone
// freaks out at is actually useful (and Optional still // freaks out at is actually useful (and Optional still
// helped us out here) // helped us out here)
String mangledArgs = ""; String mangled = "";
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++)
final String mangledArg = mangleType(args[i], dict, loc); mangled += backref(args[i], argDict).orElse(mangleType(args[i], dict));
return mangled + (f.hasVarArgs() ? "Z" : "@");
mangledArgs += mangledArg.length() == 1 ?
mangledArg :
backref(args[i], argDict).orElse(mangledArg);
}
return mangledArgs + (f.hasVarArgs() ? "Z" : "@");
} }
} }
@ -521,8 +495,7 @@ public class MSVC7Mangle extends GhidraScript{
// vtable // vtable
if (ident.startsWith("?_7")) return "?" + ident + "6B@"; if (ident.startsWith("?_7")) return "?" + ident + "6B@";
return "?" + ident + "3" + return "?" + ident + "3" + mangleType(d.getDataType(), dict) +
mangleType(d.getDataType(), dict, "0x" + d.getAddress().toString()) +
"A"; "A";
} }