More iSG memcard stuff (#364)

This commit is contained in:
Steven Casper 2024-09-05 09:01:52 -04:00 committed by GitHub
parent 03c006619f
commit 35c306b277
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 517 additions and 44 deletions

View File

@ -9,6 +9,7 @@ extern "C" {
void* memset(void*, int, size_t); void* memset(void*, int, size_t);
void* memcpy(void*, const void*, size_t); void* memcpy(void*, const void*, size_t);
int memcmp(const void* ptr1, const void* ptr2, size_t num);
size_t strlen(const char*); size_t strlen(const char*);
char* strcpy(char* dest, const char* source); char* strcpy(char* dest, const char* source);
char* strncpy(char* dest, const char* source, size_t n); char* strncpy(char* dest, const char* source, size_t n);

View File

@ -167,26 +167,25 @@ typedef struct OSContext
f64 psf[32]; f64 psf[32];
} OSContext; } OSContext;
#define PAD_MAX_CONTROLLERS 4 #define PAD_MAX_CONTROLLERS 4
#define PAD_BUTTON_LEFT 0x0001 #define PAD_BUTTON_LEFT 0x0001
#define PAD_BUTTON_RIGHT 0x0002 #define PAD_BUTTON_RIGHT 0x0002
#define PAD_BUTTON_DOWN 0x0004 #define PAD_BUTTON_DOWN 0x0004
#define PAD_BUTTON_UP 0x0008 #define PAD_BUTTON_UP 0x0008
#define PAD_TRIGGER_Z 0x0010 #define PAD_TRIGGER_Z 0x0010
#define PAD_TRIGGER_R 0x0020 #define PAD_TRIGGER_R 0x0020
#define PAD_TRIGGER_L 0x0040 #define PAD_TRIGGER_L 0x0040
#define PAD_BUTTON_A 0x0100 #define PAD_BUTTON_A 0x0100
#define PAD_BUTTON_B 0x0200 #define PAD_BUTTON_B 0x0200
#define PAD_BUTTON_X 0x0400 #define PAD_BUTTON_X 0x0400
#define PAD_BUTTON_Y 0x0800 #define PAD_BUTTON_Y 0x0800
#define PAD_BUTTON_START 0x1000 #define PAD_BUTTON_START 0x1000
#define PAD_ERR_NONE 0 #define PAD_ERR_NONE 0
#define PAD_ERR_NO_CONTROLLER -1 #define PAD_ERR_NO_CONTROLLER -1
#define PAD_ERR_NOT_READY -2 #define PAD_ERR_NOT_READY -2
#define PAD_ERR_TRANSFER -3 #define PAD_ERR_TRANSFER -3
typedef struct PADStatus typedef struct PADStatus
{ {
@ -238,6 +237,19 @@ void AXFreeVoice(_AXVPB*);
void OSSetSoundMode(u32 mode); void OSSetSoundMode(u32 mode);
void VIWaitForRetrace(); void VIWaitForRetrace();
#define CARD_FILENAME_MAX 32
#define CARD_MAX_FILE 127
#define CARD_ICON_MAX 8
typedef struct CARDFileInfo
{
/*0x00*/ s32 chan;
/*0x04*/ s32 fileNo;
/*0x08*/ s32 offset;
/*0x0C*/ s32 length;
/*0x10*/ u16 iBlock;
} CARDFileInfo;
#define CARD_RESULT_UNLOCKED 1 #define CARD_RESULT_UNLOCKED 1
#define CARD_RESULT_READY 0 #define CARD_RESULT_READY 0
#define CARD_RESULT_BUSY -1 #define CARD_RESULT_BUSY -1
@ -256,9 +268,37 @@ void VIWaitForRetrace();
#define CARD_RESULT_CANCELED -14 #define CARD_RESULT_CANCELED -14
#define CARD_RESULT_FATAL_ERROR -128 #define CARD_RESULT_FATAL_ERROR -128
// CARDBios.h
void CARDInit(void); void CARDInit(void);
s32 CARDUnmount(s32 chan); s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed);
s32 CARDGetEncoding(s32 chan, u16* encode);
s32 CARDGetSectorSize(s32 chan, u32* size);
// CARDMount.h
s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize); s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize);
s32 CARDUnmount(s32 chan);
// CARDCheck.h
s32 CARDCheckEx(s32 chan, s32* xferBytes);
// CARDStat.h
typedef struct CARDStat
{
/*0x00*/ char fileName[CARD_FILENAME_MAX];
/*0x20*/ u32 length;
/*0x24*/ u32 time;
/*0x28*/ u8 gameName[4];
/*0x2C*/ u8 company[2];
/*0x2E*/ u8 bannerFormat;
/*0x30*/ u32 iconAddr;
/*0x34*/ u16 iconFormat;
/*0x36*/ u16 iconSpeed;
/*0x38*/ u32 commentAddr;
/*0x3C*/ u32 offsetBanner;
/*0x40*/ u32 offsetBannerTlut;
/*0x44*/ u32 offsetIcon[CARD_ICON_MAX];
/*0x64*/ u32 offsetIconTlut;
/*0x68*/ u32 offsetData;
} CARDStat;
// CARDRead.h
s32 CARDRead(struct CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,6 +1,9 @@
#include "isavegame.h" #include "isavegame.h"
#include "xMemMgr.h"
#include "iFile.h" #include "iFile.h"
#include "iSystem.h"
#include "iTRC.h" #include "iTRC.h"
#include <dolphin.h> #include <dolphin.h>
@ -197,6 +200,449 @@ static S32 iSG_mc_exists(S32 slot)
return ret; return ret;
} }
static S32 iSG_mc_tryRepair(st_ISG_MEMCARD_DATA* mcdata)
{
S32 result = 0;
S32 rc = 0;
s32 xferBytes = 0;
if (mcdata->unk_0 == 0)
{
rc = 0;
}
else if (mcdata->unk_12c)
{
rc = 0;
}
else
{
do
{
result = CARDCheckEx(mcdata->unk_4, &xferBytes);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY)
{
rc = 1;
}
else if (result == CARD_RESULT_ENCODING)
{
rc = 1;
}
else
{
if (result != CARD_RESULT_BROKEN)
{
mcdata->unk_12c = 1;
}
rc = 0;
}
}
return rc;
}
static S32 iSG_mc_isformatted(st_ISG_MEMCARD_DATA* mcdata)
{
S32 result = 0;
S32 rc = 0;
s32 xferBytes = 0;
if (mcdata->unk_0 == 0)
{
rc = 0;
}
else if (mcdata->unk_12c)
{
rc = 0;
}
else
{
do
{
result = CARDCheckEx(mcdata->unk_4, &xferBytes);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY)
{
rc = 1;
}
else if (result == CARD_RESULT_BROKEN)
{
rc = 0;
}
else
{
rc = 0;
}
}
return rc;
}
static S32 iSG_mc_isGCcard(st_ISG_MEMCARD_DATA* mcdata, int* param2, int* param3)
{
S32 result = 0;
S32 rc = 0;
s32 xferBytes = 0;
u16 encoding = 0;
s32 memSize = 0;
s32 sectorSize = 0;
if (param2)
{
*param2 = 0;
}
if (param3)
{
*param3 = 0;
}
if (mcdata->unk_0 == 0)
{
return 0;
}
if (mcdata->unk_12c)
{
return 0;
}
do
{
result = CARDProbeEx(mcdata->unk_4, &memSize, &sectorSize);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY)
{
rc = 1;
}
if (rc != 0)
{
do
{
result = CARDCheckEx(mcdata->unk_4, &xferBytes);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY)
{
rc = 1;
}
else if (result == CARD_RESULT_BROKEN)
{
rc = 2;
}
else
{
if (result == CARD_RESULT_ENCODING)
{
rc = 3;
if (param2)
{
*param2 = 1;
}
}
else
{
rc = 0;
if (result == CARD_RESULT_ENCODING && param2)
{
*param2 = 1;
}
if (result == CARD_RESULT_IOERROR && param3)
{
*param3 = 1;
}
}
}
}
if (rc == 1)
{
do
{
result = CARDGetEncoding(mcdata->unk_4, &encoding);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY && encoding && param2)
{
*param2 = 1;
}
}
return rc;
}
static S32 iSG_cubeicon_size(S32 param1, S32 param2);
static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA*, const char*);
// PS2 signature:
// static signed int iSG_isSpaceForFile(class st_ISG_MEMCARD_DATA* mcdata, S32 mcidx, S32 fsize,
// char* dpath, char* fname, S32* bytesNeeded, S32* availOnDisk)
static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const char* param3,
S32* param4, S32* param5, S32* param6)
{
S32 rc = 0;
S32 result = 0;
s32 byteNotUsed = 0;
s32 filesNotUsed = 0;
S32 len;
if (mcdata->unk_0 == 0)
{
return 0;
}
len = iSG_cubeicon_size(mcdata->unk_4, mcdata->sectorSize);
len = len + param2;
// FIXME: fakematch: x + (n-1) & -x is the same as Round x up to next n
len = -mcdata->sectorSize & len + mcdata->sectorSize - 1;
do
{
result = CARDFreeBlocks(mcdata->unk_4, &byteNotUsed, &filesNotUsed);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY)
{
if (param5)
{
*param5 = byteNotUsed / mcdata->sectorSize;
}
if (param4)
{
*param4 = len / mcdata->sectorSize;
}
}
else
{
return 0;
}
if (param6)
{
*param6 = 1;
}
if (iSG_get_finfo(mcdata, param3))
{
if (param6)
{
*param6 = *param6 - 1 & ~(*param6 - 1 >> 0x1f); // FIXME: Fakematch
}
if (len <= mcdata->unk_b0.length + byteNotUsed)
{
rc = 1;
}
}
else
{
if (len <= byteNotUsed && filesNotUsed > 0)
{
rc = 1;
}
}
return rc;
}
static S32 iSG_mc_mount(S32 slot);
static bool iSG_mc_settgt(st_ISG_MEMCARD_DATA* mcdata, S32 slot)
{
if (iSG_mc_mount(slot))
{
mcdata->unk_0 = 1;
mcdata->unk_4 = slot;
iSG_mc_tryRepair(mcdata);
CARDGetSectorSize(slot, (u32*)&mcdata->sectorSize);
}
else
{
mcdata->unk_0 = 0;
}
return mcdata->unk_0 != 0;
}
static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA*, const char*, int, en_ISG_IOMODE, en_ASYNC_OPERR*);
static void iSG_mc_fclose(st_ISG_MEMCARD_DATA*);
static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* param2)
{
S32 rc = 0;
en_ASYNC_OPERR operr = ISG_OPERR_NONE;
if (iSG_mc_fopen(mcdata, param2, -1, ISG_IOMODE_READ, &operr))
{
rc = 1;
memcpy(&mcdata->unk_b0, &mcdata->unk_20, sizeof(CARDStat));
memcpy(&mcdata->unk_9c, &mcdata->unk_c, sizeof(CARDFileInfo));
iSG_mc_fclose(mcdata);
}
return rc;
}
static S32 iSG_curKosher(CARDStat* stat, CARDFileInfo* info)
{
S32 rc = 1;
if ((stat->iconAddr < 1 || stat->iconAddr > 0x7fffffff) &&
(stat->commentAddr < 1 || stat->commentAddr > 0x7fffffff))
{
rc = 0;
}
else
{
char stuff[0x200] = { 0 };
sprintf(stuff, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan");
void* alloc = xMemPushTemp(0x5e00 + 0x1f);
// align buf address to 32 bytes
char* buf = (char*)((U32)alloc + 0x1f & ~0x1f);
S32 result;
do
{
result = CARDRead(info, buf, 0x5e00, 0);
} while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY)
{
if (memcmp(buf + 0x5a40, stuff, strlen(stuff) - 1))
{
rc = 0;
}
if (memcmp(buf, "Battle for Bikini Bottom", strlen("Battle for Bikini Bottom") - 1))
{
rc = 0;
}
}
xMemPopTemp(alloc);
}
return rc;
}
static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA*, const char*);
static S32 iSG_fileKosher(st_ISG_MEMCARD_DATA* mcdata, const char* param2, int param3, int* param4)
{
S32 rc = 0;
en_ASYNC_OPERR operr = ISG_OPERR_NONE;
if (param4)
{
*param4 = 0;
}
if (iSG_mc_fopen(mcdata, param2, -1, ISG_IOMODE_READ, &operr) == 0)
{
return -1;
}
S32 ret = iSG_curKosher(&mcdata->unk_20, &mcdata->unk_c);
iSG_mc_fclose(mcdata);
if (ret == 0)
{
rc = 0;
if (param3 && iSG_mc_fdel(mcdata, param2) && param4)
{
*param4 = 1;
}
}
else
{
rc = 1;
}
return rc;
}
static S32 iSG_get_fsize(st_ISG_MEMCARD_DATA* mcdata, const char* param2)
{
S32 rc = -1;
if (iSG_get_finfo(mcdata, param2))
{
rc = mcdata->unk_b0.length;
}
if (rc < 0)
{
rc = -1;
}
return rc;
}
static S32 iSG_get_fmoddate(st_ISG_MEMCARD_DATA* mcdata, const char* fname, int* sec, int* min,
int* hr, int* mon, int* day, int* yr)
{
S32 rc = 1;
OSCalendarTime time = { 0 };
if (iSG_get_finfo(mcdata, fname) == 0)
{
rc = 0;
}
else
{
// FIXME: This first param isn't right, can't decipher the 64 bit math
OSTicksToCalendarTime((u64)mcdata->unk_b0.time * (u64)(GET_BUS_FREQUENCY() / 4), &time);
if (sec)
{
*sec = time.sec;
}
if (min)
{
*min = time.min;
}
if (hr)
{
*hr = time.hour;
}
if (mon)
{
*mon = time.mon + 1;
}
if (day)
{
*day = time.mday;
}
if (mon)
{
*mon = time.mon + 1;
}
if (day)
{
*day = time.mday;
}
if (yr)
{
*yr = time.year;
}
}
return rc;
}
static void iSG_timestamp(CARDStat*)
{
}
static S32 iSG_cubeicon_size(S32 slot, S32 param2)
{
if ((U32)slot > 1)
{
return -1;
}
// FIXME: fakematch: x + (n-1) & -x is the same as Round x up to next n
S32 t = (param2 + 0x1ffU) & -param2;
return -t & (t + 0x5c3f);
}
static S32 iSG_chk_icondata() static S32 iSG_chk_icondata()
{ {
return 1; return 1;
@ -225,25 +671,24 @@ static void iSG_discard_icondata()
static S32 iSG_mc_unmount(S32 slot) static S32 iSG_mc_unmount(S32 slot)
{ {
S32 ret = 0; S32 rc = 0;
s32 chan = slot;
S32 result; S32 result;
do do
{ {
result = CARDUnmount(chan); result = CARDUnmount(slot);
} while (result == CARD_RESULT_BUSY); } while (result == CARD_RESULT_BUSY);
if (result == CARD_RESULT_READY) if (result == CARD_RESULT_READY)
{ {
ret = 1; rc = 1;
} }
else if (result == CARD_RESULT_NOCARD) else if (result == CARD_RESULT_NOCARD)
{ {
ret = 1; rc = 1;
} }
return ret; return rc;
} }
static void iSG_cb_asyndone(long, long) static void iSG_cb_asyndone(long, long)

View File

@ -3,28 +3,7 @@
#include <types.h> #include <types.h>
struct sceMcStDateTime #include <dolphin.h>
{
U8 Resv2;
U8 Sec;
U8 Min;
U8 Hour;
U8 Day;
U8 Month;
U16 Year;
};
struct sceMcTblGetDir
{
sceMcStDateTime _Create;
sceMcStDateTime _Modify;
U32 FileSizeByte;
U16 AttrFile;
U16 Reserve1;
U32 Reserve2;
U32 PdaAplNo;
U8 EntryName[32];
};
enum en_ISG_IOMODE enum en_ISG_IOMODE
{ {
@ -131,7 +110,15 @@ public:
struct st_ISG_MEMCARD_DATA struct st_ISG_MEMCARD_DATA
{ {
S32 unk_0; S32 unk_0;
S32 unk_pad[75]; S32 unk_4;
S32 sectorSize;
CARDFileInfo unk_c;
CARDStat unk_20;
S32 unk_pad5[4];
CARDFileInfo unk_9c;
CARDStat unk_b0;
S32 unk_pad6[4];
S32 unk_12c;
}; };
#define ISG_NUM_SLOTS 2 #define ISG_NUM_SLOTS 2