mirror of
https://github.com/fadden/fhpack.git
synced 2024-09-27 08:54:55 +00:00
Merge branch 'peterferrie-master'
This commit is contained in:
commit
9221ef09d1
127
LZ4FH6502.S
127
LZ4FH6502.S
@ -2,7 +2,10 @@
|
|||||||
* *
|
* *
|
||||||
* LZ4FH uncompression for 6502 *
|
* LZ4FH uncompression for 6502 *
|
||||||
* By Andy McFadden *
|
* By Andy McFadden *
|
||||||
* Version 1.0, August 2015 *
|
* Version 1.0.1, August 2015 *
|
||||||
|
* *
|
||||||
|
* Refactored for size & speed *
|
||||||
|
* by Peter Ferrie. *
|
||||||
* *
|
* *
|
||||||
* Developed with Merlin-16 *
|
* Developed with Merlin-16 *
|
||||||
* *
|
* *
|
||||||
@ -59,13 +62,54 @@ entry
|
|||||||
lda (srcptr),y
|
lda (srcptr),y
|
||||||
cmp #lz4fh_magic ;does magic match?
|
cmp #lz4fh_magic ;does magic match?
|
||||||
beq goodmagic
|
beq goodmagic
|
||||||
jmp fail
|
|
||||||
|
fail
|
||||||
|
jsr bell
|
||||||
|
jmp monitor
|
||||||
|
|
||||||
|
* These stubs increment the high byte and then jump
|
||||||
|
* back. This saves a cycle because branch-not-taken
|
||||||
|
* becomes the common case. We assume that we're not
|
||||||
|
* unpacking data at $FFxx, so BNE is branch-always.
|
||||||
|
hi2
|
||||||
|
inc srcptr+1
|
||||||
|
bne nohi2
|
||||||
|
|
||||||
|
hi3
|
||||||
|
inc srcptr+1
|
||||||
|
clc
|
||||||
|
bcc nohi3
|
||||||
|
|
||||||
|
hi4
|
||||||
|
inc dstptr+1
|
||||||
|
bne nohi4
|
||||||
|
|
||||||
|
notempty
|
||||||
|
cmp #tok_eod
|
||||||
|
bne fail
|
||||||
|
rts ;success!
|
||||||
|
|
||||||
|
* handle "special" match values (value in A)
|
||||||
|
specialmatch
|
||||||
|
cmp #tok_empty
|
||||||
|
bne notempty
|
||||||
|
|
||||||
|
tya ;empty match, advance srcptr
|
||||||
|
adc srcptr ; past and jump to main loop
|
||||||
|
sta srcptr
|
||||||
|
bcc mainloop
|
||||||
|
inc srcptr+1
|
||||||
|
bne mainloop
|
||||||
|
|
||||||
|
hi5
|
||||||
|
inc srcptr+1
|
||||||
|
clc
|
||||||
|
bcc nohi5
|
||||||
|
|
||||||
goodmagic
|
goodmagic
|
||||||
inc srcptr
|
inc srcptr
|
||||||
bne :nohi
|
bne mainloop
|
||||||
inc srcptr+1
|
inc srcptr+1
|
||||||
:nohi
|
|
||||||
|
|
||||||
mainloop
|
mainloop
|
||||||
* Get the mixed-length byte and handle the literal.
|
* Get the mixed-length byte and handle the literal.
|
||||||
@ -77,16 +121,14 @@ mainloop
|
|||||||
lsr A
|
lsr A
|
||||||
lsr A
|
lsr A
|
||||||
beq noliteral
|
beq noliteral
|
||||||
cmp #$0f
|
cmp #$0f ;sets carry for >= 15
|
||||||
bne shortlit
|
bne shortlit
|
||||||
|
|
||||||
inc srcptr
|
inc srcptr
|
||||||
bne :nohi
|
beq hi2
|
||||||
inc srcptr+1
|
nohi2
|
||||||
:nohi
|
|
||||||
lda (srcptr),y ;get length extension
|
lda (srcptr),y ;get length extension
|
||||||
clc
|
adc #14 ;(carry set) add 15 - will not exceed 255
|
||||||
adc #15 ;add 15 - will not exceed 255
|
|
||||||
|
|
||||||
* At this point, srcptr holds the address of the "mix"
|
* At this point, srcptr holds the address of the "mix"
|
||||||
* word or the length extension, and dstptr holds the
|
* word or the length extension, and dstptr holds the
|
||||||
@ -98,7 +140,7 @@ mainloop
|
|||||||
* We could save a couple of cycles by substituting
|
* We could save a couple of cycles by substituting
|
||||||
* addr,y in place of (dp),y, but the added setup cost
|
* addr,y in place of (dp),y, but the added setup cost
|
||||||
* would only benefit longer literal strings.
|
* would only benefit longer literal strings.
|
||||||
shortlit sta savlen
|
shortlit tax
|
||||||
tay
|
tay
|
||||||
:litloop
|
:litloop
|
||||||
lda (srcptr),y ;5
|
lda (srcptr),y ;5
|
||||||
@ -107,21 +149,18 @@ shortlit sta savlen
|
|||||||
bne :litloop ;3 -> 16 cycles/byte
|
bne :litloop ;3 -> 16 cycles/byte
|
||||||
|
|
||||||
* Advance srcptr by savlen+1, and dstptr by savlen
|
* Advance srcptr by savlen+1, and dstptr by savlen
|
||||||
lda srcptr
|
txa
|
||||||
sec ;this gets us the +1
|
sec ;this gets us the +1
|
||||||
adc savlen
|
adc srcptr
|
||||||
sta srcptr
|
sta srcptr
|
||||||
bcc :nohi
|
bcs hi3
|
||||||
inc srcptr+1
|
nohi3 ;carry cleared by hi3
|
||||||
clc
|
txa
|
||||||
:nohi
|
adc dstptr
|
||||||
lda dstptr
|
|
||||||
adc savlen
|
|
||||||
sta dstptr
|
sta dstptr
|
||||||
bcc :nohi1
|
bcs hi4
|
||||||
inc dstptr+1
|
nohi4
|
||||||
:nohi1
|
dey ;Y=0; DEY so next INY goes to 0
|
||||||
ldy #$ff ;next INY rolls back to zero
|
|
||||||
|
|
||||||
* Handle match. Y holds an offset into srcptr such
|
* Handle match. Y holds an offset into srcptr such
|
||||||
* that we need to increment it once to get the next
|
* that we need to increment it once to get the next
|
||||||
@ -155,13 +194,13 @@ _desthi ora #$00 ;OR in hi-res page
|
|||||||
* remember how many bytes it took to encode. Y is
|
* remember how many bytes it took to encode. Y is
|
||||||
* indexing the last value used, so we want to go
|
* indexing the last value used, so we want to go
|
||||||
* advance srcptr by Y+1.
|
* advance srcptr by Y+1.
|
||||||
|
|
||||||
tya
|
tya
|
||||||
sec
|
sec
|
||||||
adc srcptr
|
adc srcptr
|
||||||
sta srcptr
|
sta srcptr
|
||||||
bcc :nohi
|
bcs hi5
|
||||||
inc srcptr+1
|
nohi5 ;hi5 clears carry
|
||||||
:nohi
|
|
||||||
|
|
||||||
* Copy the match. The length is in X. Note this
|
* Copy the match. The length is in X. Note this
|
||||||
* must be a forward copy so overlapped data works.
|
* must be a forward copy so overlapped data works.
|
||||||
@ -180,46 +219,24 @@ _desthi ora #$00 ;OR in hi-res page
|
|||||||
|
|
||||||
* advance dstptr past copied data
|
* advance dstptr past copied data
|
||||||
lda dstptr
|
lda dstptr
|
||||||
clc
|
adc savlen ;carry is clear
|
||||||
adc savlen
|
|
||||||
sta dstptr
|
sta dstptr
|
||||||
bcc :nohi1
|
bcc mainloop
|
||||||
inc dstptr+1
|
inc dstptr+1
|
||||||
:nohi1
|
|
||||||
|
|
||||||
DO overrun_check
|
DO overrun_check
|
||||||
LDA dstptr+1
|
LDA dstptr+1
|
||||||
CMP #$60
|
CMP #$60
|
||||||
BLT :OKAY
|
bcc mainloop
|
||||||
BRK
|
BRK
|
||||||
BRK
|
BRK
|
||||||
:OKAY
|
|
||||||
jmp mainloop
|
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
|
|
||||||
bne mainloop ;branch always
|
bne mainloop ;always (not unpacking at $FFxx)
|
||||||
|
|
||||||
FIN
|
FIN
|
||||||
|
|
||||||
* handle "special" match values (value in A)
|
lst on
|
||||||
specialmatch
|
sav LZ4FH6502
|
||||||
cmp #tok_empty
|
lst off
|
||||||
bne :notempty
|
|
||||||
tya ;empty match, advance srcptr
|
|
||||||
adc srcptr ; past and jump to main loop
|
|
||||||
sta srcptr
|
|
||||||
bcc :nohi
|
|
||||||
inc srcptr+1
|
|
||||||
clc
|
|
||||||
:nohi
|
|
||||||
jmp mainloop
|
|
||||||
|
|
||||||
:notempty
|
|
||||||
cmp #tok_eod
|
|
||||||
bne fail
|
|
||||||
rts ;success!
|
|
||||||
fail
|
|
||||||
jsr bell
|
|
||||||
jmp monitor
|
|
||||||
|
|
||||||
|
240
LZ4FH6502.SMA.S
Normal file
240
LZ4FH6502.SMA.S
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* LZ4FH uncompression for 6502 *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 1.0.1, August 2015 *
|
||||||
|
* *
|
||||||
|
* Refactored for size & speed *
|
||||||
|
* by Peter Ferrie. (This *
|
||||||
|
* version favors code size.) *
|
||||||
|
* *
|
||||||
|
* Developed with Merlin-16 *
|
||||||
|
* *
|
||||||
|
********************************
|
||||||
|
lst off
|
||||||
|
org $0300
|
||||||
|
|
||||||
|
*
|
||||||
|
* Constants
|
||||||
|
*
|
||||||
|
lz4fh_magic equ $66 ;ascii 'f'
|
||||||
|
tok_empty equ 253
|
||||||
|
tok_eod equ 254
|
||||||
|
|
||||||
|
overrun_check equ 0
|
||||||
|
|
||||||
|
*
|
||||||
|
* Variable storage
|
||||||
|
*
|
||||||
|
srcptr equ $3c ;2b a1l
|
||||||
|
dstptr equ $3e ;2b a1h
|
||||||
|
copyptr equ $00 ;2b
|
||||||
|
savmix equ $02 ;1b
|
||||||
|
savlen equ $03 ;1b
|
||||||
|
savsrc equ $04 ;1b
|
||||||
|
|
||||||
|
*
|
||||||
|
* ROM routines
|
||||||
|
*
|
||||||
|
bell equ $ff3a
|
||||||
|
monitor equ $ff69
|
||||||
|
|
||||||
|
*
|
||||||
|
* Parameters, stashed at the top of the text input
|
||||||
|
* buffer. We use this, rather than just having them
|
||||||
|
* poked directly into the code, so that the 6502 and
|
||||||
|
* 65816 implementations work the same way without
|
||||||
|
* either getting weird.
|
||||||
|
*
|
||||||
|
in_src equ $2fc ;2b
|
||||||
|
in_dst equ $2fe ;2b
|
||||||
|
|
||||||
|
entry
|
||||||
|
lda in_src ;copy source address to zero page
|
||||||
|
sta srcptr
|
||||||
|
lda in_src+1
|
||||||
|
sta srcptr+1
|
||||||
|
lda in_dst ;copy destination address to zero page
|
||||||
|
sta dstptr
|
||||||
|
lda in_dst+1
|
||||||
|
sta dstptr+1
|
||||||
|
sta _desthi+1
|
||||||
|
|
||||||
|
ldy #$00
|
||||||
|
lda (srcptr),y
|
||||||
|
cmp #lz4fh_magic ;does magic match?
|
||||||
|
beq goodmagic
|
||||||
|
|
||||||
|
fail
|
||||||
|
jsr bell
|
||||||
|
jmp monitor
|
||||||
|
|
||||||
|
* These stubs increment the high byte and then jump
|
||||||
|
* back. This saves a cycle because branch-not-taken
|
||||||
|
* becomes the common case. We assume that we're not
|
||||||
|
* unpacking data at $ffxx, so BNE is branch-always.
|
||||||
|
hi2
|
||||||
|
inc srcptr+1
|
||||||
|
bne nohi2
|
||||||
|
|
||||||
|
hi3
|
||||||
|
inc srcptr+1
|
||||||
|
clc
|
||||||
|
bcc nohi3
|
||||||
|
|
||||||
|
hi4
|
||||||
|
inc dstptr+1
|
||||||
|
bne nohi4
|
||||||
|
|
||||||
|
notempty
|
||||||
|
cmp #tok_eod
|
||||||
|
bne fail
|
||||||
|
rts ;success!
|
||||||
|
|
||||||
|
* handle "special" match values (value in A)
|
||||||
|
specialmatch
|
||||||
|
cmp #tok_empty
|
||||||
|
bne notempty
|
||||||
|
advsrc1
|
||||||
|
sec
|
||||||
|
advsrc2
|
||||||
|
|
||||||
|
tya ;empty match, advance srcptr
|
||||||
|
adc srcptr ; past and jump to main loop
|
||||||
|
sta srcptr
|
||||||
|
bcc mainloop
|
||||||
|
inc srcptr+1
|
||||||
|
bne mainloop
|
||||||
|
|
||||||
|
goodmagic
|
||||||
|
inc srcptr
|
||||||
|
bne mainloop
|
||||||
|
inc srcptr+1
|
||||||
|
|
||||||
|
mainloop
|
||||||
|
* Get the mixed-length byte and handle the literal.
|
||||||
|
ldy #$00
|
||||||
|
lda (srcptr),y ;get mixed-length byte
|
||||||
|
sta savmix
|
||||||
|
lsr A ;get the literal length
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
beq noliteral
|
||||||
|
cmp #$0f ;sets carry for >= 15
|
||||||
|
bne shortlit
|
||||||
|
|
||||||
|
inc srcptr
|
||||||
|
beq hi2
|
||||||
|
nohi2
|
||||||
|
lda (srcptr),y ;get length extension
|
||||||
|
adc #14 ;(carry set) add 15 - will not exceed 255
|
||||||
|
|
||||||
|
* At this point, srcptr holds the address of the "mix"
|
||||||
|
* word or the length extension, and dstptr holds the
|
||||||
|
* address of the next output location. So we want to
|
||||||
|
* read from (srcptr),y+1 and write to (dstptr),y.
|
||||||
|
* We can do this by sticking the DEY between the LDA
|
||||||
|
* and STA.
|
||||||
|
*
|
||||||
|
* We could save a couple of cycles by substituting
|
||||||
|
* addr,y in place of (dp),y, but the added setup cost
|
||||||
|
* would only benefit longer literal strings.
|
||||||
|
shortlit tax
|
||||||
|
tay
|
||||||
|
:litloop
|
||||||
|
lda (srcptr),y ;5
|
||||||
|
dey ;2 if len is 255, copy 0-254
|
||||||
|
sta (dstptr),y ;6
|
||||||
|
bne :litloop ;3 -> 16 cycles/byte
|
||||||
|
|
||||||
|
* Advance srcptr by savlen+1, and dstptr by savlen
|
||||||
|
txa
|
||||||
|
sec ;this gets us the +1
|
||||||
|
adc srcptr
|
||||||
|
sta srcptr
|
||||||
|
bcs hi3
|
||||||
|
nohi3
|
||||||
|
txa
|
||||||
|
adc dstptr
|
||||||
|
sta dstptr
|
||||||
|
bcs hi4
|
||||||
|
nohi4
|
||||||
|
dey ;Y=0; DEY so next INY goes to 0
|
||||||
|
|
||||||
|
* Handle match. Y holds an offset into srcptr such
|
||||||
|
* that we need to increment it once to get the next
|
||||||
|
* interesting byte.
|
||||||
|
noliteral
|
||||||
|
lda savmix
|
||||||
|
and #$0f
|
||||||
|
cmp #$0f
|
||||||
|
blt :shortmatch ;BCC
|
||||||
|
|
||||||
|
iny
|
||||||
|
lda (srcptr),y ;get length extension
|
||||||
|
cmp #237 ;"normal" values are 0-236
|
||||||
|
bge specialmatch ;BCS
|
||||||
|
adc #15 ;will not exceed 255
|
||||||
|
|
||||||
|
* Put the destination address into copyptr.
|
||||||
|
:shortmatch
|
||||||
|
adc #4 ;min match; won't exceed 255
|
||||||
|
sta savlen ;save match len for later
|
||||||
|
tax ;and keep it in X
|
||||||
|
iny
|
||||||
|
lda (srcptr),y ;match offset, lo
|
||||||
|
sta copyptr
|
||||||
|
iny
|
||||||
|
lda (srcptr),y ;match offset, hi
|
||||||
|
_desthi ora #$00 ;OR in hi-res page
|
||||||
|
sta copyptr+1
|
||||||
|
|
||||||
|
* Advance srcptr past the encoded match while we still
|
||||||
|
* remember how many bytes it took to encode. Y is
|
||||||
|
* indexing the last value used, so we want to go
|
||||||
|
* advance srcptr by Y+1.
|
||||||
|
|
||||||
|
sty savsrc
|
||||||
|
|
||||||
|
* Copy the match. The length is in X. Note this
|
||||||
|
* must be a forward copy so overlapped data works.
|
||||||
|
*
|
||||||
|
* We know the match is at least 4 bytes long, so
|
||||||
|
* we could save a few cycles by not doing the
|
||||||
|
* ADC #4 earlier, and unrolling the first 4
|
||||||
|
* load/store operations here.
|
||||||
|
ldy #$00
|
||||||
|
:copyloop
|
||||||
|
lda (copyptr),y ;5
|
||||||
|
sta (dstptr),y ;6
|
||||||
|
iny ;2
|
||||||
|
dex ;2
|
||||||
|
bne :copyloop ;3 -> 18 cycles/byte
|
||||||
|
|
||||||
|
* advance dstptr past copied data
|
||||||
|
lda dstptr
|
||||||
|
adc savlen ;carry should still be clear
|
||||||
|
sta dstptr
|
||||||
|
|
||||||
|
ldy savsrc
|
||||||
|
linkadv
|
||||||
|
bcc advsrc1
|
||||||
|
|
||||||
|
inc dstptr+1
|
||||||
|
DO overrun_check
|
||||||
|
LDA dstptr+1
|
||||||
|
CMP #$60
|
||||||
|
bcc linkadv
|
||||||
|
BRK
|
||||||
|
BRK
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
bne advsrc2
|
||||||
|
|
||||||
|
FIN
|
||||||
|
|
||||||
|
|
||||||
|
lst on
|
||||||
|
sav LZ4FH6502
|
||||||
|
lst off
|
50
LZ4FH65816.S
50
LZ4FH65816.S
@ -2,7 +2,10 @@
|
|||||||
* *
|
* *
|
||||||
* LZ4FH uncompression for 65816 *
|
* LZ4FH uncompression for 65816 *
|
||||||
* By Andy McFadden *
|
* By Andy McFadden *
|
||||||
* Version 1.0, August 2015 *
|
* Version 1.0.1, August 2015 *
|
||||||
|
* *
|
||||||
|
* Refactored for size & speed *
|
||||||
|
* by Peter Ferrie. *
|
||||||
* *
|
* *
|
||||||
* Developed with Merlin-16 *
|
* Developed with Merlin-16 *
|
||||||
* *
|
* *
|
||||||
@ -55,7 +58,27 @@ entry
|
|||||||
inx
|
inx
|
||||||
and #$00ff
|
and #$00ff
|
||||||
cmp #lz4fh_magic
|
cmp #lz4fh_magic
|
||||||
|
beq mainloop
|
||||||
|
|
||||||
|
fail
|
||||||
|
jsr bell
|
||||||
|
jmp monitor
|
||||||
|
|
||||||
|
notempty
|
||||||
|
cmp #tok_eod ;end-of-data or error
|
||||||
|
|
||||||
|
* exit
|
||||||
|
sec ;return to emulation mode
|
||||||
|
xce
|
||||||
bne fail
|
bne fail
|
||||||
|
rts
|
||||||
|
|
||||||
|
mx %00 ;undo the sec/xce
|
||||||
|
|
||||||
|
* handle "special" match length values (in A)
|
||||||
|
specialmatch
|
||||||
|
cmp #tok_empty
|
||||||
|
bne notempty
|
||||||
|
|
||||||
mainloop
|
mainloop
|
||||||
lda $0000,x
|
lda $0000,x
|
||||||
@ -73,8 +96,7 @@ mainloop
|
|||||||
lda $0000,x ;length >= 15, get next
|
lda $0000,x ;length >= 15, get next
|
||||||
inx
|
inx
|
||||||
and #$00ff
|
and #$00ff
|
||||||
clc
|
adc #14 ;(carry set) +15 - won't exceed 255
|
||||||
adc #15
|
|
||||||
|
|
||||||
* At this point, Y holds the address of the next
|
* At this point, Y holds the address of the next
|
||||||
* compressed data byte, X has the address of the
|
* compressed data byte, X has the address of the
|
||||||
@ -115,22 +137,6 @@ _dstmod ora #$ff00 ;OR in hi-res page
|
|||||||
plx ;restore srcptr
|
plx ;restore srcptr
|
||||||
bra mainloop
|
bra mainloop
|
||||||
|
|
||||||
* handle "special" match length values (in A)
|
lst on
|
||||||
specialmatch
|
sav LZ4FH65816
|
||||||
cmp #tok_empty
|
lst off
|
||||||
beq mainloop ;empty match, just loop
|
|
||||||
|
|
||||||
cmp #tok_eod
|
|
||||||
bne fail
|
|
||||||
|
|
||||||
* exit
|
|
||||||
sec ;return to emulation mode
|
|
||||||
xce
|
|
||||||
rts
|
|
||||||
|
|
||||||
fail
|
|
||||||
sec
|
|
||||||
xce
|
|
||||||
jsr bell
|
|
||||||
jmp monitor
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user