From fbc5619d6a48a974967773e3c1fa210c72cb43d0 Mon Sep 17 00:00:00 2001 From: KeybadeBlox Date: Mon, 12 Jan 2026 09:46:56 -0500 Subject: [PATCH] Begin populating JSRF/GameData.hpp --- decompile/objdiff.json | 5 +- decompile/src/JSRF/GameData.cpp | 3 + decompile/src/JSRF/GameData.hpp | 154 ++++++++++++++++++++++++++++++++ delink/symboltable.tsv | 8 +- 4 files changed, 165 insertions(+), 5 deletions(-) diff --git a/decompile/objdiff.json b/decompile/objdiff.json index 1604aac..3cb19c1 100644 --- a/decompile/objdiff.json +++ b/decompile/objdiff.json @@ -125,7 +125,10 @@ "metadata": { "complete": false, "source_path": "src/JSRF/GameData.cpp" + }, + "symbol_mappings": { + "GameData::`scalar_deleting_destructor'": "??_GGameData@@UAEPAXI@Z" } } ] -} \ No newline at end of file +} diff --git a/decompile/src/JSRF/GameData.cpp b/decompile/src/JSRF/GameData.cpp index 63e8858..0fda95f 100644 --- a/decompile/src/JSRF/GameData.cpp +++ b/decompile/src/JSRF/GameData.cpp @@ -5,3 +5,6 @@ Save data and closely-related runtime data. #pragma bss_seg(".data") #include "GameData.hpp" + + +GameData g_gameData = GameData(); diff --git a/decompile/src/JSRF/GameData.hpp b/decompile/src/JSRF/GameData.hpp index a1070d0..278f2d9 100644 --- a/decompile/src/JSRF/GameData.hpp +++ b/decompile/src/JSRF/GameData.hpp @@ -5,6 +5,160 @@ Save data and closely-related runtime data. #ifndef GAMEDATA_HPP #define GAMEDATA_HPP +#include "../XDK/Win32.hpp" +// Data structure actually saved to disk +struct SaveData { + unsigned chapter; + unsigned missionDigits34; + unsigned spawnPosIndex; + unsigned playtimeFrames; + unsigned unlockedChars; + + // Boolean flags read and written by missions + unsigned chapterFlags[16]; // Reset every chapter + unsigned globalFlags [16]; // Never reset + unsigned specialFlags[16]; // Never reset; special effects like + // unlocking/completing tutorials, finishing + // street challenges + + unsigned spawnedSouls [8]; // Souls that have appeared on streets + unsigned collectedSouls[8]; // Souls that have been acquired + unsigned heldSouls [8]; // Souls currently usable (i.e. not stolen) + + unsigned unusedPerStageBitmask[16]; + + // Which tags have been sprayed and by who + // Indexed by stage, tag ID, and player/rival tag; rival tags don't + // count towards completion and can be painted over. Each entry is a + // packed bit array of 3 bits per "G" mark, valued 7 if nothing is + // painted or 0-3 to indicate player 1-4 painted it (in story mode, + // rival graffiti is considered painted by players 2-4). + unsigned tagState[16][80][2]; + + struct SaveSettings { + float volumeMusic; + float volumeSfx; + BOOL rumbleEnabled; + unsigned unused[29]; + } saveSettings; + + unsigned garageMusic; + unsigned unusedBitfield[8]; + + // Sewer switches at offset 0 then noise tanks at offset 3 + unsigned miscObjectives[32]; + + struct TestRunScoreSaved { + unsigned score; + unsigned char character; + unsigned char rank1; // Used by Jet Tech + unsigned char rank2; // Used by other test runs + } highScores[16][4][5]; + + unsigned clutchTimer; + unsigned unusedTimer; + + unsigned selectedTags [5]; // Like GameData but for P1 in 1-player + unsigned customTagSelected[5]; // Like GameData but for P1 in 1-player + + unsigned eventsSeen[16]; +}; + +// Numeric IDs for selecting different listss of state flags +enum FlagList { + FLAGLIST_MISSION, + FLAGLIST_CHAPTER, + FLAGLIST_GLOBAL, + FLAGLIST_SPECIAL +}; + +// Numeric IDs for tag sizes (should maybe put somewhere else?) +enum TagSize { TAGSIZE_SS, TAGSIZE_S, TAGSIZE_M, TAGSIZE_L, TAGSIZE_XL }; + +// Numeric IDs for different test run categories +enum TestRunType { + TESTRUN_GRAFFITI, + TESTRUN_TECH, + TESTRUN_DASH, + TESTRUN_FLAG +}; + +// Unpacked version of TestRunScoreSaved +struct TestRunScore { + unsigned score; + unsigned character; + unsigned rank1; // Used by Jet Tech + unsigned rank2; // Used by other test runs +}; + +// Numeric IDs for different timers +enum Timer { TIMER_DEATHBALLPRACTICE, TIMER_CLUTCH, TIMER_UNUSED }; + +// Save data-ish data structure used at runtime +extern struct GameData { + SaveData saveActive; + SaveData saveStashed; // Holds save data during test runs/tutorials + + unsigned missionFlags[16]; // Reset every mission transition + unsigned deathBallPracticeTimer; // For Jazz sequence in Future Site + + // Indexed like SaveData.highScores; true if score is most recent and + // also made leaderboard + BOOL mostRecentHighScore[16][4][5]; + + // Tags indexed by single or multiplayer, then gang (GGs, Golden + // Rhinos/Zero Beat, Poison Jam, Immortals) or player, then size + unsigned selectedTags [2][4][5]; // IDs of tags in use + BOOL customTagSelected[2][4][5]; // True means tag ID is for custom + // graffiti list, not ingame list + + BOOL checkFlagCondition (unsigned cond); + void writeStateFlag (unsigned flagVal); + void incrementChapter (); + void setMissionDigits34 (unsigned val); + void setSpawnPosIndex (unsigned val); + unsigned getSpawnPosIndex (); + void unlockCharacter (unsigned charId); + void lockCharacter (unsigned charId); + BOOL characterUnlocked (unsigned charId); + BOOL checkFlagConditions (unsigned * conds , unsigned count); + void writeStateFlags (unsigned * writes, unsigned count); + BOOL checkFlagConditionUnpacked(FlagList flagList, unsigned index); + void writeStateFlagUnpacked (FlagList flagList, unsigned index, unsigned val); + void setSoulSpawned (unsigned soulId); + BOOL getSoulSpawned (unsigned soulId); + void setSoulCollected (unsigned soulId); + BOOL getSoulHeld (unsigned soulId); + BOOL soulSpawnedUncollected(unsigned soulId); + void clearHeldSouls (); + void restoreHeldSouls (); + unsigned getSoulCount (); + unsigned getTotalSoulsInStage(unsigned stageId); + unsigned getHeldSoulsInStage (unsigned stageId); + unsigned setSoulCollectedBySize(TagSize size, unsigned index); + void setUnusedPerStageBitmask(unsigned stageId, unsigned index); + int getTagState (unsigned stageId, unsigned index, BOOL rivalTag); + void setTagState (unsigned stageId, unsigned index, BOOL rivalTag, unsigned val); + void setTagCovered (unsigned stageId, unsigned index, BOOL rivalTag, unsigned gangOrPlayer); + void setVolumeSettings (float volMusic, float volSfx); + void getVolumeSettings (float * outMusic, float * outSfx); + void setRumbleEnabled (BOOL val); + BOOL getRumbleEnabled (); + void setGarageMusic (unsigned songId); + unsigned getGarageMusic (); + void setUnusedBitfield (unsigned index); + void setMiscObjective (unsigned index); + BOOL getMiscObjective (unsigned index); + unsigned countMiscObjectives (); + BOOL getHighScore (unsigned stageId, TestRunType type, unsigned rank, TestRunScore * out); + void incrementTimer (Timer timer); + unsigned getTimer (Timer timer); + void setTimer (Timer timer, unsigned frames); + + GameData(); + virtual ~GameData(); +} g_gameData; + #endif diff --git a/delink/symboltable.tsv b/delink/symboltable.tsv index 111aef7..2061e04 100644 --- a/delink/symboltable.tsv +++ b/delink/symboltable.tsv @@ -245,16 +245,16 @@ setSoulCollected 00039e80 f getSoulHeld 00039eb0 f soulSpawnedUncollected 00039ef0 f clearHeldSouls 00039f40 f -restoreCollectedSouls 00039f60 f +restoreHeldSouls 00039f60 f getSoulCount 00039fd0 f getTotalSoulsInStage 0003a0a0 f getHeldSoulsInStage 0003a130 f setSoulCollectedBySize 0003a2b0 f -getUnusedPerStageBitmask 0003a2f0 f +setUnusedPerStageBitmask 0003a2f0 f getTagState 0003a340 f setTagState 0003a3a0 f setTagCovered 0003a400 f -setVolume 0003a4a0 f +setVolumeSettings 0003a4a0 f getVolumeSettings 0003a4c0 f setRumbleEnabled 0003a4e0 f getRumbleEnabled 0003a4f0 f @@ -970,7 +970,7 @@ vtable 001c4d50 l vtable 001c4d58 l vtable 001c4f68 l vtable 001ca168 l -vtable 001ca3d8 l +`vftable' 001ca3d8 l vtable 001ca440 l vtable 001ca4c8 l vtable 001ca508 l