From 08abfd3913c2870b3f346100b39ebe993e94892c Mon Sep 17 00:00:00 2001 From: KeybadeBlox Date: Fri, 2 Jan 2026 00:05:52 -0500 Subject: [PATCH] Finish populating JSRF/Core --- decompile/objdiff.json | 56 +++++++- decompile/src/JSRF/Core.cpp | 272 ++++++++++++++++++++++++++++++++++++ decompile/src/JSRF/Core.hpp | 26 ++-- decompile/src/JSRF/Jet2.cpp | 2 +- decompile/src/XDK/Win32.hpp | 3 + readme.md | 2 +- 6 files changed, 342 insertions(+), 19 deletions(-) diff --git a/decompile/objdiff.json b/decompile/objdiff.json index 30ffb37..5bd8d18 100644 --- a/decompile/objdiff.json +++ b/decompile/objdiff.json @@ -15,10 +15,10 @@ }, "symbol_mappings": { "[.rdata-0]": "[.xdata$x-0]", - "_main_funcinfo": "$T737", - "_main_handler": "$L741", - "_main_handler_unwind1": "$L733", - "_main_unwindmap": "$T743" + "_main_funcinfo": "$T745", + "_main_handler": "$L749", + "_main_handler_unwind1": "$L741", + "_main_unwindmap": "$T751" } }, { @@ -34,6 +34,46 @@ "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::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::setSkipDraw": "?enableSkipDraw@Game@@QAEXXZ", + "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@", @@ -71,8 +111,12 @@ "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" + "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" } } ] -} \ No newline at end of file +} diff --git a/decompile/src/JSRF/Core.cpp b/decompile/src/JSRF/Core.cpp index eba9ca1..6776322 100644 --- a/decompile/src/JSRF/Core.cpp +++ b/decompile/src/JSRF/Core.cpp @@ -302,3 +302,275 @@ PlayerObj::PlayerObj(GameObj * parent, GameObjIndex index, GameObjFlags flags) : // Eliminated by link time code generation (aliased with 0x000121D0) PlayerObj::~PlayerObj() {} + +// Address: 0x00012210 +// Matching: no +Game::Game(unsigned * unknown1, unsigned unknown2) { +} + +// Address: 0x00012390 +// Matching: no +Game::~Game() { +} + +// Address: 0x000123E0 +// Matching: no +void Game::exec() { +} + +// Address: 0x00012580 +// Matching: no +void Game::drawObj(GameObj * obj, int unknown) { +} + +// Address: 0x000125E0 +// Matching: no +void Game::drawList_( + GameObjFlags flagFilterAny1, + int drawArg1, + int drawArg2, + GameObjFlags flagFilterAll, + unsigned otherBitfieldFilterAny, + GameObjFlags flagFilterNone, + GameObjFlags flagFilterAny2 +) { +} + +// Address: 0x00012680 +// Matching: no +void Game::drawTree1(GameObj * obj) { +} + +// Address: 0x000126D0 +// Matching: no +void Game::setCoveredPauseNextFrame(BOOL val) { +} + +// Address: 0x000126F0 +// Matching: no +void Game::setEventNextFrame(BOOL val) { +} + +// Address: 0x00012710 +// Matching: no +void Game::setFreezeCamNextFrame(BOOL val) { +} + +// Address: 0x00012730 +// Matching: no +void Game::setUncoveredPauseNextFrame(BOOL val) { +} + +// Address: 0x00012750 +// Matching: yes +void Game::enableDrawChildren() { + this->drawChildren = TRUE; +} + +// Address: 0x00012760 +// Matching: yes +void Game::enableSkipDraw() { + this->skipDraw = TRUE; +} + +// Address: 0x00012770 +// Matching: no +void Game::fatal() { +} + +// Address: 0x000127B0 +// Matching: yes +void Game::setDrawMode(DrawMode mode) { + this->drawMode = mode; +} + +// Address: 0x000127C0 +// Matching: yes +void Game::setGlobal(GlobalIndex index, unsigned val) { + this->globals[index] = val; +} + +// Address: 0x000127E0 +// Matching: yes +unsigned Game::getGlobal(GlobalIndex index) { + return this->globals[index]; +} + +// Address: 0x000127F0 +// Matching: no +void Game::addToDrawList(GameObj * obj) { +} + +// Address: 0x00012840 +// Matching: no +void Game::removeFromDrawList(GameObj * obj) { +} + +// Address: 0x00012870 +// Matching: yes +void Game::setObj(GameObjIndex index, GameObj * obj) { + if (0 <= index && index < OBJ_CNT) + this->objects[index] = obj; +} + +// Address: 0x00012890 +// Matching: yes +void Game::unsetObj(GameObjIndex index) { + if (0 <= index && this->objects[index] != NULL) + this->objects[index] = NULL; +} + +// Address: 0x000128C0 +// Matching: yes +GameObj * Game::getObj(GameObjIndex index) { + return 0 <= index ? this->objects[index] : NULL; +} + +// Address: 0x000128E0 +// Matching: yes +int Game::allocObjIndex(GameObjIndex min, GameObjIndex max) { + if (min <= max) do + if (this->objects[min] == NULL) return min; + else min = GameObjIndex(min + 1); + while (min <= max); + + return -1; +} + +// Address: 0x00012910 +// Matching: yes +BOOL Game::objIndexAvail(GameObjIndex index) { + return this->objects[index] == NULL; +} + +// Address: 0x00012930 +// Matching: yes +void Game::swapObjs(GameObjIndex index1, GameObjIndex index2) { + GameObj * tmp = this->objects[index1]; + this->objects[index1] = this->objects[index2]; + this->objects[index2] = tmp; + + if (this->objects[index1] != NULL) this->objects[index1]->index = index1; + if (this->objects[index2] != NULL) this->objects[index2]->index = index2; +} + +// Address: 0x00012980 +// Matching: no +void Game::clearScreen() { +} + +// Address: 0x000129B0 +// Matching: yes +void Game::enableSomeExtraDrawListCode() { + this->runSomeExtraDrawListCode = TRUE; +} + +// Address: 0x000129C0 +// Matching: yes +void Game::setLogosStarted(BOOL val) { + this->logosStarted = val; +} + +// Address: 0x000129D0 +// Matching: yes +void Game::clearDrawPriorityList() { + this->drawPriorityListHead = NULL; + this->drawPriorityListEndNext = &g_game->drawPriorityListHead; +} + +// Address: 0x000129F0 +// Matching: yes +GameObj * Game::getDrawPriorityListHead() { + return this->drawPriorityListHead; +} + +// Address: 0x00012A00 +// Matching: yes +void Game::appendToDrawPriorityList(GameObj * obj) { + obj->drawPriorityListNext = NULL; + *this->drawPriorityListEndNext = obj; + this->drawPriorityListEndNext = &obj->drawPriorityListNext; +} + +// Address: 0x00012A20 +// Matching: no +void Game::sortDrawPriorityListSingleLevel(char sortKeyBitOffset) { +} + +// Address: 0x00012AC0 +// Matching: yes +void Game::setFallbackBgColour(D3DCOLOR colour, BOOL useFallback) { + this->useFallbackBgColour = useFallback; + this->bgColourFallback = colour; +} + +// Address: 0x00012AE0 +// Matching: no +RootExecObj::RootExecObj(GameObj * parent, GameObjIndex index, GameObjFlags flags) : + GameObj(parent, index, flags) { +} + +// Address: 0x00012BE0 +// Matching: no +RootExecObj::~RootExecObj() { +} + +// Address: 0x00012C10 +// Matching: no +void Game::initRootExecObj() { +} + +// Address: 0x00012C80 +// Matching: no +void Game::drawList(GameObjFlags flagFilterAll, BOOL unknown) { +} + +// Address: 0x000131A0 +// Matching: no +void Game::sortDrawPriorityList() { + this->sortDrawPriorityListSingleLevel(0x00); + this->sortDrawPriorityListSingleLevel(0x08); + this->sortDrawPriorityListSingleLevel(0x10); + this->sortDrawPriorityListSingleLevel(0x18); +} + +// Address: 0x000131F0 +// Matching: no +void Game::drawObjs() { +} + +// Address: 0x00013930 +// Matching: no +void Game::draw() { +} + +// Address: 0x00013A80 +// Matching: no +void Game::frame() { +} + +// Address: 0x00013F80 +// Matching: no +int Game::mainLoop() { + if (this->initState < 0) return -1; + + while (true) { + while (this->fatalErr) { + // (need to declare these somewhere) + //readInput(); + //Sleep(0x10); + } + + this->frame(); + } +} + +// Address: 0x00013FC0 +// Matching: no +void removeFromObjListByIndex(GameObjIndex index) { + GameObj * obj = g_game->getObj(index); + if (obj != NULL) { + obj->removeFromObjList(obj); + obj->removeChildrenFromObjList(obj->firstChild); + } +} diff --git a/decompile/src/JSRF/Core.hpp b/decompile/src/JSRF/Core.hpp index de4b9af..838a2fb 100644 --- a/decompile/src/JSRF/Core.hpp +++ b/decompile/src/JSRF/Core.hpp @@ -36,8 +36,10 @@ enum GameObjFlags { // objecs. enum GameObjIndex { OBJ_NOTINDEXED = -1, // Not stored in array - OBJ_DIRECTOR = 0 + OBJ_DIRECTOR = 0, // TODO + + OBJ_CNT = 0x1DF4 }; // Base class of most objects (and everything in g_game->objects) @@ -50,19 +52,18 @@ struct GameObj { unsigned sortKey; // Four-level key, one byte each D3DVECTOR someTranslation; - // Links forming a tree of objects + // Links forming a tree of objects for exec phase GameObj * parent; GameObj * firstChild; GameObj * prevSibling; GameObj * nextSibling; - // Some kind of linked list walked during rendering - GameObj * somethingLinkedNext; - GameObj * * somethingLinkedPrevNext; - GameObj * * * somethingLinkedEndNextPtr; + // Some data structures used for draw phrase + GameObj * nextDrawTree; + GameObj * * prevDrawTreeNext; + GameObj * * * lastDrawTreeNextPtr; - // Another linked list sort of arrangement - GameObj * someKindOfNextObj; + GameObj * drawPriorityListNext; virtual ~GameObj(); @@ -213,6 +214,7 @@ enum DrawMode { enum GlobalIndex { }; +#pragma pack(4) extern struct Game { char unknown0x4[4]; unsigned unknown0x8; @@ -272,6 +274,8 @@ extern struct Game { GameObj * drawPriorityListsByKeyHeads [256]; GameObj * * drawPriorityListsByKeyEndNexts[256]; + unsigned unknown0x87B4; + LARGE_INTEGER execPerfCount; LARGE_INTEGER drawPerfCount; @@ -312,7 +316,7 @@ extern struct Game { void setUncoveredPauseNextFrame(BOOL val); void enableDrawChildren(); - void setSkipDraw(); + void enableSkipDraw(); void fatal(); void setDrawMode(DrawMode mode); @@ -335,11 +339,11 @@ extern struct Game { void clearDrawPriorityList(); GameObj * getDrawPriorityListHead(); - void appendToDrawPriorityList(); + void appendToDrawPriorityList(GameObj * obj); void sortDrawPriorityListSingleLevel(char sortKeyBitOffset); void setFallbackBgColour(D3DCOLOR colour, BOOL useFallback); - void initExecRootObj(); + void initRootExecObj(); void drawList(GameObjFlags flagFilterAll, BOOL); void sortDrawPriorityList(); void drawObjs(); diff --git a/decompile/src/JSRF/Jet2.cpp b/decompile/src/JSRF/Jet2.cpp index e170652..86f6f30 100644 --- a/decompile/src/JSRF/Jet2.cpp +++ b/decompile/src/JSRF/Jet2.cpp @@ -15,7 +15,7 @@ Game * g_game; // Matching: yes void main(void) { g_game = new Game(NULL, 0); - g_game->initExecRootObj(); + g_game->initRootExecObj(); g_game->mainLoop(); delete g_game; } diff --git a/decompile/src/XDK/Win32.hpp b/decompile/src/XDK/Win32.hpp index 5804e1e..32cc801 100644 --- a/decompile/src/XDK/Win32.hpp +++ b/decompile/src/XDK/Win32.hpp @@ -24,6 +24,9 @@ typedef unsigned long DWORD; typedef int BOOL; typedef float FLOAT; +#define TRUE 1 +#define FALSE 0 + // 64-bit integer compatibility type union LARGE_INTEGER { struct { diff --git a/readme.md b/readme.md index fb7fb2d..42fd15d 100644 --- a/readme.md +++ b/readme.md @@ -3,7 +3,7 @@ A matching decompilation of the Xbox game Jet Set Radio Future. ## Progress - Delinking progress: 0.52% (13263 out of 2574172 bytes in XBE address space) -- Decompilation progress: 3.1% (3 out of the 98 functions delinked so far) +- Decompilation progress: 26.5% (26 out of the 98 functions delinked so far) ## Roadmap The approach of this decompilation is to: