251 lines
3.1 KiB
ArmAsm
251 lines
3.1 KiB
ArmAsm
;
|
|
; 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:
|
|
|