; ; Copyright (c) 2002, 2003 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. ; ; ------------------------------------------------------------------- ; the circular buffer needs to be page aligned, so only the high-bytes ; of the buffer start and len is imported to enforce this. ; the data that are to be decrunched must not have been crunched with ; a maximum offset size greater than the buffer size. use the -m option ; with a value of (buffer_len_hi * 256) or less. ; ------------------------------------------------------------------- .import buffer_start_hi: absolute .import buffer_len_hi: absolute ; ------------------------------------------------------------------- ; The decruncher jsr:s to the get_crunched_byte address when it wants to ; read a crunched byte. This subroutine has to preserve x and y register ; and must not modify the state of the carry flag. ; ------------------------------------------------------------------- .import get_crunched_byte ; ------------------------------------------------------------------- ; this subsoutine is called before decrunching. It initializes the ; decruncher zeropage locations and precalculates the decrunch tables. ; ------------------------------------------------------------------- .export init_decruncher ; ------------------------------------------------------------------- ; this function is the heart of the decruncher. Call this whenever you ; want a decrunched byte. It will return it in the accumulator. It will ; also destroy the values in y and x reg and mess up the status flags. ; This function will not change the interrupt status bit and it will not ; modify the memory configuration. ; ------------------------------------------------------------------- .export get_decrunched_byte ; ------------------------------------------------------------------- ; zero page addresses used ; ------------------------------------------------------------------- zp_src_hi = $a7 zp_src_lo = zp_src_hi + 1 zp_src_bi = zp_src_hi + 2 zp_bitbuf = zp_src_hi + 3 zp_len_lo = $ae zp_len_hi = zp_len_lo + 1 zp_bits_lo = $fb zp_bits_hi = zp_bits_lo + 1 zp_dest_hi = $fd zp_dest_lo = zp_dest_hi + 1 ; dest addr lo zp_dest_bi = zp_dest_hi + 2 ; dest addr hi ; ------------------------------------------------------------------- ; symbolic names for constants ; ------------------------------------------------------------------- buffer_end_hi = buffer_start_hi + buffer_len_hi tabl_bi = decrunch_table tabl_lo = decrunch_table + 52 tabl_hi = decrunch_table + 104 ; ------------------------------------------------------------------- ; 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 init the decruncher, it will init used zeropage ; zero page locations and the decrunch tables ; no constraints on register content, however the ; decimal flag has to be #0 (it almost always is, otherwise do a cld) ; ------------------------------------------------------------------- init_decruncher: jsr get_crunched_byte sta zp_bitbuf ldx #0 stx zp_dest_lo stx zp_dest_hi stx zp_len_lo stx zp_len_hi ldy #0 ; ------------------------------------------------------------------- ; calculate tables (49 bytes) ; x and y must be #0 when entering ; _init_nextone: inx tya and #$0f beq _init_shortcut ; starta på ny sekvens txa ; this clears reg a lsr a ; and sets the carry flag ldx zp_bits_lo _init_rolle: rol a rol zp_bits_hi dex bpl _init_rolle ; c = 0 after this (rol zp_bits_hi) adc tabl_lo-1,y tax lda zp_bits_hi adc tabl_hi-1,y _init_shortcut: sta tabl_hi,y txa sta tabl_lo,y ldx #4 jsr _bit_get_bits ; clears x-reg. sta tabl_bi,y iny cpy #52 bne _init_nextone _do_exit: rts ; ------------------------------------------------------------------- ; decrunch one byte ; get_decrunched_byte: ldy zp_len_lo bne _do_sequence ldx zp_len_hi bne _do_sequence2 jsr _bit_get_bit1 beq _get_sequence ; ------------------------------------------------------------------- ; literal handling (13 bytes) ; jsr get_crunched_byte bcc _do_literal ; ------------------------------------------------------------------- ; count zero bits + 1 to get length table index (10 bytes) ; y = x = 0 when entering ; _get_sequence: _seq_next1: iny jsr _bit_get_bit1 beq _seq_next1 cpy #$11 bcs _do_exit ; ------------------------------------------------------------------- ; calulate length of sequence (zp_len) (17 bytes) ; ldx tabl_bi - 1,y jsr _bit_get_bits adc tabl_lo - 1,y sta zp_len_lo lda zp_bits_hi adc tabl_hi - 1,y sta zp_len_hi ; ------------------------------------------------------------------- ; here we decide what offset table to use (20 bytes) ; x is 0 here ; bne _seq_nots123 ldy zp_len_lo cpy #$04 bcc _seq_size123 _seq_nots123: ldy #$03 _seq_size123: ldx tabl_bit - 1,y jsr _bit_get_bits adc tabl_off - 1,y tay ; ------------------------------------------------------------------- ; calulate absolute offset (zp_src) (27 bytes) ; ldx tabl_bi,y jsr _bit_get_bits; adc tabl_lo,y bcc _seq_skipcarry inc zp_bits_hi clc _seq_skipcarry: adc zp_dest_lo sta zp_src_lo lda zp_bits_hi adc tabl_hi,y adc zp_dest_hi ; ------------------------------------------------------------------- cmp #