From: cuz Date: Sun, 18 Nov 2001 20:05:57 +0000 (+0000) Subject: Update from Piotr X-Git-Tag: V2.12.0~2486 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f2967f26fcea5d183ba4d8b13cdc2c5db0a03ab5;p=cc65 Update from Piotr git-svn-id: svn://svn.cc65.org/cc65/trunk@1124 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/include/zlib.h b/include/zlib.h index e7a145307..9bc5dcb27 100644 --- a/include/zlib.h +++ b/include/zlib.h @@ -1,53 +1,172 @@ -/*****************************************************************************/ -/* */ -/* 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 - - - +/*****************************************************************************/ +/* */ +/* zlib.h */ +/* */ +/* Decompression routines for the 'deflate' format */ +/* */ +/* */ +/* */ +/* (C) 2000-2001 Piotr Fusik */ +/* */ +/* This file is based on the zlib.h from 'zlib' general purpose compression */ +/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */ +/* */ +/* Jean-loup Gailly Mark Adler */ +/* jloup@gzip.org madler@alumni.caltech.edu */ +/* */ +/* 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 + +#define Z_OK 0 +#define Z_DATA_ERROR (-3) +/* Return codes for uncompress() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported) */ + +#define Z_NULL 0 + + +unsigned __fastcall__ inflatemem (char* dest, const char* source); +/* + Decompresses the source buffer into the destination buffer. + Returns the size of the uncompressed data (number of bytes written starting + from dest). + + This function expects data in the DEFLATE format, described in RFC + (Request for Comments) 1951 in the file + ftp://ds.internic.net/rfc/rfc1951.txt. + + This function does not exist in the original zlib. Its implementation + using original zlib might be following: + + unsigned inflatemem (char* dest, const char* source) + { + z_stream stream; + + stream.next_in = (Bytef*) source; + stream.avail_in = 65535; + + stream.next_out = dest; + stream.avail_out = 65535; + + stream.zalloc = (alloc_func) 0; + stream.zfree = (free_func) 0; + + inflateInit2(&stream, -MAX_WBITS); + inflate(&stream, Z_FINISH); + inflateEnd(&stream); + + return stream.total_out; + } +*/ + + +int uncompress (char* dest, unsigned* destLen, + const char* source, unsigned sourceLen); +/* + Original zlib description: + + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. + + Implementation notes: + + This function expects data in the ZLIB format, described in RFC 1950 + in the file ftp://ds.internic.net/rfc/rfc1950.txt. The ZLIB format is + essentially the DEFLATE format plus a very small header and Adler-32 + checksum. + + Z_MEM_ERROR and Z_BUF_ERROR are never returned in this implementation. +*/ + + +unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf, + unsigned len); + +/* + Original zlib description: + + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + unsigned long adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); + + Implementation notes: + + This function isn't actually much faster than crc32(), but it is smaller + and does not use any lookup tables. +*/ + + +unsigned long __fastcall__ crc32 (unsigned long crc, const char* buf, + unsigned len); +/* + Original zlib description: + + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + unsigned long crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); + + Implementation notes: + + This function uses statically allocated 1 KB lookup table. The table is + initialised before it is used for the first time (that is, if buffer is + NULL or length is zero, then the lookup table isn't initialised). +*/ + + +/* end of zlib.h */ +#endif + + + diff --git a/libsrc/zlib/adler32.s b/libsrc/zlib/adler32.s new file mode 100644 index 000000000..bebfdc90c --- /dev/null +++ b/libsrc/zlib/adler32.s @@ -0,0 +1,85 @@ +; +; Piotr Fusik, 18.11.2001 +; +; unsigned long __fastcall__ adler32 (unsigned long adler, unsigned char* buf, +; unsigned len); +; + + .export _adler32 + + .import incsp2, incsp4, popax, popeax + .importzp sreg, ptr1, ptr2, tmp1 + +BASE = 65521 ; largest prime smaller than 65536 + +_adler32: +; ptr2 = (len & 0xff) == 0 ? len : len + 0x100; + tay + beq @L1 + inx +@L1: sta ptr2 + stx ptr2+1 +; ptr1 = buf + jsr popax + sta ptr1 + stx ptr1+1 +; if (buf == NULL) return 1L; + ora ptr1+1 + beq @L0 +; s1 = adler & 0xFFFF; s2 = adler >> 16; + jsr popeax +; if (len == 0) return adler; + ldy ptr2 + bne @L2 + ldy ptr2+1 + beq @RET +@L2: ldy #0 +; s1 += *ptr++; if (s1 >= BASE) s1 -= BASE; +@L3: clc + adc (ptr1),y + bcc @L4 + inx + beq @L5 ; C flag is set +@L4: cpx #>BASE + bcc @L6 + cmp #= BASE) s2 -= BASE; + adc sreg ; C flag is clear + sta sreg + txa + adc sreg+1 + sta sreg+1 + bcs @L7 + cmp #>BASE + bcc @L8 + lda sreg + cmp #BASE + sta sreg+1 +@L8: lda tmp1 + iny + bne @L9 + inc ptr1+1 +@L9: dec ptr2 + bne @L3 + dec ptr2+1 + bne @L3 +; return (s2 << 16) | s1; +@RET: rts + +; return 1L +@L0: sta sreg + sta sreg+1 + lda #1 +; ignore adler + jmp incsp4 diff --git a/libsrc/zlib/crc32.s b/libsrc/zlib/crc32.s new file mode 100644 index 000000000..d47e92f10 --- /dev/null +++ b/libsrc/zlib/crc32.s @@ -0,0 +1,134 @@ +; +; Piotr Fusik, 14.11.2001 +; +; unsigned long __fastcall__ crc32 (unsigned long crc, unsigned char* buf, +; unsigned len); +; + + .export _crc32 + + .import compleax, incsp2, incsp4, popax, popeax + .importzp sreg, ptr1, ptr2, tmp1, tmp2 + +POLYNOMIAL = $EDB88320 + +make_table: + ldx #0 +@L1: lda #0 + sta tmp2 + sta sreg + sta sreg+1 + ldy #8 + txa +@L2: sta tmp1 + lsr a + bcc @L3 + lda sreg+1 + lsr a + eor #(POLYNOMIAL>>24)&$FF + sta sreg+1 + lda sreg + ror a + eor #(POLYNOMIAL>>16)&$FF + sta sreg + lda tmp2 + ror a + eor #(POLYNOMIAL>>8)&$FF + sta tmp2 + lda tmp1 + ror a + eor #POLYNOMIAL&$FF + bcs @L4 ; branch always +@L3: rol a + lsr sreg+1 + ror sreg + ror tmp2 + ror a +@L4: dey + bne @L2 + sta table_0,x + lda tmp2 + sta table_1,x + lda sreg + sta table_2,x + lda sreg+1 + sta table_3,x + inx + bne @L1 + inc table_initialised +RET: + rts + +_crc32: +; ptr2 = (len & 0xff) == 0 ? len : len + 0x100; + tay + beq @L1 + inx +@L1: sta ptr2 + stx ptr2+1 +; ptr1 = buf + jsr popax + sta ptr1 + stx ptr1+1 +; if (buf == NULL) return 0; + ora ptr1+1 + beq @L0 +; if (!tables_initialised) make_tables(); + lda table_initialised + bne @dont_make + jsr make_table +@dont_make: +; eax = crc + jsr popeax +; if (len == 0) return crc; + ldy ptr2 + bne @L2 + ldy ptr2+1 + beq RET +@L2: +; eax = ~crc + jsr compleax + stx tmp2 + ldy #0 +; crc = (crc >> 8) ^ table[(crc & 0xff) ^ *p++]; +@L3: eor (ptr1),y + tax + lda table_0,x + eor tmp2 + sta tmp1 + lda table_1,x + eor sreg + sta tmp2 + lda table_2,x + eor sreg+1 + sta sreg + lda table_3,x + sta sreg+1 + lda tmp1 + iny + bne @L4 + inc ptr1+1 +@L4: dec ptr2 + bne @L3 + dec ptr2+1 + bne @L3 + ldx tmp2 + jmp compleax + +; return 0L +@L0: sta sreg + sta sreg+1 +; ignore crc + jmp incsp4 + + .data +table_initialised: + .byte 0 + + .bss +table_0: .res 256 +table_1: .res 256 +table_2: .res 256 +table_3: .res 256 + + diff --git a/libsrc/zlib/inflatemem.s b/libsrc/zlib/inflatemem.s index 6c2959084..de444ef7d 100644 --- a/libsrc/zlib/inflatemem.s +++ b/libsrc/zlib/inflatemem.s @@ -1,637 +1,673 @@ -; -; 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 - 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+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 -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) - - - +; +; Piotr Fusik, 18.11.2001 +; +; unsigned __fastcall__ inflatemem (char* dest, const char* source); +; + + .export _inflatemem + + .import incsp2 + .importzp sp, sreg + .importzp ptr1, ptr2, ptr3, ptr4 + .importzp 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: + +; inputPointer = source + sta inputPointer + stx inputPointer+1 +; outputPointer = dest + ldy #0 + lda (sp),y + sta outputPointer + iny + lda (sp),y + sta outputPointer+1 + +; ldy #1 + sty getBitHold +inflatemem_1: +; Get a bit of EOF and two bits of block type + 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 +; C flag is set! + +; return outputPointer - dest; + lda outputPointer + ldy #0 + sbc (sp),y ; C flag is set + pha + iny + lda outputPointer+1 + sbc (sp),y + tax + pla +; pop dest + jmp incsp2 + +; -------------------------------------------------------------------------- +; 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 + 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 ptr+1 + sta src+1 +; Clear counts + ldy #TREES_SIZE + lda #0 +buildHuffmanTree_1: + sta bitsCount-1,y + dey + bne buildHuffmanTree_1 + beq buildHuffmanTree_3 ; branch always +; Count number of codes of each length +buildHuffmanTree_2: + tax + inc bitsCount,x + iny + bne buildHuffmanTree_3 + inc ptr+1 +buildHuffmanTree_3: + lda (ptr),y + bpl buildHuffmanTree_2 +; Calculate pointer for each length + ldx #0 + stx bitsCount + lda #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 +.ifpc02 + ldy #1 +.else + ldy #0 +.endif + bcs buildHuffmanTree_9 ; branch always +; Put codes into their place in sorted table +buildHuffmanTree_7: + beq buildHuffmanTree_8 + tax + 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 src + sbc #<(endCodeLength-1) ; C flag is zero +.ifpc02 +.else + iny ; ldy #1 +.endif + sta (ptr),y + lda src+1 + sbc #>(endCodeLength-1) +.ifpc02 + sta (ptr) +.else + dey ; ldy #0 + sta (ptr),y +.endif +buildHuffmanTree_8: + inc src + bne buildHuffmanTree_9 + inc src+1 +buildHuffmanTree_9: +.ifpc02 + lda (src) +.else + lda (src),y +.endif + 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 + +; -------------------------------------------------------------------------- +; +; Constant data +; + + .rodata +; -------------------------------------------------------------------------- +; 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) + + + diff --git a/libsrc/zlib/uncompress.c b/libsrc/zlib/uncompress.c new file mode 100644 index 000000000..fb07ba43a --- /dev/null +++ b/libsrc/zlib/uncompress.c @@ -0,0 +1,36 @@ +/* + * uncompress.c + * + * Piotr Fusik, 18.11.2001 + */ + +#include + +int uncompress (char* dest, unsigned* destLen, + const char* source, unsigned sourceLen) +{ + unsigned len; + unsigned char* ptr; + unsigned long csum; + /* source[0]: Compression method and flags + bits 0 to 3: Compression method (must be Z_DEFLATED) + bits 4 to 7: Compression info (must be <= 7) + source[1]: Flags + bits 0 to 4: Check bits + bit 5: Preset dictionary (not supported, sorry) + bits 6 to 7: Compression level + */ + if ((source[0] & 0x8f) != Z_DEFLATED || source[1] & 0x20) + return Z_DATA_ERROR; + if ((((unsigned) source[0] << 8) | (unsigned char) source[1]) % 31) + return Z_DATA_ERROR; + *destLen = len = inflatemem(dest, source + 2); + ptr = (unsigned char*) source + sourceLen - 4; + csum = adler32(adler32(0L, Z_NULL, 0), dest, len); + if ((unsigned char) csum != ptr[3] + || (unsigned char) (csum >> 8) != ptr[2] + || (unsigned char) (csum >> 16) != ptr[1] + || (unsigned char) (csum >> 24) != ptr[0]) + return Z_DATA_ERROR; + return Z_OK; +}