home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
packery
/
xpk_source
/
libraries
/
duke
/
xpkduke.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-19
|
6KB
|
269 lines
/*
* This library is mainly intended to demonstrate how to program a sub
* library.
*/
#define VERSION 1
#define NO_SUB_PRAGMAS
#include <xpk/xpksub.h>
#include <exec/memory.h>
#include <pragma/exec_lib.h>
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
#ifdef __MAXON__
#define __asm
#endif
#define SCANBUFLEN 32768
/*
* Pack a chunk
*/
struct NukeData {
APTR inbuf;
APTR outbuf;
APTR last;
APTR next;
CPTR cwri;
CPTR uwri;
CPTR uend;
CPTR delpos;
UWORD ulen;
UWORD clen;
UWORD ustop;
UWORD ustart;
UWORD ucount;
UWORD scanrange;
UWORD room1;
UWORD room2;
UWORD room4;
UWORD roomN;
UWORD data1;
UWORD data2;
ULONG data4;
ULONG dataN;
CPTR dest1;
CPTR dest2;
CPTR dest4;
CPTR destN;
ULONG dummy;
CPTR contbuf;
ULONG flags;
};
#ifdef __cplusplus
extern "C" {
#endif
LONG __asm AsmPack (register __a4 struct NukeData *ND);
STRPTR __asm AsmUnpack(register __a1 STRPTR wread, register __a4 STRPTR bread,
register __a0 STRPTR dst, register __a2 STRPTR end);
#ifdef __cplusplus
}
#endif
#define PACKMEM (65536+SCANBUFLEN)*sizeof(USHORT)+sizeof(struct NukeData)+SCANBUFLEN
#define UNPACKMEM SCANBUFLEN
#define A3000 XPKMF_A3000SPEED
static struct XpkMode NukeMode = {
NULL, // Next mode
100, // Handles up to
A3000, // Flags
PACKMEM, // Packing memory
UNPACKMEM, // Unpacking memory
36, // Packing speed
630, // Unpacking speed
454, // Compression ratio
0, // Reserved
"normal", // Description
};
static struct XpkInfo NukeInfo = {
1, /* info version */
VERSION, /* lib version */
0, /* master vers */
1, /* ModesVersion */
(STRPTR) "DUKE", /* short name */
(STRPTR) "Duke", /* long name */
(STRPTR) "NUKE with a delta preprocessor", /* Description */
0x44554B45, /* 'DUKE', 4 letter ID */
XPKIF_PK_CHUNK | /* flags */
XPKIF_UP_CHUNK,
30000, /* max in chunk */
10, /* min in chunk */
30000, /* def in chunk */
(STRPTR) "Duking", /* pk message */
(STRPTR) "Unduking", /* up message */
(STRPTR) "Duked", /* pk past msg */
(STRPTR) "Unduked", /* up past msg */
50, /* DefMode */
0, /* Pad */
&NukeMode, /* ModeDesc */
0, /* MinModeDesc */
0, /* MaxModeDesc */
0,0,0,0 /* reserved */
};
void DoDelta(STRPTR dst, STRPTR src, LONG len)
{
UBYTE a=0, b=0;
if (len>0) {
switch (len & 7) {
do {
case 0: *dst++ = (UBYTE) ((b=*src++) - a);
case 7: *dst++ = (UBYTE) ((a=*src++) - b);
case 6: *dst++ = (UBYTE) ((b=*src++) - a);
case 5: *dst++ = (UBYTE) ((a=*src++) - b);
case 4: *dst++ = (UBYTE) ((b=*src++) - a);
case 3: *dst++ = (UBYTE) ((a=*src++) - b);
case 2: *dst++ = (UBYTE) ((b=*src++) - a);
case 1: *dst++ = (UBYTE) ((a=*src++) - b);
} while ((len-=8)>0);
}
}
}
void UndoDelta(STRPTR dst, STRPTR src, LONG len)
{
UBYTE l = 0;
if (len > 0) {
switch (len & 7) {
do {
case 0: *dst++ = (l+=*src++);
case 7: *dst++ = (l+=*src++);
case 6: *dst++ = (l+=*src++);
case 5: *dst++ = (l+=*src++);
case 4: *dst++ = (l+=*src++);
case 3: *dst++ = (l+=*src++);
case 2: *dst++ = (l+=*src++);
case 1: *dst++ = (l+=*src++);
} while ((len-=8)>0);
}
}
}
/*
* Returns an info structure about our packer
*/
#ifdef __cplusplus
extern "C"
#endif
struct XpkInfo *XpksPackerInfo(void)
{
return &NukeInfo;
}
#ifdef __cplusplus
extern "C"
#endif
void __asm XpksPackFree(register __a0 struct XpkSubParams *xpar)
{
struct NukeData *ND=(struct NukeData *)xpar->Sub[0];
if( xpar->Sub[1] ) FreeMem( (APTR)xpar->Sub[1], SCANBUFLEN), xpar->Sub[1]=0;
if( !ND ) return;
if( ND->last ) FreeMem( ND->last, 65536 *sizeof(UWORD));
if( ND->next ) FreeMem( ND->next, SCANBUFLEN*sizeof(UWORD));
FreeMem(ND, sizeof(struct NukeData));
}
struct NukeData *alloctabs(struct XpkSubParams *xpar)
{
struct NukeData *ND;
if ((xpar->Sub[0] = (LONG) (ND = (struct NukeData*) AllocMem(sizeof(struct NukeData),MEMF_CLEAR))) &&
(ND->last = AllocMem(65536*sizeof(UWORD),0)) &&
(ND->next = AllocMem(SCANBUFLEN*sizeof(UWORD),0)) &&
(xpar->Sub[1] = (LONG) AllocMem(SCANBUFLEN,0))) {
return ND;
}
else
{
XpksPackFree(xpar);
return 0;
}
}
/*
* This forces the next chunk to be decompressable independently from the
* previous one.
*/
#ifdef __cplusplus
extern "C"
#endif
LONG __asm XpksPackReset(register __a0 struct XpkSubParams *xpar )
{
return 0;
}
#ifdef __cplusplus
extern "C"
#endif
LONG __asm XpksPackChunk(register __a0 struct XpkSubParams *xpar )
{
struct NukeData *ND=(struct NukeData *)xpar->Sub[0];
if (!ND)
if (!(ND=alloctabs(xpar)))
return XPKERR_NOMEM;
DoDelta((STRPTR)xpar->Sub[1], (STRPTR) xpar->InBuf, xpar->InLen);
ND->inbuf = (APTR) xpar->Sub[1];
ND->outbuf= xpar->OutBuf;
ND->ulen = (UWORD) xpar->InLen;
ND->clen = (UWORD) (xpar->OutBufLen-4);
memset(ND->last,0,65536*sizeof(UWORD));
memset(ND->next,0,SCANBUFLEN*sizeof(UWORD));
if((xpar->OutLen = AsmPack(ND))<0 || xpar->OutLen>xpar->InLen) {
XpksPackReset(xpar);
return XPKERR_EXPANSION;
}
return 0;
}
#ifdef __cplusplus
extern "C"
#endif
LONG __asm XpksUnpackChunk(register __a0 struct XpkSubParams *xpar)
{
if(!xpar->Sub[1] && !(xpar->Sub[1] = (LONG) AllocMem(SCANBUFLEN,0)))
return XPKERR_NOMEM;
AsmUnpack((STRPTR) xpar->InBuf, (STRPTR)xpar->InBuf + xpar->InLen,
(STRPTR)xpar->Sub[1], (STRPTR)xpar->Sub[1] + xpar->OutLen);
UndoDelta((STRPTR)xpar->OutBuf, (STRPTR )xpar->Sub[1], xpar->OutLen);
return 0;
}
#ifdef __cplusplus
extern "C"
#endif
void __asm XpksUnpackFree(register __a0 struct XpkSubParams *xpar)
{
if (xpar->Sub[1]) FreeMem((APTR)xpar->Sub[1], SCANBUFLEN), xpar->Sub[1]=0;
}