diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 4e0cc413ff..939bd88ac0 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -166,6 +166,8 @@ Debug_CheckSaveBlock:: msgbox Debug_SaveBlock1Size, MSGBOX_DEFAULT callnative CheckSaveBlock2Size msgbox Debug_SaveBlock2Size, MSGBOX_DEFAULT + callnative CheckSaveBlock3Size + msgbox Debug_SaveBlock3Size, MSGBOX_DEFAULT callnative CheckPokemonStorageSize msgbox Debug_PokemonStorageSize, MSGBOX_DEFAULT release @@ -179,6 +181,10 @@ Debug_SaveBlock2Size:: .string "SaveBlock2 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" .string "Free space: {STR_VAR_3}b.$" +Debug_SaveBlock3Size:: + .string "SaveBlock3 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" + Debug_PokemonStorageSize:: .string "{PKMN}Storage size: {STR_VAR_1}b/{STR_VAR_2}b.\n" .string "Free space: {STR_VAR_3}b.$" diff --git a/include/global.h b/include/global.h index 75dcf7d245..fac78b0eed 100644 --- a/include/global.h +++ b/include/global.h @@ -167,6 +167,12 @@ struct UCoords32 u32 y; }; +struct SaveBlock3 +{ +}; + +extern struct SaveBlock3 *gSaveBlock3Ptr; + struct Time { /*0x00*/ s16 days; diff --git a/include/load_save.h b/include/load_save.h index 389bd5a2b9..084c0977e8 100644 --- a/include/load_save.h +++ b/include/load_save.h @@ -2,6 +2,7 @@ #define GUARD_LOAD_SAVE_H #include "pokemon_storage_system.h" +#include "save.h" #define SAVEBLOCK_MOVE_RANGE 128 @@ -27,6 +28,7 @@ struct PokemonStorageASLR { extern struct SaveBlock1ASLR gSaveblock1; extern struct SaveBlock2ASLR gSaveblock2; +extern struct SaveBlock3 gSaveblock3; extern struct PokemonStorageASLR gPokemonStorage; extern bool32 gFlashMemoryPresent; @@ -35,6 +37,7 @@ extern struct SaveBlock2 *gSaveBlock2Ptr; extern struct PokemonStorage *gPokemonStoragePtr; void CheckForFlashMemory(void); +void ClearSav3(void); void ClearSav2(void); void ClearSav1(void); void SetSaveBlocksPointers(u16 offset); diff --git a/include/save.h b/include/save.h index 41913d1df4..aef84c3158 100644 --- a/include/save.h +++ b/include/save.h @@ -1,11 +1,11 @@ #ifndef GUARD_SAVE_H #define GUARD_SAVE_H -// Each 4 KiB flash sector contains 3968 bytes of actual data followed by a 128 byte footer. -// Only 12 bytes of the footer are used. +// Each 4 KiB flash sector contains 3968 bytes of actual data followed by 116 bytes of SaveBlock3 and then 12 bytes of footer. #define SECTOR_DATA_SIZE 3968 -#define SECTOR_FOOTER_SIZE 128 -#define SECTOR_SIZE (SECTOR_DATA_SIZE + SECTOR_FOOTER_SIZE) +#define SAVE_BLOCK_3_CHUNK_SIZE 116 +#define SECTOR_FOOTER_SIZE 12 +#define SECTOR_SIZE (SECTOR_DATA_SIZE + SAVE_BLOCK_3_CHUNK_SIZE + SECTOR_FOOTER_SIZE) #define NUM_SAVE_SLOTS 2 @@ -69,7 +69,7 @@ struct SaveSectorLocation struct SaveSector { u8 data[SECTOR_DATA_SIZE]; - u8 unused[SECTOR_FOOTER_SIZE - 12]; // Unused portion of the footer + u8 saveBlock3Chunk[SAVE_BLOCK_3_CHUNK_SIZE]; u16 id; u16 checksum; u32 signature; diff --git a/src/debug.c b/src/debug.c index e3506ab7f0..1210d8762d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2088,6 +2088,7 @@ void CheckSaveBlock1Size(struct ScriptContext *ctx) ConvertIntToDecimalStringN(gStringVar1, currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar2, maxSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar3, maxSb1Size - currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar4, 1, STR_CONV_MODE_LEFT_ALIGN, 6); } void CheckSaveBlock2Size(struct ScriptContext *ctx) @@ -2099,6 +2100,15 @@ void CheckSaveBlock2Size(struct ScriptContext *ctx) ConvertIntToDecimalStringN(gStringVar3, maxSb2Size - currSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); } +void CheckSaveBlock3Size(struct ScriptContext *ctx) +{ + u32 currSb3Size = (sizeof(struct SaveBlock3)); + u32 maxSb3Size = SAVE_BLOCK_3_CHUNK_SIZE * NUM_SECTORS_PER_SLOT; + ConvertIntToDecimalStringN(gStringVar1, currSb3Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar2, maxSb3Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxSb3Size - currSb3Size, STR_CONV_MODE_LEFT_ALIGN, 6); +} + void CheckPokemonStorageSize(struct ScriptContext *ctx) { u32 currPkmnStorageSize = sizeof(struct PokemonStorage); diff --git a/src/load_save.c b/src/load_save.c index 667f9e1c3c..70db12fb98 100644 --- a/src/load_save.c +++ b/src/load_save.c @@ -30,6 +30,7 @@ struct LoadedSaveData }; // EWRAM DATA +EWRAM_DATA struct SaveBlock3 gSaveblock3 = {}; EWRAM_DATA struct SaveBlock2ASLR gSaveblock2 = {0}; EWRAM_DATA struct SaveBlock1ASLR gSaveblock1 = {0}; EWRAM_DATA struct PokemonStorageASLR gPokemonStorage = {0}; @@ -41,6 +42,7 @@ EWRAM_DATA u32 gLastEncryptionKey = 0; bool32 gFlashMemoryPresent; struct SaveBlock1 *gSaveBlock1Ptr; struct SaveBlock2 *gSaveBlock2Ptr; +IWRAM_INIT struct SaveBlock3 *gSaveBlock3Ptr = &gSaveblock3; struct PokemonStorage *gPokemonStoragePtr; // code @@ -57,6 +59,11 @@ void CheckForFlashMemory(void) } } +void ClearSav3(void) +{ + CpuFill16(0, &gSaveblock3, sizeof(struct SaveBlock3)); +} + void ClearSav2(void) { CpuFill16(0, &gSaveblock2, sizeof(struct SaveBlock2ASLR)); diff --git a/src/new_game.c b/src/new_game.c index 0efc12d47f..ece85ac544 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -158,6 +158,7 @@ void NewGameInitData(void) ResetPokedex(); ClearFrontierRecord(); ClearSav1(); + ClearSav3(); ClearAllMail(); gSaveBlock2Ptr->specialSaveWarpFlags = 0; gSaveBlock2Ptr->gcnLinkFlags = 0; diff --git a/src/save.c b/src/save.c index 3f8b25a3a3..e65dda971e 100644 --- a/src/save.c +++ b/src/save.c @@ -20,6 +20,8 @@ static u8 CopySaveSlotData(u16, struct SaveSectorLocation *); static u8 TryWriteSector(u8, u8 *); static u8 HandleWriteSector(u16, const struct SaveSectorLocation *); static u8 HandleReplaceSector(u16, const struct SaveSectorLocation *); +static void CopyToSaveBlock3(u32, struct SaveSector *); +static void CopyFromSaveBlock3(u32, struct SaveSector *); // Divide save blocks into individual chunks to be written to flash sectors @@ -75,6 +77,7 @@ struct // These will produce an error if a save struct is larger than the space // alloted for it in the flash. +STATIC_ASSERT(sizeof(struct SaveBlock3) <= SAVE_BLOCK_3_CHUNK_SIZE * NUM_SECTORS_PER_SLOT, SaveBlock3FreeSpace); STATIC_ASSERT(sizeof(struct SaveBlock2) <= SECTOR_DATA_SIZE, SaveBlock2FreeSpace); STATIC_ASSERT(sizeof(struct SaveBlock1) <= SECTOR_DATA_SIZE * (SECTOR_ID_SAVEBLOCK1_END - SECTOR_ID_SAVEBLOCK1_START + 1), SaveBlock1FreeSpace); STATIC_ASSERT(sizeof(struct PokemonStorage) <= SECTOR_DATA_SIZE * (SECTOR_ID_PKMN_STORAGE_END - SECTOR_ID_PKMN_STORAGE_START + 1), PokemonStorageFreeSpace); @@ -202,6 +205,8 @@ static u8 HandleWriteSector(u16 sectorId, const struct SaveSectorLocation *locat for (i = 0; i < size; i++) gReadWriteSector->data[i] = data[i]; + CopyFromSaveBlock3(sectorId, gReadWriteSector); + gReadWriteSector->checksum = CalculateChecksum(data, size); return TryWriteSector(sector, gReadWriteSector->data); @@ -336,6 +341,8 @@ static u8 HandleReplaceSector(u16 sectorId, const struct SaveSectorLocation *loc for (i = 0; i < size; i++) gReadWriteSector->data[i] = data[i]; + CopyFromSaveBlock3(sectorId, gReadWriteSector); + gReadWriteSector->checksum = CalculateChecksum(data, size); // Erase old save data @@ -505,6 +512,7 @@ static u8 CopySaveSlotData(u16 sectorId, struct SaveSectorLocation *locations) u16 j; for (j = 0; j < locations[id].size; j++) ((u8 *)locations[id].data)[j] = gReadWriteSector->data[j]; + CopyToSaveBlock3(id, gReadWriteSector); } } @@ -1050,3 +1058,22 @@ void Task_LinkFullSave(u8 taskId) break; } } + +static u32 SaveBlock3Size(u32 sectorId) +{ + s32 begin = sectorId * SAVE_BLOCK_3_CHUNK_SIZE; + s32 end = (sectorId + 1) * SAVE_BLOCK_3_CHUNK_SIZE; + return max(0, min(end, (s32)sizeof(gSaveblock3)) - begin); +} + +static void CopyToSaveBlock3(u32 sectorId, struct SaveSector *sector) +{ + u32 size = SaveBlock3Size(sectorId); + memcpy((u8 *)&gSaveblock3 + (sectorId * SAVE_BLOCK_3_CHUNK_SIZE), sector->saveBlock3Chunk, size); +} + +static void CopyFromSaveBlock3(u32 sectorId, struct SaveSector *sector) +{ + u32 size = SaveBlock3Size(sectorId); + memcpy(sector->saveBlock3Chunk, (u8 *)&gSaveblock3 + (sectorId * SAVE_BLOCK_3_CHUNK_SIZE), size); +} diff --git a/test/test_runner.c b/test/test_runner.c index f02ddb6387..f5b7224523 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -120,6 +120,7 @@ top: MoveSaveBlocks_ResetHeap(); ClearSav1(); ClearSav2(); + ClearSav3(); gIntrTable[7] = Intr_Timer2;