Sync save sector checks

This commit is contained in:
GriffinR 2022-08-05 11:49:17 -04:00
parent 40cbfc0722
commit f16b6100c8
5 changed files with 70 additions and 50 deletions

View File

@ -129,6 +129,10 @@ extern u8 gStringVar4[];
#define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT)
#define NUM_ADDITIONAL_PHRASE_BYTES ROUND_BITS_TO_BYTES(NUM_ADDITIONAL_PHRASES)
// This produces an error at compile-time if expr is zero.
// It looks like file.c:line: size of array `id' is negative
#define STATIC_ASSERT(expr, id) typedef char id[(expr) ? 1 : -1];
struct Coords8
{
s8 x;

View File

@ -9,7 +9,10 @@
#define SECTOR_FOOTER_SIZE 128
#define SECTOR_SIZE (SECTOR_DATA_SIZE + SECTOR_FOOTER_SIZE)
#define FILE_SIGNATURE 0x08012025 // signature value to determine if a sector is in use
#define NUM_SAVE_SLOTS 2
// If the sector's signature field is not this value then the sector is either invalid or empty.
#define SECTOR_SIGNATURE 0x08012025
#define SPECIAL_SECTOR_SENTINEL 0xB39D
@ -26,12 +29,19 @@
#define SECTOR_ID_TRAINER_TOWER_2 31
#define SECTORS_COUNT 32
#define NUM_HOF_SECTORS 2
#define SAVE_STATUS_EMPTY 0
#define SAVE_STATUS_OK 1
#define SAVE_STATUS_INVALID 2
#define SAVE_STATUS_NO_FLASH 4
#define SAVE_STATUS_ERROR 0xFF
// Special sector id value for certain save functions
// to indicate that all sectors should be used
// instead of a specific sector.
#define FULL_SAVE_SLOT 0xFFFF
enum
{
SAVE_NORMAL,
@ -58,16 +68,11 @@ struct SaveSector
u16 checksum;
u32 signature;
u32 counter;
}; // size is 0x1000
}; // size is SECTOR_SIZE (0x1000)
#define SECTOR_SIGNATURE_OFFSET offsetof(struct SaveSector, signature)
#define SECTOR_COUNTER_OFFSET offsetof(struct SaveSector, counter)
// Special sector id value for certain save functions
// to indicate that all sectors should be used
// instead of a specific sector.
#define FULL_SAVE_SLOT 0xFFFF
// operations for SetDamagedSectorBits
enum
{

View File

@ -4,6 +4,12 @@
#include "save.h"
#include "cereader_tool.h"
#define SEC30_SIZE (offsetof(struct EReaderTrainerTowerSet, floors[4]))
#define SEC31_SIZE (sizeof(struct EReaderTrainerTowerSet) - SEC30_SIZE)
// The trainer tower data exceeds SECTOR_DATA_SIZE. They're allowed to use the full save sector up to the counter field.
STATIC_ASSERT(SEC30_SIZE + SEC31_SIZE <= SECTOR_COUNTER_OFFSET * 2, EReaderTrainerTowerSetFreeSpace);
u8 sub_815D654(void)
{
return (gSaveBlock1Ptr->trainerTower[0].unk9 + 1) % 256;
@ -36,20 +42,17 @@ bool32 ValidateTrainerTowerData(struct EReaderTrainerTowerSet * ttdata)
return TRUE;
}
#define SEC30_SIZE (offsetof(struct EReaderTrainerTowerSet, floors[4]))
#define SEC31_SIZE (sizeof(struct EReaderTrainerTowerSet) - SEC30_SIZE)
static bool32 CEReaderTool_SaveTrainerTower_r(struct EReaderTrainerTowerSet * ttdata, u8 * buffer)
{
AGB_ASSERT_EX(ttdata->dummy == 0, ABSPATH("cereader_tool.c"), 198);
AGB_ASSERT_EX(ttdata->id == 0, ABSPATH("cereader_tool.c"), 199)
memset(buffer, 0, 0x1000);
memset(buffer, 0, SECTOR_SIZE);
memcpy(buffer, ttdata, SEC30_SIZE);
buffer[1] = sub_815D654();
if (TryWriteSpecialSaveSector(SECTOR_ID_TRAINER_TOWER_1, buffer) != TRUE)
return FALSE;
memset(buffer, 0, 0x1000);
memset(buffer, 0, SECTOR_SIZE);
memcpy(buffer, (u8 *)ttdata + SEC30_SIZE, SEC31_SIZE);
if (TryWriteSpecialSaveSector(SECTOR_ID_TRAINER_TOWER_2, buffer) != TRUE)
return FALSE;
@ -58,7 +61,7 @@ static bool32 CEReaderTool_SaveTrainerTower_r(struct EReaderTrainerTowerSet * tt
bool32 CEReaderTool_SaveTrainerTower(struct EReaderTrainerTowerSet * ttdata)
{
u8 * buffer = AllocZeroed(0x1000);
u8 * buffer = AllocZeroed(SECTOR_SIZE);
bool32 result = CEReaderTool_SaveTrainerTower_r(ttdata, buffer);
Free(buffer);
return result;
@ -81,7 +84,7 @@ static bool32 CEReaderTool_LoadTrainerTower_r(struct EReaderTrainerTowerSet * tt
bool32 CEReaderTool_LoadTrainerTower(struct EReaderTrainerTowerSet * ttdata)
{
void *buffer = AllocZeroed(0x1000);
void *buffer = AllocZeroed(SECTOR_SIZE);
bool32 success = CEReaderTool_LoadTrainerTower_r(ttdata, buffer);
Free(buffer);
return success;

View File

@ -26,13 +26,16 @@
#include "constants/songs.h"
#include "constants/maps.h"
#define HALL_OF_FAME_MAX_TEAMS 50
#define HALL_OF_FAME_BG_PAL RGB(22, 24, 29)
struct HallofFameMon
{
u32 tid;
u32 personality;
u16 species:9;
u16 lvl:7;
u8 nick[10];
u8 nick[POKEMON_NAME_LENGTH];
};
struct HallofFameTeam
@ -40,6 +43,8 @@ struct HallofFameTeam
struct HallofFameMon mon[PARTY_SIZE];
};
STATIC_ASSERT(sizeof(struct HallofFameTeam) * HALL_OF_FAME_MAX_TEAMS <= SECTOR_DATA_SIZE * NUM_HOF_SECTORS, HallOfFameFreeSpace);
struct HofGfx
{
u16 state;
@ -52,9 +57,6 @@ static EWRAM_DATA u32 sSelectedPaletteIndices = 0;
static EWRAM_DATA struct HallofFameTeam * sHofMonPtr = NULL;
static EWRAM_DATA struct HofGfx * sHofGfxPtr = NULL;
#define HALL_OF_FAME_MAX_TEAMS 50
#define HALL_OF_FAME_BG_PAL (RGB(22, 24, 29))
static void Task_Hof_InitMonData(u8 taskId);
static void Task_Hof_InitTeamSaveData(u8 taskId);
static void Task_Hof_TrySaveData(u8 taskId);
@ -425,12 +427,12 @@ static void Task_Hof_InitTeamSaveData(u8 taskId)
SaveQuestLogData();
if (!gHasHallOfFameRecords)
{
memset(gDecompressionBuffer, 0, 0x2000);
memset(gDecompressionBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
}
else
{
if (LoadGameSave(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK)
memset(gDecompressionBuffer, 0, 0x2000);
memset(gDecompressionBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
}
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, lastSavedTeam++)
@ -747,7 +749,7 @@ void CB2_InitHofPC(void)
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 7));
SetGpuReg(REG_OFFSET_BLDY, 0);
CreateTask(Task_HofPC_CopySaveData, 0);
sHofMonPtr = AllocZeroed(0x2000);
sHofMonPtr = AllocZeroed(SECTOR_SIZE * NUM_HOF_SECTORS);
SetMainCallback2(CB2_HofIdle);
break;
}
@ -765,7 +767,7 @@ static void Task_HofPC_CopySaveData(u8 taskId)
}
else
{
CpuCopy16(gDecompressionBuffer, sHofMonPtr, 0x2000);
CpuCopy16(gDecompressionBuffer, sHofMonPtr, SECTOR_SIZE * NUM_HOF_SECTORS);
savedTeams = sHofMonPtr;
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, savedTeams++)
{

View File

@ -49,26 +49,32 @@ struct
{
u16 offset;
u16 size;
} static const sSaveSlotLayout[] =
} static const sSaveSlotLayout[NUM_SECTORS_PER_SLOT] =
{
SAVEBLOCK_CHUNK(gSaveBlock2, 0), // SECTOR_ID_SAVEBLOCK2
SAVEBLOCK_CHUNK(struct SaveBlock2, 0), // SECTOR_ID_SAVEBLOCK2
SAVEBLOCK_CHUNK(gSaveBlock1, 0), // SECTOR_ID_SAVEBLOCK1_START
SAVEBLOCK_CHUNK(gSaveBlock1, 1),
SAVEBLOCK_CHUNK(gSaveBlock1, 2),
SAVEBLOCK_CHUNK(gSaveBlock1, 3), // SECTOR_ID_SAVEBLOCK1_END
SAVEBLOCK_CHUNK(struct SaveBlock1, 0), // SECTOR_ID_SAVEBLOCK1_START
SAVEBLOCK_CHUNK(struct SaveBlock1, 1),
SAVEBLOCK_CHUNK(struct SaveBlock1, 2),
SAVEBLOCK_CHUNK(struct SaveBlock1, 3), // SECTOR_ID_SAVEBLOCK1_END
SAVEBLOCK_CHUNK(gPokemonStorage, 0), // SECTOR_ID_PKMN_STORAGE_START
SAVEBLOCK_CHUNK(gPokemonStorage, 1),
SAVEBLOCK_CHUNK(gPokemonStorage, 2),
SAVEBLOCK_CHUNK(gPokemonStorage, 3),
SAVEBLOCK_CHUNK(gPokemonStorage, 4),
SAVEBLOCK_CHUNK(gPokemonStorage, 5),
SAVEBLOCK_CHUNK(gPokemonStorage, 6),
SAVEBLOCK_CHUNK(gPokemonStorage, 7),
SAVEBLOCK_CHUNK(gPokemonStorage, 8), // SECTOR_ID_PKMN_STORAGE_END
SAVEBLOCK_CHUNK(struct PokemonStorage, 0), // SECTOR_ID_PKMN_STORAGE_START
SAVEBLOCK_CHUNK(struct PokemonStorage, 1),
SAVEBLOCK_CHUNK(struct PokemonStorage, 2),
SAVEBLOCK_CHUNK(struct PokemonStorage, 3),
SAVEBLOCK_CHUNK(struct PokemonStorage, 4),
SAVEBLOCK_CHUNK(struct PokemonStorage, 5),
SAVEBLOCK_CHUNK(struct PokemonStorage, 6),
SAVEBLOCK_CHUNK(struct PokemonStorage, 7),
SAVEBLOCK_CHUNK(struct PokemonStorage, 8), // SECTOR_ID_PKMN_STORAGE_END
};
// These will produce an error if a save struct is larger than the space
// alloted for it in the flash.
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);
// Sector num to begin writing save data. Sectors are rotated each time the game is saved. (possibly to avoid wear on flash memory?)
u16 gLastWrittenSector;
u32 gLastSaveCounter;
@ -165,7 +171,7 @@ static u8 HandleWriteSector(u16 sectorId, const struct SaveSectorLocation *locat
sectorNum = gLastWrittenSector + sectorId;
sectorNum %= NUM_SECTORS_PER_SLOT;
sectorNum += NUM_SECTORS_PER_SLOT * (gSaveCounter % 2);
sectorNum += NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
data = locations[sectorId].data;
size = locations[sectorId].size;
@ -176,7 +182,7 @@ static u8 HandleWriteSector(u16 sectorId, const struct SaveSectorLocation *locat
// fill buffer with save data
gSaveDataBufferPtr->id = sectorId;
gSaveDataBufferPtr->signature = FILE_SIGNATURE;
gSaveDataBufferPtr->signature = SECTOR_SIGNATURE;
gSaveDataBufferPtr->counter = gSaveCounter;
for (i = 0; i < size; i++)
@ -194,7 +200,7 @@ static u8 HandleWriteSectorNBytes(u8 sectorId, u8 *data, u16 size)
for (i = 0; i < SECTOR_SIZE; i++)
((char *)sector)[i] = 0;
sector->signature = FILE_SIGNATURE;
sector->signature = SECTOR_SIGNATURE;
for (i = 0; i < size; i++)
sector->data[i] = data[i];
@ -287,7 +293,7 @@ static u8 HandleReplaceSector(u16 sectorId, const struct SaveSectorLocation *loc
sectorNum = gLastWrittenSector + sectorId;
sectorNum %= NUM_SECTORS_PER_SLOT;
sectorNum += NUM_SECTORS_PER_SLOT * (gSaveCounter % 2);
sectorNum += NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
data = locations[sectorId].data;
size = locations[sectorId].size;
@ -298,7 +304,7 @@ static u8 HandleReplaceSector(u16 sectorId, const struct SaveSectorLocation *loc
// fill buffer with save data
gSaveDataBufferPtr->id = sectorId;
gSaveDataBufferPtr->signature = FILE_SIGNATURE;
gSaveDataBufferPtr->signature = SECTOR_SIGNATURE;
gSaveDataBufferPtr->counter = gSaveCounter;
for (i = 0; i < size; i++)
gSaveDataBufferPtr->data[i] = data[i];
@ -359,7 +365,7 @@ static u8 CopySectorSignatureByte(u16 sectorId, const struct SaveSectorLocation
sector = gLastWrittenSector + sectorId - 1;
sector %= NUM_SECTORS_PER_SLOT;
sector += NUM_SECTORS_PER_SLOT * (gSaveCounter % 2);
sector += NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
if (ProgramFlashByte(sector, SECTOR_SIGNATURE_OFFSET, ((u8 *)gSaveDataBufferPtr)[SECTOR_SIGNATURE_OFFSET]))
{
@ -382,10 +388,10 @@ static u8 WriteSectorSignatureByte(u16 sectorId, const struct SaveSectorLocation
sector = gLastWrittenSector + sectorId - 1;
sector %= NUM_SECTORS_PER_SLOT;
sector += NUM_SECTORS_PER_SLOT * (gSaveCounter % 2);
sector += NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
// write only the first byte of the signature, which was skipped in HandleReplaceSector
if (ProgramFlashByte(sector, SECTOR_SIGNATURE_OFFSET, FILE_SIGNATURE & 0xFF))
if (ProgramFlashByte(sector, SECTOR_SIGNATURE_OFFSET, SECTOR_SIGNATURE & 0xFF))
{
// sector is damaged, so enable the bit in gDamagedSaveSectors and restore the last written sector and save counter.
SetDamagedSectorBits(ENABLE, sector);
@ -421,7 +427,7 @@ static u8 CopySaveSlotData(u16 sectorId, const struct SaveSectorLocation *locati
{
u16 i;
u16 checksum;
u16 sector = NUM_SECTORS_PER_SLOT * (gSaveCounter % 2);
u16 sector = NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
u16 id;
for (i = 0; i < NUM_SECTORS_PER_SLOT; i++)
@ -432,7 +438,7 @@ static u8 CopySaveSlotData(u16 sectorId, const struct SaveSectorLocation *locati
gLastWrittenSector = i;
checksum = CalculateChecksum(gSaveDataBufferPtr->data, locations[id].size);
if (gSaveDataBufferPtr->signature == FILE_SIGNATURE && gSaveDataBufferPtr->checksum == checksum)
if (gSaveDataBufferPtr->signature == SECTOR_SIGNATURE && gSaveDataBufferPtr->checksum == checksum)
{
u16 j;
for (j = 0; j < locations[id].size; j++)
@ -461,7 +467,7 @@ static u8 GetSaveValidStatus(const struct SaveSectorLocation *locations)
for (sector = 0; sector < NUM_SECTORS_PER_SLOT; sector++)
{
ReadFlashSector(sector, gSaveDataBufferPtr);
if (gSaveDataBufferPtr->signature == FILE_SIGNATURE)
if (gSaveDataBufferPtr->signature == SECTOR_SIGNATURE)
{
signatureValid = TRUE;
checksum = CalculateChecksum(gSaveDataBufferPtr->data, locations[gSaveDataBufferPtr->id].size);
@ -489,7 +495,7 @@ static u8 GetSaveValidStatus(const struct SaveSectorLocation *locations)
for (sector = 0; sector < NUM_SECTORS_PER_SLOT; sector++)
{
ReadFlashSector(NUM_SECTORS_PER_SLOT + sector, gSaveDataBufferPtr);
if (gSaveDataBufferPtr->signature == FILE_SIGNATURE)
if (gSaveDataBufferPtr->signature == SECTOR_SIGNATURE)
{
signatureValid = TRUE;
checksum = CalculateChecksum(gSaveDataBufferPtr->data, locations[gSaveDataBufferPtr->id].size);
@ -567,7 +573,7 @@ static u8 TryLoadSaveSector(u8 sectorId, u8 *data, u16 size)
struct SaveSector *sector = &gSaveDataBuffer;
ReadFlashSector(sectorId, sector);
if (sector->signature == FILE_SIGNATURE)
if (sector->signature == SECTOR_SIGNATURE)
{
u16 checksum = CalculateChecksum(sector->data, size);
if (sector->id == checksum)