293 lines
3.8 KiB
NASM
293 lines
3.8 KiB
NASM
/*
|
|
|
|
decrunch.asm
|
|
|
|
NMOS 6502 decompressor for data stored in TSCrunch format.
|
|
|
|
This code is written for the KickAssembler assembler.
|
|
|
|
Copyright Antonio Savona 2022.
|
|
|
|
*/
|
|
|
|
|
|
//#define INPLACE //Enables inplace decrunching. Use -i switch when crunching.
|
|
|
|
.label tsget = $f8 //2 bytes
|
|
.label tstemp = $fa
|
|
.label tsput = $fb //2 bytes
|
|
.label lzput = $fd //2 bytes
|
|
|
|
|
|
#if INPLACE
|
|
|
|
.macro TS_DECRUNCH(src)
|
|
{
|
|
lda #<src
|
|
sta.zp tsget
|
|
lda #>src
|
|
sta.zp tsget + 1
|
|
jsr tsdecrunch
|
|
}
|
|
|
|
#else
|
|
|
|
.macro TS_DECRUNCH(src,dst)
|
|
{
|
|
lda #<src
|
|
sta.zp tsget
|
|
lda #>src
|
|
sta.zp tsget + 1
|
|
lda #<dst
|
|
sta.zp tsput
|
|
lda #>dst
|
|
sta.zp tsput + 1
|
|
jsr tsdecrunch
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
tsdecrunch:
|
|
{
|
|
decrunch:
|
|
|
|
#if INPLACE
|
|
ldy #$ff
|
|
!: iny
|
|
lda (tsget),y
|
|
sta tsput , y //last iteration trashes lzput, with no effect.
|
|
cpy #3
|
|
bne !-
|
|
|
|
pha
|
|
|
|
lda lzput
|
|
sta optRun + 1
|
|
|
|
tya
|
|
ldy #0
|
|
beq update_getonly
|
|
#else
|
|
ldy #0
|
|
|
|
|
|
lda (tsget),y
|
|
sta optRun + 1
|
|
|
|
inc tsget
|
|
bne entry2
|
|
inc tsget + 1
|
|
#endif
|
|
|
|
entry2:
|
|
lax (tsget),y
|
|
|
|
bmi rleorlz
|
|
|
|
cmp #$20
|
|
bcs lz2
|
|
|
|
//literal
|
|
|
|
#if INPLACE
|
|
|
|
inc tsget
|
|
beq updatelit_hi
|
|
return_from_updatelit:
|
|
|
|
ts_delit_loop:
|
|
|
|
lda (tsget),y
|
|
sta (tsput),y
|
|
iny
|
|
dex
|
|
|
|
bne ts_delit_loop
|
|
|
|
tya
|
|
tax
|
|
//carry is clear
|
|
ldy #0
|
|
#else //not inplace
|
|
tay
|
|
|
|
ts_delit_loop:
|
|
|
|
lda (tsget),y
|
|
dey
|
|
sta (tsput),y
|
|
|
|
bne ts_delit_loop
|
|
|
|
txa
|
|
inx
|
|
#endif
|
|
|
|
updatezp_noclc:
|
|
adc tsput
|
|
sta tsput
|
|
bcs updateput_hi
|
|
putnoof:
|
|
txa
|
|
update_getonly:
|
|
adc tsget
|
|
sta tsget
|
|
bcc entry2
|
|
inc tsget+1
|
|
bcs entry2
|
|
|
|
#if INPLACE
|
|
updatelit_hi:
|
|
inc tsget+1
|
|
bcc return_from_updatelit
|
|
#endif
|
|
updateput_hi:
|
|
inc tsput+1
|
|
clc
|
|
bcc putnoof
|
|
|
|
rleorlz:
|
|
|
|
alr #$7f
|
|
bcc ts_delz
|
|
|
|
//RLE
|
|
beq optRun
|
|
|
|
plain:
|
|
ldx #2
|
|
iny
|
|
sta tstemp //number of bytes to de-rle
|
|
|
|
lda (tsget),y //fetch rle byte
|
|
ldy tstemp
|
|
!runStart:
|
|
sta (tsput),y
|
|
|
|
ts_derle_loop:
|
|
|
|
dey
|
|
sta (tsput),y
|
|
|
|
bne ts_derle_loop
|
|
|
|
//update zero page with a = runlen, x = 2 , y = 0
|
|
lda tstemp
|
|
|
|
bcs updatezp_noclc
|
|
|
|
done:
|
|
#if INPLACE
|
|
pla
|
|
sta (tsput),y
|
|
#endif
|
|
rts
|
|
//LZ2
|
|
lz2:
|
|
beq done
|
|
|
|
ora #$80
|
|
adc tsput
|
|
sta lzput
|
|
lda tsput + 1
|
|
sbc #$00
|
|
sta lzput + 1
|
|
|
|
//y already zero
|
|
lda (lzput),y
|
|
sta (tsput),y
|
|
iny
|
|
lda (lzput),y
|
|
sta (tsput),y
|
|
|
|
tya
|
|
dey
|
|
|
|
adc tsput
|
|
sta tsput
|
|
bcs lz2_put_hi
|
|
!skp:
|
|
inc tsget
|
|
bne entry2
|
|
inc tsget + 1
|
|
bne entry2
|
|
|
|
lz2_put_hi:
|
|
inc tsput + 1
|
|
bcs !skp-
|
|
|
|
//LZ
|
|
ts_delz:
|
|
|
|
lsr
|
|
sta lzto + 1
|
|
|
|
iny
|
|
|
|
lda tsput
|
|
bcc long
|
|
|
|
sbc (tsget),y
|
|
sta lzput
|
|
lda tsput+1
|
|
|
|
sbc #$00
|
|
|
|
ldx #2
|
|
//lz MUST decrunch forward
|
|
lz_put:
|
|
sta lzput+1
|
|
|
|
ldy #0
|
|
|
|
lda (lzput),y
|
|
sta (tsput),y
|
|
|
|
iny
|
|
lda (lzput),y
|
|
sta (tsput),y
|
|
|
|
ts_delz_loop:
|
|
|
|
iny
|
|
|
|
lda (lzput),y
|
|
sta (tsput),y
|
|
|
|
lzto: cpy #0
|
|
bne ts_delz_loop
|
|
|
|
tya
|
|
|
|
//update zero page with a = runlen, x = 2, y = 0
|
|
ldy #0
|
|
//clc not needed as we have len - 1 in A (from the encoder) and C = 1
|
|
|
|
jmp updatezp_noclc
|
|
|
|
optRun:
|
|
ldy #255
|
|
sty tstemp
|
|
|
|
ldx #1
|
|
//A is zero
|
|
|
|
bne !runStart-
|
|
|
|
long:
|
|
//carry is clear and compensated for from the encoder
|
|
adc (tsget),y
|
|
sta lzput
|
|
iny
|
|
lax (tsget),y
|
|
ora #$80
|
|
adc tsput + 1
|
|
|
|
cpx #$80
|
|
rol lzto + 1
|
|
ldx #3
|
|
|
|
bne lz_put
|
|
|
|
} |