Save-compatible SaveBlock3 (#4112)

* SaveBlock3 in sector footers

* Update load_save.c

Since mgriffin is currently not available I took the liberty to edit the file. Hope it's fine.

* SaveBlock3 in debug menu (#3)

---------

Co-authored-by: DizzyEggg <jajkodizzy@wp.pl>
Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
Co-authored-by: psf <77138753+pkmnsnfrn@users.noreply.github.com>
This commit is contained in:
Martin Griffin 2024-02-10 17:14:36 +00:00 committed by GitHub
parent 81fdfdd90b
commit 311d732359
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 66 additions and 5 deletions

View file

@ -166,6 +166,8 @@ Debug_CheckSaveBlock::
msgbox Debug_SaveBlock1Size, MSGBOX_DEFAULT msgbox Debug_SaveBlock1Size, MSGBOX_DEFAULT
callnative CheckSaveBlock2Size callnative CheckSaveBlock2Size
msgbox Debug_SaveBlock2Size, MSGBOX_DEFAULT msgbox Debug_SaveBlock2Size, MSGBOX_DEFAULT
callnative CheckSaveBlock3Size
msgbox Debug_SaveBlock3Size, MSGBOX_DEFAULT
callnative CheckPokemonStorageSize callnative CheckPokemonStorageSize
msgbox Debug_PokemonStorageSize, MSGBOX_DEFAULT msgbox Debug_PokemonStorageSize, MSGBOX_DEFAULT
release release
@ -179,6 +181,10 @@ Debug_SaveBlock2Size::
.string "SaveBlock2 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" .string "SaveBlock2 size: {STR_VAR_1}b/{STR_VAR_2}b.\n"
.string "Free space: {STR_VAR_3}b.$" .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:: Debug_PokemonStorageSize::
.string "{PKMN}Storage size: {STR_VAR_1}b/{STR_VAR_2}b.\n" .string "{PKMN}Storage size: {STR_VAR_1}b/{STR_VAR_2}b.\n"
.string "Free space: {STR_VAR_3}b.$" .string "Free space: {STR_VAR_3}b.$"

View file

@ -167,6 +167,12 @@ struct UCoords32
u32 y; u32 y;
}; };
struct SaveBlock3
{
};
extern struct SaveBlock3 *gSaveBlock3Ptr;
struct Time struct Time
{ {
/*0x00*/ s16 days; /*0x00*/ s16 days;

View file

@ -2,6 +2,7 @@
#define GUARD_LOAD_SAVE_H #define GUARD_LOAD_SAVE_H
#include "pokemon_storage_system.h" #include "pokemon_storage_system.h"
#include "save.h"
#define SAVEBLOCK_MOVE_RANGE 128 #define SAVEBLOCK_MOVE_RANGE 128
@ -27,6 +28,7 @@ struct PokemonStorageASLR {
extern struct SaveBlock1ASLR gSaveblock1; extern struct SaveBlock1ASLR gSaveblock1;
extern struct SaveBlock2ASLR gSaveblock2; extern struct SaveBlock2ASLR gSaveblock2;
extern struct SaveBlock3 gSaveblock3;
extern struct PokemonStorageASLR gPokemonStorage; extern struct PokemonStorageASLR gPokemonStorage;
extern bool32 gFlashMemoryPresent; extern bool32 gFlashMemoryPresent;
@ -35,6 +37,7 @@ extern struct SaveBlock2 *gSaveBlock2Ptr;
extern struct PokemonStorage *gPokemonStoragePtr; extern struct PokemonStorage *gPokemonStoragePtr;
void CheckForFlashMemory(void); void CheckForFlashMemory(void);
void ClearSav3(void);
void ClearSav2(void); void ClearSav2(void);
void ClearSav1(void); void ClearSav1(void);
void SetSaveBlocksPointers(u16 offset); void SetSaveBlocksPointers(u16 offset);

View file

@ -1,11 +1,11 @@
#ifndef GUARD_SAVE_H #ifndef GUARD_SAVE_H
#define GUARD_SAVE_H #define GUARD_SAVE_H
// Each 4 KiB flash sector contains 3968 bytes of actual data followed by a 128 byte footer. // Each 4 KiB flash sector contains 3968 bytes of actual data followed by 116 bytes of SaveBlock3 and then 12 bytes of footer.
// Only 12 bytes of the footer are used.
#define SECTOR_DATA_SIZE 3968 #define SECTOR_DATA_SIZE 3968
#define SECTOR_FOOTER_SIZE 128 #define SAVE_BLOCK_3_CHUNK_SIZE 116
#define SECTOR_SIZE (SECTOR_DATA_SIZE + SECTOR_FOOTER_SIZE) #define SECTOR_FOOTER_SIZE 12
#define SECTOR_SIZE (SECTOR_DATA_SIZE + SAVE_BLOCK_3_CHUNK_SIZE + SECTOR_FOOTER_SIZE)
#define NUM_SAVE_SLOTS 2 #define NUM_SAVE_SLOTS 2
@ -69,7 +69,7 @@ struct SaveSectorLocation
struct SaveSector struct SaveSector
{ {
u8 data[SECTOR_DATA_SIZE]; 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 id;
u16 checksum; u16 checksum;
u32 signature; u32 signature;

View file

@ -2088,6 +2088,7 @@ void CheckSaveBlock1Size(struct ScriptContext *ctx)
ConvertIntToDecimalStringN(gStringVar1, currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar1, currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6);
ConvertIntToDecimalStringN(gStringVar2, maxSb1Size, 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(gStringVar3, maxSb1Size - currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6);
ConvertIntToDecimalStringN(gStringVar4, 1, STR_CONV_MODE_LEFT_ALIGN, 6);
} }
void CheckSaveBlock2Size(struct ScriptContext *ctx) void CheckSaveBlock2Size(struct ScriptContext *ctx)
@ -2099,6 +2100,15 @@ void CheckSaveBlock2Size(struct ScriptContext *ctx)
ConvertIntToDecimalStringN(gStringVar3, maxSb2Size - currSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); 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) void CheckPokemonStorageSize(struct ScriptContext *ctx)
{ {
u32 currPkmnStorageSize = sizeof(struct PokemonStorage); u32 currPkmnStorageSize = sizeof(struct PokemonStorage);

View file

@ -30,6 +30,7 @@ struct LoadedSaveData
}; };
// EWRAM DATA // EWRAM DATA
EWRAM_DATA struct SaveBlock3 gSaveblock3 = {};
EWRAM_DATA struct SaveBlock2ASLR gSaveblock2 = {0}; EWRAM_DATA struct SaveBlock2ASLR gSaveblock2 = {0};
EWRAM_DATA struct SaveBlock1ASLR gSaveblock1 = {0}; EWRAM_DATA struct SaveBlock1ASLR gSaveblock1 = {0};
EWRAM_DATA struct PokemonStorageASLR gPokemonStorage = {0}; EWRAM_DATA struct PokemonStorageASLR gPokemonStorage = {0};
@ -41,6 +42,7 @@ EWRAM_DATA u32 gLastEncryptionKey = 0;
bool32 gFlashMemoryPresent; bool32 gFlashMemoryPresent;
struct SaveBlock1 *gSaveBlock1Ptr; struct SaveBlock1 *gSaveBlock1Ptr;
struct SaveBlock2 *gSaveBlock2Ptr; struct SaveBlock2 *gSaveBlock2Ptr;
IWRAM_INIT struct SaveBlock3 *gSaveBlock3Ptr = &gSaveblock3;
struct PokemonStorage *gPokemonStoragePtr; struct PokemonStorage *gPokemonStoragePtr;
// code // code
@ -57,6 +59,11 @@ void CheckForFlashMemory(void)
} }
} }
void ClearSav3(void)
{
CpuFill16(0, &gSaveblock3, sizeof(struct SaveBlock3));
}
void ClearSav2(void) void ClearSav2(void)
{ {
CpuFill16(0, &gSaveblock2, sizeof(struct SaveBlock2ASLR)); CpuFill16(0, &gSaveblock2, sizeof(struct SaveBlock2ASLR));

View file

@ -158,6 +158,7 @@ void NewGameInitData(void)
ResetPokedex(); ResetPokedex();
ClearFrontierRecord(); ClearFrontierRecord();
ClearSav1(); ClearSav1();
ClearSav3();
ClearAllMail(); ClearAllMail();
gSaveBlock2Ptr->specialSaveWarpFlags = 0; gSaveBlock2Ptr->specialSaveWarpFlags = 0;
gSaveBlock2Ptr->gcnLinkFlags = 0; gSaveBlock2Ptr->gcnLinkFlags = 0;

View file

@ -20,6 +20,8 @@ static u8 CopySaveSlotData(u16, struct SaveSectorLocation *);
static u8 TryWriteSector(u8, u8 *); static u8 TryWriteSector(u8, u8 *);
static u8 HandleWriteSector(u16, const struct SaveSectorLocation *); static u8 HandleWriteSector(u16, const struct SaveSectorLocation *);
static u8 HandleReplaceSector(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 // 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 // These will produce an error if a save struct is larger than the space
// alloted for it in the flash. // 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 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 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); 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++) for (i = 0; i < size; i++)
gReadWriteSector->data[i] = data[i]; gReadWriteSector->data[i] = data[i];
CopyFromSaveBlock3(sectorId, gReadWriteSector);
gReadWriteSector->checksum = CalculateChecksum(data, size); gReadWriteSector->checksum = CalculateChecksum(data, size);
return TryWriteSector(sector, gReadWriteSector->data); return TryWriteSector(sector, gReadWriteSector->data);
@ -336,6 +341,8 @@ static u8 HandleReplaceSector(u16 sectorId, const struct SaveSectorLocation *loc
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
gReadWriteSector->data[i] = data[i]; gReadWriteSector->data[i] = data[i];
CopyFromSaveBlock3(sectorId, gReadWriteSector);
gReadWriteSector->checksum = CalculateChecksum(data, size); gReadWriteSector->checksum = CalculateChecksum(data, size);
// Erase old save data // Erase old save data
@ -505,6 +512,7 @@ static u8 CopySaveSlotData(u16 sectorId, struct SaveSectorLocation *locations)
u16 j; u16 j;
for (j = 0; j < locations[id].size; j++) for (j = 0; j < locations[id].size; j++)
((u8 *)locations[id].data)[j] = gReadWriteSector->data[j]; ((u8 *)locations[id].data)[j] = gReadWriteSector->data[j];
CopyToSaveBlock3(id, gReadWriteSector);
} }
} }
@ -1050,3 +1058,22 @@ void Task_LinkFullSave(u8 taskId)
break; 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);
}

View file

@ -120,6 +120,7 @@ top:
MoveSaveBlocks_ResetHeap(); MoveSaveBlocks_ResetHeap();
ClearSav1(); ClearSav1();
ClearSav2(); ClearSav2();
ClearSav3();
gIntrTable[7] = Intr_Timer2; gIntrTable[7] = Intr_Timer2;