mirror of https://github.com/fadden/fhpack.git
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
|
@ -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
|
||||
|
|
@ -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