XADMaster/libxad/clients/IFF-CDAF.c
2016-05-07 13:40:22 +03:00

784 lines
21 KiB
C
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef XADMASTER_IFF_CDAF_C
#define XADMASTER_IFF_CDAF_C
/* $Id: IFF-CDAF.c,v 1.12 2005/06/23 14:54:41 stoecker Exp $
IFF-CDAF format archivers (XpkArchive and Shrink)
XAD library system for archive handling
Copyright (C) 1998 and later by Dirk Stˆcker <soft@dstoecker.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../unix/xadClient.h"
#include "xadIO.c"
#include "xadIO_XPK.c"
#ifndef XADMASTERVERSION
#define XADMASTERVERSION 10
#endif
XADCLIENTVERSTR("IFF-CDAF 1.3 (23.2.2004)")
#define XPKARCHIVE_VERSION 1
#define XPKARCHIVE_REVISION 3
#define SHRINK_VERSION XPKARCHIVE_VERSION
#define SHRINK_REVISION XPKARCHIVE_REVISION
/* Shrink *****************************************************************************************/
struct ShrinkBuf {
struct xadInOut *io;
xadUINT16 data[1056];
xadUINT32 bitcount;
xadUINT32 bitbuf;
};
static const xadUINT16 ShrinkData[15] =
{0x0000, 0x0004, 0x000C, 0x001C, 0x003C, 0x007C, 0x00FC, 0x01FC,
0x03FC, 0x07FC, 0x0FFC, 0x1FFC, 0x3FFC, 0x7FFC, 0xFFFC};
static xadUINT16 ShrinkGetBits(xadUINT16 num, struct ShrinkBuf *sb)
{
xadUINT16 ret = 0, i;
while(num--)
{
i = 0;
sb->bitcount >>= 1;
if(sb->bitbuf >= sb->bitcount)
{
i = 1;
sb->bitbuf -= sb->bitcount;
}
while(sb->bitcount < 0x1000000)
{
sb->bitbuf = (sb->bitbuf << 8) | xadIOGetChar(sb->io);
sb->bitcount <<= 8;
}
ret = (ret << 1) | i;
}
return ret;
}
static void ShrinkSub1(struct ShrinkBuf *sb)
{
xadINT32 i;
for(i = 504; i < 1008; ++i)
{
if(sb->data[i])
sb->data[i] = (sb->data[i] >> 1)+1;
}
for(i = 503; i > 0; --i)
sb->data[i] = sb->data[2*i] + sb->data[2*i+1];
}
static void ShrinkSub2(xadUINT16 arg, struct ShrinkBuf *sb)
{
arg += 504;
while(arg)
{
++sb->data[arg];
arg >>= 1;
}
if(sb->data[1] >= 0x2000)
ShrinkSub1(sb);
}
static xadUINT32 ShrinkSub3(xadUINT32 a, struct ShrinkBuf *sb)
{
xadUINT16 d1, d2;
xadUINT32 res, j;
if(!a)
return 0;
a <<= 16;
d1 = a/sb->data[1];
d2 = ((a%sb->data[1])<<16)/sb->data[1];
j = sb->bitcount;
res = (xadUINT16) (((xadUINT16)j * d1) >> 16);
j >>= 16;
return res + ((xadUINT16)(((xadUINT16)j*d2) >> 16)) + (d1 * j);
}
static xadINT32 DeShrink(struct xadInOut *io, xadUINT8 bits)
{
xadINT32 i, j = 0, k, l, m, err;
xadUINT32 pos = 0, pos2, windowmask;
xadSTRPTR window;
struct xadMasterBase *xadMasterBase = io->xio_xadMasterBase;
struct ShrinkBuf *sb;
if((sb = (struct ShrinkBuf *) xadAllocVec(XADM sizeof(struct ShrinkBuf), XADMEMF_CLEAR)))
{
if((window = (xadSTRPTR) xadAllocVec(XADM 1<<(10+bits), XADMEMF_CLEAR)))
{
sb->io = io;
windowmask = (1<<(10+bits))-1;
for(i = 0; i < 4; ++i)
sb->bitbuf = (sb->bitbuf << 8) | xadIOGetChar(io);
sb->bitcount = 0x80000000;
for(i = 0; i < 261; ++i)
sb->data[504 + i] = (i < 32 || i > 126) ? 1 : 3;
sb->data[897] = sb->data[764] = 1;
for(i = 503; i > 0; --i)
sb->data[i] = sb->data[2*i] + sb->data[2*i+1];
while(!(io->xio_Flags & (XADIOF_LASTOUTBYTE|XADIOF_ERROR)))
{
if(j <= pos)
{
if(j < 48)
ShrinkSub2(j+261, sb);
i = 4;
for(k = 0; i < j+4; ++k)
i <<= 1;
if(i == j+4 && k < 14)
{
if(k < 13)
{
i = (k << 1) + 394;
ShrinkSub2(i++, sb);
ShrinkSub2(i, sb);
}
i = (k << 1) + 420;
ShrinkSub2(i++, sb);
ShrinkSub2(i, sb);
i += 27;
ShrinkSub2(i++, sb);
ShrinkSub2(i, sb);
i += 27;
ShrinkSub2(i++, sb);
ShrinkSub2(i, sb);
if(k < 7)
{
for(i = 0; i < 4; ++i)
ShrinkSub2((k << 2)+i+309, sb);
}
for(i = 0; i < 4; ++i)
ShrinkSub2(14*i+k+337, sb);
}
if(++j >= 48)
j = (j != 48) ? ((j+3)<<1)-4 : 60;
}
else
{
for(m = i = l = 0; m < 504;)
{
m <<= 1;
if((k = ShrinkSub3(i + sb->data[m], sb)) <= sb->bitbuf)
{
l = k;
i += sb->data[m++];
}
}
sb->bitbuf -= l;
sb->bitcount = ShrinkSub3(sb->data[m], sb);
l = 3 + (sb->data[1] >> 10);
for(i = m; i; i >>= 1)
sb->data[i] += l;
if(sb->data[1] >= 0x2000)
ShrinkSub1(sb);
while(sb->bitcount < 0x1000000)
{
sb->bitbuf = (sb->bitbuf << 8) | xadIOGetChar(io);;
sb->bitcount <<= 8;
}
m -= 504;
if(m < 0x100)
window[(pos++)&windowmask] = xadIOPutChar(io, m);
else
{
if(m < 261)
{
if(m < 260)
{
k = m - 256;
l = 2 + ShrinkGetBits(k+2, sb) + ShrinkData[k];
}
else
l = ShrinkGetBits(16, sb);
pos2 = pos-1;
while(l--)
window[(pos++)&windowmask] = xadIOPutChar(io, window[(pos2++)&windowmask]);
}
else if(m < 309)
{
m -= 259;
pos2 = pos-m;
for(i = 0; i < 2; ++i)
window[(pos++)&windowmask] = xadIOPutChar(io, window[(pos2++)&windowmask]);
}
else
{
if(m < 337)
{
k = m - 309;
m = ((ShrinkGetBits(k>>2, sb) << 2) | (k&3)) + ShrinkData[k>>2] + 3;
l = 3;
}
else if(m < 393)
{
m -= 337;
k = m / 14;
m %= 14;
l = ShrinkGetBits(k+2, sb) + ShrinkData[k] + 8;
m = ShrinkGetBits(m+2, sb) + ShrinkData[m] + l;
}
else if(m < 394)
{
l = ShrinkGetBits(16, sb);
m = ShrinkGetBits(16, sb);
}
else
{
if(m < 420)
{
l = 4;
k = 394;
}
else if(m < 448)
{
l = 5;
k = 420;
}
else if(m < 476)
{
l = 6;
k = 448;
}
else
{
l = 7;
k = 476;
}
k = m - k;
m = ((ShrinkGetBits(1 + (k >> 1), sb) << 1) | (k&1)) + ShrinkData[k >> 1] + l;
}
pos2 = pos-m;
while(l--)
window[(pos++)&windowmask] = xadIOPutChar(io, window[(pos2++)&windowmask]);
}
}
}
}
err = io->xio_Error;
xadFreeObjectA(XADM window, 0);
}
else
err = XADERR_NOMEMORY;
xadFreeObjectA(XADM sb, 0);
}
else
err = XADERR_NOMEMORY;
return err;
}
/**************************************************************************************************/
struct CDAFfile {
xadUINT8 ID[4]; /* FILE */
xadUINT8 ChunkSize[4];
xadUINT8 Checksum;
xadUINT8 Method;
xadUINT8 Version;
xadUINT8 Generation; /* Generation of the file: 0=new .. 255=deleted */
xadUINT8 SystemID[2];
xadUINT8 Filesize[4];
xadUINT8 Year; /* Since 1900 */
xadUINT8 Month;
xadUINT8 Day;
xadUINT8 Hour;
xadUINT8 Mins;
xadUINT8 Secs;
xadUINT8 CRC[2]; /* empty for XPK */
xadUINT8 Protection[4];
};
#define CDAFSYSID_AMIGA 0x414D
#define CDAFSYSID_ATARI_ST 0x5354
#define CDAFSYSID_ARCHIMEDES 0x4152
#define CDAFSYSID_MS_DOS 0x4D53
#define CDAFSYSID_UNIX 0x5558
#define CDAFSYSID_MAC 0x4D41
#define CDAFSYSID_HELIOS 0x4845
struct CDAFinfo {
xadUINT16 CRC;
xadUINT8 Method;
xadUINT8 Offset;
};
#define CDAFPI(a) ((struct CDAFinfo *) ((a)->xfi_PrivateInfo))
XADGETINFO(IFF_CDAF)
{
xadINT32 err, i;
struct CDAFfile cf;
xadUINT8 buffer[256];
xadUINT8 a[2][4];
xadSTRPTR name;
struct xadFileInfo *fi;
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, 16, 0, ai)))
return err;
if((err = xadHookAccess(XADM XADAC_READ, 4, a, ai)))
return err;
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, EndGetM32(a[0]), 0, ai)))
return err;
while(!err && ai->xai_InPos < ai->xai_InSize)
{
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct CDAFfile), &cf, ai)))
{
i = ((EndGetM32(cf.ChunkSize) - (sizeof(struct CDAFfile) - 8))+1)&(~1);
if(i <= 256)
name = (xadSTRPTR) buffer;
else if(!(name = xadAllocVec(XADM i, XADMEMF_ANY)))
err = XADERR_NOMEMORY;
if(!err)
{
if(!(err = xadHookAccess(XADM XADAC_READ, i, name, ai)))
{
if(!(err = xadHookAccess(XADM XADAC_READ, 8, a, ai)))
{
if((fi = (struct xadFileInfo *) xadAllocObject(XADM XADOBJ_FILEINFO,
XAD_OBJPRIVINFOSIZE, sizeof(struct CDAFinfo), XAD_OBJNAMESIZE, i+1,
EndGetM32(a[0]) == 0x4E4F5445 ? XAD_OBJCOMMENTSIZE : TAG_IGNORE, EndGetM32(a[1])+1, TAG_DONE)))
{
xadCopyMem(XADM name, fi->xfi_FileName, i);
if(EndGetM32(a[0]) == 0x4E4F5445)
{
if(!(err = xadHookAccess(XADM XADAC_READ, (EndGetM32(a[1])+1)&(~1), fi->xfi_Comment, ai)))
err = xadHookAccess(XADM XADAC_READ, 8, a, ai);
}
if(!err)
{
if(EndGetM32(a[0]) != 0x424F4459)
err = XADERR_ILLEGALDATA;
else
{
struct xadDate xd;
fi->xfi_DataPos = ai->xai_InPos; /* file position */
CDAFPI(fi)->Method = cf.Method;
CDAFPI(fi)->Offset = 4;
CDAFPI(fi)->CRC = EndGetM16(cf.CRC);
fi->xfi_Size = EndGetM32(cf.Filesize);
fi->xfi_Protection = EndGetM32(cf.Protection);
fi->xfi_CrunchSize = EndGetM32(a[1]);
if(cf.Generation == 255)
fi->xfi_Flags = XADFIF_DELETED;
else
fi->xfi_Generation = cf.Generation;
fi->xfi_Flags |= XADFIF_SEEKDATAPOS|XADFIF_EXTRACTONBUILD;
xd.xd_Second = cf.Secs;
xd.xd_Minute = cf.Mins;
xd.xd_Hour = cf.Hour;
xd.xd_Day = cf.Day;
xd.xd_Month = cf.Month;
xd.xd_Year = 1900 + cf.Year;
xd.xd_Micros = 0;
xadConvertDates(XADM XAD_DATEXADDATE, &xd, XAD_GETDATEXADDATE,
&fi->xfi_Date, TAG_DONE);
}
}
if(err)
xadFreeObjectA(XADM fi, 0);
else
err = xadAddFileEntry(XADM fi, ai, XAD_SETINPOS, ai->xai_InPos+((EndGetM32(a[1])+1)&(~1)), TAG_DONE);
}
else
err = XADERR_NOMEMORY;
}
}
}
if(name && name != (xadSTRPTR) buffer)
xadFreeObjectA(XADM name, 0);
}
}
if(err)
{
ai->xai_Flags |= XADAIF_FILECORRUPT;
ai->xai_LastError = err;
}
return ai->xai_FileInfo ? 0 : err;
}
/**************************************************************************************************/
static const xadUINT8 ShrinkString[] = "FORM\xFF\xFF\xFF\xFF" "CDAFNAME\0\0\0\x06shrink";
XADRECOGDATA(Shrink)
{
xadUINT32 i;
for(i = 0; i < 24 && (ShrinkString[i] == 0xFF || ShrinkString[i] == data[i]); ++i)
;
if(i == 24)
return 1;
else
return 0;
}
XADUNARCHIVE(Shrink)
{
xadINT32 err = 0;
xadUINT16 crc = 0;
struct xadFileInfo *fi;
fi = ai->xai_CurFile;
if(!CDAFPI(fi)->Method)
err = xadHookTagAccess(XADM XADAC_COPY, fi->xfi_Size, 0, ai, XAD_USESKIPINFO, XADTRUE, XAD_GETCRC16, &crc, TAG_DONE);
else
{
struct xadInOut *io;
if(CDAFPI(fi)->Offset)
err = xadHookAccess(XADM XADAC_INPUTSEEK, CDAFPI(fi)->Offset, 0, ai);
if(!err)
{
if((io = xadIOAlloc(XADIOF_ALLOCINBUFFER|XADIOF_ALLOCOUTBUFFER|XADIOF_NOCRC32, ai, xadMasterBase)))
{
io->xio_InSize = fi->xfi_CrunchSize-CDAFPI(fi)->Offset;
io->xio_OutSize = fi->xfi_Size;
if(!(err = DeShrink(io, CDAFPI(fi)->Method)))
err = xadIOWriteBuf(io);
crc = io->xio_CRC16;
xadFreeObjectA(XADM io, 0);
}
else
err = XADERR_NOMEMORY;
}
}
if(!err && CDAFPI(fi)->CRC && crc != CDAFPI(fi)->CRC)
err = XADERR_CHECKSUM;
return err;
}
/**************************************************************************************************/
XADRECOGDATA(SPack)
{
xadUINT32 i;
static const xadUINT8 *c = (xadUINT8 *)"PACKFI";
for(i = 0; i < 6 && c[i] == data[i]; ++i)
;
if(i == 6)
return 1;
else
return 0;
}
struct SPackData {
xadUINT8 ID[2];
xadUINT8 Num[2];
xadUINT8 UnCrSize[4];
xadUINT8 CrSize[4];
xadUINT8 CRC[2];
};
/* data format of INDX entry
struct DateStamp
for ever file:
xadUINT16 DiskNumber
xadUINT16 ID
xadUINT16 NameSize
[name]
xadUINT32 UncrunchedSize
xadUINT8 ZeroChar
*/
XADGETINFO(SPack)
{
xadUINT32 i;
xadUINT8 b[3][4];
xadINT32 err;
struct xadFileInfo *fi;
i = (xadUINT32)ai->xai_InPos; /* save StartPosition for BackSeek. */
if(ai->xai_MultiVolume)
{
struct xadSkipInfo *si = 0, *si2;
xadSize *a;
for(a = ai->xai_MultiVolume+1; *a; ++a)
{
if(!(si2 = (struct xadSkipInfo *) xadAllocObjectA(XADM XADOBJ_SKIPINFO, 0)))
return XADERR_NOMEMORY;
si2->xsi_Position = *a;
si2->xsi_SkipSize = 6;
if(si)
si->xsi_Next = si2;
else
ai->xai_SkipInfo = si2;
si = si2;
}
}
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, ai->xai_InSize-i-12, 0, ai)))
{
if(!(err = xadHookAccess(XADM XADAC_READ, 12, b, ai)))
{
if(EndGetM32(b[0]) == 0x494E4458)
err = xadHookTagAccess(XADM XADAC_INPUTSEEK, -12-EndGetM32(b[1]), 0, ai, XAD_USESKIPINFO, XADTRUE, TAG_DONE);
else if(EndGetM32(b[1]) == 0x494E4458)
err = xadHookTagAccess(XADM XADAC_INPUTSEEK, -8-EndGetM32(b[2]), 0, ai, XAD_USESKIPINFO, XADTRUE, TAG_DONE);
else
err = XADERR_ILLEGALDATA;
if(!err)
{
xadUINT8 buf[14];
if(!(err = xadHookTagAccess(XADM XADAC_READ, 14, buf, ai, XAD_USESKIPINFO, XADTRUE, TAG_DONE)))
{
if(EndGetM16(buf) == 0x4649)
{
xadSTRPTR buf2;
xadUINT32 b2s;
b2s = EndGetM32(buf+4);
if((buf2 = (xadSTRPTR) xadAllocVec(XADM b2s, XADMEMF_ANY)))
{
struct xadInOut *io;
if((io = xadIOAlloc(XADIOF_ALLOCINBUFFER|XADIOF_NOCRC32|XADIOF_NOCRC16, ai, xadMasterBase)))
{
io->xio_InSize = EndGetM32(buf+8);
io->xio_OutBufferSize = io->xio_OutSize = b2s;
io->xio_OutBuffer = (xadUINT8 *)buf2;
if(!(err = DeShrink(io, 7)) && EndGetM16(buf+12) != xadCalcCRC16(XADM XADCRC16_ID1, 0, b2s, (xadUINT8 *)buf2))
err = XADERR_CHECKSUM;
xadFreeObjectA(XADM io, 0);
}
else
err = XADERR_NOMEMORY;
if(!err)
{
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, -ai->xai_InPos+i+4, 0, ai)))
{
xadSTRPTR dat;
struct SPackData sp;
dat = buf2+12; /* pointer to current buffer pos */
while(!err && dat < buf2+b2s)
{
if(!(err = xadHookTagAccess(XADM XADAC_READ, sizeof(struct SPackData), &sp, ai, XAD_USESKIPINFO,
XADTRUE, TAG_DONE)))
{
xadUINT16 i;
i = EndGetM16(dat+6);
if(EndGetM16(sp.ID) == 0x4649 && EndGetM16(dat+2) == 0x4649 &&
(EndGetM16(sp.Num)&0x7FFF) == EndGetM16(dat+4) && EndGetM32(sp.UnCrSize) == EndGetM32(dat+8+i))
{
dat += 8;
if((fi = (struct xadFileInfo *) xadAllocObject(XADM XADOBJ_FILEINFO,
XAD_OBJPRIVINFOSIZE, sizeof(struct CDAFinfo), XAD_OBJNAMESIZE, i+1, TAG_DONE)))
{
xadCopyMem(XADM dat, fi->xfi_FileName, i);
dat += i + 4 + 1;
xadConvertDates(XADM XAD_DATEDATESTAMP, buf2, XAD_GETDATEXADDATE,
&fi->xfi_Date, TAG_DONE);
fi->xfi_Size = EndGetM32(sp.UnCrSize);
fi->xfi_Flags = XADFIF_SEEKDATAPOS|XADFIF_EXTRACTONBUILD;
if(EndGetM16(sp.Num) & 0x8000)
{
CDAFPI(fi)->Method = 0;
fi->xfi_DataPos = ai->xai_InPos - 6;
fi->xfi_CrunchSize = EndGetM32(sp.UnCrSize);
err = xadAddFileEntry(XADM fi, ai, XAD_SETINPOS, ai->xai_InPos+sp.UnCrSize-6,
XAD_USESKIPINFO, 1, TAG_DONE);
}
else
{
CDAFPI(fi)->Method = 7;
CDAFPI(fi)->CRC = EndGetM16(sp.CRC);
fi->xfi_DataPos = ai->xai_InPos;
fi->xfi_CrunchSize = EndGetM32(sp.CrSize);
err = xadAddFileEntry(XADM fi, ai, XAD_SETINPOS, ai->xai_InPos+sp.CrSize,
XAD_USESKIPINFO, 1, TAG_DONE);
}
}
else
err = XADERR_NOMEMORY;
}
else
err = XADERR_ILLEGALDATA;
} /* XADAC_READ */
} /* while */
} /* XADAC_INPUTSEEK */
}
xadFreeObjectA(XADM buf2, 0);
} /* xadAllocObject */
else
err = XADERR_NOMEMORY;
}
else
err = XADERR_ILLEGALDATA;
}
}
}
}
if(err)
{
ai->xai_Flags |= XADAIF_FILECORRUPT;
ai->xai_LastError = err;
}
return ai->xai_FileInfo ? 0 : err;
}
/**************************************************************************************************/
XADRECOGDATA(SPackSFX)
{
if(EndGetM32(data) == 0x3F3 /*HUNK_HEADER*/)
{
if(EndGetM32(data+10*4) == 0x42ADFFFC && EndGetM32(data+12*4) == 0x2C780004
&& EndGetM32(data+13*4) == 0x4EAEFE68 && EndGetM32(data+15*4) == 0x208093C9
&& EndGetM32(data+16*4) == 0x4EAEFEDA)
return 1;
}
return 0;
}
XADGETINFO(SPackSFX)
{
xadINT32 err;
xadUINT8 mem[12*4];
if(!(err = xadHookAccess(XADM XADAC_READ, 12*4, mem, ai)))
{
/* err is misued here! */
if(mem[11*4+3] == 0xF4)
err = 6624 - 12*4;
else
err = 6616 - 12*4;
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, err, 0, ai)))
err = SPack_GetInfo(ai, xadMasterBase);
}
return err;
}
/**************************************************************************************************/
XADCLIENT(SPackSFX) {
XADNEXTCLIENT,
XADCLIENT_VERSION,
XADMASTERVERSION,
SHRINK_VERSION,
SHRINK_REVISION,
100,
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO|XADCF_FREESKIPINFO,
XADCID_SPACKSFX,
"S-Pack SFX",
XADRECOGDATAP(SPackSFX),
XADGETINFOP(SPackSFX),
XADUNARCHIVEP(Shrink),
NULL
};
XADCLIENT(SPack) {
(struct xadClient *) &SPackSFX_Client,
XADCLIENT_VERSION,
XADMASTERVERSION,
SHRINK_VERSION,
SHRINK_REVISION,
6,
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO|XADCF_FREESKIPINFO,
XADCID_SPACK,
"S-Pack",
XADRECOGDATAP(SPack),
XADGETINFOP(SPack),
XADUNARCHIVEP(Shrink),
NULL
};
XADCLIENT(Shrink) {
(struct xadClient *) &SPack_Client,
XADCLIENT_VERSION,
XADMASTERVERSION,
SHRINK_VERSION,
SHRINK_REVISION,
24,
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
XADCID_SHRINK,
"Shrink",
XADRECOGDATAP(Shrink),
XADGETINFOP(IFF_CDAF),
XADUNARCHIVEP(Shrink),
NULL
};
#undef XADNEXTCLIENT
#define XADNEXTCLIENT XADNEXTCLIENTNAME(Shrink)
/* // Uses XPK only - not supported
XADFIRSTCLIENT(XPKArchive) {
(struct xadClient *) &Shrink_Client,
XADCLIENT_VERSION,
XADMASTERVERSION,
XPKARCHIVE_VERSION,
XPKARCHIVE_REVISION,
30,
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
XADCID_XPKARCHIVE,
"XPK Archive",
XADRECOGDATAP(XPKArchive),
XADGETINFOP(IFF_CDAF),
XADUNARCHIVEP(XPKArchive),
NULL
};
#undef XADNEXTCLIENT
#define XADNEXTCLIENT XADNEXTCLIENTNAME(XPKArchive)
*/
#endif /* XADMASTER_IFF_CDAF_C */