home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / packery / xpk_source / libraries / duke / xpkduke.c < prev    next >
C/C++ Source or Header  |  1996-10-19  |  6KB  |  269 lines

  1. /*
  2.  * This library is mainly intended to demonstrate how to program a sub
  3.  * library.
  4.  */
  5.  
  6. #define VERSION        1
  7.  
  8. #define NO_SUB_PRAGMAS
  9.  
  10. #include <xpk/xpksub.h>
  11. #include <exec/memory.h>
  12. #include <pragma/exec_lib.h>
  13.  
  14. #define SDI_TO_ANSI
  15. #include "SDI_ASM_STD_protos.h"
  16.  
  17. #ifdef __MAXON__
  18.   #define __asm
  19. #endif
  20.  
  21. #define SCANBUFLEN 32768
  22.  
  23. /*
  24.  * Pack a chunk
  25.  */
  26.  
  27. struct NukeData {
  28.     APTR    inbuf;
  29.     APTR    outbuf;
  30.     APTR    last;
  31.     APTR    next;
  32.     CPTR    cwri;
  33.     CPTR    uwri;
  34.     CPTR    uend;
  35.     CPTR    delpos;
  36.     UWORD    ulen;
  37.     UWORD    clen;
  38.     UWORD    ustop;
  39.     UWORD    ustart;
  40.     UWORD    ucount;
  41.     UWORD    scanrange;
  42.     UWORD    room1;
  43.     UWORD    room2;
  44.     UWORD    room4;
  45.     UWORD    roomN;
  46.     UWORD    data1;
  47.     UWORD    data2;
  48.     ULONG    data4;
  49.     ULONG    dataN;
  50.     CPTR    dest1;
  51.     CPTR    dest2;
  52.     CPTR    dest4;
  53.     CPTR    destN;
  54.     ULONG    dummy;
  55.     CPTR    contbuf;
  56.     ULONG    flags;
  57. };
  58.  
  59. #ifdef __cplusplus
  60. extern "C" {
  61. #endif
  62.  
  63. LONG __asm AsmPack  (register __a4 struct NukeData *ND);
  64. STRPTR __asm AsmUnpack(register __a1 STRPTR wread, register __a4 STRPTR bread,
  65.                         register __a0 STRPTR dst, register __a2 STRPTR end);
  66. #ifdef __cplusplus
  67. }
  68. #endif
  69.  
  70.  
  71. #define PACKMEM   (65536+SCANBUFLEN)*sizeof(USHORT)+sizeof(struct NukeData)+SCANBUFLEN
  72. #define UNPACKMEM SCANBUFLEN
  73. #define A3000     XPKMF_A3000SPEED
  74.  
  75. static struct XpkMode NukeMode = {
  76.   NULL,       // Next mode
  77.   100,        // Handles up to
  78.   A3000,      // Flags
  79.   PACKMEM,    // Packing memory
  80.   UNPACKMEM,  // Unpacking memory
  81.   36,         // Packing speed
  82.   630,        // Unpacking speed
  83.   454,        // Compression ratio
  84.   0,          // Reserved
  85.   "normal",   // Description
  86. };
  87.  
  88. static struct XpkInfo NukeInfo = {
  89.     1,               /* info version */
  90.     VERSION,         /* lib  version */
  91.     0,               /* master vers  */
  92.     1,               /* ModesVersion */
  93.     (STRPTR) "DUKE", /* short name   */
  94.     (STRPTR) "Duke", /* long name    */
  95.     (STRPTR) "NUKE with a delta preprocessor", /* Description */
  96.     0x44554B45,     /* 'DUKE', 4 letter ID  */
  97.     XPKIF_PK_CHUNK | /* flags        */
  98.     XPKIF_UP_CHUNK,
  99.     30000,           /* max in chunk */
  100.     10,              /* min in chunk */
  101.     30000,           /* def in chunk */
  102.     (STRPTR) "Duking",   /* pk message   */
  103.     (STRPTR) "Unduking", /* up message   */
  104.     (STRPTR) "Duked",    /* pk past msg  */
  105.     (STRPTR) "Unduked",  /* up past msg  */
  106.     50,              /* DefMode      */
  107.     0,               /* Pad          */
  108.     &NukeMode,       /* ModeDesc     */
  109.     0,               /* MinModeDesc  */
  110.     0,               /* MaxModeDesc  */
  111.     0,0,0,0          /* reserved     */
  112. };
  113.  
  114. void DoDelta(STRPTR dst, STRPTR src, LONG len)
  115. {
  116.   UBYTE a=0, b=0;
  117.  
  118.   if (len>0) {
  119.     switch (len & 7) {
  120.       do {
  121.     case 0: *dst++ = (UBYTE) ((b=*src++) - a);
  122.     case 7: *dst++ = (UBYTE) ((a=*src++) - b);
  123.     case 6: *dst++ = (UBYTE) ((b=*src++) - a);
  124.     case 5: *dst++ = (UBYTE) ((a=*src++) - b);
  125.     case 4: *dst++ = (UBYTE) ((b=*src++) - a);
  126.     case 3: *dst++ = (UBYTE) ((a=*src++) - b);
  127.     case 2: *dst++ = (UBYTE) ((b=*src++) - a);
  128.     case 1: *dst++ = (UBYTE) ((a=*src++) - b);
  129.       } while ((len-=8)>0);
  130.     }
  131.   }
  132. }
  133.  
  134. void UndoDelta(STRPTR dst, STRPTR src, LONG len)
  135. {
  136.   UBYTE l = 0;
  137.  
  138.   if (len > 0) {
  139.     switch (len & 7) {
  140.      do {
  141.     case 0: *dst++ = (l+=*src++);
  142.     case 7: *dst++ = (l+=*src++);
  143.     case 6: *dst++ = (l+=*src++);
  144.     case 5: *dst++ = (l+=*src++);
  145.     case 4: *dst++ = (l+=*src++);
  146.     case 3: *dst++ = (l+=*src++);
  147.     case 2: *dst++ = (l+=*src++);
  148.     case 1: *dst++ = (l+=*src++);
  149.       } while ((len-=8)>0);
  150.     }
  151.   }
  152. }
  153.  
  154.  
  155. /*
  156.  * Returns an info structure about our packer
  157.  */
  158.  
  159. #ifdef __cplusplus
  160. extern "C"
  161. #endif
  162.  
  163. struct XpkInfo *XpksPackerInfo(void)
  164. {
  165.   return &NukeInfo;
  166. }
  167.  
  168. #ifdef __cplusplus
  169. extern "C"
  170. #endif
  171.  
  172. void __asm XpksPackFree(register __a0 struct XpkSubParams *xpar)
  173. {
  174.     struct NukeData  *ND=(struct NukeData *)xpar->Sub[0];
  175.  
  176.     if( xpar->Sub[1] ) FreeMem( (APTR)xpar->Sub[1], SCANBUFLEN), xpar->Sub[1]=0;
  177.     if( !ND )      return;
  178.     if( ND->last ) FreeMem( ND->last, 65536     *sizeof(UWORD));
  179.     if( ND->next ) FreeMem( ND->next, SCANBUFLEN*sizeof(UWORD));
  180.     FreeMem(ND, sizeof(struct NukeData));
  181. }
  182.  
  183.  
  184. struct NukeData *alloctabs(struct XpkSubParams *xpar)
  185. {
  186.   struct NukeData *ND;
  187.  
  188.   if ((xpar->Sub[0] = (LONG) (ND = (struct NukeData*) AllocMem(sizeof(struct NukeData),MEMF_CLEAR))) &&
  189.       (ND->last = AllocMem(65536*sizeof(UWORD),0)) &&
  190.       (ND->next = AllocMem(SCANBUFLEN*sizeof(UWORD),0)) &&
  191.       (xpar->Sub[1] = (LONG) AllocMem(SCANBUFLEN,0))) {
  192.     return ND;
  193.   }
  194.   else
  195.   {
  196.     XpksPackFree(xpar);
  197.     return 0;
  198.   }
  199. }
  200.  
  201. /*
  202.  * This forces the next chunk to be decompressable independently from the
  203.  * previous one. 
  204.  */
  205.  
  206. #ifdef __cplusplus
  207. extern "C"
  208. #endif
  209.  
  210. LONG __asm XpksPackReset(register __a0 struct XpkSubParams *xpar )
  211. {
  212.   return 0;
  213. }
  214.  
  215. #ifdef __cplusplus
  216. extern "C"
  217. #endif
  218.  
  219. LONG __asm XpksPackChunk(register __a0 struct XpkSubParams *xpar )
  220. {
  221.   struct NukeData *ND=(struct NukeData *)xpar->Sub[0];
  222.  
  223.   if (!ND)
  224.     if (!(ND=alloctabs(xpar)))
  225.       return XPKERR_NOMEM;
  226.  
  227.   DoDelta((STRPTR)xpar->Sub[1], (STRPTR) xpar->InBuf, xpar->InLen);
  228.  
  229.   ND->inbuf = (APTR) xpar->Sub[1];
  230.   ND->outbuf= xpar->OutBuf;
  231.   ND->ulen  = (UWORD) xpar->InLen;
  232.   ND->clen  = (UWORD) (xpar->OutBufLen-4);
  233.  
  234.   memset(ND->last,0,65536*sizeof(UWORD));
  235.   memset(ND->next,0,SCANBUFLEN*sizeof(UWORD));
  236.  
  237.   if((xpar->OutLen = AsmPack(ND))<0 || xpar->OutLen>xpar->InLen) {
  238.     XpksPackReset(xpar);
  239.     return XPKERR_EXPANSION;
  240.   }
  241.   return 0;
  242. }
  243.  
  244. #ifdef __cplusplus
  245. extern "C"
  246. #endif
  247.  
  248. LONG __asm XpksUnpackChunk(register __a0 struct XpkSubParams *xpar)
  249. {
  250.   if(!xpar->Sub[1] && !(xpar->Sub[1] = (LONG) AllocMem(SCANBUFLEN,0)))
  251.      return XPKERR_NOMEM;
  252.  
  253.   AsmUnpack((STRPTR) xpar->InBuf,  (STRPTR)xpar->InBuf  + xpar->InLen,
  254.             (STRPTR)xpar->Sub[1], (STRPTR)xpar->Sub[1] + xpar->OutLen);
  255.  
  256.   UndoDelta((STRPTR)xpar->OutBuf, (STRPTR )xpar->Sub[1], xpar->OutLen);   
  257.  
  258.   return 0;
  259. }
  260.  
  261. #ifdef __cplusplus
  262. extern "C"
  263. #endif
  264.  
  265. void __asm XpksUnpackFree(register __a0 struct XpkSubParams *xpar)
  266. {
  267.   if (xpar->Sub[1]) FreeMem((APTR)xpar->Sub[1], SCANBUFLEN), xpar->Sub[1]=0;
  268. }
  269.