Skip to content

Commit

Permalink
Implemented support for out-of-bounds rom reads. Fixes #138, fixes #113
Browse files Browse the repository at this point in the history
  • Loading branch information
Gericom committed Apr 7, 2024
1 parent 2f0609f commit d1efd9b
Showing 1 changed file with 44 additions and 14 deletions.
58 changes: 44 additions & 14 deletions code/core/arm9/source/SdCache/SdCache.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "common.h"
#include <string.h>
#include "Fat/ff.h"
#include "Fat/diskio.h"
#include "Fat/FsIpc.h"
Expand Down Expand Up @@ -93,16 +94,35 @@ static u32 getSdSectorOfRomBlock(u32 romBlock)
return sector;
}

static void fillOutOfBoundsCacheBlock(u32 romBlock, u32 cacheBlock)
{
u32 romSize = f_size(&gFile);
u32 powerOf2RomSize = romSize < 0x100000 ? 0x100000 : (1 << (32 - __builtin_clz(romSize - 1)));
if (romBlock * SDC_BLOCK_SIZE < powerOf2RomSize)
{
memset(&sdc_cache[cacheBlock][0], 0xFF, SDC_BLOCK_SIZE);
}
else
{
for (u32 i = 0; i < SDC_BLOCK_SIZE; i += 4)
{
u32 address = romBlock * SDC_BLOCK_SIZE + i;
u32 oobValue = (address >> 1) & 0xFFFF;
*(u32 *)&sdc_cache[cacheBlock][i] = oobValue | ((oobValue + 1) << 16);
}
}

sCacheBlockToRomBlock[cacheBlock] = romBlock;
sdc_romBlockToCacheBlock[romBlock] = &sdc_cache[cacheBlock][0];
dc_drainWriteBuffer();
}

/// @brief Loads a rom block to the given buffer.
/// @param romBlock Rom block index to load.
/// @param dst The destination buffer.
static void* loadRomBlock(u32 romBlock, u32 cacheBlock)
{
u32 sector = getSdSectorOfRomBlock(romBlock);
if (sector == 0)
{
return &sdc_cache[0][0];
}

u32 irqs = fs_waitForCompletionOfCurrentTransaction(true);
if (isCurrentlyFetching())
Expand Down Expand Up @@ -148,26 +168,36 @@ static void* loadRomBlock(u32 romBlock, u32 cacheBlock)
}

FsWaitToken waitToken;
fs_readCacheAlignedSectorsAsync(
gFile.obj.fs->pdrv == DEV_FAT ? FS_DEVICE_DLDI : FS_DEVICE_DSI_SD,
&sdc_cache[cacheBlock][0], sector,
SDC_BLOCK_SIZE / 512, &waitToken);
sCurrentFetch.romBlock = romBlock;
sCurrentFetch.cacheBlock = cacheBlock;
if (sector != 0)
{
fs_readCacheAlignedSectorsAsync(
gFile.obj.fs->pdrv == DEV_FAT ? FS_DEVICE_DLDI : FS_DEVICE_DSI_SD,
&sdc_cache[cacheBlock][0], sector,
SDC_BLOCK_SIZE / 512, &waitToken);
sCurrentFetch.romBlock = romBlock;
sCurrentFetch.cacheBlock = cacheBlock;
}

if ((arm_getCpsr() & 0x1F) != 0x12)
{
sTabuBlock = cacheBlock;
}

arm_restoreIrqs(irqs);
irqs = fs_waitForCompletion(&waitToken, true);
if (sCurrentFetch.romBlock == romBlock)
if (sector != 0)
{
finishFetch();
irqs = fs_waitForCompletion(&waitToken, true);
if (sCurrentFetch.romBlock == romBlock)
{
finishFetch();
}
arm_restoreIrqs(irqs);
}
else
{
fillOutOfBoundsCacheBlock(romBlock, cacheBlock);
}

arm_restoreIrqs(irqs);
return &sdc_cache[cacheBlock][0];
}

Expand Down

0 comments on commit d1efd9b

Please sign in to comment.