Skip to content

Save Functions

Chris Feger edited this page Jun 17, 2020 · 13 revisions

Value Access

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 (see General Enums and Structs: Pouch) and a slot number. Returns the item ID of the specified slot

Wonder Cards

int sav_wcx_free_slot();

Gets the first empty Wonder Card slot, or, if all are filled, the maximum index.

void sav_inject_wcx(char* data, enum Generation type, int slot, int alternateFormat);

Injects a wonder card.

  • data should be a pointer to the Wonder Card data in the correct format for the generation. If the Wonder Card data passed in is not in the correct format, issues will occur.
  • slot refers to which Wonder Card slot it should be injected to, though GEN_LGPE does not store Wonder Cards, and, as such, this argument does not affect it.
  • alternateFormat is a boolean that refers to the format of the data passed in, based on the value of enum Generation type as follows:
    • GEN_FOUR: if true, data is interpreted as a WC4 (meaning that the internal Pokémon data is decrypted). Otherwise, data will be interpreted as a PGT.
    • GEN_FIVE: ignored
    • GEN_SIX: if true, data is interpreted as a WC6FULL. Otherwise, data will be interpreted as a WC6
    • GEN_SEVEN: if true, data is interpreted as a WC7FULL. Otherwise, data will be interpreted as a WC7
    • GEN_LGPE: if true, data is interpreted as a WB7FULL. Otherwise, data will be interpreted as a WB7

Values

void sav_get_data(char* dataOut, unsigned int size, int off1, int off2);
void sav_set_data(char* data, unsigned int size, int off1, int off2);
int sav_get_bit(int off1, int off2, int bitNum);
void sav_set_bit(int bitVal, int off1, int off2, int bitNum);
char sav_get_byte(int off1, int off2);
void sav_set_byte(char data, int off1, int off2);
short sav_get_short(int off1, int off2);
void sav_set_short(short data, int off1, int off2);
int sav_get_int(int off1, int off2);
void sav_set_int(int data, int off1, int off2);
char* sav_get_string(int off1, int off2, unsigned int codepoints);
void sav_set_string(char* string, int off1, int off2, unsigned int codepoints);

These functions are used to read data from and write data to the save. All functions with get will retrieve data, and all with set will write it. off1 and off2 work as follows:

  • In Generations 4-7 and LGPE, off1 and off2 are added together to get the final offset.
  • In Generation 3 and 8, off1 indicates the block used.
    • In Generation 3, values -1-13 are allowed for off1: 0-13 indicate the block index to use, and -1 indicates that the offset is absolute.
    • In Generation 8, any value that is a block key is allowed for off1. There is no indication that an offset is absolute, as there are no absolute offsets in G8 saves.
  • In Generations 3 and 8, off2 is the offset from the start of the block indicated by off1.
  • sav_get_bit will return 0 for unset and 1 for set, and sav_set_bit's bitVal argument should be 0 for unset and 1 for set.
  • bitNum is zero-indexed from the least-significant bit. An example:

Byte value: 0x7B | bitNum | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | Value returned | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |

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.