[Scummvm-cvs-logs] SF.net SVN: scummvm:[51824] tools/branches/gsoc2010-decompiler
pidgeot at users.sourceforge.net
pidgeot at users.sourceforge.net
Sat Aug 7 04:39:11 CEST 2010
Revision: 51824
http://scummvm.svn.sourceforge.net/scummvm/?rev=51824&view=rev
Author: pidgeot
Date: 2010-08-07 02:39:11 +0000 (Sat, 07 Aug 2010)
Log Message:
-----------
DECOMPILER: Code generation for KYRA
Modified Paths:
--------------
tools/branches/gsoc2010-decompiler/Makefile.common
tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp
tools/branches/gsoc2010-decompiler/decompiler/codegen.h
tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp
tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.cpp
tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.h
tools/branches/gsoc2010-decompiler/decompiler/stack.h
Added Paths:
-----------
tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp
tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h
Modified: tools/branches/gsoc2010-decompiler/Makefile.common
===================================================================
--- tools/branches/gsoc2010-decompiler/Makefile.common 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/Makefile.common 2010-08-07 02:39:11 UTC (rev 51824)
@@ -282,7 +282,8 @@
decompiler/scummv6/engine.o \
decompiler/scummv6/codegen.o \
decompiler/kyra/disassembler.o \
- decompiler/kyra/engine.o
+ decompiler/kyra/engine.o \
+ decompiler/kyra/codegen.o
decompile_LIBS := \
-lboost_program_options
Modified: tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/codegen.cpp 2010-08-07 02:39:11 UTC (rev 51824)
@@ -34,6 +34,14 @@
static int dupindex = 0;
+int32 IntEntry::getValue() {
+ return _val;
+}
+
+bool IntEntry::getSigned() {
+ return _isSigned;
+}
+
std::ostream &IntEntry::print(std::ostream &output) const {
if (_isSigned)
output << (int32)_val;
@@ -104,6 +112,10 @@
return new IntEntry(_val, _isSigned);
}
+std::string CodeGenerator::constructFuncSignature(const Function &func) {
+ return "";
+}
+
std::string CodeGenerator::indentString(std::string s) {
std::stringstream stream;
stream << std::string(kIndentAmount * _indentLevel, ' ') << s;
@@ -120,53 +132,68 @@
void CodeGenerator::generate(const Graph &g) {
_g = g;
- // Find entry point
- // FIXME: For simplicity, we simply treat the first group as the entry point, because that's how SCUMM works.
- // This should be changed later to allow for functions etc.
- VertexRange vr = boost::vertices(_g);
- GraphVertex entryPoint = *(vr.first);
- GroupPtr p = GET(entryPoint);
- while (p->_prev != NULL)
- p = p->_prev;
- entryPoint = p->_vertex;
+ for (FuncMap::iterator fn = _engine->_functions.begin(); fn != _engine->_functions.end(); ++fn)
+ {
+ _indentLevel = 0;
+ while (!_stack.empty())
+ _stack.pop();
+ GraphVertex entryPoint = fn->second._v;
+ std::string funcSignature = constructFuncSignature(fn->second);
+ bool printFuncSignature = !funcSignature.empty();
+ if (printFuncSignature) {
+ _curGroup = GET(entryPoint);
+ if (!(fn == _engine->_functions.begin()))
+ addOutputLine("");
+ addOutputLine(funcSignature, false, true);
+ }
- // DFS from entry point to process each vertex
- Stack<DFSEntry> dfsStack;
- std::set<GraphVertex> seen;
- dfsStack.push(DFSEntry(entryPoint, EntryStack()));
- seen.insert(entryPoint);
- while (!dfsStack.empty()) {
- DFSEntry e = dfsStack.pop();
- GroupPtr tmp = GET(e.first);
- _stack = e.second;
- GraphVertex v = e.first;
- process(v);
- OutEdgeRange r = boost::out_edges(v, _g);
- for (OutEdgeIterator i = r.first; i != r.second; ++i) {
- GraphVertex target = boost::target(*i, _g);
- if (seen.find(target) == seen.end()) {
- dfsStack.push(DFSEntry(target, _stack));
- seen.insert(target);
+ GroupPtr lastGroup = GET(entryPoint);
+
+ // DFS from entry point to process each vertex
+ Stack<DFSEntry> dfsStack;
+ std::set<GraphVertex> seen;
+ dfsStack.push(DFSEntry(entryPoint, EntryStack()));
+ seen.insert(entryPoint);
+ while (!dfsStack.empty()) {
+ DFSEntry e = dfsStack.pop();
+ GroupPtr tmp = GET(e.first);
+ if (tmp->_start->_address > lastGroup->_start->_address)
+ lastGroup = tmp;
+ _stack = e.second;
+ GraphVertex v = e.first;
+ process(v);
+ OutEdgeRange r = boost::out_edges(v, _g);
+ for (OutEdgeIterator i = r.first; i != r.second; ++i) {
+ GraphVertex target = boost::target(*i, _g);
+ if (seen.find(target) == seen.end()) {
+ dfsStack.push(DFSEntry(target, _stack));
+ seen.insert(target);
+ }
}
}
- }
- // Print output
- // TODO: Proper indenting
- p = GET(entryPoint);
- while (p != NULL) {
- for (std::vector<CodeLine>::iterator it = p->_code.begin(); it != p->_code.end(); ++it) {
- if (it->_unindentBefore /*&& _indentLevel != 0*/)
- _indentLevel--;
- _output << boost::format("%08X: %s") % p->_start->_address % indentString(it->_line) << std::endl;
- if (it->_indentAfter)
- _indentLevel++;
+ if (printFuncSignature) {
+ _curGroup = lastGroup;
+ addOutputLine("}", true, false);
}
- p = p->_next;
+
+ // Print output
+ // TODO: Proper indenting
+ GroupPtr p = GET(entryPoint);
+ while (p != NULL) {
+ for (std::vector<CodeLine>::iterator it = p->_code.begin(); it != p->_code.end(); ++it) {
+ if (it->_unindentBefore /*&& _indentLevel != 0*/)
+ _indentLevel--;
+ _output << boost::format("%08X: %s") % p->_start->_address % indentString(it->_line) << std::endl;
+ if (it->_indentAfter)
+ _indentLevel++;
+ }
+ p = p->_next;
+ }
+
+ if (_indentLevel != 0)
+ std::cerr << boost::format("WARNING: Indent level for function at %d ended at %d\n") % fn->first % _indentLevel;
}
-
- if (_indentLevel != 0)
- std::cerr << "WARNING: Indent level ended at " << _indentLevel << std::endl;
}
void CodeGenerator::addOutputLine(std::string s, bool unindentBefore, bool indentAfter) {
@@ -320,11 +347,15 @@
break;
}
break;
+ case kReturn:
+ // TODO: Allow specification of return value as part of return statement
+ addOutputLine("return;");
+ break;
case kSpecial:
{
_argList.clear();
bool returnsValue = (it->_codeGenData.find("r") == 0);
- std::string metadata = (!returnsValue ? it->_codeGenData : it->_codeGenData.substr(1) );
+ std::string metadata = (!returnsValue ? it->_codeGenData : it->_codeGenData.substr(1));
for (size_t i = 0; i < metadata.length(); i++)
processSpecialMetadata(*it, metadata[i]);
_stack.push(new CallEntry(it->_name, _argList));
Modified: tools/branches/gsoc2010-decompiler/decompiler/codegen.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/codegen.h 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/codegen.h 2010-08-07 02:39:11 UTC (rev 51824)
@@ -33,6 +33,8 @@
class Engine;
+class Function;
+
enum StackEntryType {
seInt,
seVar,
@@ -150,6 +152,10 @@
*/
IntEntry(uint32 val, bool isSigned) : StackEntry(seInt), _val(val), _isSigned(isSigned) { }
+ int32 getValue();
+
+ bool getSigned();
+
virtual std::ostream &print(std::ostream &output) const;
virtual EntryPtr dup(std::ostream &output);
@@ -336,7 +342,6 @@
*/
class CodeGenerator {
private:
- Engine *_engine; ///< Pointer to the Engine used for the script.
Graph _g; ///< The annotated graph of the script.
const ArgOrder _binOrder; ///< Order of operands for binary operations.
const ArgOrder _callOrder; ///< Order of operands for call arguments.
@@ -349,6 +354,7 @@
void process(GraphVertex v);
protected:
+ Engine *_engine; ///< Pointer to the Engine used for the script.
std::ostream &_output; ///< The std::ostream to output the code to.
EntryStack _stack; ///< The stack currently being processed.
uint _indentLevel; ///< Indentation level.
@@ -402,6 +408,13 @@
*/
void addArg(EntryPtr p);
+ /**
+ * Construct the signature for a function.
+ *
+ * @param func Reference to the function to construct the signature for.
+ */
+ virtual std::string constructFuncSignature(const Function &func);
+
public:
virtual ~CodeGenerator() { }
Modified: tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp 2010-08-07 02:39:11 UTC (rev 51824)
@@ -168,10 +168,16 @@
continue;
bool functionExists = false;
+ bool detectEndPoint = false;
for (FuncMap::iterator fn = _engine->_functions.begin(); fn != _engine->_functions.end(); ++fn) {
if (fn->first == it->_address) {
- if (fn->second._endIt == _insts.end())
+ if (fn->second._endIt == _insts.end()) {
return;
+ }
+ if (fn->second._startIt == fn->second._endIt) {
+ detectEndPoint = true;
+ break;
+ }
nextFunc = fn->second._endIt->_address;
functionExists = true;
}
@@ -180,12 +186,14 @@
if (functionExists)
continue;
- InEdgeRange ier = boost::in_edges(v, _g);
bool isEntryPoint = true;
- for (InEdgeIterator e = ier.first; e != ier.second; ++e) {
- // If an ingoing edge exists from earlier in the code, this is not a function entry point
- if (GET(boost::source(*e, _g))->_start->_address < gr->_start->_address)
- isEntryPoint = false;
+ if (!detectEndPoint) {
+ InEdgeRange ier = boost::in_edges(v, _g);
+ for (InEdgeIterator e = ier.first; e != ier.second; ++e) {
+ // If an ingoing edge exists from earlier in the code, this is not a function entry point
+ if (GET(boost::source(*e, _g))->_start->_address < gr->_start->_address)
+ isEntryPoint = false;
+ }
}
if (isEntryPoint) {
@@ -216,7 +224,14 @@
} else {
endInst = _insts.end();
}
- Function f(gr->_start, endInst);
+ Function f;
+ if (detectEndPoint) {
+ f = _engine->_functions[gr->_start->_address];
+ f._endIt = endInst;
+ } else {
+ f = Function(gr->_start, endInst);
+ f._name = "auto_";
+ }
f._v = find(it);
_engine->_functions[gr->_start->_address] = f;
if (!endPoint->_next)
Added: tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp 2010-08-07 02:39:11 UTC (rev 51824)
@@ -0,0 +1,209 @@
+/* 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 "codegen.h"
+#include "engine.h"
+
+std::string Kyra::CodeGenerator::constructFuncSignature(const Function &func) {
+ std::stringstream s;
+ s << func._name << "(";
+ for (uint32 i = 0; i != func._args; ++i) {
+ if (i != 0)
+ s << ", ";
+ s << "param" << (i+1);
+ }
+ s << ") {";
+ return s.str();
+}
+
+void Kyra::CodeGenerator::processInst(const Instruction inst) {
+ switch (inst._type) {
+ case kLoad:
+ switch (inst._opcode) {
+ case 2:
+ _stack.push(new VarEntry("retval"));
+ break;
+ case 3:
+ case 4:
+ _stack.push(new IntEntry(inst._params[0].getSigned(), true));
+ break;
+ case 5:
+ {
+ std::stringstream s;
+ s << boost::format("var%d") % inst._params[0].getSigned();
+ _stack.push(new VarEntry(s.str()));
+ }
+ break;
+ case 6:
+ {
+ std::stringstream s;
+ s << boost::format("localvar%d") % inst._params[0].getSigned();
+ _stack.push(new VarEntry(s.str()));
+ }
+ break;
+ case 7:
+ {
+ std::stringstream s;
+ s << boost::format("param%d") % inst._params[0].getSigned();
+ _stack.push(new VarEntry(s.str()));
+ }
+ break;
+ }
+ break;
+ case kStore:
+ switch (inst._opcode) {
+ case 8:
+ {
+ EntryPtr p = new VarEntry("retval");
+ writeAssignment(p, _stack.pop());
+ }
+ break;
+ case 9:
+ {
+ std::stringstream s;
+ s << boost::format("var%d") % inst._params[0].getSigned();
+ EntryPtr p = new VarEntry(s.str());
+ writeAssignment(p, _stack.pop());
+ }
+ break;
+ case 10:
+ {
+ std::stringstream s;
+ s << boost::format("localvar%d") % inst._params[0].getSigned();
+ EntryPtr p = new VarEntry(s.str());
+ writeAssignment(p, _stack.pop());
+ }
+ break;
+ case 11:
+ {
+ std::stringstream s;
+ s << boost::format("param%d") % inst._params[0].getSigned();
+ EntryPtr p = new VarEntry(s.str());
+ writeAssignment(p, _stack.pop());
+ }
+ break;
+ }
+ break;
+ case kStack:
+ if (inst._opcode == 12) {
+ for (int i = inst._params[0].getSigned(); i != 0; --i) {
+ if (!_stack.empty())
+ _stack.pop();
+ }
+ } else if (inst._opcode == 13) {
+ for (int i = 0; i != inst._params[0].getSigned(); ++i) {
+ std::stringstream s;
+ s << boost::format("localvar%d") % i;
+ _stack.push(new VarEntry(s.str()));
+ }
+ }
+ break;
+ case kCondJump:
+ switch (_curGroup->_type) {
+ case kIfCond:
+ case kWhileCond:
+ break;
+ case kDoWhileCond:
+ _stack.push(new UnaryOpEntry(_stack.pop(), "!"));
+ break;
+ default:
+ {
+ std::stringstream s;
+ s << boost::format("WARNING: Couldn't handle conditional jump at address %08X") % inst._address;
+ addOutputLine(s.str());
+ }
+ break;
+ }
+ break;
+ case kCall:
+ {
+ _argList.clear();
+ Function f = _engine->_functions.find(inst._params[0].getUnsigned())->second;
+ for (size_t i = 0; i < f._metadata.length(); i++)
+ processSpecialMetadata(inst, f._metadata[i]);
+ _stack.push(new CallEntry(f._name, _argList));
+ if (!f._retVal) {
+ std::stringstream stream;
+ stream << _stack.pop() << ";";
+ addOutputLine(stream.str());
+ } else {
+ EntryPtr p = new VarEntry("retval");
+ writeAssignment(p, _stack.pop());
+ }
+ break;
+ }
+ case kSpecial:
+ {
+ if (inst._opcode == 2)
+ return;
+ _argList.clear();
+ bool returnsValue = (inst._codeGenData.find("r") == 1);
+ std::string metadata = (!returnsValue ? inst._codeGenData.substr(1) : inst._codeGenData.substr(2));
+ for (size_t i = 0; i < metadata.length(); i++)
+ processSpecialMetadata(inst, metadata[i]);
+ _stack.push(new CallEntry(inst._name, _argList));
+ if (!returnsValue) {
+ std::stringstream stream;
+ stream << _stack.pop() << ";";
+ addOutputLine(stream.str());
+ } else {
+ EntryPtr p = new VarEntry("retval");
+ writeAssignment(p, _stack.pop());
+ }
+ break;
+ }
+ default:
+ {
+ std::stringstream s;
+ s << boost::format("WARNING: Unknown opcode %X at address %08X") % inst._opcode % inst._address;
+ addOutputLine(s.str());
+ }
+ break;
+ }
+}
+
+void Kyra::CodeGenerator::processSpecialMetadata(const Instruction inst, char c) {
+ switch (c) {
+ case '0':
+ _stackOffset = 0;
+ break;
+ case 'p':
+ addArg(_stack.peekPos(_stackOffset++));
+ break;
+ case 's':
+ {
+ EntryPtr p = _stack.peekPos(_stackOffset++);
+ if (p->_type == seInt) {
+ IntEntry *ie = (IntEntry *)p.get();
+ addArg(new StringEntry(((Kyra::Engine *)_engine)->_textStrings[ie->getValue()]));
+ } else {
+ EntryList idxs;
+ idxs.push_front(p);
+ addArg(new ArrayEntry("strings", idxs));
+ }
+ }
+ break;
+ default:
+ ::CodeGenerator::processSpecialMetadata(inst, c);
+ break;
+ }
+}
Property changes on: tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.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/kyra/codegen.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h 2010-08-07 02:39:11 UTC (rev 51824)
@@ -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_KYRA_CODEGEN_H
+#define DEC_KYRA_CODEGEN_H
+
+#include "../codegen.h"
+
+namespace Kyra {
+
+/**
+ * KYRA code generator.
+ */
+class CodeGenerator : public ::CodeGenerator {
+private:
+ int _stackOffset; ///< Running count of where in the stack to look for the next argument.
+public:
+ /**
+ * Constructor for Kyra::CodeGenerator.
+ *
+ * @param engine Pointer to the Engine used for the script.
+ * @param output The std::ostream to output the code to.
+ */
+ CodeGenerator(Engine *engine, std::ostream &output) : ::CodeGenerator(engine, output, kLIFO, kLIFO) {}
+protected:
+ void processInst(const Instruction inst);
+ virtual void processSpecialMetadata(const Instruction inst, char c);
+ std::string constructFuncSignature(const Function &func);
+};
+
+} // End of namespace Kyra
+
+#endif
Property changes on: tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Modified: tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp 2010-08-07 02:39:11 UTC (rev 51824)
@@ -33,225 +33,225 @@
static FunctionData kyra2FuncDesc[] = {
// 0x00
- { "o2_setCharacterFacingRefresh", "0ppp" },
- { "o2_setCharacterPos", "0ppp" },
- { "o2_defineObject", "0pspppp" },
- { "o2_refreshCharacter", "0pppp" },
+ { "o2_setCharacterFacingRefresh", "\xC0r0ppp" },
+ { "o2_setCharacterPos", "\xC0r0ppp" },
+ { "o2_defineObject", "\xC0r0pspppp" },
+ { "o2_refreshCharacter", "\xC0r0pppp" },
// 0x04
- { "o2_getCharacterX", "" },
- { "o2_getCharacterY", "" },
- { "o2_getCharacterFacing", "" },
- { "o2_getCharacterScene", "" },
+ { "o2_getCharacterX", "\xC0r" },
+ { "o2_getCharacterY", "\xC0r" },
+ { "o2_getCharacterFacing", "\xC0r" },
+ { "o2_getCharacterScene", "\xC0r" },
// 0x08
- { "o2_setSceneComment", "0s" },
- { "unk09", "0p" },
- { "unk0A", "0p" },
- { "o2_setCharacterAnimFrame", "0ppp" },
+ { "o2_setSceneComment", "\xC0r0s" },
+ { "unk09", "\xC0r0p" },
+ { "unk0A", "\xC0r0p" },
+ { "o2_setCharacterAnimFrame", "\xC0r0ppp" },
// 0x0c
- { "o2_setCharacterFacingOverwrite", "0p" },
- { "o2_trySceneChange", "0pppp" },
- { "o2_moveCharacter", "0ppp" },
- { "o2_customCharacterChat", "0spppp" },
+ { "o2_setCharacterFacingOverwrite", "\xC0r0p" },
+ { "o2_trySceneChange", "\xC0r0pppp" },
+ { "o2_moveCharacter", "\xC0r0ppp" },
+ { "o2_customCharacterChat", "\xC0r0spppp" },
// 0x10
- { "o2_soundFadeOut", "" },
- { "o2_showChapterMessage", "0pp" },
- { "o2_restoreTalkTextMessageBkgd", "" },
- { "o2_printString", "0spppp" },
+ { "o2_soundFadeOut", "\xC0r" },
+ { "o2_showChapterMessage", "\xC0r0pp" },
+ { "o2_restoreTalkTextMessageBkgd", "\xC0r" },
+ { "o2_printString", "\xC0r0spppp" },
// 0x14
- { "o2_wsaClose", "0p" },
- { "o2_backUpScreen", "0p" },
- { "o2_restoreScreen", "0p" },
- { "o2_displayWsaFrame", "0ppppppppp" },
+ { "o2_wsaClose", "\xC0r0p" },
+ { "o2_backUpScreen", "\xC0r0p" },
+ { "o2_restoreScreen", "\xC0r0p" },
+ { "o2_displayWsaFrame", "\xC0r0ppppppppp" },
// 0x18
- { "o2_displayWsaSequentialFramesLooping", "0pppppppp" },
- { "o2_wsaOpen", "0sp" },
- { "o2_displayWsaSequentialFrames", "0ppppppp" },
- { "o2_displayWsaSequence", "0pppppp" },
+ { "o2_displayWsaSequentialFramesLooping", "\xC0r0pppppppp" },
+ { "o2_wsaOpen", "\xC0r0sp" },
+ { "o2_displayWsaSequentialFrames", "\xC0r0ppppppp" },
+ { "o2_displayWsaSequence", "\xC0r0pppppp" },
// 0x1c
- { "o2_addItemToInventory", "0ppp" },
- { "o2_drawShape", "0ppppp" },
- { "o2_addItemToCurScene", "0ppp" },
- { "o2_limitMouseRange", "0pppp" },
+ { "o2_addItemToInventory", "\xC0r0ppp" },
+ { "o2_drawShape", "\xC0r0ppppp" },
+ { "o2_addItemToCurScene", "\xC0r0ppp" },
+ { "o2_limitMouseRange", "\xC0r0pppp" },
// 0x20
- { "o2_checkForItem", "0pp" },
- { "o2_loadSoundFile", "0p" },
- { "o2_removeSlotFromInventory", "0p" },
- { "o2_defineItem", "0pppp" },
+ { "o2_checkForItem", "\xC0r0pp" },
+ { "o2_loadSoundFile", "\xC0r0p" },
+ { "o2_removeSlotFromInventory", "\xC0r0p" },
+ { "o2_defineItem", "\xC0r0pppp" },
// 0x24
- { "o2_removeItemFromInventory", "0p" },
- { "o2_countItemInInventory", "0pp" },
- { "o2_countItemsInScene", "0p" },
- { "o1_queryGameFlag", "0p" },
+ { "o2_removeItemFromInventory", "\xC0r0p" },
+ { "o2_countItemInInventory", "\xC0r0pp" },
+ { "o2_countItemsInScene", "\xC0r0p" },
+ { "o1_queryGameFlag", "\xC0r0p" },
// 0x28
- { "o1_resetGameFlag", "0p" },
- { "o1_setGameFlag", "0p" },
- { "o1_setHandItem", "0p" },
- { "o1_removeHandItem", "" },
+ { "o1_resetGameFlag", "\xC0r0p" },
+ { "o1_setGameFlag", "\xC0r0p" },
+ { "o1_setHandItem", "\xC0r0p" },
+ { "o1_removeHandItem", "\xC0r" },
// 0x2c
- { "o1_getMouseState", "" },
- { "o1_hideMouse", "" },
- { "o2_addSpecialExit", "0ppppp" },
- { "o1_setMousePos", "0pp" },
+ { "o1_getMouseState", "\xC0r" },
+ { "o1_hideMouse", "\xC0r" },
+ { "o2_addSpecialExit", "\xC0r0ppppp" },
+ { "o1_setMousePos", "\xC0r0pp" },
// 0x30
- { "o1_showMouse", "" },
- { "o2_drawBox", "0ppppp" },
- { "o2_wipeDownMouseItem", "0ppp" },
- { "o2_getElapsedSecs", "" },
+ { "o1_showMouse", "\xC0r" },
+ { "o2_drawBox", "\xC0r0ppppp" },
+ { "o2_wipeDownMouseItem", "\xC0r0ppp" },
+ { "o2_getElapsedSecs", "\xC0r" },
// 0x34
- { "o2_getTimerDelay", "0p" },
- { "o1_playSoundEffect", "0p" },
- { "o2_delaySecs", "0p" },
- { "o2_delay", "0pp" },
+ { "o2_getTimerDelay", "\xC0r0p" },
+ { "o1_playSoundEffect", "\xC0r0p" },
+ { "o2_delaySecs", "\xC0r0p" },
+ { "o2_delay", "\xC0r0pp" },
// 0x38
- { "o2_dummy38", "" },
- { "o2_setTimerDelay", "0pp" },
- { "o2_setScaleTableItem", "0pp" },
- { "o2_setDrawLayerTableItem", "0pp" },
+ { "o2_dummy38", "\xC0r" },
+ { "o2_setTimerDelay", "\xC0r0pp" },
+ { "o2_setScaleTableItem", "\xC0r0pp" },
+ { "o2_setDrawLayerTableItem", "\xC0r0pp" },
// 0x3c
- { "o2_setCharPalEntry", "0pp" },
- { "o2_loadZShapes", "0p" },
- { "o2_drawSceneShape", "0pppp" },
- { "o2_drawSceneShapeOnPage", "0ppppp" },
+ { "o2_setCharPalEntry", "\xC0r0pp" },
+ { "o2_loadZShapes", "\xC0r0p" },
+ { "o2_drawSceneShape", "\xC0r0pppp" },
+ { "o2_drawSceneShapeOnPage", "\xC0r0ppppp" },
// 0x40
- { "o2_disableAnimObject", "0p" },
- { "o2_enableAnimObject", "0p" },
- { "o2_dummy42", "" },
- { "o2_loadPalette384", "0s" },
+ { "o2_disableAnimObject", "\xC0r0p" },
+ { "o2_enableAnimObject", "\xC0r0p" },
+ { "o2_dummy42", "\xC0r" },
+ { "o2_loadPalette384", "\xC0r0s" },
// 0x44
- { "o2_setPalette384", "" },
- { "o2_restoreBackBuffer", "0p" },
- { "o2_backUpInventoryGfx", "" },
- { "o2_disableSceneAnim", "0p" },
+ { "o2_setPalette384", "\xC0r" },
+ { "o2_restoreBackBuffer", "\xC0r0p" },
+ { "o2_backUpInventoryGfx", "\xC0r" },
+ { "o2_disableSceneAnim", "\xC0r0p" },
// 0x48
- { "o2_enableSceneAnim", "0p" },
- { "o2_restoreInventoryGfx", "" },
- { "o2_setSceneAnimPos2", "0ppp" },
- { "o2_update", "0p" },
+ { "o2_enableSceneAnim", "\xC0r0p" },
+ { "o2_restoreInventoryGfx", "\xC0r" },
+ { "o2_setSceneAnimPos2", "\xC0r0ppp" },
+ { "o2_update", "\xC0r0p" },
// 0x4c
- { "unk4C_palFade?", "0pp" },
- { "o2_fadeScenePal", "0pp" },
- { "o2_dummy4E", "" },
- { "o2_dummy4F", "" },
+ { "unk4C_palFade?", "\xC0r0pp" },
+ { "o2_fadeScenePal", "\xC0r0pp" },
+ { "o2_dummy4E", "\xC0r" },
+ { "o2_dummy4F", "\xC0r" },
// 0x50
- { "o2_enterNewScene", "0ppppp" },
- { "o2_switchScene", "0p" },
- { "o2_getShapeFlag1", "0pp" },
- { "o2_setPathfinderFlag", "0p" },
+ { "o2_enterNewScene", "\xC0r0ppppp" },
+ { "o2_switchScene", "\xC0r0p" },
+ { "o2_getShapeFlag1", "\xC0r0pp" },
+ { "o2_setPathfinderFlag", "\xC0r0p" },
// 0x54
- { "o2_getSceneExitToFacing", "0pp" },
- { "o2_setLayerFlag", "0p" },
- { "o2_setZanthiaPos", "0pp" },
- { "o2_loadMusicTrack", "0p" },
+ { "o2_getSceneExitToFacing", "\xC0r0pp" },
+ { "o2_setLayerFlag", "\xC0r0p" },
+ { "o2_setZanthiaPos", "\xC0r0pp" },
+ { "o2_loadMusicTrack", "\xC0r0p" },
// 0x58
- { "o1_playWanderScoreViaMap", "0pp" },
- { "o1_playSoundEffect", "0p" },
- { "o2_setSceneAnimPos", "0ppp" },
- { "o1_blockInWalkableRegion", "0pppp" },
+ { "o1_playWanderScoreViaMap", "\xC0r0pp" },
+ { "o1_playSoundEffect", "\xC0r0p" },
+ { "o2_setSceneAnimPos", "\xC0r0ppp" },
+ { "o1_blockInWalkableRegion", "\xC0r0pppp" },
// 0x5c
- { "o1_blockOutWalkableRegion", "0pppp" },
- { "unk5D", "0ppppp" },
- { "o2_setCauldronState", "0pp" },
- { "o2_showItemString", "0pp" },
+ { "o1_blockOutWalkableRegion", "\xC0r0pppp" },
+ { "unk5D", "\xC0r0ppppp" },
+ { "o2_setCauldronState", "\xC0r0pp" },
+ { "o2_showItemString", "\xC0r0pp" },
// 0x60
- { "o1_getRand", "0pp" },
- { "o2_isAnySoundPlaying", "" },
- { "o1_setDeathHandler", "0p" },
- { "o2_setDrawNoShapeFlag", "0p" },
+ { "o1_getRand", "\xC0r0pp" },
+ { "o2_isAnySoundPlaying", "\xC0r" },
+ { "o1_setDeathHandler", "\xC0r0p" },
+ { "o2_setDrawNoShapeFlag", "\xC0r0p" },
// 0x64
- { "o2_setRunFlag", "0p" },
- { "o2_showLetter", "0p" },
- { "o1_shakeScreen", "0pp" },
- { "o1_fillRect", "0pppppp" },
+ { "o2_setRunFlag", "\xC0r0p" },
+ { "o2_showLetter", "\xC0r0p" },
+ { "o1_shakeScreen", "\xC0r0pp" },
+ { "o1_fillRect", "\xC0r0pppppp" },
// 0x68
- { "o2_getKey", "" },
- { "unk69", "0pppp" },
- { "o2_playFireflyScore", "" },
- { "o2_waitForConfirmationClick", "0p" },
+ { "o2_getKey", "\xC0r" },
+ { "unk69", "\xC0r0pppp" },
+ { "o2_playFireflyScore", "\xC0r" },
+ { "o2_waitForConfirmationClick", "\xC0r0p" },
// 0x6c
- { "o2_encodeShape", "0ppppp" },
- { "o2_defineRoomEntrance", "0ppp" },
- { "o2_runAnimationScript", "0sppp" },
- { "o2_setSpecialSceneScriptRunTime", "0pp" },
+ { "o2_encodeShape", "\xC0r0ppppp" },
+ { "o2_defineRoomEntrance", "\xC0r0ppp" },
+ { "o2_runAnimationScript", "\xC0r0sppp" },
+ { "o2_setSpecialSceneScriptRunTime", "\xC0r0pp" },
// 0x70
- { "o2_defineSceneAnim", "0pppppppppppps" },
- { "o2_updateSceneAnim", "pp" },
- { "o2_updateSceneAnim", "pp" },
- { "o2_addToSceneAnimPosAndUpdate", "0ppp" },
+ { "o2_defineSceneAnim", "\xC0r0pppppppppppps" },
+ { "o2_updateSceneAnim", "\xC0r0pp" },
+ { "o2_updateSceneAnim", "\xC0r0pp" },
+ { "o2_addToSceneAnimPosAndUpdate", "\xC0r0ppp" },
// 0x74
- { "o2_useItemOnMainChar", "" },
- { "o2_startDialogue", "0p" },
- { "o2_randomSceneChat", "" },
- { "o2_setDlgIndex", "0p" },
+ { "o2_useItemOnMainChar", "\xC0r" },
+ { "o2_startDialogue", "\xC0r0p" },
+ { "o2_randomSceneChat", "\xC0r" },
+ { "o2_setDlgIndex", "\xC0r0p" },
// 0x78
- { "o2_getDlgIndex", "" },
- { "o2_defineScene", "0pspppppp" },
- { "o2_addCauldronStateTableEntry", "0pp" },
- { "o2_setCountDown", "0p" },
+ { "o2_getDlgIndex", "\xC0r" },
+ { "o2_defineScene", "\xC0r0pspppppp" },
+ { "o2_addCauldronStateTableEntry", "\xC0r0pp" },
+ { "o2_setCountDown", "\xC0r0p" },
// 0x7c
- { "o2_getCountDown", "" },
- { "o2_dummy7D", "" },
- { "o2_dummy7E", "" },
- { "o2_pressColorKey", "0p" },
+ { "o2_getCountDown", "\xC0r" },
+ { "o2_dummy7D", "\xC0r" },
+ { "o2_dummy7E", "\xC0r" },
+ { "o2_pressColorKey", "\xC0r0p" },
// 0x80
- { "o2_objectChat", "0sp" },
- { "o2_changeChapter", "0pp" },
- { "o2_getColorCodeFlag1", "" },
- { "o2_setColorCodeFlag1", "0p" },
+ { "o2_objectChat", "\xC0r0sp" },
+ { "o2_changeChapter", "\xC0r0pp" },
+ { "o2_getColorCodeFlag1", "\xC0r" },
+ { "o2_setColorCodeFlag1", "\xC0r0p" },
// 0x84
- { "o2_getColorCodeFlag2", "" },
- { "o2_setColorCodeFlag2", "0p" },
- { "o2_getColorCodeValue", "0p" },
- { "o2_setColorCodeValue", "0pp" },
+ { "o2_getColorCodeFlag2", "\xC0r" },
+ { "o2_setColorCodeFlag2", "\xC0r0p" },
+ { "o2_getColorCodeValue", "\xC0r0p" },
+ { "o2_setColorCodeValue", "\xC0r0pp" },
// 0x88
- { "o2_countItemInstances", "0p" },
- { "o2_removeItemFromScene", "0pp" },
- { "o2_initObject", "0p" },
- { "o2_npcChat", "0spp" }, // FIXME: Non-talkie metadata; talkie opcode is 0spp
+ { "o2_countItemInstances", "\xC0r0p" },
+ { "o2_removeItemFromScene", "\xC0r0pp" },
+ { "o2_initObject", "\xC0r0p" },
+ { "o2_npcChat", "\xC0r0spp" }, // FIXME: Non-talkie metadata; talkie opcode is 0spp
// 0x8c
- { "o2_deinitObject", "0p" },
- { "o2_playTimSequence", "0s" },
- { "o2_makeBookOrCauldronAppear", "0p" },
- { "o2_setSpecialSceneScriptState", "0p" },
+ { "o2_deinitObject", "\xC0r0p" },
+ { "o2_playTimSequence", "\xC0r0s" },
+ { "o2_makeBookOrCauldronAppear", "\xC0r0p" },
+ { "o2_setSpecialSceneScriptState", "\xC0r0p" },
// 0x90
- { "o2_clearSpecialSceneScriptState", "0p" },
- { "o2_querySpecialSceneScriptState", "0p" },
- { "o2_resetInputColorCode", "" },
- { "o2_setHiddenItemsEntry", "0pp" },
+ { "o2_clearSpecialSceneScriptState", "\xC0r0p" },
+ { "o2_querySpecialSceneScriptState", "\xC0r0p" },
+ { "o2_resetInputColorCode", "\xC0r" },
+ { "o2_setHiddenItemsEntry", "\xC0r0pp" },
// 0x94
- { "o2_getHiddenItemsEntry", "0p" },
- { "o2_mushroomEffect", "" },
- { "o2_wsaClose", "0p" },
- { "o2_meanWhileScene", "0p" },
+ { "o2_getHiddenItemsEntry", "\xC0r0p" },
+ { "o2_mushroomEffect", "\xC0r" },
+ { "o2_wsaClose", "\xC0r0p" },
+ { "o2_meanWhileScene", "\xC0r0p" },
// 0x98
- { "o2_customChat", "0spp" },
- { "o2_customChatFinish", "" },
- { "o2_setupSceneAnimation", "0pppppppppppps" },
- { "o2_stopSceneAnimation", "0pp" },
+ { "o2_customChat", "\xC0r0spp" },
+ { "o2_customChatFinish", "\xC0r" },
+ { "o2_setupSceneAnimation", "\xC0r0pppppppppppps" },
+ { "o2_stopSceneAnimation", "\xC0r0pp" },
// 0x9c
- { "o2_disableTimer", "0p" },
- { "o2_enableTimer", "0p" },
- { "o2_setTimerCountdown", "0pp" },
- { "o2_processPaletteIndex", "0pppppp" },
+ { "o2_disableTimer", "\xC0r0p" },
+ { "o2_enableTimer", "\xC0r0p" },
+ { "o2_setTimerCountdown", "\xC0r0pp" },
+ { "o2_processPaletteIndex", "\xC0r0pppppp" },
// 0xa0
- { "o2_updateTwoSceneAnims", "0pppp" },
- { "o2_getRainbowRoomData", "0p" },
- { "o2_drawSceneShapeEx", "0pppp" },
- { "o2_midiSoundFadeout", "" },
+ { "o2_updateTwoSceneAnims", "\xC0r0pppp" },
+ { "o2_getRainbowRoomData", "\xC0r0p" },
+ { "o2_drawSceneShapeEx", "\xC0r0pppp" },
+ { "o2_midiSoundFadeout", "\xC0r" },
// 0xa4
- { "o2_getSfxDriver", "" },
- { "o2_getVocSupport", "" },
- { "o2_getMusicDriver", "" },
- { "o2_setVocHigh", "0p" },
+ { "o2_getSfxDriver", "\xC0r" },
+ { "o2_getVocSupport", "\xC0r" },
+ { "o2_getMusicDriver", "\xC0r" },
+ { "o2_setVocHigh", "\xC0r0p" },
// 0xa8
- { "o2_getVocHigh", "" },
- { "o2_zanthiaChat", "0sp" },
- { "o2_isVoiceEnabled", "" },
- { "o2_isVoicePlaying", "" },
+ { "o2_getVocHigh", "\xC0r" },
+ { "o2_zanthiaChat", "\xC0r0sp" },
+ { "o2_isVoiceEnabled", "\xC0r" },
+ { "o2_isVoicePlaying", "\xC0r" },
// 0xac
- { "o2_stopVoicePlaying", "" },
- { "o2_getGameLanguage", "" },
- { "o2_demoFinale", "" },
- { "o2_dummyAF", "" }
+ { "o2_stopVoicePlaying", "\xC0r" },
+ { "o2_getGameLanguage", "\xC0r" },
+ { "o2_demoFinale", "\xC0r" },
+ { "o2_dummyAF", "\xC0r" }
};
IFFChunk::IFFChunk() {
@@ -326,7 +326,9 @@
uint16 numStrings = minTextOffset / 2;
#define posString(x) (char*)&_textChunk._data[READ_BE_UINT16(&((uint16 *)_textChunk._data)[(x)])]
for (uint16 i = 0; i < numStrings; ++i) {
- _engine->_textStrings.push_back(posString(i));
+ std::stringstream s;
+ s << "\"" << posString(i) << "\"";
+ _engine->_textStrings.push_back(s.str());
}
#undef posString
}
@@ -466,7 +468,7 @@
break;
case 16:
if (parameter == 0) {
- OPCODE_MD("boolCast", kUnaryOp, 0, false, false, "(bool)");
+ OPCODE_MD("boolNegate", kUnaryOp, 0, false, false, "!");
} else if (parameter == 1) {
OPCODE_MD("arithmeticNegate", kUnaryOp, 0, false, false,"-");
} else if (parameter == 2) {
@@ -555,12 +557,10 @@
addrMap[it->_address] = it;
std::sort(funcAddrs.begin(), funcAddrs.end());
- //Create ranges from entry points
+ // We only have the entry points, but the end points are not known, so create placeholder function entries
for (size_t i = 0; i < funcAddrs.size(); i++) {
- if (i == funcAddrs.size() - 1) // Last function
- _engine->_functions[funcAddrs[i]] = Function(addrMap[funcAddrs[i]], _insts.end());
- else
- _engine->_functions[funcAddrs[i]] = Function(addrMap[funcAddrs[i]], addrMap[funcAddrs[i+1]]);
+ _engine->_functions[funcAddrs[i]] = Function(addrMap[funcAddrs[i]], addrMap[funcAddrs[i]]);
+ _engine->_functions[funcAddrs[i]]._name = "global_";
}
// Correct jumps to functions so they're treated as calls
@@ -574,3 +574,4 @@
lastWasPushPos = (it->_name.compare("pushPos") == 0);
}
}
+
Modified: tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.cpp 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.cpp 2010-08-07 02:39:11 UTC (rev 51824)
@@ -22,6 +22,7 @@
#include "engine.h"
#include "disassembler.h"
+#include "codegen.h"
#include <iostream>
#include <sstream>
@@ -36,15 +37,15 @@
}
::CodeGenerator *Kyra::Engine::getCodeGenerator(std::ostream &output) {
- // TODO
- return NULL;
+ return new CodeGenerator(this, output);
}
void Kyra::Engine::postCFG(std::vector<Instruction> &insts, Graph g) {
// Add metadata to functions
for (FuncMap::iterator it = _functions.begin(); it != _functions.end(); ++it) {
std::stringstream s;
- s << boost::format("sub0x%X") % it->second._startIt->_address;
+ s << it->second._name << boost::format("sub0x%X") % it->second._startIt->_address;
+ it->second._name = s.str();
int maxArg = 0;
for (ConstInstIterator instIt = it->second._startIt; instIt != it->second._endIt; ++instIt) {
if (instIt->_name.compare("pushBPAdd") == 0) {
@@ -55,6 +56,9 @@
}
it->second._args = maxArg;
it->second._retVal = true;
+ std::stringstream md;
+ md << "0" << std::string(maxArg, 'p');
+ it->second._metadata = md.str();
}
}
Modified: tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.h 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/engine.h 2010-08-07 02:39:11 UTC (rev 51824)
@@ -39,7 +39,6 @@
uint32 getDestAddress(ConstInstIterator it) const;
::CodeGenerator *getCodeGenerator(std::ostream &output);
void postCFG(std::vector<Instruction> &insts, Graph g);
- bool supportsCodeGen() { return false; }
bool detectMoreFuncs();
std::vector<std::string> _textStrings;
Modified: tools/branches/gsoc2010-decompiler/decompiler/stack.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/stack.h 2010-08-07 01:27:14 UTC (rev 51823)
+++ tools/branches/gsoc2010-decompiler/decompiler/stack.h 2010-08-07 02:39:11 UTC (rev 51824)
@@ -79,7 +79,11 @@
* @param pos The number of items to skip on the stack.
* @return The desired item from the stack.
*/
- T &peekPos(size_t pos) { return _stack.at(pos); }
+ T &peekPos(size_t pos) {
+ if (pos >= _stack.size())
+ std::cerr << "WARNING: Looking outside stack\n";
+ return _stack.at(pos);
+ }
/**
* Return the item on the specificed stack position without removing it.
@@ -87,7 +91,11 @@
* @param pos The number of items to skip on the stack.
* @return The desired item from the stack.
*/
- const T &peekPos(size_t pos) const { return _stack.at(pos); }
+ const T &peekPos(size_t pos) const {
+ if (pos >= _stack.size())
+ std::cerr << "WARNING: Looking outside stack\n";
+ return _stack.at(pos);
+ }
};
#endif
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