compression: add some compression tests
This commit is contained in:
parent
6f6e36b231
commit
1ae6ddac20
|
@ -3,6 +3,8 @@ PNG2GR = ../../utils/gr-utils/png2gr
|
|||
PNG2HGR = ../../utils/hgr-utils/png2hgr
|
||||
LZSA = ~/research/lzsa/lzsa/lzsa
|
||||
B2D = ../../utils/bmp2dhr/b2d
|
||||
EXOMIZER = ~/research/6502_compression/exomizer.git/src/exomizer
|
||||
ZX02 = ~/research/6502_compression/zx02.git/build/zx02
|
||||
|
||||
DOS33 = ../../utils/dos33fs-utils/dos33
|
||||
TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
|
||||
|
@ -13,10 +15,13 @@ LINKERSCRIPTS = ../../linker_scripts/
|
|||
|
||||
all: compression_test.dsk
|
||||
|
||||
compression_test.dsk: HELLO LZSA_TEST
|
||||
compression_test.dsk: HELLO LZSA_TEST EXOMIZER_TEST ZX02_TEST
|
||||
cp $(EMPTYDISK) compression_test.dsk
|
||||
$(DOS33) -y compression_test.dsk SAVE A HELLO
|
||||
$(DOS33) -y compression_test.dsk BSAVE -a 0x6000 LZSA_TEST
|
||||
$(DOS33) -y compression_test.dsk BSAVE -a 0x6000 EXOMIZER_TEST
|
||||
$(DOS33) -y compression_test.dsk BSAVE -a 0x6000 ZX02_TEST
|
||||
|
||||
|
||||
|
||||
####
|
||||
|
@ -29,22 +34,48 @@ HELLO: hello.bas
|
|||
LZSA_TEST: lzsa_test.o
|
||||
ld65 -o LZSA_TEST lzsa_test.o -C $(LINKERSCRIPTS)/apple2_6000.inc
|
||||
|
||||
lzsa_test.o: lzsa_test.s graphics_level5.inc
|
||||
lzsa_test.o: lzsa_test.s decompress_fast_v2.s level5.lzsa
|
||||
ca65 -o lzsa_test.o lzsa_test.s -l lzsa_test.lst
|
||||
|
||||
###
|
||||
|
||||
graphics_level5.inc: level5.lzsa
|
||||
echo "level5_lzsa: .incbin \"level5.lzsa\"" > graphics_level5.inc
|
||||
|
||||
###
|
||||
|
||||
level5.lzsa: level5.hgr
|
||||
$(LZSA) -r -f2 level5.hgr level5.lzsa
|
||||
|
||||
###
|
||||
|
||||
EXOMIZER_TEST: exomizer_test.o
|
||||
ld65 -o EXOMIZER_TEST exomizer_test.o -C $(LINKERSCRIPTS)/apple2_6000.inc
|
||||
|
||||
exomizer_test.o: exomizer_test.s exodecrunch.s level5.exo
|
||||
ca65 -o exomizer_test.o exomizer_test.s -l exomizer_test.lst
|
||||
|
||||
###
|
||||
|
||||
level5.exo: level5.hgr
|
||||
# $(EXOMIZER) mem level5.hgr -o level5.exo
|
||||
$(EXOMIZER) mem -l "$$6000" "level5.hgr,$$2000" -o level5.exo
|
||||
|
||||
|
||||
###
|
||||
|
||||
ZX02_TEST: zx02_test.o
|
||||
ld65 -o ZX02_TEST zx02_test.o -C $(LINKERSCRIPTS)/apple2_6000.inc
|
||||
|
||||
zx02_test.o: zx02_test.s zx02_optim.s level5.zx02
|
||||
ca65 -o zx02_test.o zx02_test.s -l zx02_test.lst
|
||||
|
||||
###
|
||||
|
||||
level5.zx02: level5.hgr
|
||||
$(ZX02) level5.hgr level5.zx02
|
||||
|
||||
|
||||
###
|
||||
|
||||
level5.hgr: level5.png
|
||||
$(PNG2HGR) level5.png > level5.hgr
|
||||
|
||||
|
||||
clean:
|
||||
rm -f HELLO LZSA_TEST *~ *.o *.lst level5.lzsa
|
||||
rm -f HELLO LZSA_TEST EXOMIZER_TEST *~ *.o *.lst level5.lzsa
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
LEVEL5.PNG (hires background image from Lemmings, 8k)
|
||||
|
||||
Compressed Decompression
|
||||
File size Routine Size Time (cycles) FPS
|
||||
===========================================================
|
||||
lzsa 4012 259 bytes 7cc5e = 511,070 ~2.0
|
||||
exomizer 3851(?) ??? ?????
|
||||
zx02_opt 3869 138 bytes 7076f = 460,655 ~2.2
|
|
@ -0,0 +1,575 @@
|
|||
;
|
||||
; Copyright (c) 2002 - 2020 Magnus Lind.
|
||||
;
|
||||
; This software is provided 'as-is', without any express or implied warranty.
|
||||
; In no event will the authors be held liable for any damages arising from
|
||||
; the use of this software.
|
||||
;
|
||||
; Permission is granted to anyone to use this software for any purpose,
|
||||
; including commercial applications, and to alter it and redistribute it
|
||||
; freely, subject to the following restrictions:
|
||||
;
|
||||
; 1. The origin of this software must not be misrepresented; you must not
|
||||
; claim that you wrote the original software. If you use this software in a
|
||||
; product, an acknowledgment in the product documentation would be
|
||||
; appreciated but is not required.
|
||||
;
|
||||
; 2. Altered source versions must be plainly marked as such, and must not
|
||||
; be misrepresented as being the original software.
|
||||
;
|
||||
; 3. This notice may not be removed or altered from any distribution.
|
||||
;
|
||||
; 4. The names of this software and/or it's copyright holders may not be
|
||||
; used to endorse or promote products derived from this software without
|
||||
; specific prior written permission.
|
||||
;
|
||||
; -------------------------------------------------------------------
|
||||
; Known quirks:
|
||||
; Can't handle a sequence reference that ends at $ffff. It is left in
|
||||
; since it is a corner case and fixing it impacts negatively on
|
||||
; performance or backwards compatibility.
|
||||
; A simple way to work around this is to not decrunch to address $ffff.
|
||||
; -------------------------------------------------------------------
|
||||
; Controls if the shared get_bits routines should be inlined or not.
|
||||
;INLINE_GET_BITS=1
|
||||
.IFNDEF INLINE_GET_BITS
|
||||
INLINE_GET_BITS = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; if literal sequences is not used (the data was crunched with the -c
|
||||
; flag) then the following line can be uncommented for shorter and.
|
||||
; slightly faster code.
|
||||
;LITERAL_SEQUENCES_NOT_USED = 1
|
||||
.IFNDEF LITERAL_SEQUENCES_NOT_USED
|
||||
LITERAL_SEQUENCES_NOT_USED = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; if the sequence length is limited to 256 (the data was crunched with
|
||||
; the -M256 flag) then the following line can be uncommented for
|
||||
; shorter and slightly faster code.
|
||||
;MAX_SEQUENCE_LENGTH_256 = 1
|
||||
.IFNDEF MAX_SEQUENCE_LENGTH_256
|
||||
MAX_SEQUENCE_LENGTH_256 = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; if the sequence length 3 has its own offset table (the data was
|
||||
; crunched with the -P+16 flag) then the following
|
||||
; line must be uncommented.
|
||||
;EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 1
|
||||
.IFNDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
|
||||
EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; if sequence offsets are not reused (the data was crunched with the
|
||||
; -P-32 flag) then the following line must be uncommented. Uncommenting the
|
||||
; line will also result in shorter and slightly faster code.
|
||||
;DONT_REUSE_OFFSET = 1
|
||||
.IFNDEF DONT_REUSE_OFFSET
|
||||
DONT_REUSE_OFFSET = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; if decrunching forwards then the following line must be uncommented.
|
||||
;DECRUNCH_FORWARDS = 1
|
||||
.IFNDEF DECRUNCH_FORWARDS
|
||||
DECRUNCH_FORWARDS = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; if split encoding is used (the data is crunched with the -E flag)
|
||||
; then the following line must be uncommented.
|
||||
;ENABLE_SPLIT_ENCODING = 1
|
||||
.IFNDEF ENABLE_SPLIT_ENCODING
|
||||
ENABLE_SPLIT_ENCODING = 0
|
||||
.ENDIF
|
||||
|
||||
; -------------------------------------------------------------------
|
||||
; The decruncher jsr:s to the get_crunched_byte address when it wants to
|
||||
; read a crunched byte into A. This subroutine has to preserve X and Y
|
||||
; register and must not modify the state of the carry nor the overflow flag.
|
||||
; -------------------------------------------------------------------
|
||||
;.import get_crunched_byte
|
||||
; -------------------------------------------------------------------
|
||||
; This function is the heart of the decruncher. (for non split crunched files)
|
||||
; It initializes the decruncher zeropage locations and precalculates the
|
||||
; decrunch tables and decrunches the data
|
||||
; This function will not change the interrupt status bit and it will not
|
||||
; modify the memory configuration.
|
||||
; -------------------------------------------------------------------
|
||||
.export decrunch
|
||||
.IF ENABLE_SPLIT_ENCODING <> 0
|
||||
; -------------------------------------------------------------------
|
||||
; To decrunch files crunched with the split feature (-E) you can't use the
|
||||
; decrunch function. Instead you call the split_decrunch function. But you
|
||||
; can only do this if the decrunch table contains the encoding used by the
|
||||
; file you are decrunching. To generate the correct content for the decrunch
|
||||
; table call set the get_crunched_byte function to point to the encoding data
|
||||
; and then call the split_gentable function.
|
||||
; -------------------------------------------------------------------
|
||||
.export split_gentable
|
||||
.export split_decrunch
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; zero page addresses used
|
||||
; -------------------------------------------------------------------
|
||||
zp_len_lo = $9e
|
||||
zp_len_hi = $9f
|
||||
|
||||
zp_src_lo = $ae
|
||||
zp_src_hi = zp_src_lo + 1
|
||||
|
||||
zp_bits_hi = $a7
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
zp_ro_state = $a8
|
||||
.ENDIF
|
||||
|
||||
zp_bitbuf = $fd
|
||||
zp_dest_lo = zp_bitbuf + 1 ; dest addr lo
|
||||
zp_dest_hi = zp_bitbuf + 2 ; dest addr hi
|
||||
|
||||
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
|
||||
encoded_entries = 68
|
||||
.ELSE
|
||||
encoded_entries = 52
|
||||
.ENDIF
|
||||
|
||||
tabl_bi = decrunch_table
|
||||
tabl_lo = decrunch_table + encoded_entries
|
||||
tabl_hi = decrunch_table + encoded_entries * 2
|
||||
|
||||
;; refill bits is always inlined
|
||||
.MACRO mac_refill_bits
|
||||
pha
|
||||
jsr get_crunched_byte
|
||||
rol
|
||||
sta zp_bitbuf
|
||||
pla
|
||||
.ENDMACRO
|
||||
|
||||
.MACRO mac_get_bits
|
||||
.IF INLINE_GET_BITS <> 0
|
||||
.SCOPE
|
||||
adc #$80 ; needs c=0, affects v
|
||||
asl
|
||||
bpl gb_skip
|
||||
gb_next:
|
||||
asl zp_bitbuf
|
||||
bne gb_ok
|
||||
mac_refill_bits
|
||||
gb_ok:
|
||||
rol
|
||||
bmi gb_next
|
||||
gb_skip:
|
||||
bvc skip
|
||||
gb_get_hi:
|
||||
sec
|
||||
sta zp_bits_hi
|
||||
jsr get_crunched_byte
|
||||
skip:
|
||||
.ENDSCOPE
|
||||
.ELSE
|
||||
jsr get_bits
|
||||
.ENDIF
|
||||
.ENDMACRO
|
||||
|
||||
.MACRO mac_init_zp
|
||||
.SCOPE
|
||||
; -------------------------------------------------------------------
|
||||
; init zeropage and x reg. (8 bytes)
|
||||
;
|
||||
init_zp:
|
||||
jsr get_crunched_byte
|
||||
sta zp_bitbuf - 1,x
|
||||
dex
|
||||
bne init_zp
|
||||
.ENDSCOPE
|
||||
.ENDMACRO
|
||||
|
||||
.IF INLINE_GET_BITS = 0
|
||||
get_bits:
|
||||
adc #$80 ; needs c=0, affects v
|
||||
asl
|
||||
bpl gb_skip
|
||||
gb_next:
|
||||
asl zp_bitbuf
|
||||
bne gb_ok
|
||||
mac_refill_bits
|
||||
gb_ok:
|
||||
rol
|
||||
bmi gb_next
|
||||
gb_skip:
|
||||
bvs gb_get_hi
|
||||
rts
|
||||
gb_get_hi:
|
||||
sec
|
||||
sta zp_bits_hi
|
||||
jmp get_crunched_byte
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; no code below this comment has to be modified in order to generate
|
||||
; a working decruncher of this source file.
|
||||
; However, you may want to relocate the tables last in the file to a
|
||||
; more suitable address.
|
||||
; -------------------------------------------------------------------
|
||||
|
||||
; -------------------------------------------------------------------
|
||||
; jsr this label to decrunch, it will in turn init the tables and
|
||||
; call the decruncher
|
||||
; no constraints on register content, however the
|
||||
; decimal flag has to be cleared (it almost always is, otherwise do a cld)
|
||||
decrunch:
|
||||
.IF ENABLE_SPLIT_ENCODING <> 0
|
||||
ldx #3
|
||||
jsr internal_gentable
|
||||
jmp normal_decrunch
|
||||
split_gentable:
|
||||
ldx #1
|
||||
internal_gentable:
|
||||
jsr split_init_zp
|
||||
.ELSE
|
||||
ldx #3
|
||||
mac_init_zp
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; calculate tables (64 bytes) + get_bits macro
|
||||
; x must be #0 when entering
|
||||
;
|
||||
ldy #0
|
||||
clc
|
||||
table_gen:
|
||||
tax
|
||||
tya
|
||||
and #$0f
|
||||
sta tabl_lo,y
|
||||
beq shortcut ; start a new sequence
|
||||
; -------------------------------------------------------------------
|
||||
txa
|
||||
adc tabl_lo - 1,y
|
||||
sta tabl_lo,y
|
||||
lda zp_len_hi
|
||||
adc tabl_hi - 1,y
|
||||
shortcut:
|
||||
sta tabl_hi,y
|
||||
; -------------------------------------------------------------------
|
||||
lda #$01
|
||||
sta <zp_len_hi
|
||||
lda #$78 ; %01111000
|
||||
mac_get_bits
|
||||
; -------------------------------------------------------------------
|
||||
lsr
|
||||
tax
|
||||
beq rolled
|
||||
php
|
||||
rolle:
|
||||
asl zp_len_hi
|
||||
sec
|
||||
ror
|
||||
dex
|
||||
bne rolle
|
||||
plp
|
||||
rolled:
|
||||
ror
|
||||
sta tabl_bi,y
|
||||
bmi no_fixup_lohi
|
||||
lda zp_len_hi
|
||||
stx zp_len_hi
|
||||
.BYTE $24
|
||||
no_fixup_lohi:
|
||||
txa
|
||||
; -------------------------------------------------------------------
|
||||
iny
|
||||
cpy #encoded_entries
|
||||
bne table_gen
|
||||
; -------------------------------------------------------------------
|
||||
.IF ENABLE_SPLIT_ENCODING <> 0
|
||||
rts
|
||||
split_decrunch:
|
||||
ldx #3
|
||||
jsr split_init_zp
|
||||
; X reg must be 0 here
|
||||
sec
|
||||
normal_decrunch:
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; prepare for main decruncher
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
ror zp_ro_state
|
||||
sec
|
||||
.ENDIF
|
||||
ldy zp_dest_lo
|
||||
stx zp_dest_lo
|
||||
stx zp_bits_hi
|
||||
; -------------------------------------------------------------------
|
||||
; copy one literal byte to destination (11 bytes)
|
||||
;
|
||||
literal_start1:
|
||||
.IF DECRUNCH_FORWARDS = 0
|
||||
tya
|
||||
bne no_hi_decr
|
||||
dec zp_dest_hi
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
dec zp_src_hi
|
||||
.ENDIF
|
||||
no_hi_decr:
|
||||
dey
|
||||
.ENDIF
|
||||
jsr get_crunched_byte
|
||||
sta (zp_dest_lo),y
|
||||
.IF DECRUNCH_FORWARDS <> 0
|
||||
iny
|
||||
bne skip_hi_incr
|
||||
inc zp_dest_hi
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
inc zp_src_hi
|
||||
.ENDIF
|
||||
skip_hi_incr:
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; fetch sequence length index (15 bytes)
|
||||
; x must be #0 when entering and contains the length index + 1
|
||||
; when exiting or 0 for literal byte
|
||||
next_round:
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
ror zp_ro_state
|
||||
.ENDIF
|
||||
dex
|
||||
lda zp_bitbuf
|
||||
no_literal1:
|
||||
asl
|
||||
bne nofetch8
|
||||
jsr get_crunched_byte
|
||||
rol
|
||||
nofetch8:
|
||||
inx
|
||||
bcc no_literal1
|
||||
sta zp_bitbuf
|
||||
; -------------------------------------------------------------------
|
||||
; check for literal byte (2 bytes)
|
||||
;
|
||||
beq literal_start1
|
||||
; -------------------------------------------------------------------
|
||||
; check for decrunch done and literal sequences (4 bytes)
|
||||
;
|
||||
cpx #$11
|
||||
.IF INLINE_GET_BITS <> 0
|
||||
bcc skip_jmp
|
||||
jmp exit_or_lit_seq
|
||||
skip_jmp:
|
||||
.ELSE
|
||||
bcs exit_or_lit_seq
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; calulate length of sequence (zp_len) (18(11) bytes) + get_bits macro
|
||||
;
|
||||
lda tabl_bi - 1,x
|
||||
mac_get_bits
|
||||
adc tabl_lo - 1,x ; we have now calculated zp_len_lo
|
||||
sta zp_len_lo
|
||||
.IF MAX_SEQUENCE_LENGTH_256 = 0
|
||||
lda zp_bits_hi
|
||||
adc tabl_hi - 1,x ; c = 0 after this.
|
||||
sta zp_len_hi
|
||||
; -------------------------------------------------------------------
|
||||
; here we decide what offset table to use (27(26) bytes) + get_bits_nc macro
|
||||
; z-flag reflects zp_len_hi here
|
||||
;
|
||||
ldx zp_len_lo
|
||||
.ELSE
|
||||
tax
|
||||
.ENDIF
|
||||
.IF MAX_SEQUENCE_LENGTH_256 = 0
|
||||
lda #0
|
||||
.ENDIF
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
; -------------------------------------------------------------------
|
||||
; here we decide to reuse latest offset or not (13(15) bytes)
|
||||
;
|
||||
bit <zp_ro_state
|
||||
bmi test_reuse
|
||||
no_reuse:
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; here we decide what offset table to use (17(15) bytes)
|
||||
;
|
||||
.IF MAX_SEQUENCE_LENGTH_256 = 0
|
||||
sta <zp_bits_hi
|
||||
.ENDIF
|
||||
lda #$e1
|
||||
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
|
||||
cpx #$04
|
||||
.ELSE
|
||||
cpx #$03
|
||||
.ENDIF
|
||||
bcs gbnc2_next
|
||||
lda tabl_bit - 1,x
|
||||
gbnc2_next:
|
||||
asl zp_bitbuf
|
||||
bne gbnc2_ok
|
||||
tax
|
||||
jsr get_crunched_byte
|
||||
rol
|
||||
sta zp_bitbuf
|
||||
txa
|
||||
gbnc2_ok:
|
||||
rol
|
||||
bcs gbnc2_next
|
||||
tax
|
||||
; -------------------------------------------------------------------
|
||||
; calulate absolute offset (zp_src) (17 bytes) + get_bits macro
|
||||
;
|
||||
lda tabl_bi,x
|
||||
mac_get_bits
|
||||
.IF DECRUNCH_FORWARDS = 0
|
||||
adc tabl_lo,x
|
||||
sta zp_src_lo
|
||||
lda zp_bits_hi
|
||||
adc tabl_hi,x
|
||||
adc zp_dest_hi
|
||||
sta zp_src_hi
|
||||
.ELSE
|
||||
clc
|
||||
adc tabl_lo,x
|
||||
eor #$ff
|
||||
sta zp_src_lo
|
||||
lda zp_bits_hi
|
||||
adc tabl_hi,x
|
||||
eor #$ff
|
||||
adc zp_dest_hi
|
||||
sta zp_src_hi
|
||||
clc
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; prepare for copy loop (2 bytes)
|
||||
;
|
||||
ldx zp_len_lo
|
||||
; -------------------------------------------------------------------
|
||||
; main copy loop (30 bytes)
|
||||
;
|
||||
copy_next:
|
||||
.IF DECRUNCH_FORWARDS = 0
|
||||
tya
|
||||
bne copy_skip_hi
|
||||
dec zp_dest_hi
|
||||
dec zp_src_hi
|
||||
copy_skip_hi:
|
||||
dey
|
||||
.ENDIF
|
||||
.IF LITERAL_SEQUENCES_NOT_USED = 0
|
||||
bcs get_literal_byte
|
||||
.ENDIF
|
||||
lda (zp_src_lo),y
|
||||
literal_byte_gotten:
|
||||
sta (zp_dest_lo),y
|
||||
.IF DECRUNCH_FORWARDS <> 0
|
||||
iny
|
||||
bne copy_skip_hi
|
||||
inc zp_dest_hi
|
||||
inc zp_src_hi
|
||||
copy_skip_hi:
|
||||
.ENDIF
|
||||
dex
|
||||
bne copy_next
|
||||
.IF MAX_SEQUENCE_LENGTH_256 = 0
|
||||
lda zp_len_hi
|
||||
.IF INLINE_GET_BITS <> 0
|
||||
bne copy_next_hi
|
||||
.ENDIF
|
||||
.ENDIF
|
||||
stx zp_bits_hi
|
||||
.IF INLINE_GET_BITS = 0
|
||||
beq next_round
|
||||
.ELSE
|
||||
jmp next_round
|
||||
.ENDIF
|
||||
.IF MAX_SEQUENCE_LENGTH_256 = 0
|
||||
copy_next_hi:
|
||||
dec zp_len_hi
|
||||
jmp copy_next
|
||||
.ENDIF
|
||||
.IF DONT_REUSE_OFFSET = 0
|
||||
; -------------------------------------------------------------------
|
||||
; test for offset reuse (11 bytes)
|
||||
;
|
||||
test_reuse:
|
||||
bvs no_reuse
|
||||
.IF MAX_SEQUENCE_LENGTH_256 <> 0
|
||||
lda #$00 ; fetch one bit
|
||||
.ENDIF
|
||||
asl zp_bitbuf
|
||||
bne gbnc1_ok
|
||||
pha
|
||||
jsr get_crunched_byte
|
||||
rol
|
||||
sta zp_bitbuf
|
||||
pla
|
||||
gbnc1_ok:
|
||||
rol
|
||||
beq no_reuse ; bit == 0 => C=0, no reuse
|
||||
bne copy_next ; bit != 0 => C=0, reuse previous offset
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; exit or literal sequence handling (16(12) bytes)
|
||||
;
|
||||
exit_or_lit_seq:
|
||||
.IF LITERAL_SEQUENCES_NOT_USED = 0
|
||||
beq decr_exit
|
||||
jsr get_crunched_byte
|
||||
.IF MAX_SEQUENCE_LENGTH_256 = 0
|
||||
sta zp_len_hi
|
||||
.ENDIF
|
||||
jsr get_crunched_byte
|
||||
tax
|
||||
bcs copy_next
|
||||
decr_exit:
|
||||
.ENDIF
|
||||
rts
|
||||
.IF LITERAL_SEQUENCES_NOT_USED = 0
|
||||
get_literal_byte:
|
||||
jsr get_crunched_byte
|
||||
bcs literal_byte_gotten
|
||||
.ENDIF
|
||||
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
|
||||
; -------------------------------------------------------------------
|
||||
; the static stable used for bits+offset for lengths 1, 2 and 3 (3 bytes)
|
||||
; bits 2, 4, 4 and offsets 64, 48, 32 corresponding to
|
||||
; %10010000, %11100011, %11100010
|
||||
tabl_bit:
|
||||
.BYTE $90, $e3, $e2
|
||||
.ELSE
|
||||
; -------------------------------------------------------------------
|
||||
; the static stable used for bits+offset for lengths 1 and 2 (2 bytes)
|
||||
; bits 2, 4 and offsets 48, 32 corresponding to %10001100, %11100010
|
||||
tabl_bit:
|
||||
.BYTE $8c, $e2
|
||||
.ENDIF
|
||||
|
||||
.IF ENABLE_SPLIT_ENCODING <> 0
|
||||
split_init_zp:
|
||||
mac_init_zp
|
||||
rts
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
; end of decruncher
|
||||
; -------------------------------------------------------------------
|
||||
|
||||
; -------------------------------------------------------------------
|
||||
; this 156 (204) byte table area may be relocated. It may also be
|
||||
; clobbered by other data between decrunches.
|
||||
; -------------------------------------------------------------------
|
||||
decrunch_table:
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.ENDIF
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
.byte 0,0,0,0,0,0,0,0,0,0,0,0
|
||||
; -------------------------------------------------------------------
|
||||
; end of decruncher
|
||||
; -------------------------------------------------------------------
|
|
@ -0,0 +1,79 @@
|
|||
; -------------------------------------------------------------------
|
||||
; this file is intended to be assembled and linked with the cc65 toolchain.
|
||||
; It has not been tested with any other assemblers or linkers.
|
||||
; -------------------------------------------------------------------
|
||||
; -------------------------------------------------------------------
|
||||
; example usage of the standard decruncher
|
||||
; this program decrunches data to memory
|
||||
; -------------------------------------------------------------------
|
||||
; if decrunching forwards then the following line must be uncommented.
|
||||
;DECRUNCH_FORWARDS = 1
|
||||
.IFNDEF DECRUNCH_FORWARDS
|
||||
DECRUNCH_FORWARDS = 0
|
||||
.ENDIF
|
||||
; -------------------------------------------------------------------
|
||||
;.import decrunch
|
||||
;.export get_crunched_byte
|
||||
;.import end_of_data
|
||||
|
||||
; .byte $01,$08,$0b,$08,<2003,>2003,$9e,'2','0','6','1',0,0,0
|
||||
; -------------------------------------------------------------------
|
||||
; we begin here
|
||||
; -------------------------------------------------------------------
|
||||
|
||||
lda #$20
|
||||
sta zp_dest_hi
|
||||
lda #$00
|
||||
sta zp_dest_lo
|
||||
|
||||
|
||||
.IF DECRUNCH_FORWARDS = 0
|
||||
lda $04
|
||||
sta _byte_lo
|
||||
lda $05
|
||||
sta _byte_hi
|
||||
.ELSE
|
||||
lda #<end_of_data
|
||||
sta _byte_lo
|
||||
lda #>end_of_data
|
||||
sta _byte_hi
|
||||
|
||||
; lda $02
|
||||
; sta _byte_lo
|
||||
; lda $03
|
||||
; sta _byte_hi
|
||||
.ENDIF
|
||||
jsr decrunch
|
||||
|
||||
end:
|
||||
jmp end
|
||||
|
||||
; -------------------------------------------------------------------
|
||||
get_crunched_byte:
|
||||
.IF DECRUNCH_FORWARDS = 0
|
||||
lda _byte_lo
|
||||
bne _byte_skip_hi
|
||||
dec _byte_hi
|
||||
_byte_skip_hi:
|
||||
dec _byte_lo
|
||||
.ENDIF
|
||||
_byte_lo = * + 1
|
||||
_byte_hi = * + 2
|
||||
lda $ffff ; needs to be set correctly before
|
||||
|
||||
.IF DECRUNCH_FORWARDS <> 0
|
||||
inc _byte_lo
|
||||
bne _byte_skip_hi
|
||||
inc _byte_hi
|
||||
_byte_skip_hi:
|
||||
.ENDIF
|
||||
rts ; decrunch_file is called.
|
||||
; end_of_data needs to point to the address just after the address
|
||||
; of the last byte of crunched data.
|
||||
; -------------------------------------------------------------------
|
||||
|
||||
.include "exodecrunch.s"
|
||||
|
||||
.incbin "level5.exo"
|
||||
|
||||
end_of_data:
|
|
@ -21,6 +21,9 @@ end:
|
|||
jmp end
|
||||
|
||||
|
||||
.include "graphics_level5.inc"
|
||||
|
||||
|
||||
.include "decompress_fast_v2.s"
|
||||
|
||||
level5_lzsa:
|
||||
.incbin "level5.lzsa"
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
; De-compressor for ZX02 files
|
||||
; ----------------------------
|
||||
;
|
||||
; Decompress ZX02 data (6502 optimized format), optimized for speed and size
|
||||
; 138 bytes code, 58.0 cycles/byte in test file.
|
||||
;
|
||||
; Compress with:
|
||||
; zx02 input.bin output.zx0
|
||||
;
|
||||
; (c) 2022 DMSC
|
||||
; Code under MIT license, see LICENSE file.
|
||||
|
||||
|
||||
ZP=$80
|
||||
|
||||
offset = ZP+0
|
||||
ZX0_src = ZP+2
|
||||
ZX0_dst = ZP+4
|
||||
bitr = ZP+6
|
||||
pntr = ZP+7
|
||||
|
||||
; Initial values for offset, source, destination and bitr
|
||||
zx0_ini_block:
|
||||
.byte $00, $00, <comp_data, >comp_data, <out_addr, >out_addr, $80
|
||||
|
||||
;--------------------------------------------------
|
||||
; Decompress ZX0 data (6502 optimized format)
|
||||
|
||||
full_decomp:
|
||||
; Get initialization block
|
||||
ldy #7
|
||||
|
||||
copy_init: lda zx0_ini_block-1, y
|
||||
sta offset-1, y
|
||||
dey
|
||||
bne copy_init
|
||||
|
||||
; Decode literal: Ccopy next N bytes from compressed file
|
||||
; Elias(length) byte[1] byte[2] ... byte[N]
|
||||
decode_literal:
|
||||
jsr get_elias
|
||||
|
||||
cop0: lda (ZX0_src), y
|
||||
inc ZX0_src
|
||||
bne plus1
|
||||
inc ZX0_src+1
|
||||
plus1: sta (ZX0_dst),y
|
||||
inc ZX0_dst
|
||||
bne plus2
|
||||
inc ZX0_dst+1
|
||||
plus2: dex
|
||||
bne cop0
|
||||
|
||||
asl bitr
|
||||
bcs dzx0s_new_offset
|
||||
|
||||
; Copy from last offset (repeat N bytes from last offset)
|
||||
; Elias(length)
|
||||
jsr get_elias
|
||||
dzx0s_copy:
|
||||
lda ZX0_dst
|
||||
sbc offset ; C=0 from get_elias
|
||||
sta pntr
|
||||
lda ZX0_dst+1
|
||||
sbc offset+1
|
||||
sta pntr+1
|
||||
|
||||
cop1:
|
||||
lda (pntr), y
|
||||
inc pntr
|
||||
bne plus3
|
||||
inc pntr+1
|
||||
plus3: sta (ZX0_dst),y
|
||||
inc ZX0_dst
|
||||
bne plus4
|
||||
inc ZX0_dst+1
|
||||
plus4: dex
|
||||
bne cop1
|
||||
|
||||
asl bitr
|
||||
bcc decode_literal
|
||||
|
||||
; Copy from new offset (repeat N bytes from new offset)
|
||||
; Elias(MSB(offset)) LSB(offset) Elias(length-1)
|
||||
dzx0s_new_offset:
|
||||
; Read elias code for high part of offset
|
||||
jsr get_elias
|
||||
beq exit ; Read a 0, signals the end
|
||||
; Decrease and divide by 2
|
||||
dex
|
||||
txa
|
||||
lsr ; @
|
||||
sta offset+1
|
||||
|
||||
; Get low part of offset, a literal 7 bits
|
||||
lda (ZX0_src), y
|
||||
inc ZX0_src
|
||||
bne plus5
|
||||
inc ZX0_src+1
|
||||
plus5:
|
||||
; Divide by 2
|
||||
ror ; @
|
||||
sta offset
|
||||
|
||||
; And get the copy length.
|
||||
; Start elias reading with the bit already in carry:
|
||||
ldx #1
|
||||
jsr elias_skip1
|
||||
|
||||
inx
|
||||
bcc dzx0s_copy
|
||||
|
||||
; Read an elias-gamma interlaced code.
|
||||
; ------------------------------------
|
||||
get_elias:
|
||||
; Initialize return value to #1
|
||||
ldx #1
|
||||
bne elias_start
|
||||
|
||||
elias_get: ; Read next data bit to result
|
||||
asl bitr
|
||||
rol ; @
|
||||
tax
|
||||
|
||||
elias_start:
|
||||
; Get one bit
|
||||
asl bitr
|
||||
bne elias_skip1
|
||||
|
||||
; Read new bit from stream
|
||||
lda (ZX0_src), y
|
||||
inc ZX0_src
|
||||
bne plus6
|
||||
inc ZX0_src+1
|
||||
plus6: ;sec ; not needed, C=1 guaranteed from last bit
|
||||
rol ;@
|
||||
sta bitr
|
||||
|
||||
elias_skip1:
|
||||
txa
|
||||
bcs elias_get
|
||||
; Got ending bit, stop reading
|
||||
exit:
|
||||
rts
|
|
@ -0,0 +1,32 @@
|
|||
.include "zp.inc"
|
||||
.include "hardware.inc"
|
||||
|
||||
lzsa_test:
|
||||
|
||||
bit SET_GR
|
||||
bit PAGE0
|
||||
bit HIRES
|
||||
bit FULLGR
|
||||
|
||||
; lda #<level5_lzsa
|
||||
; sta getsrc_smc+1 ; LZSA_SRC_LO
|
||||
; lda #>level5_lzsa
|
||||
; sta getsrc_smc+2 ; LZSA_SRC_HI
|
||||
;
|
||||
; lda #$20
|
||||
|
||||
jsr full_decomp
|
||||
|
||||
; jsr decompress_lzsa2_fast
|
||||
|
||||
end:
|
||||
jmp end
|
||||
|
||||
|
||||
out_addr = $2000
|
||||
|
||||
.include "zx02_optim.s"
|
||||
|
||||
comp_data:
|
||||
level5_zx02:
|
||||
.incbin "level5.zx02"
|
Loading…
Reference in New Issue