[Scummvm-cvs-logs] SF.net SVN: scummvm:[49252] tools/branches/gsoc2010-decompiler

pidgeot at users.sourceforge.net pidgeot at users.sourceforge.net
Thu May 27 00:25:44 CEST 2010


Revision: 49252
          http://scummvm.svn.sourceforge.net/scummvm/?rev=49252&view=rev
Author:   pidgeot
Date:     2010-05-26 22:25:43 +0000 (Wed, 26 May 2010)

Log Message:
-----------
Simple disassembler, code clean-up

Added a SimpleDisassembler class to provide a wrapper for instruction 
sets with instructions of the form "opcode params".
Cleaned up decompiler driver. Added code for engine-specific 
instantiation (just disassembler for now). Added listing of engines.
Added generic dump to file to Disassembler.
Renamed executable to avoid filename conflict on *nix.
Minor bug fixes.

Modified Paths:
--------------
    tools/branches/gsoc2010-decompiler/Makefile.common
    tools/branches/gsoc2010-decompiler/decompiler/decompiler.cpp
    tools/branches/gsoc2010-decompiler/decompiler/disassembler.cpp
    tools/branches/gsoc2010-decompiler/decompiler/disassembler.h
    tools/branches/gsoc2010-decompiler/decompiler/instruction.h
    tools/branches/gsoc2010-decompiler/decompiler/objectFactory.h

Added Paths:
-----------
    tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.cpp
    tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.h
    tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.cpp
    tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.h

Modified: tools/branches/gsoc2010-decompiler/Makefile.common
===================================================================
--- tools/branches/gsoc2010-decompiler/Makefile.common	2010-05-26 22:05:51 UTC (rev 49251)
+++ tools/branches/gsoc2010-decompiler/Makefile.common	2010-05-26 22:25:43 UTC (rev 49252)
@@ -59,7 +59,7 @@
 	construct_mohawk$(EXEEXT) \
 	degob$(EXEEXT) \
 	scummvm-tools-cli$(EXEEXT) \
-	decompiler$(EXEEXT)
+	decompile$(EXEEXT)
 
 ifdef USE_FREETYPE
 ifdef USE_ICONV
@@ -118,7 +118,7 @@
 	scummvm-tools \
 	scummvm-tools-cli \
 	sword2_clue \
-	decompiler
+	decompile
 
 
 decine_OBJS := engines/cine/decine.o
@@ -257,11 +257,14 @@
 	$(tools_OBJS)
 scummvm-tools-cli_LIBS := $(LIBS)
 
-decompiler_OBJS := \
+decompile_OBJS := \
+	common/file.o \
 	decompiler/decompiler.o \
-	common/file.o
+	decompiler/disassembler.o \
+	decompiler/simple_disassembler.o \
+	decompiler/unknown_opcode.o
 
-decompiler_LIBS := \
+decompile_LIBS := \
 	-lboost_program_options	
 
 # Make base/version.o depend on all other object files. This way if anything is

Modified: tools/branches/gsoc2010-decompiler/decompiler/decompiler.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/decompiler.cpp	2010-05-26 22:05:51 UTC (rev 49251)
+++ tools/branches/gsoc2010-decompiler/decompiler/decompiler.cpp	2010-05-26 22:25:43 UTC (rev 49252)
@@ -25,53 +25,80 @@
 
 #include "objectFactory.h"
 
-using namespace std;
-using namespace boost::program_options;
+#include "disassembler.h"
 
+namespace po = boost::program_options;
+
+#define ENGINE(id, description, disasmClass) engines[std::string(id)] = description; disassemblerFactory.addEntry<disasmClass>(std::string(id));
+
 int main(int argc, char** argv) {
-	options_description visible("Options");
-	visible.add_options()
-		("help", "Produce this help message.")
-		("engine", value<string>(), "Engine the script originates from.")
-		("list", "List the supported engines.");
+	try	{
+		std::map<std::string, std::string> engines;
+		ObjectFactory<Disassembler> disassemblerFactory;
 
-	options_description args("");
-	args.add(visible).add_options()
-		("inputfile", value<string>(), "Input file");
+		po::options_description visible("Options");
+		visible.add_options()
+			("help", "Produce this help message.")
+			("engine", po::value<std::string>(), "Engine the script originates from.")
+			("list", "List the supported engines.")
+			("dump-disassembly", po::value<std::string>(), "Dump the disassembly to a specified file.");
 
-	positional_options_description filename;
-	filename.add("inputfile", -1);	
+		po::options_description args("");
+		args.add(visible).add_options()
+			("input-file", po::value<std::string>(), "Input file");
 
-	variables_map vm;
-	try {
-		store(command_line_parser(argc, argv).options(args).positional(filename).run(), vm);
-		notify(vm);    
-	} catch (std::exception& e) {
-		std::cout << e.what();
-	}
+		po::positional_options_description fileArg;
+		fileArg.add("input-file", -1);	
+
+		po::variables_map vm;
+		try {
+			po::store(po::command_line_parser(argc, argv).options(args).positional(fileArg).run(), vm);
+			po::notify(vm);    
+		} catch (std::exception& e) {
+			std::cout << e.what();
+		}
 	
-	if (vm.count("help") || !vm.count("inputfile")) {
-		cout << "Usage: " << argv[0] << " [option...] file" << endl << endl;
-		cout << args << "\n";
-		return 1;
-	}
+		if (vm.count("list")) {
+			std::cout << "Available engines:" << "\n";
 
-	if (vm.count("list")) {
-		//TODO
-		cout << "Listing of engines is not yet implemented." << "\n";
-		return 0;
-	}
+			std::map<std::string, std::string>::iterator it;
+			for (it = engines.begin(); it != engines.end(); it++)
+				std::cout << (*it).first << " " << (*it).second << "\n";
+		
+			return 0;
+		}
 
-	if (!vm.count("engine")) {
-		cout << "Engine must be specified." << "\n";
-		return 2;
-	} else {
-		cout << "Engine selected: " <<	vm["engine"].as<string>() << "\n";
-	}
+		if (vm.count("help") || !vm.count("input-file")) {
+			std::cout << "Usage: " << argv[0] << " [option...] file" << "\n";
+			std::cout << args << "\n";
+			return 1;
+		}
+	
+		if (!vm.count("engine")) {
+			std::cout << "Engine must be specified." << "\n";
+			return 2;
+		} else if (engines.find(vm["engine"].as<std::string>()) == engines.end()) {
+			std::cout << "Unknown engine." << "\n";
+			return 2;
+		}
 
-	cout << "Input file is " << vm["inputfile"].as<string>() << "\n";
+		std::string engine = vm["engine"].as<std::string>();
+		std::string inputFile = vm["input-file"].as<std::string>();
 
-	//TODO: Process file
+		//TODO: Process file
+		Disassembler* disassembler = disassemblerFactory.create(engine);
+		disassembler->open(inputFile.c_str());
 
+		std::vector<Instruction> insts = disassembler->disassemble();
+		if (vm.count("dump-disassembly")) {
+			disassembler->dumpDisassembly(vm["dump-disassembly"].as<std::string>().c_str());
+		}
+
+		delete disassembler;
+	} catch (std::exception& e) {
+		std::cout << e.what();
+		return 3;
+	}
+
 	return 0;
 }

Modified: tools/branches/gsoc2010-decompiler/decompiler/disassembler.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/disassembler.cpp	2010-05-26 22:05:51 UTC (rev 49251)
+++ tools/branches/gsoc2010-decompiler/decompiler/disassembler.cpp	2010-05-26 22:25:43 UTC (rev 49252)
@@ -22,6 +22,49 @@
 
 #include "disassembler.h"
 
-void Disassembler::open(char *filename) {
-	f.open(filename);
+void Disassembler::open(const char *filename) {
+	_f.open(filename, "rb");
 }
+
+void Disassembler::dumpDisassembly(const char *filename) {
+	Common::File _output;
+	_output.open(filename, "w");
+
+	char* buf;
+	int length;
+
+	for (size_t i = 0; i < _insts.size(); i++)
+	{
+		Instruction inst = _insts[i];
+		length = sprintf(buf, "%08x: %s ",inst._address, inst._name.c_str());
+		for (size_t j = 0; j < inst._params.size(); j++)
+		{
+			Parameter p = inst._params[j];
+			if (j != 0)
+				length += sprintf(&buf[length], ", ");
+			switch(p._type)
+			{
+				case kSByte:
+					length += sprintf(&buf[length], "%d", p._sbyte);
+					break;
+				case kByte:
+					length += sprintf(&buf[length], "%u", p._byte);
+					break;					
+				case kShort:
+					length += sprintf(&buf[length], "%d", p._short);
+					break;					
+				case kUShort:
+					length += sprintf(&buf[length], "%u", p._ushort);
+					break;					
+				case kInt:
+					length += sprintf(&buf[length], "%d", p._int);
+					break;					
+				case kUInt:
+					length += sprintf(&buf[length], "%u", p._uint);
+					break;					
+			}
+		}
+		buf[length] = '\n';
+		_output.write(buf, length + 1);
+	}
+}

Modified: tools/branches/gsoc2010-decompiler/decompiler/disassembler.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/disassembler.h	2010-05-26 22:05:51 UTC (rev 49251)
+++ tools/branches/gsoc2010-decompiler/decompiler/disassembler.h	2010-05-26 22:25:43 UTC (rev 49252)
@@ -27,22 +27,33 @@
 
 #include "instruction.h"
 #include "common/file.h"
+#include "unknown_opcode.h"
 
 class Disassembler {
 protected:
-	Common::File f; ///<Used to perform file I/O.
+	Common::File _f; ///<Used to perform file I/O.
+	std::vector<Instruction> _insts; ///<Container for disassembled instructions.
+	uint32 _addressBase; ///<Base address where the script starts.		
 
 public:
+	virtual ~Disassembler() {};
+
 	/**
 	 * Open a file for disassembly.		
-	 * @param filename 
+	 * @param filename The file to disassemble. 
 	 */
-	void open(char *filename);
+	void open(const char *filename);
 
 	/**
 	 * Disassembles a file.
 	 */
 	virtual std::vector<Instruction> disassemble() = 0;
+
+	/**
+	 * Outputs the disassembly to a file.
+	 * @param filename The file to output the disassembly to.
+	 */
+	virtual void dumpDisassembly(const char *filename);
 };
 
 #endif

Modified: tools/branches/gsoc2010-decompiler/decompiler/instruction.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/instruction.h	2010-05-26 22:05:51 UTC (rev 49251)
+++ tools/branches/gsoc2010-decompiler/decompiler/instruction.h	2010-05-26 22:25:43 UTC (rev 49252)
@@ -23,6 +23,7 @@
 #ifndef DEC_INSTRUCTION_H
 #define DEC_INSTRUCTION_H
 
+#include <string>
 #include <vector>
 
 #include "common/scummsys.h"
@@ -74,7 +75,7 @@
 struct Instruction {
 	uint32 _address; ///<The instruction address.
 	int16 _stackChange; ///<How much this instruction changes the stack pointer by.
-	char *_name; ///<The instruction name (opcode name).
+	std::string _name; ///<The instruction name (opcode name).
 	InstType _type; ///<The instruction type.
 	std::vector<Parameter> _params; ///<Array of parameters used for the instruction.
 };

Modified: tools/branches/gsoc2010-decompiler/decompiler/objectFactory.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/objectFactory.h	2010-05-26 22:05:51 UTC (rev 49251)
+++ tools/branches/gsoc2010-decompiler/decompiler/objectFactory.h	2010-05-26 22:25:43 UTC (rev 49252)
@@ -46,12 +46,13 @@
 	typedef BaseType *(*CreateFunc)(); ///<Function pointer to the object creation function.
 	std::map<std::string, CreateFunc> _registry; ///<Map from an identifier to a creation function.
 
+public:
 	/**
 	 * Register a new entry.
 	 * @param name The name to register the class under.
 	 */
 	template<typename Type>
-	void addEntry(std::string& name)	{
+	void addEntry(std::string name) {
 		_registry[name] = &createObject<BaseType, Type>;
 	}
 

Added: tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.cpp	                        (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.cpp	2010-05-26 22:25:43 UTC (rev 49252)
@@ -0,0 +1,76 @@
+/* ScummVM Tools
+* Copyright (C) 2010 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 "simple_disassembler.h"
+
+void SimpleDisassembler::readParams(Instruction *inst, char *typeString)
+{
+	while (*typeString)
+	{
+		Parameter p;
+		switch (*typeString)
+		{
+		case 'b': //signed byte
+			p._type = kSByte;
+			p._sbyte = _f.readChar();
+			break;
+		case 'B': //unsigned byte
+			p._type = kByte;
+			p._byte = _f.readByte();
+			break;
+		case 's': //16-bit integer (short), little-endian
+			p._type = kShort;
+			p._short = _f.readSint16LE();
+			break;
+		case 'S': //16-bit integer (short), big-endian
+			p._type = kShort;
+			p._short = _f.readSint16BE();
+			break;
+		case 'w': //16-bit integer (word), little-endian
+			p._type = kUShort;
+			p._ushort = _f.readUint16LE();
+			break;
+		case 'W': //16-bit integer (word), big-endian
+			p._type = kUShort;
+			p._ushort = _f.readUint16BE();
+			break;
+		case 'i': //32-bit integer (int), little-endian
+			p._type = kInt;
+			p._int = _f.readSint32LE();
+			break;
+		case 'I': //32-bit integer (int), big-endian
+			p._type = kInt;
+			p._int = _f.readSint32BE();
+			break;
+		case 'd': //32-bit integer (dword), little-endian
+			p._type = kUInt;
+			p._uint = _f.readUint32LE();
+			break;
+		case 'D': //32-bit integer (dword), big-endian
+			p._type = kUInt;
+			p._uint = _f.readUint32BE();
+			break;
+		}
+		inst->_params.push_back(p);
+		typeString++;
+	}
+}


Property changes on: tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.h	                        (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.h	2010-05-26 22:25:43 UTC (rev 49252)
@@ -0,0 +1,82 @@
+/* ScummVM Tools
+* Copyright (C) 2010 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 DEC_SIMPLE_DISASSEMBLER_H
+#define DEC_SIMPLE_DISASSEMBLER_H
+
+#include "disassembler.h"
+
+/**
+ * Simple disassembler acting as a base for instruction sets only consisting of simple instructions (opcode params...).
+ */
+class SimpleDisassembler : public Disassembler
+{
+protected:
+	uint32 _address; ///<Variable to maintain the current address.
+
+	/**
+	 * Read parameters and associate them with an instruction.
+	 * @param inst Pointer to the instruction to associate the parameters with.
+	 * @param typeString NUL-terminated string describing the type of each parameter.
+	 */
+	void readParams(Instruction *inst, char *typeString);
+};
+
+#define INC_ADDR _address++;
+#define ADD_INST _insts.push_back(Instruction());
+#define LAST_INST (_insts[insts.size()-1])
+
+#define START_OPCODES \
+	while (!_f.eos()) { \
+		uint8 opcode = _f.readByte(); \
+		switch (opcode) {
+#define END_OPCODES \
+		default: \
+			throw UnknownOpcodeException(_address, opcode);\
+		} \
+		INC_ADDR; \
+	}
+
+#define OPCODE_BASE(val) case val:
+
+#define OPCODE(val, name, category, stackChange, params) \
+	OPCODE_BASE(val)\
+		ADD_INST; \
+		LAST_INST._address = _address; \
+		LAST_INST._stackChange = stackChange; \
+		LAST_INST._name = std::string(name); \
+		LAST_INST._type = category; \
+		readParams(LAST_INST, params); \
+		break;
+
+#define START_SUBOPCODE(val) \
+	OPCODE_BASE(val) \
+		uint8 opcode = _f.readByte(); \
+		switch (opcode) {
+#define END_SUBOPCODE \
+		default: \
+			throw UnknownOpcodeException(_address, opcode);\
+		} \
+		INC_ADDR; \
+		break;
+
+#endif


Property changes on: tools/branches/gsoc2010-decompiler/decompiler/simple_disassembler.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.cpp	                        (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.cpp	2010-05-26 22:25:43 UTC (rev 49252)
@@ -0,0 +1,35 @@
+/* ScummVM Tools
+* Copyright (C) 2010 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 "unknown_opcode.h"
+
+UnknownOpcodeException::UnknownOpcodeException(uint32 address, uint8 opcode)
+{
+	_address = address;
+	_opcode = opcode;
+}
+
+const char* UnknownOpcodeException::what() throw()
+{
+	sprintf(_buf, "Unknown opcode (address: %08x, opcode: %02x)", _address, _opcode);
+	return _buf;
+}


Property changes on: tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.h	                        (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.h	2010-05-26 22:25:43 UTC (rev 49252)
@@ -0,0 +1,52 @@
+/* ScummVM Tools
+* Copyright (C) 2010 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 DEC_UNKNOWN_OPCODE_H
+#define DEC_UNKNOWN_OPCODE_H
+
+#include <exception>
+
+#include "common/scummsys.h"
+
+/**
+ * Exception representing an unknown opcode.
+ */
+class UnknownOpcodeException : public std::exception
+{
+	uint32 _address; ///<Address where the invalid opcode was found.
+	uint8 _opcode; ///<The value of the invalid opcode.
+	char _buf[255];	///<Buffer for formatting the error message.
+
+	/**
+	 * Constructor for UnknownOpcodeException.
+	 * @param address Address where the invalid opcode was found.
+	 * @param opcode The value of the invalid opcode.
+	 */
+	UnknownOpcodeException(uint32 address, uint8 opcode);
+
+	/**
+	 * Description of the exception.
+	 */
+	virtual const char* what() throw();
+};
+
+#endif


Property changes on: tools/branches/gsoc2010-decompiler/decompiler/unknown_opcode.h
___________________________________________________________________
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