diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index cbe379f0f..7924f1dc7 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -110,7 +110,7 @@ namespace SAInterpreter void Context::stopScript (const std::string& name) {} - float Context::getDistance (const std::string& name) const + float Context::getDistance (const std::string& name, const std::string& id) const { return 0; } diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp index 1ee3129f7..6cf4f8cd7 100644 --- a/apps/mwinterpreter/context.hpp +++ b/apps/mwinterpreter/context.hpp @@ -58,7 +58,7 @@ namespace SAInterpreter virtual void stopScript (const std::string& name); - virtual float getDistance (const std::string& name) const; + virtual float getDistance (const std::string& name, const std::string& id = "") const; virtual float getSecondsPassed() const; diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 216627786..78b06d2b4 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -35,6 +35,7 @@ set(GAMESCRIPT mwscript/cellextensions.cpp mwscript/miscextensions.cpp mwscript/guiextensions.cpp + mwscript/soundextensions.cpp mwscript/extensions.cpp mwscript/globalscripts.cpp ) @@ -46,17 +47,16 @@ set(GAMESCRIPT_HEADER mwscript/cellextensions.hpp mwscript/miscextensions.hpp mwscript/guiextensions.hpp + mwscript/soundextensions.hpp mwscript/extensions.hpp mwscript/globalscripts.hpp ) source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER}) set(GAMESOUND - mwsound/soundmanager.cpp - mwsound/extensions.cpp) + mwsound/soundmanager.cpp) set(GAMESOUND_HEADER - mwsound/soundmanager.hpp - mwsound/extensions.hpp) + mwsound/soundmanager.hpp) source_group(apps\\openmw\\mwsound FILES ${GAMESOUND} ${GAMESOUND_HEADER}) set(GAMEGUI diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 1cda9aeaa..d968239bc 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -46,5 +46,13 @@ op 0x2000015: EnableMapMenu op 0x2000016: EnableStatsMenu op 0x2000017: EnableRest op 0x2000018: ShowRestMenu -opcodes 0x2000019-0x3ffffff unused +op 0x2000019: Say, explicit reference +op 0x200001a: SayDone, explicit reference +op 0x200001b: PlaySound3D, explicit reference +op 0x200001c: PlaySound3DVP, explicit reference +op 0x200001d: PlayLoopSound3D, explicit reference +op 0x200001e: PlayLoopSound3DVP, explicit reference +op 0x200001f: StopSound, explicit reference +op 0x2000020: GetSoundPlaying, explicit reference +opcodes 0x2000021-0x3ffffff unused diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index e309d632c..b688b2037 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -1,8 +1,7 @@ #include "extensions.hpp" -#include "../mwsound/extensions.hpp" - +#include "soundextensions.hpp" #include "cellextensions.hpp" #include "miscextensions.hpp" #include "guiextensions.hpp" @@ -14,7 +13,7 @@ namespace MWScript Cell::registerExtensions (extensions); Misc::registerExtensions (extensions); Gui::registerExtensions (extensions); - MWSound::registerExtensions (extensions); + Sound::registerExtensions (extensions); } } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 064ac583d..239c558bd 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -16,11 +16,9 @@ namespace MWScript { - InterpreterContext::PtrWithCell InterpreterContext::getReference ( + MWWorld::Ptr InterpreterContext::getReference ( const std::string& id, bool activeOnly) { - PtrWithCell ref; - if (!id.empty()) { return mEnvironment.mWorld->getPtr (id, activeOnly); @@ -30,15 +28,13 @@ namespace MWScript if (mReference.isEmpty()) throw std::runtime_error ("no implicit reference"); - return PtrWithCell (mReference, mEnvironment.mWorld->find (mReference)); + return mReference; } } - InterpreterContext::CPtrWithCell InterpreterContext::getReference ( + const MWWorld::Ptr InterpreterContext::getReference ( const std::string& id, bool activeOnly) const { - CPtrWithCell ref; - if (!id.empty()) { return mEnvironment.mWorld->getPtr (id, activeOnly); @@ -48,7 +44,7 @@ namespace MWScript if (mReference.isEmpty()) throw std::runtime_error ("no implicit reference"); - return CPtrWithCell (mReference, mEnvironment.mWorld->find (mReference)); + return mReference; } } @@ -176,18 +172,17 @@ namespace MWScript mEnvironment.mGlobalScripts->removeScript (name); } - float InterpreterContext::getDistance (const std::string& name) const + float InterpreterContext::getDistance (const std::string& name, const std::string& id) const { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - std::pair ref = - mEnvironment.mWorld->getPtr (name, true); + // TODO handle exterior cells (when ref and ref2 are located in different cells) + const MWWorld::Ptr ref2 = getReference (id, false); + + const MWWorld::Ptr ref = mEnvironment.mWorld->getPtr (name, true); double diff[3]; for (int i=0; i<3; ++i) - diff[i] = ref.first.getCellRef().pos.pos[i] - mReference.getCellRef().pos.pos[i]; + diff[i] = ref.getCellRef().pos.pos[i] - ref2.getCellRef().pos.pos[i]; return std::sqrt (diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2]); } @@ -204,19 +199,19 @@ namespace MWScript bool InterpreterContext::isDisabled (const std::string& id) const { - CPtrWithCell ref = getReference (id, false); - return !ref.first.getRefData().isEnabled(); + const MWWorld::Ptr ref = getReference (id, false); + return !ref.getRefData().isEnabled(); } void InterpreterContext::enable (const std::string& id) { - PtrWithCell ref = getReference (id, false); + MWWorld::Ptr ref = getReference (id, false); mEnvironment.mWorld->enable (ref); } void InterpreterContext::disable (const std::string& id) { - PtrWithCell ref = getReference (id, false); + MWWorld::Ptr ref = getReference (id, false); mEnvironment.mWorld->disable (ref); } diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index bdc871a01..ac719f151 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -22,12 +22,10 @@ namespace MWScript Locals *mLocals; MWWorld::Ptr mReference; - typedef std::pair PtrWithCell; - typedef std::pair CPtrWithCell; - PtrWithCell getReference (const std::string& id, bool activeOnly); - - CPtrWithCell getReference (const std::string& id, bool activeOnly) const; + MWWorld::Ptr getReference (const std::string& id, bool activeOnly); + + const MWWorld::Ptr getReference (const std::string& id, bool activeOnly) const; public: @@ -70,7 +68,7 @@ namespace MWScript virtual void stopScript (const std::string& name); - virtual float getDistance (const std::string& name) const; + virtual float getDistance (const std::string& name, const std::string& id = "") const; virtual bool hasBeenActivated() const; diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 912e959ae..926dcb699 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -15,8 +15,7 @@ #include #include -#include "../mwsound/extensions.hpp" - +#include "soundextensions.hpp" #include "cellextensions.hpp" #include "miscextensions.hpp" #include "guiextensions.hpp" @@ -125,7 +124,7 @@ namespace MWScript Cell::installOpcodes (interpreter); Misc::installOpcodes (interpreter); Gui::installOpcodes (interpreter); - MWSound::installOpcodes (interpreter); + Sound::installOpcodes (interpreter); } } diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp new file mode 100644 index 000000000..40229475e --- /dev/null +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -0,0 +1,398 @@ + +#include "extensions.hpp" + +#include + +#include +#include +#include + +#include "interpretercontext.hpp" + +#include "../mwworld/world.hpp" + +#include "../mwsound/soundmanager.hpp" + +namespace MWScript +{ + namespace Sound + { + class OpSay : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string file = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string text = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().say (context.getReference(), file, text, + context); + } + }; + + class OpSayDone : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + runtime.push (context.getSoundManager().sayDone (context.getReference(), + context)); + } + }; + + class OpStreamMusic : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().streamMusic (sound, context); + } + }; + + class OpPlaySound : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().playSound (sound, 1.0, 1.0, context); + } + }; + + class OpPlaySoundVP : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Float volume = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float pitch = runtime[0].mFloat; + runtime.pop(); + + context.getSoundManager().playSound (sound, volume, pitch, context); + } + }; + + class OpPlaySound3D : public Interpreter::Opcode0 + { + bool mLoop; + + public: + + OpPlaySound3D (bool loop) : mLoop (loop) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().playSound3D (context.getReference(), sound, + 1.0, 1.0, mLoop, context); + } + }; + + class OpPlaySoundVP3D : public Interpreter::Opcode0 + { + bool mLoop; + + public: + + OpPlaySoundVP3D (bool loop) : mLoop (loop) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Float volume = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float pitch = runtime[0].mFloat; + runtime.pop(); + + context.getSoundManager().playSound3D (context.getReference(), sound, volume, + pitch, mLoop, context); + + } + }; + + class OpStopSound : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().stopSound3D (context.getReference(), sound, context); + } + }; + + class OpGetSoundPlaying : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + int index = runtime[0].mInteger; + runtime.pop(); + + runtime.push (context.getSoundManager().getSoundPlaying ( + context.getReference(), runtime.getStringLiteral (index), context)); + } + }; + + class OpSayExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string file = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string text = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().say (context.getWorld().getPtr (id, true), + file, text, context); + } + }; + + class OpSayDoneExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + runtime.push (context.getSoundManager().sayDone ( + context.getWorld().getPtr (id, true), context)); + } + }; + + class OpPlaySound3DExplicit : public Interpreter::Opcode0 + { + bool mLoop; + + public: + + OpPlaySound3DExplicit (bool loop) : mLoop (loop) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().playSound3D ( + context.getWorld().getPtr (id, true), sound, 1.0, 1.0, mLoop, context); + } + }; + + class OpPlaySoundVP3DExplicit : public Interpreter::Opcode0 + { + bool mLoop; + + public: + + OpPlaySoundVP3DExplicit (bool loop) : mLoop (loop) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Float volume = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float pitch = runtime[0].mFloat; + runtime.pop(); + + context.getSoundManager().playSound3D ( + context.getWorld().getPtr (id, true), sound, volume, pitch, mLoop, context); + + } + }; + + class OpStopSoundExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string sound = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + context.getSoundManager().stopSound3D ( + context.getWorld().getPtr (id, true), sound, context); + } + }; + + class OpGetSoundPlayingExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + int index = runtime[0].mInteger; + runtime.pop(); + + runtime.push (context.getSoundManager().getSoundPlaying ( + context.getWorld().getPtr (id, true), + runtime.getStringLiteral (index), context)); + } + }; + + const int opcodeSay = 0x2000001; + const int opcodeSayDone = 0x2000002; + const int opcodeStreamMusic = 0x2000003; + const int opcodePlaySound = 0x2000004; + const int opcodePlaySoundVP = 0x2000005; + const int opcodePlaySound3D = 0x2000006; + const int opcodePlaySound3DVP = 0x2000007; + const int opcodePlayLoopSound3D = 0x2000008; + const int opcodePlayLoopSound3DVP = 0x2000009; + const int opcodeStopSound = 0x200000a; + const int opcodeGetSoundPlaying = 0x200000b; + + const int opcodeSayExplicit = 0x2000019; + const int opcodeSayDoneExplicit = 0x200001a; + const int opcodePlaySound3DExplicit = 0x200001b; + const int opcodePlaySound3DVPExplicit = 0x200001c; + const int opcodePlayLoopSound3DExplicit = 0x200001d; + const int opcodePlayLoopSound3DVPExplicit = 0x200001e; + const int opcodeStopSoundExplicit = 0x200001f; + const int opcodeGetSoundPlayingExplicit = 0x2000020; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction ("say", "SS", opcodeSay, opcodeSayExplicit); + extensions.registerFunction ("saydone", 'l', "", opcodeSayDone, opcodeSayDoneExplicit); + extensions.registerInstruction ("streammusic", "S", opcodeStreamMusic); + extensions.registerInstruction ("playsound", "c", opcodePlaySound); + extensions.registerInstruction ("playsoundvp", "cff", opcodePlaySoundVP); + extensions.registerInstruction ("playsound3d", "c", opcodePlaySound3D, + opcodePlaySound3DExplicit); + extensions.registerInstruction ("playsound3dvp", "cff", opcodePlaySound3DVP, + opcodePlaySound3DVPExplicit); + extensions.registerInstruction ("playloopsound3d", "c", opcodePlayLoopSound3D, + opcodePlayLoopSound3DExplicit); + extensions.registerInstruction ("playloopsound3dvp", "cff", opcodePlayLoopSound3DVP, + opcodePlayLoopSound3DVPExplicit); + extensions.registerInstruction ("stopsound", "c", opcodeStopSound, + opcodeStopSoundExplicit); + extensions.registerFunction ("getsoundplaying", 'l', "c", opcodeGetSoundPlaying, + opcodeGetSoundPlayingExplicit); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5 (opcodeSay, new OpSay); + interpreter.installSegment5 (opcodeSayDone, new OpSayDone); + interpreter.installSegment5 (opcodeStreamMusic, new OpStreamMusic); + interpreter.installSegment5 (opcodePlaySound, new OpPlaySound); + interpreter.installSegment5 (opcodePlaySoundVP, new OpPlaySoundVP); + interpreter.installSegment5 (opcodePlaySound3D, new OpPlaySound3D (false)); + interpreter.installSegment5 (opcodePlaySound3DVP, new OpPlaySoundVP3D (false)); + interpreter.installSegment5 (opcodePlayLoopSound3D, new OpPlaySound3D (true)); + interpreter.installSegment5 (opcodePlayLoopSound3DVP, new OpPlaySoundVP3D (true)); + interpreter.installSegment5 (opcodeStopSound, new OpStopSound); + interpreter.installSegment5 (opcodeGetSoundPlaying, new OpGetSoundPlaying); + + interpreter.installSegment5 (opcodeSayExplicit, new OpSayExplicit); + interpreter.installSegment5 (opcodeSayDoneExplicit, new OpSayDoneExplicit); + interpreter.installSegment5 (opcodePlaySound3DExplicit, + new OpPlaySound3DExplicit (false)); + interpreter.installSegment5 (opcodePlaySound3DVPExplicit, + new OpPlaySoundVP3DExplicit (false)); + interpreter.installSegment5 (opcodePlayLoopSound3DExplicit, + new OpPlaySound3DExplicit (true)); + interpreter.installSegment5 (opcodePlayLoopSound3DVPExplicit, + new OpPlaySoundVP3DExplicit (true)); + interpreter.installSegment5 (opcodeStopSoundExplicit, new OpStopSoundExplicit); + interpreter.installSegment5 (opcodeGetSoundPlayingExplicit, + new OpGetSoundPlayingExplicit); + } + } +} + diff --git a/apps/openmw/mwscript/soundextensions.hpp b/apps/openmw/mwscript/soundextensions.hpp new file mode 100644 index 000000000..85416a6df --- /dev/null +++ b/apps/openmw/mwscript/soundextensions.hpp @@ -0,0 +1,27 @@ +#ifndef GAME_SCRIPT_SOUNDEXTENSIONS_H +#define GAME_SCRIPT_SOUNDEXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + namespace Sound + { + // Script-extensions related to sound + + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif + diff --git a/apps/openmw/mwsound/extensions.cpp b/apps/openmw/mwsound/extensions.cpp deleted file mode 100644 index 4aee9827c..000000000 --- a/apps/openmw/mwsound/extensions.cpp +++ /dev/null @@ -1,236 +0,0 @@ - -#include "extensions.hpp" - -#include - -#include -#include -#include - -#include "../mwscript/interpretercontext.hpp" - -#include "../mwworld/world.hpp" - -#include "soundmanager.hpp" - -namespace MWSound -{ - namespace Script - { - class OpSay : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string file = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - std::string text = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - context.getSoundManager().say (context.getReference(), file, text, - context); - } - }; - - class OpSayDone : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - runtime.push (context.getSoundManager().sayDone (context.getReference(), - context)); - } - }; - - class OpStreamMusic : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string sound = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - context.getSoundManager().streamMusic (sound, context); - } - }; - - class OpPlaySound : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string sound = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - context.getSoundManager().playSound (sound, 1.0, 1.0, context); - } - }; - - class OpPlaySoundVP : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string sound = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - float volume = *reinterpret_cast (&runtime[0]); - runtime.pop(); - - float pitch = *reinterpret_cast (&runtime[0]); - runtime.pop(); - - context.getSoundManager().playSound (sound, volume, pitch, context); - } - }; - - class OpPlaySound3D : public Interpreter::Opcode0 - { - bool mLoop; - - public: - - OpPlaySound3D (bool loop) : mLoop (loop) {} - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string sound = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - context.getSoundManager().playSound3D (context.getReference(), sound, - 1.0, 1.0, mLoop, context); - } - }; - - class OpPlaySoundVP3D : public Interpreter::Opcode0 - { - bool mLoop; - - public: - - OpPlaySoundVP3D (bool loop) : mLoop (loop) {} - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string sound = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - float volume = *reinterpret_cast (&runtime[0]); - runtime.pop(); - - float pitch = *reinterpret_cast (&runtime[0]); - runtime.pop(); - - context.getSoundManager().playSound3D (context.getReference(), sound, volume, - pitch, mLoop, context); - - } - }; - - class OpStopSound : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - std::string sound = runtime.getStringLiteral (runtime[0]); - runtime.pop(); - - context.getSoundManager().stopSound3D (context.getReference(), sound, context); - } - }; - - class OpGetSoundPlaying : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - int index = runtime[0]; - runtime.pop(); - - runtime.push (context.getSoundManager().getSoundPlaying ( - context.getReference(), runtime.getStringLiteral (index), context)); - } - }; - - const int opcodeSay = 0x2000001; - const int opcodeSayDone = 0x2000002; - const int opcodeStreamMusic = 0x2000003; - const int opcodePlaySound = 0x2000004; - const int opcodePlaySoundVP = 0x2000005; - const int opcodePlaySound3D = 0x2000006; - const int opcodePlaySound3DVP = 0x2000007; - const int opcodePlayLoopSound3D = 0x2000008; - const int opcodePlayLoopSound3DVP = 0x2000009; - const int opcodeStopSound = 0x200000a; - const int opcodeGetSoundPlaying = 0x200000b; - } - - void registerExtensions (Compiler::Extensions& extensions) - { - extensions.registerInstruction ("say", "SS", Script::opcodeSay); - extensions.registerFunction ("saydone", 'l', "", Script::opcodeSayDone); - extensions.registerInstruction ("streammusic", "S", Script::opcodeStreamMusic); - extensions.registerInstruction ("playsound", "c", Script::opcodePlaySound); - extensions.registerInstruction ("playsoundvp", "cff", Script::opcodePlaySoundVP); - extensions.registerInstruction ("playsound3d", "c", Script::opcodePlaySound3D); - extensions.registerInstruction ("playsound3dvp", "cff", Script::opcodePlaySound3DVP); - extensions.registerInstruction ("playloopsound3d", "c", Script::opcodePlayLoopSound3D); - extensions.registerInstruction ("playloopsound3dvp", "cff", - Script::opcodePlayLoopSound3DVP); - extensions.registerInstruction ("stopsound", "c", Script::opcodeStopSound); - extensions.registerFunction ("getsoundplaying", 'l', "c", Script::opcodeGetSoundPlaying); - } - - void installOpcodes (Interpreter::Interpreter& interpreter) - { - interpreter.installSegment5 (Script::opcodeSay, new Script::OpSay); - interpreter.installSegment5 (Script::opcodeSayDone, new Script::OpSayDone); - interpreter.installSegment5 (Script::opcodeStreamMusic, new Script::OpStreamMusic); - interpreter.installSegment5 (Script::opcodePlaySound, new Script::OpPlaySound); - interpreter.installSegment5 (Script::opcodePlaySoundVP, new Script::OpPlaySoundVP); - interpreter.installSegment5 (Script::opcodePlaySound3D, new Script::OpPlaySound3D (false)); - interpreter.installSegment5 (Script::opcodePlaySound3DVP, - new Script::OpPlaySoundVP3D (false)); - interpreter.installSegment5 (Script::opcodePlayLoopSound3D, - new Script::OpPlaySound3D (true)); - interpreter.installSegment5 (Script::opcodePlayLoopSound3DVP, - new Script::OpPlaySoundVP3D (true)); - interpreter.installSegment5 (Script::opcodeStopSound, new Script::OpStopSound); - interpreter.installSegment5 (Script::opcodeGetSoundPlaying, new Script::OpGetSoundPlaying); - } -} diff --git a/apps/openmw/mwsound/extensions.hpp b/apps/openmw/mwsound/extensions.hpp deleted file mode 100644 index 0e860952a..000000000 --- a/apps/openmw/mwsound/extensions.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef GAME_SOUND_EXTENSIONS_H -#define GAME_SOUND_EXTENSIONS_H - -namespace Compiler -{ - class Extensions; -} - -namespace Interpreter -{ - class Interpreter; -} - -namespace MWSound -{ - // Script-extensions related to sound - - void registerExtensions (Compiler::Extensions& extensions); - - void installOpcodes (Interpreter::Interpreter& interpreter); -} - -#endif - diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index 9d031512d..a65fcb7cc 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -15,13 +15,18 @@ namespace MWWorld class Ptr { + public: + + typedef ESMS::CellStore CellStore; + boost::any mPtr; ESM::CellRef *mCellRef; RefData *mRefData; + CellStore *mCell; public: - Ptr() : mCellRef (0), mRefData (0) {} + Ptr() : mCellRef (0), mRefData (0), mCell (0) {} bool isEmpty() const { @@ -29,11 +34,12 @@ namespace MWWorld } template - Ptr (ESMS::LiveCellRef *liveCellRef) + Ptr (ESMS::LiveCellRef *liveCellRef, CellStore *cell) { mPtr = liveCellRef; mCellRef = &liveCellRef->ref; mRefData = &liveCellRef->mData; + mCell = cell; } template @@ -53,6 +59,12 @@ namespace MWWorld assert (mRefData); return *mRefData; } + + Ptr::CellStore *getCell() const + { + assert (mCell); + return mCell; + } }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 8fb635ef3..840a88d7d 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -15,7 +15,8 @@ namespace { template void listCellScripts (const ESMS::ESMStore& store, - ESMS::CellRefList& cellRefList, MWWorld::World::ScriptList& scriptList) + ESMS::CellRefList& cellRefList, MWWorld::World::ScriptList& scriptList, + MWWorld::Ptr::CellStore *cell) { for (typename ESMS::CellRefList::List::iterator iter ( cellRefList.list.begin()); @@ -28,116 +29,102 @@ namespace iter->mData.setLocals (*script); scriptList.push_back ( - std::make_pair (iter->base->script, MWWorld::Ptr (&*iter))); + std::make_pair (iter->base->script, MWWorld::Ptr (&*iter, cell))); } } } } - - template - bool hasReference (ESMS::CellRefList& cellRefList, const MWWorld::Ptr& ptr) - { - for (typename ESMS::CellRefList::List::iterator iter ( - cellRefList.list.begin()); - iter!=cellRefList.list.end(); ++iter) - { - if (&iter->mData==&ptr.getRefData()) - return true; - } - - return false; - } } namespace MWWorld { void World::insertInteriorScripts (ESMS::CellStore& cell) { - listCellScripts (mStore, cell.activators, mLocalScripts); - listCellScripts (mStore, cell.potions, mLocalScripts); - listCellScripts (mStore, cell.appas, mLocalScripts); - listCellScripts (mStore, cell.armors, mLocalScripts); - listCellScripts (mStore, cell.books, mLocalScripts); - listCellScripts (mStore, cell.clothes, mLocalScripts); - listCellScripts (mStore, cell.containers, mLocalScripts); - listCellScripts (mStore, cell.creatures, mLocalScripts); - listCellScripts (mStore, cell.doors, mLocalScripts); - listCellScripts (mStore, cell.ingreds, mLocalScripts); - listCellScripts (mStore, cell.lights, mLocalScripts); - listCellScripts (mStore, cell.lockpicks, mLocalScripts); - listCellScripts (mStore, cell.miscItems, mLocalScripts); - listCellScripts (mStore, cell.npcs, mLocalScripts); - listCellScripts (mStore, cell.probes, mLocalScripts); - listCellScripts (mStore, cell.repairs, mLocalScripts); - listCellScripts (mStore, cell.weapons, mLocalScripts); + listCellScripts (mStore, cell.activators, mLocalScripts, &cell); + listCellScripts (mStore, cell.potions, mLocalScripts, &cell); + listCellScripts (mStore, cell.appas, mLocalScripts, &cell); + listCellScripts (mStore, cell.armors, mLocalScripts, &cell); + listCellScripts (mStore, cell.books, mLocalScripts, &cell); + listCellScripts (mStore, cell.clothes, mLocalScripts, &cell); + listCellScripts (mStore, cell.containers, mLocalScripts, &cell); + listCellScripts (mStore, cell.creatures, mLocalScripts, &cell); + listCellScripts (mStore, cell.doors, mLocalScripts, &cell); + listCellScripts (mStore, cell.ingreds, mLocalScripts, &cell); + listCellScripts (mStore, cell.lights, mLocalScripts, &cell); + listCellScripts (mStore, cell.lockpicks, mLocalScripts, &cell); + listCellScripts (mStore, cell.miscItems, mLocalScripts, &cell); + listCellScripts (mStore, cell.npcs, mLocalScripts, &cell); + listCellScripts (mStore, cell.probes, mLocalScripts, &cell); + listCellScripts (mStore, cell.repairs, mLocalScripts, &cell); + listCellScripts (mStore, cell.weapons, mLocalScripts, &cell); } - Ptr World::getPtr (const std::string& name, CellStore& cell) + Ptr World::getPtr (const std::string& name, Ptr::CellStore& cell) { if (ESMS::LiveCellRef *ref = cell.activators.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.potions.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.appas.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.armors.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.books.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.clothes.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.containers.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.creatures.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.doors.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.ingreds.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.creatureLists.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.itemLists.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.lights.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.lockpicks.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.miscItems.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.npcs.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.probes.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.repairs.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.statics.find (name)) - return ref; + return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.weapons.find (name)) - return ref; + return Ptr (ref, &cell); return Ptr(); } - MWRender::CellRender *World::searchRender (CellStore *store) + MWRender::CellRender *World::searchRender (Ptr::CellStore *store) { CellRenderCollection::iterator iter = mActiveCells.find (store); @@ -157,7 +144,7 @@ namespace MWWorld World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, const std::string& startCell, bool newGame) - : mSkyManager (0), mScene (renderer), mPlayerPos (0) + : mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0) { boost::filesystem::path masterPath (dataDir); masterPath /= master; @@ -169,6 +156,7 @@ namespace MWWorld mStore.load (mEsm); mInteriors[startCell].loadInt (startCell, mStore, mEsm); + mCurrentCell = &mInteriors[startCell]; insertInteriorScripts (mInteriors[startCell]); @@ -251,15 +239,12 @@ namespace MWWorld return iter->second; } - std::pair World::getPtr (const std::string& name, bool activeOnly) + Ptr World::getPtr (const std::string& name, bool activeOnly) { // the player is always in an active cell. if (name=="player") { - // TODO: find real cell (might need to be stored in playerPos). For now we - // use the first active cell. This will fail the moment we move into an - // exterior cell. - return std::make_pair (mPlayerPos->getPlayer(), mActiveCells.begin()->first); + return Ptr (mPlayerPos->getPlayer(), mCurrentCell); } // active cells @@ -269,7 +254,7 @@ namespace MWWorld Ptr ptr = getPtr (name, *iter->first); if (!ptr.isEmpty()) - return std::make_pair (ptr, iter->first); + return ptr; } if (!activeOnly) @@ -280,58 +265,29 @@ namespace MWWorld throw std::runtime_error ("unknown ID: " + name); } - void World::enable (std::pair& reference) + void World::enable (Ptr reference) { - if (!reference.first.getRefData().isEnabled()) + if (!reference.getRefData().isEnabled()) { - reference.first.getRefData().enable(); + reference.getRefData().enable(); - if (MWRender::CellRender *render = searchRender (reference.second)) + if (MWRender::CellRender *render = searchRender (reference.getCell())) { - render->enable (reference.first.getRefData().getHandle()); + render->enable (reference.getRefData().getHandle()); } } } - void World::disable (std::pair& reference) + void World::disable (Ptr reference) { - if (!reference.first.getRefData().isEnabled()) + if (!reference.getRefData().isEnabled()) { - reference.first.getRefData().enable(); + reference.getRefData().enable(); - if (MWRender::CellRender *render = searchRender (reference.second)) + if (MWRender::CellRender *render = searchRender (reference.getCell())) { - render->disable (reference.first.getRefData().getHandle()); + render->disable (reference.getRefData().getHandle()); } } } - - World::CellStore *World::find (const Ptr& ptr) - { - for (CellRenderCollection::iterator iter (mActiveCells.begin()); iter!=mActiveCells.end(); - ++iter) - { - if ( - hasReference (iter->first->activators, ptr) || - hasReference (iter->first->potions, ptr) || - hasReference (iter->first->appas, ptr) || - hasReference (iter->first->armors, ptr) || - hasReference (iter->first->books, ptr) || - hasReference (iter->first->clothes, ptr) || - hasReference (iter->first->containers, ptr) || - hasReference (iter->first->creatures, ptr) || - hasReference (iter->first->doors, ptr) || - hasReference (iter->first->ingreds, ptr) || - hasReference (iter->first->lights, ptr) || - hasReference (iter->first->lockpicks, ptr) || - hasReference (iter->first->miscItems, ptr) || - hasReference (iter->first->npcs, ptr) || - hasReference (iter->first->probes, ptr) || - hasReference (iter->first->repairs, ptr) || - hasReference (iter->first->weapons, ptr)) - return iter->first; - } - - throw std::runtime_error ("failed to locate reference in active cell"); - } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 0c299b9f9..d6df3b826 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -36,20 +36,20 @@ namespace MWWorld public: typedef std::vector > ScriptList; - typedef ESMS::CellStore CellStore; private: - typedef std::map CellRenderCollection; + typedef std::map CellRenderCollection; MWRender::SkyManager* mSkyManager; MWRender::MWScene mScene; MWRender::PlayerPos *mPlayerPos; + Ptr::CellStore *mCurrentCell; // the cell, the player is in CellRenderCollection mActiveCells; CellRenderCollection mBufferedCells; // loaded, but not active (buffering not implementd yet) ESM::ESMReader mEsm; ESMS::ESMStore mStore; - std::map mInteriors; + std::map mInteriors; ScriptList mLocalScripts; std::map mGlobalVariables; @@ -59,9 +59,9 @@ namespace MWWorld void insertInteriorScripts (ESMS::CellStore& cell); - Ptr getPtr (const std::string& name, CellStore& cellStore); + Ptr getPtr (const std::string& name, Ptr::CellStore& cellStore); - MWRender::CellRender *searchRender (CellStore *store); + MWRender::CellRender *searchRender (Ptr::CellStore *store); public: @@ -82,16 +82,13 @@ namespace MWWorld Interpreter::Type_Data& getGlobalVariable (const std::string& name); - std::pair getPtr (const std::string& name, bool activeOnly); + Ptr getPtr (const std::string& name, bool activeOnly); ///< Return a pointer to a liveCellRef with the given name. /// \param activeOnly do non search inactive cells. - void enable (std::pair& reference); + void enable (Ptr reference); - void disable (std::pair& reference); - - CellStore *find (const Ptr& ptr); - ///< Only active cells are searched. + void disable (Ptr reference); }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index e11dde521..d0138078e 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -311,6 +311,40 @@ namespace Compiler mNextOperand = false; return true; } + else if (keyword==Scanner::K_getdistance) + { + mTokenLoc = loc; + parseArguments ("c", scanner); + + Generator::getDistance (mCode, mLiterals, mExplicit); + mOperands.push_back ('f'); + mExplicit.clear(); + mRefOp = false; + + mNextOperand = false; + return true; + } + + // check for custom extensions + if (const Extensions *extensions = getContext().getExtensions()) + { + char returnType; + std::string argumentType; + + if (extensions->isFunction (keyword, returnType, argumentType, true)) + { + mTokenLoc = loc; + parseArguments (argumentType, scanner); + + extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit); + mOperands.push_back (returnType); + mExplicit.clear(); + mRefOp = false; + + mNextOperand = false; + return true; + } + } } return Parser::parseKeyword (keyword, loc, scanner); @@ -360,18 +394,18 @@ namespace Compiler mNextOperand = false; return true; - } + } else if (keyword==Scanner::K_getdistance) { mTokenLoc = loc; parseArguments ("c", scanner); - Generator::getDistance (mCode); + Generator::getDistance (mCode, mLiterals, ""); mOperands.push_back ('f'); mNextOperand = false; return true; - } + } else if (keyword==Scanner::K_getsecondspassed) { mTokenLoc = loc; @@ -400,12 +434,12 @@ namespace Compiler char returnType; std::string argumentType; - if (extensions->isFunction (keyword, returnType, argumentType)) + if (extensions->isFunction (keyword, returnType, argumentType, false)) { mTokenLoc = loc; parseArguments (argumentType, scanner); - extensions->generateFunctionCode (keyword, mCode); + extensions->generateFunctionCode (keyword, mCode, mLiterals, ""); mOperands.push_back (returnType); mNextOperand = false; diff --git a/components/compiler/extensions.cpp b/components/compiler/extensions.cpp index ff05208de..78ae0fdfd 100644 --- a/components/compiler/extensions.cpp +++ b/components/compiler/extensions.cpp @@ -5,6 +5,7 @@ #include #include "generator.hpp" +#include "literals.hpp" namespace Compiler { @@ -20,31 +21,39 @@ namespace Compiler return iter->second; } - bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType) const + bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType, + bool explicitReference) const { std::map::const_iterator iter = mFunctions.find (keyword); if (iter==mFunctions.end()) return false; + if (explicitReference && iter->second.mCodeExplicit==-1) + return false; + returnType = iter->second.mReturn; argumentType = iter->second.mArguments; return true; } - bool Extensions::isInstruction (int keyword, std::string& argumentType) const + bool Extensions::isInstruction (int keyword, std::string& argumentType, + bool explicitReference) const { std::map::const_iterator iter = mInstructions.find (keyword); if (iter==mInstructions.end()) return false; + + if (explicitReference && iter->second.mCodeExplicit==-1) + return false; argumentType = iter->second.mArguments; return true; } void Extensions::registerFunction (const std::string& keyword, char returnType, - const std::string& argumentType, int segment5code) + const std::string& argumentType, int segment5code, int segment5codeExplicit) { assert (segment5code>=33554432 && segment5code<=67108863); @@ -56,12 +65,13 @@ namespace Compiler function.mReturn = returnType; function.mArguments = argumentType; function.mCode = segment5code; + function.mCodeExplicit = segment5codeExplicit; mFunctions.insert (std::make_pair (code, function)); } void Extensions::registerInstruction (const std::string& keyword, - const std::string& argumentType, int segment5code) + const std::string& argumentType, int segment5code, int segment5codeExplicit) { assert (segment5code>=33554432 && segment5code<=67108863); @@ -72,23 +82,34 @@ namespace Compiler Instruction instruction; instruction.mArguments = argumentType; instruction.mCode = segment5code; + instruction.mCodeExplicit = segment5codeExplicit; mInstructions.insert (std::make_pair (code, instruction)); } - void Extensions::generateFunctionCode (int keyword, std::vector& code) - const + void Extensions::generateFunctionCode (int keyword, std::vector& code, + Literals& literals, const std::string& id) const { std::map::const_iterator iter = mFunctions.find (keyword); if (iter==mFunctions.end()) throw std::logic_error ("unknown custom function keyword"); - code.push_back (Generator::segment5 (iter->second.mCode)); + if (!id.empty()) + { + if (iter->second.mCodeExplicit==-1) + throw std::logic_error ("explicit references not supported"); + + int index = literals.addString (id); + Generator::pushInt (code, literals, index); + } + + code.push_back (Generator::segment5 ( + id.empty() ? iter->second.mCode : iter->second.mCodeExplicit)); } void Extensions::generateInstructionCode (int keyword, - std::vector& code) + std::vector& code, Literals& literals, const std::string& id) const { std::map::const_iterator iter = mInstructions.find (keyword); @@ -96,6 +117,16 @@ namespace Compiler if (iter==mInstructions.end()) throw std::logic_error ("unknown custom instruction keyword"); - code.push_back (Generator::segment5 (iter->second.mCode)); + if (!id.empty()) + { + if (iter->second.mCodeExplicit==-1) + throw std::logic_error ("explicit references not supported"); + + int index = literals.addString (id); + Generator::pushInt (code, literals, index); + } + + code.push_back (Generator::segment5 ( + id.empty() ? iter->second.mCode : iter->second.mCodeExplicit)); } } diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index f864daf1b..85a761951 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -9,6 +9,8 @@ namespace Compiler { + class Literals; + /// \brief Collection of compiler extensions class Extensions @@ -18,12 +20,14 @@ namespace Compiler char mReturn; std::string mArguments; int mCode; + int mCodeExplicit; }; struct Instruction { std::string mArguments; int mCode; + int mCodeExplicit; }; int mNextKeywordIndex; @@ -40,33 +44,37 @@ namespace Compiler /// - if no match is found 0 is returned. /// - keyword must be all lower case. - bool isFunction (int keyword, char& returnType, std::string& argumentType) const; + bool isFunction (int keyword, char& returnType, std::string& argumentType, + bool explicitReference) const; ///< Is this keyword registered with a function? If yes, return return and argument /// types. - bool isInstruction (int keyword, std::string& argumentType) const; + bool isInstruction (int keyword, std::string& argumentType, + bool explicitReference) const; ///< Is this keyword registered with a function? If yes, return argument types. void registerFunction (const std::string& keyword, char returnType, - const std::string& argumentType, int segment5code); + const std::string& argumentType, int segment5code, int segment5codeExplicit = -1); ///< Register a custom function /// - keyword must be all lower case. /// - keyword must be unique + /// - if explicit references are not supported, segment5codeExplicit must be set to -1 /// \note Currently only segment 5 opcodes are supported. void registerInstruction (const std::string& keyword, - const std::string& argumentType, int segment5code); + const std::string& argumentType, int segment5code, int segment5codeExplicit = -1); ///< Register a custom instruction /// - keyword must be all lower case. /// - keyword must be unique + /// - if explicit references are not supported, segment5codeExplicit must be set to -1 /// \note Currently only segment 5 opcodes are supported. - void generateFunctionCode (int keyword, std::vector& code) - const; + void generateFunctionCode (int keyword, std::vector& code, + Literals& literals, const std::string& id) const; ///< Append code for function to \a code. - void generateInstructionCode (int keyword, std::vector& code) - const; + void generateInstructionCode (int keyword, std::vector& code, + Literals& literals, const std::string& id) const; ///< Append code for function to \a code. }; } diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index ece1bebaf..0be2c4151 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -314,6 +314,11 @@ namespace { code.push_back (Compiler::Generator::segment5 (56)); } + + void opGetDistanceExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (57)); + } } namespace Compiler @@ -706,9 +711,18 @@ namespace Compiler opStopScript (code); } - void getDistance (CodeContainer& code) + void getDistance (CodeContainer& code, Literals& literals, const std::string id) { - opGetDistance (code); + if (id.empty()) + { + opGetDistance (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opGetDistanceExplicit (code); + } } void getSecondsPassed (CodeContainer& code) diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 9623b7226..a7559f7e9 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -107,7 +107,7 @@ namespace Compiler void stopScript (CodeContainer& code); - void getDistance (CodeContainer& code); + void getDistance (CodeContainer& code, Literals& literals, const std::string id); void getSecondsPassed (CodeContainer& code); diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index d46d5f093..22f7f458d 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -157,6 +157,21 @@ namespace Compiler mState = EndState; return true; } + + // check for custom extensions + if (const Extensions *extensions = getContext().getExtensions()) + { + std::string argumentType; + + if (extensions->isInstruction (keyword, argumentType, mState==ExplicitState)) + { + mExprParser.parseArguments (argumentType, scanner, mCode, true); + + extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit); + mState = EndState; + return true; + } + } } if (mState==BeginState) @@ -189,21 +204,6 @@ namespace Compiler mState = EndState; return true; } - - // check for custom extensions - if (const Extensions *extensions = getContext().getExtensions()) - { - std::string argumentType; - - if (extensions->isInstruction (keyword, argumentType)) - { - mExprParser.parseArguments (argumentType, scanner, mCode, true); - - extensions->generateInstructionCode (keyword, mCode); - mState = EndState; - return true; - } - } } else if (mState==SetLocalVarState && keyword==Scanner::K_to) { diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index aae0051bd..0d77903f4 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -53,7 +53,8 @@ namespace Interpreter virtual void stopScript (const std::string& name) = 0; - virtual float getDistance (const std::string& name) const = 0; + virtual float getDistance (const std::string& name, const std::string& id = "") const + = 0; virtual float getSecondsPassed() const = 0; diff --git a/components/interpreter/controlopcodes.hpp b/components/interpreter/controlopcodes.hpp index cf9185a69..534ccc4dd 100644 --- a/components/interpreter/controlopcodes.hpp +++ b/components/interpreter/controlopcodes.hpp @@ -24,7 +24,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; + Type_Integer data = runtime[0].mInteger; runtime.pop(); if (data==0) @@ -38,7 +38,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; + Type_Integer data = runtime[0].mInteger; runtime.pop(); if (data!=0) diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index dcf204473..40ce3535b 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -115,6 +115,8 @@ op 53: push 1, if implicit reference is disabled, 0 else op 54: explicit reference = stack[0]; pop; enable explicit reference op 55: explicit reference = stack[0]; pop; disable explicit reference op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else -opcodes 57-33554431 unused +op 57: explicit reference = stack[0]; pop; + replace stack[0] with distance between explicit reference and a reference of ID stack[0] +opcodes 58-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/genericopcodes.hpp b/components/interpreter/genericopcodes.hpp index 116b586e4..44ef3fc6b 100644 --- a/components/interpreter/genericopcodes.hpp +++ b/components/interpreter/genericopcodes.hpp @@ -12,7 +12,7 @@ namespace Interpreter virtual void execute (Runtime& runtime, unsigned int arg0) { - runtime.push (arg0); + runtime.push (static_cast (arg0)); } }; @@ -22,9 +22,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Integer data = *reinterpret_cast (&runtime[0]); + Type_Integer data = runtime[0].mInteger; Type_Float floatValue = static_cast (data); - runtime[0] = *reinterpret_cast (&floatValue); + runtime[0].mFloat = floatValue; } }; @@ -34,9 +34,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Float data = *reinterpret_cast (&runtime[0]); + Type_Float data = runtime[0].mFloat; Type_Integer integerValue = static_cast (data); - runtime[0] = *reinterpret_cast (&integerValue); + runtime[0].mInteger = integerValue; } }; @@ -46,9 +46,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Integer data = *reinterpret_cast (&runtime[0]); + Type_Integer data = runtime[0].mInteger; data = -data; - runtime[0] = *reinterpret_cast (&data); + runtime[0].mInteger = data; } }; @@ -58,9 +58,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Float data = *reinterpret_cast (&runtime[0]); + Type_Float data = runtime[0].mFloat; data = -data; - runtime[0] = *reinterpret_cast (&data); + runtime[0].mFloat = data; } }; @@ -70,9 +70,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Integer data = *reinterpret_cast (&runtime[1]); + Type_Integer data = runtime[1].mInteger; Type_Float floatValue = static_cast (data); - runtime[1] = *reinterpret_cast (&floatValue); + runtime[1].mFloat = floatValue; } }; @@ -82,9 +82,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Float data = *reinterpret_cast (&runtime[1]); + Type_Float data = runtime[1].mFloat; Type_Integer integerValue = static_cast (data); - runtime[1] = *reinterpret_cast (&integerValue); + runtime[1].mInteger = integerValue; } }; } diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 522f77b95..2e22d10e5 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -103,6 +103,7 @@ namespace Interpreter // spacial interpreter.installSegment5 (49, new OpGetDistance); + interpreter.installSegment5 (57, new OpGetDistanceExplicit); } } diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 427b4b574..ea62b7ad8 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -13,10 +13,10 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; - int index = runtime[1]; + Type_Integer data = runtime[0].mInteger; + int index = runtime[1].mInteger; - runtime.getContext().setLocalShort (index, *reinterpret_cast (&data)); + runtime.getContext().setLocalShort (index, data); runtime.pop(); runtime.pop(); @@ -29,10 +29,10 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; - int index = runtime[1]; + Type_Integer data = runtime[0].mInteger; + int index = runtime[1].mInteger; - runtime.getContext().setLocalLong (index, *reinterpret_cast (&data)); + runtime.getContext().setLocalLong (index, data); runtime.pop(); runtime.pop(); @@ -45,10 +45,10 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; - int index = runtime[1]; + Type_Float data = runtime[0].mFloat; + int index = runtime[1].mInteger; - runtime.getContext().setLocalFloat (index, *reinterpret_cast (&data)); + runtime.getContext().setLocalFloat (index, data); runtime.pop(); runtime.pop(); @@ -61,8 +61,8 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int intValue = runtime.getIntegerLiteral (runtime[0]); - runtime[0] = intValue; + Type_Integer intValue = runtime.getIntegerLiteral (runtime[0].mInteger); + runtime[0].mInteger = intValue; } }; @@ -72,8 +72,8 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - float floatValue = runtime.getFloatLiteral (runtime[0]); - runtime[0] = *reinterpret_cast (&floatValue); + Type_Float floatValue = runtime.getFloatLiteral (runtime[0].mInteger); + runtime[0].mFloat = floatValue; } }; @@ -83,9 +83,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; int value = runtime.getContext().getLocalShort (index); - runtime[0] = *reinterpret_cast (&value); + runtime[0].mInteger = value; } }; @@ -95,9 +95,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; int value = runtime.getContext().getLocalLong (index); - runtime[0] = *reinterpret_cast (&value); + runtime[0].mInteger = value; } }; @@ -107,9 +107,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; float value = runtime.getContext().getLocalFloat (index); - runtime[0] = *reinterpret_cast (&value); + runtime[0].mFloat = value; } }; @@ -119,12 +119,12 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; - int index = runtime[1]; + Type_Integer data = runtime[0].mInteger; + int index = runtime[1].mInteger; std::string name = runtime.getStringLiteral (index); - runtime.getContext().setGlobalShort (name, *reinterpret_cast (&data)); + runtime.getContext().setGlobalShort (name, data); runtime.pop(); runtime.pop(); @@ -137,12 +137,12 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; - int index = runtime[1]; + Type_Integer data = runtime[0].mInteger; + int index = runtime[1].mInteger; std::string name = runtime.getStringLiteral (index); - runtime.getContext().setGlobalLong (name, *reinterpret_cast (&data)); + runtime.getContext().setGlobalLong (name, data); runtime.pop(); runtime.pop(); @@ -155,12 +155,12 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Data data = runtime[0]; - int index = runtime[1]; + Type_Float data = runtime[0].mFloat; + int index = runtime[1].mInteger; std::string name = runtime.getStringLiteral (index); - runtime.getContext().setGlobalFloat (name, *reinterpret_cast (&data)); + runtime.getContext().setGlobalFloat (name, data); runtime.pop(); runtime.pop(); @@ -173,10 +173,10 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); - int value = runtime.getContext().getGlobalShort (name); - runtime[0] = *reinterpret_cast (&value); + Type_Integer value = runtime.getContext().getGlobalShort (name); + runtime[0].mInteger = value; } }; @@ -186,10 +186,10 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); - int value = runtime.getContext().getGlobalLong (name); - runtime[0] = *reinterpret_cast (&value); + Type_Integer value = runtime.getContext().getGlobalLong (name); + runtime[0].mInteger = value; } }; @@ -199,10 +199,10 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); - float value = runtime.getContext().getGlobalFloat (name); - runtime[0] = *reinterpret_cast (&value); + Type_Float value = runtime.getContext().getGlobalFloat (name); + runtime[0].mFloat = value; } }; } diff --git a/components/interpreter/mathopcodes.hpp b/components/interpreter/mathopcodes.hpp index d569a5470..14d5d98df 100644 --- a/components/interpreter/mathopcodes.hpp +++ b/components/interpreter/mathopcodes.hpp @@ -16,14 +16,11 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - T result = - *reinterpret_cast (&runtime[1]) - + - *reinterpret_cast (&runtime[0]); + T result = getData (runtime[1]) + getData (runtime[0]); runtime.pop(); - runtime[0] = *reinterpret_cast (&result); + getData (runtime[0]) = result; } }; @@ -34,14 +31,11 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - T result = - *reinterpret_cast (&runtime[1]) - - - *reinterpret_cast (&runtime[0]); + T result = getData (runtime[1]) - getData (runtime[0]); runtime.pop(); - - runtime[0] = *reinterpret_cast (&result); + + getData (runtime[0]) = result; } }; @@ -52,14 +46,11 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - T result = - *reinterpret_cast (&runtime[1]) - * - *reinterpret_cast (&runtime[0]); + T result = getData (runtime[1]) * getData (runtime[0]); runtime.pop(); - - runtime[0] = *reinterpret_cast (&result); + + getData (runtime[0]) = result; } }; @@ -70,19 +61,16 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - T left = *reinterpret_cast (&runtime[0]); + T left = getData (runtime[0]); if (left==0) throw std::runtime_error ("division by zero"); - T result = - *reinterpret_cast (&runtime[1]) - / - left; + T result = getData (runtime[1]) / left; runtime.pop(); - - runtime[0] = *reinterpret_cast (&result); + + getData (runtime[0]) = result; } }; @@ -92,7 +80,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Float value = *reinterpret_cast (&runtime[0]); + Type_Float value = runtime[0].mFloat; if (value<0) throw std::runtime_error ( @@ -100,7 +88,7 @@ namespace Interpreter value = std::sqrt (value); - runtime[0] = *reinterpret_cast (&value); + runtime[0].mFloat = value; } }; @@ -111,13 +99,11 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int result = C() ( - *reinterpret_cast (&runtime[1]), - *reinterpret_cast (&runtime[0])); + int result = C() (getData (runtime[1]), getData (runtime[0])); runtime.pop(); - runtime[0] = *reinterpret_cast (&result); + runtime[0].mInteger = result; } }; } diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 852d2d154..8d05c58da 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -22,7 +22,7 @@ namespace Interpreter throw std::logic_error ("message box buttons not implemented yet"); // message - int index = runtime[0]; + int index = runtime[0].mInteger; runtime.pop(); std::string message = runtime.getStringLiteral (index); @@ -44,13 +44,13 @@ namespace Interpreter if (c=='S' || c=='s') { - int index = runtime[0]; + int index = runtime[0].mInteger; runtime.pop(); formattedMessage += runtime.getStringLiteral (index); } else if (c=='g' || c=='G') { - int value = *reinterpret_cast (&runtime[0]); + Type_Integer value = runtime[0].mInteger; runtime.pop(); std::ostringstream out; @@ -64,7 +64,7 @@ namespace Interpreter ++i; } - float value = *reinterpret_cast (&runtime[0]); + float value = runtime[0].mFloat; runtime.pop(); std::ostringstream out; @@ -107,7 +107,7 @@ namespace Interpreter { double r = static_cast (std::rand()) / RAND_MAX; // [0, 1) - Type_Integer limit = *reinterpret_cast (&runtime[0]); + Type_Integer limit = runtime[0].mInteger; if (limit<0) throw std::runtime_error ( @@ -115,7 +115,7 @@ namespace Interpreter Type_Integer value = static_cast (r*limit); // [o, limit) - runtime[0] = *reinterpret_cast (&value); + runtime[0].mInteger = value; } }; @@ -125,9 +125,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - float duration = runtime.getContext().getSecondsPassed(); + Type_Float duration = runtime.getContext().getSecondsPassed(); - runtime.push (*reinterpret_cast (&duration)); + runtime.push (duration); } }; @@ -167,7 +167,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; runtime.pop(); std::string id = runtime.getStringLiteral (index); @@ -181,7 +181,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; runtime.pop(); std::string id = runtime.getStringLiteral (index); @@ -195,7 +195,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - int index = runtime[0]; + int index = runtime[0].mInteger; runtime.pop(); std::string id = runtime.getStringLiteral (index); diff --git a/components/interpreter/runtime.cpp b/components/interpreter/runtime.cpp index 746be60d2..f3a3a905d 100644 --- a/components/interpreter/runtime.cpp +++ b/components/interpreter/runtime.cpp @@ -68,11 +68,25 @@ namespace Interpreter mPC = PC; } - void Runtime::push (Type_Data data) + void Runtime::push (const Data& data) { mStack.push_back (data); } + void Runtime::push (Type_Integer value) + { + Data data; + data.mInteger = value; + push (data); + } + + void Runtime::push (Type_Float value) + { + Data data; + data.mFloat = value; + push (data); + } + void Runtime::pop() { if (mStack.empty()) @@ -81,7 +95,7 @@ namespace Interpreter mStack.resize (mStack.size()-1); } - Type_Data& Runtime::operator[] (int Index) + Data& Runtime::operator[] (int Index) { if (Index<0 || Index>=static_cast (mStack.size())) throw std::runtime_error ("stack index out of range"); diff --git a/components/interpreter/runtime.hpp b/components/interpreter/runtime.hpp index 73e90f68a..e9ba01041 100644 --- a/components/interpreter/runtime.hpp +++ b/components/interpreter/runtime.hpp @@ -18,7 +18,7 @@ namespace Interpreter const Type_Code *mCode; int mCodeSize; int mPC; - std::vector mStack; + std::vector mStack; public: @@ -42,13 +42,19 @@ namespace Interpreter void setPC (int PC); ///< set program counter. - void push (Type_Data data); + void push (const Data& data); ///< push data on stack + void push (Type_Integer value); + ///< push integer data on stack. + + void push (Type_Float value); + ///< push float data on stack. + void pop(); ///< pop stack - Type_Data& operator[] (int Index); + Data& operator[] (int Index); ///< Access stack member, counted from the top. Context& getContext(); diff --git a/components/interpreter/scriptopcodes.hpp b/components/interpreter/scriptopcodes.hpp index 84fd546fb..56502d510 100644 --- a/components/interpreter/scriptopcodes.hpp +++ b/components/interpreter/scriptopcodes.hpp @@ -13,8 +13,8 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - std::string name = runtime.getStringLiteral (runtime[0]); - runtime[0] = runtime.getContext().isScriptRunning (name); + std::string name = runtime.getStringLiteral (runtime[0].mInteger); + runtime[0].mInteger = runtime.getContext().isScriptRunning (name); } }; @@ -24,7 +24,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - std::string name = runtime.getStringLiteral (runtime[0]); + std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); runtime.getContext().startScript (name); } @@ -36,7 +36,7 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - std::string name = runtime.getStringLiteral (runtime[0]); + std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); runtime.getContext().stopScript (name); } diff --git a/components/interpreter/spatialopcodes.hpp b/components/interpreter/spatialopcodes.hpp index 2a401ae8a..e37df8116 100644 --- a/components/interpreter/spatialopcodes.hpp +++ b/components/interpreter/spatialopcodes.hpp @@ -12,13 +12,31 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - std::string name = runtime.getStringLiteral (runtime[0]); + std::string name = runtime.getStringLiteral (runtime[0].mInteger); - float distance = runtime.getContext().getDistance (name); + Type_Float distance = runtime.getContext().getDistance (name); - runtime[0] = *reinterpret_cast (&distance); + runtime[0].mFloat = distance; } }; + + class OpGetDistanceExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0].mInteger; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + std::string name = runtime.getStringLiteral (runtime[0].mInteger); + + Type_Float distance = runtime.getContext().getDistance (name, id); + + runtime[0].mFloat = distance; + } + }; } #endif diff --git a/components/interpreter/types.hpp b/components/interpreter/types.hpp index 2747d1447..89529189f 100644 --- a/components/interpreter/types.hpp +++ b/components/interpreter/types.hpp @@ -1,6 +1,8 @@ #ifndef INTERPRETER_TYPES_H_INCLUDED #define INTERPRETER_TYPES_H_INCLUDED +#include + namespace Interpreter { typedef unsigned int Type_Code; // 32 bit @@ -12,6 +14,30 @@ namespace Interpreter typedef int Type_Integer; // 32 bit typedef float Type_Float; // 32 bit + + union Data + { + Type_Integer mInteger; + Type_Float mFloat; + }; + + template + T& getData (Data& data) + { + throw std::runtime_error ("unsupported data type"); + } + + template<> + inline Type_Integer& getData (Data& data) + { + return data.mInteger; + } + + template<> + inline Type_Float& getData (Data& data) + { + return data.mFloat; + } } #endif