Space Harrier 2 has an interesting, but simple graphics compression algorithm.
It has a 32 byte decompression buffer for holding decompressed tile data. For each tile, it'll use a list of bitfields that describe the places in the decompression buffer to copy a field's corresponding byte into. It is then finished off with a string of bytes that then fill up the rest of the unwritten to spots. The buffer is then copied to VRAM and it loops. It does this until it hits a termination flag.
; ---------------------------------------------------------------------------
; Space Harrier II graphics decompression
; VDP write command should be set before calling this
; ---------------------------------------------------------------------------
; PARAMETERS:
; a0.l - Pointer to compressed art
; ---------------------------------------------------------------------------
SH2GfxDecomp:
lea $FFF2C0.w,a3 ; Decompression buffer
moveq #0,d0 ; Buffer write flags
moveq #0,d2 ; Get number of bitfield copies for this tile
move.b (a0)+,d2
beq.w .CopyRest ; If there are none, branch
bmi.w .End ; If this is the end of the compressed data, branch
subq.w #1,d2 ; Subtract 1 for dbf
; ---------------------------------------------------------------------------
.GetCopyPattern:
lea $FFF2C0.w,a2 ; Decompression buffer
movea.l a2,a3
move.b (a0)+,d3 ; Get byte to copy
move.b (a0)+,d4 ; Get copy pattern
lsl.w #8,d4
move.b (a0)+,d4
lsl.l #8,d4
move.b (a0)+,d4
lsl.l #8,d4
move.b (a0)+,d4
or.l d4,d0 ; Mark spots in pattern as written to
moveq #32-1,d7 ; Start checking which places in buffer to copy byte into
.CopyByteLoop:
lsl.l #1,d4 ; Shift copy pattern and get MSB
bcc.w .AdvanceCopy ; If the byte shouldn't be written to this spot, branch
move.b d3,(a2) ; If it should, write it
.AdvanceCopy:
addq.l #1,a2 ; Go to next byte in buffer
dbf d7,.CopyByteLoop ; Loop until the whole copy pattern is scanned
dbf d2,.GetCopyPattern ; Loop until all copy patterns are scanned for this tile
; ---------------------------------------------------------------------------
moveq #$FFFFFFFF,d1 ; Is the whole buffer filled up?
eor.l d0,d1
beq.w .CopyToVRAM ; If so, branch
.CopyRest:
moveq #32-1,d7 ; Start copying the rest of the tile data
.CopyRestLoop:
lsl.l #1,d0 ; Shift remaining pattern and get MSB
bcs.w .AdvanceRest ; If the next byte shouldn't be written to this spot, branch
move.b (a0)+,(a3) ; Copy byte and advance
.AdvanceRest:
addq.l #1,a3 ; Go to next byte in buffer
dbf d7,.CopyRestLoop ; Loop until the rest of the buffer is filled up
; ---------------------------------------------------------------------------
.CopyToVRAM:
lea $FFF2C0.w,a6 ; Copy buffer to VRAM
lea $C00000,a5
move.l (a6)+,(a5)
move.l (a6)+,(a5)
move.l (a6)+,(a5)
move.l (a6)+,(a5)
move.l (a6)+,(a5)
move.l (a6)+,(a5)
move.l (a6)+,(a5)
move.l (a6)+,(a5)
bra.s SH2GfxDecomp ; Loop back to start for next tile
.End:
rts
Space Harrier 2 has an interesting, but simple graphics compression algorithm.
It has a 32 byte decompression buffer for holding decompressed tile data. For each tile, it'll use a list of bitfields that describe the places in the decompression buffer to copy a field's corresponding byte into. It is then finished off with a string of bytes that then fill up the rest of the unwritten to spots. The buffer is then copied to VRAM and it loops. It does this until it hits a termination flag.