; ; (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are met: ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; * The name of its author may not be used to endorse or promote products ; derived from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; !cpu 6510 BITS_LEFT = 0 .depacker_dst = $01 .smc_offsetd = .depacker_dst - (.dali_code_end - .dali_code_start) !ifdef SFX_FAST { DALI_FAST_SRC = lz_src - .smc_offsetd + 2 DALI_FAST_DST = lz_dst - .smc_offsetd + 2 DALI_FAST_SFX_ADDR = lz_sfx_addr - .smc_offsetd + 2 DALI_FAST_DATA_END = lz_data_end - .smc_offsetd + 2 DALI_FAST_DATA_SIZE_HI = lz_data_size_hi - .smc_offsetd + 2 DALI_FAST_01 = lz_01 - .smc_offsetd + 2 DALI_FAST_CLI = lz_cli - .smc_offsetd + 2 } else { DALI_SMALL_SRC = lz_src - .smc_offsetd + 2 DALI_SMALL_DST = lz_dst - .smc_offsetd + 2 DALI_SMALL_SFX_ADDR = lz_sfx_addr - .smc_offsetd + 2 DALI_SMALL_DATA_END = lz_data_end - .smc_offsetd + 2 DALI_SMALL_DATA_SIZE_HI = lz_data_size_hi - .smc_offsetd + 2 } !macro get_lz_bit { !if BITS_LEFT = 1 { asl anc $08 would not hurt, but $9e hurts !word 1602 !byte $9e !text "2061" !byte $00,$00,$00 ;/!\ ATTENTION, the depacker just fits into ZP this way, if it gets larger, the copy routine will overwrite $00, as it is a 8-bit address sta sei !ifdef SFX_FAST { ;full zp code will be copied, but later less bytes will be copied back ldx #<($100 + (.depacker_end - .restore_end)) txs } ldy #.depacker_end - .depacker_start - !ifdef SFX_FAST { pha ;saved zp to stack down to $02 lax <.depacker_dst - 1,y ;saves a byte, 2 byte compared to lda $0000,y } ldx .depacker_code - 1,y stx <.depacker_dst - 1,y dey bne - jmp .depack ;------------------ ;depacker starts here ;------------------ .dali_code_end .depacker_code !pseudopc .depacker_dst { .depacker_start !byte $34 lz_bits !if BITS_LEFT = 1 { !byte $40 } else { !byte $02 } .depack !ifdef SFX_FAST { lz_01 = * + 1 lda #$37 ;replace value for $01 in saved ZP on stack pha } - ;copy data to end of ram ($ffff) dey lz_data_end = * + 1 .src lda $beef,y .dst sta $ff00,y tya ;annoying, but need to copy from $ff ... $00 bne - dec <.src + 2 lz_data_size_hi = * + 1 lda #$00 ;check for last page to copy dcp <.dst + 2 bne - ;ldy #$00 ;is already 0 ;------------------ ;LITERAL ;------------------ .lz_start_over lda #$01 ;we fall through this check on entry and start with literal +get_lz_bit !ifdef SFX_FAST { bcc .literal bcs .lz_new_offset ;after each match check for another match or literal? - ;lz_length as inline +get_lz_bit ;fetch payload bit rol ;can also moved to front and executed once on start .literal +get_lz_bit bcc - bne + jsr lz_refill_bits beq .lz_l_page ;happens very seldom, so let's do that with lz_l_page that also decrements lz_len_hi, it returns on c = 1, what is always true after jsr .lz_length + tax .lz_l_page_ } else { bcs .lz_new_offset ;after each match check for another match or literal? .literal jsr get_length tax beq .lz_l_page .lz_l_page_ } cp_literal lz_src = * + 1 lda $beef,y ;looks expensive, but is cheaper than loop sta (lz_dst),y inc same as lda #$01 +get_lz_bit bcs .lz_new_offset ;either match with new offset or old offset ;------------------ ;DO MATCH ;------------------ .lz_match jsr get_length !ifdef SFX_FAST { sbc #$01 ;saves the sec and iny later on, if it results in a = $ff, no problem, we branch with the beq later on sec } else { .lz_m_page_ sbc #$01 ;saves the sec and iny later on, if it results in a = $ff, no problem, we branch with the beq later on bcs .lz_match_ dcp