1
0
mirror of https://github.com/cc65/cc65.git synced 2025-03-13 15:32:09 +00:00

Update from Piotr

git-svn-id: svn://svn.cc65.org/cc65/trunk@1124 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-11-18 20:05:57 +00:00
parent 2de4a26251
commit f2967f26fc
5 changed files with 1100 additions and 690 deletions

View File

@ -6,10 +6,13 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2001 Piotr Fusik */ /* (C) 2000-2001 Piotr Fusik <fox@scene.pl> */
/* a.k.a. Fox/Taquart */
/* EMail: fox@scene.pl */
/* */ /* */
/* 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 */ /* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */ /* warranty. In no event will the authors be held liable for any damages */
@ -35,16 +38,132 @@
#ifndef _ZLIB_H #ifndef _ZLIB_H
#define _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
void* inflatemem (void* dest, void* src); unsigned __fastcall__ inflatemem (char* dest, const char* source);
/* Read the deflate compressed data starting from src and store /*
* the uncompressed data starting from dest. Decompresses the source buffer into the destination buffer.
* Return pointer to a byte after the decompressed data. That is, the result Returns the size of the uncompressed data (number of bytes written starting
* minus dest is the size of the decompressed data. 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 */ /* end of zlib.h */
#endif #endif

85
libsrc/zlib/adler32.s Normal file
View File

@ -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
bcc @L6
inx ; ldx #0
@L5: sbc #<BASE ; C flag is set
clc
@L6: sta tmp1
; s2 += s1; if (s2 >= 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
bcc @L8
@L7: lda sreg
sbc #<BASE ; C flag is set
sta sreg
lda sreg+1
sbc #>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

134
libsrc/zlib/crc32.s Normal file
View File

@ -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

View File

@ -1,13 +1,15 @@
; ;
; Piotr Fusik, 11.11.2001 ; Piotr Fusik, 18.11.2001
; ;
; void* inflatemem (void* dest, void* src); ; unsigned __fastcall__ inflatemem (char* dest, const char* source);
; ;
.export _inflatemem .export _inflatemem
.import popax .import incsp2
.importzp sreg, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, tmp4 .importzp sp, sreg
.importzp ptr1, ptr2, ptr3, ptr4
.importzp tmp1, tmp2, tmp3, tmp4
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
; ;
@ -51,18 +53,21 @@ dest = ptr4 ; 2 bytes
_inflatemem: _inflatemem:
; Get inputPointer and outputPointer from stack ; inputPointer = source
jsr popax
sta inputPointer sta inputPointer
stx inputPointer+1 stx inputPointer+1
jsr popax ; outputPointer = dest
ldy #0
lda (sp),y
sta outputPointer sta outputPointer
stx outputPointer+1 iny
lda (sp),y
sta outputPointer+1
ldy #1 ; ldy #1
sty getBitHold sty getBitHold
; Get a bit of EOF and two bits of block type
inflatemem_1: inflatemem_1:
; Get a bit of EOF and two bits of block type
ldx #3 ldx #3
lda #0 lda #0
jsr getBits jsr getBits
@ -75,9 +80,20 @@ inflatemem_1:
jsr callExtr jsr callExtr
plp plp
bcc inflatemem_1 bcc inflatemem_1
; C flag is set!
; return outputPointer - dest;
lda outputPointer lda outputPointer
ldx outputPointer+1 ldy #0
rts 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 ; Go to the routine decompressing block type X
@ -347,30 +363,31 @@ inflateCodes_2:
buildHuffmanTree: buildHuffmanTree:
lda #<literalCodeLength lda #<literalCodeLength
sta buildHuffmanTree_3+1 sta ptr
sta buildHuffmanTree_9+1 sta src
lda #>literalCodeLength lda #>literalCodeLength
sta buildHuffmanTree_3+2 sta ptr+1
sta buildHuffmanTree_9+2 sta src+1
; Clear counts ; Clear counts
ldx #TREES_SIZE-1 ldy #TREES_SIZE
lda #0 lda #0
buildHuffmanTree_1: buildHuffmanTree_1:
sta bitsCount,x sta bitsCount-1,y
dex dey
bpl buildHuffmanTree_1 bne buildHuffmanTree_1
bmi buildHuffmanTree_3 ; branch always beq buildHuffmanTree_3 ; branch always
; Count number of codes of each length ; Count number of codes of each length
buildHuffmanTree_2: buildHuffmanTree_2:
tax
inc bitsCount,x inc bitsCount,x
inc buildHuffmanTree_3+1 iny
bne buildHuffmanTree_3 bne buildHuffmanTree_3
inc buildHuffmanTree_3+2 inc ptr+1
buildHuffmanTree_3: buildHuffmanTree_3:
ldx $ffff ; patched at runtime lda (ptr),y
bpl buildHuffmanTree_2 bpl buildHuffmanTree_2
; Calculate pointer for each length ; Calculate pointer for each length
tax ; ldx #0 ldx #0
stx bitsCount stx bitsCount
lda #<sortedCodes lda #<sortedCodes
ldy #>sortedCodes ldy #>sortedCodes
@ -391,10 +408,16 @@ buildHuffmanTree_6:
inx inx
cpx #TREES_SIZE cpx #TREES_SIZE
bcc buildHuffmanTree_4 bcc buildHuffmanTree_4
.ifpc02
ldy #1
.else
ldy #0
.endif
bcs buildHuffmanTree_9 ; branch always bcs buildHuffmanTree_9 ; branch always
; Put codes into their place in sorted table ; Put codes into their place in sorted table
buildHuffmanTree_7: buildHuffmanTree_7:
beq buildHuffmanTree_8 beq buildHuffmanTree_8
tax
lda bitsPointer_l,x lda bitsPointer_l,x
sta ptr sta ptr
clc clc
@ -404,24 +427,31 @@ buildHuffmanTree_7:
sta ptr+1 sta ptr+1
adc #0 adc #0
sta bitsPointer_h,x sta bitsPointer_h,x
lda buildHuffmanTree_9+1 lda src
sbc #<(endCodeLength-1) ; C flag is zero sbc #<(endCodeLength-1) ; C flag is zero
ldy #1 .ifpc02
.else
iny ; ldy #1
.endif
sta (ptr),y sta (ptr),y
lda buildHuffmanTree_9+2 lda src+1
sbc #>(endCodeLength-1) sbc #>(endCodeLength-1)
.ifpc02 .ifpc02
sta (ptr) sta (ptr)
.else .else
dey dey ; ldy #0
sta (ptr),y sta (ptr),y
.endif .endif
buildHuffmanTree_8: buildHuffmanTree_8:
inc buildHuffmanTree_9+1 inc src
bne buildHuffmanTree_9 bne buildHuffmanTree_9
inc buildHuffmanTree_9+2 inc src+1
buildHuffmanTree_9: buildHuffmanTree_9:
ldx $ffff ; patched at runtime .ifpc02
lda (src)
.else
lda (src),y
.endif
bpl buildHuffmanTree_7 bpl buildHuffmanTree_7
rts rts
@ -534,6 +564,12 @@ getBit_ret:
rts rts
; -------------------------------------------------------------------------- ; --------------------------------------------------------------------------
;
; Constant data
;
.rodata
; --------------------------------------------------------------------------
; Addresses of functions extracting different blocks ; Addresses of functions extracting different blocks
extr_l: extr_l:
.byte <(inflateCopyBlock-1) .byte <(inflateCopyBlock-1)

36
libsrc/zlib/uncompress.c Normal file
View File

@ -0,0 +1,36 @@
/*
* uncompress.c
*
* Piotr Fusik, 18.11.2001
*/
#include <zlib.h>
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;
}