From 03c006619fa1453ed66b44db481e833d446f34b9 Mon Sep 17 00:00:00 2001 From: Steven Casper Date: Wed, 4 Sep 2024 08:12:32 -0400 Subject: [PATCH] isavegame progress (#363) * Add some memcard stuff to dolphin header * isavegame progress --- include/dolphin/dolphin.h | 23 +++- src/SB/Core/gc/isavegame.cpp | 208 +++++++++++++++++++++++++++++------ src/SB/Core/gc/isavegame.h | 86 ++++++++------- 3 files changed, 245 insertions(+), 72 deletions(-) diff --git a/include/dolphin/dolphin.h b/include/dolphin/dolphin.h index 31e1f184..01a4d64c 100644 --- a/include/dolphin/dolphin.h +++ b/include/dolphin/dolphin.h @@ -236,9 +236,30 @@ void PADReset(u32 mask); void AXQuit(); void AXFreeVoice(_AXVPB*); void OSSetSoundMode(u32 mode); -s32 CARDProbeEx(s32, s32*, s32*); void VIWaitForRetrace(); +#define CARD_RESULT_UNLOCKED 1 +#define CARD_RESULT_READY 0 +#define CARD_RESULT_BUSY -1 +#define CARD_RESULT_WRONGDEVICE -2 +#define CARD_RESULT_NOCARD -3 +#define CARD_RESULT_NOFILE -4 +#define CARD_RESULT_IOERROR -5 +#define CARD_RESULT_BROKEN -6 +#define CARD_RESULT_EXIST -7 +#define CARD_RESULT_NOENT -8 +#define CARD_RESULT_INSSPACE -9 +#define CARD_RESULT_NOPERM -10 +#define CARD_RESULT_LIMIT -11 +#define CARD_RESULT_NAMETOOLONG -12 +#define CARD_RESULT_ENCODING -13 +#define CARD_RESULT_CANCELED -14 +#define CARD_RESULT_FATAL_ERROR -128 + +void CARDInit(void); +s32 CARDUnmount(s32 chan); +s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize); + #ifdef __cplusplus } #endif diff --git a/src/SB/Core/gc/isavegame.cpp b/src/SB/Core/gc/isavegame.cpp index 76052932..7147775f 100644 --- a/src/SB/Core/gc/isavegame.cpp +++ b/src/SB/Core/gc/isavegame.cpp @@ -1,35 +1,52 @@ #include "isavegame.h" -#include -#include -#include - +#include "iFile.h" #include "iTRC.h" -extern char isavegame_strings[]; +#include +#include +#include +#include -extern st_ISGSESSION g_isgdata_MAIN; +// WIP +struct st_ISG_TPL_TEXPALETTE +{ +}; -extern S32 g_isginit; +// .sbss +static volatile S32 g_isginit; +static st_ISG_TPL_TEXPALETTE* g_rawicon; +static st_ISG_TPL_TEXPALETTE* g_rawbanr; +static S32 g_iconsize; +static S32 g_banrsize; +static S8 isMounted; + +// .data +static st_ISGSESSION g_isgdata_MAIN = { 0 }; +static struct +{ + S32 unk_0; + S32 unk_4; + S32 unk_8; +} g_legalSectSize = { 0x2000, 0, -1 }; + +static S32 iSG_start_your_engines(); +static S32 iSG_chk_icondata(); +static S32 iSG_load_icondata(); +static void iSG_discard_icondata(); +static S32 iSG_mc_unmount(S32 slot); -#if 0 S32 iSGStartup() { - S32 i = g_isginit; - - if (g_isginit != 0) + if (g_isginit++ != 0) { - g_isginit = i; - - return i; + return g_isginit; } - g_isginit = i; iSG_start_your_engines(); iSG_load_icondata(); - return i; + return g_isginit; } -#endif S32 iSGShutdown() { @@ -37,15 +54,13 @@ S32 iSGShutdown() return 1; } -// WIP char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx) { - static S32 rotate = 0; - static char rotatebuf[32][8]; + static volatile S32 rotate = 0; // fakematch?? + static char rotatebuf[8][32] = { 0 }; - char* use_buf = rotatebuf[rotate]; - char* fmt_sd = isavegame_strings; - rotate++; + const char* fmt_sd = "%s%02d"; + char* use_buf = rotatebuf[rotate++]; if (rotate == 8) { rotate = 0; @@ -62,7 +77,7 @@ char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx) } else { - sprintf(use_buf, fmt_sd, isavegame_strings + 7, idx); + sprintf(use_buf, fmt_sd, "SpongeBob", idx); } break; case ISG_NGTYP_GAMEDIR: @@ -74,39 +89,164 @@ char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx) return use_buf; } -#if 0 -// Struct definition is screwed up. st_ISGSESSION* iSGSessionBegin(void* cltdata, void (*chgfunc)(void*, en_CHGCODE), S32 monitor) { iTRCDisk::CheckDVDAndResetState(); memset(&g_isgdata_MAIN, 0, sizeof(st_ISGSESSION)); + g_isgdata_MAIN.unk_260 = -1; g_isgdata_MAIN.chgfunc = chgfunc; g_isgdata_MAIN.cltdata = cltdata; iSG_chk_icondata(); return &g_isgdata_MAIN; } -#endif -#if 0 -// Structs make no sense void iSGSessionEnd(st_ISGSESSION* isgdata) { iTRCDisk::CheckDVDAndResetState(); - for (S32 i = 0; i < 2; i++) + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) { - if (isgdata->mcdata[i].mcport != 0) + if (isgdata->mcdata[i].unk_0) { iSG_mc_unmount(i); - isgdata->mcdata[i].mcport = 0; + isgdata->mcdata[i].unk_0 = 0; } } + memset(isgdata, 0, sizeof(st_ISGSESSION)); } -#endif -void iSG_cb_asyndone(long, long) +static S32 iSG_start_your_engines() +{ + CARDInit(); + return 1; +} + +// Looks equivalent. Can't get variable initializtions to match. +S32 iSG_mcidx2slot(S32 param1, S32* param2, S32* param3) +{ + s32 cardReady[ISG_NUM_SLOTS] = {}; + S32 ret = 0; + S32 idk = 0; + s32 memSize = 0; + s32 sectorSize = 0; + *param2 = -1; + + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + s32 result; + do + { + result = CARDProbeEx(i, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + cardReady[i] = TRUE; + } + } + + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + if (cardReady[i]) + { + if (idk == param1) + { + *param2 = i; + ret = 1; + break; + } + idk++; + } + } + + if (param3) + { + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + param3[i] = cardReady[i]; + } + } + + return ret; +} + +static S32 iSG_mc_exists(S32 slot) +{ + S32 ret = 0; + s32 memSize = 0; + s32 sectorSize = 0; + + if (slot < -1) + { + return 0; + } + + S32 result; + do + { + result = CARDProbeEx(slot, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + + return ret; +} + +static S32 iSG_chk_icondata() +{ + return 1; +} + +void iSG_tpl_unpack(st_ISG_TPL_TEXPALETTE*); +static S32 iSG_load_icondata() +{ + g_rawicon = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCIcon.tpl", NULL, (U32*)g_iconsize); + g_rawbanr = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCBanner.tpl", NULL, (U32*)g_banrsize); + iSG_tpl_unpack(g_rawicon); + iSG_tpl_unpack(g_rawbanr); + + return g_rawicon && g_iconsize && g_rawbanr && g_banrsize ? 1 : 0; +} + +static void iSG_discard_icondata() +{ + OSFreeToHeap(__OSCurrHeap, g_rawicon); + OSFreeToHeap(__OSCurrHeap, g_rawbanr); + g_rawicon = NULL; + g_iconsize = 0; + g_rawbanr = NULL; + g_banrsize = 0; +} + +static S32 iSG_mc_unmount(S32 slot) +{ + S32 ret = 0; + s32 chan = slot; + S32 result; + + do + { + result = CARDUnmount(chan); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + else if (result == CARD_RESULT_NOCARD) + { + ret = 1; + } + + return ret; +} + +static void iSG_cb_asyndone(long, long) { } diff --git a/src/SB/Core/gc/isavegame.h b/src/SB/Core/gc/isavegame.h index 166a44b8..b3c59078 100644 --- a/src/SB/Core/gc/isavegame.h +++ b/src/SB/Core/gc/isavegame.h @@ -94,36 +94,55 @@ enum en_CHGCODE ISG_CHG_GAMELIST }; -struct st_ISG_MEMCARD_DATA -{ - S32 mcport; - S32 mcslot; - S32 mcfp; - en_ISG_IOMODE fmode; - char gamepath[64]; - sceMcTblGetDir finfo; - S32 cur_mcop; - en_ISGMC_ERRSTATUS mcerr; - S32 allow_cache; +/* DWARF Definitions (PS2) + +class st_ISG_MEMCARD_DATA { + // total size: 0x100 +public: + signed int mcport; // offset 0x0, size 0x4 + signed int mcslot; // offset 0x4, size 0x4 + signed int mcfp; // offset 0x8, size 0x4 + enum en_ISG_IOMODE fmode; // offset 0xC, size 0x4 + char gamepath[64]; // offset 0x10, size 0x40 + class sceMcTblGetDir finfo; // offset 0x80, size 0x40 + signed int cur_mcop; // offset 0xC0, size 0x4 + enum en_ISGMC_ERRSTATUS mcerr; // offset 0xC4, size 0x4 + signed int allow_cache; // offset 0xC8, size 0x4 }; -// This struct is definitely wrong -// Size should be 0x280 +class st_ISGSESSION { + // total size: 0x9C +public: + class st_ISG_MEMCARD_DATA * mcdata; // offset 0x0, size 0x4 + char gameroot[64]; // offset 0x4, size 0x40 + char gamedir[64]; // offset 0x44, size 0x40 + enum en_ASYNC_OPCODE as_curop; // offset 0x84, size 0x4 + enum en_ASYNC_OPSTAT as_opstat; // offset 0x88, size 0x4 + enum en_ASYNC_OPERR as_operr; // offset 0x8C, size 0x4 + void * cltdata; // offset 0x90, size 0x4 + enum en_CHGCODE chgcode; // offset 0x94, size 0x4 + void (* chgfunc)(void *, enum en_CHGCODE); // offset 0x98, size 0x4 +}; + + +*/ + +// Size should be 0x130 +struct st_ISG_MEMCARD_DATA +{ + S32 unk_0; + S32 unk_pad[75]; +}; + +#define ISG_NUM_SLOTS 2 struct st_ISGSESSION { - // This is just a pointer in the DWARF - // I've changed it because of iSGSessionEnd, - // but there might just be another field before this instead. - st_ISG_MEMCARD_DATA mcdata[2]; - - char gameroot[64]; - char gamedir[64]; - en_ASYNC_OPCODE as_curop; - en_ASYNC_OPSTAT as_opstat; - en_ASYNC_OPERR as_operr; - void* cltdata; - en_CHGCODE chgcode; - void (*chgfunc)(void*, en_CHGCODE); + st_ISG_MEMCARD_DATA mcdata[ISG_NUM_SLOTS]; + S32 unk_260; + S32 unk_264[4]; + void (*chgfunc)(void*, en_CHGCODE); // 0x274 + void* cltdata; // 0x278 + S32 unk_27c; }; enum en_NAMEGEN_TYPE @@ -145,10 +164,9 @@ U32 iSGTgtState(st_ISGSESSION* isgdata, S32 tgtidx, const char* dpath); S32 iSGTgtFormat(st_ISGSESSION* isgdata, S32 tgtidx, S32 async, S32* canRecover); S32 iSGTgtSetActive(st_ISGSESSION* isgdata, S32 tgtidx); S32 iSGTgtHaveRoom(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, - const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile); + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile); S32 iSGTgtHaveRoomStartup(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, - const char* fname, S32* bytesNeeded, S32* availOnDisk, - S32* needFile); + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile); U8 iSGCheckMemoryCard(st_ISGSESSION* isgdata, S32 index); S32 iSGFileSize(st_ISGSESSION* isgdata, const char* fname); char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname); @@ -157,23 +175,17 @@ char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname, S32* sec, S32* m en_ASYNC_OPSTAT iSGPollStatus(st_ISGSESSION* isgdata, en_ASYNC_OPCODE* curop, S32 block); en_ASYNC_OPERR iSGOpError(st_ISGSESSION* isgdata, char* errmsg); S32 iSGReadLeader(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 numbytes, - S32 async); + S32 async); S32 iSGSelectGameDir(st_ISGSESSION* isgdata, const char* dname); void iSGMakeTimeStamp(char* str); S32 iSGSetupGameDir(st_ISGSESSION* isgdata, const char* dname, S32 force_iconfix); -S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, - char*); +S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, char*); S32 iSGLoadFile(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 async); void iSGAutoSave_Startup(); st_ISGSESSION* iSGAutoSave_Connect(S32 idx_target, void* cltdata, void (*chg)(void*, en_CHGCODE)); void iSGAutoSave_Disconnect(st_ISGSESSION* isg); S32 iSGAutoSave_Monitor(st_ISGSESSION* isg, S32 idx_target); S32 iSGCheckForWrongDevice(); -S32 iSG_start_your_engines(); -S32 iSG_load_icondata(); -void iSG_discard_icondata(); -S32 iSG_chk_icondata(); -S32 iSG_mc_unmount(S32 slot); S32 iSGCheckForCorruptFiles(st_ISGSESSION*, char files[][64]); #endif