Skip to content

Commit db5cb65

Browse files
committed
iSGSaveFile done and iSGReadLeader close
1 parent 8cd0c05 commit db5cb65

File tree

2 files changed

+213
-9
lines changed

2 files changed

+213
-9
lines changed

include/dolphin/dolphin.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ typedef struct CARDFileInfo
250250
/*0x10*/ u16 iBlock;
251251
} CARDFileInfo;
252252

253+
#define CARD_ATTR_PUBLIC 0x04u
254+
#define CARD_ATTR_NO_COPY 0x08u
255+
#define CARD_ATTR_NO_MOVE 0x10u
256+
#define CARD_ATTR_GLOBAL 0x20u
257+
#define CARD_ATTR_COMPANY 0x40u
258+
253259
#define CARD_RESULT_UNLOCKED 1
254260
#define CARD_RESULT_READY 0
255261
#define CARD_RESULT_BUSY -1
@@ -297,12 +303,15 @@ typedef struct CARDStat
297303
/*0x64*/ u32 offsetIconTlut;
298304
/*0x68*/ u32 offsetData;
299305
} CARDStat;
306+
s32 CARDSetStatus(s32 chan, s32 fileNo, struct CARDStat* stat);
300307
// CARDRead.h
301308
s32 CARDRead(struct CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset);
302309
// CARDOpen.h
303310
s32 CARDFastOpen(s32 chan, s32 fileNo, CARDFileInfo* fileInfo);
304311
s32 CARDOpen(s32 chan, char* fileName, CARDFileInfo* fileInfo);
305312
s32 CARDClose(CARDFileInfo* fileInfo);
313+
// CARDNet
314+
s32 CARDSetAttributes(s32 chan, s32 fileNo, u8 attr);
306315

307316
#ifdef __cplusplus
308317
}

src/SB/Core/gc/isavegame.cpp

Lines changed: 204 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <string.h>
1212
#include <types.h>
1313

14+
// Not 100% on what this does or if it's correctly defined for all cases. Seems to be used for allocation alignment
15+
#define ALIGN_THING(x, n) (n + x - 1 & -x)
16+
1417
// WIP
1518
struct st_ISG_TPL_TEXPALETTE
1619
{
@@ -570,12 +573,206 @@ S32 iSGSetupGameDir(st_ISGSESSION* isgdata, const char* dname, S32 force_iconfix
570573
return 1;
571574
}
572575

576+
static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int param4);
577+
static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA*, const char*, S32, en_ISG_IOMODE, en_ASYNC_OPERR*);
578+
static void iSG_mc_fclose(st_ISG_MEMCARD_DATA*);
579+
static void iSG_mc_fclose(st_ISG_MEMCARD_DATA*, CARDStat*);
580+
static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA*, const char*);
581+
static S32 iSG_mc_fwrite(st_ISG_MEMCARD_DATA*, char*, int);
582+
static S32 iSG_upd_icostat(CARDStat*, CARDStat*);
583+
static void iSG_timestamp(CARDStat*);
584+
S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, char* arg5)
585+
{
586+
void* alloc;
587+
S32 allocsize;
588+
char* icondata;
589+
S32 iconsize;
590+
591+
S32 writeret = 0;
592+
en_ASYNC_OPERR operr = ISG_OPERR_NONE;
593+
CARDStat statA = { 0 };
594+
CARDStat statB = { 0 };
595+
596+
ResetButton::DisableReset();
597+
if (isgdata->slot < 0)
598+
{
599+
isgdata->unk_26c = ISG_OPSTAT_FAILURE;
600+
isgdata->unk_268 = ISG_OPERR_NOCARD;
601+
return 0;
602+
}
603+
604+
st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot];
605+
if (mcdata->unk_12c != 0)
606+
{
607+
isgdata->unk_26c = ISG_OPSTAT_FAILURE;
608+
isgdata->unk_268 = ISG_OPERR_DAMAGE;
609+
return 0;
610+
}
611+
612+
iTRCDisk::CheckDVDAndResetState();
613+
iconsize = iSG_cubeicon_size(isgdata->slot, mcdata->sectorSize);
614+
S32 sectorsize200 = ALIGN_THING(mcdata->sectorSize, 0x200);
615+
iconsize += ALIGN_THING(sectorsize200, n);
616+
617+
allocsize = iconsize + 0x1f;
618+
alloc = xMemPushTemp(allocsize);
619+
memset(alloc, 0, allocsize);
620+
icondata = (char*)((U32)alloc + 0x1f & 0xFFFFFFE0);
621+
622+
memcpy(iSG_bfr_icondata(icondata, &statA, arg5, mcdata->sectorSize), data, n);
623+
iTRCDisk::CheckDVDAndResetState();
624+
625+
if (iSG_mc_fopen(mcdata, fname, iconsize, ISG_IOMODE_WRITE, &operr) != 0)
626+
{
627+
if (iSG_mc_fwrite(mcdata, icondata, iconsize) != 0)
628+
{
629+
writeret = 1;
630+
}
631+
else
632+
{
633+
writeret = 0;
634+
operr = ISG_OPERR_SVWRITE;
635+
}
636+
637+
if (writeret != 0)
638+
{
639+
iSG_upd_icostat(&statA, &mcdata->unk_20);
640+
iSG_timestamp(&mcdata->unk_20);
641+
s32 result;
642+
do
643+
{
644+
result = CARDSetStatus(mcdata->unk_4, mcdata->unk_c.fileNo, &mcdata->unk_20);
645+
} while (result == CARD_RESULT_BUSY);
646+
647+
if (result != CARD_RESULT_READY)
648+
{
649+
writeret = 0;
650+
}
651+
}
652+
653+
if (writeret != 0)
654+
{
655+
s32 result;
656+
do
657+
{
658+
result = CARDSetAttributes(mcdata->unk_4, mcdata->unk_c.fileNo, CARD_ATTR_PUBLIC);
659+
} while (result == CARD_RESULT_BUSY);
660+
}
661+
662+
iSG_mc_fclose(mcdata, &statB);
663+
}
664+
xMemPopTemp(alloc);
665+
666+
if (writeret == 0 && mcdata->unk_12c == 0)
667+
{
668+
iSG_mc_fdel(mcdata, fname);
669+
}
670+
671+
ResetButton::EnableReset();
672+
iTRCDisk::CheckDVDAndResetState();
673+
674+
isgdata->unk_268 = ISG_OPERR_NONE;
675+
if (writeret != 0)
676+
{
677+
isgdata->unk_26c = ISG_OPSTAT_SUCCESS;
678+
}
679+
else
680+
{
681+
isgdata->unk_26c = ISG_OPSTAT_FAILURE;
682+
if (operr != ISG_OPERR_NONE)
683+
{
684+
isgdata->unk_268 = operr;
685+
}
686+
else
687+
{
688+
isgdata->unk_268 = ISG_OPERR_UNKNOWN;
689+
}
690+
}
691+
return writeret;
692+
}
693+
573694
S32 iSGLoadFile(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 async)
574695
{
575696
S32 numBytes = iSGFileSize(isgdata, fname);
576697
return iSGReadLeader(isgdata, fname, databuf, numBytes, async);
577698
}
578699

700+
static S32 iSG_mc_fread(st_ISG_MEMCARD_DATA* mcdata, char*, S32, S32);
701+
S32 iSGReadLeader(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 numbytes, S32 async)
702+
{
703+
en_ASYNC_OPERR operr = ISG_OPERR_NONE;
704+
S32 readret = 0;
705+
void* alloc = NULL;
706+
if (isgdata->slot < 0)
707+
{
708+
isgdata->unk_26c = ISG_OPSTAT_FAILURE;
709+
isgdata->unk_268 = ISG_OPERR_NOCARD;
710+
return 0;
711+
}
712+
st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot];
713+
714+
if (data->unk_12c != 0)
715+
{
716+
isgdata->unk_26c = ISG_OPSTAT_FAILURE;
717+
isgdata->unk_268 = ISG_OPERR_DAMAGE;
718+
return 0;
719+
}
720+
721+
iTRCDisk::CheckDVDAndResetState();
722+
S32 iconsize = iSG_cubeicon_size(data->unk_4, data->sectorSize);
723+
U32 sign = (S32)databuf >> 0x1f;
724+
// /x + (n-1) & -x is the same as Round x up to next n
725+
S32 nearest200 = -data->sectorSize & 0x1ff + data->sectorSize;
726+
// FIXME: I think the code is supposed to check if there is enough room at the end of the existing databuf allocation to use
727+
// and only allocate if not.
728+
void* readbuf;
729+
if (((sign * 0x20 | (int)databuf * 0x8000000 + sign >> 0x1b) != sign) ||
730+
(sign = numbytes, readbuf = databuf, numbytes != (numbytes / nearest200) * nearest200))
731+
{
732+
sign = numbytes + 0x1ffU & 0xfffffe00;
733+
S32 __n = sign + 0x1f;
734+
alloc = (void*)xMemPushTemp(__n);
735+
readbuf = alloc;
736+
memset(alloc, 0, __n);
737+
readbuf = (char*)((int)alloc + 0x1fU & 0xffffffe0);
738+
}
739+
iTRCDisk::CheckDVDAndResetState();
740+
741+
if (iSG_mc_fopen(data, fname, -1, ISG_IOMODE_READ, &operr) != 0)
742+
{
743+
readret = (bool)iSG_mc_fread(data, (char*)readbuf, numbytes, iconsize);
744+
iSG_mc_fclose(data);
745+
}
746+
747+
if (readret == 0 && alloc != NULL)
748+
{
749+
memcpy(databuf, readbuf, numbytes);
750+
}
751+
if (alloc != NULL)
752+
{
753+
xMemPopTemp(alloc);
754+
}
755+
756+
isgdata->unk_268 = ISG_OPERR_NONE;
757+
if (readret != 0)
758+
{
759+
isgdata->unk_26c = ISG_OPSTAT_SUCCESS;
760+
}
761+
else
762+
{
763+
isgdata->unk_26c = ISG_OPSTAT_FAILURE;
764+
if (data->unk_12c != 0)
765+
{
766+
isgdata->unk_268 = ISG_OPERR_DAMAGE;
767+
}
768+
else
769+
{
770+
isgdata->unk_268 = ISG_OPERR_OTHER;
771+
}
772+
}
773+
return readret;
774+
}
775+
579776
en_ASYNC_OPSTAT iSGPollStatus(st_ISGSESSION* isgdata, en_ASYNC_OPCODE* curop, S32 block)
580777
{
581778
return isgdata->unk_26c;
@@ -878,8 +1075,7 @@ static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const cha
8781075
}
8791076
len = iSG_cubeicon_size(mcdata->unk_4, mcdata->sectorSize);
8801077
len = len + param2;
881-
// FIXME: fakematch: x + (n-1) & -x is the same as Round x up to next n
882-
len = -mcdata->sectorSize & len + mcdata->sectorSize - 1;
1078+
len = ALIGN_THING(mcdata->sectorSize, len);
8831079

8841080
do
8851081
{
@@ -948,8 +1144,6 @@ static S32 iSG_mc_settgt(st_ISG_MEMCARD_DATA* mcdata, S32 slot)
9481144
return mcdata->unk_0 != 0 ? 1 : 0;
9491145
}
9501146

951-
static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA*, const char*, int, en_ISG_IOMODE, en_ASYNC_OPERR*);
952-
static void iSG_mc_fclose(st_ISG_MEMCARD_DATA*);
9531147
static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* dpath)
9541148
{
9551149
S32 rc = 0;
@@ -1007,7 +1201,6 @@ static S32 iSG_curKosher(CARDStat* stat, CARDFileInfo* info)
10071201

10081202
return rc;
10091203
}
1010-
static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA*, const char*);
10111204
static S32 iSG_fileKosher(st_ISG_MEMCARD_DATA* mcdata, const char* param2, int param3, int* param4)
10121205
{
10131206
S32 rc = 0;
@@ -1130,9 +1323,11 @@ static S32 iSG_cubeicon_size(S32 slot, S32 param2)
11301323
return -1;
11311324
}
11321325

1133-
// FIXME: fakematch: x + (n-1) & -x is the same as Round x up to next n
1134-
S32 t = (param2 + 0x1ffU) & -param2;
1135-
return -t & (t + (sizeof(IconData) - 1));
1326+
S32 t = ALIGN_THING(param2, 0x200);
1327+
1328+
// FIXME: Macro not quite right
1329+
// return ALIGN_THING(t, sizeof(IconData));
1330+
return -t & sizeof(IconData) + t - 1;
11361331
}
11371332

11381333
static S32 iSG_chk_icondata()
@@ -1202,7 +1397,7 @@ static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int pa
12021397

12031398
memcpy(param1, &data, sizeof(data));
12041399

1205-
S32 t = param4 + 0x1ff & -param4;
1400+
S32 t = ALIGN_THING(param4, 0x1ff);
12061401
return param1 + (t + (sizeof(IconData) - 1) & -t);
12071402
}
12081403

0 commit comments

Comments
 (0)