Skip to content

Save Functions

SpiredMoth edited this page Sep 16, 2019 · 13 revisions

Block Offsets

Gen 4 save files store 2 sets of save data (current and backup), broken up into 3 blocks apiece and the blocks can be mixed up within the file. A Gen 4 save file could look like the following:

  • Save data 1 (starting at 0x0): backup general block, current storage block, backup HoF block
  • Save data 2 (starting at 0x40000): current general block, backup storage block, current HoF block
int sav_sbo();
int sav_gbo();

// example usage
int ofs = sav_gbo() + 0x0;

These are only needed for Gen 4 (DP, PT, HGSS).

The return values of sav_gbo and sav_sbo point you the proper portion of the file containing the current version of the general and storage blocks respectively.

A value of 0 is returned if used on a Gen 5+ save, meaning they'll have no adverse effect on setting offsets on other games.

Value Access

int sav_get_max(enum SAV_MaxField field, ...);

enum SAV_MaxField {
    MAX_SLOTS,
    MAX_BOXES,
    MAX_WONDER_CARDS,
    MAX_SPECIES,
    MAX_MOVE,
    MAX_ITEM,
    MAX_ABILITY,
    MAX_BALL,
    MAX_FORM,
    MAX_IN_POUCH
};

// example usage
int totalSpecies = sav_get_max(MAX_SPECIES);
int pikachuForms = sav_get_max(MAX_FORM, 25);
int maxMedicine = sav_get_max(MAX_IN_POUCH, Medicine);

Used to get max values associated with the currently loaded save. Most fields will not require a second argument. Notable caveats and arguments are:

  • MAX_FORM: Requires a species number as an argument
  • MAX_IN_POUCH: Returns the maximum amount of items for the save. Requires an enum Pouch (see below).
int sav_get_value(enum SAV_Field field, ...);

enum SAV_Field
{
    SAV_OT_NAME,
    SAV_TID,
    SAV_SID,
    SAV_GENDER,
    SAV_COUNTRY,
    SAV_SUBREGION,
    SAV_REGION,
    SAV_LANGUAGE,
    SAV_MONEY,
    SAV_BP,
    SAV_HOURS,
    SAV_MINUTES,
    SAV_SECONDS,
    SAV_ITEM
};

// example usage
char *otName = (char *)sav_get_value(SAV_OT_NAME);
int tid = sav_get_value(SAV_OT_TID);
int firstMedicine = sav_get_value(SAV_ITEM, Medicine, 0);

Used to get values out of the currently loaded save. Most fields will not require even a second argument. See below for what fields are available. Notable caveats and arguments are:

  • SAV_OT_NAME: Returns a UTF-8 formatted string that must be manually freed. Cast to char* to use it properly
  • SAV_TID and SAV_SID: Both return the 5-digit format
  • SAV_ITEM: Requires an enum Pouch and a slot number. Returns the item ID of the specified slot
enum Pouch {
    NormalItem,
    KeyItem,
    TM,
    Mail,
    Medicine,
    Berry,
    Ball,
    Battle,
    Candy,
    ZCrystals
};

Strings

char* sav_get_string(unsigned int offset, unsigned int codepoints);

Used to get a UTF-8 encoded string from an arbitrary offset in the save, stopping at the null terminator.

  • codepoints is the character limit, including the null terminator.
  • Returned string must be manually freed.

NOTE: This was added to the API after the release of PKSM 7.0.1

void sav_set_string(char* string, unsigned int offset, unsigned int codepoints);

Used to write a UTF-8 string to an arbitrary offset in the save, and overwrites unnecessary bytes with 0. codepoints is the character limit, including the null terminator.

Box Data Encryption

void sav_box_decrypt();
void sav_box_encrypt();

IMPORTANT: These should always be used as a pair and always in this order. Mixing them or not using them in pairs will produce unpredictable results.

Any edits you aim to make should be done after calling sav_box_decrypt and before calling sav_box_encrypt.