Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

6502 gunzip

1 view
Skip to first unread message

Jan Bruns

unread,
Oct 21, 2020, 1:05:10 AM10/21/20
to
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


Jan Bruns

unread,
Oct 21, 2020, 6:23:25 AM10/21/20
to

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

Es war noch ein offensichtlicher bug in Lgz_prepare_default_tabs.

Ich habe grad nochmal überdacht, ob man Lgz_take_lencode (also das Ding,
das diese "(HCLEN + 4) x 3 bits" [Zitat RFC 1951] entgegen nimmt) nicht
irgendwie so gestalten kann, daß es die Daten erstmal irgendwo
zwischenspeichert, und hinterher erst alles in einem Rutsch über
Lgz_put_lencode läuft, wie bei den andren Tabellen auch.

Scheint aber eher schlechter zu sein:

Lgz_init_initial_codelen: // irgendwo in BTYPE, oder so
lda Lgz_tabpages
sta Lgz_save_initial_codelen_point+2
sta Lgz_init_initial_codelen_loop+2
sta Lgz_copy_initial_codelens_loop+2
ldx #12
lda #00
Lgz_init_initial_codelen_loop:
sta ff00,x
dex
bpl Lgz_init_initial_codelen_loop
rts




Lgz_save_initial_codelen: // statt Lgz_take_lencode
ldx Lgz_codes_loaded
ldy Lgz_hclenorder,x
lda Lgz_indat
Lgz_save_initial_codelen_point:
sta ff00,y
inc Lgz_codes_loaded
lda Lgz_codes_loaded
cmp Lgz_HCLEN
bcs Lgz_copy_initial_codelens
lda #05
ldx #03
jmp Lgz_expectbits
Lgz_copy_initial_codelens:
ldx #00
stx Lgz_codes_loaded
stx Lgz_copy_initial_codelens_loop+1
dex
stx Lgz_putwhat
Lgz_copy_initial_codelens_loop:
lda ff00
sta Lgz_indat
jsr Lgz_put_lencode
inc Lgz_copy_initial_codelens_loop+1
lda Lgz_copy_initial_codelens_loop+1
cmp #13
bne Lgz_copy_initial_codelens_loop
Lgz_take_lencode_final: // wie bei Lgz_take_lencode
...


Mag aber sein, daß das mit kompakterem, kompletten Zerofill bei der
Initialisierung noch anderswo wieder was spart, und dann doch besser oder
zumindest geringfügig kürzer ist. Ich weiss es nicht.

Gruss

Jan Bruns

Jens Kallup

unread,
Oct 21, 2020, 10:59:52 AM10/21/20
to
Am 21.10.2020 um 07:05 schrieb Jan Bruns:
> Ich glaube, da hat die Welt drauf gewartet, nicht?
> Nur deshalb ging's nicht voran.

hihi,

macht das einer mit C64 ?

Jens

Jan Bruns

unread,
Oct 22, 2020, 8:55:24 AM10/22/20
to

Jens Kallup:
Ach komm, so viel besser ist der PC auch gar nicht.

Die vorgestellte Routine kann so grob etwa 500 komprimierte Bytes pro s
entpacken, bräuchte also für 1MB vllt. sowas wie eine halbe Std.

Solange brauche ich am PC zuweilen auch in Zusammenhang mit
Dekomprimierung irgendwelcher (etwas grösserer) Dateien, bsds. wenn ich
mir dann auch noch ein Skript oder sowas überlegen muss, um bspw.
zusätzlich nochmal einzeln gepackte Dateien in Unterverzeichnissen
loszuwerden. Dann lahmt wahrscheinlich noch entweder der USB-Stick
selbst, oder aber die USB Verbindung, und alle sowas.

Gruss

Jan Bruns

0 new messages