Dekompresor dla Shrinkler
CODE: xxl, fox (29/03/2021)
ENTRY: SOURCE and DESTINATION adress store in unshrinkler_src and unshrinkler_dst
unshrinkler_PARITY equ 0 ; wersja no parity (wydajniejsza dla 8-bitowców); 1 - wersja oryginalna
unshrinkler_zp equ $xx ; 18 bytes on ZP
unshrinkler_data equ $xxxx ; 6/8 pages for decompressor (6 - no parity)
mwa #packed_data_addr unshrinkler_zp
mwa #unpacked_addr unshrinkler_zp+2
jsr unshrinkler
jmp *
; ====================================================
unshrinkler
?src equ unshrinkler_zp
?dst equ unshrinkler_zp+2
?copy equ unshrinkler_zp+4
?factor equ unshrinkler_zp+4
?tabs equ unshrinkler_zp+6
?number equ unshrinkler_zp+8
?cp equ unshrinkler_zp+10
?d2 equ unshrinkler_zp+12
?d3 equ unshrinkler_zp+14
?frac equ unshrinkler_zp+16
?srcBits equ unshrinkler_zp+18
?probs equ unshrinkler_data
?probsRef equ unshrinkler_data+$200+$200*unshrinkler_PARITY
?probsLength equ ?probsRef
?probsOffset equ ?probsRef+$200
ldx #>[?probsOffset+$100]
ldy #1
sty ?d3
dey
sty ?d3+1
ift .lo(unshrinkler_data)==0
sty ?tabs
els
lda #.lo(unshrinkler_data)
sta ?tabs
eif
tya
?initPage
stx ?tabs+1
?initByte
sta (?tabs),y
iny
bne ?initByte
sta ?srcBits ; eventually $80
eor #$80
dex
cpx #>unshrinkler_data
bcs ?initPage
tax ; #0
?literal
ldy #1
?literalBit
jsr ?getBit
tya
rol @
tay
bcc ?literalBit
sta (?dst,x) ; X=0
inc ?dst
bne ?storeSamePage
inc ?dst+1
?storeSamePage
jsr ?getKind
bcc ?literal
lda #>?probsRef
jsr ?getBitFrom
bcc ?readOffset
?readLength
lda #>?probsLength
jsr ?getNumber
lda #$ff
?offsetL equ *-1
adc ?dst ; C=0
sta ?copy
lda #$ff
?offsetH equ *-1
adc ?dst+1
sta ?copy+1
ldx ?number+1
beq ?copyRemainder
?copyPage
lda (?copy),y
sta (?dst),y
iny
bne ?copyPage
inc ?copy+1
inc ?dst+1
dex
bne ?copyPage
?copyRemainder
ldx ?number
beq ?copyDone
?copyByte
lda (?copy),y
sta (?dst),y
iny
dex
bne ?copyByte
tya
clc
adc ?dst
sta ?dst
bcc ?copyDone
inc ?dst+1
?copyDone
jsr ?getKind
bcc ?literal
?readOffset
lda #>?probsOffset
jsr ?getNumber
lda #3
sbc ?number ; C=0
sta ?offsetL
tya ; #0
sbc ?number+1
sta ?offsetH
bcc ?readLength
rts ; finish
?getNumber
sta ?tabs+1
lda #1
sta ?number
sty ?number+1 ; #0
?getNumberCount
iny
iny
jsr ?getBit
bcs ?getNumberCount
?getNumberBit
dey
jsr ?getBit
rol ?number
rol ?number+1
dey
bne ?getNumberBit
rts
?getKind
ldy #0
ift unshrinkler_PARITY
lda ?dst
and #1
asl @
adc #>?probs
els
lda #>?probs
eif
?getBitFrom
sta ?tabs+1
bne ?getBit ; always
?readBit
asl ?d3
rol ?d3+1
asl ?srcBits
bne ?gotBit
lda (?src,x) ; X=0
inc ?src
bne ?readSamePage
inc ?src+1
?readSamePage
rol @ ; C=1
sta ?srcBits
?gotBit
rol ?d2
rol ?d2+1
?getBit
lda ?d3+1
bpl ?readBit
lda (?tabs),y
sta ?factor+1
sta ?frac+1
inc ?tabs+1
lda (?tabs),y
sta ?factor
ldx #4
?computeFrac
lsr ?frac+1
ror @
dex
bne ?computeFrac
sta ?frac
txa ; #0
sta ?cp+1
ldx #16
?mulLoop
lsr ?factor+1
ror ?factor
bcc ?mulNext
clc
adc ?d3
pha
lda ?cp+1
adc ?d3+1
sta ?cp+1
pla
?mulNext
ror ?cp+1
ror @
dex
bne ?mulLoop
sta ?cp
eor #$ff
sec
adc ?d2
tax
lda ?d2+1
sbc ?cp+1
bcs ?zero
ldx ?cp
lda ?cp+1
bcc ?setD3 ; always
?zero
stx ?d2
sta ?d2+1
lda ?d3
sbc ?cp ; C=1
tax
lda ?d3+1
sbc ?cp+1
?setD3
stx ?d3
sta ?d3+1
php
lda (?tabs),y
sbc ?frac
sta (?tabs),y
dec ?tabs+1
lda (?tabs),y
sbc ?frac+1
plp
bcs ?retZero
sbc #$ef ; C=0
sec
dta {ldx #}
?retZero
clc
sta (?tabs),y
ldx #0
rts
use: Shrinkler.exe -d -p -9 source destination.shk
Shrinkler 4.6 No parity
zobacz: https://github.com/atari8xxl/unShrinkler
zobacz: https://www.pouet.net/prod.php?which=64851
zobacz: https://github.com/askeksa/Shrinkler
