diff options
Diffstat (limited to 'src/agb_sram.c')
-rw-r--r-- | src/agb_sram.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/agb_sram.c b/src/agb_sram.c new file mode 100644 index 0000000..e58d5fa --- /dev/null +++ b/src/agb_sram.c @@ -0,0 +1,89 @@ +#include "global.h" +#include "agb_sram.h" + +static u16 verifySramFast_Work[80]; // buffer to hold code of VerifySramFast_Core +static u16 readSramFast_Work[64]; // buffer to hold code of ReadSramFast_Core + +u32 (*VerifySramFast)(const u8 *src, u8 *dest, u32 size); // pointer to verifySramFast_Work +void (*ReadSramFast)(const u8 *src, u8 *dest, u32 size); // pointer to readSramFast_Work + +void ReadSramFast_Core(const u8 *src, u8 *dest, u32 size) +{ + REG_WAITCNT = (REG_WAITCNT & ~3) | 3; + while (--size != -1) + *dest++ = *src++; +} + +void WriteSramFast(const u8 *src, u8 *dest, u32 size) +{ + REG_WAITCNT = (REG_WAITCNT & ~3) | 3; + while (--size != -1) + *dest++ = *src++; +} + +u32 VerifySramFast_Core(const u8 *src, u8 *dest, u32 size) +{ + REG_WAITCNT = (REG_WAITCNT & ~3) | 3; + while (--size != -1) + { + if (*dest++ != *src++) + return (u32)(dest - 1); + } + return 0; +} + +void SetSramFastFunc(void) +{ + u16 *src; + u16 *dest; + u16 size; + + src = (u16 *)ReadSramFast_Core; + // clear the least significant bit so that we get the actual start address of the function + src = (u16 *)((uintptr_t)src ^ 1); // NOTE: In Fire Emblem 8, this is '& ~1' instead of '^ 1'. + dest = readSramFast_Work; + // get the size of the function by subtracting the address of the next function + size = ((uintptr_t)WriteSramFast - (uintptr_t)ReadSramFast_Core) / 2; + // copy the function into the WRAM buffer + while (size != 0) + { + *dest++ = *src++; + size--; + } + // add 1 to the address of the buffer so that we stay in THUMB mode when bx-ing to the address + ReadSramFast = (void *)((uintptr_t)readSramFast_Work + 1); + + src = (u16 *)VerifySramFast_Core; + // clear the least significant bit so that we get the actual start address of the function + src = (u16 *)((uintptr_t)src ^ 1); // NOTE: In Fire Emblem 8, this is '& ~1' instead of '^ 1'. + dest = verifySramFast_Work; + // get the size of the function by subtracting the address of the next function + size = ((uintptr_t)SetSramFastFunc - (uintptr_t)VerifySramFast_Core) / 2; + // copy the function into the WRAM buffer + while (size != 0) + { + *dest++ = *src++; + size--; + } + // add 1 to the address of the buffer so that we stay in THUMB mode when bx-ing to the address + VerifySramFast = (void *)((uintptr_t)verifySramFast_Work + 1); + + REG_WAITCNT = (REG_WAITCNT & ~3) | 3; +} + +u32 WriteAndVerifySramFast(const u8 *src, u8 *dest, u32 size) +{ + u8 i; + u32 errorAddr; + + // try writing and verifying the data 3 times + for (i = 0; i < 3; i++) + { + WriteSramFast(src, dest, size); + errorAddr = VerifySramFast(src, dest, size); + if (errorAddr == 0) + break; + } + + return errorAddr; +} |