mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-29 03:23:48 +02:00
784 lines
21 KiB
C
Executable file
784 lines
21 KiB
C
Executable file
#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 */
|