-
Notifications
You must be signed in to change notification settings - Fork 4
Save Format
The save slots in Final Fantasy VII save files have identical structure between various platforms, but the save file headers/footers and number of save slots per file differ between platforms. This wiki and Black Chocobo are excellent resources for learning more about Final Fantasy VII save files.
The save file begins with a file header. The format of this header differs between the game platforms (see Version/Format Differences).
After the header, the save file contains the save slot(s). Note that the PlayStation and PlayStation Vita formats only have a single save slot, whereas all others explored in this write-up have 15.
With the exception of the PC version of Final Fantasy VII, all save slots start with a 512 byte header, the contents of which I don't know. The PC version has no save slot headers.
All versions of Final Fantasy VII store the core save slot data in the same format, and it is always exactly 4,340 bytes in size. All of the following offsets are given such that 0x0000
denotes the start of the Save Slot Data.
Offset (bytes) | Size (bytes) | Description |
---|---|---|
0x0000 |
4 | Checksum |
0x0004 |
1 | Preview: Lead Character's Level |
0x0005 |
1 | Preview: Party Portrait 1 |
0x0006 |
1 | Preview: Party Portrait 2 |
0x0007 |
1 | Preview: Party Portrait 3 |
0x0008 |
16 | Preview: Lead Character's Name |
0x0018 |
2 | Preview: Lead Character's Current HP |
0x001A |
2 | Preview: Lead Character's Maximum HP |
0x001C |
2 | Preview: Lead Character's Current MP |
0x001E |
2 | Preview: Lead Character's Maximum MP |
0x0020 |
4 | Preview: Total Gil |
0x0024 |
4 | Preview: Total Playtime (seconds) |
0x0028 |
32 | Preview: Save Location |
0x0048 |
3 | RGB Color of Upper-Left Corner of Window |
0x004B |
3 | RGB Color of Upper-Right Corner of Window |
0x004E |
3 | RGB Color of Lower-Left Corner of Window |
0x0051 |
3 | RGB Color of Lower_Right Corner of Window |
0x0054 |
132 | Character Record: Cloud |
0x00D8 |
132 | Character Record: Barret |
0x015C |
132 | Character Record: Tifa |
0x01E0 |
132 | Character Record: Aerith |
0x0264 |
132 | Character Record: Red XIII |
0x02E8 |
132 | Character Record: Yuffie |
0x036C |
132 | Character Record: Cait Sith |
0x03F0 |
132 | Character Record: Vincent |
0x0474 |
132 | Character Record: Cid |
0x04F8 |
1 | Party Portrait 1 |
0x04F9 |
1 | Party Portrait 2 |
0x04FA |
1 | Party Portrait 3 |
0x04FB |
1 | Blank 1 (0xFF ) |
0x04FC |
640 | Item Stock (2 bytes/slot, 320 slots) |
0x077C |
800 | Materia Stock (4 bytes/slot, 200 slots) |
0x0A9C |
192 | Materia Stolen by Yuffie (4 bytes/slot, 48 slots) |
0x0A9C |
32 | Unknown 4 (all 0xFF ?) |
0x0B7C |
4 | Total Gil |
0x0B80 |
4 | Total Playtime (seconds) |
0x0B84 |
4 | Countdown (seconds) |
0x0B88 |
4 | Total Playtime Seconds Fraction (1/65535 seconds) |
0x0B8C |
4 | Countdown Seconds Fraction (1/65535 seconds) |
0x0B90 |
6 | Current Module (0x000000000100 : Field, 0x020000000300 : World Map) |
0x0B96 |
2 | Current Location |
0x0B98 |
2 | Blank 2 (0xFFFF ) |
0x0B9A |
2 | Map Location: X-Coordinate (signed) |
0x0B9C |
2 | Map Location: Y-Coordinate (signed) |
0x0B9E |
2 | Map Location: Triangle ID |
0x0BA0 |
1 | Direction of Player Model on Map |
0x0BA1 |
1 | Encounter Timer: Step ID / Seed |
0x0BA2 |
1 | Encounter Timer: Offset |
0x0BA3 |
1 | Blank 3 (0x00 ) |
0x0BA4 |
2 | Plot Progression Variable |
0x0BA6 |
1 | Yuffie's Initial Level (must be 0 before she joins the party) |
0x0BA7 |
1 | Love Points: Aerith |
0x0BA8 |
1 | Love Points: Tifa |
0x0BA9 |
1 | Love Points: Yuffie |
0x0BAA |
1 | Love Points: Barret |
0x0BAB |
1 | Temporary Party Placeholder: Character 1 |
0x0BAC |
1 | Temporary Party Placeholder: Character 2 |
0x0BAD |
1 | Temporary Party Placeholder: Character 3 |
0x0BAE |
6 | Unknown 9 (all 0x00 ?) |
0x0BB4 |
1 | Game Timer: Hours (0-255) |
0x0BB5 |
1 | Game Timer: Minutes (0-60) |
0x0BB6 |
1 | Game Timer: Seconds (0-60) |
0x0BB7 |
1 | Game Timer: Frames (0-30) |
0x0BB8 |
1 | Countdown Timer: Hours (0-255) |
0x0BB9 |
1 | Countdown Timer: Minutes (0-60) |
0x0BBA |
1 | Countdown Timer: Seconds (0-60) |
0x0BBB |
1 | Countdown Timer: Frames (0-30) |
0x0BBC |
2 | Number of Battles |
0x0BBE |
2 | Number of Escapes |
0x0BC0 |
2 | Visible Menu Items |
0x0BC2 |
2 | Locked Menu Items |
0x0BC4 |
4 | Unknown 10 (always 0x00 ?) |
0x0BC8 |
1 | Field Items 1 |
0x0BC9 |
1 | Field Items 2 |
0x0BCA |
10 | Unknown 11 (all 0x00 ?) |
0x0BD4 |
1 | Field Items 3 |
0x0BD5 |
1 | Field Items 4 |
0x0BD6 |
14 | Unknown 12 |
TODO | TODO | TODO |
Note that items starting with "Preview:" are purely cosmetic (they appear in the preview in the save menu), and only changing these will not impact the game.
Recall that the first 4 bytes of a save slot are the checksum. The checksum is computed as follows, where slot_data
is the raw bytes of a save slot, excluding the checksum (i.e., excluding the aforementioned first 4 bytes). I learned this algorithm from the code in this forum post by dziugo.
def checksum(slot_data):
r = 0xFFFF
pbit = 0x8000
for t in slot_data:
r ^= (t << 8)
for _ in range(8):
if r & pbit:
r = (r << 1) ^ 0x1021
else:
r <<= 1
r &= 0xFFFF
return (r ^ 0xFFFF) & 0xFFFF
To fix the checksums of every save slot in a Final Fantasy VII save file, you can use this tool, which was originally written by dziugo and was updated by me.
Every character has a character record in the following format, and it is always exactly 132 bytes in size. All of the following offsets are given such that 0x00
denotes the start of the character record.
Offset (bytes) | Size (bytes) | Description |
---|---|---|
0x00 |
1 | Vincent → Sephiroth Flag |
0x01 |
1 | Level (0-99) |
0x02 |
1 | Strength (0-255) |
0x03 |
1 | Vitality (0-255) |
0x04 |
1 | Magic (0-255) |
0x05 |
1 | Spirit (0-255) |
0x06 |
1 | Dexterity (0-255) |
0x07 |
1 | Luck (0-255) |
0x08 |
1 | Strength Bonus (from Power Source) |
0x09 |
1 | Vitality Bonus (from Guard Source) |
0x0A |
1 | Magic Bonus (from Magic Source) |
0x0B |
1 | Spirit Bonus (from Mind Source) |
0x0C |
1 | Dexterity Bonus (from Speed Source) |
0x0D |
1 | Luck Bonus (from Luck Source) |
0x0E |
1 | Current Limit Level (1-4) |
0x0F |
1 | Limit Bar (0 = empty, 255 = Limit Break) |
0x10 |
12 | Character Name |
0x1C |
1 | Equipped Weapon |
0x1D |
1 | Equipped Armor |
0x1E |
1 | Equipped Accessory |
0x1F |
1 | Character Flags (0x10 : Sadness, 0x20 : Fury) |
0x20 |
1 | Character Order (0xFF : Normal, 0xFE : Back) |
0x21 |
1 | Level Progress (0-63; <4 hidden by game GUI) |
0x22 |
2 | Learned Limit Skills |
0x24 |
2 | Number of Kills |
0x26 |
2 | Number of Limit 1-1 Uses |
0x28 |
2 | Number of Limit 2-1 Uses |
0x2A |
2 | Number of Limit 3-1 Uses |
0x2C |
2 | Current HP |
0x2E |
2 | Base HP (before materia) |
0x30 |
2 | Current MP |
0x32 |
2 | Base MP (before materia) |
0x34 |
4 | Unknown 2 |
0x38 |
2 | Maximum HP (after materia) |
0x3A |
2 | Maximum HP (after materia) |
0x3C |
4 | Current Experience |
0x40 |
32 | Weapon Materia (4 bytes/slot, 8 slots) |
0x60 |
32 | Armor Materia (4 bytes/slot, 8 slots) |
0x80 |
4 | Experience Until Next Level |
The learned limit skills are stored in 16 bits (i.e., 2 bytes) in the following format:
MSB LSB
[ 0 ][ 0 ][ 0 ][ 0 ][ 0 ][ 0 ][4-1][ 0 ][3-2][3-1][ 0 ][2-2][2-1][ 0 ][1-2][1-1]
-
MSB
= Most Significant Bit -
LSB
= Least Significant Bit -
[A-B]
= Limit A-B (i.e., the B-th limit in level A)- For example,
[3-1]
denotes Limit 3-1: the first limit in Limit Level 3 - 1 = learned, 0 = not learned
- For example,
-
[ 0 ]
= 0 bit
Each record in the Item Stock has 2 bytes, and there are 320 item slots, so the Item Stock is 640 bytes total. For each item record, the first byte denotes the item ID, and the second byte denotes the item quantity. However, because there are more than 256 items in the game (there are 319, excluding key items), some items share the same ID byte, and the quantity byte is leveraged to identify which of the two possible items it is.
For ID bytes between 0x00
and 0x3F
, if the quantity byte is even, the slot contains the "even item" corresponding to that ID byte, and if the quantity byte is odd, the slot contains the "odd item" corresponding to that ID byte. The actual quantity of the item is the quantity byte divided by 2 (ignore remainder). For ID bytes larger than 0x3F
, the approach is the same, but only "even items" exist.
For example, for the ID byte 0x03
, the "even item" is Ether, and the "odd item" is Mythril Armlet. Thus, if the 2-byte item slot is 0x03
0x07
, the quantity byte (7) is odd, meaning we have the "odd item" (Mythril Armlet), and the actual quantity is floor(7/2) = 3. Thus, 0x03 0x07
means we have 3 Mythril Armlets.
A database of Final Fantasy VII items can be found in PyFF7.
Each record in the Materia Stock has 4 bytes, and there are 200 materia slots, so the Materia Stock is 800 bytes total. For each materia record, the first byte denotes the materia ID, and the remaining 3 bytes are an unsigned integer representing the materia's AP. A database of Final Fantasy VII materia can be found in PyFF7.
At various points in the game, menu items can be (in)visible or (un)locked. Specifically, the Materia and PHS menu items are invisible at the beginning of the game (Materia is made visible first, followed later by PHS), and at parts of the game in which you can't switch characters, the PHS menu item is visible but is locked. For the Visible Menu Items bytes, 1 = visible and 0 = invisible. For the Locked Menu Items bytes, 1 = locked and 0 = unlocked. The order of the bits is as follows (for both Visible Menu Items and Locked Menu Items):
MSB LSB
[ 0 ][ 0 ][ 0 ][ 0 ][ 0 ][ 0 ][Save][PHS][Config][Limit][Order][Status][Equip][Materia][Magic][Item]
-
MSB
= Most Significant Bit -
LSB
= Least Significant Bit -
[ 0 ]
= 0 bit
The field items flags for any location are a single byte, where each bit represents a specific item that can be found. A bit value of 1 means the item has been picked up, and a bit value of 0 means it has not been picked up. This is the format for all field items bytes:
MSB LSB
[ H ][ G ][ F ][ E ][ D ][ C ][ B ][ A ]
-
MSB
= Most Significant Bit -
LSB
= Least Significant Bit
- This seems to be the Train Graveyard
-
[ A ]
= Hi-Potion (mds7st1 / Barrel 1) -
[ B ]
= Echo Screen (mds7st1 / Barrel 2) -
[ C ]
= Potion (mds7st2 / Floor 2) -
[ D ]
= Ether (mds7st2 / Floor 3) -
[ E ]
= Hi-Potion (mds7st1 / Roof Train 1) -
[ F ]
= Potion (mds7st1 / Inside Train 2) -
[ G ]
= Potion (mds7st1 / Floor 1) -
[ H ]
= Hi-Potion (mds7st2 / Roof Train 2)
- This seems to be the Great Glacier
-
[ A ]
= Elixir (hyou8_2/tr00/s1) -
[ B ]
= Potion (hyou5_1/tr00/s1) -
[ C ]
= Safety Bit (hyou5_3/trbox/s1) -
[ D ]
= Mind Source (hyou2/trbox/s1) -
[ E ]
= Sneak Glove (mkt_w/event/s1) -
[ F ]
= Premium Heart (mkt_ia/event/s3, mkt_ia/line00/s4) -
[ G ]
=0x00
(None) -
[ H ]
=0x00
(None)
- This seems to include Aerith's home, the farm, and parts of the Midgar slums
-
[ A ]
= Potion (md8_3/p/s1) -
[ B ]
= Potion + Phoenix Down (ealin_2/zu/s1) -
[ C ]
= Ether (eals_1/p/s1) -
[ D ]
= Cover Materia (eals_1/mp/s1) -
[ E ]
= Choco-Mog Summon (farm/dancer/s1) -
[ F ]
= Sense Materia (mds6_22/mat/s1) -
[ G ]
= Ramuh Summon (crcin_2/mat/s1) -
[ H ]
= Mythril Key Item (zz1/m1/s1)
- This seems to be the Materia Cave and Northern Cave
-
[ A ]
= Mime Materia (zz5/l1,l2,l3,l4/s1) -
[ B ]
= HP<->MP Materia (zz6/mat/s1) -
[ C ]
= Quadra Magic Materia (zz7/l1,l2,l3,l4/s1) -
[ D ]
= Knights of the Round Summon (zz8/l1,l2,l3,l4/s1) -
[ E ]
= Elixir (las3_1/hako1/s1, las4_0/cid/s1) -
[ F ]
= X-Potion (las3_1/hako2/s1) -
[ G ]
= Turbo Ether (las3_2/hako1/s1, las4_0/tifa/s1, las4_0/cait/s1) -
[ H ]
= Vaccine (las3_2/hako2/s1, las4_0/yufi/s1)
With the exception of the PC version of Final Fantasy VII, all save slots end with a 3,340 byte footer, the contents of which I don't know. The PC version has no save slot footers.
Format | File (bytes) | Header (bytes) | Slots | Slot Header (bytes) | Slot Footer (bytes) |
---|---|---|---|---|---|
DEX | 134,976 | 12,096 | 15 | 512 | 3,340 |
Mem Card | 131,072 | 8,192 | 15 | 512 | 3,340 |
PC Version | 65,109 | 9 | 15 | 0 | 0 |
PSP Version | 131,200 | 8,320 | 15 | 512 | 3,340 |
PSV Version | 8,324 | 132 | 1 | 512 | 3,340 |
PSX Version | 8,192 | 0 | 1 | 512 | 3,340 |
VGM Version | 131,136 | 8,256 | 15 | 512 | 3,340 |
- File Header
-
Save Slot(s)
-
Save Slot 1
- 0 or 512 bytes (Save Slot Header)
- 4,340 bytes (Save Slot Data)
- TODO
- 0 or 3,340 bytes (Save Slot Footer)
- ...
-
Save Slot 1
Niema Moshiri 2019