Skip to content

Reuse filler save space for Variables and Flags

Kyra Zimmer edited this page Apr 25, 2022 · 6 revisions

This is an alternative to 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:

#define ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT 116
#define ADDITIONAL_SAVE_PAYLOAD_SIZE (ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT*NUM_SECTORS_PER_SLOT)
extern u8 gAdditionalSaveData[];

in src/save.c, add (before the gSaveDataBuffer at the start):

EWRAM_DATA u8 gAdditionalSaveData[ADDITIONAL_SAVE_PAYLOAD_SIZE];

Saving the data

then, still in src/save.c, add this at the end of HandleWriteSector (right before the return line):

for (i = 0; i < ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT; i++)
  gReadWriteSector->unused[i] = gAdditionalSaveData[i + 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):

for (j = 0; j < ADDITIONAL_SAVE_PAYLOAD_SIZE_PER_SLOT; j++)
  gAdditionalSaveData[j + 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:

#include "save.h"

then, in the same file, in GetVarPointer, add this right before the last else:

else if (id >= 0xF000)
  return &gAdditionalSaveData[(id - 0xF000)*2];

and in GetFlagPointer, again before the last else:

else if (id >= 0xF000)
  return &gAdditionalSaveData[(id - 0xF000)/8];

Defining Variables and Flags

define them as usual in include/constants/flags.h and include/constants/vars.h, starting from 0xF000:

#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)
  • Flags are 1bit long (ID gets divided by 8).

so the above examples would then internally look like this (do not actually put this code anywhere, it's just to show a comparison how the data would look like):

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!

Clone this wiki locally