1
0
mirror of https://github.com/pfusik/zlib6502.git synced 2024-06-08 13:29:27 +00:00

Optimize size and speed.

This commit is contained in:
Piotr Fusik 2007-06-17 15:18:50 +02:00
parent 35cc87a05c
commit a9c38e537e

View File

@ -1,535 +1,453 @@
zpage equ $f0 ; 11 bytes ; inflate - uncompress data stored in the DEFLATE format
inflate equ $8000 ; by Piotr Fusik <fox@scene.pl>
; Last modified: 2007-06-17
* 'Inflate' ; Compile with xasm (http://xasm.atari.org/), for example:
; Uncompress data stored in the DEFLATE format. ; xasm inflate.asx /l /d:inflate=$b700 /d:inflate_data=$b900 /d:inflate_zp=$f0
; ; inflate is 509 bytes of code and initialized data
; DEFLATE is a popular compression format, used e.g. in ZIP and GZIP archives, ; inflate_data is 764 bytes of uninitialized data
; and the ZLIB library. The original description of this format ; inflate_zp is 10 bytes on page zero
; is available in RFC (Request for Comments) 1951 in the file
; ftp://www.ietf.org/rfc/rfc1951.txt.
; Both compressed and uncompressed data must completely fit in the memory.
; As the compressed data is read sequentially and only once, it is possible
; for the compressed and uncompressed data to overlap, i.e. the data being
; uncompressed can be stored in place of some compressed data which has been
; already read. There is no general rule, but practically both data may
; overlap almost entirely, with the uncompressed data ending just a few
; bytes before the end of the compressed data.
; If you want to modify this code to support non-continuous memory areas
; for the output, you should note that the uncompressed data is used as
; a look-behind buffer, up to 32K.
; As the code is not self-modifying, it can be put in ROM.
; This source code is written in the 6502 assembly language,
; using syntax of xasm (http://xasm.atari.org).
; The one-character comments I use are:
; '!' branch always
; '-' C flag is zero (useful for adc)
; '+' C flag is set (useful for sbc)
; At the end of this file you can find source code of a simple C program
; that performs DEFLATE compression using the popular ZLIB library.
;
; Permission is granted to anyone to use this code for any purpose, including
; commercial applications, and redistribute it freely in its original form.
;
; Author: Piotr Fusik <fox@scene.pl>
; Last modified: 11 Oct 2003
* Constants ; Pointer to compressed data
inputPointer equ inflate_zp ; 2 bytes
; Whether to support the new DEFLATE64, introduced as the compression method 9 ; Pointer to uncompressed data
; in PKZIP 4.0, released Nov 2000. This format is very uncommon (not even outputPointer equ inflate_zp+2 ; 2 bytes
; supported by ZLIB) and doesn't seem to be useful on 6502 systems, since
; the main change is the 64K look-behind buffer. It's here just for fun! :-)
USE_DEFLATE64 equ 0
; Maximum length of a Huffman code. ; Local variables
MAX_BITS equ 15
; All Huffman trees are stored in the bitsCount, bitsPointer_l getBit_buffer equ inflate_zp+4 ; 1 byte
; and bitsPointer_h arrays. There may be two trees: the literal/length tree
; and the distance tree, or just one - the temporary tree.
; Index in the mentioned arrays for the beginning of the literal/length tree getBits_base equ inflate_zp+5 ; 1 byte
; or the temporary tree. inflateStoredBlock_pageCounter equ inflate_zp+5 ; 1 byte
PRIMARY_TREE equ 0
; Index in the mentioned arrays for the beginning of the distance tree. inflateCodes_sourcePointer equ inflate_zp+6 ; 2 bytes
DISTANCE_TREE equ MAX_BITS inflateDynamicBlock_lengthIndex equ inflate_zp+6 ; 1 byte
inflateDynamicBlock_lastLength equ inflate_zp+7 ; 1 byte
inflateDynamicBlock_tempCodes equ inflate_zp+7 ; 1 byte
; Size of each array. inflateCodes_lengthMinus2 equ inflate_zp+8 ; 1 byte
TREES_SIZE equ 2*MAX_BITS inflateDynamicBlock_allCodes equ inflate_zp+8 ; 1 byte
inflateCodes_primaryCodes equ inflate_zp+9 ; 1 byte
* Page zero ; Argument values for getBits
GET_1_BIT equ $81
GET_2_BITS equ $82
GET_3_BITS equ $84
GET_4_BITS equ $88
GET_5_BITS equ $90
GET_6_BITS equ $a0
GET_7_BITS equ $c0
; (public) Pointer to the compressed data. ; Maximum length of a Huffman code
inputPointer equ zpage ; 2 bytes MAX_CODE_LENGTH equ 15
; (public) Pointer to the uncompressed data. ; Huffman trees
outputPointer equ zpage+2 ; 2 bytes TREE_SIZE equ MAX_CODE_LENGTH+1
PRIMARY_TREE equ 0
DISTANCE_TREE equ TREE_SIZE
; Local variables. ; Alphabet
; As far as there is no conflict, same memory locations are used LENGTH_SYMBOLS equ 1+29+2
; for different variables. DISTANCE_SYMBOLS equ 30
CONTROL_SYMBOLS equ LENGTH_SYMBOLS+DISTANCE_SYMBOLS
inflateDynamicBlock_cnt equ zpage+4 ; 1 byte TOTAL_SYMBOLS equ 256+CONTROL_SYMBOLS
inflateCodes_src equ zpage+4 ; 2 bytes
buildHuffmanTree_src equ zpage+4 ; 2 bytes
getNextLength_last equ zpage+4 ; 1 byte
getNextLength_index equ zpage+5 ; 1 byte
buildHuffmanTree_ptr equ zpage+6 ; 2 bytes
fetchCode_ptr equ zpage+6 ; 2 bytes
getBits_tmp equ zpage+6 ; 1 byte
moveBlock_len equ zpage+8 ; 2 bytes
inflateDynamicBlock_np equ zpage+8 ; 1 byte
inflateDynamicBlock_nd equ zpage+9 ; 1 byte
getBit_hold equ zpage+10 ; 1 byte
* Code ; Uncompress DEFLATE stream starting from the address stored in inputPointer
; to the memory starting from the address stored in outputPointer
org inflate org inflate
mvy #0 getBit_buffer
* (public) inflate inflate_blockLoop
; Decompress the DEFLATE data starting from the address stored in inputPointer
; to the memory starting from the address stored in outputPointer.
mvy #1 getBit_hold
bne inflate_2 !
inflate_1
jsr inflate_3
inflate_2
; Get a bit of EOF and two bits of block type ; Get a bit of EOF and two bits of block type
ldx #3 ; ldy #0
lda #0 sty getBits_base
lda #GET_3_BITS
jsr getBits jsr getBits
lsr @ lsr @
bcc inflate_1 php
inflate_3 tax
lsr @ bne inflateCompressedBlock
bne inflateDynamicBlock
; Note: inflateDynamicBlock may assume that A = 1
bcs inflateFixedBlock
; Note: inflateCopyBlock may assume that C = 0
* inflateCopyBlock ; Copy uncompressed block
; Decompress a 'stored' data block. ; ldy #0
inflateCopyBlock sty getBit_buffer
; Ignore bits until byte boundary jsr getWord
mvy #1 getBit_hold jsr getWord
; Get 16-bit length sta inflateStoredBlock_pageCounter
ldx #inputPointer ; jmp inflateStoredBlock_firstByte
mva (0,x) moveBlock_len bcs inflateStoredBlock_firstByte
mva (inputPointer),y moveBlock_len+1 inflateStoredBlock_copyByte
; Skip the length and one's complement of it jsr getByte
lda #4 inflateStoreByte
adc:sta inputPointer - jsr storeByte
scc:inc inputPointer+1 bcc inflateCodes_loop
inflateStoredBlock_firstByte
inx
bne inflateStoredBlock_copyByte
inc inflateStoredBlock_pageCounter
bne inflateStoredBlock_copyByte
* moveBlock inflate_nextBlock
; Copy block of length moveBlock_len from (0,x) to the output. plp
moveBlock bcc inflate_blockLoop
ldy moveBlock_len
beq moveBlock_1
ldy #0
inc moveBlock_len+1
moveBlock_1
mva (0,x) (outputPointer),y
inw 0,x
inw outputPointer
dec moveBlock_len
bne moveBlock_1
dec moveBlock_len+1
bne moveBlock_1
rts rts
* inflateFixedBlock inflateCompressedBlock
; Decompress a Huffman-coded data block with default Huffman trees
; (defined by the DEFLATE format):
; literalCodeLength :144 dta 8
; :112 dta 9
; endCodeLength dta 7
; lengthCodeLength :23 dta 7
; :6 dta 8
; distanceCodeLength :30+2*USE_DEFLATE64 dta 5+DISTANCE_TREE
; :2 dta 8
; (two 8-bit codes from the primary tree are not used).
inflateFixedBlock
ldx #159+USE_DEFLATE64
stx distanceCodeLength+32+2*USE_DEFLATE64
lda #8
inflateFixedBlock_1
sta literalCodeLength-1,x
sta literalCodeLength+159+USE_DEFLATE64-1,x-
bne inflateFixedBlock_1
ldx #112
inc:rne literalCodeLength+144-1,x-
ldx #24
dec:rne endCodeLength-1,x-
ldx #30+2*USE_DEFLATE64
lda #5+DISTANCE_TREE
sta:rne distanceCodeLength-1,x-
beq inflateCodes !
* inflateDynamicBlock ; Decompress a block with fixed Huffman trees:
; Decompress a Huffman-coded data block, reading Huffman trees first. ; :144 dta 8
inflateDynamicBlock ; :112 dta 9
; numberOfPrimaryCodes = 257 + getBits(5) ; :24 dta 7
ldx #5 ; :6 dta 8
; lda #1 ; :2 dta 8 ; codes with no meaning
jsr getBits ; :30 dta 5+DISTANCE_TREE
sta inflateDynamicBlock_np ; ldy #0
; numberOfDistanceCodes = 1 + getBits(5) inflateFixedBlock_setCodeLengths
ldx #5 lda #4
lda #1+29+1 cpy #144
jsr getBits rol @
sta inflateDynamicBlock_nd sta literalSymbolCodeLength,y
; numberOfTemporaryCodes = 4 + getBits(4) cpy #CONTROL_SYMBOLS
lda:tax #4 bcs inflateFixedBlock_noControlSymbol
jsr getBits lda #5+DISTANCE_TREE
sta inflateDynamicBlock_cnt cpy #LENGTH_SYMBOLS
; Get lengths of temporary codes in the order stored in tempCodeLengthOrder bcs inflateFixedBlock_setControlCodeLength
txa:tay #0 cpy #24
inflateDynamicBlock_1 adc #2-DISTANCE_TREE
ldx #3 ; A = 0 inflateFixedBlock_setControlCodeLength
jsr getBits ; does not change Y sta controlSymbolCodeLength,y
inflateDynamicBlock_2 inflateFixedBlock_noControlSymbol
ldx tempCodeLengthOrder,y
sta literalCodeLength,x
lda #0
iny iny
cpy inflateDynamicBlock_cnt bne inflateFixedBlock_setCodeLengths
bcc inflateDynamicBlock_1 mva #LENGTH_SYMBOLS inflateCodes_primaryCodes
cpy #19
bcc inflateDynamicBlock_2 dex
ror literalCodeLength+19 + beq inflateCodes
; Decompress a block reading Huffman trees first
; Build the tree for temporary codes ; Build the tree for temporary codes
jsr buildHuffmanTree jsr buildTempHuffmanTree
; Use temporary codes to get lengths of literal/length and distance codes ; Use temporary codes to get lengths of literal/length and distance codes
ldx #0 ldx #0
ldy #1 ; sec
stx getNextLength_last inflateDynamicBlock_decodeLength
inflateDynamicBlock_3
jsr getNextLength
sta literalCodeLength,x+
bne inflateDynamicBlock_3
inflateDynamicBlock_4
jsr getNextLength
inflateDynamicBlock_5
sta endCodeLength,x+
cpx inflateDynamicBlock_np
bcc inflateDynamicBlock_4
lda #0
cpx #1+29
bcc inflateDynamicBlock_5
inflateDynamicBlock_6
jsr getNextLength
cmp #0
seq:adc #DISTANCE_TREE-1 +
sta endCodeLength,x+
cpx inflateDynamicBlock_nd
bcc inflateDynamicBlock_6
ror endCodeLength,x +
* inflateCodes
; Decompress a data block using given Huffman trees.
inflateCodes
jsr buildHuffmanTree
inflateCodes_1
jsr fetchPrimaryCode
bcs inflateCodes_2
; Literal code
sta (outputPointer),0
inc outputPointer
bne inflateCodes_1
inc outputPointer+1
bcc inflateCodes_1 !
; End of block
inflateCodes_ret
rts
inflateCodes_2
beq inflateCodes_ret
; Restore a block from the look-behind buffer
jsr getValue
sta moveBlock_len
tya
jsr getBits
sta moveBlock_len+1
ldx #DISTANCE_TREE
jsr fetchCode
jsr getValue
sec
eor #$ff
adc outputPointer
sta inflateCodes_src
php php
tya stx inflateDynamicBlock_lengthIndex
jsr getBits
plp
eor #$ff
adc outputPointer+1
sta inflateCodes_src+1
ldx #inflateCodes_src
jsr moveBlock
beq inflateCodes_1 !
* buildHuffmanTree
; Build Huffman trees basing on code lengths (in bits)
; stored in the *CodeLength arrays.
; A byte with its highest bit set marks the end.
buildHuffmanTree
mwa #literalCodeLength buildHuffmanTree_src
; Clear bitsCount and bitsPointer_l
ldy #2*TREES_SIZE+1
lda #0
sta:rne bitsCount-1,y-
beq buildHuffmanTree_3 !
; Count number of codes of each length
buildHuffmanTree_2
tax
inc bitsPointer_l,x
iny
bne buildHuffmanTree_3
inc buildHuffmanTree_src+1
buildHuffmanTree_3
lda (buildHuffmanTree_src),y
bpl buildHuffmanTree_2
; Calculate a pointer for each length
ldx #0
lda #<sortedCodes
ldy #>sortedCodes
clc
buildHuffmanTree_4
sta bitsPointer_l,x
tya:sta bitsPointer_h,x
lda bitsPointer_l+1,x
adc bitsPointer_l,x -
scc:iny
inx
cpx #TREES_SIZE
bcc buildHuffmanTree_4
mva #>literalCodeLength buildHuffmanTree_src+1
ldy #0
bcs buildHuffmanTree_9 !
; Put codes into their place in the sorted array
buildHuffmanTree_6
beq buildHuffmanTree_7
tax
mva bitsPointer_l-1,x buildHuffmanTree_ptr
mva bitsPointer_h-1,x buildHuffmanTree_ptr+1
tya
ldy:inc bitsCount-1,x
sta (buildHuffmanTree_ptr),y
tay
buildHuffmanTree_7
iny
bne buildHuffmanTree_9
inc buildHuffmanTree_src+1
ldx #MAX_BITS-1
mva:rpl bitsCount,x literalCount,x-
buildHuffmanTree_9
lda (buildHuffmanTree_src),y
bpl buildHuffmanTree_6
rts
* getNextLength
; Decode next code length using temporary codes.
getNextLength
stx getNextLength_index
dey
bne getNextLength_1
; Fetch a temporary code ; Fetch a temporary code
jsr fetchPrimaryCode jsr fetchPrimaryCode
; Temporary code 0..15: put this length ; Temporary code 0..15: put this length
ldy #1 tax
cmp #16 bpl inflateDynamicBlock_verbatimLength
bcc getNextLength_2
; Temporary code 16: repeat last length 3 + getBits(2) times ; Temporary code 16: repeat last length 3 + getBits(2) times
; Temporary code 17: put zero length 3 + getBits(3) times ; Temporary code 17: put zero length 3 + getBits(3) times
; Temporary code 18: put zero length 11 + getBits(7) times ; Temporary code 18: put zero length 11 + getBits(7) times
tay
ldx tempExtraBits-16,y
lda tempBaseValue-16,y
jsr getBits jsr getBits
cpy #17 ; sec
adc #1
cpx #GET_7_BITS
scc:adc #7
tay tay
txa #0 lda #0
bcs getNextLength_2 cpx #GET_3_BITS
getNextLength_1 scs:lda inflateDynamicBlock_lastLength
lda getNextLength_last inflateDynamicBlock_verbatimLength
getNextLength_2 iny
sta getNextLength_last ldx inflateDynamicBlock_lengthIndex
ldx getNextLength_index plp
inflateDynamicBlock_storeLength
bcc inflateDynamicBlock_controlSymbolCodeLength
sta literalSymbolCodeLength,x+
cpx #1
inflateDynamicBlock_storeNext
dey
bne inflateDynamicBlock_storeLength
sta inflateDynamicBlock_lastLength
; jmp inflateDynamicBlock_decodeLength
beq inflateDynamicBlock_decodeLength
inflateDynamicBlock_controlSymbolCodeLength
cpx inflateCodes_primaryCodes
scc:ora #DISTANCE_TREE
sta controlSymbolCodeLength,x+
cpx inflateDynamicBlock_allCodes
bcc inflateDynamicBlock_storeNext
dey
; ldy #0
; jmp inflateCodes
; Decompress a block
inflateCodes
jsr buildHuffmanTree
inflateCodes_loop
jsr fetchPrimaryCode
bcc inflateStoreByte
tax
beq inflate_nextBlock
; Copy sequence from look-behind buffer
; ldy #0
sty getBits_base
cmp #9
bcc inflateCodes_setSequenceLength
tya
; lda #0
cpx #1+28
bcs inflateCodes_setSequenceLength
dex
txa
lsr @
ror getBits_base
inc getBits_base
lsr @
rol getBits_base
jsr getAMinus1BitsMax8
; sec
adc #0
inflateCodes_setSequenceLength
sta inflateCodes_lengthMinus2
ldx #DISTANCE_TREE
jsr fetchCode
; sec
sbc inflateCodes_primaryCodes
tax
cmp #4
bcc inflateCodes_setOffsetLowByte
inc getBits_base
lsr @
jsr getAMinus1BitsMax8
inflateCodes_setOffsetLowByte
eor #$ff
sta inflateCodes_sourcePointer
lda getBits_base
cpx #10
bcc inflateCodes_setOffsetHighByte
lda getNPlus1Bits_mask-10,x
jsr getBits
clc
inflateCodes_setOffsetHighByte
eor #$ff
; clc
adc outputPointer+1
sta inflateCodes_sourcePointer+1
jsr copyByte
jsr copyByte
inflateCodes_copyByte
jsr copyByte
dec inflateCodes_lengthMinus2
bne inflateCodes_copyByte
; jmp inflateCodes_loop
beq inflateCodes_loop
buildTempHuffmanTree
; ldy #0
tya
inflateDynamicBlock_clearCodeLengths
sta literalSymbolCodeLength,y
sta literalSymbolCodeLength+TOTAL_SYMBOLS-256,y
iny
bne inflateDynamicBlock_clearCodeLengths
; numberOfPrimaryCodes = 257 + getBits(5)
; numberOfDistanceCodes = 1 + getBits(5)
; numberOfTemporaryCodes = 4 + getBits(4)
ldx #3
inflateDynamicBlock_getHeader
lda inflateDynamicBlock_headerBits-1,x
jsr getBits
; sec
adc inflateDynamicBlock_headerBase-1,x
sta inflateDynamicBlock_tempCodes-1,x
sta inflateDynamicBlock_headerBase+1
dex
bne inflateDynamicBlock_getHeader
; Get lengths of temporary codes in the order stored in tempCodeLengthOrder
; ldx #0
inflateDynamicBlock_getTempCodeLengths
lda #GET_3_BITS
jsr getBits
ldy tempCodeLengthOrder,x
sta literalSymbolCodeLength,y
ldy #0
inx
cpx inflateDynamicBlock_tempCodes
bcc inflateDynamicBlock_getTempCodeLengths
; Build Huffman trees basing on code lengths (in bits)
; stored in the *SymbolCodeLength arrays
buildHuffmanTree
; Clear nBitCode_totalCount, nBitCode_literalCount, nBitCode_controlCount
tya
; lda #0
sta:rne nBitCode_clearFrom,y+
; Count number of codes of each length
; ldy #0
buildHuffmanTree_countCodeLengths
ldx literalSymbolCodeLength,y
inc nBitCode_literalCount,x
inc nBitCode_totalCount,x
cpy #CONTROL_SYMBOLS
bcs buildHuffmanTree_noControlSymbol
ldx controlSymbolCodeLength,y
inc nBitCode_controlCount,x
inc nBitCode_totalCount,x
buildHuffmanTree_noControlSymbol
iny
bne buildHuffmanTree_countCodeLengths
; Calculate offsets of symbols sorted by code length
; lda #0
ldx #-3*TREE_SIZE
buildHuffmanTree_calculateOffsets
sta nBitCode_literalOffset+3*TREE_SIZE-$100,x
add nBitCode_literalCount+3*TREE_SIZE-$100,x
inx
bne buildHuffmanTree_calculateOffsets
; Put symbols in their place in the sorted array
; ldy #0
buildHuffmanTree_assignCode
tya
ldx literalSymbolCodeLength,y
ldy:inc nBitCode_literalOffset,x
sta codeToLiteralSymbol,y
tay
cpy #CONTROL_SYMBOLS
bcs buildHuffmanTree_noControlSymbol2
ldx controlSymbolCodeLength,y
ldy:inc nBitCode_controlOffset,x
sta codeToControlSymbol,y
tay
buildHuffmanTree_noControlSymbol2
iny
bne buildHuffmanTree_assignCode
rts rts
* fetchPrimaryCode ; Read Huffman code using the primary tree
; Read a code basing on the primary tree.
fetchPrimaryCode fetchPrimaryCode
ldx #PRIMARY_TREE ldx #PRIMARY_TREE
; Read a code from input basing on the tree specified in X,
* fetchCode ; return low byte of this code in A,
; Read a code from input basing on the tree specified in X. ; return C flag reset for literal code, set for length code
; Return low byte of this code in A.
; For the literal/length tree, the C flag is set if the code is non-literal.
fetchCode fetchCode
lda #0 ; ldy #0
fetchCode_1 tya
fetchCode_nextBit
jsr getBit jsr getBit
rol @ rol @
inx inx
sub bitsCount-1,x sub nBitCode_totalCount,x
bcs fetchCode_1 bcs fetchCode_nextBit
adc bitsCount-1,x - ; clc
cmp literalCount-1,x adc nBitCode_controlCount,x
sta fetchCode_ptr bcs fetchCode_control
ldy bitsPointer_l-1,x ; clc
mva bitsPointer_h-1,x fetchCode_ptr+1 adc nBitCode_literalOffset,x
lda (fetchCode_ptr),y tax
lda codeToLiteralSymbol,x
clc
rts
fetchCode_control
add nBitCode_controlOffset-1,x
tax
lda codeToControlSymbol,x
sec
rts rts
* getValue ; Read A minus 1 bits, but no more than 8
; Decode low byte of a value (length or distance), basing on the code in A. getAMinus1BitsMax8
; The result is the base value for this code plus some bits read from input. rol getBits_base
getValue tax
tay cmp #9
ldx lengthExtraBits-1,y bcs getByte
lda:pha lengthBaseValue_l-1,y lda getNPlus1Bits_mask-2,x
lda:tay lengthBaseValue_h-1,y
pla
* getBits
; Read X-bit number from the input and add it to A.
; Increment Y if overflow.
; If X > 8, read only 8 bits.
; On return X holds number of unread bits: X = (X > 8 ? X - 8 : 0);
getBits getBits
cpx #0 jsr getBits_loop
beq getBits_ret getBits_normalizeLoop
pha lsr getBits_base
mva #-1 getBits_tmp ror @
pla bcc getBits_normalizeLoop
getBits_1 rts
; Read 16 bits
getWord
jsr getByte
tax
; Read 8 bits
getByte
lda #$80
getBits_loop
jsr getBit jsr getBit
bcc getBits_2 ror @
sbc getBits_tmp + bcc getBits_loop
scc:iny
getBits_2
dex
beq getBits_ret
asl getBits_tmp
bmi getBits_1
getBits_ret
rts rts
* getBit ; Read one bit, return in the C flag
; Read a single bit from input, return it in the C flag.
getBit getBit
lsr getBit_hold lsr getBit_buffer
bne getBit_ret bne getBit_return
pha pha
sty getBit_hold ; ldy #0
lda (inputPointer),0 lda (inputPointer),y
ldy getBit_hold
inw inputPointer inw inputPointer
ror @ + sec
sta getBit_hold ror @
sta getBit_buffer
pla pla
getBit_ret getBit_return
rts rts
; Copy a previously written byte
copyByte
ldy outputPointer
lda (inflateCodes_sourcePointer),y
ldy #0
; Write a byte
storeByte
sta (outputPointer),y
inc outputPointer
bne storeByte_return
inc outputPointer+1
inc inflateCodes_sourcePointer+1
storeByte_return
rts
* Arrays for the temporary codes. getNPlus1Bits_mask
dta GET_1_BIT,GET_2_BITS,GET_3_BITS,GET_4_BITS,GET_5_BITS,GET_6_BITS,GET_7_BITS
; Order, in which lengths of the temporary codes are stored.
tempCodeLengthOrder tempCodeLengthOrder
dta b(16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15) dta GET_2_BITS,GET_3_BITS,GET_7_BITS,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
; Base values. inflateDynamicBlock_headerBits dta GET_4_BITS,GET_5_BITS,GET_5_BITS
tempBaseValue inflateDynamicBlock_headerBase dta 3,0,0 ; second byte is modified at runtime!
dta b(3,3,11)
; Number of extra bits to read. org inflate_data
tempExtraBits
dta b(2,3,7)
; Data for building trees
* Arrays for the length and distance codes. literalSymbolCodeLength
; Base values.
lengthBaseValue_l
dta l(3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43)
dta l(51,59,67,83,99,115,131,163,195,227)
:!USE_DEFLATE64 dta l(258)
:USE_DEFLATE64 dta l(3)
distanceBaseValue_l
dta l(1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385)
dta l(513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577)
:USE_DEFLATE64 dta l(32769,49153)
lengthBaseValue_h
dta h(3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43)
dta h(51,59,67,83,99,115,131,163,195,227)
:!USE_DEFLATE64 dta h(258)
:USE_DEFLATE64 dta h(3)
distanceBaseValue_h
dta h(1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385)
dta h(513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577)
:USE_DEFLATE64 dta h(32769,49153)
; Number of extra bits to read.
lengthExtraBits
dta b(0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4)
dta b(4,4,5,5,5,5)
:!USE_DEFLATE64 dta b(0)
:USE_DEFLATE64 dta b(16)
distanceExtraBits
dta b(0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10)
dta b(11,11,12,12,13,13)
:USE_DEFLATE64 dta b(14,14)
; Number of literal codes of each length in the primary tree
; (MAX_BITS bytes, overlap with literalCodeLength).
literalCount
* Data for building the primary tree.
; Lengths of literal codes.
literalCodeLength
org *+256 org *+256
; Length of the end code. controlSymbolCodeLength
endCodeLength org *+CONTROL_SYMBOLS
org *+1
; Lengths of length codes.
lengthCodeLength
org *+29
; Huffman trees
* Data for building the distance tree. nBitCode_clearFrom
nBitCode_totalCount
org *+2*TREE_SIZE
nBitCode_literalCount
org *+TREE_SIZE
nBitCode_controlCount
org *+2*TREE_SIZE
nBitCode_literalOffset
org *+TREE_SIZE
nBitCode_controlOffset
org *+2*TREE_SIZE
; Lengths of distance codes. codeToLiteralSymbol
distanceCodeLength org *+256
org *+30+2*USE_DEFLATE64 codeToControlSymbol
; For two unused codes in the fixed trees and an 'end' mark org *+CONTROL_SYMBOLS
org *+3
* The Huffman trees.
; Number of codes of each length.
bitsCount
org *+TREES_SIZE
; Pointers to sorted codes of each length.
bitsPointer_l
org *+TREES_SIZE+1
bitsPointer_h
org *+TREES_SIZE
; Sorted codes.
sortedCodes
org *+256+1+29+30+2*USE_DEFLATE64+2
end end