mirror of
https://github.com/rvtr/TDT.git
synced 2025-10-31 13:51:07 -04:00
Fix save file FAT header generation
This commit is contained in:
parent
baba3783f4
commit
db69aca1b4
154
arm9/src/sav.c
154
arm9/src/sav.c
@ -2,51 +2,7 @@
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
static u32 _getClusterSize(u32 sizebytes)
|
||||
{
|
||||
if (sizebytes < 573440)
|
||||
return 512;
|
||||
|
||||
else if (sizebytes < 5472256)
|
||||
return 2048;
|
||||
|
||||
else if (sizebytes < 17301504)
|
||||
return 4096;
|
||||
|
||||
else
|
||||
return 2048;
|
||||
}
|
||||
|
||||
static u16 _getMaxFiles(u32 sizebytes)
|
||||
{
|
||||
if (sizebytes < 573440)
|
||||
return 16;
|
||||
|
||||
else
|
||||
return 256;
|
||||
}
|
||||
|
||||
//wip
|
||||
static u16 _getFatz(u32 sizebytes)
|
||||
{
|
||||
if (sizebytes <= 0x4000) //16 kb
|
||||
return 1;
|
||||
|
||||
else if (sizebytes <= 0x200000) //2 mb
|
||||
return 3;
|
||||
|
||||
else
|
||||
return 6;
|
||||
}
|
||||
|
||||
//wip
|
||||
static u16 _getTotSec16(u32 sizebytes, u16 bytesPerSec)
|
||||
{
|
||||
if (sizebytes == 0x4000) //16 kb
|
||||
return 27;
|
||||
|
||||
return sizebytes / bytesPerSec;
|
||||
}
|
||||
#define align(v, a) (((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
|
||||
|
||||
bool initFatHeader(FILE* f)
|
||||
{
|
||||
@ -57,61 +13,75 @@ bool initFatHeader(FILE* f)
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 size = ftell(f);
|
||||
|
||||
//based on GodMode9
|
||||
//https://github.com/d0k3/GodMode9/blob/d8d43c14f3317423c677b1c7e0987bcb9bbd7299/arm9/source/game/nds.c#L47-L105
|
||||
const u16 sectorSize = 0x200;
|
||||
|
||||
//fit maximum sectors for the size
|
||||
const u16 maxSectors = size / sectorSize;
|
||||
u16 sectorCount = 1;
|
||||
u16 secPerTrk = 1;
|
||||
u16 numHeads = 1;
|
||||
u16 sectorCountNext = 0;
|
||||
while (sectorCountNext <= maxSectors)
|
||||
{
|
||||
sectorCountNext = secPerTrk * (numHeads + 1) * (numHeads + 1);
|
||||
if (sectorCountNext <= maxSectors)
|
||||
{
|
||||
numHeads++;
|
||||
sectorCount = sectorCountNext;
|
||||
|
||||
secPerTrk++;
|
||||
sectorCountNext = secPerTrk * numHeads * numHeads;
|
||||
if (sectorCountNext <= maxSectors)
|
||||
{
|
||||
sectorCount = sectorCountNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
sectorCountNext = (secPerTrk + 1) * numHeads * numHeads;
|
||||
if (sectorCountNext <= maxSectors)
|
||||
{
|
||||
secPerTrk++;
|
||||
sectorCount = sectorCountNext;
|
||||
}
|
||||
|
||||
u8 secPerCluster = (sectorCount > (8 << 10)) ? 8 : (sectorCount > (1 << 10) ? 4 : 1);
|
||||
|
||||
u16 rootEntryCount = size < 0x8C000 ? 0x20 : 0x200;
|
||||
|
||||
u16 totalClusters = align(sectorCount, secPerCluster) / secPerCluster;
|
||||
u32 fatBytes = (align(totalClusters, 2) / 2) * 3; // 2 sectors -> 3 byte
|
||||
u16 fatSize = align(fatBytes, sectorSize) / sectorSize;
|
||||
|
||||
|
||||
FATHeader* h = (FATHeader*)malloc(sizeof(FATHeader));
|
||||
|
||||
h->BS_JmpBoot[0] = 0xE9;
|
||||
h->BS_JmpBoot[1] = 0;
|
||||
h->BS_JmpBoot[2] = 0;
|
||||
|
||||
h->BS_OEMName[0] = 'M';
|
||||
h->BS_OEMName[1] = 'S';
|
||||
h->BS_OEMName[2] = 'W';
|
||||
h->BS_OEMName[3] = 'I';
|
||||
h->BS_OEMName[4] = 'N';
|
||||
h->BS_OEMName[5] = '4';
|
||||
h->BS_OEMName[6] = '.';
|
||||
h->BS_OEMName[7] = '1';
|
||||
memcpy(h->BS_OEMName, "MSWIN4.1", 8);
|
||||
|
||||
h->BPB_BytesPerSec = 512;
|
||||
h->BPB_SecPerClus = _getClusterSize(size) / h->BPB_BytesPerSec;
|
||||
h->BPB_RsvdSecCnt = 1;
|
||||
h->BPB_NumFATs = 2;
|
||||
h->BPB_RootEntCnt = _getMaxFiles(size) * 2;
|
||||
h->BPB_TotSec16 = _getTotSec16(size, h->BPB_BytesPerSec); //
|
||||
h->BPB_Media = 0xF8;
|
||||
h->BPB_FATSz16 = _getFatz(size); //
|
||||
h->BPB_SecPerTrk = 0;
|
||||
h->BPB_NumHeads = 0;
|
||||
h->BPB_HiddSec = 0;
|
||||
h->BPB_TotSec32 = 0;
|
||||
h->BS_DrvNum = 0x07;
|
||||
h->BS_Reserved1 = 0;
|
||||
h->BPB_BytesPerSec = sectorSize;
|
||||
h->BPB_SecPerClus = secPerCluster;
|
||||
h->BPB_RsvdSecCnt = 0x0001;
|
||||
h->BPB_NumFATs = 0x02;
|
||||
h->BPB_RootEntCnt = rootEntryCount;
|
||||
h->BPB_TotSec16 = sectorCount;
|
||||
h->BPB_Media = 0xF8; // "hard drive"
|
||||
h->BPB_FATSz16 = fatSize;
|
||||
h->BPB_SecPerTrk = secPerTrk;
|
||||
h->BPB_NumHeads = numHeads;
|
||||
h->BPB_HiddSec = 0x00000000;
|
||||
h->BPB_TotSec32 = 0x00000000;
|
||||
h->BS_DrvNum = 0x05;
|
||||
h->BS_Reserved1 = 0x00;
|
||||
h->BS_BootSig = 0x29;
|
||||
h->BS_VolID = 305419896;
|
||||
|
||||
h->BS_VolLab[0] = 'V';
|
||||
h->BS_VolLab[1] = 'O';
|
||||
h->BS_VolLab[2] = 'L';
|
||||
h->BS_VolLab[3] = 'U';
|
||||
h->BS_VolLab[4] = 'M';
|
||||
h->BS_VolLab[5] = 'E';
|
||||
h->BS_VolLab[6] = 'L';
|
||||
h->BS_VolLab[7] = 'A';
|
||||
h->BS_VolLab[8] = 'B';
|
||||
h->BS_VolLab[9] = 'E';
|
||||
h->BS_VolLab[10] = 'L';
|
||||
|
||||
h->BS_FilSysType[0] = 'F';
|
||||
h->BS_FilSysType[1] = 'A';
|
||||
h->BS_FilSysType[2] = 'T';
|
||||
h->BS_FilSysType[3] = '1';
|
||||
h->BS_FilSysType[4] = '2';
|
||||
h->BS_FilSysType[5] = ' ';
|
||||
h->BS_FilSysType[6] = ' ';
|
||||
h->BS_FilSysType[7] = ' ';
|
||||
|
||||
memset(h->BS_BootCode, 0, 448);
|
||||
|
||||
h->BS_VolID = 0x12345678;
|
||||
memcpy(h->BS_VolLab, "VOLUMELABEL", 11);
|
||||
memcpy(h->BS_FilSysType,"FAT12 ", 8);
|
||||
memset(h->BS_BootCode, 0, sizeof(h->BS_BootCode));
|
||||
h->BS_BootSign = 0xAA55;
|
||||
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user