diff --git a/lzsa_test/Makefile b/lzsa_test/Makefile new file mode 100644 index 00000000..2f48a2eb --- /dev/null +++ b/lzsa_test/Makefile @@ -0,0 +1,33 @@ +include ../Makefile.inc + +DOS33 = ../dos33fs-utils/dos33 +PNG_TO_40x96 = ../gr-utils/png_to_40x96 +PNG_TO_40x48D = ../gr-utils/png_to_40x48d +PNG2RLE = ../gr-utils/png2rle +B2D = ../bmp2dhr/b2d + +all: gr_lzsa.dsk + +gr_lzsa.dsk: HELLO GR_LZSA + cp empty.dsk mist.dsk + $(DOS33) -y mist.dsk SAVE A HELLO + $(DOS33) -y mist.dsk BSAVE -a 0x1000 GR_LZSA + +### + +GR_LZSA: gr_lzsa.o + ld65 -o GR_LZSA gr_lzsa.o -C ../linker_scripts/apple2_1000.inc + +gr_lzsa.o: gr_lzsa.s decompress_small_v2.s + ca65 -o gr_lzsa.o gr_lzsa.s -l gr_lzsa.lst + + +### + +HELLO: hello.bas + ../asoft_basic-utils/tokenize_asoft < hello.bas > HELLO + +#### + +clean: + rm -f *~ *.o *.lst HELLO GR_LZSA diff --git a/lzsa_test/decompress_small_v2.s b/lzsa_test/decompress_small_v2.s new file mode 100644 index 00000000..250ee743 --- /dev/null +++ b/lzsa_test/decompress_small_v2.s @@ -0,0 +1,338 @@ +; ----------------------------------------------------------------------------- +; Decompress raw LZSA2 block. +; Create one with lzsa -r -f2 +; +; in: +; * LZSA_SRC_LO and LZSA_SRC_HI contain the compressed raw block address +; * LZSA_DST_LO and LZSA_DST_HI contain the destination buffer address +; +; out: +; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1 +; +; ----------------------------------------------------------------------------- +; Backward decompression is also supported, use lzsa -r -b -f2 +; To use it, also define BACKWARD_DECOMPRESS=1 before including this code! +; +; in: +; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data +; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer +; +; out: +; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1 +; +; ----------------------------------------------------------------------------- +; +; Copyright (C) 2019 Emmanuel Marty +; +; 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 source distribution. +; ----------------------------------------------------------------------------- + +;NIBCOUNT = $FC ; zero-page location for temp offset + +decompress_lzsa2: + ldy #$00 + sty NIBCOUNT + +decode_token: + jsr getsrc ; read token byte: XYZ|LL|MMM + pha ; preserve token on stack + + and #$18 ; isolate literals count (LL) + beq no_literals ; skip if no literals to copy + lsr ; shift literals count into place + lsr + lsr + cmp #$03 ; LITERALS_RUN_LEN_V2? + bcc prepare_copy_literals ; if less, count is directly embedded in token + + jsr getnibble ; get extra literals length nibble + ; add nibble to len from token + adc #$02 ; (LITERALS_RUN_LEN_V2) minus carry + cmp #$12 ; LITERALS_RUN_LEN_V2 + 15 ? + bcc prepare_copy_literals ; if less, literals count is complete + + jsr getsrc ; get extra byte of variable literals count + ; the carry is always set by the CMP above + ; GETSRC doesn't change it + sbc #$EE ; overflow? + +prepare_copy_literals: + tax + bcc prepare_copy_literals_high ; if not, literals count is complete + + ; handle 16 bits literals count + ; literals count = directly these 16 bits + jsr getlargesrc ; grab low 8 bits in X, high 8 bits in A + tay ; put high 8 bits in Y + +prepare_copy_literals_high: + txa + beq copy_literals + iny + +copy_literals: + jsr getput ; copy one byte of literals + dex + bne copy_literals + dey + bne copy_literals + +no_literals: + pla ; retrieve token from stack + pha ; preserve token again + asl + bcs repmatch_or_large_offset ; 1YZ: rep-match or 13/16 bit offset + + asl ; 0YZ: 5 or 9 bit offset + bcs offset_9_bit + + ; 00Z: 5 bit offset + + ldx #$FF ; set offset bits 15-8 to 1 + + jsr getcombinedbits ; rotate Z bit into bit 0, read nibble for bits 4-1 + ora #$E0 ; set bits 7-5 to 1 + bne got_offset_lo ; go store low byte of match offset and prepare match + +offset_9_bit: ; 01Z: 9 bit offset + ;;asl ; shift Z (offset bit 8) in place + rol + rol + and #$01 + eor #$FF ; set offset bits 15-9 to 1 + bne got_offset_hi ; go store high byte, read low byte of match offset and prepare match + ; (*same as JMP GOT_OFFSET_HI but shorter) + +repmatch_or_large_offset: + asl ; 13 bit offset? + bcs repmatch_or_16_bit ; handle rep-match or 16-bit offset if not + + ; 10Z: 13 bit offset + + jsr getcombinedbits ; rotate Z bit into bit 8, read nibble for bits 12-9 + adc #$DE ; set bits 15-13 to 1 and substract 2 (to substract 512) + bne got_offset_hi ; go store high byte, read low byte of match offset and prepare match + ; (*same as JMP GOT_OFFSET_HI but shorter) + +repmatch_or_16_bit: ; rep-match or 16 bit offset + ;;asl ; XYZ=111? + bmi rep_match ; reuse previous offset if so (rep-match) + + ; 110: handle 16 bit offset + jsr getsrc ; grab high 8 bits +got_offset_hi: + tax + jsr getsrc ; grab low 8 bits +got_offset_lo: + sta offslo ; store low byte of match offset + stx offshi ; store high byte of match offset + +rep_match: + +.ifdef BACKWARD_DECOMPRESS + + ; Backward decompression - substract match offset + + sec ; add dest + match offset + lda putdst+1 ; low 8 bits +offslo = *+1 + sbc #$AA + sta copy_match_loop+1 ; store back reference address + lda putdst+2 +offshi = *+1 + sbc #$AA ; high 8 bits + sta copy_match_loop+2 ; store high 8 bits of address + sec + +.else + + ; Forward decompression - add match offset + + clc ; add dest + match offset + lda putdst+1 ; low 8 bits +offslo = *+1 + adc #$AA + sta copy_match_loop+1 ; store back reference address +offshi = *+1 + lda #$AA ; high 8 bits + adc putdst+2 + sta copy_match_loop+2 ; store high 8 bits of address +.endif + + pla ; retrieve token from stack again + and #$07 ; isolate match len (MMM) + adc #$01 ; add MIN_MATCH_SIZE_V2 and carry + cmp #$09 ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2? + bcc prepare_copy_match ; if less, length is directly embedded in token + + jsr getnibble ; get extra match length nibble + ; add nibble to len from token + adc #$08 ; (MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2) minus carry + cmp #$18 ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15? + bcc prepare_copy_match ; if less, match length is complete + + jsr getsrc ; get extra byte of variable match length + ; the carry is always set by the CMP above + ; GETSRC doesn't change it + sbc #$E8 ; overflow? + +prepare_copy_match: + tax + bcc prepare_copy_match_y ; if not, the match length is complete + beq decompression_done ; if EOD code, bail + + ; Handle 16 bits match length + jsr getlargesrc ; grab low 8 bits in X, high 8 bits in A + tay ; put high 8 bits in Y + +prepare_copy_match_y: + txa + beq copy_match_loop + iny + +copy_match_loop: + lda $AAAA ; get one byte of backreference + jsr putdst ; copy to destination + +.ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- put backreference bytes backward + + lda copy_match_loop+1 + bne getmatch_done + dec copy_match_loop+2 +getmatch_done: + dec copy_match_loop+1 + +.else + + ; Forward decompression -- put backreference bytes forward + + inc copy_match_loop+1 + bne getmatch_done + inc copy_match_loop+2 + +getmatch_done: + +.endif + + dex + bne copy_match_loop + dey + bne copy_match_loop + jmp decode_token + +getcombinedbits: + eor #$80 + asl + php + + jsr getnibble ; get nibble into bits 0-3 (for offset bits 1-4) + plp ; merge Z bit as the carry bit (for offset bit 0) +combinedbitz: + rol ; nibble -> bits 1-4; carry(!Z bit) -> bit 0 ; carry cleared +decompression_done: + rts + +getnibble: +nibbles = *+1 + lda #$AA + lsr NIBCOUNT + bcs has_nibbles + + inc NIBCOUNT + jsr getsrc ; get 2 nibbles + sta nibbles + lsr + lsr + lsr + lsr + sec + +has_nibbles: + and #$0F ; isolate low 4 bits of nibble + rts + +.ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- get and put bytes backward + +getput: + jsr getsrc +putdst: +LZSA_DST_LO = *+1 +LZSA_DST_HI = *+2 + sta $AAAA + lda putdst+1 + bne putdst_done + dec putdst+2 +putdst_done: + dec putdst+1 + rts + +getlargesrc: + jsr getsrc ; grab low 8 bits + tax ; move to X + ; fall through grab high 8 bits + +getsrc: +LZSA_SRC_LO = *+1 +LZSA_SRC_HI = *+2 + lda $AAAA + pha + lda getsrc+1 + bne getsrc_done + dec getsrc+2 +getsrc_done: + dec getsrc+1 + pla + rts + +.else + + ; Forward decompression -- get and put bytes forward + +getput: + jsr getsrc + +putdst: +LZSA_DST_LO = *+1 +LZSA_DST_HI = *+2 + sta $AAAA + inc putdst+1 + bne putdst_done + inc putdst+2 +putdst_done: + rts + +getlargesrc: + jsr getsrc ; grab low 8 bits + tax ; move to X + ; fall through grab high 8 bits + +getsrc: +LZSA_SRC_LO = *+1 +LZSA_SRC_HI = *+2 + lda $AAAA + inc getsrc+1 + bne getsrc_done + inc getsrc+2 +getsrc_done: + rts + +.endif + diff --git a/lzsa_test/empty.dsk b/lzsa_test/empty.dsk new file mode 100644 index 00000000..b34eb519 Binary files /dev/null and b/lzsa_test/empty.dsk differ diff --git a/lzsa_test/gr_copy.s b/lzsa_test/gr_copy.s new file mode 100644 index 00000000..a657400b --- /dev/null +++ b/lzsa_test/gr_copy.s @@ -0,0 +1,161 @@ + ;========================================================= + ; gr_copy_to_current, 40x48 version + ;========================================================= + ; copy 0xc00 to DRAW_PAGE + ; + ; 45 + 2 + 120*(8*9 + 5) -1 + 6 = 9292 +;.align $100 +gr_copy_to_current: + + lda DRAW_PAGE ; 3 + clc ; 2 + adc #$4 ; 2 + sta gr_copy_line+5 ; 4 + sta gr_copy_line+11 ; 4 + adc #$1 ; 2 + sta gr_copy_line+17 ; 4 + sta gr_copy_line+23 ; 4 + adc #$1 ; 2 + sta gr_copy_line+29 ; 4 + sta gr_copy_line+35 ; 4 + adc #$1 ; 2 + sta gr_copy_line+41 ; 4 + sta gr_copy_line+47 ; 4 + ;=========== + ; 45 + + ldy #119 ; for early ones, copy 120 bytes ; 2 + +gr_copy_line: + lda $C00,Y ; load a byte (self modified) ; 4 + sta $400,Y ; store a byte (self modified) ; 5 + + lda $C80,Y ; load a byte (self modified) ; 4 + sta $480,Y ; store a byte (self modified) ; 5 + + lda $D00,Y ; load a byte (self modified) ; 4 + sta $500,Y ; store a byte (self modified) ; 5 + + lda $D80,Y ; load a byte (self modified) ; 4 + sta $580,Y ; store a byte (self modified) ; 5 + + lda $E00,Y ; load a byte (self modified) ; 4 + sta $600,Y ; store a byte (self modified) ; 5 + + lda $E80,Y ; load a byte (self modified) ; 4 + sta $680,Y ; store a byte (self modified) ; 5 + + lda $F00,Y ; load a byte (self modified) ; 4 + sta $700,Y ; store a byte (self modified) ; 5 + + lda $F80,Y ; load a byte (self modified) ; 4 + sta $780,Y ; store a byte (self modified) ; 5 + + dey ; decrement pointer ; 2 + bpl gr_copy_line ; ; 2nt/3 + + rts ; 6 + + + + ;========================================================= + ; gr_copy_to_current, 40x48 version + ;========================================================= + ; copy 0x1000 to DRAW_PAGE + +gr_copy_to_current_1000: + + lda DRAW_PAGE ; 3 + clc ; 2 + adc #$4 ; 2 + sta gr_copy_line_40+5 ; 4 + sta gr_copy_line_40+11 ; 4 + adc #$1 ; 2 + sta gr_copy_line_40+17 ; 4 + sta gr_copy_line_40+23 ; 4 + adc #$1 ; 2 + sta gr_copy_line_40+29 ; 4 + sta gr_copy_line_40+35 ; 4 + adc #$1 ; 2 + sta gr_copy_line_40+41 ; 4 + sta gr_copy_line_40+47 ; 4 + ;=========== + ; 45 + + ldy #119 ; for early ones, copy 120 bytes ; 2 + +gr_copy_line_40: + lda $1000,Y ; load a byte (self modified) ; 4 + sta $400,Y ; store a byte (self modified) ; 5 + + lda $1080,Y ; load a byte (self modified) ; 4 + sta $480,Y ; store a byte (self modified) ; 5 + + lda $1100,Y ; load a byte (self modified) ; 4 + sta $500,Y ; store a byte (self modified) ; 5 + + lda $1180,Y ; load a byte (self modified) ; 4 + sta $580,Y ; store a byte (self modified) ; 5 + + lda $1200,Y ; load a byte (self modified) ; 4 + sta $600,Y ; store a byte (self modified) ; 5 + + lda $1280,Y ; load a byte (self modified) ; 4 + sta $680,Y ; store a byte (self modified) ; 5 + + lda $1300,Y ; load a byte (self modified) ; 4 + sta $700,Y ; store a byte (self modified) ; 5 + + lda $1380,Y ; load a byte (self modified) ; 4 + sta $780,Y ; store a byte (self modified) ; 5 + + dey ; decrement pointer ; 2 + bpl gr_copy_line_40 ; ; 2nt/3 + + rts ; 6 + + + + ;========================================================= + ; gr_copy_to_current_40x40 + ;========================================================= + ; Take image in 0xc00 + ; Copy to DRAW_PAGE + ; Actually copy lines 0..39 + ; Don't over-write bottom 4 lines of text +gr_copy_to_current_40x40: + + ldx #0 +gc_40x40_loop: + lda gr_offsets,x + sta OUTL + sta INL + lda gr_offsets+1,x + clc + adc DRAW_PAGE + sta OUTH + + lda gr_offsets+1,x + clc + adc #$8 + sta INH + + ldy #39 +gc_40x40_inner: + lda (INL),Y + sta (OUTL),Y + + dey + bpl gc_40x40_inner + + inx + inx + + cpx #40 + bne gc_40x40_loop + + rts ; 6 + + + + diff --git a/lzsa_test/gr_lzsa.s b/lzsa_test/gr_lzsa.s new file mode 100644 index 00000000..e572c3cb --- /dev/null +++ b/lzsa_test/gr_lzsa.s @@ -0,0 +1,36 @@ + +.include "zp.inc" +.include "hardware.inc" + + lda #0 + sta DRAW_PAGE + + bit SET_GR + bit PAGE0 + + lda #graphic_start + sta LZSA_SRC_HI + + lda #$0 + sta LZSA_DST_LO + lda #$c + sta LZSA_DST_HI + + jsr decompress_lzsa2 + + jsr gr_copy_to_current + + +blah: + jmp blah + + + .include "decompress_small_v2.s" + .include "gr_copy.s" + .include "gr_offsets.s" + +graphic_start: + .incbin "spaceship_far_n.gr.small_v2" +graphic_end: diff --git a/lzsa_test/gr_offsets.s b/lzsa_test/gr_offsets.s new file mode 100644 index 00000000..d3af91f7 --- /dev/null +++ b/lzsa_test/gr_offsets.s @@ -0,0 +1,5 @@ +gr_offsets: + .word $400,$480,$500,$580,$600,$680,$700,$780 + .word $428,$4a8,$528,$5a8,$628,$6a8,$728,$7a8 + .word $450,$4d0,$550,$5d0,$650,$6d0,$750,$7d0 + diff --git a/lzsa_test/hardware.inc b/lzsa_test/hardware.inc new file mode 100644 index 00000000..8d203e23 --- /dev/null +++ b/lzsa_test/hardware.inc @@ -0,0 +1,86 @@ +;; HARDWARE LOCATIONS + +KEYPRESS = $C000 +KEYRESET = $C010 + +;; SOFT SWITCHES +CLR80COL = $C000 ; PAGE0/PAGE1 normal +SET80COL = $C001 ; PAGE0/PAGE1 switches PAGE0 in Aux instead +EIGHTYCOLOFF = $C00C +EIGHTYCOLON = $C00D +SPEAKER = $C030 +SET_GR = $C050 +SET_TEXT = $C051 +FULLGR = $C052 +TEXTGR = $C053 +PAGE0 = $C054 +PAGE1 = $C055 +LORES = $C056 ; Enable LORES graphics +HIRES = $C057 ; Enable HIRES graphics +AN3 = $C05E ; Annunciator 3 + +PADDLE_BUTTON0 = $C061 +PADDL0 = $C064 +PTRIG = $C070 + +;; BASIC ROUTINES + +NORMAL = $F273 + +;; MONITOR ROUTINES + +HLINE = $F819 ;; HLINE Y,$2C at A +VLINE = $F828 ;; VLINE A,$2D at Y +CLRSCR = $F832 ;; Clear low-res screen +CLRTOP = $F836 ;; clear only top of low-res screen +SETCOL = $F864 ;; COLOR=A +TEXT = $FB36 +TABV = $FB5B ;; VTAB to A +BELL = $FBDD ;; ring the bell +BASCALC = $FBC1 ;; +VTAB = $FC22 ;; VTAB to CV +HOME = $FC58 ;; Clear the text screen +WAIT = $FCA8 ;; delay 1/2(26+27A+5A^2) us +CROUT1 = $FD8B +SETINV = $FE80 ;; INVERSE +SETNORM = $FE84 ;; NORMAL +COUT = $FDED ;; output A to screen +COUT1 = $FDF0 ;; output A to screen + + + + + + +COLOR_BLACK = 0 +COLOR_RED = 1 +COLOR_DARKBLUE = 2 +COLOR_PURPLE = 3 +COLOR_DARKGREEN = 4 +COLOR_GREY = 5 +COLOR_MEDIUMBLUE = 6 +COLOR_LIGHTBLUE = 7 +COLOR_BROWN = 8 +COLOR_ORANGE = 9 +COLOR_GREY2 = 10 +COLOR_PINK = 11 +COLOR_LIGHTGREEN = 12 +COLOR_YELLOW = 13 +COLOR_AQUA = 14 +COLOR_WHITE = 15 + +COLOR_BOTH_BLACK = $00 +COLOR_BOTH_RED = $11 +COLOR_BOTH_DARKBLUE = $22 +COLOR_BOTH_DARKGREEN = $44 +COLOR_BOTH_GREY = $55 +COLOR_BOTH_MEDIUMBLUE = $66 +COLOR_BOTH_LIGHTBLUE = $77 +COLOR_BOTH_BROWN = $88 +COLOR_BOTH_ORANGE = $99 +COLOR_BOTH_PINK = $BB +COLOR_BOTH_LIGHTGREEN = $CC +COLOR_BOTH_YELLOW = $DD +COLOR_BOTH_AQUA = $EE +COLOR_BOTH_WHITE = $FF + diff --git a/lzsa_test/hello.bas b/lzsa_test/hello.bas new file mode 100644 index 00000000..617228a8 --- /dev/null +++ b/lzsa_test/hello.bas @@ -0,0 +1,2 @@ +5 HOME +120 PRINT CHR$(4);"BRUN GR_LZSA" diff --git a/lzsa_test/notes b/lzsa_test/notes new file mode 100644 index 00000000..f9b2bb32 --- /dev/null +++ b/lzsa_test/notes @@ -0,0 +1,7 @@ +spaceship_far_n + +rle 277 +lz4 323 + +lzsa -r -f1 -- small_v1 -- 252 bytes +lzsa -r -f2 -- small_v2 -- 228 bytes diff --git a/lzsa_test/spaceship_far_n.gr b/lzsa_test/spaceship_far_n.gr new file mode 100644 index 00000000..f5b87f30 Binary files /dev/null and b/lzsa_test/spaceship_far_n.gr differ diff --git a/lzsa_test/spaceship_far_n.gr.small_v2 b/lzsa_test/spaceship_far_n.gr.small_v2 new file mode 100644 index 00000000..080e248d Binary files /dev/null and b/lzsa_test/spaceship_far_n.gr.small_v2 differ diff --git a/lzsa_test/zp.inc b/lzsa_test/zp.inc new file mode 100644 index 00000000..77d9d025 --- /dev/null +++ b/lzsa_test/zp.inc @@ -0,0 +1,100 @@ +;; Zero Page + +;; LZ4 addresses + +NIBCOUNT = $00 +LZ4_SRC = $00 +LZ4_DST = $02 +LZ4_END = $04 +WHICH_LOAD = $05 +COUNT = $06 +MENU_BASE = $06 +MENU_HIGHLIGHT = $07 +DELTA = $08 + + +;; Zero page monitor routines addresses + +WNDLFT = $20 +WNDWDTH = $21 +WNDTOP = $22 +WNDBTM = $23 +CH = $24 +CV = $25 +GBASL = $26 +GBASH = $27 +BASL = $28 +BASH = $29 +H2 = $2C +V2 = $2D +MASK = $2E +COLOR_MASK = $2F +COLOR = $30 + + +SEEDL = $4e +SEEDH = $4f +XMAX = $50 + +FRAMEL = $60 +FRAMEH = $61 +CURSOR_X= $62 +CURSOR_Y= $63 +XPOS = $64 +YPOS = $65 +DIRECTION = $66 + DIRECTION_N = $0 + DIRECTION_S = $1 + DIRECTION_E = $2 + DIRECTION_W = $3 +LOCATION = $67 +LOCATION_STRUCT_L = $68 +LOCATION_STRUCT_H = $69 +IN_SPECIAL = $6A +CURSOR_VISIBLE = $6B +IN_LEFT = $6C +IN_RIGHT = $6D +BTC_L = $6E +BTC_H = $6F + +DISP_PAGE = $ED ; ALL +DRAW_PAGE = $EE ; ALL + + +TINL = $F0 +TINH = $F1 +BINL = $F2 +BINH = $F3 + + +SCROLL_COUNT = $F9 +TEMP = $FA +TEMPY = $FB +INL = $FC +INH = $FD +OUTL = $FE +OUTH = $FF + +; read any file slot 6 version +; based on FASTLD6 and RTS copyright (c) Peter Ferrie 2011-2013,2018 + +; modified to assembled with ca64 -- vmw +; added code to patch it to run from current disk slot -- vmw + + + adrlo = $26 ; constant from boot prom + adrhi = $27 ; constant from boot prom + tmpsec = $3c ; constant from boot prom + reqsec = $3d ; constant from boot prom + sizelo = $44 + sizehi = $45 + secsize = $46 + + ldsizel = $70 + ldsizeh = $71 + namlo = $7b + namhi = $7c + step = $7d ; state for stepper motor + tmptrk = $7e ; temporary copy of current track + phase = $7f ; current phase for /seek + diff --git a/mist/decompress_small_v2.s b/mist/decompress_small_v2.s new file mode 100644 index 00000000..250ee743 --- /dev/null +++ b/mist/decompress_small_v2.s @@ -0,0 +1,338 @@ +; ----------------------------------------------------------------------------- +; Decompress raw LZSA2 block. +; Create one with lzsa -r -f2 +; +; in: +; * LZSA_SRC_LO and LZSA_SRC_HI contain the compressed raw block address +; * LZSA_DST_LO and LZSA_DST_HI contain the destination buffer address +; +; out: +; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1 +; +; ----------------------------------------------------------------------------- +; Backward decompression is also supported, use lzsa -r -b -f2 +; To use it, also define BACKWARD_DECOMPRESS=1 before including this code! +; +; in: +; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data +; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer +; +; out: +; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1 +; +; ----------------------------------------------------------------------------- +; +; Copyright (C) 2019 Emmanuel Marty +; +; 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 source distribution. +; ----------------------------------------------------------------------------- + +;NIBCOUNT = $FC ; zero-page location for temp offset + +decompress_lzsa2: + ldy #$00 + sty NIBCOUNT + +decode_token: + jsr getsrc ; read token byte: XYZ|LL|MMM + pha ; preserve token on stack + + and #$18 ; isolate literals count (LL) + beq no_literals ; skip if no literals to copy + lsr ; shift literals count into place + lsr + lsr + cmp #$03 ; LITERALS_RUN_LEN_V2? + bcc prepare_copy_literals ; if less, count is directly embedded in token + + jsr getnibble ; get extra literals length nibble + ; add nibble to len from token + adc #$02 ; (LITERALS_RUN_LEN_V2) minus carry + cmp #$12 ; LITERALS_RUN_LEN_V2 + 15 ? + bcc prepare_copy_literals ; if less, literals count is complete + + jsr getsrc ; get extra byte of variable literals count + ; the carry is always set by the CMP above + ; GETSRC doesn't change it + sbc #$EE ; overflow? + +prepare_copy_literals: + tax + bcc prepare_copy_literals_high ; if not, literals count is complete + + ; handle 16 bits literals count + ; literals count = directly these 16 bits + jsr getlargesrc ; grab low 8 bits in X, high 8 bits in A + tay ; put high 8 bits in Y + +prepare_copy_literals_high: + txa + beq copy_literals + iny + +copy_literals: + jsr getput ; copy one byte of literals + dex + bne copy_literals + dey + bne copy_literals + +no_literals: + pla ; retrieve token from stack + pha ; preserve token again + asl + bcs repmatch_or_large_offset ; 1YZ: rep-match or 13/16 bit offset + + asl ; 0YZ: 5 or 9 bit offset + bcs offset_9_bit + + ; 00Z: 5 bit offset + + ldx #$FF ; set offset bits 15-8 to 1 + + jsr getcombinedbits ; rotate Z bit into bit 0, read nibble for bits 4-1 + ora #$E0 ; set bits 7-5 to 1 + bne got_offset_lo ; go store low byte of match offset and prepare match + +offset_9_bit: ; 01Z: 9 bit offset + ;;asl ; shift Z (offset bit 8) in place + rol + rol + and #$01 + eor #$FF ; set offset bits 15-9 to 1 + bne got_offset_hi ; go store high byte, read low byte of match offset and prepare match + ; (*same as JMP GOT_OFFSET_HI but shorter) + +repmatch_or_large_offset: + asl ; 13 bit offset? + bcs repmatch_or_16_bit ; handle rep-match or 16-bit offset if not + + ; 10Z: 13 bit offset + + jsr getcombinedbits ; rotate Z bit into bit 8, read nibble for bits 12-9 + adc #$DE ; set bits 15-13 to 1 and substract 2 (to substract 512) + bne got_offset_hi ; go store high byte, read low byte of match offset and prepare match + ; (*same as JMP GOT_OFFSET_HI but shorter) + +repmatch_or_16_bit: ; rep-match or 16 bit offset + ;;asl ; XYZ=111? + bmi rep_match ; reuse previous offset if so (rep-match) + + ; 110: handle 16 bit offset + jsr getsrc ; grab high 8 bits +got_offset_hi: + tax + jsr getsrc ; grab low 8 bits +got_offset_lo: + sta offslo ; store low byte of match offset + stx offshi ; store high byte of match offset + +rep_match: + +.ifdef BACKWARD_DECOMPRESS + + ; Backward decompression - substract match offset + + sec ; add dest + match offset + lda putdst+1 ; low 8 bits +offslo = *+1 + sbc #$AA + sta copy_match_loop+1 ; store back reference address + lda putdst+2 +offshi = *+1 + sbc #$AA ; high 8 bits + sta copy_match_loop+2 ; store high 8 bits of address + sec + +.else + + ; Forward decompression - add match offset + + clc ; add dest + match offset + lda putdst+1 ; low 8 bits +offslo = *+1 + adc #$AA + sta copy_match_loop+1 ; store back reference address +offshi = *+1 + lda #$AA ; high 8 bits + adc putdst+2 + sta copy_match_loop+2 ; store high 8 bits of address +.endif + + pla ; retrieve token from stack again + and #$07 ; isolate match len (MMM) + adc #$01 ; add MIN_MATCH_SIZE_V2 and carry + cmp #$09 ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2? + bcc prepare_copy_match ; if less, length is directly embedded in token + + jsr getnibble ; get extra match length nibble + ; add nibble to len from token + adc #$08 ; (MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2) minus carry + cmp #$18 ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15? + bcc prepare_copy_match ; if less, match length is complete + + jsr getsrc ; get extra byte of variable match length + ; the carry is always set by the CMP above + ; GETSRC doesn't change it + sbc #$E8 ; overflow? + +prepare_copy_match: + tax + bcc prepare_copy_match_y ; if not, the match length is complete + beq decompression_done ; if EOD code, bail + + ; Handle 16 bits match length + jsr getlargesrc ; grab low 8 bits in X, high 8 bits in A + tay ; put high 8 bits in Y + +prepare_copy_match_y: + txa + beq copy_match_loop + iny + +copy_match_loop: + lda $AAAA ; get one byte of backreference + jsr putdst ; copy to destination + +.ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- put backreference bytes backward + + lda copy_match_loop+1 + bne getmatch_done + dec copy_match_loop+2 +getmatch_done: + dec copy_match_loop+1 + +.else + + ; Forward decompression -- put backreference bytes forward + + inc copy_match_loop+1 + bne getmatch_done + inc copy_match_loop+2 + +getmatch_done: + +.endif + + dex + bne copy_match_loop + dey + bne copy_match_loop + jmp decode_token + +getcombinedbits: + eor #$80 + asl + php + + jsr getnibble ; get nibble into bits 0-3 (for offset bits 1-4) + plp ; merge Z bit as the carry bit (for offset bit 0) +combinedbitz: + rol ; nibble -> bits 1-4; carry(!Z bit) -> bit 0 ; carry cleared +decompression_done: + rts + +getnibble: +nibbles = *+1 + lda #$AA + lsr NIBCOUNT + bcs has_nibbles + + inc NIBCOUNT + jsr getsrc ; get 2 nibbles + sta nibbles + lsr + lsr + lsr + lsr + sec + +has_nibbles: + and #$0F ; isolate low 4 bits of nibble + rts + +.ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- get and put bytes backward + +getput: + jsr getsrc +putdst: +LZSA_DST_LO = *+1 +LZSA_DST_HI = *+2 + sta $AAAA + lda putdst+1 + bne putdst_done + dec putdst+2 +putdst_done: + dec putdst+1 + rts + +getlargesrc: + jsr getsrc ; grab low 8 bits + tax ; move to X + ; fall through grab high 8 bits + +getsrc: +LZSA_SRC_LO = *+1 +LZSA_SRC_HI = *+2 + lda $AAAA + pha + lda getsrc+1 + bne getsrc_done + dec getsrc+2 +getsrc_done: + dec getsrc+1 + pla + rts + +.else + + ; Forward decompression -- get and put bytes forward + +getput: + jsr getsrc + +putdst: +LZSA_DST_LO = *+1 +LZSA_DST_HI = *+2 + sta $AAAA + inc putdst+1 + bne putdst_done + inc putdst+2 +putdst_done: + rts + +getlargesrc: + jsr getsrc ; grab low 8 bits + tax ; move to X + ; fall through grab high 8 bits + +getsrc: +LZSA_SRC_LO = *+1 +LZSA_SRC_HI = *+2 + lda $AAAA + inc getsrc+1 + bne getsrc_done + inc getsrc+2 +getsrc_done: + rts + +.endif + diff --git a/mist/graphics_island/Makefile.orig b/mist/graphics_island/Makefile.orig new file mode 100644 index 00000000..33f6bd45 --- /dev/null +++ b/mist/graphics_island/Makefile.orig @@ -0,0 +1,85 @@ +#include ../Makefile.inc + +PNG2RLE = ../../gr-utils/png2rle + +all: mist_graphics.inc + +#### + +mist_graphics.inc: \ + m_link_book.png \ + dock_n.png dock_s.png dock_e.png dock_w.png \ + dock_switch_n.png \ + dock_steps_w.png \ + above_dock_e.png above_dock_n.png above_dock_s.png \ + step_base_s.png step_base_n.png \ + step_land1_w.png step_land1_e.png \ + step_land2_e.png step_land2_w.png \ + step_dentist_e.png step_dentist_w.png \ + step_land3_w.png step_land3_e.png \ + step_top_e.png step_top_w.png step_top_n.png step_top_s.png \ + temple_door_n.png temple_door_s.png \ + temple_center_n.png temple_center_w.png \ + red_book_shelf.png \ + red_book_closed.png \ + pool_s.png \ + clock_s.png \ + spaceship_far_e.png spaceship_far_n.png \ + red_book_open.png red_book_static.png red_book_static2.png \ + tree2_n.png \ + tree5_n.png tree5_e.png \ + gear_n.png gear_w.png gear_s.png \ + gear_base_n.png + $(PNG2RLE) asm m_link_book.png link_book_rle > mist_graphics.inc + $(PNG2RLE) asm dock_n.png dock_n_rle >> mist_graphics.inc + $(PNG2RLE) asm dock_s.png dock_s_rle >> mist_graphics.inc + $(PNG2RLE) asm dock_e.png dock_e_rle >> mist_graphics.inc + $(PNG2RLE) asm dock_w.png dock_w_rle >> mist_graphics.inc + $(PNG2RLE) asm dock_switch_n.png dock_switch_n_rle >> mist_graphics.inc + $(PNG2RLE) asm dock_switch_s.png dock_switch_s_rle >> mist_graphics.inc + $(PNG2RLE) asm dock_steps_w.png dock_steps_w_rle >> mist_graphics.inc + $(PNG2RLE) asm above_dock_e.png above_dock_e_rle >> mist_graphics.inc + $(PNG2RLE) asm above_dock_s.png above_dock_s_rle >> mist_graphics.inc + $(PNG2RLE) asm above_dock_n.png above_dock_n_rle >> mist_graphics.inc + $(PNG2RLE) asm step_base_n.png step_base_n_rle >> mist_graphics.inc + $(PNG2RLE) asm step_base_s.png step_base_s_rle >> mist_graphics.inc + $(PNG2RLE) asm step_land1_w.png step_land1_w_rle >> mist_graphics.inc + $(PNG2RLE) asm step_land1_e.png step_land1_e_rle >> mist_graphics.inc + $(PNG2RLE) asm step_land2_w.png step_land2_w_rle >> mist_graphics.inc + $(PNG2RLE) asm step_land2_e.png step_land2_e_rle >> mist_graphics.inc + $(PNG2RLE) asm step_dentist_w.png step_dentist_w_rle >> mist_graphics.inc + $(PNG2RLE) asm step_dentist_e.png step_dentist_e_rle >> mist_graphics.inc + $(PNG2RLE) asm step_land3_w.png step_land3_w_rle >> mist_graphics.inc + $(PNG2RLE) asm step_land3_e.png step_land3_e_rle >> mist_graphics.inc + $(PNG2RLE) asm step_top_e.png step_top_e_rle >> mist_graphics.inc + $(PNG2RLE) asm step_top_w.png step_top_w_rle >> mist_graphics.inc + $(PNG2RLE) asm step_top_n.png step_top_n_rle >> mist_graphics.inc + $(PNG2RLE) asm step_top_s.png step_top_s_rle >> mist_graphics.inc + $(PNG2RLE) asm temple_door_n.png temple_door_n_rle >> mist_graphics.inc + $(PNG2RLE) asm temple_door_s.png temple_door_s_rle >> mist_graphics.inc + $(PNG2RLE) asm temple_center_n.png temple_center_n_rle >> mist_graphics.inc + $(PNG2RLE) asm temple_center_s.png temple_center_s_rle >> mist_graphics.inc + $(PNG2RLE) asm temple_center_e.png temple_center_e_rle >> mist_graphics.inc + $(PNG2RLE) asm temple_center_w.png temple_center_w_rle >> mist_graphics.inc + $(PNG2RLE) asm red_book_closed.png red_book_closed_rle >> mist_graphics.inc + $(PNG2RLE) asm red_book_shelf.png red_book_shelf_rle >> mist_graphics.inc + $(PNG2RLE) asm pool_s.png pool_s_rle >> mist_graphics.inc + $(PNG2RLE) asm clock_s.png clock_s_rle >> mist_graphics.inc + $(PNG2RLE) asm spaceship_far_n.png ss_far_n_rle >> mist_graphics.inc + $(PNG2RLE) asm spaceship_far_e.png ss_far_e_rle >> mist_graphics.inc + $(PNG2RLE) asm red_book_open.png red_book_open_rle >> mist_graphics.inc + $(PNG2RLE) asm red_book_static.png red_book_static_rle >> mist_graphics.inc + $(PNG2RLE) asm red_book_static2.png red_book_static2_rle >> mist_graphics.inc + $(PNG2RLE) asm tree2_n.png tree2_n_rle >> mist_graphics.inc + $(PNG2RLE) asm tree5_n.png tree5_n_rle >> mist_graphics.inc + $(PNG2RLE) asm tree5_e.png tree5_e_rle >> mist_graphics.inc + $(PNG2RLE) asm gear_n.png gear_n_rle >> mist_graphics.inc + $(PNG2RLE) asm gear_s.png gear_s_rle >> mist_graphics.inc + $(PNG2RLE) asm gear_w.png gear_w_rle >> mist_graphics.inc + $(PNG2RLE) asm gear_base_n.png gear_base_n_rle >> mist_graphics.inc + + +#### + +clean: + rm -f *~ *.o *.lst mist_graphics.inc