SavePatch File Format Documentation¶
The SavePatch file format is a text-based format used to define cheat codes, patches, and modifications for game save files. This format is parsed by Apollo Save Tool to apply modifications to game save data.
Basic Syntax Rules¶
Case Sensitivity: Most tags are case-insensitive except where noted
Comments: Lines starting with
;are commentsLine Endings: Can use
\nor\r\n(automatically normalized)Whitespace: Trailing spaces are trimmed from lines
Encoding: Plain ASCII text (UTF-8 may work but not guaranteed)
Error Handling¶
The parser is generally tolerant of formatting issues:
Missing closing tags may cause parsing errors
Malformed hex values may not be detected until patch application
Empty or malformed lines are skipped
Unknown directives are ignored
File Structure¶
SavePatch files are plain text files with a specific structure that includes file specifications, code definitions, options, and metadata. The format uses special markers and syntax to define different elements.
Header¶
The file header (optional) consists of 3 lines with the following format:
Syntax:
;Game ID
;Game Title/Name
;Author/Source
Example:
;CUSA00542
;The Last of Us Remastered
;by Bucanero
File target Specification¶
The file must begin with a file specification that tells Apollo which save files the patch applies to.
The target Save file is required to be declared once, but can be declared multiple times if needed to apply codes to different files. Wildcards are supported.
Syntax:
:<folder_pattern\>{file_pattern}
The Save Folder part is optional, and it only needs the folder name. The program uses it to disable the cheats if a different folder name is used.
For instance, :PROFILE-FOLDER\SAVEFILE.DAT if the cheat only works in the profile folder.
Examples:
:BLES00001-SAVEDATA\SAVEDATA.DAT
:*.DAT
:SAVE?.BIN
File Patterns
:- Colon indicates file specification lineExact filename - Apply to specific file only
Wildcards - Use
*for multiple characters,?for single characterPath support - Can include directory paths (use
\as separator)
Example:
:BLES00049PROFILE002\EM_GAME.DAT
Here, BLES00049PROFILE002 is the Save Folder, and
EM_GAME.DAT is the target Save Data file name.
If only the file name is used, the folder is not validated.
Example:
:EM_GAME.DAT
If the code is valid for multiple Save files, you can use the asterisk * wildcard.
Example:
:*.SAV
Option Definitions Section¶
Options allow users to select different variations of a patch (e.g., different amounts of money, different items).
Syntax:
{option_tag}value1=name1;value2=name2;...{/option_tag}
Examples:
{MONEY}000186A0=99,999;000F4240=1,000,000{/MONEY}
{WEAPON}01=Iron Sword;02=Steel Sword;03=Diamond Sword{/WEAPON}
Option Structure
Opening tag:
{OPTION_NAME}Value-Name pairs:
value=Display Nameseparated by;Values are zero-padded hex strings (e.g., “000186A0” for 0x186A0)
Closing tag:
{/OPTION_NAME}Values must be fixed width (padded with zeros)
Code Definition Sections¶
Each cheat code or patch is defined in its own section with a title and code lines.
Code Title Syntax:
[CODE_TITLE]
; some comments
code line 1
code line 2
...
Special Title Prefixes
[DEFAULT:...]- Code is activated by default[INFO:...]- Informational/alert message[PYTHON:...]- Python script code[SW:...]- Save Wizard / Game Genie code (force type and skip auto-detection)[BSD:...]- BSD script code (force type and skip auto-detection)[LE:...]- Read/write this code’s data as little-endian[BE:...]- Read/write this code’s data as big-endian[GROUP:...]- Group header for organizing codes
Prefixes combine, in any order and any number. Each one is read off the front
of the title and the next is tried against what is left, so
[DEFAULT:PYTHON:Name] is a Python code, ticked by default, named Name:
[INFO:PYTHON:Read me first]
[BE:SW:Max Money (PS3)]
Where two of them say the same kind of thing, the last one written wins:
[SW:BSD:Name] is a BSD script, and [LE:BE:Name] is big-endian.
[GROUP:...] is the exception – it names a heading rather than a code, so
it is read on its own and does not combine.
The reading stops at the first word that is not a prefix, so a code whose name
genuinely begins with one of these words followed by a colon would lose it.
[INFO:BE: watch the byte order] is an alert about byte order to a human,
but to the parser it is a big-endian code named watch the byte order.
Code Lines
Code lines follow the title and contain the actual patch data:
[Money 9,999,999]
80010004 12345678
28000004 0098967F
Code Types
The parser detects code types automatically:
Game Genie / Save Wizard - every code line is exactly
XXXXXXXX YYYYYYYYBSD Script - anything else
Python Script (when
[PYTHON:...]prefix is used)
Detection reads the body, so a Save Wizard code with one mistyped line is taken
for a BSD script and fails to run, and a BSD script whose every line happens to
have that shape is taken for Save Wizard. [SW:...] and [BSD:...] state
the type instead, and a stated type is never overridden by the body:
[SW:Max Money]
80010004 12345678
28000004 0098967F
Byte Order
[LE:...] and [BE:...] state the byte order of the save data one code
writes, overriding for that code alone whatever the host selected with
apollo_set_endianness():
[BE:Max Money (PS3)]
20000004 0098967F
This is for a patch that mixes byte orders, or one shipped for a big-endian platform that should not depend on the front-end guessing right. Most patches need neither: the host sets the mode once for the save it is patching.
Two things to know:
Only Save Wizard codes act on it, where it governs every multi-byte read and write the code makes. The prefix is still parsed on a BSD or Python code and shows up in
flags, but nothing reads it there – a BSD script controls byte order itself withendian_swap.Unlike
[SW:...]and[BSD:...], these do not state the code type. The body still decides it, so[BE:...]on a code whose lines are not allXXXXXXXX YYYYYYYYgives a BSD script that happens to carry an ignored flag. Combine the two when you mean both:[BE:SW:...].
Game Genie / Save Wizard Codes¶
To define a Save Wizard / Game Genie code, simply write the code lines
after declaring the code name between square brackets. (Example: [Cheat Name])
Example:
:PLAY.DAT
[Max HP & SP Points]
2000006C 0001869F
20000170 0001869F
Python Script Codes¶
To define a Python script code,
write the script lines after declaring the code name
between square brackets and the [python:Cheat Name] tag.
Example:
:SAVE*.DAT
[Python:99 Upgrade points]
import apollo
pos = apollo.search(savedata, "VoiceOfThePeople")
savedata[pos + 32] = 0x63
print("Written value:", savedata[pos + 32])
BSD Script Codes¶
To define a BSD script code, write the script lines after declaring the code name
between square brackets. (Example: [Cheat Name])
Example:
:SAVE.DAT
[BSD Example 1]
;Searches for the word "difficulty" as text.
search "difficulty"
;Overwrites with the text at 0 bytes after the found offset.
; in this case "next 0" is at the found offset.
; "next (10)" or "next 0xA" would write 10 bytes after the found offset.
write next 0: "VeryEasy"
[BSD Example 2]
;Addresses enclosed in parenthesis are treated as decimal.
; Like (99) = 0x63
write at (99): 0x446966666963756C7479
;The following 2 lines are equivalent:
write at (99): 0x446966666963756C7479
write at 0x63: "Difficulty"
Option Substitution in Codes¶
Options can be referenced within code lines using the option tag:
80010004 12345678
28000004 0{MONEY}
The
{MONEY}placeholder will be replaced with the selected valueMultiple options can be used in a single code
Options can appear anywhere in the code line
Using Cheat Status¶
Cheats Status flags are detected in the cheat code name.
info:→ If the cheat name starts withINFO:the text is shown with an alert icon.default:→ The patch is activated by default.(Required)→ If a patch code is mandatory to work (like a checksum update), adding the(Required)tag makes the code to be auto-added when the user selects any code.
Example:
[INFO: This Patch may not work]
;The text is shown with an alert icon.
04000000 00000018
[DEFAULT:Max 99 Lives]
; This code is activated by default
0000ABCD 00000063
[Unlock All Character Bios (Required)]
;The code is required and will be auto-added when the user selects any other code.
94000000 00000018
4A000000 00000001
402A0004 00000000
Grouping Codes¶
Codes can be grouped together using group headers:
[GROUP:Cheat Category 1]
[Infinite Health]
...code lines...
[Infinite Ammo]
...code lines...
GROUP:Cheat Category 2
[Unlock All Weapons]
...code lines...
[GROUP:...]starts a groupSubsequent codes belong to the group until next group header
The current Group can be ended with a
[Group:\]separator
Example:
[group:Group #1]
; The patches that follow this label are grouped as childs.
[default:Cheat 1]
00000000 00000000
[Another Cheat in Group #1]
10000123 0000ABCD
[group:Group #2]
[Cheat in Group #2]
00000000 00000000
[group:\]
; Ends the current group.
[info:Cheats below do not work]
[Cheat 2 (partial working)]
00000000 00000000
[Cheat 3 (not working)]
00000000 00000000
Complete Example¶
Here’s a complete SavePatch file example:
; CUSA00001
; Example Game
; Author: Cheat Author
; ============================================
:BLES00001-SAVEDATA\SAVEDATA.DAT
{MAXMON}000186A0=99,999;000F4240=1,000,000{/MAXMON}
{LV}0001=Level 1;000A=Level 10;0032=Level 50{/LV}
[GROUP:Basic Cheats]
[DEFAULT:Max Money]
80010004 12345678
28000004 {MAXMON}
[INFO:This cheat gives you maximum money]
; This is just a comment showing info
[Max Level]
80010004 23456789
28000004 0000{LV}
[GROUP:Advanced Cheats]
[Unlock All Weapons]
80010004 34567890
28000004 FFFFFFFF
[Group:\]
; Ends the current group.
[PYTHON:Custom CRC32 Script (Required)]
# Python script embedded in savepatch
import uhashlib
# Custom patch logic to update checksum
crc = uhashlib.crc32(savedata[0x10:])
savedata[4:8] = crc
Notes¶
Text Editors: Any plain text editor can create/edit files
Best Practices¶
Always include file specification as the first non-comment line
Use consistent hex formatting (uppercase, fixed width)
Test options with all possible values
Include comments for complex patches
Use groups to organize related cheats
Validate patch files with Apollo CLI before distribution