[Scummvm-cvs-logs] SF.net SVN: scummvm:[35284] residual/trunk
aquadran at users.sourceforge.net
aquadran at users.sourceforge.net
Sun Dec 7 23:46:45 CET 2008
Revision: 35284
http://scummvm.svn.sourceforge.net/scummvm/?rev=35284&view=rev
Author: aquadran
Date: 2008-12-07 22:46:45 +0000 (Sun, 07 Dec 2008)
Log Message:
-----------
added patch extractor
Modified Paths:
--------------
residual/trunk/AUTHORS
residual/trunk/tools/module.mk
Added Paths:
-----------
residual/trunk/tools/patch_ex/
residual/trunk/tools/patch_ex/cab.h
residual/trunk/tools/patch_ex/cabd.cpp
residual/trunk/tools/patch_ex/mspack.h
residual/trunk/tools/patch_ex/mszip.h
residual/trunk/tools/patch_ex/mszipd.cpp
residual/trunk/tools/patch_ex/patch_ex.cpp
Modified: residual/trunk/AUTHORS
===================================================================
--- residual/trunk/AUTHORS 2008-12-07 19:15:57 UTC (rev 35283)
+++ residual/trunk/AUTHORS 2008-12-07 22:46:45 UTC (rev 35284)
@@ -13,7 +13,7 @@
Torbjorn Andersson - Various code fixes
Ori Avtalion - Lipsync, LAF support
Marcus Comstedt - Dreamcast port
- Andrea Corna - Improved font support
+ Andrea Corna - Improved font support, patch extractor
Jonathan Gray - Various code fixes
Vincent Hamm - Various engine code
Travis Howell - Various code fixes, Windows daily builds
Modified: residual/trunk/tools/module.mk
===================================================================
--- residual/trunk/tools/module.mk 2008-12-07 19:15:57 UTC (rev 35283)
+++ residual/trunk/tools/module.mk 2008-12-07 22:46:45 UTC (rev 35284)
@@ -17,7 +17,8 @@
tools/int2flt$(EXEEXT) \
tools/set2fig$(EXEEXT) \
tools/unlab$(EXEEXT) \
- tools/vima$(EXEEXT)
+ tools/vima$(EXEEXT) \
+ tools/patch_ex/patch_ex$(EXEEXT)
# below not added as it depends for ppm, bpm library
# tools/mat2ppm$(EXEEXT)
@@ -32,6 +33,8 @@
clean-tools:
-$(RM) $(TOOLS)
+ -$(RM) tools/patch_ex/*.o
+ -$(RM) -r tools/patch_ex/.deps
#
# Build rules for the tools
@@ -77,4 +80,8 @@
$(MKDIR) tools/$(DEPDIR)
$(CXX) $(CFLAGS) -Wall -o $@ $<
+tools/patch_ex/patch_ex$(EXEEXT): $(srcdir)/tools/patch_ex/patch_ex.o $(srcdir)/tools/patch_ex/mszipd.o $(srcdir)/tools/patch_ex/cabd.o
+ $(MKDIR) tools/patch_ex/$(DEPDIR)
+ $(CXX) $(CFLAGS) tools/patch_ex/mszipd.o tools/patch_ex/cabd.o -Wall -o $@ $<
+
.PHONY: clean-tools tools
Property changes on: residual/trunk/tools/patch_ex
___________________________________________________________________
Added: svn:ignore
+ patch_ex
*.o
*.d
Added: residual/trunk/tools/patch_ex/cab.h
===================================================================
--- residual/trunk/tools/patch_ex/cab.h (rev 0)
+++ residual/trunk/tools/patch_ex/cab.h 2008-12-07 22:46:45 UTC (rev 35284)
@@ -0,0 +1,124 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * file distributed with this source distribution.
+
+ * 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
+ *
+ * $URL
+ * $Id
+ *
+ */
+
+/* This file is part of libmspack.
+ * (C) 2003-2004 Stuart Caie.
+ *
+ * This source code is adopted and striped for Residual project.
+ *
+ * libmspack is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * For further details, see the file COPYING.LIB distributed with libmspack
+ */
+
+#ifndef MSPACK_CAB_H
+#define MSPACK_CAB_H
+
+#include "tools/patch_ex/mszip.h"
+
+#define cfhead_Signature (0x00)
+#define cfhead_CabinetSize (0x08)
+#define cfhead_FileOffset (0x10)
+#define cfhead_MinorVersion (0x18)
+#define cfhead_MajorVersion (0x19)
+#define cfhead_NumFolders (0x1A)
+#define cfhead_NumFiles (0x1C)
+#define cfhead_Flags (0x1E)
+#define cfhead_SetID (0x20)
+#define cfhead_CabinetIndex (0x22)
+#define cfhead_SIZEOF (0x24)
+#define cfheadext_HeaderReserved (0x00)
+#define cfheadext_FolderReserved (0x02)
+#define cfheadext_DataReserved (0x03)
+#define cfheadext_SIZEOF (0x04)
+#define cffold_DataOffset (0x00)
+#define cffold_NumBlocks (0x04)
+#define cffold_CompType (0x06)
+#define cffold_SIZEOF (0x08)
+#define cffile_UncompressedSize (0x00)
+#define cffile_FolderOffset (0x04)
+#define cffile_FolderIndex (0x08)
+#define cffile_Date (0x0A)
+#define cffile_Time (0x0C)
+#define cffile_Attribs (0x0E)
+#define cffile_SIZEOF (0x10)
+#define cfdata_CheckSum (0x00)
+#define cfdata_CompressedSize (0x04)
+#define cfdata_UncompressedSize (0x06)
+#define cfdata_SIZEOF (0x08)
+
+#define cffoldCOMPTYPE_MASK (0x000f)
+#define cffoldCOMPTYPE_NONE (0x0000)
+#define cffoldCOMPTYPE_MSZIP (0x0001)
+#define cfheadPREV_CABINET (0x0001)
+#define cfheadNEXT_CABINET (0x0002)
+#define cfheadRESERVE_PRESENT (0x0004)
+#define cffileCONTINUED_FROM_PREV (0xFFFD)
+#define cffileCONTINUED_TO_NEXT (0xFFFE)
+#define cffileCONTINUED_PREV_AND_NEXT (0xFFFF)
+
+#define CAB_BLOCKMAX (32768)
+#define CAB_INPUTMAX (CAB_BLOCKMAX+6144)
+
+struct mscabd_decompress_state {
+ struct mscabd_folder_p *folder;
+ struct mscabd_folder_data *data;
+ unsigned int offset;
+ unsigned int block;
+ struct mspack_system sys;
+ int comp_type;
+ int (*decompress)(void *, off_t);
+ void *state;
+ struct mscabd_cabinet_p *incab;
+ struct mspack_file *infh;
+ struct mspack_file *outfh;
+ unsigned char *i_ptr, *i_end;
+ unsigned char input[CAB_INPUTMAX];
+};
+
+struct mscab_decompressor_p {
+ struct mscab_decompressor base;
+ struct mscabd_decompress_state *d;
+ struct mspack_system *system;
+ int param[3];
+ int error;
+};
+
+struct mscabd_cabinet_p {
+ struct mscabd_cabinet base;
+ off_t blocks_off;
+ int block_resv;
+};
+
+struct mscabd_folder_data {
+ struct mscabd_folder_data *next;
+ struct mscabd_cabinet_p *cab;
+ off_t offset;
+};
+
+struct mscabd_folder_p {
+ struct mscabd_folder base;
+ struct mscabd_folder_data data;
+ struct mscabd_file *merge_prev;
+ struct mscabd_file *merge_next;
+};
+
+#endif
Property changes on: residual/trunk/tools/patch_ex/cab.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/tools/patch_ex/cabd.cpp
===================================================================
--- residual/trunk/tools/patch_ex/cabd.cpp (rev 0)
+++ residual/trunk/tools/patch_ex/cabd.cpp 2008-12-07 22:46:45 UTC (rev 35284)
@@ -0,0 +1,687 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * file distributed with this source distribution.
+
+ * 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
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* This file is part of libmspack.
+ * (C) 2003-2004 Stuart Caie.
+ *
+ * This source code is adopted and striped for Residual project.
+ *
+ * libmspack is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * For further details, see the file COPYING.LIB distributed with libmspack
+ */
+
+#include "tools/patch_ex/cab.h"
+
+static struct mscabd_cabinet * cabd_open(
+ struct mscab_decompressor *base, char *filename);
+static void cabd_close(
+ struct mscab_decompressor *base, struct mscabd_cabinet *origcab);
+static int cabd_read_headers(
+ struct mspack_system *sys, struct mspack_file *fh,
+ struct mscabd_cabinet_p *cab, off_t offset, int quiet);
+static char *cabd_read_string(
+ struct mspack_system *sys, struct mspack_file *fh,
+ struct mscabd_cabinet_p *cab, int *error);
+
+static int cabd_extract(
+ struct mscab_decompressor *base, struct mscabd_file *file, char *filename);
+static int cabd_init_decomp(
+ struct mscab_decompressor_p *handle, unsigned int ct);
+static void cabd_free_decomp(
+ struct mscab_decompressor_p *handle);
+static int cabd_sys_read(
+ struct mspack_file *file, void *buffer, int bytes);
+static int cabd_sys_write(
+ struct mspack_file *file, void *buffer, int bytes);
+static int cabd_sys_read_block(
+ struct mspack_system *sys, struct mscabd_decompress_state *d, int *out,
+ int ignore_cksum);
+static unsigned int cabd_checksum(
+ unsigned char *data, unsigned int bytes, unsigned int cksum);
+
+static int cabd_error(
+ struct mscab_decompressor *base);
+
+#define __egi32(a,n) ( ((((unsigned char *) a)[n+3]) << 24) | \
+ ((((unsigned char *) a)[n+2]) << 16) | \
+ ((((unsigned char *) a)[n+1]) << 8) | \
+ ((((unsigned char *) a)[n+0])))
+
+#define EndGetI32(a) __egi32(a,0)
+#define EndGetI16(a) ((((a)[1])<<8)|((a)[0]))
+
+struct mscab_decompressor *
+ mspack_create_cab_decompressor(struct mspack_system *sys)
+{
+ struct mscab_decompressor_p *handle = NULL;
+
+ if ((handle = (mscab_decompressor_p *)sys->alloc(sys, sizeof(struct mscab_decompressor_p)))) {
+ handle->base.open = &cabd_open;
+ handle->base.close = &cabd_close;
+ handle->base.extract = &cabd_extract;
+ handle->base.last_error = &cabd_error;
+ handle->system = sys;
+ handle->d = NULL;
+ handle->error = MSPACK_ERR_OK;
+
+ handle->param[MSCABD_PARAM_SEARCHBUF] = 32768;
+ handle->param[MSCABD_PARAM_FIXMSZIP] = 0;
+ handle->param[MSCABD_PARAM_DECOMPBUF] = 4096;
+ }
+ return (struct mscab_decompressor *) handle;
+}
+
+void mspack_destroy_cab_decompressor(struct mscab_decompressor *base) {
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) base;
+ if (handle) {
+ struct mspack_system *sys = handle->system;
+ cabd_free_decomp(handle);
+ if (handle->d) {
+ if (handle->d->infh) sys->close(handle->d->infh);
+ sys->free(handle->d);
+ }
+ sys->free(handle);
+ }
+}
+
+static struct mscabd_cabinet *cabd_open(struct mscab_decompressor *base,
+ char *filename)
+{
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) base;
+ struct mscabd_cabinet_p *cab = NULL;
+ struct mspack_system *sys;
+ struct mspack_file *fh;
+ int error;
+
+ if (!base) return NULL;
+ sys = handle->system;
+
+ if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
+ if ((cab = (mscabd_cabinet_p *)sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
+ cab->base.filename = filename;
+ error = cabd_read_headers(sys, fh, cab, (off_t) 0, 0);
+ if (error) {
+ cabd_close(base, (struct mscabd_cabinet *) cab);
+ cab = NULL;
+ }
+ handle->error = error;
+ }
+ else {
+ handle->error = MSPACK_ERR_NOMEMORY;
+ }
+ sys->close(fh);
+ }
+ else {
+ handle->error = MSPACK_ERR_OPEN;
+ }
+ return (struct mscabd_cabinet *) cab;
+}
+
+static void cabd_close(struct mscab_decompressor *base,
+ struct mscabd_cabinet *origcab)
+{
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) base;
+ struct mscabd_folder_data *dat, *ndat;
+ struct mscabd_cabinet *cab, *ncab;
+ struct mscabd_folder *fol, *nfol;
+ struct mscabd_file *fi, *nfi;
+ struct mspack_system *sys;
+
+ if (!base) return;
+ sys = handle->system;
+
+ handle->error = MSPACK_ERR_OK;
+
+ while (origcab) {
+ /* free files */
+ for (fi = origcab->files; fi; fi = nfi) {
+ nfi = fi->next;
+ sys->free(fi->filename);
+ sys->free(fi);
+ }
+
+ for (fol = origcab->folders; fol; fol = nfol) {
+ nfol = fol->next;
+
+ if (handle->d && (handle->d->folder == (struct mscabd_folder_p *) fol)) {
+ if (handle->d->infh) sys->close(handle->d->infh);
+ cabd_free_decomp(handle);
+ sys->free(handle->d);
+ handle->d = NULL;
+ }
+
+ for (dat = ((struct mscabd_folder_p *)fol)->data.next; dat; dat = ndat) {
+ ndat = dat->next;
+ sys->free(dat);
+ }
+ sys->free(fol);
+ }
+
+ for (cab = origcab; cab; cab = ncab) {
+ ncab = cab->prevcab;
+ sys->free(cab->prevname);
+ sys->free(cab->nextname);
+ sys->free(cab->previnfo);
+ sys->free(cab->nextinfo);
+ if (cab != origcab) sys->free(cab);
+ }
+
+ for (cab = origcab->nextcab; cab; cab = ncab) {
+ ncab = cab->nextcab;
+ sys->free(cab->prevname);
+ sys->free(cab->nextname);
+ sys->free(cab->previnfo);
+ sys->free(cab->nextinfo);
+ sys->free(cab);
+ }
+
+ cab = origcab->next;
+ sys->free(origcab);
+
+ origcab = cab;
+ }
+}
+
+static int cabd_read_headers(struct mspack_system *sys,
+ struct mspack_file *fh,
+ struct mscabd_cabinet_p *cab,
+ off_t offset, int quiet)
+{
+ int num_folders, num_files, folder_resv, i, x;
+ struct mscabd_folder_p *fol, *linkfol = NULL;
+ struct mscabd_file *file, *linkfile = NULL;
+ unsigned char buf[64];
+
+ cab->base.next = NULL;
+ cab->base.files = NULL;
+ cab->base.folders = NULL;
+ cab->base.prevcab = cab->base.nextcab = NULL;
+ cab->base.prevname = cab->base.nextname = NULL;
+ cab->base.previnfo = cab->base.nextinfo = NULL;
+
+ cab->base.base_offset = offset;
+
+ if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
+ return MSPACK_ERR_SEEK;
+ }
+
+ if (sys->read(fh, &buf[0], cfhead_SIZEOF) != cfhead_SIZEOF) {
+ return MSPACK_ERR_READ;
+ }
+
+ if (EndGetI32(&buf[cfhead_Signature]) != 0x4643534D) {
+ return MSPACK_ERR_SIGNATURE;
+ }
+
+ cab->base.length = EndGetI32(&buf[cfhead_CabinetSize]);
+ cab->base.set_id = EndGetI16(&buf[cfhead_SetID]);
+ cab->base.set_index = EndGetI16(&buf[cfhead_CabinetIndex]);
+
+ num_folders = EndGetI16(&buf[cfhead_NumFolders]);
+ if (num_folders == 0) {
+ if (!quiet) sys->message(fh, "no folders in cabinet.");
+ return MSPACK_ERR_DATAFORMAT;
+ }
+
+ num_files = EndGetI16(&buf[cfhead_NumFiles]);
+ if (num_files == 0) {
+ if (!quiet) sys->message(fh, "no files in cabinet.");
+ return MSPACK_ERR_DATAFORMAT;
+ }
+
+ if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3)) {
+ if (!quiet) sys->message(fh, "WARNING; cabinet version is not 1.3");
+ }
+
+ cab->base.flags = EndGetI16(&buf[cfhead_Flags]);
+ if (cab->base.flags & cfheadRESERVE_PRESENT) {
+ if (sys->read(fh, &buf[0], cfheadext_SIZEOF) != cfheadext_SIZEOF) {
+ return MSPACK_ERR_READ;
+ }
+ cab->base.header_resv = EndGetI16(&buf[cfheadext_HeaderReserved]);
+ folder_resv = buf[cfheadext_FolderReserved];
+ cab->block_resv = buf[cfheadext_DataReserved];
+
+ if (cab->base.header_resv > 60000) {
+ if (!quiet) sys->message(fh, "WARNING; reserved header > 60000.");
+ }
+
+ if (cab->base.header_resv) {
+ if (sys->seek(fh, (off_t) cab->base.header_resv, MSPACK_SYS_SEEK_CUR)) {
+ return MSPACK_ERR_SEEK;
+ }
+ }
+ }
+ else {
+ cab->base.header_resv = 0;
+ folder_resv = 0;
+ cab->block_resv = 0;
+ }
+
+ if (cab->base.flags & cfheadPREV_CABINET) {
+ cab->base.prevname = cabd_read_string(sys, fh, cab, &x); if (x) return x;
+ cab->base.previnfo = cabd_read_string(sys, fh, cab, &x); if (x) return x;
+ }
+
+ if (cab->base.flags & cfheadNEXT_CABINET) {
+ cab->base.nextname = cabd_read_string(sys, fh, cab, &x); if (x) return x;
+ cab->base.nextinfo = cabd_read_string(sys, fh, cab, &x); if (x) return x;
+ }
+
+ for (i = 0; i < num_folders; i++) {
+ if (sys->read(fh, &buf[0], cffold_SIZEOF) != cffold_SIZEOF) {
+ return MSPACK_ERR_READ;
+ }
+ if (folder_resv) {
+ if (sys->seek(fh, (off_t) folder_resv, MSPACK_SYS_SEEK_CUR)) {
+ return MSPACK_ERR_SEEK;
+ }
+ }
+
+ if (!(fol = (struct mscabd_folder_p *)sys->alloc(sys, sizeof(struct mscabd_folder_p)))) {
+ return MSPACK_ERR_NOMEMORY;
+ }
+ fol->base.next = NULL;
+ fol->base.comp_type = EndGetI16(&buf[cffold_CompType]);
+ fol->base.num_blocks = EndGetI16(&buf[cffold_NumBlocks]);
+ fol->data.next = NULL;
+ fol->data.cab = (struct mscabd_cabinet_p *) cab;
+ fol->data.offset = offset + (off_t)
+ ( (unsigned int) EndGetI32(&buf[cffold_DataOffset]) );
+ fol->merge_prev = NULL;
+ fol->merge_next = NULL;
+
+ if (!linkfol) cab->base.folders = (struct mscabd_folder *) fol;
+ else linkfol->base.next = (struct mscabd_folder *) fol;
+ linkfol = fol;
+ }
+
+ for (i = 0; i < num_files; i++) {
+ if (sys->read(fh, &buf[0], cffile_SIZEOF) != cffile_SIZEOF) {
+ return MSPACK_ERR_READ;
+ }
+
+ if (!(file = (struct mscabd_file *)sys->alloc(sys, sizeof(struct mscabd_file)))) {
+ return MSPACK_ERR_NOMEMORY;
+ }
+
+ file->next = NULL;
+ file->length = EndGetI32(&buf[cffile_UncompressedSize]);
+ file->attribs = EndGetI16(&buf[cffile_Attribs]);
+ file->offset = EndGetI32(&buf[cffile_FolderOffset]);
+
+ x = EndGetI16(&buf[cffile_FolderIndex]);
+ if (x < cffileCONTINUED_FROM_PREV) {
+ struct mscabd_folder *ifol = cab->base.folders;
+ while (x--) if (ifol) ifol = ifol->next;
+ file->folder = ifol;
+
+ if (!ifol) {
+ sys->free(file);
+ return MSPACK_ERR_DATAFORMAT;
+ }
+ }
+ else {
+ if ((x == cffileCONTINUED_TO_NEXT) ||
+ (x == cffileCONTINUED_PREV_AND_NEXT))
+ {
+ struct mscabd_folder *ifol = cab->base.folders;
+ while (ifol->next) ifol = ifol->next;
+ file->folder = ifol;
+
+ fol = (struct mscabd_folder_p *) ifol;
+ if (!fol->merge_next) fol->merge_next = file;
+ }
+
+ if ((x == cffileCONTINUED_FROM_PREV) ||
+ (x == cffileCONTINUED_PREV_AND_NEXT))
+ {
+ file->folder = cab->base.folders;
+
+ fol = (struct mscabd_folder_p *) file->folder;
+ if (!fol->merge_prev) fol->merge_prev = file;
+ }
+ }
+
+ x = EndGetI16(&buf[cffile_Time]);
+ file->time_h = x >> 11;
+ file->time_m = (x >> 5) & 0x3F;
+ file->time_s = (x << 1) & 0x3E;
+
+ x = EndGetI16(&buf[cffile_Date]);
+ file->date_d = x & 0x1F;
+ file->date_m = (x >> 5) & 0xF;
+ file->date_y = (x >> 9) + 1980;
+
+ file->filename = cabd_read_string(sys, fh, cab, &x);
+ if (x) {
+ sys->free(file);
+ return x;
+ }
+
+ if (!linkfile) cab->base.files = file;
+ else linkfile->next = file;
+ linkfile = file;
+ }
+
+ return MSPACK_ERR_OK;
+}
+
+static char *cabd_read_string(struct mspack_system *sys,
+ struct mspack_file *fh,
+ struct mscabd_cabinet_p *, int *error)
+{
+ off_t base = sys->tell(fh);
+ char buf[256], *str;
+ unsigned int len, i, ok;
+
+ len = sys->read(fh, &buf[0], 256);
+
+ for (i = 0, ok = 0; i < len; i++) if (!buf[i]) { ok = 1; break; }
+ if (!ok) {
+ *error = MSPACK_ERR_DATAFORMAT;
+ return NULL;
+ }
+
+ len = i + 1;
+
+ if (sys->seek(fh, base + (off_t)len, MSPACK_SYS_SEEK_START)) {
+ *error = MSPACK_ERR_SEEK;
+ return NULL;
+ }
+
+ if (!(str = (char *)sys->alloc(sys, len))) {
+ *error = MSPACK_ERR_NOMEMORY;
+ return NULL;
+ }
+
+ sys->copy(&buf[0], str, len);
+ *error = MSPACK_ERR_OK;
+ return str;
+}
+
+static int cabd_extract(struct mscab_decompressor *base,
+ struct mscabd_file *file, char *filename)
+{
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) base;
+ struct mscabd_folder_p *fol;
+ struct mspack_system *sys;
+ struct mspack_file *fh;
+
+ if (!handle) return MSPACK_ERR_ARGS;
+ if (!file) return handle->error = MSPACK_ERR_ARGS;
+
+ sys = handle->system;
+ fol = (struct mscabd_folder_p *) file->folder;
+
+ /* check if file can be extracted */
+ if ((!fol) || (fol->merge_prev) ||
+ (((file->offset + file->length) / CAB_BLOCKMAX) > fol->base.num_blocks))
+ {
+ sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
+ "cabinet set is incomplete.", file->filename);
+ return handle->error = MSPACK_ERR_DATAFORMAT;
+ }
+
+ if (!handle->d) {
+ handle->d = (mscabd_decompress_state *)sys->alloc(sys, sizeof(struct mscabd_decompress_state));
+ if (!handle->d) return handle->error = MSPACK_ERR_NOMEMORY;
+ handle->d->folder = NULL;
+ handle->d->data = NULL;
+ handle->d->sys = *sys;
+ handle->d->sys.read = &cabd_sys_read;
+ handle->d->sys.write = &cabd_sys_write;
+ handle->d->state = NULL;
+ handle->d->infh = NULL;
+ handle->d->incab = NULL;
+ }
+
+ if ((handle->d->folder != fol) || (handle->d->offset > file->offset)) {
+ if (!handle->d->infh || (fol->data.cab != handle->d->incab)) {
+ if (handle->d->infh) sys->close(handle->d->infh);
+ handle->d->incab = fol->data.cab;
+ handle->d->infh = sys->open(sys, fol->data.cab->base.filename,
+ MSPACK_SYS_OPEN_READ);
+ if (!handle->d->infh) return handle->error = MSPACK_ERR_OPEN;
+ }
+ if (sys->seek(handle->d->infh, fol->data.offset, MSPACK_SYS_SEEK_START)) {
+ return handle->error = MSPACK_ERR_SEEK;
+ }
+
+ if (cabd_init_decomp(handle, (unsigned int) fol->base.comp_type)) {
+ return handle->error;
+ }
+
+ handle->d->folder = fol;
+ handle->d->data = &fol->data;
+ handle->d->offset = 0;
+ handle->d->block = 0;
+ handle->d->i_ptr = handle->d->i_end = &handle->d->input[0];
+ }
+
+ if (!(fh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
+ return handle->error = MSPACK_ERR_OPEN;
+ }
+
+ handle->error = MSPACK_ERR_OK;
+
+ if (file->length) {
+ off_t bytes;
+ int error;
+ handle->d->outfh = NULL;
+ if ((bytes = file->offset - handle->d->offset)) {
+ error = handle->d->decompress(handle->d->state, bytes);
+ if (error != MSPACK_ERR_READ) handle->error = error;
+ }
+
+ if (!handle->error) {
+ handle->d->outfh = fh;
+ error = handle->d->decompress(handle->d->state, (off_t) file->length);
+ if (error != MSPACK_ERR_READ) handle->error = error;
+ }
+ }
+
+ sys->close(fh);
+ handle->d->outfh = NULL;
+
+ return handle->error;
+}
+
+static int cabd_init_decomp(struct mscab_decompressor_p *handle, unsigned int ct)
+{
+ struct mspack_file *fh = (struct mspack_file *) handle;
+
+ if (!handle || !handle->d) {
+ return handle->error = MSPACK_ERR_ARGS;
+ }
+
+ cabd_free_decomp(handle);
+
+ handle->d->comp_type = ct;
+
+ switch (ct & cffoldCOMPTYPE_MASK) {
+ case cffoldCOMPTYPE_MSZIP:
+ handle->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress;
+ handle->d->state = mszipd_init(&handle->d->sys, fh, fh,
+ handle->param[MSCABD_PARAM_DECOMPBUF],
+ handle->param[MSCABD_PARAM_FIXMSZIP]);
+ break;
+ default:
+ return handle->error = MSPACK_ERR_DATAFORMAT;
+ }
+ return handle->error = (handle->d->state) ? MSPACK_ERR_OK : MSPACK_ERR_NOMEMORY;
+}
+
+static void cabd_free_decomp(struct mscab_decompressor_p *handle) {
+ if (!handle || !handle->d || !handle->d->folder || !handle->d->state) return;
+
+ switch (handle->d->comp_type & cffoldCOMPTYPE_MASK) {
+ case cffoldCOMPTYPE_MSZIP: mszipd_free((mszipd_stream *)handle->d->state); break;
+ }
+ handle->d->decompress = NULL;
+ handle->d->state = NULL;
+}
+
+static int cabd_sys_read(struct mspack_file *file, void *buffer, int bytes) {
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) file;
+ unsigned char *buf = (unsigned char *) buffer;
+ struct mspack_system *sys = handle->system;
+ int avail, todo, outlen = 0, ignore_cksum;
+
+ ignore_cksum = handle->param[MSCABD_PARAM_FIXMSZIP] &&
+ ((handle->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP);
+
+ todo = bytes;
+ while (todo > 0) {
+ avail = handle->d->i_end - handle->d->i_ptr;
+
+ if (avail) {
+ if (avail > todo) avail = todo;
+ sys->copy(handle->d->i_ptr, buf, (size_t) avail);
+ handle->d->i_ptr += avail;
+ buf += avail;
+ todo -= avail;
+ }
+ else {
+ if (handle->d->block++ >= handle->d->folder->base.num_blocks) {
+ handle->error = MSPACK_ERR_DATAFORMAT;
+ break;
+ }
+
+ handle->error = cabd_sys_read_block(sys, handle->d, &outlen, ignore_cksum);
+ if (handle->error) return -1;
+
+ if (handle->d->block >= handle->d->folder->base.num_blocks) {
+ } else {
+ if (outlen != CAB_BLOCKMAX) {
+ handle->system->message(handle->d->infh,
+ "WARNING; non-maximal data block");
+ }
+ }
+ }
+ }
+ return bytes - todo;
+}
+
+static int cabd_sys_write(struct mspack_file *file, void *buffer, int bytes) {
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) file;
+ handle->d->offset += bytes;
+ if (handle->d->outfh) {
+ return handle->system->write(handle->d->outfh, buffer, bytes);
+ }
+ return bytes;
+}
+
+static int cabd_sys_read_block(struct mspack_system *sys,
+ struct mscabd_decompress_state *d,
+ int *out, int ignore_cksum)
+{
+ unsigned char hdr[cfdata_SIZEOF];
+ unsigned int cksum;
+ int len;
+
+ d->i_ptr = d->i_end = &d->input[0];
+
+ do {
+ if (sys->read(d->infh, &hdr[0], cfdata_SIZEOF) != cfdata_SIZEOF) {
+ return MSPACK_ERR_READ;
+ }
+
+ if (d->data->cab->block_resv &&
+ sys->seek(d->infh, (off_t) d->data->cab->block_resv,
+ MSPACK_SYS_SEEK_CUR))
+ {
+ return MSPACK_ERR_SEEK;
+ }
+
+ len = EndGetI16(&hdr[cfdata_CompressedSize]);
+ if (((d->i_end - d->i_ptr) + len) > CAB_INPUTMAX) {
+ return MSPACK_ERR_DATAFORMAT;
+ }
+
+ if (EndGetI16(&hdr[cfdata_UncompressedSize]) > CAB_BLOCKMAX) {
+ return MSPACK_ERR_DATAFORMAT;
+ }
+
+ if (sys->read(d->infh, d->i_end, len) != len) {
+ return MSPACK_ERR_READ;
+ }
+
+ if ((cksum = EndGetI32(&hdr[cfdata_CheckSum]))) {
+ unsigned int sum2 = cabd_checksum(d->i_end, (unsigned int) len, 0);
+ if (cabd_checksum(&hdr[4], 4, sum2) != cksum) {
+ if (!ignore_cksum) return MSPACK_ERR_CHECKSUM;
+ sys->message(d->infh, "WARNING; bad block checksum found");
+ }
+ }
+
+ d->i_end += len;
+
+ if ((*out = EndGetI16(&hdr[cfdata_UncompressedSize]))) {
+ return MSPACK_ERR_OK;
+ }
+
+ sys->close(d->infh);
+ d->infh = NULL;
+
+ if (!(d->data = d->data->next)) {
+ return MSPACK_ERR_DATAFORMAT;
+ }
+
+ d->incab = d->data->cab;
+ if (!(d->infh = sys->open(sys, d->incab->base.filename,
+ MSPACK_SYS_OPEN_READ)))
+ {
+ return MSPACK_ERR_OPEN;
+ }
+
+ if (sys->seek(d->infh, d->data->offset, MSPACK_SYS_SEEK_START)) {
+ return MSPACK_ERR_SEEK;
+ }
+ } while (1);
+
+ return MSPACK_ERR_OK;
+}
+
+static unsigned int cabd_checksum(unsigned char *data, unsigned int bytes,
+ unsigned int cksum)
+{
+ unsigned int len, ul = 0;
+
+ for (len = bytes >> 2; len--; data += 4) {
+ cksum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
+ }
+
+ switch (bytes & 3) {
+ case 3: ul |= *data++ << 16;
+ case 2: ul |= *data++ << 8;
+ case 1: ul |= *data;
+ }
+ cksum ^= ul;
+
+ return cksum;
+}
+
+static int cabd_error(struct mscab_decompressor *base) {
+ struct mscab_decompressor_p *handle = (struct mscab_decompressor_p *) base;
+ return (handle) ? handle->error : MSPACK_ERR_ARGS;
+}
Property changes on: residual/trunk/tools/patch_ex/cabd.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/tools/patch_ex/mspack.h
===================================================================
--- residual/trunk/tools/patch_ex/mspack.h (rev 0)
+++ residual/trunk/tools/patch_ex/mspack.h 2008-12-07 22:46:45 UTC (rev 35284)
@@ -0,0 +1,176 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * file distributed with this source distribution.
+
+ * 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
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* libmspack -- a library for working with Microsoft compression formats.
+ * (C) 2003-2004 Stuart Caie <kyzer at 4u.net>
+ *
+ * This source code is adopted and striped for Residual project.
+ *
+ * libmspack is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * This program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LIB_MSPACK_H
+#define LIB_MSPACK_H
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+struct mspack_system {
+ struct mspack_file * (*open)(struct mspack_system *self,
+ char *filename,
+ int mode);
+ void (*close)(struct mspack_file *file);
+ int (*read)(struct mspack_file *file,
+ void *buffer,
+ int bytes);
+ int (*write)(struct mspack_file *file,
+ void *buffer,
+ int bytes);
+ int (*seek)(struct mspack_file *file,
+ off_t offset,
+ int mode);
+ off_t (*tell)(struct mspack_file *file);
+ void (*message)(struct mspack_file *file,
+ char *format,
+ ...);
+ void * (*alloc)(struct mspack_system *self,
+ size_t bytes);
+ void (*free)(void *ptr);
+ void (*copy)(void *src,
+ void *dest,
+ size_t bytes);
+ void *null_ptr;
+};
+
+#define MSPACK_SYS_OPEN_READ (0)
+#define MSPACK_SYS_OPEN_WRITE (1)
+#define MSPACK_SYS_OPEN_UPDATE (2)
+#define MSPACK_SYS_OPEN_APPEND (3)
+
+#define MSPACK_SYS_SEEK_START (0)
+#define MSPACK_SYS_SEEK_CUR (1)
+#define MSPACK_SYS_SEEK_END (2)
+
+struct mspack_file {
+ int dummy;
+};
+
+#define MSPACK_ERR_OK (0)
+#define MSPACK_ERR_ARGS (1)
+#define MSPACK_ERR_OPEN (2)
+#define MSPACK_ERR_READ (3)
+#define MSPACK_ERR_WRITE (4)
+#define MSPACK_ERR_SEEK (5)
+#define MSPACK_ERR_NOMEMORY (6)
+#define MSPACK_ERR_SIGNATURE (7)
+#define MSPACK_ERR_DATAFORMAT (8)
+#define MSPACK_ERR_CHECKSUM (9)
+#define MSPACK_ERR_CRUNCH (10)
+#define MSPACK_ERR_DECRUNCH (11)
+
+extern struct mscab_decompressor *
+ mspack_create_cab_decompressor(struct mspack_system *sys);
+
+extern void mspack_destroy_cab_decompressor(struct mscab_decompressor *self);
+
+struct mscabd_cabinet {
+ struct mscabd_cabinet *next;
+ char *filename;
+ off_t base_offset;
+ unsigned int length;
+ struct mscabd_cabinet *prevcab;
+ struct mscabd_cabinet *nextcab;
+ char *prevname;
+ char *nextname;
+ char *previnfo;
+ char *nextinfo;
+ struct mscabd_file *files;
+ struct mscabd_folder *folders;
+ unsigned short set_id;
+ unsigned short set_index;
+ unsigned short header_resv;
+ int flags;
+};
+
+#define MSCAB_HDR_RESV_OFFSET (0x28)
+#define MSCAB_HDR_PREVCAB (0x01)
+#define MSCAB_HDR_NEXTCAB (0x02)
+#define MSCAB_HDR_RESV (0x04)
+
+struct mscabd_folder {
+ struct mscabd_folder *next;
+ int comp_type;
+ unsigned int num_blocks;
+};
+
+#define MSCABD_COMP_METHOD(comp_type) ((comp_type) & 0x0F)
+#define MSCABD_COMP_LEVEL(comp_type) (((comp_type) >> 8) & 0x1F)
+#define MSCAB_COMP_MSZIP (1)
+
+struct mscabd_file {
+ struct mscabd_file *next;
+ char *filename;
+ unsigned int length;
+ int attribs;
+ char time_h;
+ char time_m;
+ char time_s;
+ char date_d;
+ char date_m;
+ int date_y;
+ struct mscabd_folder *folder;
+ unsigned int offset;
+};
+
+#define MSCAB_ATTRIB_RDONLY (0x01)
+#define MSCAB_ATTRIB_HIDDEN (0x02)
+#define MSCAB_ATTRIB_SYSTEM (0x04)
+#define MSCAB_ATTRIB_ARCH (0x20)
+#define MSCAB_ATTRIB_EXEC (0x40)
+#define MSCAB_ATTRIB_UTF_NAME (0x80)
+
+#define MSCABD_PARAM_SEARCHBUF (0)
+#define MSCABD_PARAM_FIXMSZIP (1)
+#define MSCABD_PARAM_DECOMPBUF (2)
+
+struct mscab_decompressor {
+ struct mscabd_cabinet * (*open) (struct mscab_decompressor *self,
+ char *filename);
+ void (*close)(struct mscab_decompressor *self,
+ struct mscabd_cabinet *cab);
+ int (*extract)(struct mscab_decompressor *self,
+ struct mscabd_file *file,
+ char *filename);
+ int (*last_error)(struct mscab_decompressor *self);
+};
+
+#endif
Property changes on: residual/trunk/tools/patch_ex/mspack.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/tools/patch_ex/mszip.h
===================================================================
--- residual/trunk/tools/patch_ex/mszip.h (rev 0)
+++ residual/trunk/tools/patch_ex/mszip.h 2008-12-07 22:46:45 UTC (rev 35284)
@@ -0,0 +1,93 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * file distributed with this source distribution.
+
+ * 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
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* This file is part of libmspack.
+ * (C) 2003-2004 Stuart Caie.
+ *
+ * This source code is adopted and striped for Residual project.
+ *
+ * The deflate method was created by Phil Katz. MSZIP is equivalent to the
+ * deflate method.
+ *
+ * libmspack is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * For further details, see the file COPYING.LIB distributed with libmspack
+ */
+
+#ifndef MSPACK_MSZIP_H
+#define MSPACK_MSZIP_H 1
+
+#include "tools/patch_ex/mspack.h"
+
+#define MSZIP_FRAME_SIZE (32768)
+#define MSZIP_MAX_HUFFBITS (16)
+#define MSZIP_LITERAL_MAXSYMBOLS (288)
+#define MSZIP_LITERAL_TABLEBITS (9)
+#define MSZIP_DISTANCE_MAXSYMBOLS (32)
+#define MSZIP_DISTANCE_TABLEBITS (6)
+
+#if (1 << MSZIP_LITERAL_TABLEBITS) < (MSZIP_LITERAL_MAXSYMBOLS * 2)
+# define MSZIP_LITERAL_TABLESIZE (MSZIP_LITERAL_MAXSYMBOLS * 4)
+#else
+# define MSZIP_LITERAL_TABLESIZE ((1 << MSZIP_LITERAL_TABLEBITS) + \
+ (MSZIP_LITERAL_MAXSYMBOLS * 2))
+#endif
+
+#if (1 << MSZIP_DISTANCE_TABLEBITS) < (MSZIP_DISTANCE_MAXSYMBOLS * 2)
+# define MSZIP_DISTANCE_TABLESIZE (MSZIP_DISTANCE_MAXSYMBOLS * 4)
+#else
+# define MSZIP_DISTANCE_TABLESIZE ((1 << MSZIP_DISTANCE_TABLEBITS) + \
+ (MSZIP_DISTANCE_MAXSYMBOLS * 2))
+#endif
+
+struct mszipd_stream {
+ struct mspack_system *sys;
+ struct mspack_file *input;
+ struct mspack_file *output;
+ unsigned int window_posn;
+
+ int (*flush_window)(struct mszipd_stream *, unsigned int);
+
+ int error, repair_mode, bytes_output;
+
+ unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end;
+ unsigned int bit_buffer, bits_left, inbuf_size;
+
+ unsigned char LITERAL_len[MSZIP_LITERAL_MAXSYMBOLS];
+ unsigned char DISTANCE_len[MSZIP_DISTANCE_MAXSYMBOLS];
+
+ unsigned short LITERAL_table [MSZIP_LITERAL_TABLESIZE];
+ unsigned short DISTANCE_table[MSZIP_DISTANCE_TABLESIZE];
+
+ unsigned char window[MSZIP_FRAME_SIZE];
+};
+
+extern struct mszipd_stream *mszipd_init(struct mspack_system *system,
+ struct mspack_file *input,
+ struct mspack_file *output,
+ int input_buffer_size,
+ int repair_mode);
+
+extern int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes);
+
+void mszipd_free(struct mszipd_stream *zip);
+
+#endif
Property changes on: residual/trunk/tools/patch_ex/mszip.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/tools/patch_ex/mszipd.cpp
===================================================================
--- residual/trunk/tools/patch_ex/mszipd.cpp (rev 0)
+++ residual/trunk/tools/patch_ex/mszipd.cpp 2008-12-07 22:46:45 UTC (rev 35284)
@@ -0,0 +1,562 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * file distributed with this source distribution.
+
+ * 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
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* This file is part of libmspack.
+ * (C) 2003-2004 Stuart Caie.
+ *
+ * This source code is adopted and striped for Residual project.
+ *
+ * The deflate method was created by Phil Katz. MSZIP is equivalent to the
+ * deflate method.
+ *
+ * libmspack is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * For further details, see the file COPYING.LIB distributed with libmspack
+ */
+
+#include "tools/patch_ex/mszip.h"
+
+static const unsigned short lit_lengths[29] = {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
+ 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
+};
+
+static const unsigned short dist_offsets[30] = {
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
+ 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
+};
+
+static const unsigned char lit_extrabits[29] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
+ 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
+};
+
+static const unsigned char dist_extrabits[30] = {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
+};
+
+static const unsigned char bitlen_order[19] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+static const unsigned short bit_mask[17] = {
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#define STORE_BITS do { \
+ zip->i_ptr = i_ptr; \
+ zip->i_end = i_end; \
+ zip->bit_buffer = bit_buffer; \
+ zip->bits_left = bits_left; \
+} while (0)
+
+#define RESTORE_BITS do { \
+ i_ptr = zip->i_ptr; \
+ i_end = zip->i_end; \
+ bit_buffer = zip->bit_buffer; \
+ bits_left = zip->bits_left; \
+} while (0)
+
+#define ENSURE_BITS(nbits) do { \
+ while (bits_left < (nbits)) { \
+ if (i_ptr >= i_end) { \
+ if (zipd_read_input(zip)) return zip->error; \
+ i_ptr = zip->i_ptr; \
+ i_end = zip->i_end; \
+ } \
+ bit_buffer |= *i_ptr++ << bits_left; bits_left += 8; \
+ } \
+} while (0)
+
+#define PEEK_BITS(nbits) (bit_buffer & ((1<<(nbits))-1))
+#define PEEK_BITS_T(nbits) (bit_buffer & bit_mask[(nbits)])
+
+#define REMOVE_BITS(nbits) ((bit_buffer >>= (nbits)), (bits_left -= (nbits)))
+
+#define READ_BITS(val, nbits) do { \
+ ENSURE_BITS(nbits); (val) = PEEK_BITS(nbits); REMOVE_BITS(nbits); \
+} while (0)
+
+#define READ_BITS_T(val, nbits) do { \
+ ENSURE_BITS(nbits); (val) = PEEK_BITS_T(nbits); REMOVE_BITS(nbits); \
+} while (0)
+
+static int zipd_read_input(struct mszipd_stream *zip) {
+ int read = zip->sys->read(zip->input, &zip->inbuf[0], (int)zip->inbuf_size);
+ if (read < 0) return zip->error = MSPACK_ERR_READ;
+ zip->i_ptr = &zip->inbuf[0];
+ zip->i_end = &zip->inbuf[read];
+
+ return MSPACK_ERR_OK;
+}
+
+#define INF_ERR_BLOCKTYPE (-1)
+#define INF_ERR_COMPLEMENT (-2)
+#define INF_ERR_FLUSH (-3)
+#define INF_ERR_BITBUF (-4)
+#define INF_ERR_SYMLENS (-5)
+#define INF_ERR_BITLENTBL (-6)
+#define INF_ERR_LITERALTBL (-7)
+#define INF_ERR_DISTANCETBL (-8)
+#define INF_ERR_BITOVERRUN (-9)
+#define INF_ERR_BADBITLEN (-10)
+#define INF_ERR_LITCODE (-11)
+#define INF_ERR_DISTCODE (-12)
+#define INF_ERR_DISTANCE (-13)
+#define INF_ERR_HUFFSYM (-14)
+
+static int make_decode_table(unsigned int nsyms, unsigned int nbits,
+ unsigned char *length, unsigned short *table)
+{
+ register unsigned int leaf, reverse, fill;
+ register unsigned short sym, next_sym;
+ register unsigned char bit_num;
+ unsigned int pos = 0;
+ unsigned int table_mask = 1 << nbits;
+ unsigned int bit_mask = table_mask >> 1;
+
+ for (bit_num = 1; bit_num <= nbits; bit_num++) {
+ for (sym = 0; sym < nsyms; sym++) {
+ if (length[sym] != bit_num) continue;
+
+ fill = length[sym]; reverse = pos >> (nbits - fill); leaf = 0;
+ do {leaf <<= 1; leaf |= reverse & 1; reverse >>= 1;} while (--fill);
+
+ if((pos += bit_mask) > table_mask) return 1;
+
+ fill = bit_mask; next_sym = 1 << bit_num;
+ do { table[leaf] = sym; leaf += next_sym; } while (--fill);
+ }
+ bit_mask >>= 1;
+ }
+
+ if (pos == table_mask) return 0;
+
+ for (sym = pos; sym < table_mask; sym++) {
+ reverse = sym; leaf = 0; fill = nbits;
+ do { leaf <<= 1; leaf |= reverse & 1; reverse >>= 1; } while (--fill);
+ table[leaf] = 0xFFFF;
+ }
+
+ next_sym = ((table_mask >> 1) < nsyms) ? nsyms : (table_mask >> 1);
+
+ pos <<= 16;
+ table_mask <<= 16;
+ bit_mask = 1 << 15;
+
+ for (bit_num = nbits+1; bit_num <= MSZIP_MAX_HUFFBITS; bit_num++) {
+ for (sym = 0; sym < nsyms; sym++) {
+ if (length[sym] != bit_num) continue;
+
+ reverse = pos >> 16; leaf = 0; fill = nbits;
+ do {leaf <<= 1; leaf |= reverse & 1; reverse >>= 1;} while (--fill);
+
+ for (fill = 0; fill < (bit_num - nbits); fill++) {
+ if (table[leaf] == 0xFFFF) {
+ table[(next_sym << 1) ] = 0xFFFF;
+ table[(next_sym << 1) + 1 ] = 0xFFFF;
+ table[leaf] = next_sym++;
+ }
+ leaf = (table[leaf] << 1) | ((pos >> (15 - fill)) & 1);
+ }
+ table[leaf] = sym;
+
+ if ((pos += bit_mask) > table_mask) return 1;
+ }
+ bit_mask >>= 1;
+ }
+
+ return (pos != table_mask) ? 1 : 0;
+}
+
+#define READ_HUFFSYM(tbl, var) do { \
+ ENSURE_BITS(MSZIP_MAX_HUFFBITS); \
+ sym = zip->tbl##_table[PEEK_BITS(MSZIP_##tbl##_TABLEBITS)]; \
+ if (sym >= MSZIP_##tbl##_MAXSYMBOLS) { \
+ i = MSZIP_##tbl##_TABLEBITS - 1; \
+ do { \
+ if (i++ > MSZIP_MAX_HUFFBITS) { \
+ return INF_ERR_HUFFSYM; \
+ } \
+ sym = zip->tbl##_table[(sym << 1) | ((bit_buffer >> i) & 1)]; \
+ } while (sym >= MSZIP_##tbl##_MAXSYMBOLS); \
+ } \
+ (var) = sym; \
+ i = zip->tbl##_len[sym]; \
+ REMOVE_BITS(i); \
+} while (0)
+
+static int zip_read_lens(struct mszipd_stream *zip) {
+ register unsigned int bit_buffer;
+ register int bits_left;
+ unsigned char *i_ptr, *i_end;
+
+ unsigned short bl_table[(1 << 7)];
+ unsigned char bl_len[19];
+
+ unsigned char lens[MSZIP_LITERAL_MAXSYMBOLS + MSZIP_DISTANCE_MAXSYMBOLS];
+ unsigned int lit_codes, dist_codes, code, last_code=0, bitlen_codes, i, run;
+
+ RESTORE_BITS;
+
+ READ_BITS(lit_codes, 5); lit_codes += 257;
+ READ_BITS(dist_codes, 5); dist_codes += 1;
+ READ_BITS(bitlen_codes, 4); bitlen_codes += 4;
+ if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS) return INF_ERR_SYMLENS;
+ if (dist_codes > MSZIP_DISTANCE_MAXSYMBOLS) return INF_ERR_SYMLENS;
+
+ for (i = 0; i < bitlen_codes; i++) READ_BITS(bl_len[bitlen_order[i]], 3);
+ while (i < 19) bl_len[bitlen_order[i++]] = 0;
+
+ if (make_decode_table(19, 7, &bl_len[0], &bl_table[0])) {
+ return INF_ERR_BITLENTBL;
+ }
+
+ for (i = 0; i < (lit_codes + dist_codes); i++) {
+ ENSURE_BITS(7);
+ code = bl_table[PEEK_BITS(7)];
+ REMOVE_BITS(bl_len[code]);
+
+ if (code < 16) lens[i] = last_code = code;
+ else {
+ switch (code) {
+ case 16: READ_BITS(run, 2); run += 3; code = last_code; break;
+ case 17: READ_BITS(run, 3); run += 3; code = 0; break;
+ case 18: READ_BITS(run, 7); run += 11; code = 0; break;
+ default: return INF_ERR_BADBITLEN;
+ }
+ if ((i + run) > (lit_codes + dist_codes)) return INF_ERR_BITOVERRUN;
+ while (run--) lens[i++] = code;
+ i--;
+ }
+ }
+
+ i = lit_codes;
+ zip->sys->copy(&lens[0], &zip->LITERAL_len[0], i);
+ while (i < MSZIP_LITERAL_MAXSYMBOLS) zip->LITERAL_len[i++] = 0;
+
+ i = dist_codes;
+ zip->sys->copy(&lens[lit_codes], &zip->DISTANCE_len[0], i);
+ while (i < MSZIP_DISTANCE_MAXSYMBOLS) zip->DISTANCE_len[i++] = 0;
+
+ STORE_BITS;
+ return 0;
+}
+
+static int inflate(struct mszipd_stream *zip) {
+ unsigned int last_block, block_type, distance, length, this_run, i;
+
+ register unsigned int bit_buffer;
+ register int bits_left;
+ register unsigned short sym;
+ unsigned char *i_ptr, *i_end;
+
+ RESTORE_BITS;
+
+ do {
+ READ_BITS(last_block, 1);
+
+ READ_BITS(block_type, 2);
+
+ if (block_type == 0) {
+ unsigned char lens_buf[4];
+
+ i = bits_left & 7; REMOVE_BITS(i);
+
+ for (i = 0; (bits_left >= 8); i++) {
+ if (i == 4) return INF_ERR_BITBUF;
+ lens_buf[i] = PEEK_BITS(8);
+ REMOVE_BITS(8);
+ }
+ if (bits_left != 0) return INF_ERR_BITBUF;
+ while (i < 4) {
+ if (i_ptr >= i_end) {
+ if (zipd_read_input(zip)) return zip->error;
+ i_ptr = zip->i_ptr;
+ i_end = zip->i_end;
+ }
+ lens_buf[i++] = *i_ptr++;
+ }
+
+ length = lens_buf[0] | (lens_buf[1] << 8);
+ i = lens_buf[2] | (lens_buf[3] << 8);
+ if (length != (~i & 0xFFFF)) return INF_ERR_COMPLEMENT;
+
+ while (length > 0) {
+ if (i_ptr >= i_end) {
+ if (zipd_read_input(zip)) return zip->error;
+ i_ptr = zip->i_ptr;
+ i_end = zip->i_end;
+ }
+
+ this_run = length;
+ if (this_run > (unsigned int)(i_end - i_ptr)) this_run = i_end - i_ptr;
+ if (this_run > (MSZIP_FRAME_SIZE - zip->window_posn))
+ this_run = MSZIP_FRAME_SIZE - zip->window_posn;
+
+ zip->sys->copy(i_ptr, &zip->window[zip->window_posn], this_run);
+ zip->window_posn += this_run;
+ i_ptr += this_run;
+ length -= this_run;
+
+ if (zip->window_posn == MSZIP_FRAME_SIZE) {
+ if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) return INF_ERR_FLUSH;
+ zip->window_posn = 0;
+ }
+ }
+ }
+ else if ((block_type == 1) || (block_type == 2)) {
+ unsigned int window_posn, match_posn, code;
+
+ if (block_type == 1) {
+ i = 0;
+ while (i < 144) zip->LITERAL_len[i++] = 8;
+ while (i < 256) zip->LITERAL_len[i++] = 9;
+ while (i < 280) zip->LITERAL_len[i++] = 7;
+ while (i < 288) zip->LITERAL_len[i++] = 8;
+ for (i = 0; i < 32; i++) zip->DISTANCE_len[i] = 5;
+ }
+ else {
+ STORE_BITS;
+ if ((i = zip_read_lens(zip))) return i;
+ RESTORE_BITS;
+ }
+
+ if (make_decode_table(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS,
+ &zip->LITERAL_len[0], &zip->LITERAL_table[0]))
+ {
+ return INF_ERR_LITERALTBL;
+ }
+
+ if (make_decode_table(MSZIP_DISTANCE_MAXSYMBOLS,MSZIP_DISTANCE_TABLEBITS,
+ &zip->DISTANCE_len[0], &zip->DISTANCE_table[0]))
+ {
+ return INF_ERR_DISTANCETBL;
+ }
+
+ window_posn = zip->window_posn;
+ while (1) {
+ READ_HUFFSYM(LITERAL, code);
+ if (code < 256) {
+ zip->window[window_posn++] = (unsigned char) code;
+ if (window_posn == MSZIP_FRAME_SIZE) {
+ if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) return INF_ERR_FLUSH;
+ window_posn = 0;
+ }
+ }
+ else if (code == 256) {
+ break;
+ }
+ else {
+ code -= 257;
+ if (code > 29) return INF_ERR_LITCODE;
+ READ_BITS_T(length, lit_extrabits[code]);
+ length += lit_lengths[code];
+
+ READ_HUFFSYM(DISTANCE, code);
+ if (code > 30) return INF_ERR_DISTCODE;
+ READ_BITS_T(distance, dist_extrabits[code]);
+ distance += dist_offsets[code];
+
+ match_posn = ((distance > window_posn) ? MSZIP_FRAME_SIZE : 0)
+ + window_posn - distance;
+
+ if (length < 12) {
+ while (length--) {
+ zip->window[window_posn++] = zip->window[match_posn++];
+ match_posn &= MSZIP_FRAME_SIZE - 1;
+
+ if (window_posn == MSZIP_FRAME_SIZE) {
+ if (zip->flush_window(zip, MSZIP_FRAME_SIZE))
+ return INF_ERR_FLUSH;
+ window_posn = 0;
+ }
+ }
+ }
+ else {
+ unsigned char *runsrc, *rundest;
+ do {
+ this_run = length;
+ if ((match_posn + this_run) > MSZIP_FRAME_SIZE)
+ this_run = MSZIP_FRAME_SIZE - match_posn;
+ if ((window_posn + this_run) > MSZIP_FRAME_SIZE)
+ this_run = MSZIP_FRAME_SIZE - window_posn;
+
+ rundest = &zip->window[window_posn]; window_posn += this_run;
+ runsrc = &zip->window[match_posn]; match_posn += this_run;
+ length -= this_run;
+ while (this_run--) *rundest++ = *runsrc++;
+
+ if (window_posn == MSZIP_FRAME_SIZE) {
+ if (zip->flush_window(zip, MSZIP_FRAME_SIZE))
+ return INF_ERR_FLUSH;
+ window_posn = 0;
+ }
+ if (match_posn == MSZIP_FRAME_SIZE) match_posn = 0;
+ } while (length > 0);
+ }
+
+ }
+
+ }
+ zip->window_posn = window_posn;
+ }
+ else {
+ return INF_ERR_BLOCKTYPE;
+ }
+ } while (!last_block);
+
+ if (zip->window_posn) {
+ if (zip->flush_window(zip, zip->window_posn)) return INF_ERR_FLUSH;
+ }
+ STORE_BITS;
+
+ return 0;
+}
+
+static int mszipd_flush_window(struct mszipd_stream *zip,
+ unsigned int data_flushed)
+{
+ zip->bytes_output += data_flushed;
+ if (zip->bytes_output > MSZIP_FRAME_SIZE) {
+ return 1;
+ }
+ return 0;
+}
+
+struct mszipd_stream *mszipd_init(struct mspack_system *system,
+ struct mspack_file *input,
+ struct mspack_file *output,
+ int input_buffer_size,
+ int repair_mode)
+{
+ struct mszipd_stream *zip;
+
+ if (!system) return NULL;
+
+ input_buffer_size = (input_buffer_size + 1) & -2;
+ if (!input_buffer_size) return NULL;
+
+ if (!(zip = (mszipd_stream *)system->alloc(system, sizeof(struct mszipd_stream)))) {
+ return NULL;
+ }
+
+ zip->inbuf = (unsigned char *)system->alloc(system, (size_t) input_buffer_size);
+ if (!zip->inbuf) {
+ system->free(zip);
+ return NULL;
+ }
+
+ zip->sys = system;
+ zip->input = input;
+ zip->output = output;
+ zip->inbuf_size = input_buffer_size;
+ zip->error = MSPACK_ERR_OK;
+ zip->repair_mode = repair_mode;
+ zip->flush_window = &mszipd_flush_window;
+
+ zip->i_ptr = zip->i_end = &zip->inbuf[0];
+ zip->o_ptr = zip->o_end = NULL;
+ zip->bit_buffer = 0; zip->bits_left = 0;
+ return zip;
+}
+
+int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes) {
+ register unsigned int bit_buffer;
+ register int bits_left;
+ unsigned char *i_ptr, *i_end;
+
+ int i, state, error;
+
+ if (!zip || (out_bytes < 0)) return MSPACK_ERR_ARGS;
+ if (zip->error) return zip->error;
+
+ i = zip->o_end - zip->o_ptr;
+ if ((off_t) i > out_bytes) i = (int) out_bytes;
+ if (i) {
+ if (zip->sys->write(zip->output, zip->o_ptr, i) != i) {
+ return zip->error = MSPACK_ERR_WRITE;
+ }
+ zip->o_ptr += i;
+ out_bytes -= i;
+ }
+ if (out_bytes == 0) return MSPACK_ERR_OK;
+
+
+ while (out_bytes > 0) {
+ RESTORE_BITS;
+
+ i = bits_left & 7; REMOVE_BITS(i);
+ state = 0;
+ do {
+ READ_BITS(i, 8);
+ if (i == 'C') state = 1;
+ else if ((state == 1) && (i == 'K')) state = 2;
+ else state = 0;
+ } while (state != 2);
+
+ zip->window_posn = 0;
+ zip->bytes_output = 0;
+ STORE_BITS;
+ if ((error = inflate(zip))) {
+ if (zip->repair_mode) {
+ zip->sys->message(NULL, "MSZIP error, %u bytes of data lost.",
+ MSZIP_FRAME_SIZE - zip->bytes_output);
+ for (i = zip->bytes_output; i < MSZIP_FRAME_SIZE; i++) {
+ zip->window[i] = '\0';
+ }
+ zip->bytes_output = MSZIP_FRAME_SIZE;
+ }
+ else {
+ return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH;
+ }
+ }
+ zip->o_ptr = &zip->window[0];
+ zip->o_end = &zip->o_ptr[zip->bytes_output];
+
+ i = (out_bytes < (off_t)zip->bytes_output) ?
+ (int)out_bytes : zip->bytes_output;
+ if (zip->sys->write(zip->output, zip->o_ptr, i) != i) {
+ return zip->error = MSPACK_ERR_WRITE;
+ }
+
+ if ((error > 0) && zip->repair_mode) return error;
+
+ zip->o_ptr += i;
+ out_bytes -= i;
+ }
+
+ if (out_bytes) {
+ return zip->error = MSPACK_ERR_DECRUNCH;
+ }
+ return MSPACK_ERR_OK;
+}
+
+void mszipd_free(struct mszipd_stream *zip) {
+ struct mspack_system *sys;
+ if (zip) {
+ sys = zip->sys;
+ sys->free(zip->inbuf);
+ sys->free(zip);
+ }
+}
Property changes on: residual/trunk/tools/patch_ex/mszipd.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/tools/patch_ex/patch_ex.cpp
===================================================================
--- residual/trunk/tools/patch_ex/patch_ex.cpp (rev 0)
+++ residual/trunk/tools/patch_ex/patch_ex.cpp 2008-12-07 22:46:45 UTC (rev 35284)
@@ -0,0 +1,385 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * file distributed with this source distribution.
+
+ * 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
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* Patch extractor
+ * (C) 2008 Andrea Corna
+ *
+ * This source code is adopted and striped for Residual project.
+ *
+ * res_system functions are taken from system.c written by Stuart Caie
+ * from libmspack (http://www.cabextract.org.uk/libmspack/).
+ *
+ * Patch Extractor is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * For further details, see the file COPYING.LIB distributed with libmspack
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+
+#include "tools/patch_ex/mspack.h"
+
+// Command line actions
+enum act { UNKNOWN_ACTION, CABINET_ACTION, ALL_LANGUAGES_ACTION, LOCALISED_ACTION};
+
+// Languages codes
+#define LANG_ALL "@@"
+const char *kLanguages_ext[] = { "English", "French", "German", "Italian", "Portuguese", "Spanish", NULL};
+const char *kLanguages_code[] = { "US", "FR", "GE", "IT", "PT", "SP", NULL };
+
+// Extraction constans
+#define RAND_A (0x343FD)
+#define RAND_B (0x269EC3)
+#define CODE_TABLE_SIZE (0x100)
+#define CONTAINER_OFFSET (0x1C000)
+#define CABINET_OFFSET (CONTAINER_OFFSET + 8)
+#define CONTAINER_MAGIC "1CNT"
+
+#define BUFFER_SIZE 102400
+char lang[3];
+
+// Some useful type and function
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+
+uint32 READ_LE_UINT32(const void *ptr) {
+ const uint8 *b = (const uint8 *)ptr;
+ return (b[3] << 24) + (b[2] << 16) + (b[1] << 8) + (b[0]);
+}
+
+struct mspack_file_p {
+ FILE *fh;
+ char *name;
+ uint16 *CodeTable;
+};
+
+uint16 *create_dec_table(uint32 key) {
+ uint32 value;
+ uint16 *dectable;
+ unsigned int i;
+
+ value = key;
+ dectable = (uint16 *)malloc( CODE_TABLE_SIZE * 2);
+
+ for (i = 0; i < CODE_TABLE_SIZE; i++) {
+ value = RAND_A * value + RAND_B;
+ dectable[i] = (uint16)((value >> 16) & 0x7FFF);
+ }
+
+ return dectable;
+}
+
+static struct mspack_file *res_open(struct mspack_system *handle, char *filename, int mode) {
+ struct mspack_file_p *fh;
+ char *fmode;
+ uint32 magic, key;
+
+ switch (mode) {
+ case MSPACK_SYS_OPEN_READ: fmode = "rb"; break;
+ case MSPACK_SYS_OPEN_WRITE: fmode = "wb"; break;
+ case MSPACK_SYS_OPEN_UPDATE: fmode = "r+b"; break;
+ case MSPACK_SYS_OPEN_APPEND: fmode = "ab"; break;
+ default: return NULL;
+ }
+
+ fh = (mspack_file_p *)malloc(sizeof(struct mspack_file_p));
+
+ fh->name = filename;
+ if (!(fh->fh = fopen(filename, fmode))) {
+ free(fh);
+ return NULL;
+ }
+
+ fh->CodeTable = NULL;
+
+ if (mode != MSPACK_SYS_OPEN_READ)
+ return (struct mspack_file *)fh;
+
+ handle->seek((struct mspack_file *)fh, (off_t)CONTAINER_OFFSET, MSPACK_SYS_SEEK_START);
+ uint8 count = handle->read((struct mspack_file *) fh, &magic, 4);
+
+ if (count == 4 && memcmp(&magic, CONTAINER_MAGIC, 4) == 0) {
+ handle->read((struct mspack_file *)fh, &key, 4);
+ key = READ_LE_UINT32(&key);
+ fh->CodeTable = create_dec_table(key);
+ }
+
+ handle->seek((struct mspack_file *)fh, (off_t) 0, MSPACK_SYS_SEEK_START);
+
+ return (struct mspack_file *)fh;
+}
+
+static void res_close(struct mspack_file *file) {
+ struct mspack_file_p *handle = (struct mspack_file_p *)file;
+
+ if (handle) {
+ if (handle->CodeTable)
+ free(handle->CodeTable);
+ fclose(handle->fh);
+ free(handle);
+ }
+}
+
+static int res_seek(struct mspack_file *file, off_t offset, int mode) {
+ struct mspack_file_p *handle = (struct mspack_file_p *)file;
+
+ if (handle) {
+ switch (mode) {
+ case MSPACK_SYS_SEEK_START:
+ mode = SEEK_SET;
+ if (handle->CodeTable)
+ offset += (CONTAINER_OFFSET + 8);
+ break;
+ case MSPACK_SYS_SEEK_CUR: mode = SEEK_CUR; break;
+ case MSPACK_SYS_SEEK_END: mode = SEEK_END; break;
+ default: return -1;
+ }
+ return fseek(handle->fh, (int)offset, mode);
+ }
+ return -1;
+}
+
+static off_t res_tell(struct mspack_file *file) {
+ struct mspack_file_p *handle = (struct mspack_file_p *)file;
+
+ if (handle) {
+ off_t offset = ftell(handle->fh);
+ if (handle->CodeTable)
+ offset -= CABINET_OFFSET;
+ return offset;
+ } else
+ return 0;
+}
+
+void decode(uint8 *data, unsigned int size, uint16 *dectable, unsigned int start_point) {
+ unsigned int i;
+ for (i = 0; i < size; i++)
+ data[i] = (data[i] ^ (uint8) dectable[(i + start_point) % CODE_TABLE_SIZE]) - (uint8)(dectable[(i + start_point) % CODE_TABLE_SIZE] >> 8);
+}
+
+static int res_read(struct mspack_file *file, void *buffer, int bytes) {
+ struct mspack_file_p *handle = (struct mspack_file_p *)file;
+
+ if (handle) {
+ unsigned int start_point = (unsigned int)res_tell(file);
+ size_t count = fread(buffer, 1, (size_t) bytes, handle->fh);
+
+ if (!ferror(handle->fh)) {
+ if (handle->CodeTable)
+ decode((uint8*)buffer, count, handle->CodeTable, start_point);
+ return (int) count;
+ }
+ }
+ return -1;
+}
+
+static int res_write(struct mspack_file *file, void *buffer, int bytes) {
+ struct mspack_file_p *handle = (struct mspack_file_p *)file;
+
+ if (handle) {
+ if (handle->CodeTable)
+ return -1;
+ size_t count = fwrite(buffer, 1, (size_t)bytes, handle->fh);
+ if (!ferror(handle->fh)) return (int) count;
+ }
+ return -1;
+}
+
+static void res_msg(struct mspack_file *file, char *format, ...) {
+ va_list ap;
+
+ if (file)
+ fprintf(stderr, "%s: ", ((struct mspack_file_p *)file)->name);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc((int) '\n', stderr);
+ fflush(stderr);
+}
+
+static void *res_alloc(struct mspack_system *, size_t bytes) {
+ void *memory;
+ memory = malloc(bytes);
+ if (memory == NULL) {
+ printf("Insufficient memory!\n");
+ exit(1);
+ } else
+ return memory;
+}
+
+static void res_free(void *buffer) {
+ free(buffer);
+}
+
+static void res_copy(void *src, void *dest, size_t bytes) {
+ memcpy(dest, src, bytes);
+}
+
+static struct mspack_system res_system = {
+ &res_open, &res_close, &res_read, &res_write, &res_seek,
+ &res_tell, &res_msg, &res_alloc, &res_free, &res_copy, NULL
+};
+
+void extract_cabinet(char *filename, unsigned int lenght) {
+ struct mspack_file *original_executable, *destination_cabinet;
+ void *buffer;
+ unsigned int copied_bytes;
+ int count;
+
+ original_executable = res_open(&res_system, filename, MSPACK_SYS_OPEN_READ);
+ destination_cabinet = res_open(&res_system, "gfupd101.cab", MSPACK_SYS_OPEN_WRITE);
+
+ buffer = res_alloc(NULL, BUFFER_SIZE);
+ copied_bytes = 0;
+
+ while (copied_bytes < lenght) {
+ count = res_read(original_executable, buffer, BUFFER_SIZE);
+ res_write(destination_cabinet, buffer, count);
+ copied_bytes += count;
+ }
+ printf("Update cabinet extracted as gfupd101.cab.\n");
+
+ res_free(buffer);
+ res_close(original_executable);
+ res_close(destination_cabinet);
+}
+
+char *filter_none(struct mscabd_file *file) {
+ char *filename;
+
+ filename = (char *)malloc(strlen(file->filename) + 1);
+ strcpy(filename, file->filename);
+ return filename;
+}
+
+char *filter_localised(struct mscabd_file *file) {
+ char *filename, file_lang[3];
+
+ filename = (char *)malloc(strlen(file->filename) + 1);
+ sscanf(file->filename, "%2s_%s",file_lang, filename);
+ if (strcmp(file_lang, lang) == 0 || strcmp(file_lang, LANG_ALL) == 0)
+ return filename;
+ else
+ return NULL;
+}
+
+void extract_files(struct mscab_decompressor *cabd, struct mscabd_cabinet *cab, char *(* filter) (struct mscabd_file *)) {
+ unsigned int files_extracted = 0;
+ struct mscabd_file *file;
+ char *filename;
+
+ for (file = cab->files; file; file = file->next) {
+ if ((filename = filter(file))) {
+ if (cabd->extract(cabd, file, filename) != MSPACK_ERR_OK) {
+ printf("Extract error on %s!\n", file->filename);
+ continue;
+ }
+ printf("%s extracted as %s\n", file->filename, filename);
+ ++files_extracted;
+ free(filename);
+ }
+ }
+
+ printf("%d file extracted.\n", files_extracted);
+}
+
+int main(int argc, char *argv[]) {
+ struct mscab_decompressor *cabd;
+ struct mscabd_cabinet *cab;
+ int i;
+ enum act action;
+ char *(*filter) (struct mscabd_file *);
+
+ action = UNKNOWN_ACTION;
+
+ // Arguments checks and usage dispaly
+ if (argc != 3) {
+ printf("Usage: patchex gfupd101.exe LanguageCode/SpecialAction\n");
+ printf("Aviable languages:\n");
+ for (i = 0; kLanguages_code[i]; i++)
+ printf("-%s (%s)\n", kLanguages_ext[i], kLanguages_code[i]);
+ printf("Special actions:\n");
+ printf("- ALL: Extracts all files with their original names.\n");
+ printf("- CABINET: Extracts only the cabinet\n");
+ exit(1);
+ }
+
+ // Actions check
+ // Cabinet check
+ if (strcasecmp("CABINET", argv[2]) == 0) {
+ printf("Cabinet extraction selected\n");
+ action = CABINET_ACTION;
+ }
+
+ // All languages check
+ if (strcasecmp("ALL", argv[2]) == 0) {
+ printf("All languages selected\n");
+ action = ALL_LANGUAGES_ACTION;
+ }
+
+ // Language check
+ for(i = 0; kLanguages_code[i]; i++)
+ if (strcasecmp(kLanguages_code[i], argv[2]) == 0 || strcasecmp(kLanguages_ext[i], argv[2]) == 0) {
+ printf("%s selected.\n", kLanguages_ext[i]);
+ sprintf(lang, kLanguages_code[i]);
+ action = LOCALISED_ACTION;
+ break;
+ }
+
+ // Unknown action
+ if (action == UNKNOWN_ACTION) {
+ printf("Unknown language or action!\n");
+ exit(1);
+ }
+
+
+ // Extraction !
+ if ((cabd = mspack_create_cab_decompressor(&res_system)) != MSPACK_ERR_OK) {
+ if ((cab = cabd->open(cabd, argv[1])) != MSPACK_ERR_OK) {
+ if (action == CABINET_ACTION)
+ extract_cabinet(argv[1], cab->length);
+ else {
+ switch (action) {
+ case ALL_LANGUAGES_ACTION: filter = &filter_none; break;
+ case LOCALISED_ACTION: filter = &filter_localised; break;
+ default: printf("Internal error!\n"); exit(1); break;
+ }
+ extract_files(cabd, cab, filter);
+ }
+ cabd->close(cabd, cab);
+ } else
+ printf("Unable to open %s!\n", argv[1]);
+ mspack_destroy_cab_decompressor(cabd);
+ } else {
+ printf("Internal error!\n");
+ exit(1);
+ }
+
+ return 0;
+}
Property changes on: residual/trunk/tools/patch_ex/patch_ex.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list