Created page for review

Thomas Winwood 2023-09-27 08:22:02 +01:00
parent 0c9a898b7f
commit 361f456d0f
1 changed files with 191 additions and 0 deletions

@ -0,0 +1,191 @@
# Remove the backup save file
_THIS WILL BREAK SAVE COMPATIBILITY WITH VANILLA EMERALD AND ANY SAVE EDITING TOOLS SUCH AS PKHEX_
The Generation III Pokémon games have a backup save file in case the primary one is corrupted, but in practice it's very unlikely for this to happen unless the player deliberately breaks it. We can reclaim it to get a lot of save space without needing to remove any gameplay features.
The files we'll be editing are [`include/save.h`](https://github.com/pret/pokeemerald/blob/master/include/save.h) and [`src/save.c`](https://github.com/pret/pokeemerald/blob/master/src/save.c), so open those in your editor of choice.
## include/save.h
Delete the line `#define NUM_SAVE_SLOTS 2`.
Change `NUM_SECTORS_PER_SLOT` from 14 to 28.
```diff
#define SECTOR_ID_SAVEBLOCK2 0
#define SECTOR_ID_SAVEBLOCK1_START 1
#define SECTOR_ID_SAVEBLOCK1_END 4
#define SECTOR_ID_PKMN_STORAGE_START 5
#define SECTOR_ID_PKMN_STORAGE_END 13
-#define NUM_SECTORS_PER_SLOT 14
+#define NUM_SECTORS_PER_SLOT 28
-// Save Slot 1: 0-13; Save Slot 2: 14-27
#define SECTOR_ID_HOF_1 28
#define SECTOR_ID_HOF_2 29
#define SECTOR_ID_TRAINER_HILL 30
#define SECTOR_ID_RECORDED_BATTLE 31
#define SECTORS_COUNT 32
```
## src/save.c
We have a few places where the constant `NUM_SAVE_SLOTS` was used; since we only have one save slot, we can remove them.
Remove the line `sector += NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);` in the following five functions.
* `HandleWriteSector`
* `HandleReplaceSector`
* `WriteSectorSignatureByte_NoOffset`
* `CopySectorSignatureByte`
* `WriteSectorSignatureByte`
In the functions `CopySaveSlotData` and `GetSaveBlocksPointersBaseOffset`, remove the `slotOffset` variable.
```diff
// sectorId arg is ignored, this always reads the full save slot
static u8 CopySaveSlotData(u16 sectorId, struct SaveSectorLocation *locations)
{
u16 i;
u16 checksum;
- u16 slotOffset = NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
u16 id;
for (i = 0; i < NUM_SECTORS_PER_SLOT; i++)
{
- ReadFlashSector(i + slotOffset, gReadWriteSector);
+ ReadFlashSector(i, gReadWriteSector);
```
```diff
u16 GetSaveBlocksPointersBaseOffset(void)
{
- u16 i, slotOffset;
+ u16 i;
struct SaveSector* sector;
sector = gReadWriteSector = &gSaveDataBuffer;
if (gFlashMemoryPresent != TRUE)
return 0;
UpdateSaveAddresses();
GetSaveValidStatus(gRamSaveSectorLocations);
- slotOffset = NUM_SECTORS_PER_SLOT * (gSaveCounter % NUM_SAVE_SLOTS);
for (i = 0; i < NUM_SECTORS_PER_SLOT; i++)
{
- ReadFlashSector(i + slotOffset, gReadWriteSector);
+ ReadFlashSector(i, gReadWriteSector);
```
Finally, we need to alter the code which checked the integrity of both save slots. Replace the function `GetSaveValidStatus` like so.
```c
static u8 GetSaveValidStatus(const struct SaveSectorLocation *locations)
{
u16 i;
u16 checksum;
u32 saveSlotCounter = 0;
u32 validSectorFlags = 0;
bool8 signatureValid = FALSE;
u8 saveSlotStatus;
for (i = 0; i < NUM_SECTORS_PER_SLOT; i++)
{
ReadFlashSector(i, gReadWriteSector);
if (gReadWriteSector->signature == SECTOR_SIGNATURE)
{
signatureValid = TRUE;
checksum = CalculateChecksum(gReadWriteSector->data, locations[gReadWriteSector->id].size);
if (gReadWriteSector->checksum == checksum)
{
saveSlotCounter = gReadWriteSector->counter;
validSectorFlags |= 1 << gReadWriteSector->id;
}
}
}
if (signatureValid)
{
if (validSectorFlags == (1 << NUM_SECTORS_PER_SLOT) - 1)
return SAVE_STATUS_OK;
else
return SAVE_STATUS_ERROR;
}
else
{
// No sectors have the correct signature, treat it as empty
return SAVE_STATUS_EMPTY;
}
}
```
## How do I use this new save space?
If you now run a build you should get a working copy of Pokémon Emerald, but we haven't made use of the free space. By way of an example, I've expanded both `struct SaveBlock1` and `struct SaveBlock2` to fill the available space while keeping `struct PokemonStorage` (the number of boxes) the same size.
In [`include/save.h`](https://github.com/pret/pokeemerald/blob/master/include/save.h):
```diff
#define SECTOR_ID_SAVEBLOCK2 0
-#define SECTOR_ID_SAVEBLOCK1_START 1
-#define SECTOR_ID_SAVEBLOCK1_END 4
-#define SECTOR_ID_PKMN_STORAGE_START 5
-#define SECTOR_ID_PKMN_STORAGE_END 13
+#define SECTOR_ID_SAVEBLOCK1_START 5
+#define SECTOR_ID_SAVEBLOCK1_END 18
+#define SECTOR_ID_PKMN_STORAGE_START 19
+#define SECTOR_ID_PKMN_STORAGE_END 27
#define NUM_SECTORS_PER_SLOT 28
#define SECTOR_ID_HOF_1 28
#define SECTOR_ID_HOF_2 29
#define SECTOR_ID_TRAINER_HILL 30
#define SECTOR_ID_RECORDED_BATTLE 31
#define SECTORS_COUNT 32
```
In [`src/save.c`](https://github.com/pret/pokeemerald/blob/master/src/save.c):
```diff
struct
{
u16 offset;
u16 size;
} static const sSaveSlotLayout[NUM_SECTORS_PER_SLOT] =
{
SAVEBLOCK_CHUNK(struct SaveBlock2, 0), // SECTOR_ID_SAVEBLOCK2
+ SAVEBLOCK_CHUNK(struct SaveBlock2, 1),
+ SAVEBLOCK_CHUNK(struct SaveBlock2, 2),
+ SAVEBLOCK_CHUNK(struct SaveBlock2, 3),
+ SAVEBLOCK_CHUNK(struct SaveBlock2, 4),
- 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(struct SaveBlock1, 0), // SECTOR_ID_SAVEBLOCK1_START
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 1),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 2),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 3),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 4),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 5),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 6),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 7),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 8),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 9),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 10),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 11),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 12),
+ SAVEBLOCK_CHUNK(struct SaveBlock1, 13), // SECTOR_ID_SAVEBLOCK1_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
};
```
As implied by the comments here, it's important to ensure that the number of sectors you allocate to each chunk of the save match the constant definitions in `include/save.h`.