2 ; 2003-09-21, Piotr Fusik
3 ; 2017-02-07, Greg King
5 ; unsigned __fastcall__ inflatemem (char* dest, const char* source);
8 ; Two "lda (0,x)" instructions can't be assembled for the PC-Engine library
9 ; because an implied ".setdp $2000" changes $00 into a non-zero-page address.
10 ; Therefore, this file isn't assembled for that target.
16 .importzp sp, sreg, ptr1, ptr2, ptr3, ptr4, tmp1
20 ; --------------------------------------------------------------------------
25 ; Maximum length of a Huffman code.
28 ; All Huffman trees are stored in the bitsCount, bitsPointer_l
29 ; and bitsPointer_h arrays. There may be two trees: the literal/length tree
30 ; and the distance tree, or just one - the temporary tree.
32 ; Index in the mentioned arrays for the beginning of the literal/length tree
33 ; or the temporary tree.
36 ; Index in the mentioned arrays for the beginning of the distance tree.
37 DISTANCE_TREE = MAX_BITS
40 TREES_SIZE = 2*MAX_BITS
43 ; --------------------------------------------------------------------------
48 ; Pointer to the compressed data.
49 inputPointer := ptr1 ; 2 bytes
51 ; Pointer to the uncompressed data.
52 outputPointer := ptr2 ; 2 bytes
55 ; As far as there is no conflict, same memory locations are used
56 ; for different variables.
58 inflateDynamicBlock_cnt := ptr3 ; 1 byte
59 inflateCodes_src := ptr3 ; 2 bytes
60 buildHuffmanTree_src := ptr3 ; 2 bytes
61 getNextLength_last := ptr3 ; 1 byte
62 getNextLength_index := ptr3+1 ; 1 byte
64 buildHuffmanTree_ptr := ptr4 ; 2 bytes
65 fetchCode_ptr := ptr4 ; 2 bytes
66 getBits_tmp := ptr4 ; 1 byte
68 moveBlock_len := sreg ; 2 bytes
69 inflateDynamicBlock_np := sreg ; 1 byte
70 inflateDynamicBlock_nd := sreg+1 ; 1 byte
72 getBit_hold := tmp1 ; 1 byte
75 ; --------------------------------------------------------------------------
82 ; inputPointer = source
85 ; outputPointer = dest
86 .if (.cpu & CPU_ISET_65SC02)
101 ; Get a bit of EOF and two bits of block type
106 ; A and Z contain block type, C contains EOF flag
109 ; Go to the routine decompressing this block
115 ; return outputPointer - dest;
117 .if (.cpu & CPU_ISET_65SC02)
118 sbc (sp) ; C flag is set
122 sbc (sp),y ; C flag is set
133 ; --------------------------------------------------------------------------
134 ; Go to proper block decoding routine.
137 bne inflateCompressedBlock
139 ; --------------------------------------------------------------------------
140 ; Decompress a 'stored' data block.
143 ; Ignore bits until byte boundary
152 ; Skip the length and one's complement of it
161 ; --------------------------------------------------------------------------
162 ; Copy block of length moveBlock_len from (0,x) to the output.
167 .if (.cpu & CPU_ISET_65SC02)
174 .if (.cpu & CPU_ISET_65SC02)
177 sta (outputPointer),y
187 .if (.cpu & CPU_ISET_65SC02)
197 ; --------------------------------------------------------------------------
198 ; Decompress a Huffman-coded data block
199 ; (A = 1: fixed, A = 2: dynamic).
201 inflateCompressedBlock:
203 bne inflateDynamicBlock
204 ; Note: inflateDynamicBlock may assume that A = 1
206 ; --------------------------------------------------------------------------
207 ; Decompress a Huffman-coded data block with default Huffman trees
208 ; (defined by the DEFLATE format):
209 ; literalCodeLength: 144 times 8, 112 times 9
211 ; lengthCodeLength: 23 times 7, 6 times 8
212 ; distanceCodeLength: 30 times 5+DISTANCE_TREE, 2 times 8
213 ; (two 8-bit codes from the primary tree are not used).
217 stx distanceCodeLength+32
220 sta literalCodeLength-1,x
221 sta literalCodeLength+159-1,x
223 bne inflateFixedBlock_1
227 inc literalCodeLength+144-1,x ; sta
229 bne inflateFixedBlock_2
233 dec endCodeLength-1,x ; sta
235 bne inflateFixedBlock_3
239 sta distanceCodeLength-1,x
241 bne inflateFixedBlock_4
242 beq inflateCodes ; branch always
244 ; --------------------------------------------------------------------------
245 ; Decompress a Huffman-coded data block, reading Huffman trees first.
248 ; numberOfPrimaryCodes = 257 + getBits(5)
252 sta inflateDynamicBlock_np
253 ; numberOfDistanceCodes = 1 + getBits(5)
257 sta inflateDynamicBlock_nd
258 ; numberOfTemporaryCodes = 4 + getBits(4)
262 sta inflateDynamicBlock_cnt
263 ; Get lengths of temporary codes in the order stored in tempCodeLengthOrder
266 inflateDynamicBlock_1:
268 jsr getBits ; does not change Y
269 inflateDynamicBlock_2:
270 ldx tempCodeLengthOrder,y
271 sta literalCodeLength,x
274 cpy inflateDynamicBlock_cnt
275 bcc inflateDynamicBlock_1
277 bcc inflateDynamicBlock_2
278 ror literalCodeLength+19 ; C flag is set, so this will set b7
279 ; Build the tree for temporary codes
282 ; Use temporary codes to get lengths of literal/length and distance codes
285 stx getNextLength_last
286 inflateDynamicBlock_3:
288 sta literalCodeLength,x
290 bne inflateDynamicBlock_3
291 inflateDynamicBlock_4:
293 inflateDynamicBlock_5:
296 cpx inflateDynamicBlock_np
297 bcc inflateDynamicBlock_4
300 bcc inflateDynamicBlock_5
301 inflateDynamicBlock_6:
304 beq inflateDynamicBlock_7
305 adc #DISTANCE_TREE-1 ; C flag is set
306 inflateDynamicBlock_7:
309 cpx inflateDynamicBlock_nd
310 bcc inflateDynamicBlock_6
311 ror endCodeLength,x ; C flag is set, so this will set b7
314 ; --------------------------------------------------------------------------
315 ; Decompress a data block basing on given Huffman trees.
323 .if (.cpu & CPU_ISET_65SC02)
327 sta (outputPointer),y
332 bcc inflateCodes_1 ; branch always
338 ; Restore a block from the look-behind buffer
357 sta inflateCodes_src+1
358 ldx #inflateCodes_src
360 beq inflateCodes_1 ; branch always
362 ; --------------------------------------------------------------------------
363 ; Build Huffman trees basing on code lengths (in bits).
364 ; stored in the *CodeLength arrays.
365 ; A byte with its highest bit set marks the end.
368 lda #<literalCodeLength
369 sta buildHuffmanTree_src
370 lda #>literalCodeLength
371 sta buildHuffmanTree_src+1
372 ; Clear bitsCount and bitsPointer_l
378 bne buildHuffmanTree_1
379 beq buildHuffmanTree_3 ; branch always
380 ; Count number of codes of each length
385 bne buildHuffmanTree_3
386 inc buildHuffmanTree_src+1
388 lda (buildHuffmanTree_src),y
389 bpl buildHuffmanTree_2
390 ; Calculate a pointer for each length
399 lda bitsPointer_l+1,x
400 adc bitsPointer_l,x ; C flag is zero
401 bcc buildHuffmanTree_5
406 bcc buildHuffmanTree_4
407 lda #>literalCodeLength
408 sta buildHuffmanTree_src+1
410 bcs buildHuffmanTree_9 ; branch always
411 ; Put codes into their place in sorted table
413 beq buildHuffmanTree_7
415 lda bitsPointer_l-1,x
416 sta buildHuffmanTree_ptr
417 lda bitsPointer_h-1,x
418 sta buildHuffmanTree_ptr+1
422 sta (buildHuffmanTree_ptr),y
426 bne buildHuffmanTree_9
427 inc buildHuffmanTree_src+1
433 bpl buildHuffmanTree_8
435 lda (buildHuffmanTree_src),y
436 bpl buildHuffmanTree_6
439 ; --------------------------------------------------------------------------
440 ; Decode next code length using temporary codes.
443 stx getNextLength_index
446 ; Fetch a temporary code
448 ; Temporary code 0..15: put this length
452 ; Temporary code 16: repeat last length 3 + getBits(2) times
453 ; Temporary code 17: put zero length 3 + getBits(3) times
454 ; Temporary code 18: put zero length 11 + getBits(7) times
456 ldx tempExtraBits-16,y
457 lda tempBaseValue-16,y
464 lda getNextLength_last
466 sta getNextLength_last
467 ldx getNextLength_index
470 ; --------------------------------------------------------------------------
471 ; Read a code basing on the primary tree.
477 ; --------------------------------------------------------------------------
478 ; Read a code from input basing on the tree specified in X.
479 ; Return low byte of this code in A.
480 ; For the literal/length tree, the C flag is set if the code is non-literal.
491 adc bitsCount-1,x ; C flag is zero
494 ldy bitsPointer_l-1,x
495 lda bitsPointer_h-1,x
497 lda (fetchCode_ptr),y
500 ; --------------------------------------------------------------------------
501 ; Decode low byte of a value (length or distance), basing on the code in A.
502 ; The result is the base value for this code plus some bits read from input.
506 ldx lengthExtraBits-1,y
507 lda lengthBaseValue_l-1,y
509 lda lengthBaseValue_h-1,y
514 ; --------------------------------------------------------------------------
515 ; Read X-bit number from the input and add it to A.
516 ; Increment Y if overflow.
517 ; If X > 8, read only 8 bits.
518 ; On return X holds number of unread bits: X = (X > 8 ? X - 8 : 0);
523 .if (.cpu & CPU_ISET_65SC02)
535 sbc getBits_tmp ; C flag is set
546 ; --------------------------------------------------------------------------
547 ; Read a single bit from input, return it in the C flag.
553 .if (.cpu & CPU_ISET_65SC02)
565 ror a ; (C flag was set)
572 ; --------------------------------------------------------------------------
578 ; --------------------------------------------------------------------------
579 ; Arrays for the temporary codes.
581 ; Order, in which lengths of the temporary codes are stored.
583 .byte 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
589 ; Number of extra bits to read.
593 ; --------------------------------------------------------------------------
594 ; Arrays for the length and distance codes.
598 .byte <3,<4,<5,<6,<7,<8,<9,<10
599 .byte <11,<13,<15,<17,<19,<23,<27,<31
600 .byte <35,<43,<51,<59,<67,<83,<99,<115
601 .byte <131,<163,<195,<227,<258
603 .byte <1,<2,<3,<4,<5,<7,<9,<13
604 .byte <17,<25,<33,<49,<65,<97,<129,<193
605 .byte <257,<385,<513,<769,<1025,<1537,<2049,<3073
606 .byte <4097,<6145,<8193,<12289,<16385,<24577
608 .byte >3,>4,>5,>6,>7,>8,>9,>10
609 .byte >11,>13,>15,>17,>19,>23,>27,>31
610 .byte >35,>43,>51,>59,>67,>83,>99,>115
611 .byte >131,>163,>195,>227,>258
613 .byte >1,>2,>3,>4,>5,>7,>9,>13
614 .byte >17,>25,>33,>49,>65,>97,>129,>193
615 .byte >257,>385,>513,>769,>1025,>1537,>2049,>3073
616 .byte >4097,>6145,>8193,>12289,>16385,>24577
618 ; Number of extra bits to read.
620 .byte 0,0,0,0,0,0,0,0
621 .byte 1,1,1,1,2,2,2,2
622 .byte 3,3,3,3,4,4,4,4
625 .byte 0,0,0,0,1,1,2,2
626 .byte 3,3,4,4,5,5,6,6
627 .byte 7,7,8,8,9,9,10,10
628 .byte 11,11,12,12,13,13
631 ; --------------------------------------------------------------------------
638 ; Number of literal codes of each length in the primary tree
639 ; (MAX_BITS bytes, overlap with literalCodeLength).
642 ; --------------------------------------------------------------------------
643 ; Data for building the primary tree.
645 ; Lengths of literal codes.
648 ; Length of the end code.
651 ; Lengths of length codes.
655 ; --------------------------------------------------------------------------
656 ; Data for building the distance tree.
658 ; Lengths of distance codes.
661 ; For two unused codes in the fixed trees and an 'end' mark.
664 ; --------------------------------------------------------------------------
667 ; Number of codes of each length.
670 ; Pointers to sorted codes of each length.