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

272 lines
3.8 KiB
Plaintext

;
; NuCrunch 0.1
; Christopher Jam
; February 2016
;
; next byte is fetched from mem[ mem[zps+1]*256+(mem[zps]-1)%256 ]
; ie, init pointer to start byte then increment low byte of pointer.
; Low byte is decremented before each fetch, then if it hits zero the high byte is predecremented for the next fetch
; note that getByte requires y to be zero
; also note that this mangled pointer is a tad inimical to the literal fetches -/
#define getByte0 \
dec zps+0 :\
bne *+7 :\
jsr nextPage:\
bvc *+4 :\
lda (zps),y :\
#define _getByte0 \
bit zps+0 :\
bne *+4 :\
dec zps+1 :\
dec zps+0 :\
lda (zps),y :\
#if 0
#define getByte1 jsr get_byte
#else
#define getByte1 getByte0
#endif
#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 :\
.)
#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 <-$79-*,0 ; place decode_copy on a page boundary
#endif
decrunch_zpa=$e0 ;7 bytes required
decrunch
.(
zps = decrunch_zpa+$00
zbs1 = decrunch_zpa+$02
zbs2 = decrunch_zpa+$03
zbs4 = decrunch_zpa+$04
offsetm1= decrunch_zpa+$05
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 copy_dst+1
jsr get_byte
sta copy_dst+2
decode_literal
getEG0p1 ;get count [eg0+1] in x
ldx#1
getBit1
lda#1
bcc ret1
lda#1
getExpGoulombTail
tax
ret1
txa
sec
eor#255
adc copy_dst+1
sta copy_dst+1
sta literal_dst+1
bcs *+5
dec copy_dst+2
lda copy_dst+2
sta literal_dst+2
literal_loop
literal_src
getByte1
literal_dst
sta $f000,x
dex
bne literal_loop
; 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#2
getBit2t
bcc length_two
lda#1
getExpGoulombTail
tax
inx
beq end_of_segment ; copy length of 256 marks end of segment
length_two
txa
eor#255
sec
adc copy_dst+1
sta copy_dst+1
bcs *+6
dec copy_dst+2
sec
; note carry is set at this point; good as we want to add (offsetm1+1)
lda copy_dst+1
adc offsetm1
sta copy_src+1
lda copy_dst+2
adc offsetm1+1
sta copy_src+2
copy_loop
copy_src
lda $f000,x
copy_dst
sta $f000,x
dex
bne copy_loop
ldy#0
getBit1
bcs jmp_decode_copy
jmp decode_literal
jmp_decode_copy
jmp decode_copy
get_byte
getByte0
end_of_file
rts
end_of_segment
lda offsetm1
cmp#0
beq end_of_file
jmp next_segment
nextPage
lda (zps),y
dec zps+1
clv
rts
.)
decrunch_end