[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