summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/save.s20
-rw-r--r--include/global.h3
-rw-r--r--ld_script.txt2
-rw-r--r--src/save.c56
4 files changed, 59 insertions, 22 deletions
diff --git a/data/save.s b/data/save.s
deleted file mode 100644
index 23a8d3928..000000000
--- a/data/save.s
+++ /dev/null
@@ -1,20 +0,0 @@
- .include "asm/macros.inc"
- .include "constants/constants.inc"
-
- .section .rodata
-
-gSaveSectionOffsets:: @ 85CDC00
- .2byte 0, 0xF2C
- .2byte 0, 0xF80
- .2byte 0xF80, 0xF80
- .2byte 0x1F00, 0xF80
- .2byte 0x2E80, 0xF08
- .2byte 0, 0xF80
- .2byte 0xF80, 0xF80
- .2byte 0x1F00, 0xF80
- .2byte 0x2E80, 0xF80
- .2byte 0x3E00, 0xF80
- .2byte 0x4D80, 0xF80
- .2byte 0x5D00, 0xF80
- .2byte 0x6C80, 0xF80
- .2byte 0x7C00, 0x7D0
diff --git a/include/global.h b/include/global.h
index 9f6c45df1..f358dafe7 100644
--- a/include/global.h
+++ b/include/global.h
@@ -37,6 +37,9 @@
#define POKEMON_NAME_LENGTH 10
#define OT_NAME_LENGTH 7
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) >= (b) ? (a) : (b))
+
#define HEAP_SIZE 0x1C000
extern u8 gStringVar1[];
diff --git a/ld_script.txt b/ld_script.txt
index 871729691..345afb27f 100644
--- a/ld_script.txt
+++ b/ld_script.txt
@@ -484,7 +484,7 @@ SECTIONS {
src/battle_controller_link_partner.o(.rodata);
src/battle_message.o(.rodata);
data/cable_car.o(.rodata);
- data/save.o(.rodata);
+ src/save.o(.rodata);
data/field_effect_helpers.o(.rodata);
data/contest_ai.o(.rodata);
src/battle_controller_safari.o(.rodata);
diff --git a/src/save.c b/src/save.c
index 023ca6870..138ec7cce 100644
--- a/src/save.c
+++ b/src/save.c
@@ -4,13 +4,67 @@
#include "constants/game_stat.h"
#include "task.h"
+// for the chunk declarations
+extern struct SaveBlock2 gSaveblock2;
+extern struct SaveBlock1 gSaveblock1;
+extern struct PokemonStorage gPokemonStorage;
+
extern struct SaveSectionLocation gRamSaveSectionLocations[0xE];
extern u8 gDecompressionBuffer[];
extern u32 gFlashMemoryPresent;
extern u16 gUnknown_03006294;
extern bool8 gSoftResetDisabled;
-extern const struct SaveSectionOffsets gSaveSectionOffsets[0xE];
+// Divide save blocks into individual chunks to be written to flash sectors
+
+// Each 4 KiB flash sector contains 3968 bytes of actual data followed by a 128 byte footer
+#define SECTOR_DATA_SIZE 3968
+#define SECTOR_FOOTER_SIZE 128
+
+/*
+ * Sector Layout:
+ *
+ * Sectors 0 - 13: Save Slot 1
+ * Sectors 14 - 27: Save Slot 2
+ * Sectors 28 - 29: Hall of Fame
+ * Sectors 30 - 31: e-Reader battle tower data, maybe? (note: depreciated in Emerald US)
+ *
+ * There are two save slots for saving the player's game data. We alternate between
+ * them each time the game is saved, so that if the current save slot is corrupt,
+ * we can load the previous one. We also rotate the sectors in each save slot
+ * so that the same data is not always being written to the same sector. This
+ * might be done to reduce wear on the flash memory, but I'm not sure, since all
+ * 14 sectors get written anyway.
+ */
+
+// (u8 *)structure was removed from the first statement of the macro in Emerald.
+// This is because malloc is used to allocate addresses so storing the raw
+// addresses should not be done in the offsets information.
+#define SAVEBLOCK_CHUNK(structure, chunkNum) \
+{ \
+ chunkNum * SECTOR_DATA_SIZE, \
+ min(sizeof(structure) - chunkNum * SECTOR_DATA_SIZE, SECTOR_DATA_SIZE) \
+} \
+
+const struct SaveSectionOffsets gSaveSectionOffsets[] =
+{
+ SAVEBLOCK_CHUNK(gSaveblock2, 0),
+
+ SAVEBLOCK_CHUNK(gSaveblock1, 0),
+ SAVEBLOCK_CHUNK(gSaveblock1, 1),
+ SAVEBLOCK_CHUNK(gSaveblock1, 2),
+ SAVEBLOCK_CHUNK(gSaveblock1, 3),
+
+ SAVEBLOCK_CHUNK(gPokemonStorage, 0),
+ 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),
+};
extern void DoSaveFailedScreen(u8); // save_failed_screen
extern void LoadSerializedGame(void); // load_save