 
**************************************************************** 
* 
*  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 yet!) 
      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 = IQ - IP (positive result > 0) 
      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 = IQ - IP (positive result > 0) 
      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      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 (positive result > 0) 
*                             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 
 
      end


