diff --git a/CMakeLists.txt b/CMakeLists.txt index 17d54e241..ff8340fd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -188,7 +188,8 @@ endif() option(BUILD_MWINTERPRETER "build standalone Morrowind script code interpreter" ON) if (BUILD_MWINTERPRETER) -set(TOOLS_MWINTERPRETER ${INTERPRETER} apps/mwinterpreter/main.cpp) +set(TOOLS_MWINTERPRETER ${INTERPRETER} apps/mwinterpreter/main.cpp + apps/mwinterpreter/context.cpp apps/mwinterpreter/context.hpp) add_executable(mwinterpreter ${TOOLS_MWINTERPRETER}) endif() diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp new file mode 100644 index 000000000..618abaf83 --- /dev/null +++ b/apps/mwinterpreter/context.cpp @@ -0,0 +1,94 @@ + +#include "context.hpp" + +#include +#include +#include +#include + +namespace SAInterpreter +{ + Context::Context (const std::string& filename) + { + std::ifstream file (filename.c_str()); + + if (!file.is_open()) + throw std::runtime_error ("can't open locals file: " + filename); + + std::size_t shortSize, longSize, floatSize; + + file >> shortSize >> longSize >> floatSize; + + mShorts.resize (shortSize, 0); + mLongs.resize (longSize, 0); + mFloats.resize (floatSize, 0.0); + + std::size_t size = shortSize + longSize + floatSize; + + mNames.resize (size); + + for (std::size_t i=0; i> mNames[i]; + } + + int Context::getLocalShort (int index) const + { + assert (index>=0); + return mShorts.at (index); + } + + int Context::getLocalLong (int index) const + { + assert (index>=0); + return mLongs.at (index); + } + + float Context::getLocalFloat (int index) const + { + assert (index>=0); + return mFloats.at (index); + } + + void Context::setLocalShort (int index, int value) + { + assert (index>=0); + mShorts.at (index) = value; + } + + void Context::setLocalLong (int index, int value) + { + assert (index>=0); + mLongs.at (index) = value; + } + + void Context::setLocalFloat (int index, float value) + { + assert (index>=0); + mFloats.at (index) = value; + } + + void Context::report() + { + std::size_t i = 0; + + std::cout << "local shorts:" << std::endl; + + for (std::vector::const_iterator iter (mShorts.begin()); + iter!=mShorts.end(); ++iter) + std::cout << mNames[i++] << ": " << *iter << std::endl; + + std::cout << "local longs:" << std::endl; + + for (std::vector::const_iterator iter (mLongs.begin()); + iter!=mLongs.end(); ++iter) + std::cout << mNames[i++] << ": " << *iter << std::endl; + + std::cout << "local floats:" << std::endl; + + for (std::vector::const_iterator iter (mFloats.begin()); + iter!=mFloats.end(); ++iter) + std::cout << mNames[i++] << ": " << *iter << std::endl; + + } +} + diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp new file mode 100644 index 000000000..c3ab9bad7 --- /dev/null +++ b/apps/mwinterpreter/context.hpp @@ -0,0 +1,43 @@ +#ifndef SAINTERPRETER_CONTEXT_H_INCLUDED +#define SAINTERPRETER_CONTEXT_H_INCLUDED + +#include +#include + +#include +#include + +namespace SAInterpreter +{ + class Context : public Interpreter::Context + { + std::vector mShorts; + std::vector mLongs; + std::vector mFloats; + std::vector mNames; + + public: + + Context (const std::string& filename); + ///< Create context from file + /// \note A context for an integreted interpreter will typically not + /// configure at construction, but will offer a separate function. + + virtual int getLocalShort (int index) const; + + virtual int getLocalLong (int index) const; + + virtual float getLocalFloat (int index) const; + + virtual void setLocalShort (int index, int value); + + virtual void setLocalLong (int index, int value); + + virtual void setLocalFloat (int index, float value); + + void report(); + ///< Write state to std::cout + }; +} + +#endif diff --git a/apps/mwinterpreter/main.cpp b/apps/mwinterpreter/main.cpp index c0b0b4718..df1cbc1c5 100644 --- a/apps/mwinterpreter/main.cpp +++ b/apps/mwinterpreter/main.cpp @@ -9,14 +9,18 @@ #include #include +#include "context.hpp" + int main (int argc, char **argv) { try - { - Interpreter::Context context; - Interpreter::Interpreter interpreter (context); - + { std::string filename = argc>1 ? argv[1] : "test.mwscript"; + + std::string localfilename = filename + ".locals"; + + SAInterpreter::Context context (localfilename); + Interpreter::Interpreter interpreter (context); std::string codefilename = filename + ".code"; @@ -39,6 +43,8 @@ int main (int argc, char **argv) codefile.read (reinterpret_cast (&code[4]), size * sizeof (Interpreter::Type_Code)); interpreter.run (&code[0], size+4); + + context.report(); } catch (const std::exception &e) { diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 922dc0c70..582606c9c 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -5,7 +5,21 @@ namespace Interpreter { class Context { - + public: + + virtual ~Context() {} + + virtual int getLocalShort (int index) const = 0; + + virtual int getLocalLong (int index) const = 0; + + virtual float getLocalFloat (int index) const = 0; + + virtual void setLocalShort (int index, int value) = 0; + + virtual void setLocalLong (int index, int value) = 0; + + virtual void setLocalFloat (int index, float value) = 0; }; } diff --git a/components/interpreter/types.hpp b/components/interpreter/types.hpp index 28ad51dd1..2747d1447 100644 --- a/components/interpreter/types.hpp +++ b/components/interpreter/types.hpp @@ -7,6 +7,8 @@ namespace Interpreter typedef unsigned int Type_Data; // 32 bit + typedef short Type_Short; // 16 bit + typedef int Type_Integer; // 32 bit typedef float Type_Float; // 32 bit