Groups | Search | Server Info | Keyboard shortcuts | Login | Register


Groups > de.comp.lang.assembler > #1208

6502 gunzip

From Jan Bruns <ebay@abnuto.de>
Newsgroups de.comp.lang.assembler
Subject 6502 gunzip
Date 2020-10-21 05:05 +0000
Message-ID <hv9ts3FbqqhU1@mid.individual.net> (permalink)

Show all headers | View raw


Ich glaube, da hat die Welt drauf gewartet, nicht? 
Nur deshalb ging's nicht voran.

Gruss

Jan Bruns


; 6502 .gz file / deflate->inflate decoder 
;
; (html/js assembler: http://abnuto.de/jan/code/a65sm/index.html )
;
;
; design goal was: small runtime memory footprint
; 
; supports all features/blocktypes of inflate,
; including non-compressed blocks,
; compressed with default huffmann tabs
; compressed with dynamic huffmann tabs
;
; gz-file handling supports overreading
; irrelevant information to safely get to
; the deflate-bitstream
; gz-files could theoretically support
; other compression methods, which aren't
; supported here
;
; code module file size is 
; 1439 bytes (bare inflate, no util)
; 1469 bytes (bare inflate, with util)
; 1616 bytes (with .gz handling, no util)
; 1646 bytes (with .gz handling, with util)

; including 15 bytes of code-like global vars:
; 1454 bytes (bare inflate, no util)
; 1484 bytes (bare inflate, with util)
; 1631 bytes (with .gz handling, no util)
; 1661 bytes (with .gz handling, with util)

; during decode, 2.5 pages (640 bytes) of
; scratch-pad ram at runtime-configurable location
; are used for huffmann tables

; finally, the following 32 zero-page vars




// must be Zero-Page
Lgz_baseZP      = 10;

Lgz_indat                  = Lgz_baseZP+00 // word
Lgz_curHuffTab             = Lgz_baseZP+02 // word
Lgz_curHuffVals            = Lgz_baseZP+04 // word
Lgz_inmsk                  = Lgz_baseZP+06 // word

Lgz_codelens               = Lgz_baseZP+08 // word

// optional in Zero Page, could be moved to globals section instead
Lgz_codes_loaded           = Lgz_baseZP+0a // word, 18 refs
Lgz_datalen                = Lgz_baseZP+0c // word, 11 refs
Lgz_pattern                = Lgz_baseZP+0e // word, 8 refs
Lgz_codesum                = Lgz_baseZP+10 // word, 8 refs
Lgz_luphuff_x              = Lgz_baseZP+12 // word, 8 refs
Lgz_luphuff_x_plus_pattern = Lgz_baseZP+14 // word, 6 refs
Lgz_datadist               = Lgz_baseZP+16 // word, 6 refs
Lgz_putwhat                = Lgz_baseZP+18 // byte, 6 refs
Lgz_count_codes_cnt        = Lgz_baseZP+19 // byte, 6 refs
Lgz_bitcnt                 = Lgz_baseZP+1a // byte, 6 refs
Lgz_dattyp                 = Lgz_baseZP+1b // byte, 4 refs
Lgz_take_headbytecnt       = Lgz_baseZP+1c // byte, 8 refs
Lgz_take_headbyteflgs      = Lgz_baseZP+1d // byte, 7 refs

Lgz_dstptr = Lgz_baseZP+1e // word, used with util Lgz_put_databyte/
Lgz_datapeek


// global layout of 2.5 pages used for temp huff table storage 
//0000 LitLenHuffTab 48 bytes of Thufftab
//0030 LitLenHuffTabVals 288
//0150 DistHuffTab 48 bytes of Thufftab
//0180 DistHuffTabVals 30
//019e
//01a0 HuffTabHuffTab 48 bytes of Thufftab
//01d0 HuffTabHuffTabVals 19
//01e3
//01f0 codelens 144 byte (up to 288 nibbles of codelength 0..15)
//0280

//THufftab = record
//  codesoflen : array[0..15] of word;
//  numNonLitCodes : array[0..15] of byte;
//end;



; in terms of usage, most relevant labels are:

; Lgz_init:
;##########
; call with X=first of 2.5 pages of tmp tab mem (addr hi), and 
; A=80 (gz) or A=0 (bare inflate)

; Lgz_inflate_byte: 
;##################
; byte consumer for bare inflate

; Lgz_take_gz_byte: 
;##################
; optional, byte consumer for both, gz-data or bare inflate

; Lgz_trail:  jmp <rts>
;###########
; override to install a crc32-checking callback 
; y<>c0 indicates some error occured somewhere in the stream
; if y=c0, expect x to be one of the 8 crc32/len trailing bytes

; Lgz_put_databyte: jmp Lgz_default_put_databyte
;##################
; override to install custom uncompressed byte putter,
; be aware that this might also require Lgz_datapeek code
; MUST be overridden if util code is disabled

; Lgz_datapeek: jmp Lgz_default_datapeek
;##############
; to implement inflate's references to the decompressed data
; MUST be overridden if util code is disabled






.section 0,test2

Lgz_start:


//
//function Lgz_lookup_hufftab() : boolean;
//var x,i : word; h : boolean;
//begin
//  x := curHuffTab^.cofl[Lgz_bitcnt];
//  if (x>0)and(Lgz_indat<Lgz_pattern+x) then begin
//    Lgz_indat := Lgz_indat -Lgz_pattern;
//    h := false;
//    if (Lgz_indat>=(x-curHuffTab^.nnlc[Lgz_bitcnt])) then h := true;
//    Lgz_indat += Lgz_codesum;
//    Lgz_indat := curHuffVals[Lgz_indat];
//    if h then Lgz_indat := Lgz_indat +256;
//    Lgz_lookup_hufftab := true;
//    exit;
//  end;
//  Lgz_pattern := 2*(Lgz_pattern+x);
//  Lgz_codesum += x;
//  Lgz_lookup_hufftab := false;
//end;

Lgz_lookup_hufftab:
;##################


            // x := curHuffTab.cofl[Lgz_bitcnt]
            // xpluspattern := x+Lgz_pattern
            lda Lgz_bitcnt
            asl
            tay
            lda (Lgz_curHuffTab),y
            sta Lgz_luphuff_x
            clc
            adc Lgz_pattern
            sta Lgz_luphuff_x_plus_pattern
            iny 
            lda (Lgz_curHuffTab),y
            sta Lgz_luphuff_x+1
            adc Lgz_pattern+1
            sta Lgz_luphuff_x_plus_pattern+1

            // if x<>0 then Lgz_luphuff_xnonzero
            lda Lgz_luphuff_x
            bne Lgz_luphuff_xnonzero
            lda Lgz_luphuff_x+1
            bne Lgz_luphuff_xnonzero

Lgz_lookup_hufftab_notfound:
            // pattern += 2*(xpluspattern)
            lda Lgz_luphuff_x_plus_pattern
            asl
            sta Lgz_pattern
            lda Lgz_luphuff_x_plus_pattern+1
            rol
            sta Lgz_pattern+1

            // Lgz_codesum += x;
            clc
            lda Lgz_codesum
            adc Lgz_luphuff_x
            sta Lgz_codesum
            lda Lgz_codesum+1
            adc Lgz_luphuff_x+1
            sta Lgz_codesum+1
            clc
            rts

Lgz_luphuff_xnonzero:
            // if (xpluspattern <= indat) then Lgz_lookup_hufftab_notfound
            lda Lgz_luphuff_x_plus_pattern+1
            cmp Lgz_indat+1
            bcc Lgz_lookup_hufftab_notfound
            bne Lgz_lookup_hufftab_found
            lda Lgz_luphuff_x_plus_pattern
            cmp Lgz_indat
            bcc Lgz_lookup_hufftab_notfound
            beq Lgz_lookup_hufftab_notfound

Lgz_lookup_hufftab_found:
            // indat -= pattern
            sec
            lda Lgz_indat
            sbc Lgz_pattern
            sta Lgz_indat
            lda Lgz_indat+1
            sbc Lgz_pattern+1
            sta Lgz_indat+1

            // xminusnonlit := x-curHuffTab.nnlc[Lgz_bitcnt]
            clc
            lda Lgz_bitcnt
            adc #20
            tay
            sec
            lda Lgz_luphuff_x
            sbc (Lgz_curHuffTab),y
            sta Lgz_luphuff_x_minus_nonlit
            lda Lgz_luphuff_x+1
            sbc #00 
            sta Lgz_luphuff_x_minus_nonlit+1

            // if (Lgz_indat>=Lgz_luphuff_x_minus_nonlit) 
            // then Lgz_luphuff_x_minus_nonlit := 1 
            // else Lgz_luphuff_x_minus_nonlit := 0
            lda Lgz_indat+1
            cmp Lgz_luphuff_x_minus_nonlit+1
            bcc Lgz_luphuff_x_minus_else
            lda Lgz_indat
            cmp Lgz_luphuff_x_minus_nonlit
            bcc Lgz_luphuff_x_minus_else
Lgz_luphuff_x_minus_then:
            lda #01
            sta Lgz_luphuff_x_minus_nonlit
            bne Lgz_luphuff_x_minus_done
Lgz_luphuff_x_minus_else:
            lda #00
            sta Lgz_luphuff_x_minus_nonlit
Lgz_luphuff_x_minus_done:
            // Lgz_indat += Lgz_codesum;
            clc
            lda Lgz_indat
            adc Lgz_codesum
            sta Lgz_indat
            lda Lgz_indat+1
            adc Lgz_codesum+1
            sta Lgz_indat+1

            // Lgz_indat := curHuffVals[Lgz_indat];
            clc
            lda Lgz_indat
            adc Lgz_curHuffVals
            sta Lgz_indat
            lda Lgz_indat+1
            adc Lgz_curHuffVals+1
            sta Lgz_indat+1
            ldy #00
            lda (Lgz_indat),y
            sta Lgz_indat

            // if h then Lgz_indat := Lgz_indat +256;
            lda Lgz_luphuff_x_minus_nonlit
            sta Lgz_indat+1
            sec
            rts

Lgz_luphuff_x_minus_nonlit = Lgz_luphuff_x_plus_pattern





Lgz_take_BFINAL:
;###############
            lda Lgz_indat
            sta Lgz_islast
            lda #01 // Lgz_take_BTYPE
            ldx #02
            bne Lgz_expectbits // unconditional



Lgz_take_BTYPE:
;##############
            ldx Lgz_indat
            beq Lgz_take_BTYPE_uncompressed
            dex
            beq Lgz_take_BTYPE_statichuff
            dex
            beq Lgz_take_BTYPE_dynhuff
            lda #09 // on error, no bit-func
            ldx #01
            bne Lgz_expectbits // unconditional
Lgz_take_BTYPE_uncompressed:
            inc Lgz_takebyte_bitmode
            lda #80
            ldx #08
            bne Lgz_expectbits // unconditional
Lgz_take_BTYPE_statichuff:
            jsr Lgz_prepare_default_tabs
            lda #07
            ldx #01
            bne Lgz_expectbits // unconditional
Lgz_take_BTYPE_dynhuff:
            lda #02
            ldx #05
            bne Lgz_expectbits // unconditional


Lgz_take_HLIT:
            lda Lgz_indat
            and #1f
            clc
            adc #01
            sta Lgz_HLIT
            lda #01
            sta Lgz_HLIT+1
            lda #03
            ldx #05
            bne Lgz_expectbits // unconditional

Lgz_take_HDIST:
            lda Lgz_indat
            and #1f
            clc
            adc #01
            sta Lgz_HDIST
            lda #04
            ldx #04
            bne Lgz_expectbits // unconditional



Lgz_take_HCLEN:
;##############
            lda Lgz_indat
            and #0f
            clc
            adc #04
            sta Lgz_HCLEN
            lda #00
            sta Lgz_codes_loaded
            sta Lgz_codes_loaded+1
            jsr Lgz_clear_codelens
            lda #05
            ldx #03
            //bne Lgz_expectbits // unconditional


Lgz_expectbits:
;##############
            sta Lgz_dattyp
            stx Lgz_bitcnt

Lgz_reset_infdat:
;################
            lda #00
            sta Lgz_indat
            sta Lgz_indat+1
            sta Lgz_inmsk+1
            lda #01
            sta Lgz_inmsk

Lgz_initLookup:
;##############
            lda #00
            sta Lgz_pattern
            sta Lgz_pattern+1
            sta Lgz_codesum
            sta Lgz_codesum+1
            rts


Lgz_set_hufftab_dist:
;####################
            lda #50
            ldx #01
            bne Lgz_set_tab // unconditional
Lgz_set_hufftab_litlen:
;######################
            lda #00
            ldx #00
            beq Lgz_set_tab // unconditional
Lgz_set_hufftab_hufftab:
;#######################
            lda #a0
            ldx #01
Lgz_set_tab:
;###########
            sta Lgz_curHuffTab
            txa
            clc
            adc Lgz_tabpages
            sta Lgz_curHuffTab+1
            clc
            lda Lgz_curHuffTab
            adc #30
            sta Lgz_curHuffVals
            lda Lgz_curHuffTab+1
            adc #00 
            sta Lgz_curHuffVals+1
            rts


Lgz_set_codelenptr:
;##################
            lda #f0
            sta Lgz_codelens
            clc
            lda #01
            adc Lgz_tabpages
            sta Lgz_codelens+1
            rts


Lgz_set_tabpages:
;################
            sta Lgz_tabpages
            jsr Lgz_set_codelenptr
            lda #00
            sta Lgz_codes_loaded
            sta Lgz_codes_loaded+1
            lda #00
            sta Lgz_putwhat


            //jsr Lgz_clear_codelens
            //rts

Lgz_clear_codelens:
;##################
            ldy #8f
            lda #00
Lgz_clear_codelens_loop:
            sta (Lgz_codelens),y
            dey
            bne Lgz_clear_codelens_loop
            sta (Lgz_codelens),y
            rts

Lgz_count_codes:
;###############
            ldy #2f
            lda #00
Lgz_count_codes_loop1:
            sta (Lgz_curHuffTab),y
            dey
            bne Lgz_count_codes_loop1
            sta (Lgz_curHuffTab),y

            ldy #8f
            sty Lgz_count_codes_cnt
Lgz_count_codes_loop2:
            ldy Lgz_count_codes_cnt
            cpy #ff
            beq Lgz_count_codes_doneloop2
            lda (Lgz_codelens),y
            pha
            jsr Lgz_count_codes_docount
            pla
            ldy Lgz_count_codes_cnt
            cpy #80
            bcc Lgz_count_codes_not_nonlit1
            jsr Lgz_count_codes_dononlitcount
Lgz_count_codes_not_nonlit1:
            ldy Lgz_count_codes_cnt
            lda (Lgz_codelens),y
            lsr
            lsr
            lsr
            lsr
            pha
            jsr Lgz_count_codes_docount
            pla
            ldy Lgz_count_codes_cnt
            cpy #80
            bcc Lgz_count_codes_not_nonlit2
            jsr Lgz_count_codes_dononlitcount
Lgz_count_codes_not_nonlit2:
            dec Lgz_count_codes_cnt
            jmp Lgz_count_codes_loop2
Lgz_count_codes_doneloop2:
            rts

Lgz_count_codes_docount:
            and #0f           
            asl
            tay
            lda (Lgz_curHuffTab),y
            clc
            adc #01
            sta (Lgz_curHuffTab),y
            iny
            lda (Lgz_curHuffTab),y
            adc #00
            sta (Lgz_curHuffTab),y
            rts

Lgz_count_codes_dononlitcount:
            and #0f           
            clc
            adc #20
            tay
            lda (Lgz_curHuffTab),y
            clc
            adc #01
            sta (Lgz_curHuffTab),y
            rts

Lgz_push_single_code:
;####################
            ldx #00
            lda Lgz_push_codes_of_len_cnt
            sta (Lgz_curHuffVals,x)
            inc Lgz_curHuffVals
            bne Lgz_push_single_code_nz
            inc Lgz_curHuffVals+1
Lgz_push_single_code_nz:
            rts

Lgz_push_codes_of_len:
;#####################
            sta Lgz_push_codes_of_len_ref
            lda #0
            sta Lgz_push_codes_of_len_cnt
            tay
Lgz_push_codes_of_len_loop:
            lda (Lgz_codelens),y
            pha
            lsr
            lsr
            lsr
            lsr
            cmp Lgz_push_codes_of_len_ref
            bne Lgz_push_codes_of_len_next1
            jsr Lgz_push_single_code
Lgz_push_codes_of_len_next1:
            inc Lgz_push_codes_of_len_cnt
            pla
            and #0f
            cmp Lgz_push_codes_of_len_ref
            bne Lgz_push_codes_of_len_next2
            jsr Lgz_push_single_code
Lgz_push_codes_of_len_next2:
            inc Lgz_push_codes_of_len_cnt
            iny
            cpy #90
            bne Lgz_push_codes_of_len_loop
            rts


Lgz_collect_valcodes:
;####################
            lda #01
            sta Lgz_collect_valcode_tmp
Lgz_collect_valcodes_loop:
            jsr Lgz_push_codes_of_len
            ldx Lgz_collect_valcode_tmp
            inx
            stx Lgz_collect_valcode_tmp
            txa
            cpx #10
            bne Lgz_collect_valcodes_loop
            rts


Lgz_build_hufftab:
;################# 
            jsr Lgz_set_codelenptr
            jsr Lgz_count_codes
            jsr Lgz_collect_valcodes
            jmp Lgz_clear_codelens
            //rts




// take lencodes for initial huff code 

Lgz_take_lencode:
;################
            ldx Lgz_codes_loaded
            lda Lgz_hclenorder,x
            pha
            lsr
            tay
            pla
            and #01
            bne Lgz_take_lencode_skip1
            lda Lgz_indat
            asl
            asl
            asl
            asl
            jmp Lgz_take_lencode_skip2
Lgz_take_lencode_skip1:
            lda Lgz_indat
            and #0f
Lgz_take_lencode_skip2:
            ora (Lgz_codelens),y
            sta (Lgz_codelens),y
            ldx Lgz_codes_loaded
            inx
            stx Lgz_codes_loaded
            cpx Lgz_HCLEN
            bcs Lgz_take_lencode_final
            lda #05
            ldx #03
            jmp Lgz_expectbits
Lgz_take_lencode_final:
            jsr Lgz_set_hufftab_hufftab
            jsr Lgz_build_hufftab
            jsr Lgz_set_hufftab_hufftab
            jsr Lgz_initLookup
            lda #00
            sta Lgz_codes_loaded
            sta Lgz_codes_loaded+1
            sta Lgz_putwhat
            lda #46
            ldx #00
            jmp Lgz_expectbits


// take lencode for litlen+dist hufftabs

Lgz_put_lencode:
;###############
            lda Lgz_indat
            sta Lgz_lastput
            ldy #00
            lda Lgz_codes_loaded
            and #01
            bne Lgz_put_lencode_skip1
            lda Lgz_indat
            asl
            asl
            asl
            asl
            sta (Lgz_codelens),y
            jmp Lgz_put_lencode_skip2
Lgz_put_lencode_skip1:
            lda Lgz_indat
            and #0f
            ora (Lgz_codelens),y
            sta (Lgz_codelens),y
            inc Lgz_codelens
            bne Lgz_put_lencode_skip2
            inc Lgz_codelens+1
Lgz_put_lencode_skip2:
            inc Lgz_codes_loaded
            bne Lgz_put_lencode_skip3
            inc Lgz_codes_loaded+1

Lgz_put_lencode_skip3:
            lda Lgz_codes_loaded
            ldx Lgz_putwhat
            beq Lgz_put_lencode_for_hlit
            dex
            beq Lgz_put_lencode_for_hdist
Lgz_put_lencode_rts:
            rts

Lgz_put_lencode_for_hlit:
            cmp Lgz_HLIT
            bne Lgz_put_lencode_rts
            lda Lgz_codes_loaded+1
            cmp Lgz_HLIT+1
            bne Lgz_put_lencode_rts
            jsr Lgz_set_hufftab_litlen
Lgz_put_lencode_joint:
            jsr Lgz_build_hufftab
            inc Lgz_putwhat
            lda #00
            sta Lgz_codes_loaded
            sta Lgz_codes_loaded+1
            jsr Lgz_set_hufftab_hufftab
            rts
Lgz_put_lencode_for_hdist:
            cmp Lgz_HDIST
            bne Lgz_put_lencode_rts
            jsr Lgz_set_hufftab_dist
            jmp Lgz_put_lencode_joint

Lgz_put_rep_lencodes:
;####################
            lda Lgz_indat
            clc
            adc #03
            ldx Lgz_reptyp
            cpx #12
            bne Lgz_put_rep_lencodes_skip1
            clc
            adc #08
Lgz_put_rep_lencodes_skip1:
            sta Lgz_put_rep_lencodes_cnt
Lgz_put_rep_lencodes_loop:
            lda #0
            ldx Lgz_reptyp
            cpx #10
            bne Lgz_put_rep_lencodes_skip2
            lda Lgz_lastput
Lgz_put_rep_lencodes_skip2:
            sta Lgz_indat
            jsr Lgz_put_lencode
            dec Lgz_put_rep_lencodes_cnt
            bne Lgz_put_rep_lencodes_loop
            rts

Lgz_take_HLIT_lenval:
;####################
            jsr Lgz_put_rep_lencodes
            //jmp Lgz_take_HLIT_more

Lgz_take_HLIT_more:
;##################
            lda Lgz_putwhat
            cmp #02
            bcc Lgz_take_HLIT_more_else
            jsr Lgz_set_hufftab_litlen
            lda #47
            ldx #0
            jmp Lgz_expectbits
Lgz_take_HLIT_more_else:
            lda #46
            ldx #0
            jmp Lgz_expectbits


Lgz_take_HLIT_lencode:
;#####################
            jsr Lgz_lookup_hufftab
            bcc Lgz_take_HLIT_lencode_done
            lda Lgz_indat
            and #f0
            bne Lgz_take_HLIT_lencode_else
            jsr Lgz_put_lencode
            jmp Lgz_take_HLIT_more
Lgz_take_HLIT_lencode_else:
            lda Lgz_indat
            sta Lgz_reptyp
            sec
            sbc #10
            tax
            lda Lgz_take_HLIT_lencode_tab,x
            tax
            lda #06
            jmp Lgz_expectbits
Lgz_take_HLIT_lencode_done:
            //left out: if Lgz_bitcnt>=15 then Lgz_expectbits($49,0);
            rts
Lgz_take_HLIT_lencode_tab: .db 2,3,7


Lgz_take_complete_litlen:
;########################
            clc
            lda Lgz_indat
            adc Lgz_datalen
            sta Lgz_datalen
            lda Lgz_datalen+1
            adc #0
            sta Lgz_datalen+1
            jsr Lgz_set_hufftab_dist
            lda #48
            ldx #00
            jmp Lgz_expectbits


Lgz_handle_nonlit:
;#################
            lda #0
            sta Lgz_datalen
            sta Lgz_datalen+1
            lda Lgz_indat
            bne Lgz_handle_nonlit_nonzero
            lda Lgz_islast
            beq Lgz_handle_nonlit_zero_notlast
            lda #c0 
            sta Lgz_gzhstate
            lda #09
            ldx #0
            jmp Lgz_expectbits
Lgz_handle_nonlit_zero_notlast:
            lda #00
            ldx #01
            jmp Lgz_expectbits
Lgz_handle_nonlit_nonzero:
            lda Lgz_indat
            and #1f
            tax
            lda Lgz_datlentab,x
            sta Lgz_datalen
            cmp #0b
            bcs Lgz_handle_nonlit_extrabits
            lda Lgz_indat
            cmp #1d
            bne Lgz_handle_nonlit_not1d
            lda #1
            sta Lgz_datalen+1
Lgz_handle_nonlit_not1d:
            lda #0
            sta Lgz_indat
            jmp Lgz_take_complete_litlen
Lgz_handle_nonlit_extrabits:
            lda Lgz_indat
            sec
            sbc #05
            lsr
            lsr
            tax
            lda #07
            jmp Lgz_expectbits






Lgz_take_litlen:
;###############
            jsr Lgz_lookup_hufftab
            bcc Lgz_take_litlen_notfound
            lda Lgz_indat+1
            bne Lgz_handle_nonlit
            lda Lgz_indat
            jsr Lgz_put_databyte
            jsr Lgz_initLookup
            lda #47
            ldx #0
            jmp Lgz_expectbits
Lgz_take_litlen_notfound:
            //missing: if Lgz_bitcnt>=15 then Lgz_expectbits($49,0);
            rts


Lgz_take_complete_litdist:
;#########################
            clc
            lda Lgz_indat
            adc Lgz_datadist
            sta Lgz_datadist
            lda Lgz_indat+1
            adc Lgz_datadist+1
            sta Lgz_datadist+1
Lgz_take_complete_litdist_loop:
            jsr Lgz_datapeek
            jsr Lgz_put_databyte
            dec Lgz_datalen
            bne Lgz_take_complete_litdist_loop
            lda Lgz_datalen
            beq Lgz_take_complete_litdist_doneloop
            dec Lgz_datalen+1
            jmp Lgz_take_complete_litdist_loop
Lgz_take_complete_litdist_doneloop:
            jsr Lgz_set_hufftab_litlen
            lda #47
            ldx #0
            jmp Lgz_expectbits

Lgz_take_litdist:
;################
            jsr Lgz_lookup_hufftab
            bcc Lgz_take_litdist_notfound
            lda Lgz_indat
            and #1f
            asl
            tax
            lda Lgz_datdisttab,x
            sta Lgz_datadist
            inx
            lda Lgz_datdisttab,x
            sta Lgz_datadist+1
            lda Lgz_indat+1
            bne Lgz_take_litdist_extrabits
            lda Lgz_indat
            cmp #04
            bcs Lgz_take_litdist_extrabits
            lda #00
            sta Lgz_indat
            sta Lgz_indat+1
            jmp Lgz_take_complete_litdist
Lgz_take_litdist_extrabits:
            lda Lgz_indat
            sec
            sbc #02
            lsr
            tax
            lda #08
            jmp Lgz_expectbits
Lgz_take_litdist_notfound:
            //missing: if Lgz_bitcnt>=15 then Lgz_expectbits($49,0);
            rts


Lgz_take_databit:
;################
            tax
            lda #40
            bit Lgz_dattyp
            bne Lgz_take_databit_huffshift
            txa
            beq Lgz_take_databit_skipor
            lda Lgz_inmsk
            ora Lgz_indat
            sta Lgz_indat
            lda Lgz_inmsk+1
            ora Lgz_indat+1
            sta Lgz_indat+1
Lgz_take_databit_skipor:
            asl Lgz_inmsk
            rol Lgz_inmsk+1
            dec Lgz_bitcnt
            bne Lgz_take_databit_rts
            lda Lgz_dattyp
Lgz_take_databit_joint:
            asl
            tax
            lda Lgz_take_databit_tab0,x
            sta Lgz_take_databit_jmp+1
            lda Lgz_take_databit_tab0+1,x
            sta Lgz_take_databit_jmp+2
Lgz_take_databit_jmp:
            jmp Lgz_take_databit_rts
 
           
Lgz_take_databit_rts:
            rts

Lgz_take_databit_huffshift:
            lda Lgz_bitcnt
            cmp #10
            beq Lgz_take_databit_rts
            inc Lgz_bitcnt
            txa
            lsr
            rol Lgz_indat
            rol Lgz_indat+1
            lda Lgz_dattyp
            sec
            sbc #46-0a
            jmp Lgz_take_databit_joint
//            asl
//            tax
//            lda Lgz_take_databit_tab40,x
//            sta Lgz_take_databit_hjmp+1
//            lda Lgz_take_databit_tab40+1,x
//            sta Lgz_take_databit_hjmp+2
//Lgz_take_databit_hjmp:
//            jmp Lgz_take_databit_jmp


Lgz_prepare_default_tabs:
;########################

            jsr Lgz_set_codelenptr

            ldx #8f
            ldy #00

            lda #88
Lgz_prepare_default_tabs_l1:
            sta (Lgz_codelens),y
            dex
            cpy #8b
            bne Lgz_prepare_default_tabs_l1

            lda #77
Lgz_prepare_default_tabs_l2:
            sta (Lgz_codelens),y
            dex
            cpy #7f
            bne Lgz_prepare_default_tabs_l2

            lda #99
Lgz_prepare_default_tabs_l3:
            sta (Lgz_codelens),y
            dex
            cpy #47
            bne Lgz_prepare_default_tabs_l3

            lda #88
Lgz_prepare_default_tabs_l4:
            sta (Lgz_codelens),y
            dex
            cpy #ff
            bne Lgz_prepare_default_tabs_l4

            jsr Lgz_set_hufftab_litlen
            jsr Lgz_build_hufftab

            lda #55
            ldy #00
            ldx #0f
Lgz_prepare_default_tabs_l5:
            sta (Lgz_codelens),y
            dex
            cpx #ff
            bne Lgz_prepare_default_tabs_l5

            jsr Lgz_set_hufftab_dist
            jsr Lgz_build_hufftab
            jsr Lgz_set_hufftab_litlen

            rts

Lgz_init:
;########
;### init gz processing
;### A: mode $00: bare inflate, $80: gunzip
;### X: first page (high byte) of 640 byte tmp RAM used for huff tables
            sta Lgz_gzhstate
            txa
            jsr Lgz_set_tabpages
            lda #00
            ldx #01
            jsr Lgz_expectbits
            lda #0
            sta Lgz_take_headbytecnt
            rts




Lgz_take_databit_tab0: .db 
Lgz_take_BFINAL,,Lgz_take_BTYPE,,Lgz_take_HLIT,,Lgz_take_HDIST,,Lgz_take_HCLEN,,Lgz_take_lencode,,Lgz_take_HLIT_lenval,,Lgz_take_complete_litlen,,Lgz_take_complete_litdist,,Lgz_take_databit_rts,
Lgz_take_databit_tab40: .db 
Lgz_take_HLIT_lencode,,Lgz_take_litlen,,Lgz_take_litdist,
Lgz_hclenorder: .db 10, 11, 12, 00, 08, 07, 09, 06, 0a, 05, 0b, 04, 0c, 
03, 0d, 02, 0e, 01, 0f
Lgz_datdisttab: .db 1,,2,,3,,4,,5,,7,,9,,d,,
11,,19,,21,,31,,41,,61,,81,,c1,,101,,181,,201,,301,,401,,601,,801,,c01,,1001,,1801,,2001,,3001,,4001,,6001,
Lgz_datlentab: .db 0,3,4,5,6,7,8,9,a,b,d,f,11,13,17,1b,1f,23,2b,33,3b,
43,53,63,73,73,a3,c3,e3,02

Lgz_put_databyte:
;################
            jmp Lgz_default_put_databyte

Lgz_datapeek:
;############
            jmp Lgz_default_datapeek

// keep these 5 bytes in order...
Lgz_takebyte_bitmode: .db 0
Lgz_takebyte_bitdat: .db 0
Lgz_takebyte_bitcnt: .db 0
Lgz_takebyte_bitneg: .db 0,0



Lgz_inflate_byte:
;################
;apply inflate decoding to a byte
 
            ldx Lgz_takebyte_bitmode
            beq Lgz_byt2bitstream
            cpx #05
            beq Lgz_put_direct_byte
            dex
            sta Lgz_takebyte_bitdat,x
            inc Lgz_takebyte_bitmode
            rts
Lgz_put_direct_byte:
            jsr Lgz_put_databyte
            dec Lgz_takebyte_bitdat
            bne Lgz_takebyte_rts
            dec Lgz_takebyte_bitcnt
            bne Lgz_takebyte_rts
            lda #00
            sta Lgz_takebyte_bitmode
Lgz_takebyte_rts:
            rts

Lgz_byt2bitstream:
            sta Lgz_takebyte_bitdat
            lda #8
            sta Lgz_takebyte_bitcnt

Lgz_takebyte_loop:
            ror Lgz_takebyte_bitdat
            lda #0
            adc #0
            jsr Lgz_take_databit
            dec Lgz_takebyte_bitcnt
            bne Lgz_takebyte_loop
            rts


Lgz_inflate_end:
;###############
;end of mandatory part in case only bare deflate-inflating without gz 
file handling is required
;






Lgz_take_headbyte0:
            cmp #1f
            bne Lgz_take_errheadbyte
            beq Lgz_take_doneheadbyte
Lgz_take_headbyte1:
            cmp #8b
            bne Lgz_take_errheadbyte
            beq Lgz_take_doneheadbyte
Lgz_take_headbyte2:
            cmp #08
            bne Lgz_take_errheadbyte
            beq Lgz_take_doneheadbyte
Lgz_take_headbyte3:
            sta Lgz_take_headbyteflgs
            jmp Lgz_take_doneheadbyte
Lgz_take_errheadbyte:
            lda #81
            sta Lgz_gzhstate
Lgz_take_err_rts:
            rts


Lgz_take_gz_byte:
;################
;take a byte from gz file 

            ldy Lgz_gzhstate // 00:bitdata, 80: gz-head, 81:gz-trail, 
01..7f:remaining flags  
            beq Lgz_inflate_byte
            ;bne Lgz_take_gz_byte_nobit

Lgz_take_gz_byte_nobit:
            tax
            cpy #80
            beq Lgz_take_headbyte
Lgz_take_gz_byte_nohead:
            tya
            and #04
            bne Lgz_take_extrabyte
Lgz_take_gz_byte_noextra:
            tya
            and #18
            bne Lgz_take_string
Lgz_take_gz_byte_nostring:
            tya
            and #02
            bne Lgz_take_crc16

Lgz_trail:  jmp Lgz_take_err_rts
;#########




Lgz_take_headbyte:
;#################
; analyse 1 byte of gz file head

            ldx Lgz_take_headbytecnt
            beq Lgz_take_headbyte0
            dex
            beq Lgz_take_headbyte1
            dex
            beq Lgz_take_headbyte2
            dex
            beq Lgz_take_headbyte3
Lgz_take_doneheadbyte:
            ldx Lgz_take_headbytecnt
            inx
            stx Lgz_take_headbytecnt 
            cpx #0a
            bne Lgz_take_doneheadbyte2
Lgz_take_head_decide_next:
            lda #0
            sta Lgz_take_headbytecnt
            lda Lgz_take_headbyteflgs
            sta Lgz_gzhstate
Lgz_take_doneheadbyte2:
            rts

Lgz_take_extrabyte:
            txa
            ldx Lgz_take_headbytecnt
            cpx #02
            bcs Lgz_take_extrabyte2p
            sta Lgz_take_extrabytecnt,x
            inx
            stx Lgz_take_headbytecnt
            cpx #02
            beq Lgz_take_extrabyte_testdone
Lgz_take_extrabyte_done:
            rts
Lgz_take_extrabyte2p:
            dec Lgz_take_extrabytecnt
            bne Lgz_take_extrabyte_done
            dec Lgz_take_extrabytecnt+1
Lgz_take_extrabyte_testdone:
            lda Lgz_take_extrabytecnt
            bne Lgz_take_extrabyte_done
            lda Lgz_take_extrabytecnt+1
            bne Lgz_take_extrabyte_done
            lda Lgz_take_headbyteflgs
            and #fb
            sta Lgz_take_headbyteflgs
            jmp Lgz_take_head_decide_next

Lgz_take_string:
            txa
            cmp #0
            bne Lgz_take_extrabyte_done
            lda Lgz_take_headbyteflgs
            tax
            and #08
            beq Lgz_take_string_was_cmt
            txa
            and #f7
Lgz_take_string_was_any:
            sta Lgz_take_headbyteflgs
            jmp Lgz_take_head_decide_next
Lgz_take_string_was_cmt:
            txa
            and #ef
            jmp Lgz_take_string_was_any


Lgz_take_crc16:
            txa
            ldx Lgz_take_headbytecnt
            inx
            stx Lgz_take_headbytecnt
            cpx #02
            bne Lgz_take_extrabyte_done
            lda Lgz_take_headbyteflgs
            and #fd
            jmp Lgz_take_string_was_any



Lgz_mandatory_end:
;end of manadtory module file contents (assuming gz-file handling is 
required)







.section 0,optional helpers

Lgz_optional_helpers_start:
;if app code installs different handlers,
;this code could be left out of the module file

Lgz_default_put_databyte:
            ldy #0
            sta (Lgz_dstptr),y
            inc Lgz_dstptr
            bne Lgz_put_databyte_rts
            inc Lgz_dstptr+1
Lgz_put_databyte_rts:
            rts

Lgz_default_datapeek:
            sec
            lda Lgz_dstptr
            sbc Lgz_datadist
            sta Lgz_datapeek_load+1
            lda Lgz_dstptr+1
            sbc Lgz_datadist+1
            sta Lgz_datapeek_load+2
Lgz_datapeek_load:
            lda $1234
            rts

Lgz_optional_helpers_end:




.section 0,global_vars

Lgz_global_vars_start:
; these vars, just like the ZP-vars don't need special initialization,
; so could be left out of the module-file 

Lgz_HLIT:   .db 0,0 // 4 refs
Lgz_HDIST:  .db 0 // 2 refs
Lgz_HCLEN:  .db 0 // 2 refs
Lgz_islast: .db 0 // 2 refs
Lgz_tabpages: .db 0 // 3 refs
Lgz_gzhstate: .db 0 // byte, 5 refs
Lgz_push_codes_of_len_cnt:   .db 0 // 4 refs
Lgz_push_codes_of_len_ref:   .db 0 // 3 refs
Lgz_collect_valcode_tmp: .db 0 // 3 refs
Lgz_lastput: .db 0 // 2 refs
Lgz_reptyp: .db 0 // 3 refs
Lgz_put_rep_lencodes_cnt: .db 0 // 2 refs
Lgz_take_extrabytecnt: .db 0,0 // word, 5 refs

Lgz_global_vars_end:


.section 2,gzmodule
Lgzmodule_start:
  .copy Lgz_start,Lgz_mandatory_end
;  .copy Lgz_start,Lgz_inflate_end
Lgzmodule_optionalcode:
  .copy Lgz_optional_helpers_start,Lgz_optional_helpers_end
Lgzmodule_globals:
  .copy Lgz_global_vars_start,Lgz_global_vars_end
Lgzmodule_end:

Lgzmodule_start=c000
;Lgzmodule_end=e000
Lgz_start=Lgzmodule_start
Lgz_optional_helpers_start=Lgzmodule_optionalcode
Lgz_global_vars_start=Lgzmodule_globals

Back to de.comp.lang.assembler | Previous | NextNext in thread | Find similar


Thread

6502 gunzip Jan Bruns <ebay@abnuto.de> - 2020-10-21 05:05 +0000
  Re: 6502 gunzip Jan Bruns <ebay@abnuto.de> - 2020-10-21 10:23 +0000
  Re: 6502 gunzip Jens Kallup <kallup.jens@web.de> - 2020-10-21 16:59 +0200
    Re: 6502 gunzip Jan Bruns <ebay@abnuto.de> - 2020-10-22 12:55 +0000

csiph-web