goldbox.amiga_dax¶
The Amiga Gold Box .dax container, and the depacker its blocks are in.
goldbox/dos_savegame.py reads the DOS .DAX, which is a different
format with the same extension: a little-endian index of
id:u8 offset:u32 raw:u16 compressed:u16 and run-length coded blocks. This
one is the Amiga’s – a big-endian index of
id:u16 offset:u32 compressed:u16 raw:u16 and ByteKiller-packed blocks – and
the two must never be read through each other’s reader (#65).
Why a conversion needs it. An Amiga Pool of Radiance saved game carries
7680 bytes of the area’s own ECL script, live on load exactly as the DOS one
is, and a character record holds none of it. DOS keeps a script per container
in ECL<n>.DAX; the Amiga keeps all of them in one /ecl.dax on disk 2, the
POOLDATA volume. So a party cannot be converted to the Amiga without the
player’s disk 2, and this is what reads it.
The depacker is transcribed from the game’s own code, at /program
hunk 27 + $7346 (file offset 0x4887A), read with tools/amiga68k.py. It
is the ByteKiller shape: a bit stream consumed backwards from the end of
the block, writing the output backwards from its end, with a trailer of three
big-endian longwords – the unpacked length, a checksum, and the first bit
buffer. The checksum is a running XOR of every longword the stream reads and
the routine ends with tst.l d5 on it, so a block that unpacks to the stated
length with a non-zero checksum is a block that was read wrong.
CONFIRMED, and the oracle is the game’s own saved game: block 0 of ecl.dax
unpacked, from byte 2 on, is byte for byte the 7468 bytes the shipped
save/savgamA.dat carries in its script buffer. All 29 blocks unpack to
exactly the length the index states with a zero checksum, and every one opens
88 13 – u16le 5000, the ECL load address DOS and the C64 use too.
Module Attributes
block id, offset from the end of the index, the stored size, the unpacked size. |
|
unpacked length, checksum and the first bit buffer, one big-endian longword each. |
Functions
|
One block of an Amiga |
|
Which blocks a container holds, in the order the index lists them. |
|
|
|
|
|
Decompress one packed block, or raise saying what did not add up. |
Exceptions
This is not the Amiga |
- exception goldbox.amiga_dax.AmigaDaxError[source]¶
Bases:
ValueErrorThis is not the Amiga
.daxthis reader knows how to read.
- goldbox.amiga_dax.ENTRY = Struct('>HIHH')¶
block id, offset from the end of the index, the stored size, the unpacked size. Ten bytes, big-endian.
- Type:
The
.daxindex entry
- goldbox.amiga_dax.TRAILER = 12¶
unpacked length, checksum and the first bit buffer, one big-endian longword each.
- Type:
How many bytes of trailer every packed block ends with
- goldbox.amiga_dax.block(data, block_id, name='dax')[source]¶
One block of an Amiga
.dax, unpacked. Raises if it is not there.
- goldbox.amiga_dax.block_ids(data, name='dax')[source]¶
Which blocks a container holds, in the order the index lists them.
- goldbox.amiga_dax.blocks(data, name='dax')[source]¶
(id, unpacked bytes)for every block of an Amiga.dax.
- goldbox.amiga_dax.index(data, name='dax')[source]¶
(id, offset, stored size, unpacked size)for every block.A file too short for the index it declares is named as such rather than raising
struct.errorout of a comprehension, because the caller is a conversion reading the player’s own disk and “this is not an Amiga .dax” is an answer it has to be able to give.
- goldbox.amiga_dax.unpack(block, raw_size=None, name='block')[source]¶
Decompress one packed block, or raise saying what did not add up.
raw_sizeis the index’s own figure and is checked against the block’s own trailer when it is given; the two disagreeing means the index was read at the wrong stride, which is the failure this argument exists to catch.The listing this follows, instruction for instruction:
the trailer, backwards – unpacked length, checksum, first bit buffer;
lsr.l #1,d0for each bit, and when the buffer empties, a fresh longword with a sentinel1rotated into bit 31 so that each longword yields exactly 32 bits;tag
0then0: a 3-bit count, then that many plus one literal bytes;tag
0then1: an 8-bit offset, two bytes copied;tag
1then00or01: a 9- or 10-bit offset, three or four bytes;tag
1then10: an 8-bit count and a 12-bit offset;tag
1then11: an 8-bit count, then count + 9 literal bytes.