diff options
Diffstat (limited to 'src/save.c')
-rw-r--r-- | src/save.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/src/save.c b/src/save.c new file mode 100644 index 000000000..e05de67cc --- /dev/null +++ b/src/save.c @@ -0,0 +1,349 @@ +#include "global.h" +#include "gba/flash_internal.h" + +struct SaveSectionLocation +{ + void *data; + u16 size; +}; + +struct SaveSection +{ + u8 data[0xFF4]; + u16 id; + u16 checksum; + u32 unknown; + u32 counter; +}; + +extern struct SaveSection unk_2000000; + +extern u16 gUnknown_03005E9C; +extern u32 gUnknown_03005EA0; +extern u16 gUnknown_03005EA4; +extern u32 gUnknown_03005EA8; +extern u32 gUnknown_03005EAC; +extern struct SaveSection *gUnknown_03005EB0; +extern u16 gUnknown_03005EB4; + +u8 sub_81252D8(u16, struct SaveSectionLocation *); +u8 sub_8125440(u8, u8 *); +u8 sub_81255B8(u16 a1, struct SaveSectionLocation *a2); + +void calls_flash_erase_block(void) +{ + u16 i; + for (i = 0; i < 32; i++) + EraseFlashSector(i); +} + +void sub_81251B8(void) +{ + gUnknown_03005EAC = 0; + gUnknown_03005E9C = 0; + gUnknown_03005EA8 = 0; +} + +bool32 sub_81251D4(u8 op, u8 bit) +{ + bool32 retVal = FALSE; + + switch (op) + { + case 0: + gUnknown_03005EA8 |= 1 << bit; + break; + case 1: + gUnknown_03005EA8 &= ~(1 << bit); + break; + case 2: + if (gUnknown_03005EA8 & (1 << bit)) + retVal = TRUE; + break; + } + + return retVal; +} + +u8 save_write_to_flash(u16 a1, struct SaveSectionLocation *a2) +{ + u32 retVal; + u16 i; + + gUnknown_03005EB0 = &unk_2000000; + + if (a1 != 0xFFFF) + { + retVal = sub_81252D8(a1, a2); + } + else + { + gUnknown_03005EA4 = gUnknown_03005E9C; + gUnknown_03005EA0 = gUnknown_03005EAC; + gUnknown_03005E9C++; + gUnknown_03005E9C = gUnknown_03005E9C % 14; + gUnknown_03005EAC++; + retVal = 1; + for (i = 0; i < 14; i++) + sub_81252D8(i, a2); + if (gUnknown_03005EA8) + { + retVal = 0xFF; + gUnknown_03005E9C = gUnknown_03005EA4; + gUnknown_03005EAC = gUnknown_03005EA0; + } + } + + return retVal; +} + +u8 sub_81252D8(u16 a1, struct SaveSectionLocation *a2) +{ + u16 i; + u16 sector; + u8 *data; + u16 size; + + sector = a1 + gUnknown_03005E9C; + sector %= 14; + sector += 14 * (gUnknown_03005EAC % 2); + + data = a2[a1].data; + size = a2[a1].size; + + for (i = 0; i < sizeof(struct SaveSection); i++) + ((char *)gUnknown_03005EB0)[i] = 0; + + gUnknown_03005EB0->id = a1; + gUnknown_03005EB0->unknown = 0x8012025; + gUnknown_03005EB0->counter = gUnknown_03005EAC; + + for (i = 0; i < size; i++) + gUnknown_03005EB0->data[i] = data[i]; + + gUnknown_03005EB0->checksum = sub_8125C10(data, size); + return sub_8125440(sector, gUnknown_03005EB0->data); +} + +u8 sub_81253C8(u8 sector, u8 *data, u16 size) +{ + u16 i; + struct SaveSection *section = &unk_2000000; + + for (i = 0; i < sizeof(struct SaveSection); i++) + ((char *)section)[i] = 0; + + section->unknown = 0x8012025; + + for (i = 0; i < size; i++) + section->data[i] = data[i]; + + section->id = sub_8125C10(data, size); // id instead of checksum? + return sub_8125440(sector, section->data); +} + +u8 sub_8125440(u8 sector, u8 *data) +{ + if (ProgramFlashSectorAndVerify(sector, data)) + { + sub_81251D4(0, sector); + return 0xFF; + } + else + { + sub_81251D4(1, sector); + return 1; + } +} + +u32 sub_812546C(void) +{ + gUnknown_03005EB0 = &unk_2000000; + gUnknown_03005EA4 = gUnknown_03005E9C; + gUnknown_03005EA0 = gUnknown_03005EAC; + gUnknown_03005E9C++; + gUnknown_03005E9C = gUnknown_03005E9C % 14; + gUnknown_03005EAC++; + gUnknown_03005EB4 = 0; + gUnknown_03005EA8 = 0; + return 0; +} + +u32 sub_81254C8(void) +{ + gUnknown_03005EB0 = &unk_2000000; + gUnknown_03005EA4 = gUnknown_03005E9C; + gUnknown_03005EA0 = gUnknown_03005EAC; + gUnknown_03005EB4 = 0; + gUnknown_03005EA8 = 0; + return 0; +} + +u8 sub_812550C(u16 a1, struct SaveSectionLocation *a2) +{ + u8 retVal; + + if (gUnknown_03005EB4 < a1 - 1) + { + retVal = 1; + sub_81252D8(gUnknown_03005EB4, a2); + gUnknown_03005EB4++; + if (gUnknown_03005EA8) + { + retVal = 0xFF; + gUnknown_03005E9C = gUnknown_03005EA4; + gUnknown_03005EAC = gUnknown_03005EA0; + } + } + else + { + retVal = 0xFF; + } + + return retVal; +} + +u8 sub_812556C(u16 a1, struct SaveSectionLocation *a2) +{ + u8 retVal = 1; + sub_81255B8(a1 - 1, a2); + if (gUnknown_03005EA8) + { + retVal = 0xFF; + gUnknown_03005E9C = gUnknown_03005EA4; + gUnknown_03005EAC = gUnknown_03005EA0; + } + return retVal; +} + +u8 sub_81255B8(u16 a1, struct SaveSectionLocation *a2) +{ + u16 i; + u16 sector; + u8 *data; + u16 size; + u8 status; + + sector = a1 + gUnknown_03005E9C; + sector %= 14; + sector += 14 * (gUnknown_03005EAC % 2); + + data = a2[a1].data; + size = a2[a1].size; + + for (i = 0; i < sizeof(struct SaveSection); i++) + ((char *)gUnknown_03005EB0)[i] = 0; + + gUnknown_03005EB0->id = a1; + gUnknown_03005EB0->unknown = 0x8012025; + gUnknown_03005EB0->counter = gUnknown_03005EAC; + + for (i = 0; i < size; i++) + gUnknown_03005EB0->data[i] = data[i]; + + gUnknown_03005EB0->checksum = sub_8125C10(data, size); + + EraseFlashSector(sector); + + status = 1; + + for (i = 0; i < 0xFF8; i++) + { + if (ProgramFlashByte(sector, i, ((u8 *)gUnknown_03005EB0)[i])) + { + status = 0xFF; + break; + } + } + + if (status == 0xFF) + { + sub_81251D4(0, sector); + return 0xFF; + } + else + { + status = 1; + + for (i = 0; i < 7; i++) + { + if (ProgramFlashByte(sector, 0xFF9 + i, ((u8 *)gUnknown_03005EB0)[0xFF9 + i])) + { + status = 0xFF; + break; + } + } + + if (status == 0xFF) + { + sub_81251D4(0, sector); + return 0xFF; + } + else + { + sub_81251D4(1, sector); + return 1; + } + } +} + +u8 sub_8125758(u16 a1) +{ + u16 sector; + + sector = a1 + gUnknown_03005E9C - 1; + sector %= 14; + sector += 14 * (gUnknown_03005EAC % 2); + + if (ProgramFlashByte(sector, 0xFF8, ((u8 *)gUnknown_03005EB0)[0xFF8])) + { + sub_81251D4(0, sector); + gUnknown_03005E9C = gUnknown_03005EA4; + gUnknown_03005EAC = gUnknown_03005EA0; + return 0xFF; + } + else + { + sub_81251D4(1u, sector); + return 1; + } +} + +u8 sub_81257F0(u16 a1) +{ + u16 sector; + + sector = a1 + gUnknown_03005E9C - 1; + sector %= 14; + sector += 14 * (gUnknown_03005EAC % 2); + + if (ProgramFlashByte(sector, 0xFF8, 0x25)) + { + sub_81251D4(0, sector); + gUnknown_03005E9C = gUnknown_03005EA4; + gUnknown_03005EAC = gUnknown_03005EA0; + return 0xFF; + } + else + { + sub_81251D4(1u, sector); + return 1; + } +} + +u8 sub_812587C(u16 a1, int a2) +{ + u8 retVal; + gUnknown_03005EB0 = &unk_2000000; + if (a1 != 0xFFFF) + { + retVal = 0xFF; + } + else + { + retVal = sub_8125974(a2); + sub_81258BC(0xFFFF, a2); + } + + return retVal; +} |