mirror of
https://github.com/fadden/fhpack.git
synced 2024-09-28 00:54:28 +00:00
Add asm source to git repository
It's on the LZ4FHDemo.do disk, but this is more convenient.
This commit is contained in:
parent
2b39c5ad5d
commit
7720b2c161
225
LZ4FH6502.S
Normal file
225
LZ4FH6502.S
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* LZ4FH uncompression for 6502 *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 1.0, August 2015 *
|
||||||
|
* *
|
||||||
|
* 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
|
||||||
|
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
jmp fail
|
||||||
|
|
||||||
|
goodmagic
|
||||||
|
inc srcptr
|
||||||
|
bne :nohi
|
||||||
|
inc srcptr+1
|
||||||
|
:nohi
|
||||||
|
|
||||||
|
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
|
||||||
|
bne shortlit
|
||||||
|
|
||||||
|
inc srcptr
|
||||||
|
bne :nohi
|
||||||
|
inc srcptr+1
|
||||||
|
:nohi
|
||||||
|
lda (srcptr),y ;get length extension
|
||||||
|
clc
|
||||||
|
adc #15 ;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 sta savlen
|
||||||
|
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
|
||||||
|
lda srcptr
|
||||||
|
sec ;this gets us the +1
|
||||||
|
adc savlen
|
||||||
|
sta srcptr
|
||||||
|
bcc :nohi
|
||||||
|
inc srcptr+1
|
||||||
|
clc
|
||||||
|
:nohi
|
||||||
|
lda dstptr
|
||||||
|
adc savlen
|
||||||
|
sta dstptr
|
||||||
|
bcc :nohi1
|
||||||
|
inc dstptr+1
|
||||||
|
:nohi1
|
||||||
|
ldy #$ff ;next INY rolls back to zero
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
tya
|
||||||
|
sec
|
||||||
|
adc srcptr
|
||||||
|
sta srcptr
|
||||||
|
bcc :nohi
|
||||||
|
inc srcptr+1
|
||||||
|
:nohi
|
||||||
|
|
||||||
|
* 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
|
||||||
|
clc
|
||||||
|
adc savlen
|
||||||
|
sta dstptr
|
||||||
|
bcc :nohi1
|
||||||
|
inc dstptr+1
|
||||||
|
:nohi1
|
||||||
|
|
||||||
|
DO overrun_check
|
||||||
|
LDA dstptr+1
|
||||||
|
CMP #$60
|
||||||
|
BLT :OKAY
|
||||||
|
BRK
|
||||||
|
BRK
|
||||||
|
:OKAY
|
||||||
|
jmp mainloop
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
bne mainloop ;branch always
|
||||||
|
|
||||||
|
FIN
|
||||||
|
|
||||||
|
* 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 :nohi
|
||||||
|
inc srcptr+1
|
||||||
|
clc
|
||||||
|
:nohi
|
||||||
|
jmp mainloop
|
||||||
|
|
||||||
|
:notempty
|
||||||
|
cmp #tok_eod
|
||||||
|
bne fail
|
||||||
|
rts ;success!
|
||||||
|
fail
|
||||||
|
jsr bell
|
||||||
|
jmp monitor
|
||||||
|
|
136
LZ4FH65816.S
Normal file
136
LZ4FH65816.S
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
*********************************
|
||||||
|
* *
|
||||||
|
* LZ4FH uncompression for 65816 *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 1.0, August 2015 *
|
||||||
|
* *
|
||||||
|
* Developed with Merlin-16 *
|
||||||
|
* *
|
||||||
|
*********************************
|
||||||
|
lst off
|
||||||
|
org $0300
|
||||||
|
|
||||||
|
xc ;allow 65c02 opcodes
|
||||||
|
xc ;allow 65816 opcodes
|
||||||
|
|
||||||
|
*
|
||||||
|
* Constants
|
||||||
|
*
|
||||||
|
lz4fh_magic equ $66 ;ascii 'f'
|
||||||
|
tok_empty equ 253
|
||||||
|
tok_eod equ 254
|
||||||
|
|
||||||
|
*
|
||||||
|
* Variable storage
|
||||||
|
*
|
||||||
|
savmix equ $00 ;2b
|
||||||
|
savlen equ $02 ;2b
|
||||||
|
|
||||||
|
*
|
||||||
|
* ROM routines
|
||||||
|
*
|
||||||
|
bell equ $ff3a
|
||||||
|
monitor equ $ff69
|
||||||
|
|
||||||
|
*
|
||||||
|
* Parameters.
|
||||||
|
*
|
||||||
|
* in_dst must be $2000 or $4000
|
||||||
|
*
|
||||||
|
in_src equ $2fc ;2b
|
||||||
|
in_dst equ $2fe ;2b
|
||||||
|
|
||||||
|
* Main entry point.
|
||||||
|
entry
|
||||||
|
clc ;go native
|
||||||
|
xce
|
||||||
|
rep #$30 ;16-bit acc/index
|
||||||
|
mx %00 ; tell Merlin
|
||||||
|
|
||||||
|
ldx in_src
|
||||||
|
ldy in_dst
|
||||||
|
sty _dstmod+1
|
||||||
|
|
||||||
|
lda $0000,x
|
||||||
|
inx
|
||||||
|
and #$00ff
|
||||||
|
cmp #lz4fh_magic
|
||||||
|
bne fail
|
||||||
|
|
||||||
|
mainloop
|
||||||
|
lda $0000,x
|
||||||
|
inx
|
||||||
|
sta savmix
|
||||||
|
and #$00f0
|
||||||
|
beq noliteral
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
cmp #$000f
|
||||||
|
bne shortlit
|
||||||
|
|
||||||
|
lda $0000,x ;length >= 15, get next
|
||||||
|
inx
|
||||||
|
and #$00ff
|
||||||
|
clc
|
||||||
|
adc #15
|
||||||
|
|
||||||
|
* At this point, Y holds the address of the next
|
||||||
|
* compressed data byte, X has the address of the
|
||||||
|
* next output position, and A has the length of
|
||||||
|
* the literal.
|
||||||
|
*
|
||||||
|
* The MVN instruction moves (A+1) bytes from X
|
||||||
|
* to Y, advancing X and Y.
|
||||||
|
shortlit
|
||||||
|
dec A ;MVN wants length-1
|
||||||
|
mvn $00,$00 ;7 cycles/byte
|
||||||
|
|
||||||
|
* Now handle the match.
|
||||||
|
noliteral
|
||||||
|
lda savmix
|
||||||
|
and #$000f
|
||||||
|
cmp #$000f
|
||||||
|
blt :shortmatch ;BCC
|
||||||
|
|
||||||
|
lda $0000,x ;add length extension
|
||||||
|
inx
|
||||||
|
and #$00ff
|
||||||
|
cmp #237 ;"normal" values are 0-236
|
||||||
|
bge specialmatch
|
||||||
|
adc #15 ;carry clear; won't exceed 255
|
||||||
|
:shortmatch
|
||||||
|
adc #3 ;min match, -1 for MVN
|
||||||
|
sta savlen ;spill A while we get offset
|
||||||
|
|
||||||
|
lda $0000,x ;load source buffer offset
|
||||||
|
inx
|
||||||
|
inx
|
||||||
|
phx ;save srcptr for later
|
||||||
|
_dstmod ora #$ff00 ;OR in hi-res page
|
||||||
|
tax
|
||||||
|
lda savlen
|
||||||
|
mvn $00,$00
|
||||||
|
plx ;restore srcptr
|
||||||
|
bra mainloop
|
||||||
|
|
||||||
|
* handle "special" match length values (in A)
|
||||||
|
specialmatch
|
||||||
|
cmp #tok_empty
|
||||||
|
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