Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pmret/papermario/llms.txt

Use this file to discover all available pages before exploring further.

Paper Mario stores game state in two parallel arrays inside each save slot: a packed bit array for boolean flags (globalFlags) and a byte array for counters and multi-state values (globalBytes). These arrays are exposed to EVT scripts through the GF (global flag) and GB (global byte) variable encoding, giving every script in the game read/write access to persistent state without going through a C API call.

Save file layout

The game supports four independent save slots. The global settings file (SaveGlobals) is separate and holds data shared across all slots — sound mode, the most recently selected file, and the language setting on PAL versions.
EEPROM / Controller Pak
├── SaveGlobals  (0x80 bytes)  — sound, last file, language
├── SaveData[0]  (0x1380 bytes) — slot 1
├── SaveData[1]  (0x1380 bytes) — slot 2
├── SaveData[2]  (0x1380 bytes) — slot 3
└── SaveData[3]  (0x1380 bytes) — slot 4
Each SaveData record begins with the magic string "Mario Story 006" and two 32-bit CRC fields used to detect corruption. The fio_load_game / fio_save_game / fio_erase_game functions in src/fio.h are the only callers that read or write raw save data directly.

Global flags (GF_)

Global flags are single-bit boolean values stored in the globalFlags[64] field of SaveData — 64 words of 32 bits each, giving 2,048 addressable bits. In practice only indices up to 0x7FF are used. Each flag is named in include/saved_flag_names.h inside the GameFlags enum:
enum GameFlags {
    GF_StartedChapter1              = GameFlag(0x001),
    GF_StartedChapter2              = GameFlag(0x002),
    GF_KMR02_Met_Goombario          = GameFlag(0x024),
    GF_TRD10_Defeated_KoopaBros     = GameFlag(0x297),
    GF_KKJ25_Defeated_Bowser        = GameFlag(0x1FD),
    // ...
};

Naming convention

GF_<area>_<event> where:
  • GF_ identifies a global (saved) flag, as opposed to a local LF_ (local flag) or area-scoped AF_.
  • <area> is the four-letter map area code — for example KMR (Koopa Meadows), TRD (Koopa Fortress), MAC (Toad Town), KKJ (Bowser’s Castle). Flags not tied to a single area use EVT, NPC, or BTL.
  • <event> is a PascalCase description — Met_Goombario, Item_ShootingStar, Defeated_KoopaBros.
Slots that were allocated in the original ROM but never written to are named GF_Unused_<area>_<hex>.

Example: chapter-start flags

GF_StartedChapter1 = GameFlag(0x001), // set when Chapter 1 begins
GF_StartedChapter2 = GameFlag(0x002),
GF_StartedChapter3 = GameFlag(0x003),
GF_StartedChapter4 = GameFlag(0x004),
GF_StartedChapter5 = GameFlag(0x005),
GF_StartedChapter6 = GameFlag(0x006),
GF_StartedChapter7 = GameFlag(0x007),
GF_StartedChapter8 = GameFlag(0x008),

Global bytes (GB_)

Global bytes are 8-bit values stored in globalBytes[512] inside SaveData. Each byte can hold a value from 0 to 255. They are used for counters, multi-state machines, and any value that needs more than two states. Each byte is named in include/saved_byte_names.h inside the GameBytes enum:
enum GameBytes {
    GB_StoryProgress                = GameByte(0x000),
    GB_MAC00_DojoRank               = GameByte(0x01C),
    GB_TIK15_RipCheato_PurchaseCount = GameByte(0x038),
    GB_IWA00_Whacka_HitCount        = GameByte(0x07B),
    GB_CompletedQuizzes             = GameByte(0x160),
    GB_FinalBowserHP                = GameByte(0x18A),
    // ...
};

Naming convention

GB_<area>_<description> — the same area-code convention as flags, but with a GB_ prefix. Unused slots are GB_Unused_<area>_<hex>.

Notable bytes

ConstantIndexDescription
GB_StoryProgress0x000Current chapter checkpoint; maps directly to the StoryProgress enum
GB_KMR20_MarioReadDiaryFlags_000x00CTracks which diary pages Mario has read
GB_MAC01_Merlon_SpinJumpCount0x01BNumber of spin jumps performed for Merlon’s tutorial
GB_MAC00_DojoRank0x01CPlayer’s rank at the Toad Town Dojo (0–4)
GB_MAC03_LilOinkCount0x01DNumber of Lil’ Oinks in the pen
GB_MAC01_Rowf_NumBadges0x02CHow many badges Rowf has unlocked
GB_TIK15_RipCheato_PurchaseCount0x038Items bought from Rip Cheato
GB_IWA00_Whacka_HitCount0x07BNumber of times Whacka has been struck
GB_KKJ_CaughtCount0x04FHow many times Peach has been caught per mission
GB_OMO_TrainDestination0x0D7Current Shy Guy’s Toy Box train route destination
GB_CompletedQuizzes0x160Total Chuck Quizmo quizzes answered correctly
GB_FinalBowserHP0x18ABowser’s HP carried from Phase 1 into Phase 2
GB_WorldLocation0x1A9Encodes Mario’s current world-map position

Using GF and GB in EVT scripts

Inside an EVT script, you reference a global flag or byte by passing its enum value as an argument to the appropriate script command. The EVT interpreter decodes the encoded integer at runtime — you never dereference it yourself.
// Read a flag into local variable LVar0
Set(LVar0, GF_StartedChapter1)

// Write a flag
Set(GF_KMR02_Met_Goombario, TRUE)

// Read a byte into local variable LVar1
Set(LVar1, GB_MAC00_DojoRank)

// Write a byte
Set(GB_IWA00_Whacka_HitCount, LVar2)
GameFlag(INDEX) and GameByte(INDEX) are macros that subtract large offsets from the index so that the result falls in a special negative range. The EVT runtime identifies the variable type from that range. Passing a raw index like 0x001 instead of GF_StartedChapter1 will not work — always use the named enum constant.

Area flags and area bytes

In addition to global flags and bytes, each save slot stores a smaller set of area-scoped values that are cleared whenever you enter a new world area:
  • areaFlags[8] — 256 bits of area-local boolean flags, accessed with AreaFlag(INDEX) / AF_ names.
  • areaBytes[16] — 16 bytes of area-local state, accessed with AreaByte(INDEX).
Area values are useful for events that should reset between visits to an area — for example, tracking whether a respawning coin has been collected during the current visit.

Save file I/O functions

The C API for reading and writing save data is declared in src/fio.h:
bool fio_load_globals(void);   // load SaveGlobals from storage
bool fio_save_globals(void);   // write SaveGlobals to storage
bool fio_load_game(s32 saveSlot); // load SaveData for slot 0–3
void fio_save_game(s32 saveSlot); // write SaveData for slot 0–3
void fio_erase_game(s32 saveSlot); // erase SaveData for slot 0–3
Slot indices are zero-based (03), corresponding to the four save files shown on the file-select screen.
The extern arrays gSaveSlotMetadata[4] and gSaveSlotHasData[4] in src/fio.h hold the per-slot summary records and presence flags loaded at boot. Check gSaveSlotHasData[slot] before calling fio_load_game to avoid reading uninitialised memory.

Build docs developers (and LLMs) love