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