mirror of
https://github.com/A2osX/A2osX.git
synced 2024-11-26 13:49:18 +00:00
616 lines
13 KiB
Plaintext
616 lines
13 KiB
Plaintext
PR#3
|
||
PREFIX /A2OSX.SRC
|
||
NEW
|
||
INC 1
|
||
AUTO 6
|
||
.LIST OFF
|
||
.OP 65C02
|
||
.OR $2000
|
||
.TF /A2OSX.BOOT/LIB/LIBPAK.O
|
||
*--------------------------------------
|
||
.INB /A2OSX.DEV/INC/MACROS.I
|
||
.INB /A2OSX.DEV/INC/A2OSX.I
|
||
*--------------------------------------
|
||
S.Pak.SrcPtr .EQ ZPLIB
|
||
S.Pak.SrcBlPtr .EQ ZPLIB+2
|
||
S.Pak.SrcBlPtrT .EQ ZPLIB+4
|
||
S.Pak.DstPtr .EQ ZPLIB+6
|
||
*--------------------------------------
|
||
* File Header (16 Bytes)
|
||
*--------------------------------------
|
||
CS.START cld
|
||
jmp (.1,x)
|
||
.DA #$61 6502,Level 1 (65c02)
|
||
.DA #1 BIN Layout Version 1
|
||
.DA 0
|
||
.DA CS.END-CS.START
|
||
.DA 0
|
||
.DA 0
|
||
.DA 0
|
||
*--------------------------------------
|
||
* Relocation Table
|
||
*--------------------------------------
|
||
.1 .DA LIB.LOAD
|
||
.DA LIB.UNLOAD
|
||
.DA Pak
|
||
.DA Unpak
|
||
.DA 0
|
||
*--------------------------------------
|
||
LIB.LOAD
|
||
LIB.UNLOAD clc
|
||
rts
|
||
*--------------------------------------
|
||
* UNPACK code as short as possible
|
||
* For Self Extract
|
||
*--------------------------------------
|
||
* File Header :
|
||
* SFX :
|
||
* - BIN must begin with CLD (QCODE)
|
||
* - BIN must be relocatable
|
||
* - BIN must overwrite itself
|
||
* (well, best way is moving CODE to $200)
|
||
*--------------------------------------
|
||
* Shunk Header :
|
||
* WORD : !Target Length
|
||
* USED TO STOP UNPACK
|
||
* !!!NO EOF TOKEN!!!
|
||
* Short4 : [0..15]
|
||
* Short3 : [0..7]
|
||
*--------------------------------------
|
||
S.PAK.LEN .EQ 0
|
||
S.PAK.SHORT4 .EQ 2
|
||
S.PAK.SHORT3 .EQ 18
|
||
S.PAK .EQ 26
|
||
*--------------------------------------
|
||
* BITSTREAM :
|
||
* 0 = STORE :
|
||
* 00 : 1 byte follow (10 bits)
|
||
* 01 = 2 + n (4 bits count)
|
||
*--------------
|
||
* 1 = CMD :
|
||
*---SHORT4 --- (3)+4=7 bits --------
|
||
* 100 : SHORT4
|
||
* xxxx = index in Short4 Table
|
||
*---SHORT3 --- (3)+3=6 bits --------
|
||
* 101 : SHORT3
|
||
* xxx = index in Short3 Table
|
||
*--- BACKLINK : (3)+8+5=16 bits ----
|
||
* 110 : BackLink
|
||
* 9 bits : Offset (LO8,HI1)
|
||
* 4 bits : 3 + n (4 bits count) (18 max)
|
||
*--- REP : (3)+1, (3)+1+4 =4/8 bits ----
|
||
* 111 : REP
|
||
* 0 : repeat last byte
|
||
* 1 : repeat 2 + n (4 bits count)
|
||
*--------------------------------------
|
||
* In :
|
||
* PULLW = Src PTR
|
||
* PULLW = Src LEN
|
||
* PULLW = Dst PTR Compressed Buffer
|
||
*--------------------------------------
|
||
PIPELEN .EQ 18
|
||
STATS.SIZE .EQ 0
|
||
STATS.BL .EQ 2
|
||
STATS.REP .EQ 4
|
||
STATS.S3 .EQ 6
|
||
STATS.S4 .EQ 8
|
||
*--------------------------------------
|
||
S.Pak >PULLYA
|
||
>STYA S.Pak.Src Init for pass #1
|
||
>STYA S.Pak.SrcPtr
|
||
>PULLA Get Src Len LO
|
||
eor #$ff
|
||
sta S.Pak.SrcCnt
|
||
sta S.Pak.Cnt Init for pass #1
|
||
tax
|
||
|
||
>PULLA Get Src Len HI
|
||
eor #$ff
|
||
sta S.Pak.SrcCnt+1
|
||
sta S.Pak.Cnt+1 Init for pass #1
|
||
tay
|
||
|
||
>PULLW S.Pak.DstPtr
|
||
txa
|
||
jsr S.Pak.PutByte
|
||
tya
|
||
jsr S.Pak.PutByte
|
||
|
||
ldx #9
|
||
.1 stz S.Pak.Stat.Size,x Reset Stats
|
||
dex
|
||
bpl .1
|
||
|
||
* PASS #1 : Count occurence for each value...
|
||
|
||
S.Pak.1 ldx #0
|
||
.1 stz S.Pak.CntL,x
|
||
stz S.Pak.CntH,x
|
||
inx
|
||
bne .1
|
||
|
||
ldy #0
|
||
|
||
.2 inc S.Pak.Cnt
|
||
bne .3
|
||
inc S.Pak.Cnt+1
|
||
beq .5
|
||
|
||
.3 lda (S.Pak.SrcPtr),y
|
||
tax
|
||
inc S.Pak.CntL,x
|
||
bne .4
|
||
inc S.Pak.CntH,x
|
||
.4 iny
|
||
bne .2
|
||
inc S.Pak.SrcPtr+1
|
||
bra .2
|
||
|
||
* ...Search for Top 24
|
||
.5 ldy #23
|
||
|
||
.6 stz S.Pak.Cnt Init best score to 0
|
||
stz S.Pak.Cnt+1
|
||
|
||
stz S.Pak.Byte
|
||
ldx #0
|
||
|
||
.7 lda S.Pak.CntL,x is it better at X
|
||
cmp S.Pak.Cnt
|
||
lda S.Pak.CntH,x
|
||
sbc S.Pak.Cnt+1
|
||
bcs .8 not better
|
||
|
||
stx S.Pak.Byte
|
||
lda S.Pak.CntL,x
|
||
sta S.Pak.Cnt
|
||
lda S.Pak.CntH,x
|
||
sta S.Pak.Cnt+1
|
||
|
||
.8 inx
|
||
bne .7
|
||
|
||
lda S.Pak.Byte
|
||
sta S.Pak.Short,y
|
||
stz S.Pak.CntL,x Discard this entry
|
||
stz S.Pak.CntH,x
|
||
dey
|
||
bpl .6
|
||
|
||
ldx #15
|
||
|
||
.9 lda S.Pak.Short4,x Store SHORT4 in reverse order
|
||
jsr S.Pak.PutByte
|
||
dex
|
||
bpl .9
|
||
|
||
ldx #7
|
||
|
||
.10 lda S.Pak.Short3,x Store SHORT3 in reverse order
|
||
jsr S.Pak.PutByte
|
||
dex
|
||
bpl .10
|
||
|
||
>LDYAI S.PAK Total Header Size
|
||
>STYA S.Pak.Stat.Size
|
||
* PASS #2 :
|
||
S.Pak.2 >LDYA S.Pak.Src Init for pass #2
|
||
>STYA S.Pak.SrcPtr
|
||
>STYA S.Pak.SrcBlPtr
|
||
|
||
>LDYA S.Pak.SrcCnt
|
||
>STYA S.Pak.Cnt
|
||
|
||
lda #8
|
||
sta S.Pak.PutBit+1 Initialize properly for first "PutBit" Call
|
||
stz S.Pak.Byte
|
||
|
||
stz S.Pak.PipeLen
|
||
|
||
S.Pak.2.LOOP ldx S.Pak.PipeLen Always fill Bytes in the PIPE until full
|
||
|
||
.1 jsr S.Pak.GetByte Load PIPE....
|
||
bcs .2 end of Buffer ?
|
||
sta S.Pak.Pipe,x
|
||
inx
|
||
cpx #PIPELEN PIPE Full ?
|
||
bne .1
|
||
clc
|
||
|
||
.2 stx S.Pak.PipeLen
|
||
|
||
txa PIPE empty ....exit
|
||
beq .99
|
||
|
||
* try finding REPeating same bytes.....
|
||
S.Pak.2.REP dex
|
||
beq S.Pak.2.SHORT Only one char in PIPE...
|
||
|
||
ldx #0
|
||
|
||
.1 lda S.Pak.Pipe,x
|
||
cmp S.Pak.Pipe+1,x
|
||
bne .2
|
||
inx
|
||
cpx S.Pak.PipeLen
|
||
bne .1
|
||
|
||
.2 dex if one char.....no REP
|
||
beq .S.Pak.2.BL
|
||
dex if 2, -> REP ONE (not 2)
|
||
phx REP 1 + 0 or more....save REP count for later....
|
||
|
||
jsr S.Pak.2.STORE1 a = byte to store
|
||
|
||
lda #%11100000
|
||
plx
|
||
phx
|
||
beq .3
|
||
ora #%00010000
|
||
ldy #4
|
||
jsr S.Pak.PutYBits
|
||
txa
|
||
beq .4 if not REP 2 or more no extra count
|
||
ldy #4
|
||
jsr S.Pak.PutYBits
|
||
|
||
.4 pla
|
||
clc
|
||
adc #2
|
||
tay
|
||
jsr S.Pak.StripPipe Remove REP bytes from PIPE
|
||
|
||
ldy #STATS.REP
|
||
jsr S.Pak.UpdateStats
|
||
jmp S.Pak.2.LOOP
|
||
S.Pak.2.BL
|
||
* Try finding best matching BackLink between SrcBlPtr and SrcPtr (max 512)
|
||
.4 lda S.Pak.SrcPtr
|
||
sec
|
||
sbc S.Pak.PipeLen
|
||
sta S.Pak.Limit setup Limit to SrcPtr-PIPE
|
||
lda S.Pak.SrcPtr+1
|
||
sbc #0
|
||
sta S.Pak.Limit+1
|
||
|
||
.40 lda S.Pak.SrcBlPtr
|
||
sta S.Pak.SrcBlPtrT
|
||
lda S.Pak.SrcBlPtr+1
|
||
sta S.Pak.SrcBlPtrT+1
|
||
|
||
.5 txa Get PIPE Len
|
||
|
||
clc make sure SrcBlPtrT+PIPE < Limit
|
||
adc S.Pak.SrcBlPtrT
|
||
tay
|
||
lda S.Pak.SrcBlPtrT+1
|
||
adc #0
|
||
cpy S.Pak.Limit
|
||
sbc S.Pak.Limit+1
|
||
bcc .10 not enough room
|
||
|
||
txa
|
||
dec
|
||
tay
|
||
.8 lda (S.Pak.SrcBlPtrT),y
|
||
cmp S.Pak.Pipe,y
|
||
bne .9
|
||
dey
|
||
bpl .8
|
||
|
||
* Found a BL at S.Pak.SrcBlPtrT, Store it and remove X bytes from PIPE
|
||
phx save BL length
|
||
|
||
lda #%1100000
|
||
ldy #3
|
||
jsr S.Pak.PutYBits
|
||
|
||
lda S.Pak.Limit
|
||
sec
|
||
sbc S.Pak.SrcBlPtrT
|
||
php save C
|
||
|
||
ldy #8
|
||
jsr S.Pak.PutYBits
|
||
|
||
plp
|
||
lda S.Pak.Limit+1
|
||
sec
|
||
sbc S.Pak.SrcBlPtrT+1
|
||
|
||
jsr S.Pak.PutBit
|
||
|
||
ply Get back BL len
|
||
phy
|
||
|
||
jsr S.Pak.StripPipe Remove LEN bytes from PIPE
|
||
|
||
pla Get back BL len
|
||
sec
|
||
sbc #3 Adjust Range..3-18 to 0->15
|
||
asl
|
||
asl
|
||
asl
|
||
asl
|
||
ldy #4 store 4 bits len
|
||
jsr S.Pak.PutYBits
|
||
ldy #STATS.BL
|
||
jsr S.Pak.UpdateStats
|
||
jmp S.Pak.2.LOOP
|
||
|
||
* No match...try starting at next byte
|
||
.9 inc S.Pak.SrcBlPtrT
|
||
bne .5
|
||
inc S.Pak.SrcBlPtrT+1
|
||
bra .5
|
||
.10 dex reduce PIPE
|
||
cpx #2 2 bytes remaining? no need to BL, a BL is 16bits wide.....
|
||
bne .40 and start over from BLPtr
|
||
|
||
* NO Bl Found, STORE
|
||
S.Pak.STORE lda S.Pak.Pipe
|
||
jsr S.Pak.2.STORE1
|
||
ldy #1
|
||
jsr S.Pak.StripPipe
|
||
jmp S.Pak.2.LOOP
|
||
*--------------------------------------
|
||
S.Pak.2.STORE1
|
||
rts
|
||
*--------------------------------------
|
||
S.Pak.GetByte inc S.UnPak.Cnt
|
||
bne .1
|
||
inc S.UnPak.Cnt+1
|
||
.1 beq .9
|
||
lda (S.Pak.SrcPtr)
|
||
pha
|
||
inc S.Pak.SrcPtr
|
||
bne .2
|
||
inc S.Pak.SrcPtr+1
|
||
.2 clc
|
||
rts
|
||
.9 sec
|
||
rts
|
||
*--------------------------------------
|
||
S.Pak.PutYBits asl
|
||
jsr S.Pak.PutBit
|
||
dey
|
||
bne S.Pak.PutYBits
|
||
rts
|
||
*--------------------------------------
|
||
* S.Pak.PutBit (bit in C)
|
||
*--------------------------------------
|
||
S.Pak.PutBit ldx #$ff
|
||
pha
|
||
bne .1
|
||
lda S.Pak.Byte
|
||
jsr S.Pak.PutByte
|
||
stz S.Pak.Byte
|
||
ldx #8
|
||
|
||
.1 dex
|
||
stx S.Pak.PutBit+1
|
||
bcc .8 Nothing to "light up"
|
||
|
||
lda S.Pak.Byte
|
||
lda S.Pak.BitMask,x
|
||
sta S.Pak.Byte
|
||
.8 pla
|
||
rts
|
||
*--------------------------------------
|
||
S.Pak.PutByte sta (S.UnPak.DstPtr)
|
||
inc S.UnPak.DstPtr
|
||
bne .1
|
||
inc S.UnPak.DstPtr+1
|
||
|
||
.1 inc S.Pak.Stat.Size
|
||
bne .2
|
||
inc S.Pak.Stat.Size+1
|
||
.2
|
||
rts
|
||
*--------------------------------------
|
||
* Y = count to remove from PIPE
|
||
*--------------------------------------
|
||
S.Pak.StripPipe ldx S.Pak.PipeLen
|
||
beq .9
|
||
|
||
ldx #0
|
||
|
||
.1 lda S.Pak.Pipe+1,x
|
||
sta S.Pak.Pipe,x
|
||
inx
|
||
cpx S.Pak.PipeLen
|
||
bne .1
|
||
dec S.Pak.PipeLen
|
||
dey
|
||
bne S.Pak.StripPipe
|
||
|
||
.9 rts
|
||
*--------------------------------------
|
||
S.Pak.UpdateStats
|
||
inc S.Pak.Stat.Size,y
|
||
bne .8
|
||
inc S.Pak.Stat.Size+1,y
|
||
.8 rts
|
||
*--------------------------------------
|
||
S.Pak.BitMask .HS 0102040810204080
|
||
S.Pak.Src .BS 2
|
||
S.Pak.SrcCnt .BS 2
|
||
S.Pak.Cnt .BS 2
|
||
S.Pak.CntL .BS 256
|
||
S.Pak.CntH .BS 256
|
||
S.Pak.Short4 .BS 16
|
||
S.Pak.Short3 .BS 8
|
||
S.Pak.Byte .BS 1
|
||
S.Pak.Limit .BS 2
|
||
S.Pak.PipeLen .BS 1
|
||
S.Pak.Pipe .BS 18
|
||
*--------------------------------------
|
||
S.Pak.Stat.Size .BS 2
|
||
S.Pak.Stat.BL .BS 2
|
||
S.Pak.Stat.REP .BS 2
|
||
S.Pak.Stat.S3 .BS 2
|
||
S.Pak.Stat.S4 .BS 2
|
||
*--------------------------------------
|
||
* S.UnPak
|
||
* In :
|
||
* PULLW = Src PTR Compressed Buffer
|
||
* PULLW = Dst PTR
|
||
*--------------------------------------
|
||
S.UnPak.SrcPtr .EQ ZPLIB
|
||
S.UnPak.DstPtr .EQ ZPLIB+2
|
||
S.UnPak.ShrtTbl .EQ ZPLIB+4
|
||
S.UnPak.Cnt .EQ ZPLIB+6
|
||
*--------------------------------------
|
||
S.UnPak >PULLW S.UnPak.SrcPtr
|
||
>PULLA Get Dst PTR LO
|
||
sec
|
||
sbc #1
|
||
sta S.UnPak.DstPtr
|
||
>PULLA Get Dst PTR HI
|
||
sbc #0
|
||
sta S.UnPak.DstPtr+1 setup Dst PTR-1
|
||
|
||
jsr S.UnPak.GetByte Get !LEN for counting up to $0000
|
||
sta S.UnPak.Cnt
|
||
|
||
jsr S.UnPak.GetByte
|
||
sta S.UnPak.Cnt+1
|
||
|
||
>LDYA S.UnPak.SrcPtr Get PTR to Short Table.....
|
||
>STYA S.UnPak.ShrtTbl and save it for SHORTx
|
||
|
||
lda #8
|
||
sta S.UnPak.GetBit+1 Initialize properly for first "GetBit" Call
|
||
|
||
.1 inc S.UnPak.Cnt
|
||
bne .2
|
||
inc S.UnPak.Cnt+1
|
||
beq .99
|
||
|
||
.2 jsr S.UnPak.GetBit
|
||
bcs .4 CMD....
|
||
*---- STORE
|
||
jsr S.UnPak.GetBit
|
||
ldx #1
|
||
bcc .3 if CC one byte
|
||
jsr S.UnPak.Get4Bits CC
|
||
adc #2 range is 2->17
|
||
tax
|
||
|
||
.3 jsr S.UnPak.Get8Bits
|
||
jsr S.UnPak.PutByte
|
||
dex
|
||
bne .3
|
||
bra .1
|
||
.99 rts
|
||
*---- CMD
|
||
.4 jsr S.UnPak.GetBit
|
||
bcs .6 BACKLINK or REP...
|
||
*---- CMD : SHORT
|
||
lda #0
|
||
ldy #4
|
||
|
||
jsr S.UnPak.GetBit if CS short3
|
||
rol make offset 00000001
|
||
asl ....00000010
|
||
beq .5
|
||
|
||
dey if short3, only 3 bits
|
||
|
||
.5 jsr S.UnPak.GetBit
|
||
rol
|
||
dey
|
||
bne .5
|
||
|
||
tay if s3, offset is 00010xxx
|
||
lda (S.UnPak.ShrtTbl),y if s4, offset is 0000xxxx
|
||
jsr S.UnPak.PutByte
|
||
bra .1
|
||
*---- CMD : BACKLINK or REP
|
||
.6 jsr S.UnPak.GetBit
|
||
bcs .8 if CS -> REP
|
||
*---- CMD : BACKLINK
|
||
jsr S.UnPak.Get8Bits get Offset LO, (CC)
|
||
eor #$ff !offset LO
|
||
adc S.UnPak.DstPtr equiv. SUB offset
|
||
sta .7+1 PTR to Backlink LO
|
||
lda S.UnPak.DstPtr+1
|
||
bcs .61 if ADC sets C, no need to dec HI
|
||
dec
|
||
.61 jsr S.UnPak.GetBit get Offset HI in C
|
||
bcc .62
|
||
dec
|
||
.62 sta .7+2 PTR to Backlink HI
|
||
|
||
jsr S.UnPak.Get4Bits CC
|
||
adc #3 Backlink are ate least 3 bytes...
|
||
tax
|
||
ldy #0
|
||
|
||
.7 lda $ffff,y Self Modified code : PTR to Backlink
|
||
jsr S.UnPak.PutByte
|
||
iny
|
||
dex
|
||
bne .7
|
||
beq .1
|
||
*---- CMD : REP
|
||
.8 jsr S.UnPak.GetBit
|
||
ldx #1
|
||
bcc .9 REP 1
|
||
|
||
jsr S.UnPak.Get4Bits REP xxxx, CC
|
||
adc #2 range is 2->17
|
||
tax
|
||
|
||
.9 lda (S.UnPak.DstPtr) Get Last Byte
|
||
jsr S.UnPak.PutByte
|
||
dex
|
||
bne .9
|
||
beq .1
|
||
*--------------------------------------
|
||
S.UnPak.Get8Bits
|
||
ldy #8
|
||
.HS 2C bit abs
|
||
S.UnPak.Get4Bits
|
||
ldy #4
|
||
lda #0 make sure to reset A before reading less than 8 bits only
|
||
.1 jsr S.UnPak.GetBit and to exit with CC if even if 8 bits read
|
||
rol
|
||
dey
|
||
bne .1
|
||
rts always CC
|
||
*--------------------------------------
|
||
S.UnPak.GetBit ldx #$ff Self Modified code
|
||
bne .1
|
||
jsr S.UnPak.NxtByte
|
||
|
||
ldx #8
|
||
|
||
.1 dex
|
||
stx S.UnPak.GetBit+1
|
||
|
||
pha Don't trash A
|
||
lda (S.UnPak.SrcPtr)
|
||
and S.UnPak.BitMask,x
|
||
cmp #1 if 0:CC, i>0 CS
|
||
|
||
pla
|
||
rts Bit is in C
|
||
*--------------------------------------
|
||
S.UnPak.GetByte lda (S.UnPak.SrcPtr)
|
||
S.UnPak.NxtByte inc S.UnPak.SrcPtr
|
||
bne .8
|
||
inc S.UnPak.SrcPtr+1
|
||
.8 rts
|
||
*--------------------------------------
|
||
S.UnPak.PutByte inc S.UnPak.DstPtr
|
||
bne .8
|
||
inc S.UnPak.DstPtr+1
|
||
.8 sta (S.UnPak.DstPtr)
|
||
rts
|
||
*--------------------------------------
|
||
S.UnPak.BitMask .HS 8040201008040201
|
||
MAN
|
||
SAVE LIB/LIBPAK.S
|
||
ASM
|