SAV
Jump to navigation
Jump to search
This article (or part thereof) is obsolete. It may have made sense in the past, but it does not make sense now. It is kept here only for historic curiosity and/or posterity.
This is the documentation for the old save format. The current format is RSAV
A SAV file consists of binary records of 30000 16-bit INTs (60000 bytes). The number of records varies, but is typically 4 for the for normal save games, or 32 when the F2/F3 quicksave has been used. The records from 5 thru 31 are only accessible via plotscripting,
Integer Offset | Data Size | Name | in-memory storage | Notes |
---|---|---|---|---|
0 | INT | SAV version | Always 3 for current games | |
1 | INT | current map | map | |
2 | INT | hero X | catx(0) | This is relative to the SAV offset in the MAP lump for the current map |
3 | INT | hero Y | caty(0) | This is relative to the SAV offset in the MAP lump for the current map |
4 | INT | hero direction | catd(0) | |
5 | INT | random battle counter | foep | Decremented when you walk, random battle occurs when it reaches zero |
6 | INT | Unused | Used to be leader (and I don't remember what that means) | |
7 | INT | camera x position | mapx | Not relative to SAV offset in MAP, but maybe it should be? |
8 | INT | camera y position | mapy | Not relative to SAV offset in MAP, but maybe it should be? |
9-33 | INT*25 | Money | gold& | Money converted to a string, and stored as ascii digits, one per INT, with zero-padding on the end (profound shame) |
34-138 | INT*105 | General data | gen() | Element 0-104 of the global gen() array. (a few elements of this are ignored when loading. See GEN) |
139-535 | INT*396 | Unused | Used to contain additional elements of gen() | |
536-2634 | INT*300 | NPC x | npc().x | Current locations and state of NPC instances. see SerNPCL code |
INT*300 | NPC y | npc().y | ||
INT*300 | NPC ID | npc().id | ||
INT*300 | NPC direction | npc().dir | ||
INT*300 | NPC frame | npc().frame | ||
INT*300 | NPC x move | npc().xgo | ||
INT*300 | NPC y move | npc().ygo | ||
2635 | INT | Unused | ||
2636-2762 | BIT*2048 | tags | tag() | bit 0 and 1 always zero. Bit 2-999 are tags Bit 1000-1999 are one-time-use bits Bits 2000-2047 are unused |
2763-2803 | INT*41 | hero ID | hero() | hero ID numbers + 1, or 0 for empty party slots |
2804-3304 | INT*501 | Unused? | used to contain an array named a() and danged if I can remember what that was | |
3305-4452 | INT*41*2*14 | Hero stats | stat() | Hero stats. 41 groups of 28 ints for each hero. Current stats 0-13 first, max stats 0-13 next. See stat() for details |
4453-4698 | INT*41*6 | battle menus | bmenu() | Hero battle menus. 41 groups of 6 ints for each hero |
4699-8798 | INT*41*4*25 | spell lists | spell() | Hero spell lists. 41 groups of 4 spell lists for each hero. Each spell list contains 24 ints of attack ID numbers and one wasted int at the end of each list. |
8799-9126 | INT*41*8 | level mp | lmp() | Hero level-MP. 41 groups of 8 ints |
9127-11258 | INT*41*2*26 | Experience | exlev&() | Hero experience levels stored in the same shameful format as the gold. 41 groups of 2 badly stored numbers of 26 ints each, first current experience then next-level experience. Each number is stored as a string with one ascii char per int, zero padded at the end |
11259-11955 | INT*41*17 | her names | name$() | Hero names. 41 badly stored strings of 17 ints each. One ascii char per int, zero padded at the end. |
11956-14594 | INT | 8/16 bit inventory magic | 0 if the inventory is stored here in 8-bit format. 1 if the inventory is stored at 14800 in 16-bit format | |
INT*2 | Unused | (great exploding snakes on toast! Who designed this format! ... or yeah... I did) | ||
INT*198 | Inventory 8-bit | inventory().num inventory().id |
198 ints with item ID in the low 8 bits and item count in the high 8 bits | |
INT*38 | Unused | |||
INT*198*12 | useless item names | inventory().text | Item names, one ascii char per int. It is a mystery to me why we ever stored these here, since they can be easily re-generated from the other data. | |
INT*24 | Unused | |||
14595-14799 | INT*205 | Equipment | eqstuf() | Hero equipment. 41 groups of 5 ints |
14800-14999 | INT*100*2 | Inventory 16-bit first 100 | inventory() | 100 pairs of 2 ints for the first 100 inventory slots. First item id, second item count. Ther rest of the inventory is stored later. |
15000-19999 | INT*100*50 | Shop stock | stock() | Shop stock. 50 ints per shop for 100 shops. |
20000-20003 | BIT*64 | Hero locks | hmask() | Bits 0-40 are locks to prevent swapin/swapout of heroes. bits 41-63 are wasted |
20004-20012 | INT*9 | Caterpillar hero positions | catx() caty() catd() |
3 sets of 3 ints for the other three heroes in the caterpillar party. x,y,direction |
20013-21037 | INT*1025 | script globals 0-1024 (low 16 bits) | global() | Low 16 bits of script globals |
21038-21059 | INT * 22 | Vehicle data | veh() | Current vehicle data (see VEH#Implementation Note) |
21060 | INT | Pic+Pal+Def magic | 4444 if the following picture and palette and default weapon data is stored | |
21061-21306 | INT*41*2*3 | hero pic, pal, and default weapon | stat() | Extended hero data. 41 sets of 6 ints, from stat() elements (,,14) thru (,,16) See stat() for details |
21307 | INT | Hbits magic | 4444 if the following hero bits data is stored | |
21308-21512 | BIT*41*80 | Hero bits | nativehbits() | Hero bitsets. 41 sets of 80 bits. See DT0 |
21513-22537 | INT*1025 | script globals 0-1024 (high 16 bits) | global() | High 16 bits of script globals |
22538-28679 | INT*2*3071 | script globals 1025-4095 low 16, high 16 pairs in that order | global() | more globals |
28680-29679 | INT*500*2 | Inventory 16-bit remainder | inventory() | 500 pairs of 2 ints for the inventory slots 100-599. First item id, second item count. |
29680-29999 | INT*320 | Unused | Unused |