From aaddf5213aaa7476b75d24158526c78717cb9223 Mon Sep 17 00:00:00 2001 From: KeybadeBlox Date: Wed, 10 Dec 2025 22:38:12 -0500 Subject: [PATCH] Initial commit --- objects.csv | 4 ++ readme.md | 13 ++++ src/core.cpp | 1 + src/core.hpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++++ src/jet2.cpp | 15 ++++ src/mmatrix.cpp | 46 +++++++++++++ 6 files changed, 258 insertions(+) create mode 100644 objects.csv create mode 100644 readme.md create mode 100644 src/core.cpp create mode 100644 src/core.hpp create mode 100644 src/jet2.cpp create mode 100644 src/mmatrix.cpp diff --git a/objects.csv b/objects.csv new file mode 100644 index 0000000..18cba8e --- /dev/null +++ b/objects.csv @@ -0,0 +1,4 @@ +Proposed name,.text,D3D,DSOUND,MMATRIX,XGRPH,XPP,.rdata,.data,DOLBY +Core.o,0x00011000-0x00013FF,,,,,,0x001C4390-0x001C44FF,0x00251D40-0x00251DAB (maybe), +Jet2.o,0x0006F9E0-0x0006FA6F,,,,,,,0x0022FCE0-0x0022FCE7, +MMatrix.o,,,,0x001BA8A0-0x001BBAAF,,,,0x00264BD8-0x00264C13, diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..99f1b74 --- /dev/null +++ b/readme.md @@ -0,0 +1,13 @@ +# Jet Set Radio Future Decompilation Notes +This is just a public holding space for anything I put together as a part of +the JSRF decompilation effort. + +`objects.csv` is a table of suspected object file boundaries for delinking. +The addresses given in each section are runtime memory addresses (as one would +see in e.g. Ghidra). + +The `src/` directory contains decompiled code and data. Each symbol is +annotated with its corresponding memory address in the original binary, and +functions are marked as perfectly or imperfectly matching. It's not +necessarily intended to be compilable, but more scratch space for noting down +what I've worked out. diff --git a/src/core.cpp b/src/core.cpp new file mode 100644 index 0000000..1ecc69a --- /dev/null +++ b/src/core.cpp @@ -0,0 +1 @@ +#include "core.hpp" diff --git a/src/core.hpp b/src/core.hpp new file mode 100644 index 0000000..069a044 --- /dev/null +++ b/src/core.hpp @@ -0,0 +1,179 @@ +#ifndef CORE_HPP + + +typedef bool32 unsigned; // Need to find a clean way of representing this + +typedef Mat4 D3DVECTOR4[4]; // Should probably be defined somewhere else + +struct GraphicsPerformanceCounters { // Would come from header with Graphics COM object + unsigned fps; + unsigned trianglesPerSecond; + unsigned frameTriangleCnt; + unsigned unknown0xC; + unsigned unknown0x10; + unsigned unknown0x14; +} + +enum DrawMode { DRAW_YES, DRAW_WAITVBLANK, DRAW_NO }; + +// Base class of most 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 unknown0xC; + float unknown0x10; + unsigned sortKey; // Four-level key, one byte each + D3DVECTOR unknown0x18; + + // 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 +class Game { + char unknown0x4[4]; + unsigned unknown0x8; + unsigned * unknown0xC; + int initState; + unsigned unknown0x14; + bool32 drawProfilingInfo; + int unknown0x1C; + bool32 logosStarted; + bool32 fatalErr; + + D3DCOLOR colour; + D3DCOLOR ambientColour; + D3DCOLOR shadowColour; + D3DCOLOR bgColour; + D3DCOLOR bgColourFallback; + bool32 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 + bool32 coveredPause; // Game paused with world not visible + bool32 event; // Events (cutscenes) + bool32 freezeCam; // Time-frozen camera shots + bool32 uncoveredPause; // Game paused with world visible, or + // automatic pause at start of mission + + bool32 setCoveredPauseNextFrame; + bool32 unsetCoveredPauseNextFrame; + bool32 setEventNextFrame; + bool32 unsetEventNextFrame; + bool32 setFreezeCamNextFrame; + bool32 unsetFreezeCamNextFrame; + bool32 setUncoveredPauseNextFrame; + bool32 unsetUncoveredPauseNextFrame; + + unsigned unknown0x70; + bool32 skipDraw; + int zeroedByExec; + GraphicsPerformanceCounters perfCounters; + DrawMode 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]; + + unsigned unknown0x87B4; + + 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(); + + // TODO: methods +}; + + +#endif diff --git a/src/jet2.cpp b/src/jet2.cpp new file mode 100644 index 0000000..066b094 --- /dev/null +++ b/src/jet2.cpp @@ -0,0 +1,15 @@ +#include "core.hpp" + + +// Address: 0x0022FCE0 +Game * g_game; + + +// Address: 0x0006F9E0 +// Matching: no +void main(void) { + g_game = new Game(NULL, 0); + g_game->initExecRootObj(); + g_game->mainLoop(); + delete g_game; +} diff --git a/src/mmatrix.cpp b/src/mmatrix.cpp new file mode 100644 index 0000000..3826f4f --- /dev/null +++ b/src/mmatrix.cpp @@ -0,0 +1,46 @@ +// Address: 0x001BB690 +// Matching: yes +HRESULT __stdcall initMatrices(unsigned const count) { +/* Initialize the matrix stack with the given number of matrices. +The requested number of matrices is rounded up to the nearest multiple of two. +The initialized matrices are accessible through g_matrices. +*/ + // Allocate matrices + unsigned i = (count + 1) & 0xFFFFFFFE; // Round up + Mat4 * const mats = (Mat4 *)VirtualAlloc( + NULL, + (i + 2) * sizeof *mats, + MEM_COMMIT|MEM_RESERVE, + PAGE_READWRITE + ); + if (mats != NULL) { + Mat4 * mat = mats + 2; + + // Initialize each matrix to identity + if (i > 0) for (; i > 0; i--) { + float * entry = (float *)mat; + + for (unsigned j = 0; j < sizeof *mat/sizeof *entry; j++) { + *entry = 0; + entry += 1; + } + + (*mat)[3].w = 1; + (*mat)[2].z = 1; + (*mat)[1].y = 1; + (*mat)[0].x = 1; + mat++; + } + + // Assign to g_matrices for later access + mat = mats + 2; + g_matrices[1] = mats; + g_matrices[2] = mat; + g_matrices[0] = mats; + g_matricesHead = g_matrices + 2; + + return ERROR_SUCCESS; + } + + return E_OUTOFMEMORY; +}