[Scummvm-cvs-logs] SF.net SVN: scummvm: [32446] tools/trunk

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Sun Jun 1 01:06:53 CEST 2008


Revision: 32446
          http://scummvm.svn.sourceforge.net/scummvm/?rev=32446&view=rev
Author:   lordhoto
Date:     2008-05-31 16:06:53 -0700 (Sat, 31 May 2008)

Log Message:
-----------
Added support for HoF floppy installer files in extract_kyra.

Modified Paths:
--------------
    tools/trunk/Makefile
    tools/trunk/README
    tools/trunk/extract_kyra.cpp
    tools/trunk/kyra_pak.cpp
    tools/trunk/kyra_pak.h

Added Paths:
-----------
    tools/trunk/extract_kyra.h
    tools/trunk/kyra_ins.cpp
    tools/trunk/kyra_ins.h

Modified: tools/trunk/Makefile
===================================================================
--- tools/trunk/Makefile	2008-05-31 22:54:09 UTC (rev 32445)
+++ tools/trunk/Makefile	2008-05-31 23:06:53 UTC (rev 32446)
@@ -149,7 +149,7 @@
 extract_agos$(EXEEXT): extract_agos.o
 	$(CXX) $(LDFLAGS) -o $@ $+
 
-extract_kyra$(EXEEXT): extract_kyra.o kyra_pak.o util.o
+extract_kyra$(EXEEXT): extract_kyra.o kyra_pak.o kyra_ins.o util.o
 	$(CXX) $(LDFLAGS) -o $@ $+
 
 extract_loom_tg16$(EXEEXT): extract_loom_tg16.o util.o

Modified: tools/trunk/README
===================================================================
--- tools/trunk/README	2008-05-31 22:54:09 UTC (rev 32445)
+++ tools/trunk/README	2008-05-31 23:06:53 UTC (rev 32446)
@@ -16,6 +16,11 @@
 
         extract_kyra
                 Unpacks .PAK files from Kyrandia games.
+				It is also able to extract the installer package files from
+				Hand of Fate DOS floppy version. You should be sure you got
+				all WESTWOOD.### files for that, since they are one big package
+				file splitted into several, so with -x you will extract *all*
+				files from the installer files.
                 
                 Example of usage:
                 extract_kyra [params] <file>

Modified: tools/trunk/extract_kyra.cpp
===================================================================
--- tools/trunk/extract_kyra.cpp	2008-05-31 22:54:09 UTC (rev 32445)
+++ tools/trunk/extract_kyra.cpp	2008-05-31 23:06:53 UTC (rev 32446)
@@ -1,6 +1,6 @@
 /* extract_kyra - Extractor for Kyrandia .pak archives
  * Copyright (C) 2004  Johannes Schickel
- * Copyright (C) 2004-2006  The ScummVM Team
+ * Copyright (C) 2004-2008  The ScummVM Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,27 +22,27 @@
  */
 
 #include "kyra_pak.h"
+#include "kyra_ins.h"
 
-void showhelp(char* exename)
-{
-		printf("\nUsage: %s [params] <file>\n", exename);
+void showhelp(char *exename) {
+	printf("\nUsage: %s [params] <file>\n", exename);
 
-		printf("\nParams:\n");
-		printf("-o <filename>     Extract only <filename>\n");
-		printf("-x                Extract all files\n");
-		printf("-a                Extract files from the Amiga .PAK files\n");
+	printf("\nParams:\n");
+	printf( "-o <filename>     Extract only <filename>\n"
+			"-x                Extract all files\n"
+			"-a                Extract files from the Amiga .PAK files\n"
+			"-2                Extract files from HoF installer files\n");
 
-		exit(2);
+	exit(2);
 }
 
 int main(int argc, char **argv) {
 	char inputPath[768];
 
-	if (argc < 2) {
+	if (argc < 2)
 		showhelp(argv[0]);
-	}
 
-	bool extractAll = false, extractOne = false, isAmiga = false;
+	bool extractAll = false, extractOne = false, isAmiga = false, isHoFInstaller = false;
 	char singleFilename[256] = "";
 	int param;
 
@@ -63,29 +63,39 @@
 			extractAll = true;
 		} else if (strcmp(argv[param], "-a") == 0) {
 			isAmiga = true;
+		} else if (strcmp(argv[param], "-2") == 0) {
+			isHoFInstaller = true;
 		}
 	}
 
-	if (param > argc) {
+	if (param > argc)
 		showhelp(argv[0]);
-	}
 
-	PAKFile myfile;
-	if (!myfile.loadFile(argv[argc - 1], isAmiga)) {
-		error("Couldn't load file '%s'", argv[argc - 1]);
+	Extractor *extract = 0;
+	if (isHoFInstaller) {
+		extract = new HoFInstaller(argv[argc - 1]);
+	} else {
+		PAKFile *myfile = new PAKFile;
+		if (!myfile->loadFile(argv[argc - 1], isAmiga)) {
+			delete myfile;
+			error("Couldn't load file '%s'", argv[argc - 1]);
+		}
+
+		extract = myfile;
 	}
 
 	getPath(argc[argv - 1], inputPath);
 
-	if(extractAll) {
-		myfile.outputAllFiles(inputPath);
-	} else if(extractOne) {
+	if (extractAll) {
+		extract->outputAllFiles(inputPath);
+	} else if (extractOne) {
 		char outputFilename[1024];
-		sprintf(outputFilename, "%s/%s", inputPath, singleFilename);
-		myfile.outputFileAs(singleFilename, outputFilename);
+		snprintf(outputFilename, 1024, "%s/%s", inputPath, singleFilename);
+		extract->outputFileAs(singleFilename, outputFilename);
 	} else {
-		myfile.drawFileList();
+		extract->drawFileList();
 	}
 
 	return 0;
 }
+

Added: tools/trunk/extract_kyra.h
===================================================================
--- tools/trunk/extract_kyra.h	                        (rev 0)
+++ tools/trunk/extract_kyra.h	2008-05-31 23:06:53 UTC (rev 32446)
@@ -0,0 +1,92 @@
+/* Scumm Tools
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef EXTRACT_KYRA_H
+#define EXTRACT_KYRA_H
+
+#include "util.h"
+
+class Extractor {
+public:
+	virtual ~Extractor() {}
+
+	virtual void drawFileList();
+
+	virtual bool outputAllFiles() { return outputAllFiles("./"); } 
+	virtual bool outputAllFiles(const char *outputPath);
+
+	virtual bool outputFile(const char *file) { return outputFileAs(file, file); }
+	virtual bool outputFileAs(const char *file, const char *outputName);
+
+	struct FileList {
+		FileList() : filename(0), size(0), data(0), next(0) {}
+		~FileList() {
+			delete[] filename;
+			delete[] data;
+			delete next;
+		}
+
+		FileList *findEntry(const char *f) {
+			for (FileList *cur = this; cur; cur = cur->next) {
+				if (scumm_stricmp(cur->filename, f) != 0)
+					continue;
+				return cur;
+			}
+			return 0;
+		}
+
+		const FileList *findEntry(const char *f) const {
+			for (const FileList *cur = this; cur; cur = cur->next) {
+				if (scumm_stricmp(cur->filename, f) != 0)
+					continue;
+				return cur;
+			}
+			return 0;
+		}
+
+		void addEntry(FileList *e) {
+			if (next)
+				next->addEntry(e);
+			else
+				next = e;
+		}
+		uint32 getTableSize() const {
+			return strlen(filename)+1+4+((next != 0) ? next->getTableSize() : 0);
+		}
+		uint32 getFileSize() const {
+			return size + (next != 0 ? next->getFileSize() : 0);
+		}
+
+		char *filename;
+		uint32 size;
+		uint8 *data;
+
+		FileList *next;
+	};
+
+	typedef const FileList cFileList;
+
+	virtual cFileList *getFileList() const = 0;
+};
+
+#endif
+


Property changes on: tools/trunk/extract_kyra.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: tools/trunk/kyra_ins.cpp
===================================================================
--- tools/trunk/kyra_ins.cpp	                        (rev 0)
+++ tools/trunk/kyra_ins.cpp	2008-05-31 23:06:53 UTC (rev 32446)
@@ -0,0 +1,677 @@
+/* Scumm Tools
+ * Copyright (C) 2008 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "kyra_ins.h"
+
+class FileExpanderSource {
+public:
+	FileExpanderSource(const uint8 *data) : _dataPtr(data), _bitsLeft(8), _key(0), _index(0) {}
+	~FileExpanderSource() {}
+
+	void advSrcRefresh();
+	void advSrcBitsBy1();
+	void advSrcBitsByIndex(uint8 newIndex);
+
+	uint8 getKeyLower() { return _key & 0xff; }
+	void setIndex(uint8 index) { _index = index; }
+	uint16 getKeyMasked(uint8 newIndex);
+	uint16 keyMaskedAlign(uint16 val);
+
+	void copyBytes(uint8 *& dst);
+
+private:
+	const uint8 *_dataPtr;
+	uint16 _key;
+	int8 _bitsLeft;
+	uint8 _index;
+};
+
+void FileExpanderSource::advSrcBitsBy1() {
+	_key >>= 1;		
+	if (!--_bitsLeft) {
+		_key = ((*_dataPtr++) << 8 ) | (_key & 0xff);
+		_bitsLeft = 8;
+	}
+}
+
+void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) {
+	_index = newIndex;
+	_bitsLeft -= _index;
+	if (_bitsLeft <= 0) {
+		_key >>= (_index + _bitsLeft);
+		_index = -_bitsLeft;
+		_bitsLeft = 8 - _index;
+		_key = (*_dataPtr++ << 8) | (_key & 0xff);
+	}
+	_key >>= _index;
+}
+
+uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) {
+	static const uint8 mskTable[] = { 0x0F, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
+	_index = newIndex;
+	uint16 res = 0;
+
+	if (_index > 8) {
+		newIndex = _index - 8;
+		res = (_key & 0xff) & mskTable[8];		
+		advSrcBitsByIndex(8);
+		_index = newIndex;
+		res |= (((_key & 0xff) & mskTable[_index]) << 8);
+		advSrcBitsByIndex(_index);
+	} else {
+		res = (_key & 0xff) & mskTable[_index];
+		advSrcBitsByIndex(_index);
+	}
+
+	return res;
+}
+
+void FileExpanderSource::copyBytes(uint8 *& dst) {
+	advSrcBitsByIndex(_bitsLeft);
+	uint16 r = (READ_LE_UINT16(_dataPtr) ^ _key) + 1;
+	_dataPtr += 2;
+
+	if (r)
+		error("decompression failure");
+
+	memcpy(dst, _dataPtr, _key);
+	_dataPtr += _key;
+	dst += _key;
+}
+
+uint16 FileExpanderSource::keyMaskedAlign(uint16 val) {
+	val -= 0x101;
+	_index = (val & 0xff) >> 2;
+	int16 b = ((_bitsLeft << 8) | _index) - 1;
+	_bitsLeft = b >> 8;
+	_index = b & 0xff;
+	return (((val & 3) + 4) << _index) + 0x101 + getKeyMasked(_index);
+}
+
+void FileExpanderSource::advSrcRefresh() {
+	_key = READ_LE_UINT16(_dataPtr);
+	_dataPtr += 2;		
+	_bitsLeft = 8;
+}
+
+class FileExpander {
+public:
+	FileExpander();
+	~FileExpander();
+
+	bool process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 insize);
+
+private:
+	void generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt);
+	uint8 calcCmdAndIndex(const uint8 *tbl, int16 &para);
+
+	FileExpanderSource *_src;
+	uint8 *_tables[9];
+	uint16 *_tables16[3];
+};
+
+FileExpander::FileExpander() : _src(0) {
+	_tables[0] = new uint8[3914];
+	assert(_tables[0]);
+
+	_tables[1] = _tables[0] + 320;
+	_tables[2] = _tables[0] + 352;
+	_tables[3] = _tables[0] + 864;
+	_tables[4] = _tables[0] + 2016;
+	_tables[5] = _tables[0] + 2528;
+	_tables[6] = _tables[0] + 2656;
+	_tables[7] = _tables[0] + 2736;
+	_tables[8] = _tables[0] + 2756;
+
+	_tables16[0] = (uint16 *)(_tables[0] + 3268);
+	_tables16[1] = (uint16 *)(_tables[0] + 3302);
+	_tables16[2] = (uint16 *)(_tables[0] + 3338);
+}
+
+FileExpander::~FileExpander() {
+	delete _src;
+	delete[] _tables[0];
+}
+
+bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 compressedSize) {
+	static const uint8 indexTable[] = {
+		0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, 0x0A,
+		0x05, 0x0B, 0x04, 0x0C, 0x03, 0x0D, 0x02, 0x0E, 0x01, 0x0F
+	};
+	
+	memset(_tables[0], 0, 3914);
+
+	uint8 *d = dst;
+	uint16 tableSize0 = 0;
+	uint16 tableSize1 = 0;
+	bool needrefresh = true;
+	bool postprocess = false;
+
+	_src = new FileExpanderSource(src);
+
+	while (d < dst + outsize) {
+
+		if (needrefresh) {
+			needrefresh = false;
+			_src->advSrcRefresh();
+		}
+
+		_src->advSrcBitsBy1();
+
+		int mode = _src->getKeyMasked(2) - 1;
+		if (mode == 1) {
+			tableSize0 = _src->getKeyMasked(5) + 257;
+			tableSize1 = _src->getKeyMasked(5) + 1;
+			memset(_tables[7], 0, 19);
+				
+			const uint8 *itbl = indexTable;
+			int numbytes = _src->getKeyMasked(4) + 4;
+			
+			while (numbytes--)
+				_tables[7][*itbl++] = _src->getKeyMasked(3);
+
+			generateTables(7, 8, 255, 19);
+
+			int cnt = tableSize0 + tableSize1;
+			uint8 *tmp = _tables[0];
+
+			while (cnt) {
+				uint16 cmd = _src->getKeyLower();
+				cmd = READ_LE_UINT16(&_tables[8][cmd << 1]);
+				_src->advSrcBitsByIndex(_tables[7][cmd]);
+
+				if (cmd < 16) {
+					*tmp++ = cmd;
+					cnt--;
+				} else {
+					uint8 tmpI = 0;
+					if (cmd == 16) {
+						cmd = _src->getKeyMasked(2) + 3;
+						tmpI = *(tmp - 1);							
+					} else if (cmd == 17) {
+						cmd = _src->getKeyMasked(3) + 3;
+					} else {
+						cmd = _src->getKeyMasked(7) + 11;
+					}
+					_src->setIndex(tmpI);
+					memset(tmp, tmpI, cmd);
+					tmp += cmd;
+
+					cnt -= cmd;
+					if (cnt < 0)
+						error("decompression failure");
+				}
+			}
+				
+			memcpy(_tables[1], _tables[0] + tableSize0, tableSize1);
+			generateTables(0, 2, 3, tableSize0);
+			generateTables(1, 4, 5, tableSize1);
+			postprocess = true;
+		} else if (mode < 0) {
+			_src->copyBytes(d);
+			postprocess = false;
+			needrefresh = true;
+		} else if (mode == 0){
+			uint8 *d2 = _tables[0];			
+			memset(d2, 8, 144);
+			memset(d2 + 144, 9, 112);
+			memset(d2 + 256, 7, 24);
+			memset(d2 + 280, 8, 8);
+			d2 = _tables[1];
+			memset(d2, 5, 32);
+			tableSize0 = 288;
+			tableSize1 = 32;
+
+			generateTables(0, 2, 3, tableSize0);
+			generateTables(1, 4, 5, tableSize1);
+			postprocess = true;
+		} else {
+			error("decompression failure");
+		}
+
+		if (!postprocess)
+			continue;
+		
+		int16 cmd = 0;
+		
+		do  {
+			cmd = ((int16*) _tables[2])[_src->getKeyLower()];
+			_src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]);
+
+			if (cmd == 0x11d) {
+				cmd = 0x200;
+			} else if (cmd > 0x108) {
+				cmd = _src->keyMaskedAlign(cmd);
+			}
+
+			if (!(cmd >> 8)) {
+				*d++ = cmd & 0xff;
+			} else if (cmd != 0x100) {
+				cmd -= 0xfe;
+				int16 offset = ((int16*) _tables[4])[_src->getKeyLower()];
+				_src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]);
+				if ((offset & 0xff) >= 4) {
+					uint8 newIndex = ((offset & 0xff) >> 1) - 1;
+					offset = (((offset & 1) + 2) << newIndex) + _src->getKeyMasked(newIndex);
+				}
+
+				uint8 *s2 = d - 1 - offset;
+				if (s2 >= dst) {
+					while (cmd--)
+						*d++ = *s2++;
+				} else {
+					uint32 pos = dst - s2;
+					s2 += (d - dst);
+
+					if (pos < (uint32) cmd) {
+						cmd -= pos;
+						while (pos--)
+							*d++ = *s2++;
+						s2 = dst;
+					}
+					while (cmd--)
+						*d++ = *s2++;
+				}
+			}
+		} while (cmd != 0x100);
+	}
+
+	delete _src;
+	_src = 0;
+
+	return true;
+}
+
+void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) {
+	const uint8 *tbl1 = _tables[srcIndex];
+	const uint8 *tbl2 = _tables[dstIndex];
+	const uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2];
+
+	if (!cnt)
+		return;
+
+	const uint8 *s = tbl1;
+	memset(_tables16[0], 0, 32);
+	
+	for (int i = 0; i < cnt; i++) 
+		_tables16[0][(*s++)]++;
+
+	_tables16[1][1] = 0;
+
+	for (uint16 i = 1, r = 0; i < 16; i++) {
+		r = (r + _tables16[0][i]) << 1;
+		_tables16[1][i + 1] = r;
+	}
+
+	if (_tables16[1][16]) {
+		uint16 r = 0;
+		for (uint16 i = 1; i < 16; i++)
+			r += _tables16[0][i];
+		if (r > 1)
+			error("decompression failure");
+	}
+
+	s = tbl1;
+	uint16 *d = _tables16[2];
+	for (int i = 0; i < cnt; i++) {
+		uint16 t = *s++;
+		if (t) {
+			_tables16[1][t]++;
+			t = _tables16[1][t] - 1;
+		}
+		*d++ = t;
+	}
+
+	s = tbl1;
+	d = _tables16[2];
+	for (int i = 0; i < cnt; i++) {
+		int8 t = ((int8)(*s++)) - 1;
+		if (t > 0) {
+			uint16 v1 = *d;
+			uint16 v2 = 0;
+			
+			do {
+				v2 = (v2 << 1) | (v1 & 1);
+				v1 >>= 1;
+			} while (--t && v1);
+			
+			t++;
+			uint8 c1 = (v1 & 1);
+			while (t--) {
+				uint8 c2 = v2 >> 15;
+				v2 = (v2 << 1) | c1;
+				c1 = c2;
+			};
+
+			*d++ = v2;
+		} else {
+			d++;
+		}		
+	}
+
+	memset((void*) tbl2, 0, 512);
+
+	cnt--;
+	s = tbl1 + cnt;
+	d = &_tables16[2][cnt];
+	uint16 * bt = (uint16*) tbl3;
+	uint16 inc = 0;
+	uint16 cnt2 = 0;
+
+	do {
+		uint8 t = *s--;
+		uint16 *s2 = (uint16*) tbl2;
+
+		if (t && t < 9) {
+			inc = 1 << t;
+			uint16 o = *d;
+			
+			do {
+				s2[o] = cnt;
+				o += inc;
+			} while (!(o & 0xf00));
+
+		} else if (t > 8) {
+			if (!bt)
+				error("decompression failure");
+
+			t -= 8;
+			uint8 shiftCnt = 1;
+			uint8 v = (*d) >> 8;
+			s2 = &((uint16*) tbl2)[*d & 0xff];
+
+			do {
+				if (!*s2) {
+					*s2 = (uint16)(~cnt2);
+					*(uint32*)&bt[cnt2] = 0;
+					cnt2 += 2;
+				}
+
+				s2 = &bt[(uint16)(~*s2)];
+				if (v & shiftCnt)
+					s2++;
+
+				shiftCnt <<= 1;
+			} while (--t);
+			*s2 = cnt;
+		}
+		d--;		
+	} while (--cnt >= 0);
+}
+
+uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 &para) {
+	const uint16 *t = (const uint16*)tbl;
+	_src->advSrcBitsByIndex(8);
+	uint8 newIndex = 0;
+	uint16 v = _src->getKeyLower();
+
+	do {
+		newIndex++;
+		para = t[((~para) & 0xfffe) | (v & 1)];
+		v >>= 1;
+	} while (para < 0);
+
+	return newIndex;
+}
+
+template<class T>
+T MIN(T l, T r) {
+	return (l < r) ? l : r;
+}
+
+HoFInstaller::HoFInstaller(const char *baseFilename) : _list(0) {
+	strncpy(_baseFilename, baseFilename, sizeof(_baseFilename));
+	char *str = strstr(_baseFilename, ".");
+	if (str) {
+		if ((uint)((str - _baseFilename) + 1) < strlen(_baseFilename))
+			str[1] = 0;
+	} else {
+		error("filename too long '%s'", baseFilename);
+	}
+
+	uint32 pos = 0;
+	uint32 bytesleft = 0;
+	bool startFile = true;
+
+	_list = new Archive;
+	memset(_list, 0, sizeof(Archive));
+	Archive *newArchive = _list;
+
+	for (int8 currentFile = 1; currentFile; currentFile++) {
+		char filename[64];
+		snprintf(filename, 64, "%s%03d", _baseFilename, currentFile);
+
+		FILE *file = NULL;
+		if ((file = fopen(filename, "rb")) == NULL)
+			break;
+
+		fseek(file, pos, SEEK_SET);
+		uint8 fileId = readByte(file);
+		pos++;
+
+		uint32 size = fileSize(file) - 1;
+		if (startFile) {
+			size -= 4;
+			if (fileId == currentFile) {
+				size -= 6;
+				pos += 6;
+				fseek(file, 6, SEEK_CUR);
+			} else {
+				size = size + 1 - pos;
+			}
+
+			strcpy(newArchive->filename, _baseFilename);
+			bytesleft = newArchive->totalSize = readUint32LE(file);
+			pos += 4;
+			newArchive->firstFile = currentFile;
+			newArchive->startOffset = pos;
+			startFile = false;
+		}
+
+		uint32 cs = MIN(size, bytesleft);
+		bytesleft -= cs;
+
+		fclose(file);
+		
+		pos += cs;
+		if (cs == size) {
+			if (!bytesleft) {
+				newArchive->lastFile = currentFile;
+				newArchive->endOffset = --pos;
+
+				newArchive->next = new Archive;
+				newArchive = newArchive->next;
+				memset(newArchive, 0, sizeof(Archive));
+				currentFile = -1;
+			} else {
+				pos = 0;
+			}
+		} else {
+			startFile = true;
+			bytesleft = size - cs;
+			newArchive->lastFile = currentFile--;
+			newArchive->endOffset = --pos;
+
+			newArchive->next = new Archive;
+			newArchive = newArchive->next;
+			memset(newArchive, 0, sizeof(Archive));
+		}
+	}
+
+	FileExpander exp;
+	uint32 insize = 0;
+	uint32 outsize = 0;
+	uint8 *inbuffer = 0;
+	uint8 *outbuffer = 0;
+	uint32 inPart1 = 0;
+	uint32 inPart2 = 0;
+	char entryStr[64];
+
+	pos = 0;
+
+	const uint32 kExecSize = 0x0bba;
+	const uint32 kHeaderSize = 30;
+	const uint32 kHeaderSize2 = 46;
+
+	for (Archive *a = _list; a != 0 && a->filename[0]; a = a->next) {
+		startFile = true;
+		for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) {
+			char filename[64];
+			snprintf(filename, 64, "%s%03d", _baseFilename, i);
+
+			FILE *file = NULL;
+			if ((file = fopen(filename, "rb")) == NULL) {
+				error("[2] Couldn't open file '%s'", filename);
+				break;
+			}
+
+			uint32 size = (i == a->lastFile) ? a->endOffset : fileSize(file);
+			
+			if (startFile) {
+				startFile = false;
+				pos = a->startOffset + kExecSize;
+				if (pos > size) {
+					pos -= size;
+					fclose(file);
+					continue;
+				}
+			} else {
+				if (inPart2) {
+					fseek(file, 1, SEEK_SET);
+					fread(inbuffer + inPart1, 1, inPart2, file);
+					inPart2 = 0;
+					exp.process(outbuffer, inbuffer, outsize, insize);
+					delete[] inbuffer;
+					inbuffer = 0;
+
+					FileList *newEntry = new FileList;
+					assert(newEntry);
+					newEntry->filename = new char[strlen(entryStr)+1];
+					assert(newEntry->filename);
+					strncpy(newEntry->filename, entryStr, strlen(entryStr)+1);
+					newEntry->size = outsize;
+					newEntry->data = outbuffer;
+
+					if (_files)
+						_files->addEntry(newEntry);
+					else
+						_files = newEntry;
+				}
+				pos++;
+			}
+
+			while (pos < size) {
+				uint8 hdr[43];
+				uint32 m = 0;
+				fseek(file, pos, SEEK_SET);
+
+				if (pos + 42 > size) {
+					m = size - pos;
+					uint32 b = 42 - m;
+
+					if (m >= 4) {
+						uint32 id = readUint32LE(file);
+						if (id == 0x06054B50) {
+							startFile = true;
+							break;
+						} else {
+							fseek(file, pos, SEEK_SET);
+						}
+					}
+				
+					snprintf(filename, 64, "%s.%03d", _baseFilename, i+1);
+
+					FILE *file2 = fopen(filename, "rb");
+					if (file2 == NULL)
+						error("Couldn't open file '%s'", filename);
+
+					fread(hdr, 1, m, file);
+					fread(hdr + m , 1, b, file2);
+					fclose(file2);
+				} else {
+					fread(hdr, 1, 42, file);
+				}
+
+				uint32 id = READ_LE_UINT32(hdr);
+				
+				if (id == 0x04034B50) {
+					if (hdr[8] != 8)
+						error("compression type not implemented");
+					insize = READ_LE_UINT32(hdr + 18);
+					outsize = READ_LE_UINT32(hdr + 22);
+			
+					uint16 filestrlen = READ_LE_UINT16(hdr + 26);
+					*(hdr + 30 + filestrlen) = 0;
+					strcpy(entryStr, (const char *)(hdr + 30));
+					pos += (kHeaderSize + filestrlen - m);
+					fseek(file, pos, SEEK_SET);
+
+					outbuffer = new uint8[outsize];
+					assert(outbuffer);
+
+					if (!inbuffer) {
+						inbuffer = new uint8[insize];
+						assert(inbuffer);
+					}
+
+					if ((pos + insize) > size) {
+						// this is for files that are split between two archive files
+						inPart1 = size - pos;
+						inPart2 = insize - inPart1;				
+						fread(inbuffer, 1, inPart1, file);
+					} else {
+						fread(inbuffer, 1, insize, file);
+						inPart2 = 0;
+						exp.process(outbuffer, inbuffer, outsize, insize);
+						delete[] inbuffer;
+						inbuffer = 0;
+
+						FileList *newEntry = new FileList;
+						assert(newEntry);
+						newEntry->filename = new char[strlen(entryStr)+1];
+						assert(newEntry->filename);
+						strncpy(newEntry->filename, entryStr, strlen(entryStr)+1);
+						newEntry->size = outsize;
+						newEntry->data = outbuffer;
+
+						if (_files)
+							_files->addEntry(newEntry);
+						else
+							_files = newEntry;
+					}
+
+					pos += insize;
+					if (pos > size) {
+						pos -= size;
+						break;
+					}
+				} else {
+					uint32 filestrlen = READ_LE_UINT32(hdr + 28);
+					pos += (kHeaderSize2 + filestrlen - m);
+				}
+			}
+
+			fclose(file);
+		}
+	}
+}
+


Property changes on: tools/trunk/kyra_ins.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: tools/trunk/kyra_ins.h
===================================================================
--- tools/trunk/kyra_ins.h	                        (rev 0)
+++ tools/trunk/kyra_ins.h	2008-05-31 23:06:53 UTC (rev 32446)
@@ -0,0 +1,57 @@
+/* Scumm Tools
+ * Copyright (C) 2008 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef KYRA_INS_H
+#define KYRA_INS_H
+
+#include "extract_kyra.h"
+#include "util.h"
+
+class HoFInstaller : public Extractor {
+public:
+	HoFInstaller(const char *baseFilename);
+	~HoFInstaller() { delete _list; delete _files; }
+
+	cFileList *getFileList() const { return _files; }
+private:
+	char _baseFilename[1024];
+
+	struct Archive {
+		Archive() : next(0) {}
+		~Archive() { delete next; next = 0; }
+
+		char filename[1024];
+		uint32 firstFile;
+		uint32 startOffset;
+		uint32 lastFile;
+		uint32 endOffset;
+		uint32 totalSize;
+
+		Archive *next;
+	};
+
+	Archive *_list;
+	FileList *_files;
+};
+
+#endif
+


Property changes on: tools/trunk/kyra_ins.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: tools/trunk/kyra_pak.cpp
===================================================================
--- tools/trunk/kyra_pak.cpp	2008-05-31 22:54:09 UTC (rev 32445)
+++ tools/trunk/kyra_pak.cpp	2008-05-31 23:06:53 UTC (rev 32446)
@@ -78,7 +78,7 @@
 		startoffset = endoffset;
 	}
 
-	delete [] buffer;
+	delete[] buffer;
 	return true;
 }
 
@@ -118,83 +118,6 @@
 	return true;
 }
 
-void PAKFile::drawFileList() {
-	FileList *cur = _fileList;
-	while (cur) {
-		printf("Filename: '%s' size: %d\n", cur->filename, cur->size);
-		cur = cur->next;
-	}
-}
-
-bool PAKFile::outputAllFiles() {
-	FileList *cur = _fileList;
-	while (cur) {
-		FILE *file = fopen(cur->filename, "wb");
-		if (!file) {
-			error("couldn't open file '%s' for writing", cur->filename);
-			return false;
-		}
-		printf("Exracting file '%s'...", cur->filename);
-		if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
-			printf("OK\n");
-		} else {
-			printf("FAILED\n");
-			return false;
-		}
-		fclose(file);
-		cur = cur->next;
-	}
-	return true;
-}
-
-bool PAKFile::outputAllFiles(char* outputPath) {
-	FileList *cur = _fileList;
-	char outputFilename[1024];
-
-	while (cur) {
-		sprintf(outputFilename, "%s/%s", outputPath, cur->filename);
-		FILE *file = fopen(outputFilename, "wb");
-		if (!file) {
-			error("couldn't open file '%s' for writing", outputFilename);
-			return false;
-		}
-		printf("Exracting file '%s'...", cur->filename);
-		if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
-			printf("OK\n");
-		} else {
-			printf("FAILED\n");
-			return false;
-		}
-		fclose(file);
-		cur = cur->next;
-	}
-	return true;
-}
-
-bool PAKFile::outputFileAs(const char *f, const char *fn) {
-	FileList *cur = (_fileList != 0) ? _fileList->findEntry(f) : 0;
-
-	if (!cur) {
-		error("file '%s' not found");
-		return false;
-	}
-
-	FILE *file = fopen(fn, "wb");
-	if (!file) {
-		error("couldn't open file '%s' in write mode", fn);
-		return false;
-	}
-	printf("Exracting file '%s' to file '%s'...", cur->filename, fn);
-	if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
-		printf("OK\n");
-	} else {
-		printf("FAILED\n");
-		return false;
-	}
-	fclose(file);
-	return true;
-}
-
 const uint8 *PAKFile::getFileData(const char *file, uint32 *size) {
 	FileList *cur = (_fileList != 0) ? _fileList->findEntry(file) : 0;
 
@@ -243,11 +166,10 @@
 	newEntry->size = size;
 	newEntry->data = data;
 
-	if (_fileList) {
+	if (_fileList)
 		_fileList->addEntry(newEntry);
-	} else {
+	else
 		_fileList = newEntry;
-	}
 	return true;
 }
 
@@ -266,3 +188,63 @@
 	}
 	return false;
 }
+
+//HACK: move this to another file
+
+void Extractor::drawFileList() {
+	cFileList *cur = getFileList();
+	while (cur) {
+		printf("Filename: '%s' size: %d\n", cur->filename, cur->size);
+		cur = cur->next;
+	}
+}
+
+bool Extractor::outputAllFiles(const char *outputPath) {
+	cFileList *cur = getFileList();
+	char outputFilename[1024];
+
+	while (cur) {
+		sprintf(outputFilename, "%s/%s", outputPath, cur->filename);
+		FILE *file = fopen(outputFilename, "wb");
+		if (!file) {
+			error("couldn't open file '%s' for writing", outputFilename);
+			return false;
+		}
+		printf("Exracting file '%s'...", cur->filename);
+		if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
+			printf("OK\n");
+		} else {
+			printf("FAILED\n");
+			return false;
+		}
+		fclose(file);
+		cur = cur->next;
+	}
+	return true;
+}
+
+bool Extractor::outputFileAs(const char *f, const char *fn) {
+	cFileList *cur = getFileList();
+	cur = (cur != 0) ? cur->findEntry(f) : 0;
+
+	if (!cur) {
+		error("file '%s' not found");
+		return false;
+	}
+
+	FILE *file = fopen(fn, "wb");
+	if (!file) {
+		error("couldn't open file '%s' in write mode", fn);
+		return false;
+	}
+	printf("Exracting file '%s' to file '%s'...", cur->filename, fn);
+	if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
+		printf("OK\n");
+	} else {
+		printf("FAILED\n");
+		return false;
+	}
+	fclose(file);
+	return true;
+}
+

Modified: tools/trunk/kyra_pak.h
===================================================================
--- tools/trunk/kyra_pak.h	2008-05-31 22:54:09 UTC (rev 32445)
+++ tools/trunk/kyra_pak.h	2008-05-31 23:06:53 UTC (rev 32446)
@@ -23,9 +23,10 @@
 #ifndef KYRA_PAK_H
 #define KYRA_PAK_H
 
+#include "extract_kyra.h"
 #include "util.h"
 
-class PAKFile {
+class PAKFile : public Extractor {
 public:
 	PAKFile() : _fileList(0), _isAmiga(false) {}
 	~PAKFile() { delete _fileList; }
@@ -36,68 +37,13 @@
 
 	const uint32 getFileSize() const { return _fileList->getTableSize()+5+4+_fileList->getFileSize(); }
 
-	void drawFileList();
-
-	bool outputAllFiles();
-	bool outputAllFiles(char* outputPath);
-
-	bool outputFile(const char *file) { return outputFileAs(file, file); }
-	bool outputFileAs(const char *file, const char *outputName);
 	const uint8 *getFileData(const char *file, uint32 *size);
 
 	bool addFile(const char *name, const char *file);
 	bool addFile(const char *name, uint8 *data, uint32 size);
 
 	bool removeFile(const char *name);
-public:
-	struct FileList {
-		FileList() : filename(0), size(0), data(0), next(0) {}
-		~FileList() {
-			delete [] filename;
-			delete [] data;
-			delete next;
-		}
 
-		FileList *findEntry(const char *f) {
-			for (FileList *cur = this; cur; cur = cur->next) {
-				if (scumm_stricmp(cur->filename, f) != 0)
-					continue;
-				return cur;
-			}
-			return 0;
-		}
-
-		const FileList *findEntry(const char *f) const {
-			for (const FileList *cur = this; cur; cur = cur->next) {
-				if (scumm_stricmp(cur->filename, f) != 0)
-					continue;
-				return cur;
-			}
-			return 0;
-		}
-
-		void addEntry(FileList *e) {
-			if (next)
-				next->addEntry(e);
-			else
-				next = e;
-		}
-		uint32 getTableSize() const {
-			return strlen(filename)+1+4+((next != 0) ? next->getTableSize() : 0);
-		}
-		uint32 getFileSize() const {
-			return size + (next != 0 ? next->getFileSize() : 0);
-		}
-
-		char *filename;
-		uint32 size;
-		uint8 *data;
-
-		FileList *next;
-	};
-
-	typedef const FileList cFileList;
-
 	cFileList *getFileList() const { return _fileList; }
 private:
 	FileList *_fileList;
@@ -105,3 +51,4 @@
 };
 
 #endif
+


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