Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a5d1c8a
decompile RumbleData.cpp
hyblocker Oct 12, 2025
4cd6afa
decompile Koga::ToolData
hyblocker Oct 12, 2025
a215122
mostly decompile MovieRumble
hyblocker Oct 12, 2025
7d4cd6b
correct type
hyblocker Oct 12, 2025
1d26c8b
fix missing category in M3DUtil and System
hyblocker Oct 17, 2025
29c4d6c
minor fixes
hyblocker Oct 17, 2025
7cd1b2c
99% accuracy (stack mismatches afaik)
hyblocker Oct 17, 2025
759f805
bruh bruh
hyblocker Oct 17, 2025
4d00b23
rumble data struct + convert hex to floats
hyblocker Oct 22, 2025
ec321cb
begin decompiling RumbleMgr
hyblocker Oct 22, 2025
3addbdc
oops
hyblocker Oct 22, 2025
68d1d76
how were u not clang formatted
hyblocker Oct 22, 2025
95e52fb
decompile more
hyblocker Oct 22, 2025
8a3df32
work some more on MovieRumble
hyblocker Oct 23, 2025
dc672d3
forgor this
hyblocker Oct 23, 2025
894d9fa
mostly decompile rumble stuff now, still needs a lot of work though
hyblocker Dec 18, 2025
babf253
make TTHPRender::getFrameNumber an inline getter
hyblocker Dec 18, 2025
0d60d64
clang format
hyblocker Dec 18, 2025
dd1eabe
fix: improve RumbleMgr
hyblocker Jan 24, 2026
30c1702
Merge branch 'main' into rumble
hyblocker Feb 19, 2026
dc19ac4
Merge branch 'doldecomp:main' into rumble
hyblocker Feb 21, 2026
797c219
fix: why did the merge request mess these up
hyblocker Feb 21, 2026
906f5b5
fix: changes to fix build
hyblocker Feb 21, 2026
9a0a999
Merge branch 'rumble' of https://github.com/hyblocker/sms into rumble
hyblocker Feb 21, 2026
6e32d1a
fix: i fucking hate git why does it handle merges so fucking badly
hyblocker Feb 21, 2026
ebcc6bf
chore: lint
hyblocker Feb 21, 2026
e6a039c
chore: lint again
hyblocker Feb 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,13 +801,14 @@ def MatchingFor(*versions):
Object(Matching, "MarioUtil/GDUtil.cpp"),
Object(Matching, "MarioUtil/TexUtil.cpp"),
Object(Matching, "MarioUtil/MapUtil.cpp"),
Object(NonMatching, "MarioUtil/ToolData.cpp"),
Object(Matching, "MarioUtil/ToolData.cpp"),
],
},
{
"lib": "M3DUtil",
"mw_version": "GC/1.2.5",
"cflags": [*cflags_system, "-inline deferred"],
"progress_category": "game",
"objects": [
Object(NonMatching, "M3DUtil/M3UJoint.cpp"),
Object(NonMatching, "M3DUtil/M3UModel.cpp"),
Expand All @@ -826,6 +827,7 @@ def MatchingFor(*versions):
"lib": "System",
"mw_version": "GC/1.2.5",
"cflags": [*cflags_system, "-inline deferred"],
"progress_category": "game",
"objects": [
Object(Matching, "System/BaseParam.cpp"),
Object(NonMatching, "System/EmitterViewObj.cpp"),
Expand Down
7 changes: 2 additions & 5 deletions include/GC2D/MovieRumble.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
#define GC2D_MOVIE_RUMBLE_HPP

#include <JSystem/JDrama/JDRViewObj.hpp>

class TTHPRender;
namespace Koga {
class ToolData;
}
#include <MarioUtil/ToolData.hpp>
#include <System/THPRender.hpp>

class TMovieRumble : public JDrama::TViewObj {
public:
Expand Down
2 changes: 1 addition & 1 deletion include/MarioUtil/RumbleMgr.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#ifndef MARIO_UTIL_RUMBLE_MGR_HPP
#define MARIO_UTIL_RUMBLE_MGR_HPP

#include <types.h>
#include <dolphin/mtx.h>
#include <dolphin/pad.h>
#include <types.h>

#define RUMBLE_CHANNELS_PER_CONTROLLER 32

Expand Down
135 changes: 97 additions & 38 deletions include/MarioUtil/ToolData.hpp
Original file line number Diff line number Diff line change
@@ -1,58 +1,117 @@
#ifndef MARIO_UTIL_TOOL_DATA_HPP
#define MARIO_UTIL_TOOL_DATA_HPP

#include <dolphin/types.h>
#include <types.h>

namespace Koga {

/**
* @brief ToolData is a class that reads BCSV data. Usage is as follows:
* Create a ToolData instance, fetch the BCSV data from disk and attach it.
* One can then call GetValue to retrieve data from the file.
*
* The structures and parsing logic are based off the Mario Galaxy decomp's
* handling of JMap files
*/
class ToolData {
public:
ToolData();
virtual ~ToolData(); // if not explicitly defined its not generated ok
BOOL Attach(const void* bcsvFileData);
// returns TRUE if the value was found, otherwise FALSE
BOOL GetValue(int entryIndex, const char* key, long& pValueOut) const;
// returns TRUE if the value was found, otherwise FALSE
BOOL GetValue(int entryIndex, const char* key,
const char*& pValueOut) const;

virtual ~ToolData();
inline bool dataExists() const { return !!mData; }

bool Attach(const void*);
void Detach();
static u32 Hash(const char*);
inline bool isIndexValid(s32 entryIndex)
{
return entryIndex < mData->mNumEntries;
}

bool GetValue(int, const char*, u32&) const;
bool GetValue(int, const char*, s32&) const;
bool GetValue(int, const char*, bool&) const;
bool GetValue(int, const char*, const char*&) const;
bool GetValue(int, const char*, f32&) const;
// JMAP value types, ignored in sunshine
#define JMAP_VALUE_TYPE_LONG 0
#define JMAP_VALUE_TYPE_STRING 1
#define JMAP_VALUE_TYPE_FLOAT 2
#define JMAP_VALUE_TYPE_LONG_2 3
#define JMAP_VALUE_TYPE_SHORT 4
#define JMAP_VALUE_TYPE_BYTE 5
#define JMAP_VALUE_TYPE_STRING_PTR 6
#define JMAP_VALUE_TYPE_NULL 7

int SearchItemInfo(const char*) const;
struct JMapItem {
u32 mHash; // 0x0
u32 mMask; // 0x4
u16 mOffsData; // 0x8
u8 mShift; // 0xA
u8 mType; // 0xB
};

void FindElement(int, u32, int) const;
void FindElement(int, s32, int) const;
void FindElement(int, bool, int) const;
void FindElement(int, const char*, int) const;
void FindElement(int, f32, int) const;
struct JMapData {
s32 mNumEntries; // 0x0
s32 mNumFields; // 0x4
s32 mDataOffset; // 0x8
u32 mEntrySize; // 0xC
const JMapItem mItems[]; // 0x10
};

const void* GetData() const { return unk4; }
int GetGroupCount() const { return unk4->unk0; }
private:
inline u32 hashString(const char* key) const
{
u32 stringHash = 0;
char current_char;

public:
struct ItemInfo {
u16 getUnk8() const { return unk8; }
u32 getUnk0() const { return unk0; }
while ((current_char = *key) != 0) {
key++;
stringHash = (current_char + (stringHash << 8)) % 0x1FFFFD9;
}
return stringHash;
}

/* 0x0 */ u32 unk0;
/* 0x4 */ char unk4[0x4];
/* 0x8 */ u16 unk8;
};
inline s32 searchItemInfo(const char* pKey) const
{
s32 nFields = mData->mNumFields;
u32 hash = hashString(pKey);

struct Header {
/* 0x0 */ int unk0;
/* 0x4 */ int unk4;
/* 0x8 */ u32 unk8;
/* 0xC */ u32 unkC;
/* 0x10 */ ItemInfo unk10[];
};
for (int i = 0; i < nFields; ++i) {
if (hash == mData->mItems[i].mHash) {
return i;
}
}

/* 0x4 */ const Header* unk4;
};
return -1;
}

} // namespace Koga
inline const char* getEntryAddress(const JMapData* pData,
const s32 dataOffset,
const int entryIndex) const
{
return reinterpret_cast<const char*>(pData) + dataOffset
+ entryIndex * pData->mEntrySize;
}

inline BOOL getValue(const int entryIndex, const int itemIndex,
s32* pValueOut) const
{
const JMapItem* item = &mData->mItems[itemIndex];
const char* valuePtr
= getEntryAddress(mData, mData->mDataOffset, entryIndex)
+ item->mOffsData;
*pValueOut = *reinterpret_cast<const s32*>(valuePtr);
return TRUE;
}

inline BOOL getValue(const int entryIndex, const int itemIndex,
const char** pValueOut) const
{
const JMapItem* item = &mData->mItems[itemIndex];
*pValueOut = getEntryAddress(mData, mData->mDataOffset, entryIndex)
+ item->mOffsData;
return TRUE;
}

public:
const JMapData* mData;
};
} // namespace Koga
#endif
10 changes: 5 additions & 5 deletions src/GC2D/MovieRumble.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <GC2D/MovieRumble.hpp>
#include <stdio.h>
#include <JSystem/JKernel/JKRFileLoader.hpp>
#include <System/THPRender.hpp>
#include <MarioUtil/RumbleMgr.hpp>
#include <MarioUtil/RumbleType.hpp>
#include <MarioUtil/ToolData.hpp>
#include <MarioUtil/RumbleMgr.hpp>
#include <System/THPRender.hpp>
#include <stdio.h>

// TODO: removeme
static const char* dummyMactorStringValue1 = "\0\0\0\0\0\0\0\0\0\0\0";
Expand All @@ -23,7 +23,7 @@ void TMovieRumble::init(const char* param_1)
unk14 = new Koga::ToolData;
void* bcr = JKRGetResource(acStack_90);
unk14->Attach(bcr);
if (!unk14->GetData())
if (!unk14->dataExists())
unk18 = -1;
else
unk18 = 0;
Expand Down Expand Up @@ -71,7 +71,7 @@ void TMovieRumble::readCurInfo()
{
int group = unk18;

if (isValid() && group < unk14->GetGroupCount()) {
if (isValid() && unk14->isIndexValid(group)) {
Koga::ToolData* toolData = unk14;
toolData->GetValue(group, "start_frame", unk1C);
toolData->GetValue(group, "end_frame", unk20);
Expand Down
2 changes: 1 addition & 1 deletion src/MarioUtil/RumbleData.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <macros.h>
#include <MarioUtil/RumbleMgr.hpp>
#include <macros.h>

static int rumblePoint_00 = 0x0000000B;

Expand Down
4 changes: 2 additions & 2 deletions src/MarioUtil/RumbleMgr.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <MarioUtil/RumbleMgr.hpp>
#include <MarioUtil/MathUtil.hpp>
#include <System/Application.hpp>
#include <MarioUtil/RumbleMgr.hpp>
#include <Player/MarioAccess.hpp>
#include <System/Application.hpp>

int RumbleMgr::mMotorCountLimit = 900;
u16 RumbleMgr::mMotorTimerPeriod = 80;
Expand Down
90 changes: 22 additions & 68 deletions src/MarioUtil/ToolData.cpp
Original file line number Diff line number Diff line change
@@ -1,80 +1,34 @@
#include <MarioUtil/ToolData.hpp>
#include <types.h>

using namespace Koga;

ToolData::ToolData()
: unk4(nullptr)
{
}
#include <macros.h>

namespace Koga {
ToolData::ToolData() { mData = nullptr; }
ToolData::~ToolData() { }

bool ToolData::Attach(const void* data)
BOOL ToolData::Attach(const void* jmapData)
{
if (!data)
return false;
unk4 = (Header*)data;
return true;
if (!jmapData)
return FALSE;
this->mData = (JMapData*)jmapData;
return TRUE;
}

void ToolData::Detach() { }

u32 ToolData::Hash(const char* str)
BOOL ToolData::GetValue(int entryIndex, const char* key, long& pValueOut) const
{
u32 hash = 0;
for (; *str; ++str)
hash = (hash + (*str << 8)) % 33554393;
return hash;
s32 itemIndex = searchItemInfo(key);
if (itemIndex < 0) {
return FALSE;
}
return getValue(entryIndex, itemIndex, &pValueOut);
}

bool ToolData::GetValue(int, const char*, u32&) const { }

bool ToolData::GetValue(int param_1, const char* param_2, s32& param_3) const
BOOL ToolData::GetValue(int entryIndex, const char* key,
const char*& pValueOut) const
{
int idx = SearchItemInfo(param_2);
if (idx < 0)
return false;
u8* base = (u8*)unk4 + unk4->unk8 + param_1 * unk4->unkC;
u8* ptr = base + unk4->unk10[idx].getUnk8();
param_3 = *(s32*)ptr;
return true;
s32 itemIndex = searchItemInfo(key);
if (itemIndex < 0) {
return FALSE;
}
return getValue(entryIndex, itemIndex, &pValueOut);
}

bool ToolData::GetValue(int, const char*, bool&) const { }

bool ToolData::GetValue(int param_1, const char* param_2,
const char*& param_3) const
{
int idx = SearchItemInfo(param_2);
if (idx < 0)
return false;
u8* base = (u8*)unk4 + unk4->unk8 + param_1 * unk4->unkC;
u8* ptr = base + unk4->unk10[idx].getUnk8();
param_3 = (const char*)ptr;
return true;
}

bool ToolData::GetValue(int, const char*, f32&) const { }

int ToolData::SearchItemInfo(const char* name) const
{
int count = unk4->unk4;
u32 hash = Hash(name);

for (int i = 0; i < count; i++)
if (hash == unk4->unk10[i].unk0)
return i;

return -1;
}

void ToolData::FindElement(int, u32, int) const { }

void ToolData::FindElement(int, s32, int) const { }

void ToolData::FindElement(int, bool, int) const { }

void ToolData::FindElement(int, const char*, int) const { }

void ToolData::FindElement(int, f32, int) const { }
} // namespace Koga