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

peres001 at users.sourceforge.net peres001 at users.sourceforge.net
Sun Jun 17 09:05:16 CEST 2007


Revision: 27507
          http://scummvm.svn.sourceforge.net/scummvm/?rev=27507&view=rev
Author:   peres001
Date:     2007-06-17 00:05:15 -0700 (Sun, 17 Jun 2007)

Log Message:
-----------
Added extract_parallaction tool (nicely packaged by Kirben).

Modified Paths:
--------------
    tools/trunk/Makefile
    tools/trunk/Makefile.mingw
    tools/trunk/README

Added Paths:
-----------
    tools/trunk/extract_parallaction.cpp
    tools/trunk/extract_parallaction.h

Modified: tools/trunk/Makefile
===================================================================
--- tools/trunk/Makefile	2007-06-17 06:00:10 UTC (rev 27506)
+++ tools/trunk/Makefile	2007-06-17 07:05:15 UTC (rev 27507)
@@ -36,6 +36,7 @@
 	extract_mm_apple$(EXEEXT) \
 	extract_mm_c64$(EXEEXT) \
 	extract_mm_nes$(EXEEXT) \
+	extract_parallaction$(EXEEXT) \
 	extract_scumm_mac$(EXEEXT) \
 	extract_zak_c64$(EXEEXT)
 
@@ -109,6 +110,9 @@
 extract_mm_nes$(EXEEXT): extract_mm_nes.o util.o
 	$(CC) $(LDFLAGS) -o $@ $+
 
+extract_parallaction$(EXEEXT): extract_parallaction.o util.o
+	$(CXX) $(LDFLAGS) -o $@ $+
+
 extract_scumm_mac$(EXEEXT): extract_scumm_mac.o util.o
 	$(CC) $(LDFLAGS) -o $@ $+
 
@@ -123,6 +127,9 @@
 compress_scumm_bun.o compress_sword1.o compress_sword2.o \
 compress_kyra.o compress.o encode_dxa.o: compress.h
 
+# extract_parallaction.h
+extract_parallaction.o: extract_parallaction.h
+
 # Virtually everything depends on util.h
 compress_agos.o  compress_saga.o compress_scumm_sou.o \
 compress_scumm_bun.o compress_sword1.o compress_sword2.o \
@@ -139,6 +146,7 @@
 extract_mm_apple.o \
 extract_mm_c64.o \
 extract_mm_nes.o \
+extract_parallaction.o \
 extract_scumm_mac.o \
 extract_zak_c64.o \
 kyra_pak.o \

Modified: tools/trunk/Makefile.mingw
===================================================================
--- tools/trunk/Makefile.mingw	2007-06-17 06:00:10 UTC (rev 27506)
+++ tools/trunk/Makefile.mingw	2007-06-17 07:05:15 UTC (rev 27507)
@@ -31,6 +31,7 @@
 	strip extract_mm_apple.exe -o $(SCUMMVMPATH)/tools/extract_mm_apple.exe
 	strip extract_mm_c64.exe -o $(SCUMMVMPATH)/tools/extract_mm_c64.exe
 	strip extract_mm_nes.exe -o $(SCUMMVMPATH)/tools/extract_mm_nes.exe
+	strip extract_parallaction.exe -o $(SCUMMVMPATH)/tools/extract_parallaction.exe
 	strip extract_scumm_mac.exe -o $(SCUMMVMPATH)/tools/extract_scumm_mac.exe
 	strip extract_zak_c64.exe -o $(SCUMMVMPATH)/tools/extract_zak_c64.exe
 	cp *.bat $(SCUMMVMPATH)/tools

Modified: tools/trunk/README
===================================================================
--- tools/trunk/README	2007-06-17 06:00:10 UTC (rev 27506)
+++ tools/trunk/README	2007-06-17 07:05:15 UTC (rev 27507)
@@ -37,6 +37,9 @@
         extract_mm_nes
                 Extracts data files from the NES version of Maniac Mansion.
 
+        extract_parallaction
+                Extracts the contents of archives used by Nippon Safes
+
         extract_zak_c64
                 Extracts data files from the Commodore 64 version of Zak
                 McKracken.

Added: tools/trunk/extract_parallaction.cpp
===================================================================
--- tools/trunk/extract_parallaction.cpp	                        (rev 0)
+++ tools/trunk/extract_parallaction.cpp	2007-06-17 07:05:15 UTC (rev 27507)
@@ -0,0 +1,342 @@
+/* extract_parallaction - Extractor for Nippon Safe archives
+ * 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$
+ *
+ */
+
+#include "extract_parallaction.h"
+#include "util.h"
+
+Archive::Archive() {
+	_file = NULL;
+	_fileData = NULL;
+	_fileSize = 0;
+	_filePos = 0;
+
+	_numFiles = 0;
+	_numSlots = 0;
+}
+
+Archive::~Archive() {
+	closeSubfile();
+
+	if (_file)
+		fclose(_file);
+
+	_file = NULL;
+}
+
+bool Archive::isPackedSubfile(byte* data) {
+	return (data[0] == 'P' && data[1] == 'P' && data[2] == '2' && data[3] == '0');
+}
+
+uint32 Archive::getSizeOfPackedSubfile(byte* packedData, uint32 packedSize) {
+	uint32 size = *(uint32*)(packedData + packedSize - 4);
+
+	return ((size & 0xFF00)) |
+		((size & 0xFF0000) >> 16);
+}
+
+int32 Archive::findSubfile(const char* filename) {
+	for (uint32 i = 0; i < _numFiles; i++) {
+		if (!stricmp(filename, _names[i])) return i;
+	}
+
+	return -1;
+}
+
+void Archive::unpackSubfile(byte* packedData, uint32 packedSize) {
+
+	ppdepack(packedData, _fileData, packedSize, _fileSize);
+
+}
+
+void Archive::closeSubfile() {
+	if (_fileData) free(_fileData);
+	_fileData = NULL;
+	_fileSize = 0;
+	_filePos = 0;
+}
+
+uint32 Archive::getSizeOfSubfile() {
+	return _fileSize;
+}
+
+void Archive::openSubfile(uint32 index) {
+	if (index >= _numFiles) exit(-3);
+
+	closeSubfile();
+
+	uint32 srcOffset = _offsets[index];
+	uint32 srcSize = _sizes[index];
+
+	byte *srcData = (byte*)malloc(srcSize);
+	fseek(_file, srcOffset, SEEK_SET);
+	fread(srcData, 1, srcSize, _file);
+
+	if (isPackedSubfile(srcData)) {
+		_fileSize = getSizeOfPackedSubfile(srcData, srcSize);
+		_fileData = (byte*)malloc(_fileSize);
+
+		unpackSubfile(srcData, srcSize);
+
+		free(srcData);
+	} else {
+		_fileSize = srcSize;
+		_fileData = srcData;
+	}
+}
+
+void Archive::openSubfile(const char* filename) {
+
+	int32 index = findSubfile(filename);
+	if (index == -1) exit(-2);
+
+	openSubfile(index);
+
+	return;
+}
+
+void Archive::readSubfile(byte* buf, uint32 size) {
+	assert(size + _filePos <= _fileSize);
+	memcpy(buf, _fileData + _filePos, size);
+	_filePos += size;
+	return;
+}
+
+void Archive::open(const char* filename, bool smallArchive) {
+	uint16 maxEntries = (smallArchive) ? 180 : 384;
+
+	_file = fopen(filename, "rb");
+	if (!_file) exit(10);
+
+	strcpy(_name, filename);
+
+	fseek(_file, ARCHIVE_HEADER_SIZE, SEEK_SET);
+	fread(_names, maxEntries + 1, ARCHIVE_FILENAME_LEN, _file);
+
+	uint32 i;
+	for (i = 0; i < maxEntries; i++) {
+		if (_names[i][0] == '\0') break;
+	}
+
+	_numFiles = i;
+
+	if (_numFiles < maxEntries) {
+		uint32* t = (uint32*)_names[i];
+
+		for (; i < maxEntries + 1; i++) {
+			if (*t != 0) break;
+			t += 8;
+		}
+	} 
+
+	if ( i > maxEntries ) exit(9);
+
+	_numSlots = i;
+
+	fprintf(stderr, "%i files found in %i slots (%i empty)\n", _numFiles, _numSlots, _numSlots - _numFiles);
+
+	fseek(_file, _numSlots * ARCHIVE_FILENAME_LEN + ARCHIVE_HEADER_SIZE, SEEK_SET);
+
+	for (i = 0; i < _numSlots; i++) {
+		_sizes[i] = readUint32BE(_file);
+	}
+
+	if (smallArchive) {
+		_offsets[0] = 0x1966;
+	} else {
+		_offsets[0] = 0x4000;
+	}
+
+	ftell(_file);
+
+	for (i = 1; i < _numSlots; i++)
+		_offsets[i] = _offsets[i-1] + _sizes[i-1];
+
+	return;
+}
+
+void Archive::dumpStructs(FILE* dump) {
+	char arcName[32];
+
+	char* s = strrchr(_name, '/');
+	if (s == NULL) {
+		s = strrchr(_name, '\\');
+		if (s == NULL) s = _name;
+	}
+
+	char* d = arcName;
+	for (; *s; ) *d++ = toupper(*s++);
+	*d = '\0';
+
+	for (uint32 i = 0; i < _numFiles; i++) {
+		fprintf(dump, "{ \"%s\",%*s%5i, kArchive%s, %7i },\n", _names[i], 32-strlen(_names[i]), " ", _sizes[i], arcName+1, _offsets[i]);
+	}
+}
+
+
+#define val(p) ((p)[0]<<16 | (p)[1] << 8 | (p)[2])
+
+uint32  depackedlen(byte* packed, uint32 plen) {
+	if (packed[0] != 'P' || packed[1] != 'P' ||
+		packed[2] != '2' || packed[3] != '0')
+			return 0; /* not a powerpacker file */
+
+	return val(packed+plen-4);
+}
+
+static uint32 shift_in;
+static uint32 counter = 0;
+static byte *source;
+
+static uint32 get_bits(uint32 n) {
+	uint32 result = 0;
+	uint32 i;
+
+	for (i = 0; i < n; i++) {
+		if (counter == 0) {
+			counter = 8;
+			shift_in = *--source;
+		}
+		result = (result<<1) | (shift_in & 1);
+		shift_in >>= 1;
+		counter--;
+	}
+
+	return result;
+}
+
+void ppdepack(byte* packed, byte* depacked, uint32 plen, uint32 unplen) {
+	byte *dest;
+	int n_bits;
+	int idx;
+	uint32 bytes;
+	int to_add;
+	uint32 offset;
+	byte offset_sizes[4];
+	uint32 i;
+
+	shift_in = 0;
+	counter = 0;
+
+	offset_sizes[0] = packed[4];	/* skip signature */
+	offset_sizes[1] = packed[5];
+	offset_sizes[2] = packed[6];
+	offset_sizes[3] = packed[7];
+
+	/* initialize source of bits */
+	source = packed + plen - 4;
+
+	dest = depacked + unplen;
+
+	/* skip bits */
+	get_bits(source[3]);
+
+	/* do it forever, i.e., while the whole file isn't unpacked */
+	while (1) {
+		/* copy some bytes from the source anyway */
+		if (get_bits(1) == 0) {
+			bytes = 0;
+			do {
+				to_add = get_bits(2);
+				bytes += to_add;
+			} while (to_add == 3);
+			for (i = 0; i <= bytes; i++)
+				*--dest = get_bits(8);
+			if (dest <= depacked)
+				return;
+		}
+		/* decode what to copy from the destination file */
+		idx = get_bits(2);
+		n_bits = offset_sizes[idx];
+		/* bytes to copy */
+		bytes = idx + 1;
+		if (bytes == 4)	{ /* 4 means >=4 */
+			/* and maybe a bigger offset */
+			if (get_bits(1) == 0)
+				offset = get_bits(7);
+			else
+				offset = get_bits(n_bits);
+
+			do {
+				to_add = get_bits(3);
+				bytes += to_add;
+			} while (to_add == 7);
+		} else {
+			offset = get_bits(n_bits);
+		}
+		for (i = 0; i <= bytes; i++) {
+			dest[-1] = dest[offset];
+			dest--;
+		}
+		if (dest <= depacked)
+			return;
+	}
+
+}
+
+void optDump(const char* file, const char* dir, bool smallArchive) {
+	Archive arc;
+	arc.open(file, smallArchive);
+
+	for (uint32 i = 0; i < arc._numFiles; i++) {
+
+		arc.openSubfile(i);
+
+		char path[260];
+		strcpy(path, dir);
+
+		char *d = path + (strlen(path) - 1);
+		if (*d == '/')
+			d++;
+		else {
+			if (*d != '\\')
+				d++;
+
+			*d++ = '/';
+			*d = '\0';
+		}
+
+		for (char *s = arc._names[i]; *s; s++, d++)
+			*d = *s == '/' ? '_' : *s;
+
+		*d = '\0';
+
+		FILE* ofile = fopen(path, "wb");
+		fwrite(arc._fileData, 1, arc._fileSize, ofile);
+		fclose(ofile);
+	}
+}
+
+int main(int argc, char *argv[]) {
+
+	if (argc < 3) {
+		printf("Usage: extract_parallaction archivefile directory");
+		exit(1);
+	}
+
+	if (!strcmp(argv[1], "small")) {
+		optDump(argv[2], argv[3], true);
+	} else {
+		optDump(argv[1], argv[2], false);
+	}
+
+	return 0;
+}


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

Added: tools/trunk/extract_parallaction.h
===================================================================
--- tools/trunk/extract_parallaction.h	                        (rev 0)
+++ tools/trunk/extract_parallaction.h	2007-06-17 07:05:15 UTC (rev 27507)
@@ -0,0 +1,70 @@
+/* Scumm Tools
+ * Copyright (C) 2002-2006 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 "util.h"
+
+uint32 depackedlen(byte *packed, uint32 plen);
+void ppdepack(byte *packed, byte *depacked, uint32 plen, uint32 unplen);
+
+#define MAX_ARCHIVE_ENTRIES		384
+
+#define ARCHIVE_HEADER_SIZE		22
+#define ARCHIVE_FILENAME_LEN		32
+
+
+struct Archive {
+	uint32	_numSlots;
+	uint32	_numFiles;
+	FILE   *_file;
+	char	_name[260];
+
+	// file data
+	byte*	_fileData;
+	uint32	_fileSize;
+	uint32	_filePos;
+
+	char 	_names[MAX_ARCHIVE_ENTRIES+1][ARCHIVE_FILENAME_LEN];
+	uint32 	_sizes[MAX_ARCHIVE_ENTRIES];
+	uint32 	_offsets[MAX_ARCHIVE_ENTRIES];
+
+	void 	open(const char* filename, bool smallArchive);
+
+	void 	openSubfile(uint32 index);
+	void 	openSubfile(const char* filename);
+	void 	readSubfile(byte* buf, uint32 size);
+	uint32  getSizeOfSubfile();
+
+	Archive();
+	~Archive();
+
+	// debug stuff
+	void dumpStructs(FILE*);
+
+private:
+	int32	findSubfile(const char* filename);
+	void	closeSubfile();
+
+	bool	isPackedSubfile(byte* data);
+	uint32	getSizeOfPackedSubfile(byte* packedData, uint32 packedSize);
+	void	unpackSubfile(byte* packedData, uint32 packedSize);
+
+};


Property changes on: tools/trunk/extract_parallaction.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: 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