diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 70e5fe8c2b..9813e2e2fd 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -14,7 +14,7 @@ opcodes 0x200-0x3ff unused Segment 3: (not implemented yet) -opcodes 0x200-0x3ff unused +opcodes 0x20000-0x3ffff unused Segment 4: (not implemented yet) diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index c5262616bc..3d3b21d650 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -505,6 +505,11 @@ namespace Compiler void message (CodeContainer& code, Literals& literals, const std::string& message, int buttons) { + assert (buttons>=0); + + if (buttons>=256) + throw std::runtime_error ("A message box can't have more than 255 buttons"); + int index = literals.addString (message); opPushInt (code, index); diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index a7559f7e9c..5671949f20 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -36,8 +36,8 @@ namespace Compiler inline Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0) { - assert (c<1024); - return 0xc0000000 | (c<<20) | (arg0 & 0xffff); + assert (c<262144); + return 0xc0000000 | (c<<8) | (arg0 & 0xff); } inline Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0, @@ -52,72 +52,71 @@ namespace Compiler assert (c<67108864); return 0xc8000000 | c; } - + void pushInt (CodeContainer& code, Literals& literals, int value); void pushFloat (CodeContainer& code, Literals& literals, float value); - + void pushString (CodeContainer& code, Literals& literals, const std::string& value); void assignToLocal (CodeContainer& code, char localType, int localIndex, const CodeContainer& value, char valueType); - + void negate (CodeContainer& code, char valueType); - + void add (CodeContainer& code, char valueType1, char valueType2); - void sub (CodeContainer& code, char valueType1, char valueType2); - - void mul (CodeContainer& code, char valueType1, char valueType2); - - void div (CodeContainer& code, char valueType1, char valueType2); - + void sub (CodeContainer& code, char valueType1, char valueType2); + + void mul (CodeContainer& code, char valueType1, char valueType2); + + void div (CodeContainer& code, char valueType1, char valueType2); + void convert (CodeContainer& code, char fromType, char toType); - + void squareRoot (CodeContainer& code); - void exit (CodeContainer& code); - + void exit (CodeContainer& code); + void message (CodeContainer& code, Literals& literals, const std::string& message, int buttons); - + void fetchLocal (CodeContainer& code, char localType, int localIndex); void jump (CodeContainer& code, int offset); - + void jumpOnZero (CodeContainer& code, int offset); - + 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); - + const std::string& name, const CodeContainer& value, char valueType); + void fetchGlobal (CodeContainer& code, Literals& literals, char localType, - const std::string& name); - + const std::string& name); + void random (CodeContainer& code); - + void scriptRunning (CodeContainer& code); - + void startScript (CodeContainer& code); void stopScript (CodeContainer& code); - + void getDistance (CodeContainer& code, Literals& literals, const std::string id); void getSecondsPassed (CodeContainer& code); - + void getDisabled (CodeContainer& code, Literals& literals, const std::string id); - + void enable (CodeContainer& code, Literals& literals, const std::string id); - + void disable (CodeContainer& code, Literals& literals, const std::string id); } } #endif - diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 291d1c490c..6619fc30a1 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -19,7 +19,7 @@ Code bit-patterns: 00ccccccAAAAAAAAAAAAAAAAAAAAAAAA segment 0: 64 opcodes, 1 24-bit argument 01ccccccAAAAAAAAAAAABBBBBBBBBBBB segment 1: 64 opcodes, 2 12-bit arguments 10ccccccccccAAAAAAAAAAAAAAAAAAAA segment 2: 1024 opcodes, 1 20-bit argument -110000ccccccccccAAAAAAAAAAAAAAAA segment 3: 1024 opcodes, 1 16-bit argument +110000ccccccccccccccccccAAAAAAAA segment 3: 262144 opcodes, 1 8-bit argument 110001ccccccccccAAAAAAAABBBBBBBB segment 4: 1024 opcodes, 2 8-bit arguments 110010cccccccccccccccccccccccccc segment 5: 67108864 opcodes, no arguments other bit-patterns reserved @@ -50,8 +50,8 @@ op 0: show message box with message string literal index in stack[0]; additional arguments (if any) in stack[arg0+n]..stack[arg0+1]; n is determined according to the message string all arguments are removed from stack -opcodes 1-511 unused -opcodes 512-1023 reserved for extensions +opcodes 1-131071 unused +opcodes 131072-262143 reserved for extensions Segment 4: opcodes 0-511 unused diff --git a/components/interpreter/interpreter.cpp b/components/interpreter/interpreter.cpp index f3ebd97a7a..44f626aadb 100644 --- a/components/interpreter/interpreter.cpp +++ b/components/interpreter/interpreter.cpp @@ -13,131 +13,131 @@ namespace Interpreter void Interpreter::execute (Type_Code code) { unsigned int segSpec = code>>30; - + switch (segSpec) { case 0: { int opcode = code>>24; unsigned int arg0 = code & 0xffffff; - + std::map::iterator iter = mSegment0.find (opcode); - + if (iter==mSegment0.end()) abortUnknownCode (0, opcode); - + iter->second->execute (mRuntime, arg0); - + return; } - + case 1: { int opcode = (code>>24) & 0x3f; unsigned int arg0 = (code>>16) & 0xfff; unsigned int arg1 = code & 0xfff; - + std::map::iterator iter = mSegment1.find (opcode); - + if (iter==mSegment1.end()) abortUnknownCode (1, opcode); - + iter->second->execute (mRuntime, arg0, arg1); - + return; } - + case 2: { int opcode = (code>>20) & 0x3ff; unsigned int arg0 = code & 0xfffff; - + std::map::iterator iter = mSegment2.find (opcode); - + if (iter==mSegment2.end()) abortUnknownCode (2, opcode); - + iter->second->execute (mRuntime, arg0); - + return; - } + } } - + segSpec = code>>26; - + switch (segSpec) - { + { case 0x30: { - int opcode = (code>>16) & 0x3ff; - unsigned int arg0 = code & 0xffff; - + int opcode = (code>>8) & 0x3ffff; + unsigned int arg0 = code & 0xff; + std::map::iterator iter = mSegment3.find (opcode); - + if (iter==mSegment3.end()) abortUnknownCode (3, opcode); - + iter->second->execute (mRuntime, arg0); - + return; - } - + } + case 0x31: { int opcode = (code>>16) & 0x3ff; unsigned int arg0 = (code>>8) & 0xff; unsigned int arg1 = code & 0xff; - + std::map::iterator iter = mSegment4.find (opcode); - + if (iter==mSegment4.end()) abortUnknownCode (4, opcode); - + iter->second->execute (mRuntime, arg0, arg1); - + return; - } - + } + case 0x32: { int opcode = code & 0x3ffffff; - + std::map::iterator iter = mSegment5.find (opcode); - + if (iter==mSegment5.end()) abortUnknownCode (5, opcode); - + iter->second->execute (mRuntime); - + return; } } - + abortUnknownSegment (code); } void Interpreter::abortUnknownCode (int segment, int opcode) { std::ostringstream error; - + error << "unknown opcode " << opcode << " in segment " << segment; - + throw std::runtime_error (error.str()); } - + void Interpreter::abortUnknownSegment (Type_Code code) { std::ostringstream error; - + error << "opcode outside of the allocated segment range: " << code; - + throw std::runtime_error (error.str()); } - + Interpreter::Interpreter (Context& context) : mRuntime (context) {} - + Interpreter::~Interpreter() { for (std::map::iterator iter (mSegment0.begin()); @@ -159,12 +159,12 @@ namespace Interpreter for (std::map::iterator iter (mSegment4.begin()); iter!=mSegment4.end(); ++iter) delete iter->second; - + for (std::map::iterator iter (mSegment5.begin()); iter!=mSegment5.end(); ++iter) - delete iter->second; + delete iter->second; } - + void Interpreter::installSegment0 (int code, Opcode1 *opcode) { mSegment0.insert (std::make_pair (code, opcode)); @@ -194,24 +194,24 @@ namespace Interpreter { mSegment5.insert (std::make_pair (code, opcode)); } - + void Interpreter::run (const Type_Code *code, int codeSize) { assert (codeSize>=4); - + mRuntime.configure (code, codeSize); - + int opcodes = static_cast (code[0]); - + const Type_Code *codeBlock = code + 4; - + while (mRuntime.getPC()>=0 && mRuntime.getPC()