Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions include/Megamix/Commands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Megamix{
InputCheck = 0x200,
VersionNumber = 0x201,
LanguageCheck = 0x202,
EndlessSave = 0x205,
MSBTWithNum = 0x206,

DisplayCondvar = 0x300
Expand All @@ -21,6 +22,7 @@ namespace Megamix{
void versionCheck(CTickflow* self, u32 arg0, u32* args);
void languageCheck(CTickflow* self, u32 arg0, u32* args);
void displayCondvar(CTickflow* self, u32 arg0, u32* args);
void endlessSave(CTickflow* self, u32 arg0, u32* args);
void msbtWithNum(CTickflow* self, u32 arg0, u32* args);
}

Expand Down
27 changes: 24 additions & 3 deletions include/Megamix/Region.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "Megamix/Error.hpp"
#include "Megamix/Types.hpp"

extern u8 region;
extern u8 region; //TODO: remove

namespace Megamix {
struct GameInterface {
Expand Down Expand Up @@ -61,9 +61,28 @@ namespace Megamix {

// some common globals / managers

typedef u16 (*GetGateScoreSignature) (CSaveData* self, GateGameIndex index, s32 file);
typedef void (*SetGateScoreSignature) (CSaveData* self, GateGameIndex index, u16 score, s32 file);

CSaveData** saveData;
GetGateScoreSignature getGateScore;
SetGateScoreSignature setGateScore;

CInputManager** inputManager;
CFileManager** fileManager;
UnkStruct0054ef10** unk0054ef10;

typedef void (*SaveDataSignature) (CSaveManager*);

CSaveManager** saveManager;
SaveDataSignature saveGame;

CBlackBarManager** blackbarLayout;

// endless score saving

typedef bool (*IsGateGameValidSignature)(GateGameIndex slot);
IsGateGameValidSignature isGateGameValid;

// tickflow commands
u32 tickflowCommandsHook;
Expand All @@ -72,7 +91,6 @@ namespace Megamix {

// MSBT printf

CBlackBarManager** blackbarLayout;
typedef int (*SWPrintfSignature) (char16_t* buffer, size_t size, const char16_t* format, ...);
typedef u32 (*SetTextBoxStringSignature) (Megamix::TextBox *, const char16_t *, u32);

Expand Down Expand Up @@ -131,9 +149,12 @@ namespace Megamix {
inline CSaveData* gSaveData() { return *pointers->saveData; }
inline CInputManager* gInputManager() { return *pointers->inputManager; }
inline CFileManager* gFileManager() { return *pointers->fileManager; }

inline UnkStruct0054ef10* D_0054ef10() { return *pointers->unk0054ef10; }
inline CSaveManager* gSaveManager() { return *pointers->saveManager; }
inline CBlackBarManager* gBlackbarLayout() { return *pointers->blackbarLayout; }

inline bool isGateGameValid(GateGameIndex slot) { return pointers->isGateGameValid(slot); }

// see cpp file for impl details of this - tldr it's not good
extern int swprintf(char16_t* buffer, size_t size, const char16_t* format, ...);

Expand Down
66 changes: 65 additions & 1 deletion include/Megamix/Types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,58 @@ namespace Megamix {
//Save File
//-----------------


enum class GateGameIndex: u8 {
Game = 0xC,
AgbVirus = 0,
NtrCoinToss = 4,
RvlSword = 8,
CtrChicken = 0xC,

Difficulty = 0x3,
Easy = 0,
Medium = 1,
Hard = 2,
Endless = 3,

AgbVirusEasy = AgbVirus | Easy,
AgbVirusMedium = AgbVirus | Medium,
AgbVirusHard = AgbVirus | Hard,
AgbVirusEndless = AgbVirus | Endless,
NtrCoinTossEasy = NtrCoinToss | Easy,
NtrCoinTossMedium = NtrCoinToss | Medium,
NtrCoinTossHard = NtrCoinToss | Hard,
NtrCoinTossEndless = NtrCoinToss | Endless,
RvlSwordEasy = RvlSword | Easy,
RvlSwordMedium = RvlSword | Medium,
RvlSwordHard = RvlSword | Hard,
RvlSwordEndless = RvlSword | Endless,
CtrChickenEasy = CtrChicken | Easy,
CtrChickenMedium = CtrChicken | Medium,
CtrChickenHard = CtrChicken | Hard,
CtrChickenEndless = CtrChicken | Endless,

Invalid = 0x11,
};

inline GateGameIndex operator&(GateGameIndex lhs, GateGameIndex rhs) {
return (GateGameIndex)((u8)lhs & (u8)rhs);
}

enum class GateGameRank : u8 {
Unplayed = 0,
Failed = 1,
Beaten = 2,
Invalid = 4,
};

// Not really sure what this is, and it's undocumented
struct UnkStruct0054ef10 {
u8 padding[0x4c];
GateGameIndex currentGateSlot;
GateGameRank currentGateState;
};

enum class EGameRank : u8 {
Locked = 0,
Unplayed = 1,
Expand Down Expand Up @@ -371,6 +423,14 @@ namespace Megamix {
u8 cSaveData_sub1[0x1c20];
struct CSaveFileData fileData[4];
u32 currentFile;

u16 getGateScore(GateGameIndex index, s32 file);
void setGateScore(Megamix::GateGameIndex index, u16 score, s32 file);
};

// TODO
struct CSaveManager {
void saveGame(); // defined in Region
};

//-----------------
Expand Down Expand Up @@ -504,7 +564,7 @@ namespace Megamix {


//-----------------
//File Manager
// File Manager
//-----------------

struct CFileManager {
Expand Down Expand Up @@ -547,6 +607,10 @@ namespace Megamix {
s32 id;
};

//-----------------
// TextBox and its derivates
//-----------------

struct TextBox {
u8 parent[0xa4];
char16_t* textBuf;
Expand Down
22 changes: 22 additions & 0 deletions src/Megamix/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ namespace Megamix {
case LanguageCheck:
languageCheck(self, arg0, args);
break;
case EndlessSave:
endlessSave(self, arg0, args);
break;
case MSBTWithNum:
msbtWithNum(self, arg0, args);
break;
Expand Down Expand Up @@ -107,6 +110,25 @@ namespace Megamix {
}
}

void endlessSave(CTickflow* self, u32 arg0, u32* args) {
using enum Megamix::GateGameIndex;

if (arg0 != 0) return;

// alternatively, load the current slot loaded with the tickflow hook into a global, and use that instead
// that way we can avoid the UB on non-gate slots
GateGameIndex slot = Game::D_0054ef10()->currentGateSlot;
if ((slot & Difficulty) != Endless || !Game::isGateGameValid(slot))
return;

u32 oldScore = Game::gSaveData()->getGateScore(slot, -1);

if (oldScore < self->condvar && self->condvar <= 0xFFFF) {
Game::gSaveData()->setGateScore(slot, self->condvar, -1);
Game::gSaveManager()->saveGame();
}
}

void msbtWithNum(CTickflow* self, u32 arg0, u32* args) {
if (arg0 != 0) return;

Expand Down
70 changes: 63 additions & 7 deletions src/Megamix/Region.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "Megamix/Region.hpp"
#include <3ds.h>
#include <CTRPluginFramework.hpp>

#include "Megamix.hpp"
#include "Megamix/Types.hpp"

#include <expected>

Expand Down Expand Up @@ -46,15 +48,25 @@ namespace Megamix {
.regionBHookPos= 0x11932c,

// TODO: any of these could have been made incompatible by version differences
.saveData= (CSaveData**)GameInterface::UNIMPLEMENTED,
.saveData= (CSaveData**)GameInterface::UNIMPLEMENTED,
.getGateScore = (GameInterface::GetGateScoreSignature)GameInterface::UNIMPLEMENTED,
.setGateScore = (GameInterface::SetGateScoreSignature)GameInterface::UNIMPLEMENTED,

.inputManager= (CInputManager**)GameInterface::UNIMPLEMENTED,
.fileManager= (CFileManager**)GameInterface::UNIMPLEMENTED,
.unk0054ef10 = (UnkStruct0054ef10**)GameInterface::UNIMPLEMENTED,

.saveManager = (CSaveManager**)GameInterface::UNIMPLEMENTED,
.saveGame = (GameInterface::SaveDataSignature)GameInterface::UNIMPLEMENTED,

.blackbarLayout= (CBlackBarManager**)0x526404,

.isGateGameValid= (GameInterface::IsGateGameValidSignature)0x2569d8,

.tickflowCommandsHook= 0x25e054,
.tickflowCommandsCmd0= 0x25e338,
.tickflowCommandsReturn= 0x262eac,

.blackbarLayout= (CBlackBarManager**)0x526404,
.swprintfFunc= (GameInterface::SWPrintfSignature)THUMB_CALL_ADDR(0x100914),
.setTextBoxStringFunc= (GameInterface::SetTextBoxStringSignature)0x3204f8,
};
Expand Down Expand Up @@ -96,14 +108,24 @@ namespace Megamix {
.regionBHookPos= 0x119560,

.saveData= (CSaveData**)0x54d350,
.getGateScore = (GameInterface::GetGateScoreSignature)0x261a6c,
.setGateScore = (GameInterface::SetGateScoreSignature)0x2366c0,

.inputManager= (CInputManager**)0x54eed0,
.fileManager= (CFileManager**)0x54eedc,
.unk0054ef10 = (UnkStruct0054ef10**)0x54ef10,

.saveManager = (CSaveManager**)0x54ef28,
.saveGame = (GameInterface::SaveDataSignature)0x28bf14,

.blackbarLayout= (CBlackBarManager**)0x52f3f8,

.isGateGameValid= (GameInterface::IsGateGameValidSignature)0x255550,

.tickflowCommandsHook= 0x25c3c0,
.tickflowCommandsCmd0= 0x25c6c0,
.tickflowCommandsReturn= 0x2613cc,

.blackbarLayout= (CBlackBarManager**)0x52f3f8,
.swprintfFunc= (GameInterface::SWPrintfSignature)THUMB_CALL_ADDR(0x28a2d0),
.setTextBoxStringFunc= (GameInterface::SetTextBoxStringSignature)0x31fcd8,
};
Expand Down Expand Up @@ -139,15 +161,25 @@ namespace Megamix {
.regionAHookPos= 0x28c070,
.regionBHookPos= 0x119560,

.saveData= (CSaveData**)0x54d448,
.saveData= (CSaveData**)0x54d448,
.getGateScore = (GameInterface::GetGateScoreSignature)0x261a6c,
.setGateScore = (GameInterface::SetGateScoreSignature)0x2366c0,

.inputManager= (CInputManager**)0x54efc8,
.fileManager= (CFileManager**)0x54efd4,
.unk0054ef10 = (UnkStruct0054ef10**)0x54f008,

.saveManager = (CSaveManager**)0x54f020,
.saveGame = (GameInterface::SaveDataSignature)0x28bf14,

.blackbarLayout= (CBlackBarManager**)0x52f3f8,

.isGateGameValid= (GameInterface::IsGateGameValidSignature)0x255550,

.tickflowCommandsHook= 0x25c3c0,
.tickflowCommandsCmd0= 0x25c6c0,
.tickflowCommandsReturn= 0x2613cc,

.blackbarLayout= (CBlackBarManager**)0x52f3f8,
.swprintfFunc= (GameInterface::SWPrintfSignature)THUMB_CALL_ADDR(0x28a2d0),
.setTextBoxStringFunc= (GameInterface::SetTextBoxStringSignature)0x31fcd8,
};
Expand Down Expand Up @@ -188,15 +220,25 @@ namespace Megamix {
.regionAHookPos= 0x28c048,
.regionBHookPos= 0x119560,

.saveData= (CSaveData**)0x54d448,
.saveData= (CSaveData**)0x54d448,
.getGateScore = (GameInterface::GetGateScoreSignature)0x261a44,
.setGateScore = (GameInterface::SetGateScoreSignature)0x236698,

.inputManager= (CInputManager**)0x54efc8,
.fileManager= (CFileManager**)0x54efd4,
.unk0054ef10 = (UnkStruct0054ef10**)0x54f008,

.saveManager = (CSaveManager**)0x54f020,
.saveGame = (GameInterface::SaveDataSignature)0x28beec,

.blackbarLayout= (CBlackBarManager**)0x52f3f8,

.isGateGameValid= (GameInterface::IsGateGameValidSignature)0x255528,

.tickflowCommandsHook= 0x25c398,
.tickflowCommandsCmd0= 0x25c698,
.tickflowCommandsReturn= 0x2613a4,

.blackbarLayout= (CBlackBarManager**)0x52f3f8,
.swprintfFunc= (GameInterface::SWPrintfSignature)THUMB_CALL_ADDR(0x28a2a8),
.setTextBoxStringFunc= (GameInterface::SetTextBoxStringSignature)0x31fcd8,
};
Expand Down Expand Up @@ -274,3 +316,17 @@ extern "C" {
return Megamix::pointers->swprintfFunc;
}
}

// definitions from type stuff cause, lol

void Megamix::CSaveManager::saveGame() {
pointers->saveGame(this);
}

u16 Megamix::CSaveData::getGateScore(Megamix::GateGameIndex index, s32 file) {
return pointers->getGateScore(this, index, file);
}

void Megamix::CSaveData::setGateScore(Megamix::GateGameIndex index, u16 score, s32 file) {
pointers->setGateScore(this, index, score, file);
}
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void ctrpf::PatchProcess(ctrpf::FwkSettings&) {
if (!Megamix::isJP()) {
//TODO: find out how to make the tempo hooks JP-compatible
Megamix::Hooks::TempoHooks();
//TODO: find out how to make the tickflow commands hook JP-compatible
//TODO: find out how to make the tickflow commands hook (and each individual command) JP-compatible
Megamix::Hooks::CommandHook();
}

Expand Down