flamewing / mdcomp

Assorted compression formats for the Sega Mega Drive
Other
45 stars 4 forks source link

Compile/Puyo Puyo compression #23

Open DevsArchive opened 3 years ago

DevsArchive commented 3 years ago

Compile used a pretty basic LZ-based compression scheme for their graphics data in Puyo Puyo, with a 256 byte sliding window (and also a 4 byte buffer for copying to VRAM).

A description field can be any of the following:

%00000000             - Data end
%0xxxxxxxx            - Copy 1-127 uncompressed bytes (x)
%1xxxxxxxx oooooooo   - Copy 3-130 bytes (o) from the the current sliding window location minus 1-256 bytes (x)

Here's a disassembly of its decompression function from Mean Bean Machine:

; --------------------------------------------------------------
; PARAMETERS:
;        d0.w        - VRAM address
;        a0.l        - Pointer to compressed art
; --------------------------------------------------------------

PuyoDec:
        ori     #$700,sr                    ; Disable interrupts

        move.w  d0,d1                       ; Convert VRAM address to VDP write command
        andi.w  #$3FFF,d1
        ori.w   #$4000,d1
        move.w  d1,$C00004
        lsl.l   #2,d0
        swap    d0
        andi.w  #3,d0
        move.w  d0,$C00004

        lea     $FF0000,a1                  ; Sliding window
        lea     $FF0100,a2                  ; VDP data buffer
        clr.w   d0                          ; Sliding window offset
        clr.w   d1                          ; VDP data buffer offset

; --------------------------------------------------------------

.DecompLoop:
        move.b  (a0)+,d2                    ; Read descriptor
        tst.b   d2
        bmi.w   .CopyBackward               ; 1xxxxxxx oooooooo = copy from sliding window
        bne.w   .CopyForward                ; 0xxxxxxx = copy next set of bytes

        andi    #~$700,sr                   ; 00000000 = End
        rts

.CopyForward:
        ; Descriptor 0xxxxxxxx = copy next set of bytes
        andi.w  #$7F,d2                     ; Get number of bytes to copy
        subq.w  #1,d2                       ; Subtract 1 for DBF

.CopyForwardLoop:
        move.b  (a0)+,d4                    ; Copy byte
        move.b  d4,(a2,d1.w)                ; Store in VDP data buffer
        addq.b  #1,d1                       ; Increment VDP data buffer offset
        btst    #2,d1                       ; Has 4 bytes been written yet?
        beq.w   .CopyForwardStore           ; If not, branch
        clr.b   d1                          ; Reset VDP data buffer offset
        move.l  (a2),$C00000                ; Copy those 4 bytes into VRAM

.CopyForwardStore:
        move.b  d4,(a1,d0.w)                ; Store byte in sliding window
        addq.b  #1,d0                       ; Increment sliding window offset

        dbf     d2,.CopyForwardLoop         ; Repeat until all bytes are copied
        bra.s   .DecompLoop                 ; Get next descriptor

.CopyBackward:
        ; Descriptor 1xxxxxxx oooooooo = copy from sliding window
        andi.w  #$7F,d2                     ; Get number of bytes to copy
        addq.w  #3-1,d2                     ; Copy at least 3 bytes (1 is subtracted for DBF)

        move.w  d0,d3                       ; Get sliding window offset
        sub.b   (a0)+,d3
        subq.b  #1,d3                       ; Go back at least 1 byte

.CopyBackwardLoop:
        move.b  (a1,d3.w),d4                ; Copy byte
        move.b  d4,(a2,d1.w)                ; Store in VDP data buffer
        addq.b  #1,d1                       ; Increment VDP data buffer offset
        btst    #2,d1                       ; Has 4 bytes been written yet?
        beq.w   .CopyBackwardStore          ; If not, branch
        clr.b   d1                          ; Reset VDP data buffer offset
        move.l  (a2),$C00000                ; Copy those 4 bytes into VRAM

.CopyBackwardStore:
        move.b  d4,(a1,d0.w)                ; Store byte in sliding window
        addq.b  #1,d0                       ; Increment sliding window offset 
        addq.b  #1,d3                       ; Increment sliding window copy offset

        dbf     d2,.CopyForwardLoop         ; Repeat until all bytes are copied
        bra.s   .DecompLoop                 ; Get next descriptor