Complete delink workflow; separate from decomp

We can now create a fresh Ghidra project, import the JSRF executable
into it, import symbols into it, delink object files from it, and then
decompile with objdiff.  Just needs some documentation.
This commit is contained in:
KeybadeBlox 2025-12-16 22:30:49 -05:00
parent 87c56f01d6
commit 1a48d4323e
17 changed files with 1178 additions and 8 deletions

189
decompile/src/Core.hpp Normal file
View file

@ -0,0 +1,189 @@
/* JSRF Decompilation: Core.hpp
Game and GameObj classes that form the foundation of the JSRF game code.
*/
#ifndef CORE_HPP
#define CORE_HPP
#include "D3D.hpp"
#include "MMatrix.hpp"
#include "Std.hpp"
#include "Win32.hpp"
// TODO; move to header for Graphics COM object in Smilebit libraries
struct GraphicsPerformanceCounters {
unsigned fps;
unsigned trianglesPerSecond;
unsigned frameTriangleCnt;
unsigned unknown0xC;
unsigned unknown0x10;
unsigned unknown0x14;
};
// Base class of most objects (and everything in g_game->objects)
class GameObj {
enum GameObjFlags {
GOF_SOMETHINGLINKED_ALTLIST = 1 << 0,
GOF_SKIPDRAWCHILDREN = 1 << 16,
GOF_SKIPDRAWASCHILD = 1 << 18,
GOF_SKIPDRAWASROOT = 1 << 22,
GOF_EXCLUDEFROMSOMETHINGLINKED = 1 << 30,
GOF_DELETEAFTEREXEC = 1 << 31
} flags;
// Position in g_game->objects array
// Different indices and ranges are dedicated to different kinds of
// objecs.
enum GameObjIndex {
OBJ_NOTINDEXED = -1, // Not stored in array
OBJ_DIRECTOR = 0
// TODO
} index;
unsigned otherBitfield;
float reverseSortKey; // Sign flipped to produced sortKey
unsigned sortKey; // Four-level key, one byte each
D3DVECTOR someTranslation;
// Links forming a tree of objects
GameObj * parent;
GameObj * firstChild;
GameObj * prevSibling;
GameObj * nextSibling;
// Some kind of linked list walked during rendering
GameObj * somethingLinkedNext;
GameObj * * somethingLinkedPrevNext;
GameObj * * * somethingLinkedEndNextPtr;
// Another linked list sort of arrangement
GameObj * someKindOfNextObj;
public:
virtual ~GameObj();
GameObj(GameObj * parent, GameObjIndex index, GameObjFlags flags);
// Each frame, one of these trios of methods is called depending on
// which state the game is in
// Default implementation of each does nothing; inheriting objects
// override these methods to run some code during each phase of each
// frame.
virtual void execDefault();
virtual void postExecDefault();
virtual void drawDefault();
virtual void execEvent();
virtual void postExecEvent();
virtual void drawEvent();
virtual void execCoveredPause();
virtual void postExecCoveredPause();
virtual void drawCoveredPause();
virtual void execFreezeCam();
virtual void postExecFreezeCam();
virtual void drawFreezeCam();
virtual void execUncoveredPause();
virtual void postExecUncoveredPause();
virtual void drawUncoveredPause();
// TODO: non-virtual methods
};
// Top-level globally-accessible "god object" that runs the main loop and
// provides global access to most other objects and many variables
extern class Game {
char unknown0x4[4];
unsigned unknown0x8;
unsigned * unknown0xC;
int initState;
unsigned unknown0x14;
BOOL drawProfilingInfo;
int unknown0x1C;
BOOL logosStarted;
BOOL fatalErr;
D3DCOLOR colour;
D3DCOLOR ambientColour;
D3DCOLOR shadowColour;
D3DCOLOR bgColour;
D3DCOLOR bgColourFallback;
BOOL useFallbackBgColour;
// Game state used to select GameObj methods to call in main loop
// If multiple states are acivated, the precedence is
// coveredPause > Event > FreezeCam > UncoveredPause > Default
BOOL coveredPause; // Game paused with world not visible
BOOL event; // Events (cutscenes)
BOOL freezeCam; // Time-frozen camera shots
BOOL uncoveredPause; // Game paused with world visible, or
// automatic pause at start of mission
BOOL setCoveredPauseNextFrame;
BOOL unsetCoveredPauseNextFrame;
BOOL setEventNextFrame;
BOOL unsetEventNextFrame;
BOOL setFreezeCamNextFrame;
BOOL unsetFreezeCamNextFrame;
BOOL setUncoveredPauseNextFrame;
BOOL unsetUncoveredPauseNextFrame;
unsigned unknown0x70;
BOOL skipDraw;
int zeroedByExec;
GraphicsPerformanceCounters perfCounters;
enum DrawMode {
DRAW_YES,
DRAW_WAITVBLANK,
DRAW_NO
} drawMode;
// Globally accessible objects and variables
GameObj * objects[7668];
unsigned globals[461]; // Items may be any 32-bit type, e.g. ptr
GameObj * somethingLinkedBHead;
GameObj * * somethingLinkedBEndNext;
GameObj * somethingLinkedAHead;
GameObj * * somethingLinkedAEndNext;
GameObj * sortedLinkedListHead;
GameObj * * sortedLinkedListEndNext;
GameObj * linkedListsByKeyHeads [256];
GameObj * * linkedListByKeyEndNexts[256];
LARGE_INTEGER execPerfCount;
LARGE_INTEGER drawPerfCount;
unsigned unknown0x87C8;
unsigned unknown0x87CC;
unsigned frameCnt1;
unsigned unknown0x87D4;
unsigned unknown0x87D8;
GameObj * rootExecObj;
int frameCnt2;
int frameCnt3;
unsigned gameObjCnt;
GameObj * rootDrawObj;
int unknown0x87F0;
int unknown0x87F4;
Mat4 unknown0x87F8;
unsigned unknown0x8838;
unsigned unknown0x883C;
public:
Game(unsigned *, unsigned);
virtual ~Game();
void initExecRootObj();
void mainLoop();
// TODO: other methods
} * g_game;
#endif