⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flate.a

📁 压缩算法的源代码
💻 A
字号:
; Not copyrighted by Paul Kienitz, 20 Jun 94.;; Assembly language version of inflate_codes(), for Amiga.  Prototype:;;   int flate_codes(struct huft *tl, struct huft *td, int bl, int bd,;                   unsigned char *slide);;; It is called by defining inflate_codes(tl, td, bl, bd) as; flate_codes(tl, td, bl, bd, slide).;; Define the symbol FUNZIP if this is for fUnZip.  Define CRYPT if this is; for fUnZip with decryption enabled.  Define AZTEC to use the Aztec C; buffered input macro instead of the library getc() with FUNZIP.;; => int MUST BE 16 BITS!!! <=                    => WSIZE MUST BE 32K! <=;; struct huft is defined as follows:;;   struct huft {;     uch e;                /* number of extra bits or operation */;     uch b;                /* number of bits in this code or subcode */;     union {;       ush n;              /* literal, length base, or distance base */;       struct huft *t;     /* pointer to next level of table */;     } v;;   };                      /* sizeof(struct huft) == 6 */;; so here we define the offsets of the various members of this struct:h_e		equ	0h_b		equ	1h_n		equ	2h_t		equ	2SIZEOF_HUFT	equ	6; There are several global variables we need to access.  Their definitions:;;   unsigned long bb;;   unsigned int bk, wp;;   unsigned short mask[17];;   FILE *in;;   int encrypted;			/* FUNZIP CRYPT only */;;   int incnt, mem_mode;		/* non-FUNZIP only */;   long csize;				/* non-FUNZIP only */;   unsigned long outcnt;		/* non-FUNZIP only */;   unsigned char *inptr;		/* non-FUNZIP only */;; bb is the global buffer that holds bits from the huffman code stream, which; we cache in the register variable b.  bk is the number of valid bits in it,; which we cache in k.  The macros NEEDBITS(n) and DUMPBITS(n) have side effects; on b and k.	xref	_bb	xref	_bk	xref	_mask	xref	_wp		IFD	FUNZIP		 IFD	CRYPT	xref	_encrypted	xref	_update_keys	; int update_keys(int)	xref	_decrypt_byte	; int decrypt_byte(void)		 ENDC	; CRYPT	xref	_in	xref	_getc		; int getc(FILE *)		ELSE	; !FUNZIP	xref	_csize	xref	_incnt	xref	_mem_mode	xref	_inptr	xref	_readbyte	; int readbyte(void)		ENDC	xref	_flush		; if FUNZIP:  int flush(unsigned long)	; ...if !FUNZIP:  int flush(unsigned char *, unsigned long *, int); Here are our register variables.  Remember that int == short!b	equr	d2		; unsigned longk	equr	d3		; unsigned int <= 32e	equr	d4		; unsigned int < 256 for most usew	equr	d5		; unsigned intn	equr	d6		; unsigned intd	equr	d7		; unsigned int; assert: we always maintain w and d as valid unsigned longs.t	equr	a2		; struct huft *slide	equr	a3		; unsigned char *mask	equr	a6		; unsigned short *; Couple other items we need:savregs	reg	d2-d7/a2/a3/a6WSIZE	equ	$8000		; 32k... be careful not to treat as negative!		IFD	FUNZIP; This does getc(in).  Aztec version is based on #define getc(fp) in stdio.h		 IFD	AZTEC	xref	__filbufGETC		  MACRO	move.l		_in,a0	move.l		(a0),a1		; in->_bp	cmp.l		4(a0),a1	; in->_bend	blo.s		gci\@	move.l		a0,-(sp)	jsr		__filbuf	addq		#4,sp	bra.s		gce\@gci\@:	moveq		#0,d0		; must be valid as longword	move.b		(a1)+,d0	move.l		a1,(a0)gce\@:		  ENDM		 ELSE	; !AZTECGETC		  MACRO	move.l		_in,-(sp)	jsr		_getc	addq		#4,sp		  ENDM		 ENDC	; AZTEC		ENDC	; FUNZIP; Input depends on the NEXTBYTE macro.  This exists in three different forms.; The first two are for fUnZip, with and without decryption.  The last is for; regular UnZip with or without decryption.  The resulting byte is returned; in d0 as a longword, and d1, a0, and a1 are clobbered.		IFD	FUNZIP		 IFD	CRYPTNEXTBYTE	  MACRO	GETC	tst.w		_encrypted	beq.s		nbe\@	move.w		d0,-(sp)	; save thru next call	jsr		_decrypt_byte	eor.w		d0,(sp)		; becomes arg to update_keys	jsr		_update_keys	addq		#2,spnbe\@:	ext.l		d0		; assert -1 <= d0 <= 255		  ENDM		 ELSE	; !CRYPTNEXTBYTE	  MACRO	GETC			; nothing else in this case		  ENDM		 ENDC		ELSE	; !FUNZIPNEXTBYTE	 MACRO	subq.l		#1,_csize	bge.s		nbg\@	moveq		#-1,d0		; return EOF	bra.s		nbe\@nbg\@:	subq.w		#1,_incnt	bge.s		nbs\@	jsr		_readbyte	bra.s		nbe\@nbs\@:	moveq		#0,d0	move.l		_inptr,a0	move.b		(a0)+,d0	move.l		a0,_inptrnbe\@:		 ENDM		ENDC; FLUSH has different versions for fUnZip and UnZip.  Arg must be a longword.		IFD	FUNZIPFLUSH		 MACRO	move.l		\1,-(sp)	jsr		_flush	addq		#4,sp		 ENDM		ELSE	; !FUNZIP	xref	_mem_mode	xref	_outcntFLUSH		 MACRO	tst.w		_mem_mode	bne.s		fm\@	move.w		#0,-(sp)	; unshrink flag: always false	move.l		\1,-(sp)		; length	move.l		slide,-(sp)	; buffer to flush	jsr		_flush	lea		10(sp),sp	bra.s		fe\@fm\@:	move.l		w,_outcntfe\@:		 ENDM		ENDC	; FUNZIP; Here are the two bit-grabbing macros, defined in their non-CHECK_EOF form:;;   define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}};   define DUMPBITS(n) {b>>=(n);k-=(n);};; NEEDBITS clobbers d0, d1, a0, and a1, none of which can be used as the arg; to the macro specifying the number of bits.  The arg can be a shortword memory; address, or d2-d7.  The result is copied into d1 as a word ready for masking.; DUMPBITS has no side effects; the arg must be a d-register (or immediate in the; range 1-8?) and only the lower byte is significant.NEEDBITS	MACROnb\@:	cmp.w		\1,k		; assert 0 < k <= 32 ... arg may be 0	bhs.s		ne\@	NEXTBYTE			; returns in d0.l	lsl.l		k,d0	or.l		d0,b	addq.w		#8,k	bra.s		nb\@ne\@:	move.w		b,d1		ENDMDUMPBITS	MACRO	lsr.l		\1,b		; upper bits of \1 are ignored??	sub.b		\1,k		ENDM; ******************************************************************************; Here we go, finally:	xdef	_flate_codes	; (pointer, pointer, int, int, pointer)_flate_codes:	link		a5,#-4	movem.l		savregs,-(sp); 8(a5) = tl, 12(a5) = td, 16(a5) = bl, 18(a5) = bd, 20(a5) = slide,; -2(a5) = ml, -4(a5) = md.  Here we cache some globals and args:	move.l		20(a5),slide	lea		_mask,mask	move.l		_bb,b	move.w		_bk,k	moveq		#0,w		; keep this usable as longword	move.w		_wp,w	moveq		#0,e		; keep this usable as longword too	move.w		16(a5),d0	add.w		d0,d0	move.w		(mask,d0.w),-2(a5)	; ml = mask[bl]	move.w		18(a5),d0	add.w		d0,d0	move.w		(mask,d0.w),-4(a5)	; md = mask[bd]main_loop:	NEEDBITS	16(a5)		; bl	and.w		-2(a5),d1	; ml	mulu		#SIZEOF_HUFT,d1	move.l		8(a5),a0	; tl	lea		(a0,d1.l),t	move.b		h_e(t),e	cmp.w		#16,e	bls.s		topdmpintop:	 moveq		#1,d0	 cmp.w		#99,e	 beq		return		; error in zipfile	 move.b		h_b(t),d0	 DUMPBITS	d0	 sub.w		#16,e	 NEEDBITS	e	 move.w		e,d0	 add.w		d0,d0	 and.w		(mask,d0.w),d1	 mulu		#SIZEOF_HUFT,d1	 move.l		h_t(t),a0	 lea		(a0,d1.l),t	 move.b		h_e(t),e	 cmp.w		#16,e	 bgt.s		intoptopdmp:	move.b		h_b(t),d0	DUMPBITS	d0	cmp.w		#16,e		; is this huffman code a literal?	bne		lenchk		; no	move.w		h_n(t),d0	; yes	move.b		d0,(slide,w.l)	; stick in the decoded byte	addq.w		#1,w	cmp.w		#WSIZE,w	blo		main_loop	FLUSH		w	moveq		#0,w	bra		main_loop	; do some morelenchk:	cmp.w		#15,e		; is it an end-of-block code?	beq		finish		; if yes, we're done	NEEDBITS	e		; no: we have a duplicate string	move.w		e,d0	add.w		d0,d0	and.w		(mask,d0.w),d1	move.w		h_n(t),n	add.w		d1,n		; length of block to copy	DUMPBITS	e	NEEDBITS	18(a5)		; bd	and.w		-4(a5),d1	; md	mulu		#SIZEOF_HUFT,d1	move.l		12(a5),a0	; td	lea		(a0,d1.l),t	move.b		h_e(t),e	cmp.w		#16,e	bls.s		middmpinmid:	 moveq		#1,d0	 cmp.w		#99,e	 beq		return		; error in zipfile	 move.b		h_b(t),d0	 DUMPBITS	d0	 sub.w		#16,e	 NEEDBITS	e	 move.w		e,d0	 add.w		d0,d0	 and.w		(mask,d0.w),d1	 mulu		#SIZEOF_HUFT,d1	 move.l		h_t(t),a0	 lea		(a0,d1.l),t	 move.b		h_e(t),e	 cmp.w		#16,e	 bgt.s		inmidmiddmp:	move.b		h_b(t),d0	DUMPBITS	d0	NEEDBITS	e	move.w		e,d0	add.w		d0,d0	and.w		(mask,d0.w),d1	move.l		w,d	sub.w		h_n(t),d	sub.w		d1,d		; distance back to block to copy	DUMPBITS	eindup:	 move.w		#WSIZE,e	; violate the e < 256 rule	 and.w		#WSIZE-1,d	 cmp.w		d,w	 blo.s		ddgw	  sub.w		w,e	 bra.s		dadwddgw:	  sub.w		d,edadw:	 cmp.w		n,e	 bls.s		delen	  move.w	n,edelen:	 sub.w		e,n		; size of sub-block to copy	 move.l		slide,a0	 move.l		a0,a1	 add.l		w,a0		; w and d are valid longwords	 add.l		d,a1	 move.w		e,d0	 subq		#1,d0		; assert >= 0 if sign extendeddspin:	  move.b	(a1)+,(a0)+	; string is probably short, so	  dbra		d0,dspin	; don't use any fancier copy method	 add.w		e,w	 add.w		e,d	 cmp.w		#WSIZE,w	 blo.s		dnfl	 FLUSH		w	 moveq		#0,wdnfl:	 tst.w		n		; need to do more sub-blocks?	 bne		indup		; yes	moveq		#0,e		; restore zeroness in upper bytes	bra		main_loop	; do some morefinish:	move.w		w,_wp		; restore cached globals	move.w		k,_bk	move.l		b,_bb	moveq		#0,d0			; return "no error"return:	movem.l		(sp)+,savregs	unlk		a5	rts

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -