With Revision’s deadlines looming and the party build-up commencing today, the time budget for a possible size-coded Amiga entry doesn’t look too good anymore. Well, that’s life!
I did, however, find a little time – between my last work day before Easter and tying up my luggage – for some compression optimization. Packing before packing! :)
Specifically, I was looking to shorten the decompression header in my bootblocks. I knew I had used some magic constants before, but that was at an earlier version of Shrinkler, and maybe I haven’t used it for salvador/ZX0 at all. So let’s take a fresh look!
What exactly do the registers contain when your bootblock gets executed?
Register | Kickstart 1.2 | Kickstart 1.3 | Kickstart 2.04 | Kickstart 3.1 |
---|---|---|---|---|
d0 | 00000000 | 00000000 | 00000000 | 00000809 |
d1 | 8000ffff | 8000ffff | 0000ffff | 00000808 |
d2 | 00000001 | 00000001 | 00000001 | 00000001 |
d3 | 00000000 | 00000000 | 0000d688 | 0000ad48 |
d4 | 00000000 | 00000000 | 00001468 | 00001520 |
d5 | 00000000 | 00000000 | 00000000 | 00000000 |
d6 | ffffffff | ffffffff | ffffffff | ffffffff |
d7 | 00000000 | 00000000 | 00000000 | 00000000 |
a0 | 00001958 | 00001958 | 0000dfb8 | 0000ed38 |
a1 | 00c014e6 | 00c014e2 | 0000d54c | 0000e2c4 |
a2 | 00c0185c | ffffffff | 0000d530 | 0000e2a8 |
a3 | 00fe8b3a | 00fe86ee | 0000d54c | 0000e2c4 |
a4 | 00001558 | 00001558 | 00003e4c | 00002708 |
a5 | 00c014ba | 00c014b6 | 00000a44 | 00000a74 |
a6 | 00c00276 | 00c00276 | 00001468 | 00001520 |
a7 | 00c014b6 | 00c014b2 | 00003e10 | 000026cc |
pc | 00001564 | 00001564 | 0000dfc4 | 0000ed44 |
Note: Of course, this is not an exhaustive list. These are merely the values for some typical configurations: Amiga 500 with 512KB of extra RAM for Kickstart 1.2 and 1.3, Amiga 500+ for 2.04, and a vanilla Amiga 1200 for 3.1
But it seems there are some specific fixed values we can rely on across different Kickstart versions!*
*) If we only need to support classic Commodore-made AmigaOS editions, that is. This will probably not work with AROS68k or AmigaOS 3.2.x.
Register | Contents |
---|---|
d2 | Constant 00000001 |
d5 | Constant 00000000 |
d6 | Constant ffffffff |
d7 | Constant 00000000 |
a1 | IORequest, as specified by the OS (bootblock sequence) |
a6 | exec.library, as specified by the OS (ibid.) |
pc | Noteworthy: The 12 bytes before the entrypoint contain the bootblock header as it is stored on disk (i. e. 'DOS',0 followed
by checksum and rootblock longwords |
Nifty! Now let’s delete some code. With Shrinkler, we can save four bytes in the initialization code:
ShrinklerDecompress: ; Init range decoder state moveq #0,d2 ; omit, use d5 instead moveq #1,d3 ; omit, use d2 instead ...
And two bytes for ZX0:
zx0_decompress: moveq #-128,d1 ; initialize empty bit queue moveq #-1,d2 ; omit, use d6 instead ...
I love that each of the values 0, 1, and -1 is of use somewhere!
For both packers, the bootblock starts like this:
disk: dc.b 'DOS',0 dc.l 0 ; checksum gets inserted here root: dc.l $20000 ; destination; usually 880=rootblock entry: move.l root(pc),aX ; destination address lea meat(pc),aY ; start of compressed data pea (aX) ; rts will jump into unpacked code ... ; decompression code starts here
With this, my current bootblock stubs take up this much space:
Compression | Stub size | Room for compressed data |
---|---|---|
Shrinkler | 168 | 856 |
Shrinkler, parity disabled | 162 | 862 |
Savlador/ZX0 | 100 | 924 |
Note: It pays out to have build scripts ready for all compression schemes – with my current work-in-progress payload, the “winner” (in terms of best overall compression) fluctuates constantly!
Now, either I find some more bytes to spare during the party or I put some of that saved space to good use with an entry! :)
Then again, I already have my working gloves on…
