Entry 16
The memory card save format
Documented in The memory card save.
Filesdocs/formats/save.md
A .hack save is the game's whole ccSaveData object written to the memory
card as it sits in memory, plus a small per-slot index. Because the DWARF
names every member of ccSaveData (6), the save format is known field by
field without ever having looked at a real save file. The layout is on
the save page.
Where it goes
ccMcard (mcard.cpp) builds every path the same way: a directory from
mcDirName[volumeNum - 1] (INF SLUS_202.67:0x00306be0), a /, and a file
from mcFname (0x00306d40). The four directories are
BASLUS-20267DOTHACK - Infection's own product code, SLUS-20267 - and three
placeholders, BASLUS-00001DOTHACK, -00002 and -00003, which read as
slots reserved for the other three volumes before their product codes
existed. volumeNum is 1 in the executable's data. The slot files are
dhdata01 to dhdata13 (mcFname[1..13]). The slot index is written by
ccMcard::SaveSys (0x001664b0) to the directory name repeated - it
strcpys and then strcats the same mcDirName entry - so Infection's is
/BASLUS-20267DOTHACK/BASLUS-20267DOTHACK, the usual PS2 practice of naming
the main file after its directory. mcFname[0], BISLPS-00000HUCKER, is not
used by SaveSys; what uses it is not known.
ccMcard::MakeDir (0x001659b0) writes /icon.sys (it builds a PS2D
header) and the icon files, taking the icons from \DATA\ICON.BIN;1 through
iconBinTbl (0x00306c00, twelve {offset, size} pairs) and iconName
(icon10.ico, icon11.ico, icon12.ico, icon20.ico ... icon42.ico).
ICON.BIN is therefore twelve PS2 icons at 90,112-byte strides, three per
volume.
What is written
ccSaveSys::MainProccess (0x00171c20, a 9 KB state machine) saves in two
writes (at 0x00173e10 and 0x00173e4c):
ccMcard::SaveSys(port, 0, info, 336)-ccSaveSys.info[12], twelve 28-byteccSaveDataInfoslot records:status,level,clearFlag,parodyFlag,char name[18],u16 sum,int playtime.ccMcard::DataWrite(port, 0, slot, saveData, 0x8530)- the wholeccSaveDataobject, 34,096 bytes, verbatim.
Before the second write the slot record is refreshed from the save: status 1,
level and name from spcParam[0] (the player character, +0x7488), play time
from +0x8400, clear and parody flags from +0x842a and +0x842b, and sum.
sum is the 16-bit sum of all 0x8530 bytes of the save data (the loop at
0x001724cc); a load compares it against the slot record at 0x001724f8 and
rejects the file on a mismatch. ccSaveSys::CheckRightInfo (0x001716e0)
validates all twelve records: an empty slot (status 0) must be all zeros, a
used one (status 1) needs level 0-99, clearFlag 0-4, parodyFlag 0-1 and a
play time below 0x0CDFE5C4 - 215,999,940 sixtieths of a second, 999:59:59.
Carrying over between volumes
ccSaveSys keeps a second array, infoPrev[12] (+0x150), with
LoadInfoPrevReq and LoadDataPrevReq beside the ordinary loads: the
machinery for reading the previous volume's saves. clearFlag runs 0 to 4,
one per volume. In Infection, the first volume, those paths have nothing to
read; how Mutation uses them is a question for that disc.
ccSaveData::ConvGame (0x001752a0, sdmng.cpp) rebuilds party parameters
from charTbl (in the demo overlay) and then calls LoadGame and
InitTradeItem; no relocation in main or any overlay calls it, so in this
build it may be dead code.
What the save holds
98 members, among them: both player names (plName, plRealName), item
lists for 18 characters, trade lists, skills, growth, the mail list and its
order, web news and bulletin board read flags, 160 event entries, the Chaos
Gate lists and records, the keyword list (wordList[15]), 512 64-bit event
flags (eventFlag, +0x54f8 - the flags ccEvent::Execute sets), area bans
and protected areas, Grunty and dog counters, Data Drain counts, per-enemy kill
counts and kill areas for 313 enemies, all 18 characters' parameters, play
time, the pad assignment, volumes, voice and parody flags, and 250 reserved
bytes.
what mcFname[0] (BISLPS-00000HUCKER) is for; the icon.sys fields the game fills in; which of the twelve icons each volume uses for list, copy and delete; the meaning of most event-flag bits; whether ConvGame is reachable; how the later volumes read Infection's saves.