Skip to content

Latest commit

 

History

History
152 lines (126 loc) · 6.96 KB

File metadata and controls

152 lines (126 loc) · 6.96 KB

04 — The source tree, recovered from the debug hunks

Produced by tools/hunk.py and tools/modmap.py; raw output in notes/cosm-hunks.txt and notes/source-modules.txt.

/cosm was linked with its debug information intact. It carries 78 HUNK_DEBUG blocks: one index and 77 line-number tables, one per assembler source file. Between them they name every module of the game, its directory, the first source line that produced code, and where in the binary that code starts.

The block format

The index block is a Devpac/HiSoft-style header:

ULONG  0
char   "HEADDBGV01"
...
ULONG  77                     number of following blocks
ULONG  offset[77]             file offset of each HUNK_DEBUG that follows

Each of the 77 blocks is an HCLN line table:

ULONG  0
char   "HCLN"
ULONG  name length in longwords
char   name[]                 NUL-padded, e.g. "CDCODE/CDXLINT.S"
ULONG  count                  number of line-table entries
UBYTE  first_line             first source line that emitted code
UBYTE  0
UWORD  start | 1              start offset, low bit set as an end marker;
                              if this word reads 0, a ULONG start | 1 follows
(UBYTE line_delta, UBYTE byte_delta) x count

The variable-width start offset is the only awkward part: small offsets are stored as a word with bit 0 set, large ones as a longword with the same convention and a zero word in front of them. The decoding was checked against the disassembly rather than assumed — MAIN/NVL.S lands exactly on the nonvolatile.library calls, FUNCTIONS/READJOYPORT.S exactly on the lowlevel.library ReadJoyPort call, and DECRUNCH/DECRUNCHER.S exactly on the routine the CPIC handler branches to.

The (line_delta, byte_delta) stream decodes cleanly for most modules and desynchronises for a handful, so this document does not quote per-module code sizes. The module names, their entry counts and their first code offsets are solid; the byte totals are not, and the honest form of that is to leave them out. The "gap to next" column in notes/source-modules.txt is the distance to the next module's first byte, which is an upper bound and not a size.

The tree

Fourteen directories. Reconstructed from the 77 names:

cosm.s
MAIN/           GLOBALGFX  NVL  LOOKATCD  GLOBALAUDIO  PT_RBFINTERRUPT  LOADLEVEL
PLINK/          READDATA
LEVELS/         FIRSTDEATH  DEATHPLSTUB  DEATH1..5  EOLBDIE1..5
                EOLBTWEEN1..5  EOLBKILLYOU1..5  WSTO1..5  CORELEVEL  GAMEOVER
CDCODE/         INITCD  CDXLINT  DOOROPENINT  CDALIASES  FILELIST
TASKS/          CDTASK  CONSOLETASK  DECRUNCHTASK  DECRAM
DECRUNCH/       DECRUNCHER  CLEARBORDER
FRAMEHANDLERS/  INTERACTIVE256  NONINTERACTIVE32  NONINTERACTIVE64
                NONINTERACTIVE128  NONINTERACTIVE256
COPPER/         BBITCOPPERLIST  CBITCOPPERLIST  DBITCOPPERLIST  EBITCOPPERLIST
                DOUBLECBITCOPPERLIST  DOUBLEDBITCOPPERLIST  DOUBLEEBITCOPPERLIST
                COLOURCOPPERLIST  LOGOCOPPERLIST
INTERRUPTS/     GLOBALVBLINT  GLOBALAUDIOINT
VBLHOOKS/       GLOBALVBLCOMMANDHANDLER
FUNCTIONS/      WAIT  GRABA5  MAKETASK  GETSIGNAL  INITMSGPORT  DRAWSPRITE
                READJOYPORT
AUDIO/          VBLAUDIO
DEBUG/          PRINT  NUM  DEBUGCOPPERLIST
SYSTEM/         SYSTEM

What the shape says

The whole game is one program with five level scripts. LEVELS/ holds five parallel families — DEATHn, EOLBDIEn, EOLBTWEENn, EOLBKILLYOUn, WSTOn — one per level, all five present, all five with real code in the binary including the 4 variants whose end-of-level boss was never built (03). WSTO is the waystation, the hub the game returns to between levels; waystat.code is the overlay that goes with it.

The five FRAMEHANDLERS/ modules are the five video modes, and they line up one-for-one with the copper lists:

frame handler copper list bitplanes colours
NONINTERACTIVE32.S BBITCOPPERLIST.S 5 32
NONINTERACTIVE64.S CBITCOPPERLIST.S (and DOUBLE) 6 64
NONINTERACTIVE128.S DBITCOPPERLIST.S (and DOUBLE) 7 128
NONINTERACTIVE256.S EBITCOPPERLIST.S (and DOUBLE) 8 256
INTERACTIVE256.S DOUBLEEBITCOPPERLIST.S 8 256

The B/C/D/E naming is a plane count in a private notation and the mapping was read out of the copper lists themselves, not guessed (08). The single INTERACTIVE handler is the one used while the player is flying; everything else on the disc — logos, briefings, the theatre, the boss cut-scenes — runs through a non-interactive handler.

DECRUNCH/ is the video codec, not a file cruncher. Nothing on this disc is compressed in the ordinary sense (05 covers the census). DECRUNCH/DECRUNCHER.S starts at hunk offset 0x0a3b0, and the CPIC chunk handler at 0x979e branches straight to 0x0a3b8. TASKS/DECRUNCHTASK.S is the task that drives it and TASKS/DECRAM.S manages its buffers. DECRUNCH/CLEARBORDER.S blanks the frame around the 320 x 144 picture.

CDCODE/FILELIST.S is generated and it is the largest module in the program. 3,444 line-table entries, first byte at hunk offset 0x0b420, and it runs from there to the end of the 106,232-byte code hunk — 60,120 bytes, 56.6 % of all the code in cosm. It is not code. It is a table of 48-byte records describing contiguous segments of /cbmbuild:

ULONG  offset into cbmbuild
ULONG  length of the segment
ULONG  a per-segment size
ULONG x 9   the largest chunk sizes in the segment, for buffer sizing

and the offsets chain exactly — 0x1a20ec + 0x212fe0 = 0x3b50cc, the next record's offset, and so on. The nine trailing longwords in the first record are 33f8 2e40 31dc 36f4 3bb4 3cec 4238 4568 4970 4910, which are the first frame sizes at the head of cbmbuild itself. A 3,444-line generated assembler source whose only job is to tell the loader how big to make its buffers.

The two eleven-byte files /filelist.i and /filelist.s in the disc's root are the ghosts of the generator that produced it (11).

PLINK/ is a directory of one file, READDATA.S, fifteen line entries. The name is presumably a Psygnosis in-house tool or library; nothing else on the disc mentions it.

AUDIO/VBLAUDIO.S is the biggest hand-written module, 1,231 line entries, followed by TASKS/DECRUNCHTASK.S at 995 and DECRUNCH/DECRUNCHER.S at 620. The music replayer is larger than the video decoder.

MAIN/PT_RBFINTERRUPT.S. PT is ProTracker and RBF is the serial receive-buffer-full interrupt — the standard Amiga trick of driving a music replayer from the serial port's interrupt instead of the vertical blank, so the tempo does not tie itself to the display (09).

The complete table, with first-byte offsets and line-entry counts for all 77, is in notes/source-modules.txt.