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

tdhs at users.sourceforge.net tdhs at users.sourceforge.net
Fri Jan 29 05:02:54 CET 2010


Revision: 47664
          http://scummvm.svn.sourceforge.net/scummvm/?rev=47664&view=rev
Author:   tdhs
Date:     2010-01-29 04:02:54 +0000 (Fri, 29 Jan 2010)

Log Message:
-----------
Adding new Mohawk tool, construct_mohawk.
This takes the raw dump output resource files from extract_mohawk and reassembles them back into a Mohawk archive. This allows modification of game resources and testing of the effect on the original engine behaviour.

Modified Paths:
--------------
    tools/trunk/Makefile
    tools/trunk/Makefile.common

Added Paths:
-----------
    tools/trunk/engines/mohawk/construct_mohawk.cpp

Modified: tools/trunk/Makefile
===================================================================
--- tools/trunk/Makefile	2010-01-29 01:31:05 UTC (rev 47663)
+++ tools/trunk/Makefile	2010-01-29 04:02:54 UTC (rev 47664)
@@ -92,6 +92,7 @@
 	strip descumm.exe -o $(WIN32PATH)/tools/descumm.exe
 	strip desword2.exe -o $(WIN32PATH)/tools/desword2.exe
 	strip extract_mohawk.exe -o $(WIN32PATH)/tools/extract_mohawk.exe
+	strip construct_mohawk.exe -o $(WIN32PATH)/tools/construct_mohawk.exe
 	strip scummvm-tools.exe -o $(WIN32PATH)/tools/scummvm-tools.exe
 	strip scummvm-tools-cli.exe -o $(WIN32PATH)/tools/scummvm-tools-cli.exe
 	cp *.bat $(WIN32PATH)/tools

Modified: tools/trunk/Makefile.common
===================================================================
--- tools/trunk/Makefile.common	2010-01-29 01:31:05 UTC (rev 47663)
+++ tools/trunk/Makefile.common	2010-01-29 04:02:54 UTC (rev 47664)
@@ -68,6 +68,7 @@
 	descumm$(EXEEXT) \
 	desword2$(EXEEXT) \
 	extract_mohawk$(EXEEXT) \
+	construct_mohawk$(EXEEXT) \
 	degob$(EXEEXT) \
 	scummvm-tools-cli$(EXEEXT)
 
@@ -121,6 +122,7 @@
 	desword2 \
 	degob \
 	extract_mohawk \
+	construct_mohawk \
 	create_sjisfnt \
 	scummvm-tools \
 	scummvm-tools-cli \
@@ -176,6 +178,10 @@
 	common/md5.o \
 	common/util.o
 
+construct_mohawk_OBJS := \
+	engines/mohawk/construct_mohawk.o \
+	$(UTILS)	
+
 create_sjisfnt_OBJS := create_sjisfnt.o $(UTILS)
 create_sjisfnt_LIBS := $(FREETYPELIBS) $(ICONVLIBS)
 # Set custom build flags

Added: tools/trunk/engines/mohawk/construct_mohawk.cpp
===================================================================
--- tools/trunk/engines/mohawk/construct_mohawk.cpp	                        (rev 0)
+++ tools/trunk/engines/mohawk/construct_mohawk.cpp	2010-01-29 04:02:54 UTC (rev 47664)
@@ -0,0 +1,496 @@
+/* construct_mohawk - Mohawk file constructor
+ * Copyright (C) 2009 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 "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "common/str.h"
+#include "archive.h"
+
+uint32 _fileSize;
+
+struct RSRC_HeaderConstruct {
+	uint16 version;
+	uint16 compaction;
+	uint32 filesize;
+	uint32 abs_offset;
+	uint16 file_table_offset;
+	uint16 file_table_size;
+};
+
+RSRC_HeaderConstruct _rsrc;
+TypeTable _typeTable;
+
+struct TypeConstructResourceEntries {
+	uint16 id;
+	uint16 index;
+};
+
+struct TypeConstructNameEntries {
+	uint16 offset;
+	uint16 index;
+	// Name List
+	Common::String name;
+};
+
+struct TypeConstruct {
+	//Type Table
+	uint32 tag;
+	uint16 resource_table_offset;
+	uint16 name_table_offset;
+
+	struct ResourceTable {
+		uint16 resources;
+		Common::Array<TypeConstructResourceEntries> entries;
+	} resTable;
+
+	struct NameTable {
+		uint16 num;
+		Common::Array<TypeConstructNameEntries> entries;
+	} nameTable;
+};
+
+Common::Array<TypeConstruct> _types;
+uint16 _nameTableAmount;
+uint16 _resourceTableAmount;
+uint16 _fileTableAmount;
+Common::Array<FileTable> _fileTable;
+
+int16 getTypeIndex(uint32 tag) {
+	for (uint16 i = 0; i < _typeTable.resource_types; i++)
+		if (_types[i].tag == tag)
+			return i;
+	return -1;	// not found
+}
+
+int16 getIdIndex(int16 typeIndex, uint16 id) {
+	for (uint16 i = 0; i < _types[typeIndex].resTable.resources; i++)
+		if (_types[typeIndex].resTable.entries[i].id == id)
+			return i;
+	return -1;	// not found
+}
+
+Common::String tag2string(uint32 tag) {
+	char str[5];
+	str[0] = (char)(tag >> 24);
+	str[1] = (char)(tag >> 16);
+	str[2] = (char)(tag >> 8);
+	str[3] = (char)tag;
+	str[4] = '\0';
+	// Replace non-printable chars by dot
+	for (int i = 0; i < 4; ++i) {
+		if (!isprint(str[i]))
+			str[i] = '.';
+	}
+	return Common::String(str);
+}
+
+uint32 string2tag(const char *str) {
+	uint32 ret = 0;
+	ret += str[0] << 24;
+	ret += str[1] << 16;
+	ret += str[2] << 8;
+	ret += str[3];
+	return ret;
+}
+
+// Have a maximum buffer size
+#define MAX_BUF_SIZE 16384
+
+static byte *outputBuffer = NULL;
+
+void initMohawkArchive(void) {
+	// Initialize Mohawk Archive Parameters with parameters for empty archive
+	_fileSize = 28;
+
+	_rsrc.version = 256; // BCD 1.0
+	_rsrc.compaction = 1;
+
+	_rsrc.filesize = 36;
+	_rsrc.abs_offset = 28;
+	_rsrc.file_table_offset = 4;
+	_rsrc.file_table_size = 4;
+
+	_typeTable.name_offset = 4;
+	_typeTable.resource_types = 0;
+
+	_nameTableAmount = 0;
+	_resourceTableAmount = 0;
+	_fileTableAmount = 0;
+}
+
+void updateTypeTableOffsets(void) {
+	for (uint16 i = 0; i < _typeTable.resource_types; i++) {
+		_types[i].resource_table_offset = 4 + (_typeTable.resource_types * 8);
+
+		for (uint16 j = 0; j < i; j++) {
+			_types[i].resource_table_offset += 2 + (_types[j].resTable.resources * 4);
+			_types[i].resource_table_offset += 2 + (_types[j].nameTable.num * 4);
+		}
+
+		_types[i].name_table_offset = _types[i].resource_table_offset + 2 + (_types[i].resTable.resources * 4);
+	}
+}
+
+void addTypeToMohawkArchive(const char *resourceTag) {
+	TypeConstruct newType;
+	newType.tag = string2tag(resourceTag);
+	newType.resource_table_offset = 0;
+	newType.name_table_offset = 0;
+	newType.resTable.resources = 0;
+	newType.nameTable.num = 0;
+
+	_fileSize += 12;
+	_rsrc.filesize += 12;
+	_rsrc.file_table_offset += 12;
+	_typeTable.name_offset += 12;
+
+	_typeTable.resource_types++;
+	_types.push_back(newType);
+
+	updateTypeTableOffsets();
+}
+
+void addFileToMohawkArchive(int fileId, byte fileFlags, const char *resourceTag, int resourceId, const char *resourceName, uint32 fileSize) {
+	int16 typeIndex = getTypeIndex(string2tag(resourceTag));
+	if (typeIndex == -1) {
+		// Add New Type to typeTable
+		addTypeToMohawkArchive(resourceTag);
+		typeIndex = getTypeIndex(string2tag(resourceTag));
+	} else {
+		if (getIdIndex(typeIndex, resourceId) != -1) {
+			printf("Error : Duplicate Resource Type \'%s\' Id %d\n", resourceTag, resourceId);
+			return;
+		}
+	}
+
+	// Update Resource Table
+	TypeConstructResourceEntries newTypeResource;
+	newTypeResource.id = resourceId;
+	newTypeResource.index = fileId + 1;
+
+	_fileSize += 4;
+	_rsrc.filesize += 4;
+	_rsrc.file_table_offset += 4;
+	_typeTable.name_offset += 4;
+
+	// Insert in Resource Table ordered by id
+	uint16 j;
+	for (j = 0; j < _types[typeIndex].resTable.entries.size(); j++) {
+		if (_types[typeIndex].resTable.entries[j].id > newTypeResource.id)
+			break;
+	}
+
+	_types[typeIndex].resTable.resources++;
+	_types[typeIndex].resTable.entries.insert_at(j, newTypeResource);
+
+	updateTypeTableOffsets();
+
+	// Update Name Table if name is present
+	int nameSize = strlen(resourceName);
+	if (nameSize != 0) {
+		TypeConstructNameEntries newTypeName;
+
+		if (_types[typeIndex].nameTable.entries.empty())
+			newTypeName.offset = 0;
+		else
+			newTypeName.offset = _types[typeIndex].nameTable.entries.back().offset + _types[typeIndex].nameTable.entries.back().name.size() + 1;
+
+		newTypeName.index = fileId + 1;
+		newTypeName.name += resourceName;
+
+		_fileSize += 4 + nameSize + 1;
+		_rsrc.filesize += 4 + nameSize + 1;
+		_rsrc.file_table_offset += 4 + nameSize + 1;
+		_typeTable.name_offset += 4;
+
+		_types[typeIndex].nameTable.num++;
+		_types[typeIndex].nameTable.entries.push_back(newTypeName);
+
+		updateTypeTableOffsets();
+	}
+
+	// TODO: Error if duplicate file table ids
+	// TODO: Error if missing file table ids
+
+	// Add file data parameters to fileTable
+	uint32 fileItemOffset = 36;
+	for (uint16 i = 0; i < _fileTableAmount; i++)
+		fileItemOffset += _fileTable[i].dataSize;
+
+	FileTable fileTableItem;
+	fileTableItem.offset = fileItemOffset;
+	fileTableItem.dataSize = fileSize;
+	fileTableItem.flags = fileFlags;
+	fileTableItem.unk = 0;
+
+	_fileSize += 10;
+	_rsrc.filesize += 10;
+	_rsrc.file_table_size += 10;
+
+	_fileTableAmount++;
+	_fileTable.push_back(fileTableItem);
+
+	_fileSize += fileSize;
+	_rsrc.filesize += fileSize;
+	_rsrc.abs_offset += fileSize;
+}
+
+void sortTypeTable(Common::Array<TypeConstruct> *tempTypeTable) {
+	uint16 i, j;
+
+	// Insert in Resource Type Table ordered Alphabetically by Resource Tag
+	for (i = 0; i < _types.size(); i++) {
+		for (j = 0; j < tempTypeTable->size(); j++) {
+			if ((*tempTypeTable)[j].tag > _types[i].tag)
+				break;
+		}
+		tempTypeTable->insert_at(j, _types[i]);
+	}
+}
+
+// Order of Name Table in same order as Resource Table cross referenced by index
+void sortNameTable(Common::Array<TypeConstructNameEntries> *tempNameTable, uint16 i) {
+	for (uint16 j = 0; j < _types[i].resTable.resources; j++) {
+		for (uint16 k = 0; k < _types[i].nameTable.num; k++) {
+			if (_types[i].resTable.entries[j].index == _types[i].nameTable.entries[k].index)
+				tempNameTable->push_back(_types[i].nameTable.entries[k]);
+		}
+	}
+
+	assert(tempNameTable->size() == _types[i].nameTable.num);
+}
+
+void writeMohawkArchive(int argc, char **argv, int archiveArg, Common::File *mohawkFile) {
+	// Gap between RSRC and File Data..
+	_fileSize += 8;
+	_rsrc.filesize += 8;
+	_rsrc.abs_offset += 8;
+
+	mohawkFile->writeUint32BE(ID_MHWK);
+	mohawkFile->writeUint32BE(_fileSize);
+
+	mohawkFile->writeUint32BE(ID_RSRC);
+	mohawkFile->writeUint16BE(_rsrc.version);
+	mohawkFile->writeUint16BE(_rsrc.compaction);
+	mohawkFile->writeUint32BE(_rsrc.filesize);
+	mohawkFile->writeUint32BE(_rsrc.abs_offset);
+	mohawkFile->writeUint16BE(_rsrc.file_table_offset);
+	mohawkFile->writeUint16BE(_rsrc.file_table_size);
+
+	// Gap between RSRC and File Data...
+	mohawkFile->writeUint16BE(4); // Not sure what this is...
+	mohawkFile->writeUint16BE(0);
+	mohawkFile->writeUint16BE(0);
+	mohawkFile->writeUint16BE(0);
+
+	for (int i = archiveArg + 1; i < argc; i++) {
+		Common::Filename resourceFile = Common::Filename(argv[i]);
+
+		Common::File *resourceIn = new Common::File(resourceFile, "rb");
+		if (!resourceIn->isOpen()) {
+			printf("Could not open file \"%s\"\n", resourceFile.getName().c_str());
+			delete resourceIn;
+			return;
+		}
+
+		while (resourceIn->pos() < (int)resourceIn->size()) {
+			uint32 size = resourceIn->read_noThrow(outputBuffer, MAX_BUF_SIZE);
+			mohawkFile->write(outputBuffer, size);
+		}
+
+		resourceIn->close();
+		delete resourceIn;
+	}
+
+	// _rsrc.abs_offset points here...
+	mohawkFile->writeUint16BE(_typeTable.name_offset);
+	mohawkFile->writeUint16BE(_typeTable.resource_types);
+
+	Common::Array<TypeConstruct> tempTypeTable;
+	// _types sorted into Resource Tag Alphabetical order into tempTypeTable
+	sortTypeTable(&tempTypeTable);
+
+	for (uint16 i = 0; i < _typeTable.resource_types; i++) {
+		mohawkFile->writeUint32BE(tempTypeTable[i].tag);
+		mohawkFile->writeUint16BE(tempTypeTable[i].resource_table_offset);
+		mohawkFile->writeUint16BE(tempTypeTable[i].name_table_offset);
+	}
+
+	for (uint16 i = 0; i < _typeTable.resource_types; i++) {
+		mohawkFile->writeUint16BE(_types[i].resTable.resources);
+
+		for (uint16 j = 0; j < _types[i].resTable.resources; j++) {
+			mohawkFile->writeUint16BE(_types[i].resTable.entries[j].id);
+			mohawkFile->writeUint16BE(_types[i].resTable.entries[j].index);
+		}
+
+		mohawkFile->writeUint16BE(_types[i].nameTable.num);
+
+		Common::Array<TypeConstructNameEntries> tempNameTable;
+		// _types[i].resTable.entries sorted into resource order output into tempNameTable
+		sortNameTable(&tempNameTable, i);
+
+		for (uint16 j = 0; j < _types[i].nameTable.num; j++) {
+			mohawkFile->writeUint16BE(tempNameTable[j].offset);
+			mohawkFile->writeUint16BE(tempNameTable[j].index);
+		}
+	}
+
+	for (uint16 i = 0; i < _typeTable.resource_types; i++) {
+		for (uint16 j = 0; j < _types[i].nameTable.num; j++) {
+			mohawkFile->write(_types[i].nameTable.entries[j].name.c_str(), _types[i].nameTable.entries[j].name.size()+1);
+		}
+	}
+
+	// _rsrc.file_table_offset is added to _rsrc.abs_offset to get here...
+	mohawkFile->writeUint32BE(_fileTableAmount);
+	for (uint32 i = 0; i < _fileTableAmount; i++) {
+		mohawkFile->writeUint32BE(_fileTable[i].offset);
+		mohawkFile->writeUint16BE(_fileTable[i].dataSize & 0xFFFF);
+		mohawkFile->writeByte((_fileTable[i].dataSize >> 16) & 0xFF);
+
+		// TODO: The following should be correct, but doesn't match up.
+		//mohawkFile->writeByte((_fileTable[i].dataSize >> 24) & 0x07) || (_fileTable[i].flags & 0xF8));
+		mohawkFile->writeByte(_fileTable[i].flags);
+
+		mohawkFile->writeUint16BE(_fileTable[i].unk);
+	}
+}
+
+void printUsage(const char *appName) {
+	printf("Usage: %s [options] <mohawk archive> <binary resource file #1> [binary resource file #2] ...\n", appName);
+	printf("Options :\n");
+}
+
+int main(int argc, char *argv[]) {
+	int archiveArg;
+
+	// Parse parameters
+	for (archiveArg = 1; archiveArg < argc; archiveArg++) {
+		Common::String current = Common::String(argv[archiveArg]);
+
+		if(!current.hasPrefix("--"))
+			break;
+
+		// Decode options
+		printf("Unknown argument : \"%s\"\n", argv[archiveArg]);
+		printUsage(argv[0]);
+		return 1;
+	}
+
+	if (argc == 1 || archiveArg == argc - 1) {
+		printUsage(argv[0]);
+		return 1;
+	}
+
+	Common::Filename mohawkFilename = Common::Filename(argv[archiveArg]);
+
+	if (mohawkFilename.exists()) {
+		printf ("File \'%s\' already exists!\n", argv[archiveArg]);
+		return 1;
+	}
+
+	Common::File *mohawkFile = new Common::File(mohawkFilename, "wb+");
+	if (!mohawkFile->isOpen()) {
+		printf("Could not open Mohawk Archive \'%s\' for output\n", argv[archiveArg]);
+		mohawkFile->close();
+		return 1;
+	}
+
+	initMohawkArchive();
+
+	// Allocate a buffer for the output
+	outputBuffer = (byte *)malloc(MAX_BUF_SIZE);
+
+	// Loop over remaining parameters, treating them as resource filenames
+	for (int i = archiveArg + 1; i < argc; i++) {
+		printf("Resource %d : \"%s\"\n", i - archiveArg - 1, argv[i]);
+
+		Common::Filename resourceFile = Common::Filename(argv[i]);
+
+		if (!resourceFile.exists()) {
+			printf("Can not open resource file \"%s\"\n", argv[i]);
+			return 1;
+		}
+
+		if (!resourceFile.hasExtension("bin")) {
+			printf("Resource file \"%s\" not in raw binary format\n", argv[i]);
+			return 1;
+		}
+
+		char resourceFilename[100];
+		strncpy(resourceFilename, resourceFile.getName().c_str(), sizeof(resourceFilename));
+
+		// Parse for file index, Resource Type, Resource Id and Name
+		int fileIndex = atoi(Common::String(resourceFilename, 4).c_str());
+		printf("fileIndex : %d\n", fileIndex);
+
+		if (resourceFilename[4] != '_')
+			printf("Filename format mismatch\n");
+
+		unsigned int fileFlags;
+		sscanf(resourceFilename+5, "%02x", &fileFlags);
+		printf("fileFlags : 0x%02x\n", fileFlags);
+
+		if (resourceFilename[7] != '_')
+			printf("Filename format mismatch\n");
+
+		Common::String resourceTag = Common::String(resourceFilename+8, 4);
+		printf("resourceTag : \"%s\"\n", resourceTag.c_str());
+
+		if (resourceFilename[12] != '_')
+			printf("Filename format mismatch\n");
+
+		int nameStart = 13;
+		while (resourceFilename[nameStart] != '\0' && resourceFilename[nameStart] != '_')
+			nameStart++;
+
+		int resourceId = atoi(Common::String(resourceFilename+13, nameStart-12).c_str());
+		printf("resourceId : %d\n", resourceId);
+
+		Common::String resourceName;
+		if (resourceFilename[nameStart] == '_')
+			resourceName = Common::String(resourceFilename+nameStart+1, strlen(resourceFilename));
+		printf("resourceName : \"%s\"\n", resourceName.c_str());
+
+		Common::File *resourceIn = new Common::File(resourceFile, "rb");
+		if (!resourceIn->isOpen()) {
+			printf("Could not open file \"%s\"\n", resourceFile.getName().c_str());
+			delete resourceIn;
+			return 1;
+		}
+
+		addFileToMohawkArchive(fileIndex, (byte) fileFlags, resourceTag.c_str(), resourceId, resourceName.c_str(), resourceIn->size());
+
+		resourceIn->close();
+		delete resourceIn;
+	}
+
+	writeMohawkArchive(argc, argv, archiveArg, mohawkFile);
+
+	printf("Done!\n");
+	free(outputBuffer);
+	mohawkFile->close();
+	delete mohawkFile;
+	return 0;
+}


Property changes on: tools/trunk/engines/mohawk/construct_mohawk.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev 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