
****************************************************************
*
*  Copyright 1988 by CREATIVE FOCUS.  This code is freely
*  distributable as long as this notice is retained and no
*  other conditions are imposed upon its redistribution.
*
*
*  APACK.ASM --
*
*  A fully compatible replacement for Electronic Arts' PACKER.C
*  routine.  Converts data according to the IFF ILBM cmpByteRun1
*  compression protocol:
*
*     control bytes:
*
*       n =  0.. 127:	followed by n+1 bytes of data;
*	n = -1..-127:	followed by byte to be repeated -n+1 times;
*	n =     -128:	don't do no nada.
*
*     calling format:
*
*	 long PackRow(from, too, amt)
*	    char **from, /* pointer to source data pointer */
*		 **too;  /* pointer to destination data pointer */
*	    long amt;	 /* number of bytes to compress */
*
*	 return(number of bytes written to destination);
*
*     effects:
*
*	  *from = *from + amt, and *too = *too + return;
*	  return is "smart," that is, not greater than
*	  MaxPackedSize = amt + ((amt+127) >> 7).
*
*     by commenting out CHECK (below) you disable checking for runs
*     exceeding 128 bytes.  That CHECK is not needed if you are sure
*     the amt to be compressed is always 128 or less.
*
*  !!! DISCLAIMER !!!  You use this code entirely at your own
*  risk.  I don't warrantee its fitness for any purpose.  I
*  can't even guarantee the accuracy of anything I've said
*  about it, though I've tried my damndest to get it right.
*  I may, in fact, be completely out of my tiny little mind :-).
*
*  That being said, I can be reached for questions, comments,
*  or concerns at:
*
*	 Dr. Gerald Hull
*	 CREATIVE FOCUS
*	 12 White Street
*	 Binghamton, N.Y.  13901
*	 (607) 648-4082
*
*	 bix:	 ghull
*	 PLink:  DRJERRY
*
****************************************************************

	xdef	_PackRow

PT	equr	a0		-> beginning of replicate run (if any)
IX	equr	a1		-> end+1 of input line
IP	equr	a2		-> beginning of literal run (if any)
IQ	equr	a3		-> end+1 of lit and/or rep run (if any)
OP	equr	a4		-> end+1 of output line current pos
FP	equr	a6		frame pointer
SP	equr	a7		stack pointer
RT	equr	d0		return value
MX	equr	d1		check for maximum run = MAX
AM	equr	d2		amount
CH	equr	d3		character

REGS	reg	AM/CH/IP/IQ/OP

FRM	equ	8		input line address
TOO	equ	12		output line address
AMT	equ	16		length of input line

MAX	equ	128		maximum encodable output run

* CHECK	equ	1		turns on maximum row checking


_PackRow

****************	CASE 0:	GRAB PARAMS & INITIALIZE
CAS0
	link	FP,#0
	movem.l	REGS,-(sp)
	movea.l	FRM(FP),IP
	movea.l	(IP),IP		IP = *from
	movea.l	IP,IQ		IQ = IP
	movea.l	IQ,IX
	adda.l	AMT(FP),IX	IX = IP + amt
	movea.l	TOO(FP),OP
	movea.l	(OP),OP		OP = *too


****************	CASE 1:	LITERAL RUN
CAS1
	movea.l	IQ,PT		adjust PT (no replicates ret!)
	move.b	(IQ)+,CH	grab character
	cmpa.l	IQ,IX		if input is finished
	beq.s	CAS5		   branch to case 5

	ifd	CHECK
	move.l	IQ,MX
	sub.l	IP,MX
	cmpi	#MAX,MX		if run has reached MAX
	beq.s	CAS6		   branch to case 6
	endc

	cmp.b	(IQ),CH		if next character != CH
	bne.s	CAS1		   stay in case 1

*				else fall into case 2


****************	CASE 2:	AT LEAST 2 BYTE REPEAT
CAS2
	move.b	(IQ)+,CH	grab character
	cmpa.l	IQ,IX		if input is finished
	beq.s	CAS7		   branch to case 7

	ifd	CHECK
	move.l	IQ,MX
	sub.l	IP,MX
	cmpi	#MAX,MX		if run has reached MAX
	beq.s	CAS6		   branch to case 6
	endc

	cmp.b	(IQ),CH		if next character != CH
	bne.s	CAS1		   branch to case 1

*				else fall into case 3


****************	CASE 3:	REPLICATE RUN
CAS3
	move.b	(IQ)+,CH	grab character
	cmpa.l	IQ,IX		if input is finished
	beq.s	CAS7		   branch to case 7

	ifd	CHECK
	move.l	IQ,MX
	sub.l	PT,MX
	cmpi	#MAX,MX		if run has reached MAX
	beq.s	CAS4		   branch to case 4
	endc

	cmp.b	(IQ),CH		if next character = CH
	beq.s	CAS3		   stay in case 3

*				else fall into case 4


****************	CASE 4:	LIT AND/OR REP DUMP & CONTINUE
CAS4
	move.l	PT,AM
	sub.l	IP,AM		AM = PT - IP
*				if no literal run
	beq.s	C41		   branch to replicate run

	subq	#1,AM		AM = AM -1
	move.b	AM,(OP)+	output literal control byte

C40	move.b	(IP)+,(OP)+	output literal run
	dbra	AM,C40

C41	move.l	PT,AM
	sub.l	IQ,AM		AM = PT - IQ (negative result!)
	addq	#1,AM		AM = AM + 1
	move.b	AM,(OP)+	output replicate control byte
	move.b	CH,(OP)+	output repeated character
	movea.l	IQ,IP		reset IP
	bra.s	CAS1		branch to case 1 (not done)


****************	CASE 5:	LITERAL DUMP & QUIT
CAS5
	move.l	IQ,AM
	sub.l	IP,AM		AM = PT - IP
	subq	#1,AM		AM = AM -1
	move.b	AM,(OP)+	output literal control byte

C50	move.b	(IP)+,(OP)+	output literal run
	dbra	AM,C50

	bra.s	CAS8		branch to case 8 (done)


	ifd	CHECK

****************	CASE 6:	LITERAL DUMP & CONTINUE
CAS6
	move.l	IQ,AM
	sub.l	IP,AM		AM = PT - IP
	subq	#1,AM		AM = AM -1
	move.b	AM,(OP)+	output literal control byte

C60	move.b	(IP)+,(OP)+	output literal run
	dbra	AM,C60

	bra.s	CAS1		branch to case 1 (not done)

	endc


****************	CASE 7:	LIT AND/OR REP DUMP & FINISH
CAS7
	move.l	PT,AM
	sub.l	IP,AM		AM = PT - IP
*				if no literal run
	beq.s	C71		   branch to replicate run

	subq	#1,AM		AM = AM -1
	move.b	AM,(OP)+	output literal control byte

C70	move.b	(IP)+,(OP)+	output literal run
	dbra	AM,C70

C71	move.l	PT,AM
	sub.l	IQ,AM		AM = PT - IQ (negative result!)
	addq	#1,AM		AM = AM + 1
	move.b	AM,(OP)+	output replicate control byte
	move.b	CH,(OP)+	output repeated character

*				fall into case 8


****************	CASE 8:	ADJUST PARAMS & RETURN VALUE
CAS8
	movea.l	FRM(FP),PT	PT = **from
	move.l	IQ,(PT)		*from = *from + amt
	movea.l	TOO(FP),PT	PT = **too

	move.l	OP,RT
	sub.l	(PT),RT		return = OP - *too

	move.l	OP,(PT)		*too = *too + return
	movem.l	(SP)+,REGS
	UNLK	FP
	rts
