-/*****************************************************************************/
-/* */
-/* zlib.h */
-/* */
-/* Decompression routines for the 'deflate' format */
-/* */
-/* */
-/* */
-/* (C) 2000-2001 Piotr Fusik */
-/* a.k.a. Fox/Taquart */
-/* EMail: fox@scene.pl */
-/* */
-/* */
-/* This software is provided 'as-is', without any expressed or implied */
-/* warranty. In no event will the authors be held liable for any damages */
-/* arising from the use of this software. */
-/* */
-/* Permission is granted to anyone to use this software for any purpose, */
-/* including commercial applications, and to alter it and redistribute it */
-/* freely, subject to the following restrictions: */
-/* */
-/* 1. The origin of this software must not be misrepresented; you must not */
-/* claim that you wrote the original software. If you use this software */
-/* in a product, an acknowledgment in the product documentation would be */
-/* appreciated but is not required. */
-/* 2. Altered source versions must be plainly marked as such, and must not */
-/* be misrepresented as being the original software. */
-/* 3. This notice may not be removed or altered from any source */
-/* distribution. */
-/* */
-/*****************************************************************************/
-
-
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-
-
-void* inflatemem (void* dest, void* src);
-/* Read the deflate compressed data starting from src and store
- * the uncompressed data starting from dest.
- * Return pointer to a byte after the decompressed data. That is, the result
- * minus dest is the size of the decompressed data.
- */
-
-
-
-/* end of zlib.h */
-#endif
-
-
-
+/*****************************************************************************/\r
+/* */\r
+/* zlib.h */\r
+/* */\r
+/* Decompression routines for the 'deflate' format */\r
+/* */\r
+/* */\r
+/* */\r
+/* (C) 2000-2001 Piotr Fusik <fox@scene.pl> */\r
+/* */\r
+/* This file is based on the zlib.h from 'zlib' general purpose compression */\r
+/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */\r
+/* */\r
+/* Jean-loup Gailly Mark Adler */\r
+/* jloup@gzip.org madler@alumni.caltech.edu */\r
+/* */\r
+/* This software is provided 'as-is', without any expressed or implied */\r
+/* warranty. In no event will the authors be held liable for any damages */\r
+/* arising from the use of this software. */\r
+/* */\r
+/* Permission is granted to anyone to use this software for any purpose, */\r
+/* including commercial applications, and to alter it and redistribute it */\r
+/* freely, subject to the following restrictions: */\r
+/* */\r
+/* 1. The origin of this software must not be misrepresented; you must not */\r
+/* claim that you wrote the original software. If you use this software */\r
+/* in a product, an acknowledgment in the product documentation would be */\r
+/* appreciated but is not required. */\r
+/* 2. Altered source versions must be plainly marked as such, and must not */\r
+/* be misrepresented as being the original software. */\r
+/* 3. This notice may not be removed or altered from any source */\r
+/* distribution. */\r
+/* */\r
+/*****************************************************************************/\r
+\r
+\r
+\r
+#ifndef _ZLIB_H\r
+#define _ZLIB_H\r
+\r
+#define Z_OK 0\r
+#define Z_DATA_ERROR (-3)\r
+/* Return codes for uncompress() */\r
+\r
+#define Z_DEFLATED 8\r
+/* The deflate compression method (the only one supported) */\r
+\r
+#define Z_NULL 0\r
+\r
+\r
+unsigned __fastcall__ inflatemem (char* dest, const char* source);\r
+/*\r
+ Decompresses the source buffer into the destination buffer.\r
+ Returns the size of the uncompressed data (number of bytes written starting\r
+ from dest).\r
+\r
+ This function expects data in the DEFLATE format, described in RFC\r
+ (Request for Comments) 1951 in the file\r
+ ftp://ds.internic.net/rfc/rfc1951.txt.\r
+\r
+ This function does not exist in the original zlib. Its implementation\r
+ using original zlib might be following:\r
+\r
+ unsigned inflatemem (char* dest, const char* source)\r
+ {\r
+ z_stream stream;\r
+\r
+ stream.next_in = (Bytef*) source;\r
+ stream.avail_in = 65535;\r
+\r
+ stream.next_out = dest;\r
+ stream.avail_out = 65535;\r
+\r
+ stream.zalloc = (alloc_func) 0;\r
+ stream.zfree = (free_func) 0;\r
+\r
+ inflateInit2(&stream, -MAX_WBITS);\r
+ inflate(&stream, Z_FINISH);\r
+ inflateEnd(&stream);\r
+\r
+ return stream.total_out;\r
+ }\r
+*/\r
+\r
+\r
+int uncompress (char* dest, unsigned* destLen,\r
+ const char* source, unsigned sourceLen);\r
+/*\r
+ Original zlib description:\r
+\r
+ Decompresses the source buffer into the destination buffer. sourceLen is\r
+ the byte length of the source buffer. Upon entry, destLen is the total\r
+ size of the destination buffer, which must be large enough to hold the\r
+ entire uncompressed data. (The size of the uncompressed data must have\r
+ been saved previously by the compressor and transmitted to the decompressor\r
+ by some mechanism outside the scope of this compression library.)\r
+ Upon exit, destLen is the actual size of the compressed buffer.\r
+ This function can be used to decompress a whole file at once if the\r
+ input file is mmap'ed.\r
+\r
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not\r
+ enough memory, Z_BUF_ERROR if there was not enough room in the output\r
+ buffer, or Z_DATA_ERROR if the input data was corrupted.\r
+\r
+ Implementation notes:\r
+\r
+ This function expects data in the ZLIB format, described in RFC 1950\r
+ in the file ftp://ds.internic.net/rfc/rfc1950.txt. The ZLIB format is\r
+ essentially the DEFLATE format plus a very small header and Adler-32\r
+ checksum.\r
+\r
+ Z_MEM_ERROR and Z_BUF_ERROR are never returned in this implementation.\r
+*/\r
+\r
+\r
+unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf,\r
+ unsigned len);\r
+\r
+/*\r
+ Original zlib description:\r
+\r
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and\r
+ return the updated checksum. If buf is NULL, this function returns\r
+ the required initial value for the checksum.\r
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed\r
+ much faster. Usage example:\r
+\r
+ unsigned long adler = adler32(0L, Z_NULL, 0);\r
+\r
+ while (read_buffer(buffer, length) != EOF) {\r
+ adler = adler32(adler, buffer, length);\r
+ }\r
+ if (adler != original_adler) error();\r
+\r
+ Implementation notes:\r
+\r
+ This function isn't actually much faster than crc32(), but it is smaller\r
+ and does not use any lookup tables.\r
+*/\r
+\r
+\r
+unsigned long __fastcall__ crc32 (unsigned long crc, const char* buf,\r
+ unsigned len);\r
+/*\r
+ Original zlib description:\r
+\r
+ Update a running crc with the bytes buf[0..len-1] and return the updated\r
+ crc. If buf is NULL, this function returns the required initial value\r
+ for the crc. Pre- and post-conditioning (one's complement) is performed\r
+ within this function so it shouldn't be done by the application.\r
+ Usage example:\r
+\r
+ unsigned long crc = crc32(0L, Z_NULL, 0);\r
+\r
+ while (read_buffer(buffer, length) != EOF) {\r
+ crc = crc32(crc, buffer, length);\r
+ }\r
+ if (crc != original_crc) error();\r
+\r
+ Implementation notes:\r
+\r
+ This function uses statically allocated 1 KB lookup table. The table is\r
+ initialised before it is used for the first time (that is, if buffer is\r
+ NULL or length is zero, then the lookup table isn't initialised).\r
+*/\r
+\r
+\r
+/* end of zlib.h */\r
+#endif\r
+\r
+\r
+\r
-;
-; Piotr Fusik, 11.11.2001
-;
-; void* inflatemem (void* dest, void* src);
-;
-
- .export _inflatemem
-
- .import popax
- .importzp sreg, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, tmp4
-
-; --------------------------------------------------------------------------
-;
-; Constants
-;
-
-; Maximum length of a Huffman code
-MAX_BITS = 15
-; Index in bitsCount, bitsPointer_l and bitsPointer_h for literal tree
-LITERAL_TREE = 0
-; Index in bitsCount, bitsPointer_l and bitsPointer_h for distance tree
-DISTANCE_TREE = MAX_BITS
-; Size of each of bitsCount, bitsPointer_l and bitsPointer_h
-TREES_SIZE = 2*MAX_BITS+1
-
-; --------------------------------------------------------------------------
-;
-; Page zero
-;
-
-; Pointer to compressed data
-inputPointer = ptr1 ; 2 bytes
-; Pointer to uncompressed data
-outputPointer = ptr2 ; 2 bytes
-; Buffer for getBit
-getBitHold = tmp1 ; 1 byte
-; Local variables. Variables from different routines use same memory.
-cnt = tmp2 ; 1 byte
-tmp = sreg ; 1 byte
-ptr = sreg ; 2 bytes
-len = ptr3 ; 2 bytes
-nl = tmp3 ; 1 byte
-nd = tmp4 ; 1 byte
-src = ptr4 ; 2 bytes
-dest = ptr4 ; 2 bytes
-
-; --------------------------------------------------------------------------
-;
-; Code
-;
-
-_inflatemem:
-
-; Get inputPointer and outputPointer from stack
- jsr popax
- sta inputPointer
- stx inputPointer+1
- jsr popax
- sta outputPointer
- stx outputPointer+1
-
- ldy #1
- sty getBitHold
-; Get a bit of EOF and two bits of block type
-inflatemem_1:
- ldx #3
- lda #0
- jsr getBits
- lsr a
- tax
-; X contains block type, C contains EOF flag
-; Save EOF flag
- php
-; Go to the routine decompressing this block
- jsr callExtr
- plp
- bcc inflatemem_1
- lda outputPointer
- ldx outputPointer+1
- rts
-
-; --------------------------------------------------------------------------
-; Go to the routine decompressing block type X
-
-callExtr:
- lda extr_h,x
- pha
- lda extr_l,x
- pha
- rts
-
-; --------------------------------------------------------------------------
-; Decompress 'stored' data block
-
-inflateCopyBlock:
-; Ignore bits until byte boundary
- ldy #1
- sty getBitHold
-; Get 16-bit length
- ldx #inputPointer
- lda (0,x)
- sta len
- lda (inputPointer),y
- sta len+1
-; Skip length and one's compliment length
- lda #4
- clc
- adc inputPointer
- sta inputPointer
- bcc moveBlock
- inc inputPointer+1
-; fall into moveBlock
-
-; --------------------------------------------------------------------------
-; Copy block of length len from (0,x) to output
-
-moveBlock:
- ldy len
- beq moveBlock_1
- ldy #0
- inc len+1
-moveBlock_1:
- lda (0,x)
- sta (outputPointer),y
- inc 0,x
- bne moveBlock_2
- inc 1,x
-moveBlock_2:
- inc outputPointer
- bne moveBlock_3
- inc outputPointer+1
-moveBlock_3:
- dec len
- bne moveBlock_1
- dec len+1
- bne moveBlock_1
- rts
-
-; --------------------------------------------------------------------------
-; Decompress Huffman-coded data block with default Huffman trees:
-; literalCodeLength: 144 times 8, 112 times 9
-; endCodeLength: 24 times 7, 6 times 8
-; distanceCodeLength: 30 times 5, 2 times 8
-; (2 last codes from literal tree are not used)
-
-inflateFixedBlock:
- ldx #159
- stx distanceCodeLength+32
- lda #8
-inflateFixedBlock_1:
- sta literalCodeLength-1,x
- sta literalCodeLength+159-1,x
- dex
- bne inflateFixedBlock_1
- ldx #112
- lda #9
-inflateFixedBlock_2:
- sta literalCodeLength+144-1,x
- dex
- bne inflateFixedBlock_2
- ldx #24
- lda #7
-inflateFixedBlock_3:
- sta endCodeLength-1,x
- dex
- bne inflateFixedBlock_3
- ldx #30
- lda #5+DISTANCE_TREE
-inflateFixedBlock_4:
- sta distanceCodeLength-1,x
- dex
- bne inflateFixedBlock_4
- jmp inflateCodes
-
-; --------------------------------------------------------------------------
-; Decompress Huffman-coded data block, reading Huffman trees first
-
-inflateDynamicBlock:
-; numberOfLiteralCodes = getBits(5) + 257;
- ldx #5
- lda #<(lengthCodeLength-1)
- jsr getBits
- sta nl
-; numberOfDistanceCodes = getBits(5) + 1;
- ldx #5
- lda #1
- jsr getBits
- sta nd
- clc
- adc nl
- sta nl
-; numberOfTemporaryCodes = getBits(4) + 4;
- lda #4
- tax
- jsr getBits
- sta cnt
-; Clear lengths of temporary codes (there're 19 temp codes max),
-; clear literalCodeLength-1 (it may be used by temporary code 16)
-; and leave #0 in Y
- ldy #20
- lda #0
-inflateDynamicBlock_1:
- sta literalCodeLength-2,y
- dey
- bne inflateDynamicBlock_1
-; Get lengths of temporary codes in order stored in bll
-inflateDynamicBlock_2:
- ldx #3
- lda #0
- jsr getBits ; does not change Y
- ldx bll,y
- sta literalCodeLength,x
- iny
- cpy cnt
- bcc inflateDynamicBlock_2
- ror literalCodeLength+19 ; C flag is set, so it will set b7
-; Build tree for temporary codes
- jsr buildHuffmanTree
-
-; Use temporary codes to get lengths for literal and distance codes
-; dest is target-1, so we can access last written byte by (dest,0)
- lda #<(literalCodeLength-1)
- sta dest
- lda #>(literalCodeLength-1)
- sta dest+1
-inflateDynamicBlock_3:
- jsr fetchLiteralCode
-; Temporary code 0..15: put this length
- ldy #1
- cmp #16
- bcc inflateDynamicBlock_6
- bne inflateDynamicBlock_4
-; Temporary code 16: repeat last length 3..6 times
- ldx #2
- lda #3
- jsr getBits
- tay
- lda (dest,x) ; X == 0
- bpl inflateDynamicBlock_6 ; branch always
-inflateDynamicBlock_4:
- lsr a
-; Temporary code 17: put zero length 3..10 times
- lda #3
- tax
- bcs inflateDynamicBlock_5
-; Temporary code 18: put zero length 11..138 times
- ldx #7
- lda #11
-inflateDynamicBlock_5:
- jsr getBits
- tay
- lda #0
-; Write A length Y times
-inflateDynamicBlock_6:
- sty cnt
-inflateDynamicBlock_7:
- sta (dest),y
- dey
- bne inflateDynamicBlock_7
- lda cnt
- clc
- adc dest
- sta dest
- bcc inflateDynamicBlock_8
- inc dest+1
-inflateDynamicBlock_8:
- cmp nl
- bne inflateDynamicBlock_3
- ldy dest+1
- sbc #<endCodeLength ; C flag is set
- bcs inflateDynamicBlock_11
- dey
-inflateDynamicBlock_11:
- cpy #>endCodeLength
- bcc inflateDynamicBlock_3
-; Mark end of distance lengths
- ldx nd
- tay
- ror distanceCodeLength,x ; C flag is set, so it will set b7
-; Move distance lengths to distanceCodeLength table
-inflateDynamicBlock_9:
- dex
- lda endCodeLength,y
-; Mark existing codes (of non-zero length) as distance tree codes
- beq inflateDynamicBlock_10
- pha
- lda #0
- sta endCodeLength,y
- pla
- clc
- adc #DISTANCE_TREE
- sta distanceCodeLength,x
-inflateDynamicBlock_10:
- dey
- txa
- bne inflateDynamicBlock_9
-; fall into inflateCodes
-
-; --------------------------------------------------------------------------
-; Decompress data block basing on given Huffman trees
-
-inflateCodes:
- jsr buildHuffmanTree
-inflateCodes_1:
- jsr fetchLiteralCode
- bcc inflateCodes_2
-; Literal code
- ldy #0
- sta (outputPointer),y
- inc outputPointer
- bne inflateCodes_1
- inc outputPointer+1
- bcs inflateCodes_1 ; branch always
-; End of block
-inflateCodes_ret:
- rts
-inflateCodes_2:
- beq inflateCodes_ret
-; Repeat block
- jsr getValue
- sta len
- tya
- jsr getBits
- sta len+1
- ldx #DISTANCE_TREE
- jsr fetchCode
- jsr getValue
- sta src
- tya
- jsr getBits
- sta src+1
- lda outputPointer
- sec
- sbc src
- sta src
- lda outputPointer+1
- sbc src+1
- sta src+1
- ldx #src
- jsr moveBlock
- beq inflateCodes_1 ; branch always
-
-; --------------------------------------------------------------------------
-; Build Huffman trees basing on code lengths.
-; Lengths (in bits) are stored in literalCodeLength.
-; A byte with highest bit set marks end of length table.
-
-buildHuffmanTree:
- lda #<literalCodeLength
- sta buildHuffmanTree_3+1
- sta buildHuffmanTree_9+1
- lda #>literalCodeLength
- sta buildHuffmanTree_3+2
- sta buildHuffmanTree_9+2
-; Clear counts
- ldx #TREES_SIZE-1
- lda #0
-buildHuffmanTree_1:
- sta bitsCount,x
- dex
- bpl buildHuffmanTree_1
- bmi buildHuffmanTree_3 ; branch always
-; Count number of codes of each length
-buildHuffmanTree_2:
- inc bitsCount,x
- inc buildHuffmanTree_3+1
- bne buildHuffmanTree_3
- inc buildHuffmanTree_3+2
-buildHuffmanTree_3:
- ldx $ffff ; patched at runtime
- bpl buildHuffmanTree_2
-; Calculate pointer for each length
- tax ; ldx #0
- stx bitsCount
- lda #<sortedCodes
- ldy #>sortedCodes
-buildHuffmanTree_4:
- sta bitsPointer_l,x
- tya
- sta bitsPointer_h,x
- lda bitsCount,x
- asl a
- bcc buildHuffmanTree_5
- iny
- clc
-buildHuffmanTree_5:
- adc bitsPointer_l,x
- bcc buildHuffmanTree_6
- iny
-buildHuffmanTree_6:
- inx
- cpx #TREES_SIZE
- bcc buildHuffmanTree_4
- bcs buildHuffmanTree_9 ; branch always
-; Put codes into their place in sorted table
-buildHuffmanTree_7:
- beq buildHuffmanTree_8
- lda bitsPointer_l,x
- sta ptr
- clc
- adc #2
- sta bitsPointer_l,x
- lda bitsPointer_h,x
- sta ptr+1
- adc #0
- sta bitsPointer_h,x
- lda buildHuffmanTree_9+1
- sbc #<(endCodeLength-1) ; C flag is zero
- ldy #1
- sta (ptr),y
- lda buildHuffmanTree_9+2
- sbc #>(endCodeLength-1)
-.ifpc02
- sta (ptr)
-.else
- dey
- sta (ptr),y
-.endif
-buildHuffmanTree_8:
- inc buildHuffmanTree_9+1
- bne buildHuffmanTree_9
- inc buildHuffmanTree_9+2
-buildHuffmanTree_9:
- ldx $ffff ; patched at runtime
- bpl buildHuffmanTree_7
- rts
-
-; --------------------------------------------------------------------------
-; Read code basing on literal tree
-
-fetchLiteralCode:
- ldx #LITERAL_TREE
-; fall into fetchCode
-
-; --------------------------------------------------------------------------
-; Read code from input stream basing on tree given in X.
-; Return code in A, C is set if non-literal code.
-
-fetchCode:
- lda #0
-fetchCode_1:
- jsr getBit
- rol a
- cmp bitsCount+1,x
- bcc fetchCode_2
- sbc bitsCount+1,x
- inx
- bcs fetchCode_1 ; branch always
-fetchCode_2:
- ldy bitsPointer_l,x
- sty ptr
- ldy bitsPointer_h,x
- asl a
- bcc fetchCode_3
- iny
-fetchCode_3:
- sty ptr+1
- tay
- lda (ptr),y
- asl a
- iny
- lda (ptr),y
- rts
-
-; --------------------------------------------------------------------------
-; Read low byte of value (length or distance), basing on code A
-
-getValue:
- tay
- ldx lengthExtraBits-1,y
- lda lengthCode_l-1,y
- pha
- lda lengthCode_h-1,y
- tay
- pla
-; fall into getBits
-
-; --------------------------------------------------------------------------
-; Read X-bit number from input stream and adds it to A.
-; In case of carry, Y is incremented.
-; If X > 8, only 8 bits are read.
-; On return X holds number of unread bits: X = (X > 8 ? X - 8 : 0);
-
-getBits:
- cpx #0
- beq getBits_ret
- pha
- lda #1
- sta tmp
- pla
-getBits_1:
- jsr getBit
- bcc getBits_2
- clc
- adc tmp
- bcc getBits_2
- iny
-getBits_2:
- dex
- beq getBits_ret
- asl tmp
- bcc getBits_1
-getBits_ret:
- rts
-
-; --------------------------------------------------------------------------
-; Read single bit from input stream, return it in C flag
-
-getBit:
- lsr getBitHold
- bne getBit_ret
- pha
-.ifpc02
- lda (inputPointer)
-.else
- tya
- pha
- ldy #0
- lda (inputPointer),y
-.endif
- inc inputPointer
- bne getBit_1
- inc inputPointer+1
-getBit_1:
- ror a ; C flag set
- sta getBitHold
-.ifpc02
-.else
- pla
- tay
-.endif
- pla
-getBit_ret:
- rts
-
-; --------------------------------------------------------------------------
-; Addresses of functions extracting different blocks
-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 temporary codes are stored
-bll:
- .byte 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
-
-; --------------------------------------------------------------------------
-; Tables for length and distance codes
-; Value is Code + getBits(ExtraBits)
-
-; Base values
-lengthCode_l:
- .byte <3,<4,<5,<6,<7,<8,<9,<10
- .byte <11,<13,<15,<17,<19,<23,<27,<31
- .byte <35,<43,<51,<59,<67,<83,<99,<115
- .byte <131,<163,<195,<227,<258
-distanceCode_l:
- .byte <1,<2,<3,<4,<5,<7,<9,<13
- .byte <17,<25,<33,<49,<65,<97,<129,<193
- .byte <257,<385,<513,<769,<1025,<1537,<2049,<3073
- .byte <4097,<6145,<8193,<12289,<16385,<24577
-lengthCode_h:
- .byte >3,>4,>5,>6,>7,>8,>9,>10
- .byte >11,>13,>15,>17,>19,>23,>27,>31
- .byte >35,>43,>51,>59,>67,>83,>99,>115
- .byte >131,>163,>195,>227,>258
-distanceCode_h:
- .byte >1,>2,>3,>4,>5,>7,>9,>13
- .byte >17,>25,>33,>49,>65,>97,>129,>193
- .byte >257,>385,>513,>769,>1025,>1537,>2049,>3073
- .byte >4097,>6145,>8193,>12289,>16385,>24577
-
-; Number of extra bits to read
-lengthExtraBits:
- .byte 0,0,0,0,0,0,0,0
- .byte 1,1,1,1,2,2,2,2
- .byte 3,3,3,3,4,4,4,4
- .byte 5,5,5,5,0
-distanceExtraBits:
- .byte 0,0,0,0,1,1,2,2
- .byte 3,3,4,4,5,5,6,6
- .byte 7,7,8,8,9,9,10,10
- .byte 11,11,12,12,13,13
-
-; --------------------------------------------------------------------------
-;
-; Uninitialised data
-;
-
- .bss
-
-; --------------------------------------------------------------------------
-; Data for building literal tree
-
- .res 1
-; Length of literal codes
-literalCodeLength:
- .res 256
-; Length of 'end' code
-endCodeLength:
- .res 1
-; Length of 'length' codes
-lengthCodeLength:
- .res 29
-
-; --------------------------------------------------------------------------
-; Data for building distance tree
-
-distanceCodeLength:
- .res 30
-; For two unused codes in fixed trees and an end flag
- .res 3
-
-; --------------------------------------------------------------------------
-; Huffman tree structure
-
-; Number of codes of each length
-bitsCount:
- .res TREES_SIZE
-
-; Pointer to sorted codes of each length
-bitsPointer_l:
- .res TREES_SIZE
-bitsPointer_h:
- .res TREES_SIZE
-
-; Sorted codes
-sortedCodes:
- .res 2*(256+1+29+30+2)
-
-
-
+;\r
+; Piotr Fusik, 18.11.2001\r
+;\r
+; unsigned __fastcall__ inflatemem (char* dest, const char* source);\r
+;\r
+\r
+ .export _inflatemem\r
+\r
+ .import incsp2\r
+ .importzp sp, sreg\r
+ .importzp ptr1, ptr2, ptr3, ptr4\r
+ .importzp tmp1, tmp2, tmp3, tmp4\r
+\r
+; --------------------------------------------------------------------------\r
+;\r
+; Constants\r
+;\r
+\r
+; Maximum length of a Huffman code\r
+MAX_BITS = 15\r
+; Index in bitsCount, bitsPointer_l and bitsPointer_h for literal tree\r
+LITERAL_TREE = 0\r
+; Index in bitsCount, bitsPointer_l and bitsPointer_h for distance tree\r
+DISTANCE_TREE = MAX_BITS\r
+; Size of each of bitsCount, bitsPointer_l and bitsPointer_h\r
+TREES_SIZE = 2*MAX_BITS+1\r
+\r
+; --------------------------------------------------------------------------\r
+;\r
+; Page zero\r
+;\r
+\r
+; Pointer to compressed data\r
+inputPointer = ptr1 ; 2 bytes\r
+; Pointer to uncompressed data\r
+outputPointer = ptr2 ; 2 bytes\r
+; Buffer for getBit\r
+getBitHold = tmp1 ; 1 byte\r
+; Local variables. Variables from different routines use same memory.\r
+cnt = tmp2 ; 1 byte\r
+tmp = sreg ; 1 byte\r
+ptr = sreg ; 2 bytes\r
+len = ptr3 ; 2 bytes\r
+nl = tmp3 ; 1 byte\r
+nd = tmp4 ; 1 byte\r
+src = ptr4 ; 2 bytes\r
+dest = ptr4 ; 2 bytes\r
+\r
+; --------------------------------------------------------------------------\r
+;\r
+; Code\r
+;\r
+\r
+_inflatemem:\r
+\r
+; inputPointer = source\r
+ sta inputPointer\r
+ stx inputPointer+1\r
+; outputPointer = dest\r
+ ldy #0\r
+ lda (sp),y\r
+ sta outputPointer\r
+ iny\r
+ lda (sp),y\r
+ sta outputPointer+1\r
+\r
+; ldy #1\r
+ sty getBitHold\r
+inflatemem_1:\r
+; Get a bit of EOF and two bits of block type\r
+ ldx #3\r
+ lda #0\r
+ jsr getBits\r
+ lsr a\r
+ tax\r
+; X contains block type, C contains EOF flag\r
+; Save EOF flag\r
+ php\r
+; Go to the routine decompressing this block\r
+ jsr callExtr\r
+ plp\r
+ bcc inflatemem_1\r
+; C flag is set!\r
+\r
+; return outputPointer - dest;\r
+ lda outputPointer\r
+ ldy #0\r
+ sbc (sp),y ; C flag is set\r
+ pha\r
+ iny\r
+ lda outputPointer+1\r
+ sbc (sp),y\r
+ tax\r
+ pla\r
+; pop dest\r
+ jmp incsp2\r
+\r
+; --------------------------------------------------------------------------\r
+; Go to the routine decompressing block type X\r
+\r
+callExtr:\r
+ lda extr_h,x\r
+ pha\r
+ lda extr_l,x\r
+ pha\r
+ rts\r
+\r
+; --------------------------------------------------------------------------\r
+; Decompress 'stored' data block\r
+\r
+inflateCopyBlock:\r
+; Ignore bits until byte boundary\r
+ ldy #1\r
+ sty getBitHold\r
+; Get 16-bit length\r
+ ldx #inputPointer\r
+ lda (0,x)\r
+ sta len\r
+ lda (inputPointer),y\r
+ sta len+1\r
+; Skip length and one's compliment length\r
+ lda #4\r
+ clc\r
+ adc inputPointer\r
+ sta inputPointer\r
+ bcc moveBlock\r
+ inc inputPointer+1\r
+; fall into moveBlock\r
+\r
+; --------------------------------------------------------------------------\r
+; Copy block of length len from (0,x) to output\r
+\r
+moveBlock:\r
+ ldy len\r
+ beq moveBlock_1\r
+ ldy #0\r
+ inc len+1\r
+moveBlock_1:\r
+ lda (0,x)\r
+ sta (outputPointer),y\r
+ inc 0,x\r
+ bne moveBlock_2\r
+ inc 1,x\r
+moveBlock_2:\r
+ inc outputPointer\r
+ bne moveBlock_3\r
+ inc outputPointer+1\r
+moveBlock_3:\r
+ dec len\r
+ bne moveBlock_1\r
+ dec len+1\r
+ bne moveBlock_1\r
+ rts\r
+\r
+; --------------------------------------------------------------------------\r
+; Decompress Huffman-coded data block with default Huffman trees:\r
+; literalCodeLength: 144 times 8, 112 times 9\r
+; endCodeLength: 24 times 7, 6 times 8\r
+; distanceCodeLength: 30 times 5, 2 times 8\r
+; (2 last codes from literal tree are not used)\r
+\r
+inflateFixedBlock:\r
+ ldx #159\r
+ stx distanceCodeLength+32\r
+ lda #8\r
+inflateFixedBlock_1:\r
+ sta literalCodeLength-1,x\r
+ sta literalCodeLength+159-1,x\r
+ dex\r
+ bne inflateFixedBlock_1\r
+ ldx #112\r
+ lda #9\r
+inflateFixedBlock_2:\r
+ sta literalCodeLength+144-1,x\r
+ dex\r
+ bne inflateFixedBlock_2\r
+ ldx #24\r
+ lda #7\r
+inflateFixedBlock_3:\r
+ sta endCodeLength-1,x\r
+ dex\r
+ bne inflateFixedBlock_3\r
+ ldx #30\r
+ lda #5+DISTANCE_TREE\r
+inflateFixedBlock_4:\r
+ sta distanceCodeLength-1,x\r
+ dex\r
+ bne inflateFixedBlock_4\r
+ jmp inflateCodes\r
+\r
+; --------------------------------------------------------------------------\r
+; Decompress Huffman-coded data block, reading Huffman trees first\r
+\r
+inflateDynamicBlock:\r
+; numberOfLiteralCodes = getBits(5) + 257;\r
+ ldx #5\r
+ lda #<(lengthCodeLength-1)\r
+ jsr getBits\r
+ sta nl\r
+; numberOfDistanceCodes = getBits(5) + 1;\r
+ ldx #5\r
+ lda #1\r
+ jsr getBits\r
+ sta nd\r
+ clc\r
+ adc nl\r
+ sta nl\r
+; numberOfTemporaryCodes = getBits(4) + 4;\r
+ lda #4\r
+ tax\r
+ jsr getBits\r
+ sta cnt\r
+; Clear lengths of temporary codes (there're 19 temp codes max),\r
+; clear literalCodeLength-1 (it may be used by temporary code 16)\r
+; and leave #0 in Y\r
+ ldy #20\r
+ lda #0\r
+inflateDynamicBlock_1:\r
+ sta literalCodeLength-2,y\r
+ dey\r
+ bne inflateDynamicBlock_1\r
+; Get lengths of temporary codes in order stored in bll\r
+inflateDynamicBlock_2:\r
+ ldx #3\r
+ lda #0\r
+ jsr getBits ; does not change Y\r
+ ldx bll,y\r
+ sta literalCodeLength,x\r
+ iny\r
+ cpy cnt\r
+ bcc inflateDynamicBlock_2\r
+ ror literalCodeLength+19 ; C flag is set, so it will set b7\r
+; Build tree for temporary codes\r
+ jsr buildHuffmanTree\r
+\r
+; Use temporary codes to get lengths for literal and distance codes\r
+; dest is target-1, so we can access last written byte by (dest,0)\r
+ lda #<(literalCodeLength-1)\r
+ sta dest\r
+ lda #>(literalCodeLength-1)\r
+ sta dest+1\r
+inflateDynamicBlock_3:\r
+ jsr fetchLiteralCode\r
+; Temporary code 0..15: put this length\r
+ ldy #1\r
+ cmp #16\r
+ bcc inflateDynamicBlock_6\r
+ bne inflateDynamicBlock_4\r
+; Temporary code 16: repeat last length 3..6 times\r
+ ldx #2\r
+ lda #3\r
+ jsr getBits\r
+ tay\r
+ lda (dest,x) ; X == 0\r
+ bpl inflateDynamicBlock_6 ; branch always\r
+inflateDynamicBlock_4:\r
+ lsr a\r
+; Temporary code 17: put zero length 3..10 times\r
+ lda #3\r
+ tax\r
+ bcs inflateDynamicBlock_5\r
+; Temporary code 18: put zero length 11..138 times\r
+ ldx #7\r
+ lda #11\r
+inflateDynamicBlock_5:\r
+ jsr getBits\r
+ tay\r
+ lda #0\r
+; Write A length Y times\r
+inflateDynamicBlock_6:\r
+ sty cnt\r
+inflateDynamicBlock_7:\r
+ sta (dest),y\r
+ dey\r
+ bne inflateDynamicBlock_7\r
+ lda cnt\r
+ clc\r
+ adc dest\r
+ sta dest\r
+ bcc inflateDynamicBlock_8\r
+ inc dest+1\r
+inflateDynamicBlock_8:\r
+ cmp nl\r
+ bne inflateDynamicBlock_3\r
+ ldy dest+1\r
+ sbc #<endCodeLength ; C flag is set\r
+ bcs inflateDynamicBlock_11\r
+ dey\r
+inflateDynamicBlock_11:\r
+ cpy #>endCodeLength\r
+ bcc inflateDynamicBlock_3\r
+; Mark end of distance lengths\r
+ ldx nd\r
+ tay\r
+ ror distanceCodeLength,x ; C flag is set, so it will set b7\r
+; Move distance lengths to distanceCodeLength table\r
+inflateDynamicBlock_9:\r
+ dex\r
+ lda endCodeLength,y\r
+; Mark existing codes (of non-zero length) as distance tree codes\r
+ beq inflateDynamicBlock_10\r
+ pha\r
+ lda #0\r
+ sta endCodeLength,y\r
+ pla\r
+ clc\r
+ adc #DISTANCE_TREE\r
+ sta distanceCodeLength,x\r
+inflateDynamicBlock_10:\r
+ dey\r
+ txa\r
+ bne inflateDynamicBlock_9\r
+; fall into inflateCodes\r
+\r
+; --------------------------------------------------------------------------\r
+; Decompress data block basing on given Huffman trees\r
+\r
+inflateCodes:\r
+ jsr buildHuffmanTree\r
+inflateCodes_1:\r
+ jsr fetchLiteralCode\r
+ bcc inflateCodes_2\r
+; Literal code\r
+ ldy #0\r
+ sta (outputPointer),y\r
+ inc outputPointer\r
+ bne inflateCodes_1\r
+ inc outputPointer+1\r
+ bcs inflateCodes_1 ; branch always\r
+; End of block\r
+inflateCodes_ret:\r
+ rts\r
+inflateCodes_2:\r
+ beq inflateCodes_ret\r
+; Repeat block\r
+ jsr getValue\r
+ sta len\r
+ tya\r
+ jsr getBits\r
+ sta len+1\r
+ ldx #DISTANCE_TREE\r
+ jsr fetchCode\r
+ jsr getValue\r
+ sta src\r
+ tya\r
+ jsr getBits\r
+ sta src+1\r
+ lda outputPointer\r
+ sec\r
+ sbc src\r
+ sta src\r
+ lda outputPointer+1\r
+ sbc src+1\r
+ sta src+1\r
+ ldx #src\r
+ jsr moveBlock\r
+ beq inflateCodes_1 ; branch always\r
+\r
+; --------------------------------------------------------------------------\r
+; Build Huffman trees basing on code lengths.\r
+; Lengths (in bits) are stored in literalCodeLength.\r
+; A byte with highest bit set marks end of length table.\r
+\r
+buildHuffmanTree:\r
+ lda #<literalCodeLength\r
+ sta ptr\r
+ sta src\r
+ lda #>literalCodeLength\r
+ sta ptr+1\r
+ sta src+1\r
+; Clear counts\r
+ ldy #TREES_SIZE\r
+ lda #0\r
+buildHuffmanTree_1:\r
+ sta bitsCount-1,y\r
+ dey\r
+ bne buildHuffmanTree_1\r
+ beq buildHuffmanTree_3 ; branch always\r
+; Count number of codes of each length\r
+buildHuffmanTree_2:\r
+ tax\r
+ inc bitsCount,x\r
+ iny\r
+ bne buildHuffmanTree_3\r
+ inc ptr+1\r
+buildHuffmanTree_3:\r
+ lda (ptr),y\r
+ bpl buildHuffmanTree_2\r
+; Calculate pointer for each length\r
+ ldx #0\r
+ stx bitsCount\r
+ lda #<sortedCodes\r
+ ldy #>sortedCodes\r
+buildHuffmanTree_4:\r
+ sta bitsPointer_l,x\r
+ tya\r
+ sta bitsPointer_h,x\r
+ lda bitsCount,x\r
+ asl a\r
+ bcc buildHuffmanTree_5\r
+ iny\r
+ clc\r
+buildHuffmanTree_5:\r
+ adc bitsPointer_l,x\r
+ bcc buildHuffmanTree_6\r
+ iny\r
+buildHuffmanTree_6:\r
+ inx\r
+ cpx #TREES_SIZE\r
+ bcc buildHuffmanTree_4\r
+.ifpc02\r
+ ldy #1\r
+.else\r
+ ldy #0\r
+.endif\r
+ bcs buildHuffmanTree_9 ; branch always\r
+; Put codes into their place in sorted table\r
+buildHuffmanTree_7:\r
+ beq buildHuffmanTree_8\r
+ tax\r
+ lda bitsPointer_l,x\r
+ sta ptr\r
+ clc\r
+ adc #2\r
+ sta bitsPointer_l,x\r
+ lda bitsPointer_h,x\r
+ sta ptr+1\r
+ adc #0\r
+ sta bitsPointer_h,x\r
+ lda src\r
+ sbc #<(endCodeLength-1) ; C flag is zero\r
+.ifpc02\r
+.else\r
+ iny ; ldy #1\r
+.endif\r
+ sta (ptr),y\r
+ lda src+1\r
+ sbc #>(endCodeLength-1)\r
+.ifpc02\r
+ sta (ptr)\r
+.else\r
+ dey ; ldy #0\r
+ sta (ptr),y\r
+.endif\r
+buildHuffmanTree_8:\r
+ inc src\r
+ bne buildHuffmanTree_9\r
+ inc src+1\r
+buildHuffmanTree_9:\r
+.ifpc02\r
+ lda (src)\r
+.else\r
+ lda (src),y\r
+.endif\r
+ bpl buildHuffmanTree_7\r
+ rts\r
+\r
+; --------------------------------------------------------------------------\r
+; Read code basing on literal tree\r
+\r
+fetchLiteralCode:\r
+ ldx #LITERAL_TREE\r
+; fall into fetchCode\r
+\r
+; --------------------------------------------------------------------------\r
+; Read code from input stream basing on tree given in X.\r
+; Return code in A, C is set if non-literal code.\r
+\r
+fetchCode:\r
+ lda #0\r
+fetchCode_1:\r
+ jsr getBit\r
+ rol a\r
+ cmp bitsCount+1,x\r
+ bcc fetchCode_2\r
+ sbc bitsCount+1,x\r
+ inx\r
+ bcs fetchCode_1 ; branch always\r
+fetchCode_2:\r
+ ldy bitsPointer_l,x\r
+ sty ptr\r
+ ldy bitsPointer_h,x\r
+ asl a\r
+ bcc fetchCode_3\r
+ iny\r
+fetchCode_3:\r
+ sty ptr+1\r
+ tay\r
+ lda (ptr),y\r
+ asl a\r
+ iny\r
+ lda (ptr),y\r
+ rts\r
+\r
+; --------------------------------------------------------------------------\r
+; Read low byte of value (length or distance), basing on code A\r
+\r
+getValue:\r
+ tay\r
+ ldx lengthExtraBits-1,y\r
+ lda lengthCode_l-1,y\r
+ pha\r
+ lda lengthCode_h-1,y\r
+ tay\r
+ pla\r
+; fall into getBits\r
+\r
+; --------------------------------------------------------------------------\r
+; Read X-bit number from input stream and adds it to A.\r
+; In case of carry, Y is incremented.\r
+; If X > 8, only 8 bits are read.\r
+; On return X holds number of unread bits: X = (X > 8 ? X - 8 : 0);\r
+\r
+getBits:\r
+ cpx #0\r
+ beq getBits_ret\r
+ pha\r
+ lda #1\r
+ sta tmp\r
+ pla\r
+getBits_1:\r
+ jsr getBit\r
+ bcc getBits_2\r
+ clc\r
+ adc tmp\r
+ bcc getBits_2\r
+ iny\r
+getBits_2:\r
+ dex\r
+ beq getBits_ret\r
+ asl tmp\r
+ bcc getBits_1\r
+getBits_ret:\r
+ rts\r
+\r
+; --------------------------------------------------------------------------\r
+; Read single bit from input stream, return it in C flag\r
+\r
+getBit:\r
+ lsr getBitHold\r
+ bne getBit_ret\r
+ pha\r
+.ifpc02\r
+ lda (inputPointer)\r
+.else\r
+ tya\r
+ pha\r
+ ldy #0\r
+ lda (inputPointer),y\r
+.endif\r
+ inc inputPointer\r
+ bne getBit_1\r
+ inc inputPointer+1\r
+getBit_1:\r
+ ror a ; C flag set\r
+ sta getBitHold\r
+.ifpc02\r
+.else\r
+ pla\r
+ tay\r
+.endif\r
+ pla\r
+getBit_ret:\r
+ rts\r
+\r
+; --------------------------------------------------------------------------\r
+;\r
+; Constant data\r
+;\r
+\r
+ .rodata\r
+; --------------------------------------------------------------------------\r
+; Addresses of functions extracting different blocks\r
+extr_l:\r
+ .byte <(inflateCopyBlock-1)\r
+ .byte <(inflateFixedBlock-1)\r
+ .byte <(inflateDynamicBlock-1)\r
+extr_h:\r
+ .byte >(inflateCopyBlock-1)\r
+ .byte >(inflateFixedBlock-1)\r
+ .byte >(inflateDynamicBlock-1)\r
+\r
+; --------------------------------------------------------------------------\r
+; Order, in which lengths of temporary codes are stored\r
+bll:\r
+ .byte 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15\r
+\r
+; --------------------------------------------------------------------------\r
+; Tables for length and distance codes\r
+; Value is Code + getBits(ExtraBits)\r
+\r
+; Base values\r
+lengthCode_l:\r
+ .byte <3,<4,<5,<6,<7,<8,<9,<10\r
+ .byte <11,<13,<15,<17,<19,<23,<27,<31\r
+ .byte <35,<43,<51,<59,<67,<83,<99,<115\r
+ .byte <131,<163,<195,<227,<258\r
+distanceCode_l:\r
+ .byte <1,<2,<3,<4,<5,<7,<9,<13\r
+ .byte <17,<25,<33,<49,<65,<97,<129,<193\r
+ .byte <257,<385,<513,<769,<1025,<1537,<2049,<3073\r
+ .byte <4097,<6145,<8193,<12289,<16385,<24577\r
+lengthCode_h:\r
+ .byte >3,>4,>5,>6,>7,>8,>9,>10\r
+ .byte >11,>13,>15,>17,>19,>23,>27,>31\r
+ .byte >35,>43,>51,>59,>67,>83,>99,>115\r
+ .byte >131,>163,>195,>227,>258\r
+distanceCode_h:\r
+ .byte >1,>2,>3,>4,>5,>7,>9,>13\r
+ .byte >17,>25,>33,>49,>65,>97,>129,>193\r
+ .byte >257,>385,>513,>769,>1025,>1537,>2049,>3073\r
+ .byte >4097,>6145,>8193,>12289,>16385,>24577\r
+\r
+; Number of extra bits to read\r
+lengthExtraBits:\r
+ .byte 0,0,0,0,0,0,0,0\r
+ .byte 1,1,1,1,2,2,2,2\r
+ .byte 3,3,3,3,4,4,4,4\r
+ .byte 5,5,5,5,0\r
+distanceExtraBits:\r
+ .byte 0,0,0,0,1,1,2,2\r
+ .byte 3,3,4,4,5,5,6,6\r
+ .byte 7,7,8,8,9,9,10,10\r
+ .byte 11,11,12,12,13,13\r
+\r
+; --------------------------------------------------------------------------\r
+;\r
+; Uninitialised data\r
+;\r
+\r
+ .bss\r
+\r
+; --------------------------------------------------------------------------\r
+; Data for building literal tree\r
+\r
+ .res 1\r
+; Length of literal codes\r
+literalCodeLength:\r
+ .res 256\r
+; Length of 'end' code\r
+endCodeLength:\r
+ .res 1\r
+; Length of 'length' codes\r
+lengthCodeLength:\r
+ .res 29\r
+\r
+; --------------------------------------------------------------------------\r
+; Data for building distance tree\r
+\r
+distanceCodeLength:\r
+ .res 30\r
+; For two unused codes in fixed trees and an end flag\r
+ .res 3\r
+\r
+; --------------------------------------------------------------------------\r
+; Huffman tree structure\r
+\r
+; Number of codes of each length\r
+bitsCount:\r
+ .res TREES_SIZE\r
+\r
+; Pointer to sorted codes of each length\r
+bitsPointer_l:\r
+ .res TREES_SIZE\r
+bitsPointer_h:\r
+ .res TREES_SIZE\r
+\r
+; Sorted codes\r
+sortedCodes:\r
+ .res 2*(256+1+29+30+2)\r
+\r
+\r
+\r