From 71e035331a462dffe59e419c8820855c87f36293 Mon Sep 17 00:00:00 2001 From: Kyra Zimmer Date: Mon, 25 Apr 2022 15:34:47 +0200 Subject: [PATCH] Created Reuse filler save space for Variables and Flags (markdown) --- ...ller-save-space-for-Variables-and-Flags.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Reuse-filler-save-space-for-Variables-and-Flags.md diff --git a/Reuse-filler-save-space-for-Variables-and-Flags.md b/Reuse-filler-save-space-for-Variables-and-Flags.md new file mode 100644 index 0000000..9b846c1 --- /dev/null +++ b/Reuse-filler-save-space-for-Variables-and-Flags.md @@ -0,0 +1,83 @@ +This is an alternative to [Extra save space with two lines of code](Extra-save-space-with-two-lines-of-code). +The Tutorial linked above will increase the already existing SaveBlock areas, while this will instead add another one "in between" the original ones to keep compatibility to vanilla savegames. + +## Defining the space + +in `include/save.h`, add: + +```c +#define N_ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT 116 +#define N_ADDITIONAL_SAVE_PAYLOAD_SIZE (N_ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT*NUM_SECTORS_PER_SLOT) +extern u8 gnAdditionalSaveData[]; +``` + +in `src/save.c`, add (before the `gSaveDataBuffer` at the start): +```c +#if NCHI__ADDITIONAL_SAVE_PAYLOAD +EWRAM_DATA u8 gnAdditionalSaveData[N_ADDITIONAL_SAVE_PAYLOAD_SIZE]; +#endif +``` + +## Saving the data + +then, still in `src/save.c`, add this at the end of `HandleWriteSector` (right before the `return` line): +```c +for (i = 0; i < N_ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT; i++) + gReadWriteSector->unused[i] = gnAdditionalSaveData[i + N_ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT*sectorId]; +``` +also add the exact same code again in `HandleReplaceSector`, right before the `EraseFlashSector(sector);` line. + +## Loading the data + +still in `src/save.c`, add this in `CopySaveSlotData`, right before the end of the `if` block (and after the end of the inner `for` loop): +```c +for (j = 0; j < N_ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT; j++) + gnAdditionalSaveData[j + N_ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT*id] = gReadWriteSector->unused[j]; +``` + +# Accessing Variables and Flags + +in `src/event_data.c`, add this at the top to the includes: +```c +#include "save.h" +``` + +then, in the same file, in `GetVarPointer`, add this right before the last `else`: +```c +else if (id >= 0xF000) + return &gnAdditionalSaveData[(id - 0xF000)*2]; +``` + +and in `GetFlagPointer`, again before the last `else`: +```c +else if (id >= 0xF000) + return &gnAdditionalSaveData[(id - 0xF000)/8]; +``` + +# Defining Variables and Flags + +define them as usual in `include/constants/flags.h` and `include/constants/vars.h`, starting from `0xF000`: +```c +#define FLAG_FOR_SOMETHING_SUPER_SPECIAL 0xF000 +#define FLAG_FOR_SOMETHING_TOTALLY_BORING 0xF001 + +#define VAR_FOR_SOMETHING_SUPER_SPECIAL 0xF001 +#define VAR_FOR_SOMETHING_TOTALLY_BORING 0xF002 +``` + +# CAVEAT + +To save on space (because I don't know what your game will need), variables and flags both **share the same data space**, so make sure they don't overlap. Variables are 16bit long (so their ID gets multiplied by 2 to get the byte offset into `gnAdditionalSaveData`), and Flags are 1bit long (ID gets divided by 8). + +so the above examples would then internally look like this: +```c +struct{ + u8 FLAG_FOR_SOMETHING_SUPER_SPECIAL : 1; // flag with ID 0xF000 at bit 0 of byte 0 + u8 FLAG_FOR_SOMETHING_TOTALLY_BORING : 1; // flag with ID 0xF001 at bit 1 of byte 0 + u8 filler; // an unused byte because none of the IDs maps to it + u16 VAR_FOR_SOMETHING_SUPER_SPECIAL; // var with ID 0xF001 at bytes 2 and 3 + u16 VAR_FOR_SOMETHING_TOTALLY_BORING; // var with ID 0xF002 at bytes 4 and 5 +}; +``` + +if instead you would have more flags, or e.g. a var with ID `0xF000` (which would be at bytes 0 and 1), this would clash and corrupt your data! \ No newline at end of file