diff --git a/apps/mwcompiler/context.cpp b/apps/mwcompiler/context.cpp index 72e3aa490..895e2c62a 100644 --- a/apps/mwcompiler/context.cpp +++ b/apps/mwcompiler/context.cpp @@ -7,5 +7,10 @@ namespace SACompiler { return true; } + + char Context::getGlobalType (const std::string& name) const + { + return ' '; + } } diff --git a/apps/mwcompiler/context.hpp b/apps/mwcompiler/context.hpp index 23188ecf2..be06bbca8 100644 --- a/apps/mwcompiler/context.hpp +++ b/apps/mwcompiler/context.hpp @@ -11,6 +11,9 @@ namespace SACompiler virtual bool canDeclareLocals() const; ///< Is the compiler allowed to declare local variables? + + virtual char getGlobalType (const std::string& name) const; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. }; } diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index 09d70ff3e..abe7c2611 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -74,6 +74,32 @@ namespace SAInterpreter for (std::size_t i=0; i& buttons); + virtual bool menuMode(); + + virtual int getGlobalShort (const std::string& name) const; + + virtual int getGlobalLong (const std::string& name) const; + + virtual float getGlobalFloat (const std::string& name) const; + + virtual void setGlobalShort (const std::string& name, int value); + + virtual void setGlobalLong (const std::string& name, int value); + + virtual void setGlobalFloat (const std::string& name, float value); + void report(); ///< Write state to std::cout }; diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 4219bc3b8..de177376d 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -29,6 +29,9 @@ namespace MWScript { return mType==Type_Full; } + + virtual char getGlobalType (const std::string& name) const { return ' '; } + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. }; } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 304829dba..89b107ae8 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -71,6 +71,41 @@ namespace MWScript std::cerr << "error: message box buttons not supported" << std::endl; } + bool InterpreterContext::menuMode() + { + return false; + } + + int InterpreterContext::getGlobalShort (const std::string& name) const + { + return 0; + } + + int InterpreterContext::getGlobalLong (const std::string& name) const + { + return 0; + } + + float InterpreterContext::getGlobalFloat (const std::string& name) const + { + return 0; + } + + void InterpreterContext::setGlobalShort (const std::string& name, int value) + { + + } + + void InterpreterContext::setGlobalLong (const std::string& name, int value) + { + + } + + void InterpreterContext::setGlobalFloat (const std::string& name, float value) + { + + } + MWWorld::World& InterpreterContext::getWorld() { return *mEnvironment.mWorld; diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 0b0d2e65d..2cb8b3bce 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -47,6 +47,20 @@ namespace MWScript virtual void messageBox (const std::string& message, const std::vector& buttons); + virtual bool menuMode(); + + virtual int getGlobalShort (const std::string& name) const; + + virtual int getGlobalLong (const std::string& name) const; + + virtual float getGlobalFloat (const std::string& name) const; + + virtual void setGlobalShort (const std::string& name, int value); + + virtual void setGlobalLong (const std::string& name, int value); + + virtual void setGlobalFloat (const std::string& name, float value); + MWWorld::World& getWorld(); MWSound::SoundManager& getSoundManager(); diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index 6af0f9602..1dfdf6afe 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -1,6 +1,8 @@ #ifndef COMPILER_CONTEXT_H_INCLUDED #define COMPILER_CONTEXT_H_INCLUDED +#include + namespace Compiler { class Extensions; @@ -27,6 +29,9 @@ namespace Compiler { return mExtensions; } + + virtual char getGlobalType (const std::string& name) const = 0; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index bbeaf2c81..47e8eadaa 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -243,16 +243,29 @@ namespace Compiler mFirst = false; if (mNextOperand) - { - char type = mLocals.getType (name); + { + std::string name2 = toLower (name); + + char type = mLocals.getType (name2); if (type!=' ') { - Generator::fetchLocal (mCode, type, mLocals.getIndex (name)); + Generator::fetchLocal (mCode, type, mLocals.getIndex (name2)); mNextOperand = false; mOperands.push_back (type=='f' ? 'f' : 'l'); return true; } + + + type = getContext().getGlobalType (name2); + + if (type!=' ') + { + Generator::fetchGlobal (mCode, mLiterals, type, name2); + mNextOperand = false; + mOperands.push_back (type=='f' ? 'f' : 'l'); + return true; + } } else { @@ -281,6 +294,16 @@ namespace Compiler mNextOperand = false; return true; } + else if (keyword==Scanner::K_menumode) + { + mTokenLoc = loc; + + Generator::menuMode (mCode); + mOperands.push_back ('l'); + + mNextOperand = false; + return true; + } else { // check for custom extensions diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 5fc60ef9f..a11e0969f 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -219,6 +219,41 @@ namespace { code.push_back (Compiler::Generator::segment5 (37)); } + + void opMenuMode (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (38)); + } + + void opStoreGlobalShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (39)); + } + + void opStoreGlobalLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (40)); + } + + void opStoreGlobalFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (41)); + } + + void opFetchGlobalShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (42)); + } + + void opFetchGlobalLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (43)); + } + + void opFetchGlobalFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (44)); + } } namespace Compiler @@ -511,6 +546,85 @@ namespace Compiler } } } + + void menuMode (CodeContainer& code) + { + opMenuMode (code); + } + + void assignToGlobal (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const CodeContainer& value, char valueType) + { + int index = literals.addString (name); + + opPushInt (code, index); + + std::copy (value.begin(), value.end(), std::back_inserter (code)); + + if (localType!=valueType) + { + if (localType=='f' && valueType=='l') + { + opIntToFloat (code); + } + else if ((localType=='l' || localType=='s') && valueType=='f') + { + opFloatToInt (code); + } + } + + switch (localType) + { + case 'f': + + opStoreGlobalFloat (code); + break; + + case 's': + + opStoreGlobalShort (code); + break; + + case 'l': + + opStoreGlobalLong (code); + break; + + default: + + assert (0); + } + } + + void fetchGlobal (CodeContainer& code, Literals& literals, char localType, + const std::string& name) + { + int index = literals.addString (name); + + opPushInt (code, index); + + switch (localType) + { + case 'f': + + opFetchGlobalFloat (code); + break; + + case 's': + + opFetchGlobalShort (code); + break; + + case 'l': + + opFetchGlobalLong (code); + break; + + default: + + assert (0); + } + } } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index e19390284..4d5f46cf4 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -90,6 +90,14 @@ namespace Compiler void jumpOnNonZero (CodeContainer& code, int offset); void compare (CodeContainer& code, char op, char valueType1, char valueType2); + + void menuMode (CodeContainer& code); + + void assignToGlobal (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const CodeContainer& value, char valueType); + + void fetchGlobal (CodeContainer& code, Literals& literals, char localType, + const std::string& name); } } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 347ba2deb..699c07815 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -61,8 +61,9 @@ namespace Compiler if (mState==SetState) { - // local variable? std::string name2 = toLower (name); + + // local variable? char type = mLocals.getType (name2); if (type!=' ') { @@ -71,6 +72,15 @@ namespace Compiler return true; } + type = getContext().getGlobalType (name2); + if (type!=' ') + { + mName = name2; + mType = type; + mState = SetGlobalVarState; + return true; + } + getErrorHandler().error ("unknown variable", loc); SkipParser skip (getErrorHandler(), getContext()); scanner.scan (skip); @@ -166,7 +176,20 @@ namespace Compiler mState = EndState; return true; } - + else if (mState==SetGlobalVarState && keyword==Scanner::K_to) + { + mExprParser.reset(); + scanner.scan (mExprParser); + + std::vector code; + char type = mExprParser.append (code); + + Generator::assignToGlobal (mCode, mLiterals, mType, mName, code, type); + + mState = EndState; + return true; + } + return Parser::parseKeyword (keyword, loc, scanner); } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 0af222d86..63efb60a4 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -21,7 +21,7 @@ namespace Compiler { BeginState, ShortState, LongState, FloatState, - SetState, SetLocalVarState, + SetState, SetLocalVarState, SetGlobalVarState, MessageState, MessageCommaState, EndState }; @@ -31,6 +31,7 @@ namespace Compiler std::vector& mCode; State mState; std::string mName; + char mType; ExprParser mExprParser; public: diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 11338eeb2..72fe0610e 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -242,6 +242,7 @@ namespace Compiler "messagebox", "set", "to", "getsquareroot", + "menumode", 0 }; diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 8c0f078c6..d00f2b065 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -48,7 +48,8 @@ namespace Compiler K_return, K_messagebox, K_set, K_to, - K_getsquareroot + K_getsquareroot, + K_menumode }; enum special diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 46555d058..42af70b6c 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -32,6 +32,20 @@ namespace Interpreter std::vector empty; messageBox (message, empty); } + + virtual bool menuMode() = 0; + + virtual int getGlobalShort (const std::string& name) const = 0; + + virtual int getGlobalLong (const std::string& name) const = 0; + + virtual float getGlobalFloat (const std::string& name) const = 0; + + virtual void setGlobalShort (const std::string& name, int value) = 0; + + virtual void setGlobalLong (const std::string& name, int value) = 0; + + virtual void setGlobalFloat (const std::string& name, float value) = 0; }; } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 333747911..b984c5abe 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -96,6 +96,13 @@ op 34: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser than op 35: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser or equal, 0 else op 36: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater than, 0 else op 37: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater or equal, 0 else -opcodes 38-33554431 unused +op 38: push 1 if game is in menu mode, 0 else +op 39: store stack[0] in global short stack[1] and pop twice +op 40: store stack[0] in global long stack[1] and pop twice +op 41: store stack[0] in global float stack[1] and pop twice +op 42: replace stack[0] with global short stack[0] +op 43: replace stack[0] with global long stack[0] +op 44: replace stack[0] with global float stack[0] +opcodes 45-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 3567d5943..8b96e4bc5 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -23,7 +23,7 @@ namespace Interpreter interpreter.installSegment5 (17, new OpIntToFloat1); interpreter.installSegment5 (18, new OpFloatToInt1); - // local variables & literals + // local variables, global variables & literals interpreter.installSegment5 (0, new OpStoreLocalShort); interpreter.installSegment5 (1, new OpStoreLocalLong); interpreter.installSegment5 (2, new OpStoreLocalFloat); @@ -32,6 +32,12 @@ namespace Interpreter interpreter.installSegment5 (21, new OpFetchLocalShort); interpreter.installSegment5 (22, new OpFetchLocalLong); interpreter.installSegment5 (23, new OpFetchLocalFloat); + interpreter.installSegment5 (39, new OpStoreGlobalShort); + interpreter.installSegment5 (40, new OpStoreGlobalLong); + interpreter.installSegment5 (41, new OpStoreGlobalFloat); + interpreter.installSegment5 (42, new OpFetchGlobalShort); + interpreter.installSegment5 (43, new OpFetchGlobalLong); + interpreter.installSegment5 (44, new OpFetchGlobalFloat); // math interpreter.installSegment5 (9, new OpAddInt); @@ -77,7 +83,8 @@ namespace Interpreter interpreter.installSegment0 (2, new OpJumpBackward); // misc - interpreter.installSegment3 (0, new OpMessageBox); + interpreter.installSegment3 (0, new OpMessageBox); + interpreter.installSegment5 (38, new OpMenuMode); } } diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 4be661d87..427b4b574 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -112,6 +112,99 @@ namespace Interpreter runtime[0] = *reinterpret_cast (&value); } }; + + class OpStoreGlobalShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Data data = runtime[0]; + int index = runtime[1]; + + std::string name = runtime.getStringLiteral (index); + + runtime.getContext().setGlobalShort (name, *reinterpret_cast (&data)); + + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreGlobalLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Data data = runtime[0]; + int index = runtime[1]; + + std::string name = runtime.getStringLiteral (index); + + runtime.getContext().setGlobalLong (name, *reinterpret_cast (&data)); + + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreGlobalFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Data data = runtime[0]; + int index = runtime[1]; + + std::string name = runtime.getStringLiteral (index); + + runtime.getContext().setGlobalFloat (name, *reinterpret_cast (&data)); + + runtime.pop(); + runtime.pop(); + } + }; + + class OpFetchGlobalShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + std::string name = runtime.getStringLiteral (index); + int value = runtime.getContext().getGlobalShort (name); + runtime[0] = *reinterpret_cast (&value); + } + }; + + class OpFetchGlobalLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + std::string name = runtime.getStringLiteral (index); + int value = runtime.getContext().getGlobalLong (name); + runtime[0] = *reinterpret_cast (&value); + } + }; + + class OpFetchGlobalFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + std::string name = runtime.getStringLiteral (index); + float value = runtime.getContext().getGlobalFloat (name); + runtime[0] = *reinterpret_cast (&value); + } + }; } #endif diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 89f6116d2..2ab8f890b 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -85,7 +85,17 @@ namespace Interpreter std::vector buttons; runtime.getContext().messageBox (formattedMessage, buttons); - } + } + }; + + class OpMenuMode : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.push (runtime.getContext().menuMode()); + } }; }