snake6502/src/lzgmini.asm

243 lines
3.8 KiB
NASM

inflate SUBROUTINE
.inEnd EQU 2
.offset EQU 4
.length EQU 6
.symbol EQU 25
.marker1 EQU 30
.marker2 EQU 31
.marker3 EQU 32
.marker4 EQU 33
.copy EQU 34
clc
ldy #10
lda (srcPointer),y
adc srcPointer
sta .inEnd
dey
lda (srcPointer),y
adc srcPointer + 1
sta .inEnd + 1
clc
lda .inEnd
adc #16
sta .inEnd
lda .inEnd + 1
adc #0
sta .inEnd + 1
; Get the marker symbols
ldy #16
lda (srcPointer),y
sta .marker1
iny
lda (srcPointer),y
sta .marker2
iny
lda (srcPointer),y
sta .marker3
iny
lda (srcPointer),y
sta .marker4
; Skip header + marker symbols (16 + 4 bytes)
clc
lda srcPointer
adc #20
sta srcPointer
lda srcPointer + 1
adc #0
sta srcPointer + 1
; Main decompression loop
ldy #0 ; Make sure that Y is zero
.mainloop:
lda srcPointer ; done?
cmp .inEnd
bne .notdone
lda srcPointer + 1
cmp .inEnd + 1
bne .notdone
rts
.notdone:
lda (srcPointer),y ; A = symbol
sta .symbol
sta $d020
inc srcPointer
bne .noinc1
inc srcPointer + 1
.noinc1:
cmp .marker1 ; Marker1?
beq .domarker1
cmp .marker2 ; Marker2?
beq .domarker2
cmp .marker3 ; Marker3?
beq .domarker3
cmp .marker4 ; Marker4?
beq .domarker4
.literal:
lda .symbol
sta (dstPointer),y ; Plain copy
inc dstPointer
bne .mainloop
inc dstPointer + 1
bne .mainloop
.domarker1:
jmp .domarker1b
; marker4 - "Near copy (incl. RLE)"
.domarker4:
lda (srcPointer),y
inc srcPointer
bne .noinc3
inc srcPointer + 1
.noinc3:
cmp #0
beq .literal ; Single occurance of the marker symbol (rare)
tax
lsr
lsr
lsr
lsr
lsr
sta .offset
inc .offset
lda #0
sta .offset + 1 ; offset = (b >> 5) + 1
txa
and #$1f
tax
lda .LZG_LENGTH_DECODE_LUT,x
sta .length ; length = .LZG_LENGTH_DECODE_LUT[b & 0x1f]
jmp .docopy
; marker3 - "Short copy"
.domarker3:
lda (srcPointer),y
inc srcPointer
bne .noinc4
inc srcPointer + 1
.noinc4:
cmp #0
beq .literal ; Single occurance of the marker symbol (rare)
tax
lsr
lsr
lsr
lsr
lsr
lsr
clc
adc #3
sta .length ; length = (b >> 6) + 3
txa
and #$3f
adc #8
sta .offset
lda #0
sta .offset + 1 ; offset = (b & 0x3f) + 8
beq .docopy
; marker2 - "Medium copy"
.domarker2:
lda (srcPointer),y
inc srcPointer
bne .noinc5
inc srcPointer + 1
.noinc5:
cmp #0
beq .literal ; Single occurance of the marker symbol (rare)
tax
lsr
lsr
lsr
lsr
lsr
sta .offset + 1
lda (srcPointer),y
inc srcPointer
bne .noinc6
inc srcPointer + 1
.noinc6:
clc
adc #8
sta .offset
bcc .noinc7
inc .offset + 1 ; offset = (((b & 0xe0) << 3) | b2) + 8
.noinc7:
txa
and #$1f
tax
lda .LZG_LENGTH_DECODE_LUT,x
sta .length ; length = .LZG_LENGTH_DECODE_LUT[b & 0x1f]
bne .docopy
.literal2:
jmp .literal
; marker1 - "Distant copy"
.domarker1b:
lda (srcPointer),y
inc srcPointer
bne .noinc8
inc srcPointer + 1
.noinc8:
cmp #0
beq .literal2 ; Single occurance of the marker symbol (rare)
and #$1f
tax
lda .LZG_LENGTH_DECODE_LUT,x
sta .length ; length = .LZG_LENGTH_DECODE_LUT[b & 0x1f]
lda (srcPointer),y
inc srcPointer
bne .noinc9
inc srcPointer + 1
.noinc9:
sta .offset + 1
lda (srcPointer),y
inc srcPointer
bne .noinc10
inc srcPointer + 1
.noinc10:
clc
adc #$08
sta .offset
lda .offset + 1
adc #$08
sta .offset + 1 ; offset = ((b2 << 8) | (*src++)) + 2056
; Copy corresponding data from history window
.docopy:
sec
lda dstPointer
sbc .offset
sta .copy
lda dstPointer + 1
sbc .offset + 1
sta .copy + 1
.loop1:
lda (.copy),y
sta (dstPointer),y
iny
cpy .length
bne .loop1
ldy #0 ; Make sure that Y is zero
clc
lda dstPointer
adc .length
sta dstPointer
bcc .noinc11
inc dstPointer + 1
.noinc11:
jmp .mainloop
; Lookup Table for decoding the copy length parameter
.LZG_LENGTH_DECODE_LUT
BYTE 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,35,48,72,128