New version from Piotr

git-svn-id: svn://svn.cc65.org/cc65/trunk@2444 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2003-09-23 20:05:32 +00:00
parent 84bbb0c270
commit 73941d8f48

View File

@@ -1,5 +1,5 @@
; ;
; Piotr Fusik, 23.11.2001 ; Piotr Fusik, 21.09.2003
; ;
; unsigned __fastcall__ inflatemem (char* dest, const char* source); ; unsigned __fastcall__ inflatemem (char* dest, const char* source);
; ;
@@ -14,28 +14,38 @@
; Constants ; Constants
; ;
; Maximum length of a Huffman code ; Maximum length of a Huffman code.
MAX_BITS = 15 MAX_BITS = 15
; Index in bitsCount, bitsPointer_l and bitsPointer_h
; for temporary tree or literal/length tree ; All Huffman trees are stored in the bitsCount, bitsPointer_l
; 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
; or the temporary tree.
PRIMARY_TREE = 0 PRIMARY_TREE = 0
; Index in bitsCount, bitsPointer_l and bitsPointer_h for distance tree
; Index in the mentioned arrays for the beginning of the distance tree.
DISTANCE_TREE = MAX_BITS DISTANCE_TREE = MAX_BITS
; Size of each of bitsCount, bitsPointer_l and bitsPointer_h
; Size of each array.
TREES_SIZE = 2*MAX_BITS TREES_SIZE = 2*MAX_BITS
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; ;
; Page zero ; Page zero
; ;
; Pointer to compressed data ; Pointer to the compressed data.
inputPointer = ptr1 ; 2 bytes inputPointer = ptr1 ; 2 bytes
; Pointer to uncompressed data
; Pointer to the uncompressed data.
outputPointer = ptr2 ; 2 bytes outputPointer = ptr2 ; 2 bytes
; Local variables ; Local variables.
getBit_hold = tmp1 ; 1 byte ; As far as there is no conflict, same memory locations are used
; for different variables.
inflateDynamicBlock_cnt = ptr3 ; 1 byte inflateDynamicBlock_cnt = ptr3 ; 1 byte
inflateCodes_src = ptr3 ; 2 bytes inflateCodes_src = ptr3 ; 2 bytes
@@ -51,6 +61,9 @@ moveBlock_len = sreg ; 2 bytes
inflateDynamicBlock_np = sreg ; 1 byte inflateDynamicBlock_np = sreg ; 1 byte
inflateDynamicBlock_nd = sreg+1 ; 1 byte inflateDynamicBlock_nd = sreg+1 ; 1 byte
getBit_hold = tmp1 ; 1 byte
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; ;
; Code ; Code
@@ -82,8 +95,7 @@ inflatemem_1:
lda #0 lda #0
jsr getBits jsr getBits
lsr a lsr a
tax ; A and Z contain block type, C contains EOF flag
; X contains block type, C contains EOF flag
; Save EOF flag ; Save EOF flag
php php
; Go to the routine decompressing this block ; Go to the routine decompressing this block
@@ -111,17 +123,13 @@ inflatemem_1:
jmp incsp2 jmp incsp2
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Go to the routine decompressing block type X ; Go to proper block decoding routine.
callExtr: callExtr:
lda extr_h,x bne inflateCompressedBlock
pha
lda extr_l,x
pha
rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Decompress 'stored' data block ; Decompress a 'stored' data block.
inflateCopyBlock: inflateCopyBlock:
; Ignore bits until byte boundary ; Ignore bits until byte boundary
@@ -133,7 +141,7 @@ inflateCopyBlock:
sta moveBlock_len sta moveBlock_len
lda (inputPointer),y lda (inputPointer),y
sta moveBlock_len+1 sta moveBlock_len+1
; Skip length and one's complement of it ; Skip the length and one's complement of it
lda #4 lda #4
clc clc
adc inputPointer adc inputPointer
@@ -143,7 +151,7 @@ inflateCopyBlock:
; jmp moveBlock ; jmp moveBlock
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Copy block of length moveBlock_len from (0,x) to output ; Copy block of length moveBlock_len from (0,x) to the output.
moveBlock: moveBlock:
ldy moveBlock_len ldy moveBlock_len
@@ -179,11 +187,22 @@ moveBlock_3:
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Decompress Huffman-coded data block with default Huffman trees: ; Decompress a Huffman-coded data block
; (A = 1: fixed, A = 2: dynamic).
inflateCompressedBlock:
lsr a
bne inflateDynamicBlock
; Note: inflateDynamicBlock may assume that A = 1
; --------------------------------------------------------------------------
; Decompress a Huffman-coded data block with default Huffman trees
; (defined by the DEFLATE format):
; literalCodeLength: 144 times 8, 112 times 9 ; literalCodeLength: 144 times 8, 112 times 9
; endCodeLength: 24 times 7, 6 times 8 ; endCodeLength: 7
; lengthCodeLength: 23 times 7, 6 times 8
; distanceCodeLength: 30 times 5+DISTANCE_TREE, 2 times 8 ; distanceCodeLength: 30 times 5+DISTANCE_TREE, 2 times 8
; (two 8-bit codes from primary tree are not used) ; (two 8-bit codes from the primary tree are not used).
inflateFixedBlock: inflateFixedBlock:
ldx #159 ldx #159
@@ -212,15 +231,15 @@ inflateFixedBlock_4:
sta distanceCodeLength-1,x sta distanceCodeLength-1,x
dex dex
bne inflateFixedBlock_4 bne inflateFixedBlock_4
jmp inflateCodes beq inflateCodes ; branch always
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Decompress Huffman-coded data block, reading Huffman trees first ; Decompress a Huffman-coded data block, reading Huffman trees first.
inflateDynamicBlock: inflateDynamicBlock:
; numberOfPrimaryCodes = 257 + getBits(5) ; numberOfPrimaryCodes = 257 + getBits(5)
ldx #5 ldx #5
lda #1 ; lda #1
jsr getBits jsr getBits
sta inflateDynamicBlock_np sta inflateDynamicBlock_np
; numberOfDistanceCodes = 1 + getBits(5) ; numberOfDistanceCodes = 1 + getBits(5)
@@ -233,26 +252,26 @@ inflateDynamicBlock:
tax tax
jsr getBits jsr getBits
sta inflateDynamicBlock_cnt sta inflateDynamicBlock_cnt
; Get lengths of temporary codes in order stored in tempCodeLengthOrder ; Get lengths of temporary codes in the order stored in tempCodeLengthOrder
ldy #0 txa ; lda #0
tay
inflateDynamicBlock_1: inflateDynamicBlock_1:
ldx #3 ldx #3 ; A = 0
lda #0
jsr getBits ; does not change Y jsr getBits ; does not change Y
inflateDynamicBlock_2: inflateDynamicBlock_2:
ldx tempCodeLengthOrder,y ldx tempCodeLengthOrder,y
sta literalCodeLength,x sta literalCodeLength,x
lda #0
iny iny
cpy inflateDynamicBlock_cnt cpy inflateDynamicBlock_cnt
bcc inflateDynamicBlock_1 bcc inflateDynamicBlock_1
lda #0
cpy #19 cpy #19
bcc inflateDynamicBlock_2 bcc inflateDynamicBlock_2
ror literalCodeLength+19 ; C flag is set, so it will set b7 ror literalCodeLength+19 ; C flag is set, so this will set b7
; Build tree for temporary codes ; Build the tree for temporary codes
jsr buildHuffmanTree jsr buildHuffmanTree
; Use temporary codes to get lengths for literal/length and distance codes ; Use temporary codes to get lengths of literal/length and distance codes
ldx #0 ldx #0
ldy #1 ldy #1
stx getNextLength_last stx getNextLength_last
@@ -263,39 +282,29 @@ inflateDynamicBlock_3:
bne inflateDynamicBlock_3 bne inflateDynamicBlock_3
inflateDynamicBlock_4: inflateDynamicBlock_4:
jsr getNextLength jsr getNextLength
inflateDynamicBlock_5:
sta endCodeLength,x sta endCodeLength,x
inx inx
cpx inflateDynamicBlock_np cpx inflateDynamicBlock_np
bcc inflateDynamicBlock_4 bcc inflateDynamicBlock_4
.ifpc02
bcs inflateDynamicBlock_6 ; branch always
inflateDynamicBlock_5:
stz endCodeLength,x
.else
lda #0 lda #0
bcs inflateDynamicBlock_6 ; branch always
inflateDynamicBlock_5:
sta endCodeLength,x
.endif
inx
inflateDynamicBlock_6:
cpx #1+29 cpx #1+29
bcc inflateDynamicBlock_5 bcc inflateDynamicBlock_5
inflateDynamicBlock_7: inflateDynamicBlock_6:
jsr getNextLength jsr getNextLength
cmp #0 cmp #0
beq inflateDynamicBlock_8 beq inflateDynamicBlock_7
adc #DISTANCE_TREE-1 ; C flag is set adc #DISTANCE_TREE-1 ; C flag is set
inflateDynamicBlock_8: inflateDynamicBlock_7:
sta endCodeLength,x sta endCodeLength,x
inx inx
cpx inflateDynamicBlock_nd cpx inflateDynamicBlock_nd
bcc inflateDynamicBlock_7 bcc inflateDynamicBlock_6
ror endCodeLength,x ; C flag is set, so it will set b7 ror endCodeLength,x ; C flag is set, so this will set b7
; jmp inflateCodes ; jmp inflateCodes
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Decompress data block basing on given Huffman trees ; Decompress a data block basing on given Huffman trees.
inflateCodes: inflateCodes:
jsr buildHuffmanTree jsr buildHuffmanTree
@@ -318,7 +327,7 @@ inflateCodes_ret:
rts rts
inflateCodes_2: inflateCodes_2:
beq inflateCodes_ret beq inflateCodes_ret
; Repeat block ; Restore a block from the look-behind buffer
jsr getValue jsr getValue
sta moveBlock_len sta moveBlock_len
tya tya
@@ -343,9 +352,9 @@ inflateCodes_2:
beq inflateCodes_1 ; branch always beq inflateCodes_1 ; branch always
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Build Huffman trees basing on code lengths. ; Build Huffman trees basing on code lengths (in bits).
; Lengths (in bits) are stored in *CodeLength tables. ; stored in the *CodeLength arrays.
; A byte with highest bit set marks end of length table. ; A byte with its highest bit set marks the end.
buildHuffmanTree: buildHuffmanTree:
lda #<literalCodeLength lda #<literalCodeLength
@@ -370,7 +379,7 @@ buildHuffmanTree_2:
buildHuffmanTree_3: buildHuffmanTree_3:
lda (buildHuffmanTree_src),y lda (buildHuffmanTree_src),y
bpl buildHuffmanTree_2 bpl buildHuffmanTree_2
; Calculate pointer for each length ; Calculate a pointer for each length
ldx #0 ldx #0
lda #<sortedCodes lda #<sortedCodes
ldy #>sortedCodes ldy #>sortedCodes
@@ -420,7 +429,7 @@ buildHuffmanTree_9:
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Get next code length basing on temporary codes ; Decode next code length using temporary codes.
getNextLength: getNextLength:
stx getNextLength_index stx getNextLength_index
@@ -441,7 +450,7 @@ getNextLength:
jsr getBits jsr getBits
cpy #17 cpy #17
tay tay
lda #0 txa ; lda #0
bcs getNextLength_2 bcs getNextLength_2
getNextLength_1: getNextLength_1:
lda getNextLength_last lda getNextLength_last
@@ -451,38 +460,38 @@ getNextLength_2:
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Read code basing on primary tree ; Read a code basing on the primary tree.
fetchPrimaryCode: fetchPrimaryCode:
ldx #PRIMARY_TREE ldx #PRIMARY_TREE
; jmp fetchCode ; jmp fetchCode
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Read code from input stream basing on tree given in X. ; Read a code from input basing on the tree specified in X.
; Return low byte of code in A. ; Return low byte of this code in A.
; For literal/length tree, C is: 0 if literal code, 1 if end or length code. ; For the literal/length tree, the C flag is set if the code is non-literal.
fetchCode: fetchCode:
lda #0 lda #0
fetchCode_1: fetchCode_1:
jsr getBit jsr getBit
rol a rol a
cmp bitsCount,x
bcc fetchCode_2
sbc bitsCount,x ; C flag is set
inx inx
bcs fetchCode_1 ; branch always sec
fetchCode_2: sbc bitsCount-1,x
cmp literalCount,x bcs fetchCode_1
adc bitsCount-1,x ; C flag is zero
cmp literalCount-1,x
sta fetchCode_ptr sta fetchCode_ptr
ldy bitsPointer_l,x ldy bitsPointer_l-1,x
lda bitsPointer_h,x lda bitsPointer_h-1,x
sta fetchCode_ptr+1 sta fetchCode_ptr+1
lda (fetchCode_ptr),y lda (fetchCode_ptr),y
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Read low byte of value (length or distance), basing on code A ; Decode low byte of a value (length or distance), basing on the code in A.
; The result is the base value for this code plus some bits read from input.
getValue: getValue:
tay tay
@@ -495,35 +504,39 @@ getValue:
; jmp getBits ; jmp getBits
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Read X-bit number from input stream and add it to A. ; Read X-bit number from the input and add it to A.
; In case of carry, Y is incremented. ; Increment Y if overflow.
; If X > 8, only 8 bits are read. ; If X > 8, read only 8 bits.
; On return X holds number of unread bits: X = (X > 8 ? X - 8 : 0); ; On return X holds number of unread bits: X = (X > 8 ? X - 8 : 0);
getBits: getBits:
cpx #0 cpx #0
beq getBits_ret beq getBits_ret
.ifpc02
stz getBits_tmp
dec getBits_tmp
.else
pha pha
lda #1 lda #$ff
sta getBits_tmp sta getBits_tmp
pla pla
.endif
getBits_1: getBits_1:
jsr getBit jsr getBit
bcc getBits_2 bcc getBits_2
clc sbc getBits_tmp ; C flag is set
adc getBits_tmp
bcc getBits_2 bcc getBits_2
iny iny
getBits_2: getBits_2:
dex dex
beq getBits_ret beq getBits_ret
asl getBits_tmp asl getBits_tmp
bcc getBits_1 bmi getBits_1
getBits_ret: getBits_ret:
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Read single bit from input stream, return it in C flag ; Read a single bit from input, return it in the C flag.
getBit: getBit:
lsr getBit_hold lsr getBit_hold
@@ -532,10 +545,10 @@ getBit:
.ifpc02 .ifpc02
lda (inputPointer) lda (inputPointer)
.else .else
tya sty getBit_hold
pha
ldy #0 ldy #0
lda (inputPointer),y lda (inputPointer),y
ldy getBit_hold
.endif .endif
inc inputPointer inc inputPointer
bne getBit_1 bne getBit_1
@@ -543,15 +556,11 @@ getBit:
getBit_1: getBit_1:
ror a ; C flag is set ror a ; C flag is set
sta getBit_hold sta getBit_hold
.ifpc02
.else
pla
tay
.endif
pla pla
getBit_ret: getBit_ret:
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; ;
; Constant data ; Constant data
@@ -559,37 +568,24 @@ getBit_ret:
.rodata .rodata
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Addresses of functions extracting different blocks ; Arrays for the temporary codes.
extr_l:
.byte <(inflateCopyBlock-1)
.byte <(inflateFixedBlock-1)
.byte <(inflateDynamicBlock-1)
extr_h:
.byte >(inflateCopyBlock-1)
.byte >(inflateFixedBlock-1)
.byte >(inflateDynamicBlock-1)
; -------------------------------------------------------------------------- ; Order, in which lengths of the temporary codes are stored.
; Tables for temporary codes
; Value is BaseValue + getBits(ExtraBits)
; Order, in which lengths of temporary codes are stored
tempCodeLengthOrder: tempCodeLengthOrder:
.byte 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 .byte 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
; Base values ; Base values.
tempBaseValue: tempBaseValue:
.byte 3,3,11 .byte 3,3,11
; Number of extra bits to read ; Number of extra bits to read.
tempExtraBits: tempExtraBits:
.byte 2,3,7 .byte 2,3,7
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Tables for length and distance codes ; Arrays for the length and distance codes.
; Value is BaseValue + getBits(ExtraBits)
; Base values ; Base values.
lengthBaseValue_l: lengthBaseValue_l:
.byte <3,<4,<5,<6,<7,<8,<9,<10 .byte <3,<4,<5,<6,<7,<8,<9,<10
.byte <11,<13,<15,<17,<19,<23,<27,<31 .byte <11,<13,<15,<17,<19,<23,<27,<31
@@ -611,7 +607,7 @@ distanceBaseValue_h:
.byte >257,>385,>513,>769,>1025,>1537,>2049,>3073 .byte >257,>385,>513,>769,>1025,>1537,>2049,>3073
.byte >4097,>6145,>8193,>12289,>16385,>24577 .byte >4097,>6145,>8193,>12289,>16385,>24577
; Number of extra bits to read ; Number of extra bits to read.
lengthExtraBits: lengthExtraBits:
.byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0
.byte 1,1,1,1,2,2,2,2 .byte 1,1,1,1,2,2,2,2
@@ -623,6 +619,7 @@ distanceExtraBits:
.byte 7,7,8,8,9,9,10,10 .byte 7,7,8,8,9,9,10,10
.byte 11,11,12,12,13,13 .byte 11,11,12,12,13,13
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; ;
; Uninitialised data ; Uninitialised data
@@ -630,45 +627,45 @@ distanceExtraBits:
.bss .bss
; Number of literal codes of each length in primary tree ; Number of literal codes of each length in the primary tree
; (MAX_BITS bytes, overlap with literalCodeLength) ; (MAX_BITS bytes, overlap with literalCodeLength).
literalCount: literalCount:
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Data for building primary tree ; Data for building the primary tree.
; Lengths of literal codes ; Lengths of literal codes.
literalCodeLength: literalCodeLength:
.res 256 .res 256
; Length of end code ; Length of the end code.
endCodeLength: endCodeLength:
.res 1 .res 1
; Lengths of length codes ; Lengths of length codes.
lengthCodeLength: lengthCodeLength:
.res 29 .res 29
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Data for building distance tree ; Data for building the distance tree.
; Lengths of distance codes ; Lengths of distance codes.
distanceCodeLength: distanceCodeLength:
.res 30 .res 30
; For two unused codes in fixed trees and end-of-table flag ; For two unused codes in the fixed trees and an 'end' mark.
.res 3 .res 3
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; Huffman tree structure ; The Huffman trees.
; Number of codes of each length ; Number of codes of each length.
bitsCount: bitsCount:
.res TREES_SIZE .res TREES_SIZE
; Pointer to sorted codes of each length ; Pointers to sorted codes of each length.
bitsPointer_l: bitsPointer_l:
.res TREES_SIZE+1 .res TREES_SIZE+1
bitsPointer_h: bitsPointer_h:
.res TREES_SIZE .res TREES_SIZE
; Sorted codes ; Sorted codes.
sortedCodes: sortedCodes:
.res 256+1+29+30+2 .res 256+1+29+30+2