mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-29 03:23:48 +02:00
1496 lines
41 KiB
C
Executable file
1496 lines
41 KiB
C
Executable file
#ifndef XADMASTER_ZOOM_C
|
|
#define XADMASTER_ZOOM_C
|
|
|
|
|
|
/* $Id: Zoom.c,v 1.13 2005/06/23 14:54:41 stoecker Exp $
|
|
Zoom disk archiver client
|
|
|
|
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 "xadCRC_1021.c"
|
|
|
|
#ifndef XADMASTERVERSION
|
|
#define XADMASTERVERSION 13
|
|
#endif
|
|
|
|
XADCLIENTVERSTR("Zoom 1.11 (21.2.2004)")
|
|
|
|
#define ZOOM_VERSION 1
|
|
#define ZOOM_REVISION 11
|
|
#define ZOOM5_VERSION ZOOM_VERSION
|
|
#define ZOOM5_REVISION ZOOM_REVISION
|
|
#define LHPAK_VERSION ZOOM_VERSION
|
|
#define LHPAK_REVISION ZOOM_REVISION
|
|
#define PCOMP_VERSION ZOOM_VERSION
|
|
#define PCOMP_REVISION ZOOM_REVISION
|
|
#define SOMNI_VERSION ZOOM_VERSION
|
|
#define SOMNI_REVISION ZOOM_REVISION
|
|
#define LHSFX_VERSION ZOOM_VERSION
|
|
#define LHSFX_REVISION ZOOM_REVISION
|
|
|
|
#define BOXSIZE 5
|
|
#define TRACKSIZE (512*11*2)
|
|
|
|
struct TrackHeader
|
|
{
|
|
xadINT8 Tracks[BOXSIZE];
|
|
xadUINT32 Bits[BOXSIZE];
|
|
xadUINT16 Length;
|
|
xadUINT16 SqueezedLength;
|
|
xadUINT16 FatLength;
|
|
xadUINT16 Packed;
|
|
xadUINT32 CRC;
|
|
xadUINT16 Bytes;
|
|
};
|
|
|
|
struct OldTrackHeader
|
|
{
|
|
xadINT8 Tracks[BOXSIZE];
|
|
xadUINT32 Bits[BOXSIZE];
|
|
xadUINT16 Length; /* entry length */
|
|
xadUINT8 Bytes[2];
|
|
xadUINT16 SqueezedLength; /* length after RLE */
|
|
xadUINT16 FatLength; /* Original size */
|
|
xadUINT16 Packed; /* LH packed ? */
|
|
xadUINT16 CRC;
|
|
};
|
|
|
|
struct ZoomNote
|
|
{
|
|
xadUINT8 DateStamp[12];
|
|
xadUINT8 Note[80];
|
|
};
|
|
|
|
struct ZoomHeader
|
|
{
|
|
xadUINT32 HeaderID; /* Should be `ZOM5' */
|
|
xadINT8 From;
|
|
xadINT8 To; /* First and last track. */
|
|
xadINT8 Version; /* Which Zoom version created this file. */
|
|
xadINT8 OnlyTracks; /* TRUE if file only contains whole tracks. */
|
|
xadUINT32 Flags; /* Miscellaneous flag bits. */
|
|
/* FIXME */
|
|
xadUINT8 Date[12]; /* File creation date. */
|
|
xadUINT32 TextLength; /* Size of text attached to this file. */
|
|
xadUINT32 PackedLength; /* Compressed size of text attached to this file. */
|
|
xadINT32 NoteOffset; /* Notes attached to this file. */
|
|
xadINT8 Encrypted; /* TRUE if file is encrypted with password. */
|
|
xadINT8 Format;
|
|
xadINT16 Reserved1; /* Reserved data. */
|
|
xadUINT32 root; /* Encryption key. */
|
|
xadUINT32 Reserved2[7]; /* Reserved data. */
|
|
};
|
|
|
|
/* ZoomHeader->Flags */
|
|
#define USEHEADER 1
|
|
|
|
/***************** LZSS Parameters ***************/
|
|
|
|
#define SeqMax 60 /* MaxSize of sequence (look-ahead depth) */
|
|
|
|
/************* Huffman coding parameters *********/
|
|
|
|
#define AnzChar (256+SeqMax+1) /* character code (= 0..AnzChar-1) */
|
|
#define SizeTable (AnzChar*2-1) /* Size of table */
|
|
#define Root (SizeTable-1) /* root position */
|
|
#define frequenzlimit 0x8000 /* stop updating if cumulative frequency reaches to this value */
|
|
|
|
/* ------------- DECODE - TABELLE (code,len) ----------------- */
|
|
|
|
static const xadUINT16 d_code_len[256] = {
|
|
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
|
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
|
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
|
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
|
|
|
0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,
|
|
0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,
|
|
0x0201,0x0201,0x0201,0x0201,0x0201,0x0201,0x0201,0x0201,
|
|
0x0201,0x0201,0x0201,0x0201,0x0201,0x0201,0x0201,0x0201,
|
|
0x0301,0x0301,0x0301,0x0301,0x0301,0x0301,0x0301,0x0301,
|
|
0x0301,0x0301,0x0301,0x0301,0x0301,0x0301,0x0301,0x0301,
|
|
|
|
0x0402,0x0402,0x0402,0x0402,0x0402,0x0402,0x0402,0x0402,
|
|
0x0502,0x0502,0x0502,0x0502,0x0502,0x0502,0x0502,0x0502,
|
|
0x0602,0x0602,0x0602,0x0602,0x0602,0x0602,0x0602,0x0602,
|
|
0x0702,0x0702,0x0702,0x0702,0x0702,0x0702,0x0702,0x0702,
|
|
0x0802,0x0802,0x0802,0x0802,0x0802,0x0802,0x0802,0x0802,
|
|
0x0902,0x0902,0x0902,0x0902,0x0902,0x0902,0x0902,0x0902,
|
|
|
|
0x0A02,0x0A02,0x0A02,0x0A02,0x0A02,0x0A02,0x0A02,0x0A02,
|
|
0x0B02,0x0B02,0x0B02,0x0B02,0x0B02,0x0B02,0x0B02,0x0B02,
|
|
|
|
0x0C03,0x0C03,0x0C03,0x0C03,0x0D03,0x0D03,0x0D03,0x0D03,
|
|
0x0E03,0x0E03,0x0E03,0x0E03,0x0F03,0x0F03,0x0F03,0x0F03,
|
|
0x1003,0x1003,0x1003,0x1003,0x1103,0x1103,0x1103,0x1103,
|
|
0x1203,0x1203,0x1203,0x1203,0x1303,0x1303,0x1303,0x1303,
|
|
0x1403,0x1403,0x1403,0x1403,0x1503,0x1503,0x1503,0x1503,
|
|
0x1603,0x1603,0x1603,0x1603,0x1703,0x1703,0x1703,0x1703,
|
|
|
|
0x1804,0x1804,0x1904,0x1904,0x1A04,0x1A04,0x1B04,0x1B04,
|
|
0x1C04,0x1C04,0x1D04,0x1D04,0x1E04,0x1E04,0x1F04,0x1F04,
|
|
0x2004,0x2004,0x2104,0x2104,0x2204,0x2204,0x2304,0x2304,
|
|
0x2404,0x2404,0x2504,0x2504,0x2604,0x2604,0x2704,0x2704,
|
|
0x2804,0x2804,0x2904,0x2904,0x2A04,0x2A04,0x2B04,0x2B04,
|
|
0x2C04,0x2C04,0x2D04,0x2D04,0x2E04,0x2E04,0x2F04,0x2F04,
|
|
|
|
0x3005,0x3105,0x3205,0x3305,0x3405,0x3505,0x3605,0x3705,
|
|
0x3805,0x3905,0x3A05,0x3B05,0x3C05,0x3D05,0x3E05,0x3F05,
|
|
};
|
|
|
|
struct LhData {
|
|
xadUINT16 freq[SizeTable+1];
|
|
xadINT16 par_back[AnzChar];
|
|
xadINT16 parent[SizeTable];
|
|
xadINT16 son[SizeTable];
|
|
};
|
|
|
|
static void Update(struct LhData *dat, xadINT16 pos)
|
|
{
|
|
xadINT16 i, j, k, l;
|
|
xadUINT16 *freq;
|
|
|
|
i = dat->parent[pos];
|
|
|
|
do
|
|
{
|
|
freq = &dat->freq[i]; /* Mutterknotenhäufigkeit */
|
|
j = *freq;
|
|
*(freq++) = ++j; /* Mutterknotenhäfigkeit erhöhen */
|
|
if(*(freq++) < j) /* hat der Eintrag die Continuität beeinträchtigt ? */
|
|
{
|
|
/* dann müssen Knoten vertauscht werden, d.h. die Knoten werden umgehängt */
|
|
/* i == Swap Knoten 1 */
|
|
|
|
while(*freq < j)
|
|
++freq; /* swap Knoten 2 suchen */
|
|
|
|
--freq; /* freq == Swapknoten 2 */
|
|
k = freq - dat->freq; /* k == (offset zum Swap 2) */
|
|
dat->freq[i] = *freq; /* freq(knot1)=freq(knot2) */
|
|
*freq = j; /* freq(knot2)=freq(knot1) */
|
|
if((j = dat->son[i]) >= 0) /* wenn der l-sohn vom old knot ein code ist */
|
|
dat->parent[j+1] = k; /* dann neuer r-Vater=new knot */
|
|
dat->parent[j] = k; /* jf. neuer l-vater=new knot */
|
|
if((l = dat->son[k]) >= 0) /* wenn der l-sohn vom new knot ein code ist */
|
|
dat->parent[l+1] = i; /* dann neuer r-Vater=old knot */
|
|
dat->son[k] = j; /* l-sohn(new knot)=l-sohn(old k) */
|
|
dat->parent[l] = i; /* l-vater von sohn vom new knot = old knot */
|
|
dat->son[i] = l; /* l-sohn vom old knot= l-sohn vom new knot */
|
|
i = dat->parent[k]; /* vater holen */
|
|
}
|
|
else
|
|
i = dat->parent[i]; /* vater holen */
|
|
} while(i); /* bis Root erreicht ist. */
|
|
}
|
|
|
|
static void InitFreqTree(struct LhData *dat)
|
|
{
|
|
/* Ersteinmal müssen die Codes '-parent' in Verbindung mit 'son' gesetzt werden.
|
|
Außerdem wird die globale Häufigkeit 'freq' auf eins initialisiert. */
|
|
|
|
xadINT16 i, j, k;
|
|
|
|
k = 0; /* Zeigerwert von parent auf son */
|
|
j = -1; /* Zeigerwert von son auf parent */
|
|
for(i = 0; i < AnzChar; ++i)
|
|
{
|
|
dat->freq[i] = 1; /* Häufigkeit = 1 */
|
|
dat->son[i] = j--; /* leafs = SizeTable. SizeTable.+1.. */
|
|
dat->parent[-i-1] = k++; /* parentpointer initialisieren (T*2) */
|
|
}
|
|
|
|
k = 0;
|
|
j = AnzChar;
|
|
for(i = 0; i < Root-AnzChar+1; ++i)
|
|
{
|
|
dat->freq[j] = dat->freq[k] + dat->freq[k+1];
|
|
dat->son[j] = k; /* SONeinträge (ab AnzChar.) */
|
|
dat->parent[k] = dat->parent[k+1] = j++; /* Parenteinträge (ab 0.) */
|
|
k += 2;
|
|
}
|
|
|
|
dat->freq[SizeTable] = 0xFFFF;
|
|
dat->parent[Root] = 0;
|
|
}
|
|
|
|
static xadINT32 LhDecode(xadUINT16 *src, xadUINT32 srcsize, xadSTRPTR dest, xadUINT32 destsize, struct xadMasterBase *xadMasterBase)
|
|
{
|
|
xadINT16 bitindex, i, j, k, l;
|
|
xadINT32 err = 0;
|
|
xadUINT32 bitbuf;
|
|
xadUINT8 *str;
|
|
struct LhData *dat;
|
|
xadUINT16 *srcend;
|
|
|
|
srcend = (xadUINT16 *) (((xadSTRPTR) src) + srcsize);
|
|
|
|
if(!(dat = (struct LhData *) xadAllocVec(XADM sizeof(struct LhData), XADMEMF_ANY)))
|
|
return XADERR_NOMEMORY;
|
|
|
|
InitFreqTree(dat);
|
|
|
|
bitindex = 15; /* getlen = bitindex */
|
|
bitbuf = *(src++); /* prestore getbuf */
|
|
while(!err)
|
|
{
|
|
/**** search FreqTree from root to leaves ****/
|
|
/**** choose node son() IF bit == 0 ****/
|
|
/**** else choose son()+1 IF bit == 1 ****/
|
|
|
|
l = dat->son[Root]; /* son(R) erster Ast */
|
|
do
|
|
{
|
|
l = dat->son[l + ((bitbuf&0x8000) ? 1 : 0)];
|
|
bitbuf <<= 1;
|
|
if(!(bitindex--)) /* bitcounter runterzählen */
|
|
{
|
|
bitindex = 15;
|
|
bitbuf = *(src++);
|
|
}
|
|
} while(l >= 0);
|
|
|
|
if(dat->freq[Root] != frequenzlimit)
|
|
Update(dat, l);
|
|
|
|
if(l >= -256)
|
|
{
|
|
if(!(destsize--))
|
|
err = XADERR_DECRUNCH;
|
|
else
|
|
*(dest++) = -l - 1;
|
|
}
|
|
else if(l <= -(255+SeqMax+1)-1)
|
|
break; /* this is the leave point */
|
|
else /***** DecodePosition *****/
|
|
{
|
|
bitindex -= 7;
|
|
if(bitindex < 0)
|
|
{
|
|
bitbuf = (bitbuf << 8) | (*(src++) << -bitindex);
|
|
bitindex += 15; /* correct bitindex */
|
|
i = (xadUINT8) (bitbuf >> 16); /* get byte */
|
|
}
|
|
else
|
|
{
|
|
i = (xadUINT8) (bitbuf>>8); /* get upper byte */
|
|
bitbuf <<= 8; /* shift byte out */
|
|
if(!(bitindex--))
|
|
{
|
|
bitbuf = *(src++);
|
|
bitindex = 15;
|
|
}
|
|
}
|
|
|
|
k = d_code_len[i];
|
|
j = (xadUINT8) k; /* j: Anzahl der kommenden Bits */
|
|
k = (k&0xFF00) >> 2; /* k = (d_code(i) << 6) */
|
|
|
|
do
|
|
{
|
|
i <<= 1;
|
|
if(bitbuf & 0x8000) /* bit einfuegen */
|
|
++i;
|
|
bitbuf <<= 1; /* und bit rausschieben */
|
|
if(!(bitindex--))
|
|
{
|
|
bitbuf = *(src++);
|
|
bitindex = 15;
|
|
}
|
|
} while(j--);
|
|
|
|
str = (xadUINT8 *) dest - ((i&0x3F)|k); /* source-position */
|
|
|
|
l = -(l+256);
|
|
if(l > destsize)
|
|
err = XADERR_DECRUNCH;
|
|
else
|
|
{
|
|
destsize -= l;
|
|
while(l--)
|
|
*(dest++) = *(str++);
|
|
}
|
|
}
|
|
}
|
|
if(src != srcend || destsize)
|
|
err = XADERR_DECRUNCH;
|
|
xadFreeObjectA(XADM dat, 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static xadUINT32 NewKey(xadSTRPTR Key)
|
|
{
|
|
xadUINT32 root, i = 1;
|
|
|
|
root = *Key; /* use first entry as init value */
|
|
|
|
while(Key[i])
|
|
root *= Key[i++];
|
|
|
|
return root;
|
|
}
|
|
|
|
|
|
static void CryptKeyBlock(xadSTRPTR Block, xadINT32 Length, xadSTRPTR Key)
|
|
{
|
|
xadUINT32 root, i = 0;
|
|
|
|
root = NewKey(Key);
|
|
while(Length--)
|
|
{
|
|
root = (((root * 4253261) & 0xFFFFFF) + 372837) & 0xFFFFFF;
|
|
*Block++ ^= (root % 256) ^ (~Key[i++]);
|
|
if(!Key[i])
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
/* oldmode == 100, 101 means direct CRC check, 200 no check */
|
|
static xadINT32 CheckCRC(xadPTR buf, xadUINT32 size, xadUINT32 oldmode, xadUINT32 CRC,
|
|
struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase)
|
|
{
|
|
xadINT32 err = 0;
|
|
|
|
if(oldmode == 200)
|
|
err = 0;
|
|
else if(oldmode == 100)
|
|
{
|
|
if(xadCalcCRC32(XADM XADCRC32_ID1, 0, size, buf) != CRC)
|
|
err = XADERR_CHECKSUM;
|
|
}
|
|
else if(oldmode == 101)
|
|
{
|
|
if(xadCRC_1021_2(buf, size) != CRC)
|
|
err = XADERR_CHECKSUM;
|
|
}
|
|
else if(oldmode)
|
|
{
|
|
xadUINT16 a;
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 2, &a, ai)))
|
|
{
|
|
if(xadCRC_1021_2(buf, size) != a)
|
|
|
|
err = XADERR_CHECKSUM;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xadUINT32 a;
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 4, &a, ai)))
|
|
{
|
|
if(xadCalcCRC32(XADM XADCRC32_ID1, 0, size, buf) != a)
|
|
err = XADERR_CHECKSUM;
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/* reads lh data from current input stream and stores a pointer to
|
|
decrunched file in *str */
|
|
static xadINT32 DoDecrunch(xadSTRPTR *str, xadUINT32 insize, xadUINT32 ressize, xadUINT32 oldmode,
|
|
struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase, xadUINT32 CRC)
|
|
{
|
|
xadUINT16 *mem;
|
|
xadINT32 err = XADERR_NOMEMORY;
|
|
|
|
*str = 0;
|
|
|
|
if((mem = (xadUINT16 *) xadAllocVec(XADM insize, XADMEMF_PUBLIC)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, insize, mem, ai)))
|
|
{
|
|
xadSTRPTR mem2;
|
|
|
|
if(!(err = CheckCRC(mem, insize, oldmode, CRC, ai, xadMasterBase)))
|
|
{
|
|
if((mem2 = (xadSTRPTR) xadAllocVec(XADM ressize+1, XADMEMF_PUBLIC|XADMEMF_CLEAR)))
|
|
{
|
|
if((err = LhDecode(mem, insize, mem2, ressize, xadMasterBase)))
|
|
xadFreeObjectA(XADM mem2, 0);
|
|
else
|
|
*str = mem2;
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
} /* xadAllocVec */
|
|
} /* Hook Read */
|
|
xadFreeObjectA(XADM mem, 0);
|
|
} /* xadAllocVec */
|
|
|
|
return err;
|
|
}
|
|
|
|
static xadINT32 RunDecode(xadSTRPTR src, xadSTRPTR dest, xadUINT32 size)
|
|
{
|
|
xadSTRPTR end;
|
|
xadINT16 b, c, p;
|
|
|
|
end = dest + (*(src++) << 16); /* Get Size */
|
|
end += *(src++) << 8;
|
|
end += *(src++);
|
|
|
|
p = *(src++); /* get packbyte */
|
|
|
|
if(end-dest != size)
|
|
return XADERR_DECRUNCH;
|
|
|
|
while(dest < end) /* reached end? */
|
|
{
|
|
b = *(src++); /* get next byte */
|
|
if(b == p) /* is packbyte ? */
|
|
{
|
|
if((b = *(src++)))
|
|
{
|
|
c = *(src++); /* get byte of sequenz */
|
|
|
|
if(++b > end-dest) /* prevent overwriting */
|
|
b = end-dest;
|
|
|
|
while(b--) /* write it */
|
|
*(dest++) = c;
|
|
}
|
|
else
|
|
*(dest++) = p; /* write packbyte one time */
|
|
}
|
|
else
|
|
*(dest++) = b; /* write byte */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static xadINT32 RunDecodeOld(xadSTRPTR src, xadSTRPTR dest, xadUINT32 size, xadUINT32 srcsize, xadUINT16 Bytes)
|
|
{
|
|
xadSTRPTR s, d;
|
|
xadUINT32 cnt;
|
|
xadUINT8 b1, b2, b;
|
|
|
|
b1 = Bytes>>8;
|
|
b2 = Bytes;
|
|
|
|
s = src + srcsize;
|
|
d = dest + size;
|
|
|
|
while(d > dest) /* reached end? */
|
|
{
|
|
b = *(--s);
|
|
if(b == b1)
|
|
{
|
|
if(!(cnt = *(--s)))
|
|
cnt = 0x100;
|
|
b = *(--s);
|
|
|
|
if(cnt > d-dest)
|
|
return XADERR_DECRUNCH;
|
|
|
|
while(cnt--)
|
|
*(--d) = b;
|
|
}
|
|
else if(b == b2)
|
|
{
|
|
if(!(cnt = *(--s)))
|
|
cnt = 0x100;
|
|
while(cnt--)
|
|
*(--d) = 0;
|
|
}
|
|
else
|
|
*(--d) = b; /* write byte */
|
|
}
|
|
|
|
if(s < src)
|
|
return XADERR_DECRUNCH;
|
|
return 0;
|
|
}
|
|
|
|
static xadINT32 DoDecrunchZoom(xadSTRPTR *str, struct TrackHeader *th, xadUINT32 oldmode, xadSTRPTR pwd,
|
|
struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase)
|
|
{
|
|
xadPTR mem;
|
|
xadINT32 err = XADERR_NOMEMORY;
|
|
|
|
*str = 0;
|
|
|
|
if((mem = xadAllocVec(XADM th->Length, XADMEMF_PUBLIC)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, th->Length, mem, ai)))
|
|
{
|
|
if(!(err = CheckCRC(mem, th->Length, oldmode ? 101 : 100, th->CRC, ai, xadMasterBase)))
|
|
{
|
|
if(pwd)
|
|
CryptKeyBlock(mem, th->Length, pwd);
|
|
|
|
if(th->Packed)
|
|
{
|
|
xadSTRPTR mem2;
|
|
xadUINT32 size;
|
|
|
|
if(!(size = th->SqueezedLength))
|
|
size = th->FatLength;
|
|
|
|
if((mem2 = (xadSTRPTR) xadAllocVec(XADM size, XADMEMF_PUBLIC|XADMEMF_CLEAR)))
|
|
{
|
|
err = LhDecode(mem, th->Length, mem2, size, xadMasterBase);
|
|
xadFreeObjectA(XADM mem, 0);
|
|
mem = mem2;
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
|
|
if(!err && th->SqueezedLength)
|
|
{
|
|
xadPTR mem2;
|
|
if((mem2 = xadAllocVec(XADM th->FatLength, XADMEMF_PUBLIC|XADMEMF_CLEAR)))
|
|
{
|
|
if(oldmode)
|
|
err = RunDecodeOld(mem, mem2, th->FatLength, th->SqueezedLength, th->Bytes);
|
|
else
|
|
err = RunDecode(mem, mem2, th->FatLength);
|
|
xadFreeObjectA(XADM mem, 0);
|
|
mem = mem2;
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
} /* CRC check */
|
|
} /* read data */
|
|
} /* allocate buffer */
|
|
|
|
if(mem)
|
|
{
|
|
if(err)
|
|
xadFreeObjectA(XADM mem, 0);
|
|
else
|
|
*str = mem;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static void ClearMemLong(xadUINT32 *a, xadUINT32 size)
|
|
{
|
|
while(size--)
|
|
*(a++) = 0;
|
|
}
|
|
|
|
static void UnPackTrack(struct TrackHeader *th, xadSTRPTR buf, xadSTRPTR tmp, xadUINT32 pos,
|
|
struct xadMasterBase *xadMasterBase)
|
|
{
|
|
xadINT32 i, j = 0, k, l;
|
|
|
|
for(i = 0; i < pos; ++i)
|
|
{
|
|
l = th->Bits[i];
|
|
for(k = 0; k < 22; ++k)
|
|
{
|
|
if(l & 1)
|
|
++j;
|
|
l >>= 1;
|
|
}
|
|
}
|
|
|
|
buf += j*512;
|
|
|
|
l = th->Bits[pos];
|
|
for(i = j = 0; i < 22 ; ++i)
|
|
{
|
|
if(l & (1<<i))
|
|
xadCopyMem(XADM buf + 512*(j++), tmp + (512*i), 512);
|
|
else
|
|
ClearMemLong((xadUINT32 *) (tmp+(512*i)), 512/4);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
XADRECOGDATA(Zoom5)
|
|
{
|
|
if(data[0] == 'Z' && data[1] == 'O' && data[2] == 'M' && data[3] == '5'
|
|
&& xadCalcCRC32(XADM XADCRC32_ID1, 0, sizeof(struct ZoomHeader), data)
|
|
== (EndGetM32(data+72)))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
XADRECOGDATA(Zoom)
|
|
{
|
|
if(data[0] == 'Z' && data[1] == 'O' && data[2] == 'O' && data[3] == 'M'
|
|
&& data[6] >= 3 && xadCRC_1021_2(data, sizeof(struct ZoomHeader)) ==
|
|
EndGetM16(data+72))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
XADGETINFO(Zoom)
|
|
{
|
|
struct xadDiskInfo *di;
|
|
xadINT32 ret = XADERR_NOMEMORY;
|
|
xadINT32 oldmode = 0;
|
|
|
|
if((di = (struct xadDiskInfo *) xadAllocObject(XADM XADOBJ_DISKINFO,
|
|
XAD_OBJPRIVINFOSIZE, sizeof(struct ZoomHeader), TAG_DONE)))
|
|
{
|
|
struct ZoomHeader *zh;
|
|
|
|
ai->xai_DiskInfo = di;
|
|
zh = (struct ZoomHeader *) di->xdi_PrivateInfo;
|
|
|
|
if(!(ret = xadHookAccess(XADM XADAC_READ, sizeof(struct ZoomHeader), zh, ai)))
|
|
{
|
|
if(zh->HeaderID == 0x5A4F4F4D)
|
|
oldmode = 1;
|
|
|
|
if(!(ret = CheckCRC(zh, sizeof(struct ZoomHeader), oldmode, 0, ai,
|
|
xadMasterBase)))
|
|
{
|
|
if(zh->Encrypted)
|
|
{
|
|
di->xdi_Flags |= XADDIF_CRYPTED;
|
|
ai->xai_Flags |= XADAIF_CRYPTED;
|
|
}
|
|
|
|
di->xdi_EntryNumber = 1;
|
|
di->xdi_SectorSize = 512;
|
|
di->xdi_Cylinders = 80;
|
|
di->xdi_Heads = 2;
|
|
di->xdi_TrackSectors = 11;
|
|
di->xdi_CylSectors = 22;
|
|
di->xdi_TotalSectors = 80 * 22;
|
|
di->xdi_LowCyl = 0;
|
|
di->xdi_HighCyl = 79;
|
|
|
|
if(zh->TextLength)
|
|
{
|
|
struct xadTextInfo *ti;
|
|
|
|
if((ti = (struct xadTextInfo *) xadAllocObjectA(XADM XADOBJ_TEXTINFO, 0)))
|
|
{
|
|
ti->xti_Size = zh->TextLength;
|
|
if((ret = DoDecrunch(&ti->xti_Text, zh->PackedLength, zh->TextLength,
|
|
oldmode, ai, xadMasterBase, 0)))
|
|
xadFreeObjectA(XADM ti, 0);
|
|
else
|
|
di->xdi_TextInfo = ti;
|
|
}
|
|
else
|
|
ret = XADERR_NOMEMORY;
|
|
}
|
|
di->xdi_DataPos = ai->xai_InPos;
|
|
if(zh->Flags & USEHEADER)
|
|
di->xdi_Flags |= XADDIF_SECTORLABELS;
|
|
di->xdi_Flags |= XADDIF_SEEKDATAPOS;
|
|
|
|
if(zh->NoteOffset)
|
|
{
|
|
struct ZoomNote zn;
|
|
|
|
if(xadHookAccess(XADM XADAC_INPUTSEEK, zh->NoteOffset - ai->xai_InPos, 0, ai))
|
|
ai->xai_Flags |= XADAIF_FILECORRUPT;
|
|
else if(!(ret = xadHookAccess(XADM XADAC_READ, sizeof(struct ZoomNote), &zn, ai)))
|
|
{
|
|
struct xadTextInfo *ti;
|
|
if((ti = (struct xadTextInfo *) xadAllocObjectA(XADM XADOBJ_TEXTINFO, 0)))
|
|
{
|
|
xadSTRPTR buf;
|
|
if(di->xdi_TextInfo)
|
|
di->xdi_TextInfo->xti_Next = ti;
|
|
else
|
|
di->xdi_TextInfo = ti;
|
|
|
|
if((buf = (xadSTRPTR) xadAllocVec(XADM 80+22, XADMEMF_CLEAR|XADMEMF_PUBLIC)))
|
|
{
|
|
struct xadDate xd;
|
|
xadSTRPTR Block;
|
|
xadINT32 Tmp, Length, root;
|
|
|
|
Block = (xadSTRPTR) zn.Note;
|
|
Length = 80;
|
|
root = EndGetM32(zn.DateStamp+8);
|
|
|
|
while(Length-- > 0)
|
|
{
|
|
root = (((root * EndGetM32(zn.DateStamp+4)) & 0xFFFFFF)
|
|
+ EndGetM32(zn.DateStamp)) & 0xFFFFFF;
|
|
Tmp = root % 256;
|
|
*Block++ ^= Tmp;
|
|
}
|
|
|
|
ti->xti_Text = buf;
|
|
ti->xti_Size = 80+21;
|
|
xadConvertDates(XADM XAD_DATEDATESTAMP, &zn.DateStamp,
|
|
XAD_GETDATEXADDATE, &xd, TAG_DONE);
|
|
sprintf((char *)buf, "%02d.%02d.%04d %02d:%02d:%02d\n\n",
|
|
(xadUINT32)xd.xd_Day, (xadUINT32)xd.xd_Month,
|
|
(xadUINT32)xd.xd_Year, (xadUINT32)xd.xd_Hour,
|
|
(xadUINT32)xd.xd_Minute, (xadUINT32)xd.xd_Second);
|
|
|
|
xadCopyMem(XADM (xadPTR) &zn.Note, buf+21, 80);
|
|
}
|
|
else
|
|
ret = XADERR_NOMEMORY;
|
|
}
|
|
else
|
|
ret = XADERR_NOMEMORY;
|
|
} /* xadHokkAccess */
|
|
} /* zh->NoteOffset */
|
|
} /* CheckCRC */
|
|
} /* XADAC_READ */
|
|
} /* xadAllocObject */
|
|
|
|
return ret;
|
|
}
|
|
|
|
static xadINT32 GetTrackHead(struct xadArchiveInfo *ai, struct TrackHeader *th,
|
|
xadUINT32 oldmode, xadUINT32 useheader, struct xadMasterBase *xadMasterBase)
|
|
{
|
|
xadINT32 err;
|
|
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct TrackHeader)-2, th, ai)))
|
|
{
|
|
if(!(err = CheckCRC(th, sizeof(struct TrackHeader)-2, oldmode, 0, ai, xadMasterBase)))
|
|
{
|
|
xadUINT32 i, j = 0, k, l;
|
|
|
|
if(oldmode)
|
|
{
|
|
th->Bytes = th->SqueezedLength;
|
|
th->SqueezedLength = th->FatLength;
|
|
// th->FatLength = th->Packed;
|
|
th->Packed = th->CRC >> 16;
|
|
th->CRC = th->CRC & 0xFFFF;
|
|
}
|
|
|
|
/* as Zoom sets wrong FatLength sometimes, we need to recalculate it! */
|
|
for(i = 0; i < BOXSIZE && th->Tracks[i] != -1; ++i)
|
|
{
|
|
l = th->Bits[i];
|
|
for(k = 0; k < 22; ++k)
|
|
{
|
|
if(l & 1)
|
|
++j;
|
|
l >>= 1;
|
|
}
|
|
}
|
|
th->FatLength = j * (useheader ? 512 + 16 : 512);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
XADUNARCHIVE(Zoom)
|
|
{
|
|
struct xadDiskInfo *di;
|
|
struct ZoomHeader *zh;
|
|
struct TrackHeader th;
|
|
xadINT32 err = 0, i, j = -1, readdata = 0, oldmode;
|
|
xadSTRPTR pwd = 0, buf = 0, ebuf;
|
|
|
|
di = ai->xai_CurDisk;
|
|
zh = (struct ZoomHeader *) di->xdi_PrivateInfo;
|
|
oldmode = (zh->HeaderID == 0x5A4F4F4D);
|
|
|
|
if(di->xdi_Flags & XADDIF_CRYPTED)
|
|
{
|
|
if(!ai->xai_Password || NewKey(ai->xai_Password) != zh->root)
|
|
return XADERR_PASSWORD;
|
|
else
|
|
pwd = ai->xai_Password;
|
|
}
|
|
|
|
if(!(ebuf = xadAllocVec(XADM TRACKSIZE, XADMEMF_PUBLIC)))
|
|
return XADERR_NOMEMORY;
|
|
|
|
for(i = ai->xai_LowCyl; !err && i <= ai->xai_HighCyl; ++i)
|
|
{
|
|
if(j >= 0 || !(err = GetTrackHead(ai, &th, oldmode, zh->Flags & USEHEADER, xadMasterBase)))
|
|
{
|
|
if(j == -1)
|
|
j = 0;
|
|
|
|
if(j > BOXSIZE || th.Tracks[j] > i)
|
|
{
|
|
ClearMemLong((xadUINT32 *) ebuf, TRACKSIZE/4);
|
|
err = xadHookAccess(XADM XADAC_WRITE, TRACKSIZE, ebuf, ai);
|
|
}
|
|
else
|
|
{
|
|
if(th.Tracks[j] == i)
|
|
{
|
|
if(!readdata)
|
|
{
|
|
if(!(err = DoDecrunchZoom(&buf, &th, oldmode, pwd, ai, xadMasterBase)))
|
|
readdata = 1;
|
|
}
|
|
if(readdata)
|
|
{
|
|
if(zh->Flags & USEHEADER)
|
|
err = xadHookTagAccess(XADM XADAC_WRITE, TRACKSIZE,
|
|
buf+(j * (TRACKSIZE + 22*16)), ai, XAD_SECTORLABELS,
|
|
buf+(j * (TRACKSIZE + 22*16)) + TRACKSIZE, TAG_DONE);
|
|
else
|
|
{
|
|
UnPackTrack(&th, buf, ebuf, j, xadMasterBase);
|
|
err = xadHookAccess(XADM XADAC_WRITE, TRACKSIZE, ebuf, ai);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
--i; /* was a back-track --> skipped, run this loop again */
|
|
|
|
if(++j == BOXSIZE)
|
|
{
|
|
if(i < zh->To) /* if not, j runs over --> th is no longer accessable */
|
|
{
|
|
if(!readdata)
|
|
err = xadHookAccess(XADM XADAC_INPUTSEEK, th.Length, 0, ai);
|
|
else
|
|
xadFreeObjectA(XADM buf, 0);
|
|
j = -1; readdata = 0; buf = 0;
|
|
}
|
|
}
|
|
} /* Tracks <= i */
|
|
} /* read TrackHeader */
|
|
} /* for loop */
|
|
|
|
if(buf)
|
|
xadFreeObjectA(XADM buf, 0);
|
|
xadFreeObjectA(XADM ebuf, 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
struct LhPakEntry {
|
|
xadUINT32 SkipSize; /* 0 */
|
|
xadUINT16 CrunchedSize; /* 4 */
|
|
xadUINT16 BlockNumber; /* 6 */
|
|
xadUINT32 UnCrunchedSize; /* 8 */
|
|
xadUINT32 CRC; /* C */
|
|
xadUINT32 CheckSum; /* 10 */
|
|
};
|
|
|
|
struct LhPakHead {
|
|
struct LhPakEntry Entry; /* 0 */
|
|
xadUINT32 Protection; /* 14 */
|
|
xadUINT32 Size; /* 18 */
|
|
xadUINT8 Date[12]; /* 1C */
|
|
xadUINT16 pad1; /* 28 */
|
|
xadUINT8 LengthFileName; /* 2A */
|
|
xadUINT8 LengthComment; /* 2B */
|
|
};
|
|
|
|
XADRECOGDATA(LhPak)
|
|
{
|
|
if(((xadUINT32 *)data)[0] == 0x3F3 /* HUNK_HEADER */)
|
|
{
|
|
if(((xadUINT32 *)data)[10] == 0x4C534658 &&
|
|
((xadUINT32 *)data)[12] == 0x2C790000 &&
|
|
((xadUINT32 *)data)[14] == 0x01144AAA &&
|
|
((xadUINT32 *)data)[15] == 0x00AC6600 &&
|
|
((xadUINT32 *)data)[16] == 0x001841EA)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* maybe there are some errors in that code, not tested yet */
|
|
XADGETINFO(LhPak)
|
|
{
|
|
xadINT32 err;
|
|
xadUINT32 buffer[6];
|
|
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 24, buffer, ai)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, 0x80+buffer[5]*4-24, 0, ai)))
|
|
{
|
|
struct xadFileInfo *fi = 0, *fi2;
|
|
struct LhPakHead ph;
|
|
xadINT32 goon = 1;
|
|
xadUINT32 pos, num = 1;
|
|
|
|
while(goon && !err)
|
|
{
|
|
pos = (xadUINT32)ai->xai_InPos;
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct LhPakHead), &ph, ai)))
|
|
{
|
|
if(!ph.Entry.SkipSize)
|
|
goon = 0;
|
|
if(!(fi2 = xadAllocObject(XADM XADOBJ_FILEINFO, XAD_OBJNAMESIZE,
|
|
4*ph.LengthFileName, ph.LengthComment ? XAD_OBJCOMMENTSIZE : TAG_DONE,
|
|
4*ph.LengthComment, TAG_DONE)))
|
|
err = XADERR_NOMEMORY;
|
|
else
|
|
{
|
|
fi2->xfi_EntryNumber = num++;
|
|
fi2->xfi_DataPos = pos;
|
|
fi2->xfi_Flags |= XADFIF_SEEKDATAPOS;
|
|
fi2->xfi_CrunchSize = ph.Entry.CrunchedSize;
|
|
fi2->xfi_Protection = ph.Protection;
|
|
xadConvertDates(XADM XAD_DATEDATESTAMP, &ph.Date, XAD_GETDATEXADDATE,
|
|
&fi2->xfi_Date, TAG_DONE);
|
|
fi2->xfi_Size = ph.Size;
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 4*ph.LengthFileName, fi2->xfi_FileName, ai)))
|
|
{
|
|
if(!ph.LengthComment || !(err = xadHookAccess(XADM XADAC_READ, 4*ph.LengthComment, fi2->xfi_Comment, ai)))
|
|
{
|
|
xadUINT32 i = 0, j;
|
|
|
|
for(pos = 0; pos < 11; ++pos)
|
|
i += ((xadUINT32 *) &ph)[pos];
|
|
for(pos = 0; pos < ph.LengthFileName; ++pos)
|
|
i += ((xadUINT32 *) fi2->xfi_FileName)[pos];
|
|
for(pos = 0; pos < ph.LengthComment; ++pos)
|
|
i += ((xadUINT32 *) fi2->xfi_Comment)[pos];
|
|
if(i)
|
|
err = XADERR_CHECKSUM;
|
|
else if(goon && !(err = xadHookAccess(XADM XADAC_INPUTSEEK, ph.Entry.SkipSize-
|
|
sizeof(struct LhPakHead)-4*(ph.LengthFileName+ph.LengthComment), 0, ai)))
|
|
{
|
|
i = ph.Entry.UnCrunchedSize;
|
|
|
|
while(i < ph.Size && !err && goon)
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct LhPakEntry), &ph, ai)))
|
|
{
|
|
for(j = pos = 0; pos < 5; ++pos)
|
|
j += ((xadUINT32 *) &ph)[pos];
|
|
if(j)
|
|
err = XADERR_CHECKSUM;
|
|
else
|
|
{
|
|
i += ph.Entry.UnCrunchedSize;
|
|
fi2->xfi_CrunchSize += ph.Entry.CrunchedSize;
|
|
if(!ph.Entry.SkipSize)
|
|
goon = 0;
|
|
else
|
|
err = xadHookAccess(XADM XADAC_INPUTSEEK, ph.Entry.SkipSize-sizeof(struct LhPakEntry), 0, ai);
|
|
}
|
|
}
|
|
}
|
|
if(!goon && i < ph.Size)
|
|
err = XADERR_ILLEGALDATA;
|
|
}
|
|
}
|
|
}
|
|
if(err)
|
|
xadFreeObjectA(XADM fi2, 0);
|
|
else if(fi)
|
|
{
|
|
fi->xfi_Next = fi2; fi = fi2;
|
|
}
|
|
else
|
|
ai->xai_FileInfo = fi = fi2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(err && fi)
|
|
{
|
|
err = 0;
|
|
ai->xai_Flags |= XADAIF_FILECORRUPT;
|
|
}
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
XADUNARCHIVE(LhPak)
|
|
{
|
|
xadINT32 i, j, err;
|
|
struct LhPakHead ph;
|
|
xadSTRPTR buf;
|
|
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct LhPakHead), &ph, ai)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, (ph.LengthFileName+ph.LengthComment)*4, 0, ai)))
|
|
{
|
|
i = 0;
|
|
ph.Entry.SkipSize -= sizeof(struct LhPakHead) - sizeof(struct LhPakEntry) +
|
|
(ph.LengthFileName+ph.LengthComment)*4;
|
|
|
|
while(i < ph.Size && !err)
|
|
{
|
|
i += ph.Entry.UnCrunchedSize;
|
|
if(!(err = DoDecrunch(&buf, ph.Entry.CrunchedSize, ph.Entry.UnCrunchedSize,
|
|
100, ai, xadMasterBase, ph.Entry.CRC)))
|
|
{
|
|
err = xadHookAccess(XADM XADAC_WRITE, ph.Entry.UnCrunchedSize, buf, ai);
|
|
xadFreeObjectA(XADM buf,0);
|
|
}
|
|
if(!err && i < ph.Size)
|
|
{
|
|
if((j = ph.Entry.SkipSize - ph.Entry.CrunchedSize - sizeof(struct LhPakEntry)))
|
|
err = xadHookAccess(XADM XADAC_INPUTSEEK, j, 0, ai);
|
|
if(!err)
|
|
err = xadHookAccess(XADM XADAC_READ, sizeof(struct LhPakEntry), &ph, ai);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
XADRECOGDATA(PCompPACK)
|
|
{
|
|
if(*((xadUINT32 *) data) == 0x5041434B)
|
|
{
|
|
xadUINT32 i;
|
|
|
|
for(i = 4; i < size; ++i)
|
|
{
|
|
if(data[i] == '\n')
|
|
{
|
|
if(++i < size && data[i]) /* too large file size */
|
|
return 0;
|
|
return 1;
|
|
}
|
|
else if((data[i] & 0x7F) < 32) /* printable ASCII name */
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
XADGETINFO(PCompPACK)
|
|
{
|
|
xadINT32 err, i, j, k, num = 1;
|
|
xadUINT8 buffer[512];
|
|
struct xadFileInfo *fi = 0, *fi2;
|
|
|
|
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, 4, 0, ai)))
|
|
return err;
|
|
while(!err && ai->xai_InSize-ai->xai_InPos > 4)
|
|
{
|
|
if((j = (xadINT32)(ai->xai_InSize-ai->xai_InPos)) > 512)
|
|
j = 512;
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, j, buffer, ai)))
|
|
{
|
|
for(i = 0; i != j - 5 && buffer[i] != '\n'; ++i)
|
|
;
|
|
if(buffer[i] == '\n')
|
|
{
|
|
k = (buffer[i+1]<<24)+(buffer[i+2]<<16)+(buffer[i+3]<<8)+buffer[i+4];
|
|
|
|
j = (xadINT32)ai->xai_InPos-j+i+5;
|
|
|
|
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, j-ai->xai_InPos+k, 0, ai)))
|
|
{
|
|
if((fi2 = (struct xadFileInfo *) xadAllocObject(XADM XADOBJ_FILEINFO,
|
|
XAD_OBJNAMESIZE, i+1, TAG_DONE)))
|
|
{
|
|
fi2->xfi_DataPos = j; /* file position */
|
|
fi2->xfi_CrunchSize = k;
|
|
fi2->xfi_EntryNumber = num++;
|
|
fi2->xfi_Flags = XADFIF_NODATE|XADFIF_SEEKDATAPOS;
|
|
for(j = 0; j < i; ++j)
|
|
fi2->xfi_FileName[j] = buffer[j];
|
|
err = xadConvertDates(XADM XAD_DATECURRENTTIME, 1, XAD_GETDATEXADDATE,
|
|
&fi2->xfi_Date, TAG_DONE);
|
|
if(k > 10)
|
|
{
|
|
i += 5;
|
|
if(buffer[i] == 'L' && buffer[i+1] == 'H' && buffer[i+2] == 0 && buffer[i+6] == 0)
|
|
k = (buffer[i+2]<<24)+(buffer[i+3]<<16)+(buffer[i+4]<<8)+buffer[i+5];
|
|
}
|
|
fi2->xfi_Size = k;
|
|
if(fi)
|
|
fi->xfi_Next = fi2;
|
|
else
|
|
ai->xai_FileInfo = fi2;
|
|
fi = fi2;
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
}
|
|
else
|
|
err = XADERR_ILLEGALDATA;
|
|
}
|
|
}
|
|
if(err)
|
|
{
|
|
ai->xai_Flags |= XADAIF_FILECORRUPT;
|
|
ai->xai_LastError = err;
|
|
}
|
|
|
|
return fi ? 0 : XADERR_ILLEGALDATA;
|
|
}
|
|
|
|
struct PCompData {
|
|
xadUINT16 ID;
|
|
xadUINT32 Size;
|
|
xadUINT32 CrunchedSize;
|
|
xadUINT32 CRC;
|
|
};
|
|
|
|
XADUNARCHIVE(PCompPACK)
|
|
{
|
|
xadINT32 i, err;
|
|
|
|
i = (xadINT32)ai->xai_CurFile->xfi_Size;
|
|
if(i == ai->xai_CurFile->xfi_CrunchSize)
|
|
err = xadHookAccess(XADM XADAC_COPY, i, 0, ai);
|
|
else
|
|
{
|
|
struct PCompData pc;
|
|
xadSTRPTR buf;
|
|
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct PCompData), &pc, ai)))
|
|
{
|
|
if(!(err = DoDecrunch(&buf, pc.CrunchedSize, pc.Size, 100, ai, xadMasterBase,
|
|
pc.CRC)))
|
|
{
|
|
err = xadHookAccess(XADM XADAC_WRITE, pc.Size, buf, ai);
|
|
xadFreeObjectA(XADM buf, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
XADRECOGDATA(SOmni)
|
|
{
|
|
if(((xadUINT32 *)data)[0] == 0x3F3 /* HUNK_HEADER */)
|
|
{
|
|
if(((xadUINT32 *)data)[10] == 0x42ADFFF4 &&
|
|
((xadUINT32 *)data)[12] == 0x00044EAE &&
|
|
((xadUINT32 *)data)[14] == 0x4AAC00AC &&
|
|
((xadUINT32 *)data)[15] == 0x67026014 &&
|
|
((xadUINT32 *)data)[16] == 0x41EC005C)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
XADGETINFO(SOmni)
|
|
{
|
|
xadINT32 err, i, j, num = 1;
|
|
xadUINT16 a;
|
|
xadUINT8 buffer[10];
|
|
struct xadFileInfo *fi = 0, *fi2;
|
|
|
|
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, 0x208, 0, ai)))
|
|
return err;
|
|
if((err = xadHookAccess(XADM XADAC_READ, 4, &i, ai)))
|
|
return err;
|
|
|
|
if(i == 0x51CDFFFC)
|
|
{
|
|
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, 0x7A8-0x208-4, 0, ai)))
|
|
return err;
|
|
}
|
|
else if(i == 0x76002C7A)
|
|
{
|
|
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, 0x744-0x208-4, 0, ai)))
|
|
return err;
|
|
}
|
|
else
|
|
return XADERR_ILLEGALDATA;
|
|
|
|
if((err = xadHookAccess(XADM XADAC_READ, 2, &a, ai)))
|
|
return err;
|
|
if(a == 1) /* skip command line */
|
|
{
|
|
if((err = xadHookAccess(XADM XADAC_READ, 2, &a, ai)))
|
|
return err;
|
|
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, a, 0, ai)))
|
|
return err;
|
|
}
|
|
while(!err)
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 2, &a, ai)) && a)
|
|
{
|
|
if((fi2 = (struct xadFileInfo *) xadAllocObject(XADM XADOBJ_FILEINFO,
|
|
XAD_OBJNAMESIZE, a+1, TAG_DONE)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, a, fi2->xfi_FileName, ai)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 4, &i, ai)))
|
|
{
|
|
fi2->xfi_DataPos = ai->xai_InPos; /* file position */
|
|
fi2->xfi_CrunchSize = i;
|
|
j = i+2;
|
|
fi2->xfi_EntryNumber = num++;
|
|
fi2->xfi_Flags = XADFIF_NODATE|XADFIF_SEEKDATAPOS;
|
|
err = xadConvertDates(XADM XAD_DATECURRENTTIME, 1, XAD_GETDATEXADDATE,
|
|
&fi2->xfi_Date, TAG_DONE);
|
|
|
|
if(i > 10)
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 10, buffer, ai)))
|
|
{
|
|
if(buffer[0] == 'L' && buffer[1] == 'H' && buffer[2] == 0 && buffer[6] == 0)
|
|
i = (buffer[2]<<24)+(buffer[3]<<16)+(buffer[4]<<8)+buffer[5];
|
|
j -= 10;
|
|
}
|
|
}
|
|
fi2->xfi_Size = i;
|
|
|
|
if(!err)
|
|
err = xadHookAccess(XADM XADAC_INPUTSEEK, j, 0, ai);
|
|
}
|
|
}
|
|
|
|
if(err)
|
|
xadFreeObjectA(XADM fi2, 0);
|
|
else
|
|
{
|
|
if(fi)
|
|
fi->xfi_Next = fi2;
|
|
else
|
|
ai->xai_FileInfo = fi2;
|
|
fi = fi2;
|
|
}
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
else if(!a)
|
|
break;
|
|
}
|
|
if(err)
|
|
{
|
|
ai->xai_Flags |= XADAIF_FILECORRUPT;
|
|
ai->xai_LastError = err;
|
|
}
|
|
|
|
return fi ? 0 : XADERR_ILLEGALDATA;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
XADRECOGDATA(LhSFX)
|
|
{
|
|
if(((xadUINT32 *)data)[0] == 0x3F3 /* HUNK_HEADER */)
|
|
{
|
|
if(((xadUINT32 *)data)[10] == 0x43F90000 &&
|
|
((xadUINT32 *)data)[12] == 0x00000318 &&
|
|
((xadUINT32 *)data)[14] == 0x02EC2C79 &&
|
|
((xadUINT32 *)data)[15] == 0x00000004 &&
|
|
((xadUINT32 *)data)[16] == 0x4EAEFDD8)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct LhSFXData {
|
|
xadUINT32 Size;
|
|
xadUINT32 CrSize;
|
|
xadUINT32 pad; /* don't know what that is! */
|
|
xadUINT8 Name[48];
|
|
};
|
|
|
|
XADGETINFO(LhSFX)
|
|
{
|
|
xadINT32 err, i, j, num = 1;
|
|
struct LhSFXData sf;
|
|
struct xadFileInfo *fi = 0, *fi2;
|
|
|
|
if((err = xadHookAccess(XADM XADAC_INPUTSEEK, 0x918, 0, ai)))
|
|
return err;
|
|
|
|
while(!err)
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, 4, &i, ai)) && i != -1)
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct LhSFXData), &sf, ai)))
|
|
{
|
|
j = (xadINT32)ai->xai_InPos;
|
|
if(!(err = xadHookAccess(XADM XADAC_INPUTSEEK, sf.CrSize, 0, ai)))
|
|
{
|
|
for(i = 0; i < 48 && sf.Name[i]; ++i)
|
|
;
|
|
if((fi2 = (struct xadFileInfo *) xadAllocObject(XADM XADOBJ_FILEINFO,
|
|
i ? XAD_OBJNAMESIZE : TAG_IGNORE, i+1, TAG_DONE)))
|
|
{
|
|
if(i)
|
|
xadCopyMem(XADM sf.Name, fi2->xfi_FileName, i);
|
|
else
|
|
{
|
|
fi2->xfi_FileName = xadGetDefaultName(XADM XAD_ARCHIVEINFO, ai,
|
|
XAD_EXTENSION, ".sfx", TAG_DONE);
|
|
fi2->xfi_Flags |= XADFIF_NOFILENAME|XADFIF_XADSTRFILENAME;
|
|
}
|
|
fi2->xfi_DataPos = j; /* file position */
|
|
fi2->xfi_CrunchSize = sf.CrSize;
|
|
fi2->xfi_Size = sf.Size;
|
|
fi2->xfi_EntryNumber = num++;
|
|
fi2->xfi_Flags |= XADFIF_NODATE|XADFIF_SEEKDATAPOS;
|
|
err = xadConvertDates(XADM XAD_DATECURRENTTIME, 1, XAD_GETDATEXADDATE,
|
|
&fi2->xfi_Date, TAG_DONE);
|
|
if(fi)
|
|
fi->xfi_Next = fi2;
|
|
else
|
|
ai->xai_FileInfo = fi2;
|
|
fi = fi2;
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
}
|
|
}
|
|
else if(i == -1)
|
|
break;
|
|
}
|
|
if(err)
|
|
{
|
|
ai->xai_Flags |= XADAIF_FILECORRUPT;
|
|
ai->xai_LastError = err;
|
|
}
|
|
|
|
return fi ? 0 : XADERR_ILLEGALDATA;
|
|
}
|
|
|
|
XADUNARCHIVE(LhSFX)
|
|
{
|
|
xadSTRPTR buf;
|
|
xadINT32 err;
|
|
|
|
if(!(err = DoDecrunch(&buf, (xadUINT32)ai->xai_CurFile->xfi_CrunchSize,
|
|
(xadUINT32)ai->xai_CurFile->xfi_Size, 200, ai, xadMasterBase, 0)))
|
|
{
|
|
err = xadHookAccess(XADM XADAC_WRITE, ai->xai_CurFile->xfi_Size, buf, ai);
|
|
xadFreeObjectA(XADM buf, 0);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
XADCLIENT(LhSFX) {
|
|
XADNEXTCLIENT,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
SOMNI_VERSION,
|
|
SOMNI_REVISION,
|
|
100,
|
|
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
|
|
XADCID_LHSFX,
|
|
"LhSFX",
|
|
XADRECOGDATAP(LhSFX),
|
|
XADGETINFOP(LhSFX),
|
|
XADUNARCHIVEP(LhSFX),
|
|
NULL
|
|
};
|
|
|
|
XADCLIENT(SOmni) {
|
|
(struct xadClient *) &LhSFX_Client,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
SOMNI_VERSION,
|
|
SOMNI_REVISION,
|
|
100,
|
|
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
|
|
XADCID_SOMNI,
|
|
"S-Omni",
|
|
XADRECOGDATAP(SOmni),
|
|
XADGETINFOP(SOmni),
|
|
XADUNARCHIVEP(PCompPACK),
|
|
NULL
|
|
};
|
|
|
|
XADCLIENT(PCompPACK) {
|
|
(struct xadClient *) &SOmni_Client,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
PCOMP_VERSION,
|
|
PCOMP_REVISION,
|
|
50,
|
|
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
|
|
XADCID_PCOMPARC,
|
|
"PCompress PACK",
|
|
XADRECOGDATAP(PCompPACK),
|
|
XADGETINFOP(PCompPACK),
|
|
XADUNARCHIVEP(PCompPACK),
|
|
NULL
|
|
};
|
|
|
|
XADCLIENT(LhPak) {
|
|
(struct xadClient *) &PCompPACK_Client,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
LHPAK_VERSION,
|
|
LHPAK_REVISION,
|
|
100,
|
|
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
|
|
XADCID_LHPAK,
|
|
"LhPak SFX",
|
|
XADRECOGDATAP(LhPak),
|
|
XADGETINFOP(LhPak),
|
|
XADUNARCHIVEP(LhPak),
|
|
NULL
|
|
};
|
|
|
|
XADCLIENT(Zoom5) {
|
|
(struct xadClient *) &LhPak_Client,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
ZOOM_VERSION,
|
|
ZOOM_REVISION,
|
|
76,
|
|
XADCF_DISKARCHIVER|XADCF_FREEDISKINFO|XADCF_FREETEXTINFO|XADCF_FREETEXTINFOTEXT,
|
|
XADCID_ZOOM5,
|
|
"Zoom 5",
|
|
XADRECOGDATAP(Zoom5),
|
|
XADGETINFOP(Zoom),
|
|
XADUNARCHIVEP(Zoom),
|
|
NULL
|
|
};
|
|
|
|
XADFIRSTCLIENT(Zoom) {
|
|
(struct xadClient *) &Zoom5_Client,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
ZOOM_VERSION,
|
|
ZOOM_REVISION,
|
|
76,
|
|
XADCF_DISKARCHIVER|XADCF_FREEDISKINFO|XADCF_FREETEXTINFO|XADCF_FREETEXTINFOTEXT,
|
|
XADCID_ZOOM,
|
|
"Zoom",
|
|
XADRECOGDATAP(Zoom),
|
|
XADGETINFOP(Zoom),
|
|
XADUNARCHIVEP(Zoom),
|
|
NULL
|
|
};
|
|
|
|
#undef XADNEXTCLIENT
|
|
#define XADNEXTCLIENT XADNEXTCLIENTNAME(Zoom)
|
|
|
|
#endif /* XADMASTER_ZOOM_C */
|