Reference ยท Disc

The four discs

What changes from volume to volume, and how the stripped executables of volumes 2 to 4 get their names. Each disc is described file by file on its own page: Infection, Mutation, Outbreak, Quarantine. Everything here is measured against Infection's.

Volumes

INFMUTOUTQUA
game.hack//Infection.hack//Mutation.hack//Outbreak.hack//Quarantine
boot ELF (SYSTEM.CNF)SLUS_202.67SLUS_205.62SLUS_205.63SLUS_205.64
sectors1,268,8321,830,4481,859,6002,176,912
files869396100
boot ELF bytes19,223,3882,669,3922,649,8081,546,192
symbolsall, with DWARFnonenonenone
main section0x00100000 + 0x278880+ 0x28b800+ 0x286b80+ 0x179480
$gp0x0037faf00x00392a700x0038ddf00x00280770
overlay window0x004008000x004138000x0040f2000x00301b00
heap section0x007306000x00774b000x007737800x00670300
DATA.BIN bytes136,665,088138,172,416142,372,864142,372,864
DATA.BIN records1,0231,0311,0721,072
categoryFDTbl0x002fb7500x00310fd00x003087000x001fc680
cateCDOfsTbl0x002fb7a00x003110200x003087500x001fc6d0

All four SYSTEM.CNF files read VER = 1.00, VMODE = NTSC. Each executable carries the string MW MIPS C Compiler (2.4.1.01). The three stripped ones keep Infection's section layout by position (main, the four overlay sections, heap) with the names blanked; tools/image.py maps them by that order.

The four overlays (GCMN.PRG, DEMO.PRG, DESKTOP.PRG, TOPPAGE.PRG) are the same PRG format on every disc, loaded at that volume's window. DATA.BIN is the same archive on every disc; tools/fdtbl.py check passes every record of all four.

Files that differ

directoryINFMUTOUTQUA
root4444
DATA7779
MODULES12121010
PSS4444
STREAM4866
VOICE28291313
VOICE_E27291312
VOICE2--2121
VOICE2_E--1821
  • STREAM: INF has STR1, STR1E, STRCMN, STRCMNE. MUT adds STR2, STR2E, STRSUB, STRSUBE. OUT and QUA keep only the English (E) archives: OUT STR1E-STR3E, STRCMNE, STRSUBE and STRT; QUA STR1E-STR4E, STRCMNE, STRSUBE.
  • MODULES: OUT and QUA drop CDVDFSV.IRX and CDVDMAN.IRX, which no volume loads: every disc's CD drivers are IOPRP243.IMG's (the IOP image).
  • DATA: QUA adds KFED.BIN (688,000 bytes) and KFAED.BIN (35,200).
  • VOICE2: the characters' skill words, moved out of VOICE on OUT and QUA, with three new characters' (the Outbreak DVD).
  • STREAM/STRT.BIN (OUT only): six scenes no code opens, demo discs' screens (the Outbreak DVD).
  • IOPRP243.IMG, DATA/ICON.BIN, the logo movies, OUTSIDE.BIN and eight of the modules are byte-identical on all four discs. Each disc's page says, file by file, which other discs hold the same bytes.

The font tables in Quarantine

Infection keeps its bitmap fonts in the executable, between the last code and the first data: kf14x16 (385,280 bytes), kf20x20 (688,000), kfa20x20 (35,200), kfa14x16 (19,712), ef12x20 (13,440), ef8x16 (7,168), 1,148,800 bytes in all. From the end of the code to the first named data object is 1,166,168 bytes in INF, 1,122,628 in MUT and 1,175,028 in OUT, but only 36,868 in QUA.

MUT and OUT embed all six byte-identical to INF. QUA embeds only ef12x20 and ef8x16 - the two that INF's code uses - and ships KFED.BIN and KFAED.BIN, the same sizes and sheet layout as kf20x20 and kfa20x20. In INF the four kanji sheets are unreferenced. KFED's bytes differ (0.2% equal) because the palette indexes changed (background 1 in INF, 0 in QUA) and the glyphs were re-shaded; most of the ink falls in the same places. See text rendering.

DATA.BIN across volumes

Records per category, from each executable's own tables:

categoryINFMUTOUTQUA
desktop136136177177
spc18212121
pc37383838
town14151515
event50535353
the other 15samesamesamesame
  • MUT drops pc/CBUZ.CCS and adds 9 records: CTBUZ and CTWMK (pc), CHA3BODY, CTU4BODY, CWM5BODY (spc), TOWN06, and HANABIRA1, X7478CAM, X7484CAM (event). Of the 1,022 records in both INF and MUT, 992 inflate to the same size.
  • OUT adds 41 desktop records to MUT's (ENDING, XDDWAL56 onward, ...) and drops none.
  • OUT and QUA have the same 1,072 records. Five members differ: four desktop images (XDDN_050, XDDN_400, XDDN_490, XDDN_690, same size, different content) and boss/X11.CCS (310,052 bytes in OUT, 326,660 in QUA).

Names for the stripped executables

piney-gen syms writes each later volume's <elf>.syms (tools/xfer.py match did until 2026-09-27, byte for byte the same), and tools/image.py loads it automatically for an executable with no symbol table, so disasm.py, fdtbl.py and the rest work on every volume by Infection's names. One symbol per line, tab-separated:

section  va(8 hex)  size  FUNC|OBJECT  name  how

section is main or an overlay name. how says which pass named it:

howmeaning
exactthe body equals Infection's with address fields masked, uniquely
callthe target of a call, or a function address taken, from a paired body
orderbetween two paired neighbours, aligned by the shape of its code
datathe global a paired body addresses at the same instruction, or in the same place in the order of the addresses it builds
pointera global a carried global points at, where Infection's relocation says it points (a unanimous vote also moves a data name)
contenta global found by what it holds: its numbers equal, its pointers to the same strings; not when two of Infection's hold the same
layoutbetween two carried globals whose words agree and which sit the same distance apart in both, a global at its offset whose words agree (90%), or a data name moved there because they agree better; or two data names of one size that agree better each at the other's place
refa function that builds a carried global's (or a string's) address, where only one function does on each side

FUNC sizes are the destination's own (to the next entry point, less padding), except for exact, whose size is Infection's.

MUTOUTQUA
exact3,5181,0291,026
call604500499
order1,2143,3313,311
data4,3293,2623,248
pointer1,0931,3431,333
content1,6621,5331,505
layout173140136
ref37270
total12,59611,21011,128

The last four passes were added for the per-volume data (plans/volumes.md): Outbreak's and Quarantine's recompiled EVENTAREA and ROOTTOWN constructors carried no names, so their tables were found by content and the constructors by the tables and strings they build. The order is content, pointer, layout, content again, ref, pointer again: what a global holds outranks a table's pointer to it, since a table can keep Infection's layout while rows are added to what it points at (Mutation's pcMsg4). The pointer pass does not take a pointer's bytes for text (0x006f2d98 reads "\x98-o").

The data pass pairs a function's globals by the order its code builds them, and a reordered function misleads it. The layout pass found, on all three: BGTBL and BGTBL2 swapped (so every BG_TBL_x the pointer pass reached through them was BG_TBL_x2), BgMatName unnamed, the Grunties' voice tables (gusoponTbl to aquaTblE) each on its neighbour, and tradeMenuStr, evs209Tbl and eleven stream tables elsewhere. Each moved name was checked: Infection's bytes at its new place, not its old one. In .bss nothing tells, so no span is anchored or filled there: a first try placed main's SkillDamageValueAttributeCritical 8 bytes off, which test_battle.py's run of Mutation's ccSkillDamageValue caught.

Infection has 4,998 functions of 6 or more instructions across main and the overlays. MUT's code is mostly Infection's instruction for instruction. OUT and QUA were compiled differently:

  • saved registers are allocated differently;
  • branch delay slots Infection fills are often left as nops;
  • fptoui is inlined. So there only about a fifth match exactly, and link order does most of the work.

Precision, measured by carrying names back: MUT's names onto Infection give 9,512 symbols, 7 wrong (0.07%). OUT's names onto Infection give 7,927, 18 wrong (0.23%). The wrong order names sit on a neighbouring function; the wrong data names on a different object, or inside a larger one. Two functions with identical bodies (_kill_r, __sigtramp) cannot be told apart.

Systems across volumes

Each system below was checked by running every volume's own code in tools/eemu.py against the Python reimplementation, with the differences read from each executable rather than keyed on the volume:

systemchanged in later volumespage
area generatorareas 71 and 47 become substitute records; keyword and story-area table editsarea keywords
dungeonsfloor count a field (15 for area 125), 90 hand-made dungeons, a new save bit in the type ruledungeons
fieldssqrt.s in OUT/QUA; area 100 unprotectedfields
battleExdefense rule, 21 party members, table rebalancingbattle
textccKanjiStrlen counts every %x in OUT/QUA; more mails and repliestext rendering
event scriptsopcodes 168, 169, a new operand for 99, new events per volumeevents
savesa 0x854-byte extension for the three new characters; carry-oversave

This work also found carried names that are wrong or missing:

  • MUT's MailTbl points into desktop.prg's code.
  • MUT's skillTbl points 0x11b0 bytes into the table.
  • OUT's and QUA's skillTbl, and MUT's enemyTbl, are not named at all.

The tools find these tables from the code that uses them instead.

What the later volumes' code adds

tools/voldiff.py gaps ELF measures, section by section, the text the carried names do not cover, and lists the stretches between two named functions; tools/voldiff.py look ELF SECTION LO HI prints the strings a stretch materialises and the named functions it calls, which tells new code from code compiled too differently to be matched. On Infection itself only main's embedded fonts show.

INFMUTOUTQUA
main text0x2759680x2888680x283be40x1764e4
main unnamed, less the fonts0x1600x19ed00x1541c0x1ca88
GCMN.PRG text0x1d0fc00x1ec2400x1ee3400x1f2dc0
GCMN.PRG unnamed0x78 (0.0%)0x112c0 (3.5%)0x4be00 (15.4%)0x510d0 (16.2%)
DESKTOP.PRG unnamed0.1%0.1%1.4%1.4%
TOPPAGE.PRG, DEMO.PRG unnamed0.6%, 0.4%0.9%, 0.4%1.4%, 0.6%1.4%, 0.4%
stretches1380173170

(Measured 2026-09-27; the carry has named more since the first count.) Every stretch is listed, with its neighbours, strings and calls, in the later volumes' unnamed code.

"Less the fonts" leaves out the one stretch from DEG2RAD to the static constructors: the bitmap fonts (in QUA, which moved two of them to KFED.BIN and KFAED.BIN, whatever took their place, 0x86ac4 bytes).

The stretches of 8 KB or more, and what they are:

volumewherebyteswhat (by its strings and calls)
MUT, OUT, QUAmain, before ccInitStreamDemoThread0xffb4 / 0x10584 / 0x17ce4the new streams' effect functions (Func_str0710e, str1070e, str1430e: ccRasterNoize, ccBufferSampling, ccBufferReverce, fades)
MUTmain, after ccEvent::Execute0x3490the event engine's new instructions (overlay loads, SimGenerateCode, RoomSelect, party add and delete, gate list, items)
MUT, OUTmain, after Func_str90010x332c / 0x2778stream str9001's effects (OBJ_se1_6flo1)
MUT, OUT, QUAgcmn, after BIRD::Move0x3cf8 / 0x3c94 / 0x85b4the Grunty race (PG_RACE, town06, the xp_ cups, flags and count); QUA adds its staff roll (STFROLL_VOL4) and the hacking logos
MUT, OUT, QUAgcmn, after AreaInfoMenu0x59c4 / 0x5b20 / 0x5b20a new menu (messages, OpenInfo, number input)
OUT, QUAgcmn, after ccBoss08KillerEye::OnThinkDead0x25da0Kyvia's fights (kyviaCore, Kyvia01-04, the ex0-ex4 models, the boss camera and particles)
OUT, QUAgcmn, after ccFellowCheckNote0x10ec0the Root Towns 02-05 (town02-05 static models, their water and lights) and the party of 12 and more (SPC_01-SPC_12, expulsionSpc)
OUT, QUAgcmn, after EVENTAREA::EVENTAREA0xaf60the other event areas (se1_1, se1_2, se2_1, se2_6: their static models, animations, lens flares)
OUT, QUAgcmn, after ccEnemyG::actEscapeGold0xa6ccthe enemy races recompiled (their constructors, acts, breath), with ccEnemyL's type 3 (OBJ_elg1body)

MUT's code is Infection's with these additions. OUT and QUA were compiled differently, so part of what shows there is Infection's code under other register choices (the enemy races are); the Kyvia fights, the towns and the event areas are new.

Settled

What this page once left open:

  • KFED.BIN / KFAED.BIN. Event opcode 169 (Quarantine's ending) reads both and frees them after the staff roll (STFROLL_VOL4); no instruction reads them in between. The staff roll draws its text with the executable's own fonts (the Quarantine DVD).
  • STRT.BIN. Six scenes no code opens: the Infection and Mutation demo discs' title screens, a "February 2003" teaser and a four-part selector (the Outbreak DVD).
  • VOICE2. The characters' skill-word banks: Infection's 18, moved, and Tsukasa's, Subaru's and Sora's (the Outbreak DVD).
  • The CD modules. They did not move into IOPRP243.IMG; the image already carried newer ones on every disc. Infection's and Mutation's MODULES/CDVD*.IRX (1.04) were never loaded; the image's (2.26) are (the IOP image).
  • The stretches. All 423 are listed with what can be read of them (the later volumes' unnamed code).

Unknown

  • The names of the functions in the unnamed stretches: none survive to carry. They are read from their strings and calls, and from their code where a system is ported.