[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