Last active
January 5, 2020 17:04
-
-
Save petrihakkinen/6ed4ff9884f079e426c6c682f84cbc45 to your computer and use it in GitHub Desktop.
ZX7 decompressor for 6502 (150 bytes, 146 bytes if dest address is set by caller)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;***************************************************************** | |
; ZX7 decompressor based on | |
; ZX7 data decompressor for Apple II | |
; by Peter Ferrie (peter.ferrie@gmail.com) | |
; with modifications by Juan J. Martinez (@reidrac) | |
; optimized by Petri Häkkinen | |
; This code is in the Public Domain | |
;***************************************************************** | |
zx7_src_lo = $20 ; should always contain 0 | |
zx7_src_hi = $21 ; write source page address here | |
; internal | |
zx7_dst_lo = $22 | |
zx7_dst_hi = $23 | |
zx7_ecx_lo = $24 | |
zx7_ecx_hi = $25 | |
zx7_last = $26 | |
; in: | |
; A = dest address lo | |
; X = dest address hi | |
; Y = src address lo | |
zx7_unpack: sta zx7_dst_lo ; sta & stx can be skipped if the address is set by caller | |
stx zx7_dst_hi | |
; y = src offset | |
lda #0 | |
sta zx7_last | |
sta zx7_ecx_lo | |
sta zx7_ecx_hi | |
@copy_byte_loop:jsr @getput | |
@main_loop: jsr @next_bit | |
bcc @copy_byte_loop | |
ldx #0 ; x = counter | |
@len_size_loop: inx | |
jsr @next_bit | |
bcc @len_size_loop | |
bcs @len_value_skip ; always branch | |
@len_value_loop:jsr @next_bit | |
@len_value_skip:rol zx7_ecx_lo | |
rol zx7_ecx_hi | |
bcs @next_bit_ret | |
dex | |
bne @len_value_loop | |
inc zx7_ecx_lo | |
bne :+ | |
inc zx7_ecx_hi | |
: jsr @getsrc | |
rol | |
sta temp1 | |
txa | |
bcc @offset_end | |
lda #$10 | |
@rld_next_bit: pha | |
jsr @next_bit | |
pla | |
rol | |
bcc @rld_next_bit | |
;clc | |
;adc #1 | |
adc #0 ; carry is always set | |
lsr | |
@offset_end: sta temp2 | |
ror temp1 | |
ldx zx7_src_hi ; store src hi | |
tya ; store Y | |
pha | |
; compute new offset y | |
lda zx7_dst_lo | |
sbc temp1 | |
tay ; y = dst_lo - offset | |
; src_hi = dst_hi - temp2 | |
lda zx7_dst_hi | |
sbc temp2 | |
sta zx7_src_hi | |
@loop1: jsr @getput | |
; dec ecx | |
lda zx7_ecx_lo | |
bne :+ | |
dec zx7_ecx_hi | |
: ;sec ; carry seems to be always set, but why? | |
sbc #1 | |
sta zx7_ecx_lo | |
ora zx7_ecx_hi | |
bne @loop1 | |
; restore src | |
pla ; restore Y | |
tay | |
stx zx7_src_hi ; restore src hi | |
;jmp @main_loop | |
bcs @main_loop ; carry seems to be always set, but why? | |
@getput: jsr @getsrc | |
sty temp2 ; store Y | |
ldy #0 | |
sta (zx7_dst_lo), y | |
ldy temp2 ; restore Y | |
inc zx7_dst_lo | |
bne :+ | |
inc zx7_dst_hi | |
: rts | |
; read one byte from source | |
@getsrc: lda (zx7_src_lo), y | |
iny | |
bne :+ | |
inc zx7_src_hi | |
: rts | |
@next_bit: asl zx7_last | |
bne @next_bit_ret | |
jsr @getsrc | |
sec | |
rol | |
sta zx7_last | |
@next_bit_ret: rts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment