[Scummvm-cvs-logs] SF.net SVN: scummvm:[51040] tools/branches/gsoc2010-decompiler/decompiler
pidgeot at users.sourceforge.net
pidgeot at users.sourceforge.net
Tue Jul 20 00:50:06 CEST 2010
Revision: 51040
http://scummvm.svn.sourceforge.net/scummvm/?rev=51040&view=rev
Author: pidgeot
Date: 2010-07-19 22:50:06 +0000 (Mon, 19 Jul 2010)
Log Message:
-----------
Prototype of actual SCUMMv6 code generation
Currently crashes, committing to do valgrind testing on Linux
Modified Paths:
--------------
tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp
tools/branches/gsoc2010-decompiler/decompiler/codegen.h
tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.cpp
tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.h
Modified: tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp 2010-07-19 22:11:06 UTC (rev 51039)
+++ tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp 2010-07-19 22:50:06 UTC (rev 51040)
@@ -37,10 +37,19 @@
return this;
EntryPtr dupEntry = new DupEntry(++dupindex);
- output << this << " = " << dupEntry;
+ output << dupEntry << " = " << this;
return dupEntry;
}
+std::string CodeGenerator::indentString(std::string s) {
+ std::stringstream stream;
+ std::string indent(kIndentAmount, ' ');
+ for (uint i = 0; i < _indentLevel; i++)
+ stream << indent;
+ stream << s;
+ return stream.str();
+}
+
CodeGenerator::CodeGenerator(Engine *engine, std::ostream &output) : _output(output) {
_engine = engine;
}
@@ -91,6 +100,36 @@
}
}
+void CodeGenerator::addOutputLine(std::string s) {
+ _curGroup->_code.push_back(indentString(s));
+}
+
+void CodeGenerator::writeAssignment(EntryPtr dst, EntryPtr src) {
+ std::stringstream s;
+ s << dst << " = " << src << ";";
+ addOutputLine(s.str());
+}
+
void CodeGenerator::process(GraphVertex v) {
- // TODO
+ // TODO: Add keyword output
+ _curGroup = GET(v);
+ ConstInstIterator it = _curGroup->_start;
+ do {
+ switch (it->_type) {
+ // We handle plain dups here because their behavior should be identical across instruction sets and this prevents implementation error.
+ case kDup:
+ {
+ std::stringstream s;
+ EntryPtr p = _stack.top()->dup(s);
+ if (s.str().length() > 0)
+ addOutputLine(s.str());
+ _stack.pop();
+ _stack.push(p);
+ _stack.push(p);
+ break;
+ }
+ default:
+ processInst(*it);
+ }
+ } while (++it != _curGroup->_end);
}
Modified: tools/branches/gsoc2010-decompiler/decompiler/codegen.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/codegen.h 2010-07-19 22:11:06 UTC (rev 51039)
+++ tools/branches/gsoc2010-decompiler/decompiler/codegen.h 2010-07-19 22:50:06 UTC (rev 51040)
@@ -102,7 +102,6 @@
}
};
-
namespace boost {
/**
@@ -122,7 +121,6 @@
} // End of namespace boost
-
/**
* Stack entry containing an integer.
*/
@@ -257,6 +255,8 @@
*/
typedef std::stack<EntryPtr> Stack;
+const int kIndentAmount = 2; ///< How many spaces to use for each indent.
+
/**
* Base class for code generators.
*/
@@ -275,14 +275,39 @@
protected:
std::ostream &_output; ///< The std::ostream to output the code to.
Stack _stack; ///< The stack currently being processed.
+ uint _indentLevel; ///< Indentation level.
+ GroupPtr _curGroup; ///< Pointer to the group currently being processed.
/**
* Processes an instruction.
*
* @param inst The instruction to process.
*/
- virtual void processInst(Instruction inst) = 0;
+ virtual void processInst(const Instruction inst) = 0;
+ /**
+ * Indents a string according to the current indentation level.
+ *
+ * @param s The string to indent.
+ * @result The indented string.
+ */
+ std::string indentString(std::string s);
+
+ /**
+ * Indents a line and adds it to the current group.
+ *
+ * @param s The string to add.
+ */
+ void addOutputLine(std::string s);
+
+ /**
+ * Generate an assignment statement.
+ *
+ * @param dst The variable being assigned to.
+ * @param src The value being assigned.
+ */
+ void writeAssignment(EntryPtr dst, EntryPtr src);
+
public:
virtual ~CodeGenerator() {};
Modified: tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.cpp 2010-07-19 22:11:06 UTC (rev 51039)
+++ tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.cpp 2010-07-19 22:50:06 UTC (rev 51040)
@@ -22,6 +22,249 @@
#include "codegen.h"
-void Scumm::v6::CodeGenerator::processInst(Instruction inst) {
+void Scumm::v6::CodeGenerator::processInst(const Instruction inst) {
// TODO
+
+ // This is just to keep some order in this code and have related opcodes near each other.
+ // It's not strictly necessary, because we can just look directly at the opcode, but this should be easier to read.
+ switch (inst._type) {
+ case kLoad:
+ switch (inst._opcode) {
+ case 0x00: // pushByte
+ _stack.push(new IntEntry(inst._params[0].getUnsigned(), true));
+ break;
+ case 0x01: // pushWord
+ _stack.push(new IntEntry(inst._params[0].getSigned(), false));
+ break;
+ case 0x02: // pushByteVar
+ case 0x03: // pushWordVar
+ _stack.push(new VarEntry(decodeVarName(inst._params[0].getUnsigned())));
+ break;
+ case 0x06: // byteArrayRead
+ // TODO
+ break;
+ case 0x07: // wordArrayRead
+ // TODO
+ break;
+ case 0x0A: // byteArrayIndexedRead
+ // TODO
+ break;
+ case 0x0B: // wordArrayIndexedRead
+ // TODO
+ break;
+ }
+ break;
+ case kStore:
+ switch (inst._opcode) {
+ case 0x42:
+ case 0x43:
+ {
+ EntryPtr p = new VarEntry(decodeVarName(inst._params[0].getUnsigned()));
+ writeAssignment(p, _stack.top());
+ _stack.pop();
+ break;
+ }
+ case 0x46:
+ break;
+ case 0x47:
+ break;
+ case 0x4A:
+ break;
+ case 0x4B:
+ break;
+ }
+ default:
+ {
+ std::stringstream s;
+ s << boost::format("Unknown opcode %X at address %08X") % inst._opcode % inst._address;
+ _curGroup->_code.push_back(indentString(s.str()));
+ break;
+ }
+ }
}
+
+const char *var_names[] = {
+ /* 0 */
+ NULL,
+ "VAR_EGO",
+ "VAR_CAMERA_POS_X",
+ "VAR_HAVE_MSG",
+ /* 4 */
+ "VAR_ROOM",
+ "VAR_OVERRIDE",
+ "VAR_MACHINE_SPEED",
+ NULL,
+ /* 8 */
+ "VAR_NUM_ACTOR",
+ "VAR_V6_SOUNDMODE",
+ "VAR_CURRENTDRIVE",
+ "VAR_TMR_1",
+ /* 12 */
+ "VAR_TMR_2",
+ "VAR_TMR_3",
+ NULL,
+ NULL,
+ /* 16 */
+ NULL,
+ "VAR_CAMERA_MIN_X",
+ "VAR_CAMERA_MAX_X",
+ "VAR_TIMER_NEXT",
+ /* 20 */
+ "VAR_VIRT_MOUSE_X",
+ "VAR_VIRT_MOUSE_Y",
+ "VAR_ROOM_RESOURCE",
+ "VAR_LAST_SOUND",
+ /* 24 */
+ "VAR_CUTSCENEEXIT_KEY",
+ "VAR_TALK_ACTOR",
+ "VAR_CAMERA_FAST_X",
+ "VAR_SCROLL_SCRIPT",
+ /* 28 */
+ "VAR_ENTRY_SCRIPT",
+ "VAR_ENTRY_SCRIPT2",
+ "VAR_EXIT_SCRIPT",
+ "VAR_EXIT_SCRIPT2",
+ /* 32 */
+ "VAR_VERB_SCRIPT",
+ "VAR_SENTENCE_SCRIPT",
+ "VAR_INVENTORY_SCRIPT",
+ "VAR_CUTSCENE_START_SCRIPT",
+ /* 36 */
+ "VAR_CUTSCENE_END_SCRIPT",
+ "VAR_CHARINC",
+ "VAR_WALKTO_OBJ",
+ "VAR_DEBUGMODE",
+ /* 40 */
+ "VAR_HEAPSPACE",
+ "VAR_ROOM_WIDTH",
+ "VAR_RESTART_KEY",
+ "VAR_PAUSE_KEY",
+ /* 44 */
+ "VAR_MOUSE_X",
+ "VAR_MOUSE_Y",
+ "VAR_TIMER",
+ "VAR_TMR_4",
+ /* 48 */
+ NULL,
+ "VAR_VIDEOMODE",
+ "VAR_MAINMENU_KEY",
+ "VAR_FIXEDDISK",
+ /* 52 */
+ "VAR_CURSORSTATE",
+ "VAR_USERPUT",
+ "VAR_ROOM_HEIGHT",
+ NULL,
+ /* 56 */
+ "VAR_SOUNDRESULT",
+ "VAR_TALKSTOP_KEY",
+ NULL,
+ "VAR_FADE_DELAY",
+ /* 60 */
+ "VAR_NOSUBTITLES",
+ "VAR_SAVELOAD_SCRIPT",
+ "VAR_SAVELOAD_SCRIPT2",
+ NULL,
+ /* 64 */
+ "VAR_SOUNDPARAM",
+ "VAR_SOUNDPARAM2",
+ "VAR_SOUNDPARAM3",
+ "VAR_INPUTMODE",
+ /* 68 */
+ "VAR_MEMORY_PERFORMANCE",
+ "VAR_VIDEO_PERFORMANCE",
+ "VAR_ROOM_FLAG",
+ "VAR_GAME_LOADED",
+ /* 72 */
+ "VAR_NEW_ROOM",
+ NULL,
+ "VAR_LEFTBTN_DOWN",
+ "VAR_RIGHTBTN_DOWN",
+ /* 76 */
+ "VAR_V6_EMSSPACE",
+ NULL,
+ NULL,
+ NULL,
+ /* 80 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ /* 84 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ /* 88 */
+ NULL,
+ NULL,
+ "VAR_GAME_DISK_MSG",
+ "VAR_OPEN_FAILED_MSG",
+ /* 92 */
+ "VAR_READ_ERROR_MSG",
+ "VAR_PAUSE_MSG",
+ "VAR_RESTART_MSG",
+ "VAR_QUIT_MSG",
+ /* 96 */
+ "VAR_SAVE_BTN",
+ "VAR_LOAD_BTN",
+ "VAR_PLAY_BTN",
+ "VAR_CANCEL_BTN",
+ /* 100 */
+ "VAR_QUIT_BTN",
+ "VAR_OK_BTN",
+ "VAR_SAVE_DISK_MSG",
+ "VAR_ENTER_NAME_MSG",
+ /* 104 */
+ "VAR_NOT_SAVED_MSG",
+ "VAR_NOT_LOADED_MSG",
+ "VAR_SAVE_MSG",
+ "VAR_LOAD_MSG",
+ /* 108 */
+ "VAR_SAVE_MENU_TITLE",
+ "VAR_LOAD_MENU_TITLE",
+ "VAR_GUI_COLORS",
+ "VAR_DEBUG_PASSWORD",
+ /* 112 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ /* 116 */
+ NULL,
+ "VAR_MAIN_MENU_TITLE",
+ "VAR_RANDOM_NR",
+ "VAR_TIMEDATE_YEAR",
+ /* 120 */
+ NULL,
+ "VAR_GAME_VERSION",
+ NULL,
+ "VAR_CHARSET_MASK",
+ /* 124 */
+ NULL,
+ "VAR_TIMEDATE_HOUR",
+ "VAR_TIMEDATE_MINUTE",
+ NULL,
+ /* 128 */
+ "VAR_TIMEDATE_DAY",
+ "VAR_TIMEDATE_MONTH",
+ NULL,
+ NULL,
+};
+
+std::string Scumm::v6::CodeGenerator::decodeVarName(uint16 varID) {
+ std::stringstream s;
+ if (!(varID & 0xF000)) {
+ uint16 var = varID & 0xFFF;
+ if (var < (sizeof(var_names) / sizeof(var_names[0])) && var_names[var] != NULL)
+ return var_names[var];
+ else
+ s << boost::format("var%d") % (varID & 0xFFF);
+ } else if (varID & 0x8000) {
+ s << boost::format("bitvar%d") % (varID & 0x7FFF);
+ } else if (varID & 0x4000) {
+ s << boost::format("localvar%d") % (varID & 0xFFF);
+ } else {
+ s << boost::format("?var?%d") % varID;
+ }
+ return s.str();
+}
Modified: tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.h 2010-07-19 22:11:06 UTC (rev 51039)
+++ tools/branches/gsoc2010-decompiler/decompiler/scummv6/codegen.h 2010-07-19 22:50:06 UTC (rev 51040)
@@ -33,10 +33,18 @@
* SCUMMv6 code generator.
*/
class CodeGenerator : public ::CodeGenerator {
+private:
+ /**
+ * Decode a variable ID to a name.
+ *
+ * @param varID The ID to decode.
+ * @return The decoded variable name.
+ */
+ std::string decodeVarName(uint16 varID);
public:
CodeGenerator(Engine *engine, std::ostream &output) : ::CodeGenerator(engine, output) {}
protected:
- void processInst(Instruction inst);
+ void processInst(const Instruction inst);
};
} // End of namespace v6
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