ys2-intro/loader/tools/nucrunch-1.0.1/decrunch.s

251 lines
3.1 KiB
ArmAsm
Raw Normal View History

2025-11-13 11:07:39 -05:00
;
; NuCrunch 1.0
; Christopher Jam
; May 2018
;
.export decrunch_next_group
.export decrunch
.export decrunch_end
.macro getByte1
lda (zps),y
inc zps+0
bne *+4
inc zps+1
.endmacro
.macro getBit1
.local nomore
asl zbs1
bne nomore
getByte1
sec
rol
sta zbs1
nomore:
.endmacro
; get head of a pair of bits from the bitpair stream
; (must getBit2t precisely once before invoking again)
.macro getBit2h
.local nomore
asl zbs2
bne nomore
getByte1
sec
rol
sta zbs2
nomore:
.endmacro
; same, but preserving A/ trashing X.
.macro getBit2hpa
.local nomore
asl zbs2
bne nomore
tax
getByte1
sec
rol
sta zbs2
txa
nomore:
.endmacro
; get tail of a pair of bits from the bitpair stream
.macro getBit2t
asl zbs2
.endmacro
; get head of a quad of bits from the quad stream
; (must getBit4t precisely three times before invoking again)
.macro getBit4h
.local nomore
asl zbs4
bne nomore
getByte1
sec
rol
sta zbs4
nomore:
.endmacro
; get tail of a quad of bits from the quad stream
.macro getBit4t
asl zbs4
.endmacro
; note, trashes X. Also, carry is clear when done
.macro getExpGoulombTail
.local ndone
ndone:
getBit2hpa
rol
getBit2t
bcs ndone
.endmacro
.macro getExpGoulombTail_odd_aligned
.local ndone
ndone:
getBit2t
rol
getBit2hpa
bcs ndone
.endmacro
decrunch_zpa=$e0 ;9 bytes required
zbs1 = decrunch_zpa+$00 ; 1 byte
zbs2 = decrunch_zpa+$01 ; 1 byte
zbs4 = decrunch_zpa+$02 ; 1 byte
zpc = decrunch_zpa+$03 ; 2 bytes
zps = decrunch_zpa+$05 ; 2 bytes
zpd = decrunch_zpa+$07 ; 2 bytes
offsetm1 = zpc ; these are aliased, as never need both
decrunch:
stx zps+0
sta zps+1
ldy #0
sty zbs1
sty zbs2
sty zbs4
decrunch_next_group:
ldy #0
next_segment:
jsr get_byte
sta zpd+0
jsr get_byte
sta zpd+1
decode_literal:
; get count [ExpGoulomb0+1] in x
ldx#1
getBit1
bcc ret1
lda#1
getExpGoulombTail
tax
ret1:
literal_loop:
lda (zps),y
sta (zpd),y
iny
dex
bne literal_loop
; carry is clear either from bcc above or _getExpGoulombTail above
tya
adc zps
sta zps
bcc *+5
inc zps+1
clc
tya
adc zpd
sta zpd
bcc *+4
inc zpd+1
ldy#0
; literal is always followed by copy
decode_copy:
getBit2h
bcc short_offset
lda#1
getExpGoulombTail_odd_aligned
adc#255
sta offsetm1+1
getByte1
sta offsetm1
jmp got_high
short_offset:
lda#0
sta offsetm1+1
;ExpGoulomb k=3
getBit4h
lda#1
bcc no_tail
getExpGoulombTail_odd_aligned
no_tail:
adc#255
getBit4t
rol
getBit4t
rol
getBit4t
rol
sta offsetm1
got_high:
ldx#1
getBit2t
bcc length_two
lda#1
getExpGoulombTail
tax
cpx#255
beq end_of_segment ; copy length of 256 marks end of segment
length_two:
; note carry is clear at this point; good as we want to subtract (offsetm1+1)
lda zpd
sbc offsetm1
sta zpc
lda zpd+1
sbc offsetm1+1
sta zpc+1
lda (zpc),y
sta (zpd),y
copy_loop:
iny
lda (zpc),y
sta (zpd),y
dex
bne copy_loop
tya
; carry will be set from SBC above
adc zpd
sta zpd
bcc *+4
inc zpd+1
ldy#0
getBit1
bcs jmp_decode_copy
jmp decode_literal
jmp_decode_copy:
jmp decode_copy
get_byte:
getByte1
end_of_file:
rts
end_of_segment:
lda offsetm1
cmp#0
beq end_of_file
jmp next_segment
decrunch_end: