ys2-intro/loader/tools/nucrunch-1.0.1/decrunch.a65
2025-11-13 19:07:39 +03:00

249 lines
3.4 KiB
Plaintext

;
; NuCrunch 1.0
; Christopher Jam
; May 2018
;
#define getByte1 \
lda (zps),y :\
inc zps+0 :\
bne *+4 :\
inc zps+1
#define getBit1 \
.( :\
asl zbs1 :\
bne nomore :\
getByte1 :\
sec :\
rol :\
sta zbs1 :\
nomore :\
.)
; get head of a pair of bits from the bitpair stream
; (must getBit2t precisely once before invoking again)
#define getBit2h \
.( :\
asl zbs2 :\
bne nomore :\
getByte1 :\
sec :\
rol :\
sta zbs2 :\
nomore :\
.)
; same, but preserving A/ trashing X.
#define getBit2hpa \
.( :\
asl zbs2 :\
bne nomore :\
tax :\
getByte1 :\
sec :\
rol :\
sta zbs2 :\
txa :\
nomore :\
.)
; get tail of a pair of bits from the bitpair stream
#define getBit2t \
asl zbs2
; get head of a quad of bits from the quad stream
; (must getBit4t precisely three times before invoking again)
#define getBit4h \
.( :\
asl zbs4 :\
bne nomore :\
getByte1 :\
sec :\
rol :\
sta zbs4 :\
nomore :\
.)
; get tail of a quad of bits from the quad stream
#define getBit4t \
asl zbs4
; note, trashes X. Also, carry is clear when done
#define getExpGoulombTail \
.( :\
ndone :\
getBit2hpa :\
rol :\
getBit2t :\
bcs ndone :\
.)
#define getExpGoulombTail_odd_aligned \
.( :\
ndone :\
getBit2t :\
rol :\
getBit2hpa :\
bcs ndone :\
.)
#ifdef NUCRUNCH_ALIGN_FOR_SPEED
.dsb <-$63-*,0 ; place decode_copy on a page boundary
#endif
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
copy_src
lda (zpc),y
copy_dst
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