Merge branch 'master' into oengine

This commit is contained in:
Nicolay Korslund 2010-07-16 11:47:26 +02:00
commit 186bf8c1a1
34 changed files with 829 additions and 559 deletions

View file

@ -110,7 +110,7 @@ namespace SAInterpreter
void Context::stopScript (const std::string& name) {} 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; return 0;
} }

View file

@ -58,7 +58,7 @@ namespace SAInterpreter
virtual void stopScript (const std::string& name); 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; virtual float getSecondsPassed() const;

View file

@ -35,6 +35,7 @@ set(GAMESCRIPT
mwscript/cellextensions.cpp mwscript/cellextensions.cpp
mwscript/miscextensions.cpp mwscript/miscextensions.cpp
mwscript/guiextensions.cpp mwscript/guiextensions.cpp
mwscript/soundextensions.cpp
mwscript/extensions.cpp mwscript/extensions.cpp
mwscript/globalscripts.cpp mwscript/globalscripts.cpp
) )
@ -46,17 +47,16 @@ set(GAMESCRIPT_HEADER
mwscript/cellextensions.hpp mwscript/cellextensions.hpp
mwscript/miscextensions.hpp mwscript/miscextensions.hpp
mwscript/guiextensions.hpp mwscript/guiextensions.hpp
mwscript/soundextensions.hpp
mwscript/extensions.hpp mwscript/extensions.hpp
mwscript/globalscripts.hpp mwscript/globalscripts.hpp
) )
source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER}) source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER})
set(GAMESOUND set(GAMESOUND
mwsound/soundmanager.cpp mwsound/soundmanager.cpp)
mwsound/extensions.cpp)
set(GAMESOUND_HEADER set(GAMESOUND_HEADER
mwsound/soundmanager.hpp mwsound/soundmanager.hpp)
mwsound/extensions.hpp)
source_group(apps\\openmw\\mwsound FILES ${GAMESOUND} ${GAMESOUND_HEADER}) source_group(apps\\openmw\\mwsound FILES ${GAMESOUND} ${GAMESOUND_HEADER})
set(GAMEGUI set(GAMEGUI

View file

@ -46,5 +46,13 @@ op 0x2000015: EnableMapMenu
op 0x2000016: EnableStatsMenu op 0x2000016: EnableStatsMenu
op 0x2000017: EnableRest op 0x2000017: EnableRest
op 0x2000018: ShowRestMenu 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

View file

@ -1,8 +1,7 @@
#include "extensions.hpp" #include "extensions.hpp"
#include "../mwsound/extensions.hpp" #include "soundextensions.hpp"
#include "cellextensions.hpp" #include "cellextensions.hpp"
#include "miscextensions.hpp" #include "miscextensions.hpp"
#include "guiextensions.hpp" #include "guiextensions.hpp"
@ -14,7 +13,7 @@ namespace MWScript
Cell::registerExtensions (extensions); Cell::registerExtensions (extensions);
Misc::registerExtensions (extensions); Misc::registerExtensions (extensions);
Gui::registerExtensions (extensions); Gui::registerExtensions (extensions);
MWSound::registerExtensions (extensions); Sound::registerExtensions (extensions);
} }
} }

View file

@ -16,11 +16,9 @@
namespace MWScript namespace MWScript
{ {
InterpreterContext::PtrWithCell InterpreterContext::getReference ( MWWorld::Ptr InterpreterContext::getReference (
const std::string& id, bool activeOnly) const std::string& id, bool activeOnly)
{ {
PtrWithCell ref;
if (!id.empty()) if (!id.empty())
{ {
return mEnvironment.mWorld->getPtr (id, activeOnly); return mEnvironment.mWorld->getPtr (id, activeOnly);
@ -30,15 +28,13 @@ namespace MWScript
if (mReference.isEmpty()) if (mReference.isEmpty())
throw std::runtime_error ("no implicit reference"); 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 const std::string& id, bool activeOnly) const
{ {
CPtrWithCell ref;
if (!id.empty()) if (!id.empty())
{ {
return mEnvironment.mWorld->getPtr (id, activeOnly); return mEnvironment.mWorld->getPtr (id, activeOnly);
@ -48,7 +44,7 @@ namespace MWScript
if (mReference.isEmpty()) if (mReference.isEmpty())
throw std::runtime_error ("no implicit reference"); 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); 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()) // TODO handle exterior cells (when ref and ref2 are located in different cells)
throw std::runtime_error ("no implicit reference"); const MWWorld::Ptr ref2 = getReference (id, false);
std::pair<MWWorld::Ptr, MWWorld::World::CellStore *> ref = const MWWorld::Ptr ref = mEnvironment.mWorld->getPtr (name, true);
mEnvironment.mWorld->getPtr (name, true);
double diff[3]; double diff[3];
for (int i=0; i<3; ++i) 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]); 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 bool InterpreterContext::isDisabled (const std::string& id) const
{ {
CPtrWithCell ref = getReference (id, false); const MWWorld::Ptr ref = getReference (id, false);
return !ref.first.getRefData().isEnabled(); return !ref.getRefData().isEnabled();
} }
void InterpreterContext::enable (const std::string& id) void InterpreterContext::enable (const std::string& id)
{ {
PtrWithCell ref = getReference (id, false); MWWorld::Ptr ref = getReference (id, false);
mEnvironment.mWorld->enable (ref); mEnvironment.mWorld->enable (ref);
} }
void InterpreterContext::disable (const std::string& id) void InterpreterContext::disable (const std::string& id)
{ {
PtrWithCell ref = getReference (id, false); MWWorld::Ptr ref = getReference (id, false);
mEnvironment.mWorld->disable (ref); mEnvironment.mWorld->disable (ref);
} }

View file

@ -22,12 +22,10 @@ namespace MWScript
Locals *mLocals; Locals *mLocals;
MWWorld::Ptr mReference; MWWorld::Ptr mReference;
typedef std::pair<MWWorld::Ptr, MWWorld::World::CellStore *> PtrWithCell;
typedef std::pair<const MWWorld::Ptr, const MWWorld::World::CellStore *> CPtrWithCell;
PtrWithCell getReference (const std::string& id, bool activeOnly); MWWorld::Ptr getReference (const std::string& id, bool activeOnly);
CPtrWithCell getReference (const std::string& id, bool activeOnly) const; const MWWorld::Ptr getReference (const std::string& id, bool activeOnly) const;
public: public:
@ -70,7 +68,7 @@ namespace MWScript
virtual void stopScript (const std::string& name); 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; virtual bool hasBeenActivated() const;

View file

@ -15,8 +15,7 @@
#include <components/interpreter/installopcodes.hpp> #include <components/interpreter/installopcodes.hpp>
#include <components/interpreter/interpreter.hpp> #include <components/interpreter/interpreter.hpp>
#include "../mwsound/extensions.hpp" #include "soundextensions.hpp"
#include "cellextensions.hpp" #include "cellextensions.hpp"
#include "miscextensions.hpp" #include "miscextensions.hpp"
#include "guiextensions.hpp" #include "guiextensions.hpp"
@ -125,7 +124,7 @@ namespace MWScript
Cell::installOpcodes (interpreter); Cell::installOpcodes (interpreter);
Misc::installOpcodes (interpreter); Misc::installOpcodes (interpreter);
Gui::installOpcodes (interpreter); Gui::installOpcodes (interpreter);
MWSound::installOpcodes (interpreter); Sound::installOpcodes (interpreter);
} }
} }

View file

@ -0,0 +1,398 @@
#include "extensions.hpp"
#include <components/compiler/extensions.hpp>
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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);
}
}
}

View file

@ -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

View file

@ -1,236 +0,0 @@
#include "extensions.hpp"
#include <components/compiler/extensions.hpp>
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
float volume = *reinterpret_cast<float *> (&runtime[0]);
runtime.pop();
float pitch = *reinterpret_cast<float *> (&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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
float volume = *reinterpret_cast<float *> (&runtime[0]);
runtime.pop();
float pitch = *reinterpret_cast<float *> (&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<MWScript::InterpreterContext&> (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<MWScript::InterpreterContext&> (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);
}
}

View file

@ -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

View file

@ -15,13 +15,18 @@ namespace MWWorld
class Ptr class Ptr
{ {
public:
typedef ESMS::CellStore<RefData> CellStore;
boost::any mPtr; boost::any mPtr;
ESM::CellRef *mCellRef; ESM::CellRef *mCellRef;
RefData *mRefData; RefData *mRefData;
CellStore *mCell;
public: public:
Ptr() : mCellRef (0), mRefData (0) {} Ptr() : mCellRef (0), mRefData (0), mCell (0) {}
bool isEmpty() const bool isEmpty() const
{ {
@ -29,11 +34,12 @@ namespace MWWorld
} }
template<typename T> template<typename T>
Ptr (ESMS::LiveCellRef<T, RefData> *liveCellRef) Ptr (ESMS::LiveCellRef<T, RefData> *liveCellRef, CellStore *cell)
{ {
mPtr = liveCellRef; mPtr = liveCellRef;
mCellRef = &liveCellRef->ref; mCellRef = &liveCellRef->ref;
mRefData = &liveCellRef->mData; mRefData = &liveCellRef->mData;
mCell = cell;
} }
template<typename T> template<typename T>
@ -53,6 +59,12 @@ namespace MWWorld
assert (mRefData); assert (mRefData);
return *mRefData; return *mRefData;
} }
Ptr::CellStore *getCell() const
{
assert (mCell);
return mCell;
}
}; };
} }

View file

@ -15,7 +15,8 @@ namespace
{ {
template<typename T> template<typename T>
void listCellScripts (const ESMS::ESMStore& store, void listCellScripts (const ESMS::ESMStore& store,
ESMS::CellRefList<T, MWWorld::RefData>& cellRefList, MWWorld::World::ScriptList& scriptList) ESMS::CellRefList<T, MWWorld::RefData>& cellRefList, MWWorld::World::ScriptList& scriptList,
MWWorld::Ptr::CellStore *cell)
{ {
for (typename ESMS::CellRefList<T, MWWorld::RefData>::List::iterator iter ( for (typename ESMS::CellRefList<T, MWWorld::RefData>::List::iterator iter (
cellRefList.list.begin()); cellRefList.list.begin());
@ -28,116 +29,102 @@ namespace
iter->mData.setLocals (*script); iter->mData.setLocals (*script);
scriptList.push_back ( scriptList.push_back (
std::make_pair (iter->base->script, MWWorld::Ptr (&*iter))); std::make_pair (iter->base->script, MWWorld::Ptr (&*iter, cell)));
} }
} }
} }
} }
template<typename T>
bool hasReference (ESMS::CellRefList<T, MWWorld::RefData>& cellRefList, const MWWorld::Ptr& ptr)
{
for (typename ESMS::CellRefList<T, MWWorld::RefData>::List::iterator iter (
cellRefList.list.begin());
iter!=cellRefList.list.end(); ++iter)
{
if (&iter->mData==&ptr.getRefData())
return true;
}
return false;
}
} }
namespace MWWorld namespace MWWorld
{ {
void World::insertInteriorScripts (ESMS::CellStore<RefData>& cell) void World::insertInteriorScripts (ESMS::CellStore<RefData>& cell)
{ {
listCellScripts (mStore, cell.activators, mLocalScripts); listCellScripts (mStore, cell.activators, mLocalScripts, &cell);
listCellScripts (mStore, cell.potions, mLocalScripts); listCellScripts (mStore, cell.potions, mLocalScripts, &cell);
listCellScripts (mStore, cell.appas, mLocalScripts); listCellScripts (mStore, cell.appas, mLocalScripts, &cell);
listCellScripts (mStore, cell.armors, mLocalScripts); listCellScripts (mStore, cell.armors, mLocalScripts, &cell);
listCellScripts (mStore, cell.books, mLocalScripts); listCellScripts (mStore, cell.books, mLocalScripts, &cell);
listCellScripts (mStore, cell.clothes, mLocalScripts); listCellScripts (mStore, cell.clothes, mLocalScripts, &cell);
listCellScripts (mStore, cell.containers, mLocalScripts); listCellScripts (mStore, cell.containers, mLocalScripts, &cell);
listCellScripts (mStore, cell.creatures, mLocalScripts); listCellScripts (mStore, cell.creatures, mLocalScripts, &cell);
listCellScripts (mStore, cell.doors, mLocalScripts); listCellScripts (mStore, cell.doors, mLocalScripts, &cell);
listCellScripts (mStore, cell.ingreds, mLocalScripts); listCellScripts (mStore, cell.ingreds, mLocalScripts, &cell);
listCellScripts (mStore, cell.lights, mLocalScripts); listCellScripts (mStore, cell.lights, mLocalScripts, &cell);
listCellScripts (mStore, cell.lockpicks, mLocalScripts); listCellScripts (mStore, cell.lockpicks, mLocalScripts, &cell);
listCellScripts (mStore, cell.miscItems, mLocalScripts); listCellScripts (mStore, cell.miscItems, mLocalScripts, &cell);
listCellScripts (mStore, cell.npcs, mLocalScripts); listCellScripts (mStore, cell.npcs, mLocalScripts, &cell);
listCellScripts (mStore, cell.probes, mLocalScripts); listCellScripts (mStore, cell.probes, mLocalScripts, &cell);
listCellScripts (mStore, cell.repairs, mLocalScripts); listCellScripts (mStore, cell.repairs, mLocalScripts, &cell);
listCellScripts (mStore, cell.weapons, mLocalScripts); 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<ESM::Activator, RefData> *ref = cell.activators.find (name)) if (ESMS::LiveCellRef<ESM::Activator, RefData> *ref = cell.activators.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Potion, RefData> *ref = cell.potions.find (name)) if (ESMS::LiveCellRef<ESM::Potion, RefData> *ref = cell.potions.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Apparatus, RefData> *ref = cell.appas.find (name)) if (ESMS::LiveCellRef<ESM::Apparatus, RefData> *ref = cell.appas.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Armor, RefData> *ref = cell.armors.find (name)) if (ESMS::LiveCellRef<ESM::Armor, RefData> *ref = cell.armors.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Book, RefData> *ref = cell.books.find (name)) if (ESMS::LiveCellRef<ESM::Book, RefData> *ref = cell.books.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Clothing, RefData> *ref = cell.clothes.find (name)) if (ESMS::LiveCellRef<ESM::Clothing, RefData> *ref = cell.clothes.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Container, RefData> *ref = cell.containers.find (name)) if (ESMS::LiveCellRef<ESM::Container, RefData> *ref = cell.containers.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Creature, RefData> *ref = cell.creatures.find (name)) if (ESMS::LiveCellRef<ESM::Creature, RefData> *ref = cell.creatures.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Door, RefData> *ref = cell.doors.find (name)) if (ESMS::LiveCellRef<ESM::Door, RefData> *ref = cell.doors.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Ingredient, RefData> *ref = cell.ingreds.find (name)) if (ESMS::LiveCellRef<ESM::Ingredient, RefData> *ref = cell.ingreds.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::CreatureLevList, RefData> *ref = cell.creatureLists.find (name)) if (ESMS::LiveCellRef<ESM::CreatureLevList, RefData> *ref = cell.creatureLists.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::ItemLevList, RefData> *ref = cell.itemLists.find (name)) if (ESMS::LiveCellRef<ESM::ItemLevList, RefData> *ref = cell.itemLists.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Light, RefData> *ref = cell.lights.find (name)) if (ESMS::LiveCellRef<ESM::Light, RefData> *ref = cell.lights.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = cell.lockpicks.find (name)) if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = cell.lockpicks.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Misc, RefData> *ref = cell.miscItems.find (name)) if (ESMS::LiveCellRef<ESM::Misc, RefData> *ref = cell.miscItems.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::NPC, RefData> *ref = cell.npcs.find (name)) if (ESMS::LiveCellRef<ESM::NPC, RefData> *ref = cell.npcs.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = cell.probes.find (name)) if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = cell.probes.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = cell.repairs.find (name)) if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = cell.repairs.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Static, RefData> *ref = cell.statics.find (name)) if (ESMS::LiveCellRef<ESM::Static, RefData> *ref = cell.statics.find (name))
return ref; return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Weapon, RefData> *ref = cell.weapons.find (name)) if (ESMS::LiveCellRef<ESM::Weapon, RefData> *ref = cell.weapons.find (name))
return ref; return Ptr (ref, &cell);
return Ptr(); return Ptr();
} }
MWRender::CellRender *World::searchRender (CellStore *store) MWRender::CellRender *World::searchRender (Ptr::CellStore *store)
{ {
CellRenderCollection::iterator iter = mActiveCells.find (store); CellRenderCollection::iterator iter = mActiveCells.find (store);
@ -157,7 +144,7 @@ namespace MWWorld
World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
const std::string& master, const std::string& startCell, bool newGame) 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); boost::filesystem::path masterPath (dataDir);
masterPath /= master; masterPath /= master;
@ -169,6 +156,7 @@ namespace MWWorld
mStore.load (mEsm); mStore.load (mEsm);
mInteriors[startCell].loadInt (startCell, mStore, mEsm); mInteriors[startCell].loadInt (startCell, mStore, mEsm);
mCurrentCell = &mInteriors[startCell];
insertInteriorScripts (mInteriors[startCell]); insertInteriorScripts (mInteriors[startCell]);
@ -251,15 +239,12 @@ namespace MWWorld
return iter->second; return iter->second;
} }
std::pair<Ptr, World::CellStore *> 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. // the player is always in an active cell.
if (name=="player") if (name=="player")
{ {
// TODO: find real cell (might need to be stored in playerPos). For now we return Ptr (mPlayerPos->getPlayer(), mCurrentCell);
// 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);
} }
// active cells // active cells
@ -269,7 +254,7 @@ namespace MWWorld
Ptr ptr = getPtr (name, *iter->first); Ptr ptr = getPtr (name, *iter->first);
if (!ptr.isEmpty()) if (!ptr.isEmpty())
return std::make_pair (ptr, iter->first); return ptr;
} }
if (!activeOnly) if (!activeOnly)
@ -280,58 +265,29 @@ namespace MWWorld
throw std::runtime_error ("unknown ID: " + name); throw std::runtime_error ("unknown ID: " + name);
} }
void World::enable (std::pair<Ptr, CellStore *>& 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<Ptr, CellStore *>& 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");
}
} }

View file

@ -36,20 +36,20 @@ namespace MWWorld
public: public:
typedef std::vector<std::pair<std::string, Ptr> > ScriptList; typedef std::vector<std::pair<std::string, Ptr> > ScriptList;
typedef ESMS::CellStore<RefData> CellStore;
private: private:
typedef std::map<CellStore *, MWRender::CellRender *> CellRenderCollection; typedef std::map<Ptr::CellStore *, MWRender::CellRender *> CellRenderCollection;
MWRender::SkyManager* mSkyManager; MWRender::SkyManager* mSkyManager;
MWRender::MWScene mScene; MWRender::MWScene mScene;
MWRender::PlayerPos *mPlayerPos; MWRender::PlayerPos *mPlayerPos;
Ptr::CellStore *mCurrentCell; // the cell, the player is in
CellRenderCollection mActiveCells; CellRenderCollection mActiveCells;
CellRenderCollection mBufferedCells; // loaded, but not active (buffering not implementd yet) CellRenderCollection mBufferedCells; // loaded, but not active (buffering not implementd yet)
ESM::ESMReader mEsm; ESM::ESMReader mEsm;
ESMS::ESMStore mStore; ESMS::ESMStore mStore;
std::map<std::string, CellStore> mInteriors; std::map<std::string, Ptr::CellStore> mInteriors;
ScriptList mLocalScripts; ScriptList mLocalScripts;
std::map<std::string, Interpreter::Type_Data> mGlobalVariables; std::map<std::string, Interpreter::Type_Data> mGlobalVariables;
@ -59,9 +59,9 @@ namespace MWWorld
void insertInteriorScripts (ESMS::CellStore<RefData>& cell); void insertInteriorScripts (ESMS::CellStore<RefData>& 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: public:
@ -82,16 +82,13 @@ namespace MWWorld
Interpreter::Type_Data& getGlobalVariable (const std::string& name); Interpreter::Type_Data& getGlobalVariable (const std::string& name);
std::pair<Ptr, CellStore *> 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. ///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells. /// \param activeOnly do non search inactive cells.
void enable (std::pair<Ptr, CellStore *>& reference); void enable (Ptr reference);
void disable (std::pair<Ptr, CellStore *>& reference); void disable (Ptr reference);
CellStore *find (const Ptr& ptr);
///< Only active cells are searched.
}; };
} }

View file

@ -311,6 +311,40 @@ namespace Compiler
mNextOperand = false; mNextOperand = false;
return true; 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); return Parser::parseKeyword (keyword, loc, scanner);
@ -360,18 +394,18 @@ namespace Compiler
mNextOperand = false; mNextOperand = false;
return true; return true;
} }
else if (keyword==Scanner::K_getdistance) else if (keyword==Scanner::K_getdistance)
{ {
mTokenLoc = loc; mTokenLoc = loc;
parseArguments ("c", scanner); parseArguments ("c", scanner);
Generator::getDistance (mCode); Generator::getDistance (mCode, mLiterals, "");
mOperands.push_back ('f'); mOperands.push_back ('f');
mNextOperand = false; mNextOperand = false;
return true; return true;
} }
else if (keyword==Scanner::K_getsecondspassed) else if (keyword==Scanner::K_getsecondspassed)
{ {
mTokenLoc = loc; mTokenLoc = loc;
@ -400,12 +434,12 @@ namespace Compiler
char returnType; char returnType;
std::string argumentType; std::string argumentType;
if (extensions->isFunction (keyword, returnType, argumentType)) if (extensions->isFunction (keyword, returnType, argumentType, false))
{ {
mTokenLoc = loc; mTokenLoc = loc;
parseArguments (argumentType, scanner); parseArguments (argumentType, scanner);
extensions->generateFunctionCode (keyword, mCode); extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
mOperands.push_back (returnType); mOperands.push_back (returnType);
mNextOperand = false; mNextOperand = false;

View file

@ -5,6 +5,7 @@
#include <stdexcept> #include <stdexcept>
#include "generator.hpp" #include "generator.hpp"
#include "literals.hpp"
namespace Compiler namespace Compiler
{ {
@ -20,31 +21,39 @@ namespace Compiler
return iter->second; 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<int, Function>::const_iterator iter = mFunctions.find (keyword); std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
if (iter==mFunctions.end()) if (iter==mFunctions.end())
return false; return false;
if (explicitReference && iter->second.mCodeExplicit==-1)
return false;
returnType = iter->second.mReturn; returnType = iter->second.mReturn;
argumentType = iter->second.mArguments; argumentType = iter->second.mArguments;
return true; return true;
} }
bool Extensions::isInstruction (int keyword, std::string& argumentType) const bool Extensions::isInstruction (int keyword, std::string& argumentType,
bool explicitReference) const
{ {
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword); std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
if (iter==mInstructions.end()) if (iter==mInstructions.end())
return false; return false;
if (explicitReference && iter->second.mCodeExplicit==-1)
return false;
argumentType = iter->second.mArguments; argumentType = iter->second.mArguments;
return true; return true;
} }
void Extensions::registerFunction (const std::string& keyword, char returnType, 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); assert (segment5code>=33554432 && segment5code<=67108863);
@ -56,12 +65,13 @@ namespace Compiler
function.mReturn = returnType; function.mReturn = returnType;
function.mArguments = argumentType; function.mArguments = argumentType;
function.mCode = segment5code; function.mCode = segment5code;
function.mCodeExplicit = segment5codeExplicit;
mFunctions.insert (std::make_pair (code, function)); mFunctions.insert (std::make_pair (code, function));
} }
void Extensions::registerInstruction (const std::string& keyword, 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); assert (segment5code>=33554432 && segment5code<=67108863);
@ -72,23 +82,34 @@ namespace Compiler
Instruction instruction; Instruction instruction;
instruction.mArguments = argumentType; instruction.mArguments = argumentType;
instruction.mCode = segment5code; instruction.mCode = segment5code;
instruction.mCodeExplicit = segment5codeExplicit;
mInstructions.insert (std::make_pair (code, instruction)); mInstructions.insert (std::make_pair (code, instruction));
} }
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code) void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
const Literals& literals, const std::string& id) const
{ {
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword); std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
if (iter==mFunctions.end()) if (iter==mFunctions.end())
throw std::logic_error ("unknown custom function keyword"); 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, void Extensions::generateInstructionCode (int keyword,
std::vector<Interpreter::Type_Code>& code) std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id)
const const
{ {
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword); std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
@ -96,6 +117,16 @@ namespace Compiler
if (iter==mInstructions.end()) if (iter==mInstructions.end())
throw std::logic_error ("unknown custom instruction keyword"); 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));
} }
} }

View file

@ -9,6 +9,8 @@
namespace Compiler namespace Compiler
{ {
class Literals;
/// \brief Collection of compiler extensions /// \brief Collection of compiler extensions
class Extensions class Extensions
@ -18,12 +20,14 @@ namespace Compiler
char mReturn; char mReturn;
std::string mArguments; std::string mArguments;
int mCode; int mCode;
int mCodeExplicit;
}; };
struct Instruction struct Instruction
{ {
std::string mArguments; std::string mArguments;
int mCode; int mCode;
int mCodeExplicit;
}; };
int mNextKeywordIndex; int mNextKeywordIndex;
@ -40,33 +44,37 @@ namespace Compiler
/// - if no match is found 0 is returned. /// - if no match is found 0 is returned.
/// - keyword must be all lower case. /// - 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 ///< Is this keyword registered with a function? If yes, return return and argument
/// types. /// 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. ///< Is this keyword registered with a function? If yes, return argument types.
void registerFunction (const std::string& keyword, char returnType, 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 ///< Register a custom function
/// - keyword must be all lower case. /// - keyword must be all lower case.
/// - keyword must be unique /// - keyword must be unique
/// - if explicit references are not supported, segment5codeExplicit must be set to -1
/// \note Currently only segment 5 opcodes are supported. /// \note Currently only segment 5 opcodes are supported.
void registerInstruction (const std::string& keyword, 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 ///< Register a custom instruction
/// - keyword must be all lower case. /// - keyword must be all lower case.
/// - keyword must be unique /// - keyword must be unique
/// - if explicit references are not supported, segment5codeExplicit must be set to -1
/// \note Currently only segment 5 opcodes are supported. /// \note Currently only segment 5 opcodes are supported.
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code) void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
const; Literals& literals, const std::string& id) const;
///< Append code for function to \a code. ///< Append code for function to \a code.
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code) void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
const; Literals& literals, const std::string& id) const;
///< Append code for function to \a code. ///< Append code for function to \a code.
}; };
} }

View file

@ -314,6 +314,11 @@ namespace
{ {
code.push_back (Compiler::Generator::segment5 (56)); code.push_back (Compiler::Generator::segment5 (56));
} }
void opGetDistanceExplicit (Compiler::Generator::CodeContainer& code)
{
code.push_back (Compiler::Generator::segment5 (57));
}
} }
namespace Compiler namespace Compiler
@ -706,9 +711,18 @@ namespace Compiler
opStopScript (code); 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) void getSecondsPassed (CodeContainer& code)

View file

@ -107,7 +107,7 @@ namespace Compiler
void stopScript (CodeContainer& code); void stopScript (CodeContainer& code);
void getDistance (CodeContainer& code); void getDistance (CodeContainer& code, Literals& literals, const std::string id);
void getSecondsPassed (CodeContainer& code); void getSecondsPassed (CodeContainer& code);

View file

@ -157,6 +157,21 @@ namespace Compiler
mState = EndState; mState = EndState;
return true; 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) if (mState==BeginState)
@ -189,21 +204,6 @@ namespace Compiler
mState = EndState; mState = EndState;
return true; 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) else if (mState==SetLocalVarState && keyword==Scanner::K_to)
{ {

View file

@ -53,7 +53,8 @@ namespace Interpreter
virtual void stopScript (const std::string& name) = 0; 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; virtual float getSecondsPassed() const = 0;

View file

@ -24,7 +24,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Integer data = runtime[0].mInteger;
runtime.pop(); runtime.pop();
if (data==0) if (data==0)
@ -38,7 +38,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Integer data = runtime[0].mInteger;
runtime.pop(); runtime.pop();
if (data!=0) if (data!=0)

View file

@ -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 54: explicit reference = stack[0]; pop; enable explicit reference
op 55: explicit reference = stack[0]; pop; disable 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 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 opcodes 33554432-67108863 reserved for extensions

View file

@ -12,7 +12,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime, unsigned int arg0) virtual void execute (Runtime& runtime, unsigned int arg0)
{ {
runtime.push (arg0); runtime.push (static_cast<Type_Integer> (arg0));
} }
}; };
@ -22,9 +22,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[0]); Type_Integer data = runtime[0].mInteger;
Type_Float floatValue = static_cast<Type_Float> (data); Type_Float floatValue = static_cast<Type_Float> (data);
runtime[0] = *reinterpret_cast<Type_Data *> (&floatValue); runtime[0].mFloat = floatValue;
} }
}; };
@ -34,9 +34,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[0]); Type_Float data = runtime[0].mFloat;
Type_Integer integerValue = static_cast<Type_Integer> (data); Type_Integer integerValue = static_cast<Type_Integer> (data);
runtime[0] = *reinterpret_cast<Type_Data *> (&integerValue); runtime[0].mInteger = integerValue;
} }
}; };
@ -46,9 +46,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[0]); Type_Integer data = runtime[0].mInteger;
data = -data; data = -data;
runtime[0] = *reinterpret_cast<Type_Data *> (&data); runtime[0].mInteger = data;
} }
}; };
@ -58,9 +58,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[0]); Type_Float data = runtime[0].mFloat;
data = -data; data = -data;
runtime[0] = *reinterpret_cast<Type_Data *> (&data); runtime[0].mFloat = data;
} }
}; };
@ -70,9 +70,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[1]); Type_Integer data = runtime[1].mInteger;
Type_Float floatValue = static_cast<Type_Float> (data); Type_Float floatValue = static_cast<Type_Float> (data);
runtime[1] = *reinterpret_cast<Type_Data *> (&floatValue); runtime[1].mFloat = floatValue;
} }
}; };
@ -82,9 +82,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[1]); Type_Float data = runtime[1].mFloat;
Type_Integer integerValue = static_cast<Type_Integer> (data); Type_Integer integerValue = static_cast<Type_Integer> (data);
runtime[1] = *reinterpret_cast<Type_Data *> (&integerValue); runtime[1].mInteger = integerValue;
} }
}; };
} }

View file

@ -103,6 +103,7 @@ namespace Interpreter
// spacial // spacial
interpreter.installSegment5 (49, new OpGetDistance); interpreter.installSegment5 (49, new OpGetDistance);
interpreter.installSegment5 (57, new OpGetDistanceExplicit);
} }
} }

View file

@ -13,10 +13,10 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Integer data = runtime[0].mInteger;
int index = runtime[1]; int index = runtime[1].mInteger;
runtime.getContext().setLocalShort (index, *reinterpret_cast<int *> (&data)); runtime.getContext().setLocalShort (index, data);
runtime.pop(); runtime.pop();
runtime.pop(); runtime.pop();
@ -29,10 +29,10 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Integer data = runtime[0].mInteger;
int index = runtime[1]; int index = runtime[1].mInteger;
runtime.getContext().setLocalLong (index, *reinterpret_cast<int *> (&data)); runtime.getContext().setLocalLong (index, data);
runtime.pop(); runtime.pop();
runtime.pop(); runtime.pop();
@ -45,10 +45,10 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Float data = runtime[0].mFloat;
int index = runtime[1]; int index = runtime[1].mInteger;
runtime.getContext().setLocalFloat (index, *reinterpret_cast<float *> (&data)); runtime.getContext().setLocalFloat (index, data);
runtime.pop(); runtime.pop();
runtime.pop(); runtime.pop();
@ -61,8 +61,8 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int intValue = runtime.getIntegerLiteral (runtime[0]); Type_Integer intValue = runtime.getIntegerLiteral (runtime[0].mInteger);
runtime[0] = intValue; runtime[0].mInteger = intValue;
} }
}; };
@ -72,8 +72,8 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
float floatValue = runtime.getFloatLiteral (runtime[0]); Type_Float floatValue = runtime.getFloatLiteral (runtime[0].mInteger);
runtime[0] = *reinterpret_cast<Type_Data *> (&floatValue); runtime[0].mFloat = floatValue;
} }
}; };
@ -83,9 +83,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
int value = runtime.getContext().getLocalShort (index); int value = runtime.getContext().getLocalShort (index);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mInteger = value;
} }
}; };
@ -95,9 +95,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
int value = runtime.getContext().getLocalLong (index); int value = runtime.getContext().getLocalLong (index);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mInteger = value;
} }
}; };
@ -107,9 +107,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
float value = runtime.getContext().getLocalFloat (index); float value = runtime.getContext().getLocalFloat (index);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mFloat = value;
} }
}; };
@ -119,12 +119,12 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Integer data = runtime[0].mInteger;
int index = runtime[1]; int index = runtime[1].mInteger;
std::string name = runtime.getStringLiteral (index); std::string name = runtime.getStringLiteral (index);
runtime.getContext().setGlobalShort (name, *reinterpret_cast<int *> (&data)); runtime.getContext().setGlobalShort (name, data);
runtime.pop(); runtime.pop();
runtime.pop(); runtime.pop();
@ -137,12 +137,12 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Integer data = runtime[0].mInteger;
int index = runtime[1]; int index = runtime[1].mInteger;
std::string name = runtime.getStringLiteral (index); std::string name = runtime.getStringLiteral (index);
runtime.getContext().setGlobalLong (name, *reinterpret_cast<int *> (&data)); runtime.getContext().setGlobalLong (name, data);
runtime.pop(); runtime.pop();
runtime.pop(); runtime.pop();
@ -155,12 +155,12 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Data data = runtime[0]; Type_Float data = runtime[0].mFloat;
int index = runtime[1]; int index = runtime[1].mInteger;
std::string name = runtime.getStringLiteral (index); std::string name = runtime.getStringLiteral (index);
runtime.getContext().setGlobalFloat (name, *reinterpret_cast<float *> (&data)); runtime.getContext().setGlobalFloat (name, data);
runtime.pop(); runtime.pop();
runtime.pop(); runtime.pop();
@ -173,10 +173,10 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
std::string name = runtime.getStringLiteral (index); std::string name = runtime.getStringLiteral (index);
int value = runtime.getContext().getGlobalShort (name); Type_Integer value = runtime.getContext().getGlobalShort (name);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mInteger = value;
} }
}; };
@ -186,10 +186,10 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
std::string name = runtime.getStringLiteral (index); std::string name = runtime.getStringLiteral (index);
int value = runtime.getContext().getGlobalLong (name); Type_Integer value = runtime.getContext().getGlobalLong (name);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mInteger = value;
} }
}; };
@ -199,10 +199,10 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
std::string name = runtime.getStringLiteral (index); std::string name = runtime.getStringLiteral (index);
float value = runtime.getContext().getGlobalFloat (name); Type_Float value = runtime.getContext().getGlobalFloat (name);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mFloat = value;
} }
}; };
} }

View file

@ -16,14 +16,11 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
T result = T result = getData<T> (runtime[1]) + getData<T> (runtime[0]);
*reinterpret_cast<T *> (&runtime[1])
+
*reinterpret_cast<T *> (&runtime[0]);
runtime.pop(); runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result); getData<T> (runtime[0]) = result;
} }
}; };
@ -34,14 +31,11 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
T result = T result = getData<T> (runtime[1]) - getData<T> (runtime[0]);
*reinterpret_cast<T *> (&runtime[1])
-
*reinterpret_cast<T *> (&runtime[0]);
runtime.pop(); runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result); getData<T> (runtime[0]) = result;
} }
}; };
@ -52,14 +46,11 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
T result = T result = getData<T> (runtime[1]) * getData<T> (runtime[0]);
*reinterpret_cast<T *> (&runtime[1])
*
*reinterpret_cast<T *> (&runtime[0]);
runtime.pop(); runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result); getData<T> (runtime[0]) = result;
} }
}; };
@ -70,19 +61,16 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
T left = *reinterpret_cast<T *> (&runtime[0]); T left = getData<T> (runtime[0]);
if (left==0) if (left==0)
throw std::runtime_error ("division by zero"); throw std::runtime_error ("division by zero");
T result = T result = getData<T> (runtime[1]) / left;
*reinterpret_cast<T *> (&runtime[1])
/
left;
runtime.pop(); runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result); getData<T> (runtime[0]) = result;
} }
}; };
@ -92,7 +80,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
Type_Float value = *reinterpret_cast<Type_Float *> (&runtime[0]); Type_Float value = runtime[0].mFloat;
if (value<0) if (value<0)
throw std::runtime_error ( throw std::runtime_error (
@ -100,7 +88,7 @@ namespace Interpreter
value = std::sqrt (value); value = std::sqrt (value);
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mFloat = value;
} }
}; };
@ -111,13 +99,11 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int result = C() ( int result = C() (getData<T> (runtime[1]), getData<T> (runtime[0]));
*reinterpret_cast<T *> (&runtime[1]),
*reinterpret_cast<T *> (&runtime[0]));
runtime.pop(); runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result); runtime[0].mInteger = result;
} }
}; };
} }

View file

@ -22,7 +22,7 @@ namespace Interpreter
throw std::logic_error ("message box buttons not implemented yet"); throw std::logic_error ("message box buttons not implemented yet");
// message // message
int index = runtime[0]; int index = runtime[0].mInteger;
runtime.pop(); runtime.pop();
std::string message = runtime.getStringLiteral (index); std::string message = runtime.getStringLiteral (index);
@ -44,13 +44,13 @@ namespace Interpreter
if (c=='S' || c=='s') if (c=='S' || c=='s')
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
runtime.pop(); runtime.pop();
formattedMessage += runtime.getStringLiteral (index); formattedMessage += runtime.getStringLiteral (index);
} }
else if (c=='g' || c=='G') else if (c=='g' || c=='G')
{ {
int value = *reinterpret_cast<const int *> (&runtime[0]); Type_Integer value = runtime[0].mInteger;
runtime.pop(); runtime.pop();
std::ostringstream out; std::ostringstream out;
@ -64,7 +64,7 @@ namespace Interpreter
++i; ++i;
} }
float value = *reinterpret_cast<const float *> (&runtime[0]); float value = runtime[0].mFloat;
runtime.pop(); runtime.pop();
std::ostringstream out; std::ostringstream out;
@ -107,7 +107,7 @@ namespace Interpreter
{ {
double r = static_cast<double> (std::rand()) / RAND_MAX; // [0, 1) double r = static_cast<double> (std::rand()) / RAND_MAX; // [0, 1)
Type_Integer limit = *reinterpret_cast<Type_Integer *> (&runtime[0]); Type_Integer limit = runtime[0].mInteger;
if (limit<0) if (limit<0)
throw std::runtime_error ( throw std::runtime_error (
@ -115,7 +115,7 @@ namespace Interpreter
Type_Integer value = static_cast<Type_Integer> (r*limit); // [o, limit) Type_Integer value = static_cast<Type_Integer> (r*limit); // [o, limit)
runtime[0] = *reinterpret_cast<Type_Data *> (&value); runtime[0].mInteger = value;
} }
}; };
@ -125,9 +125,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
float duration = runtime.getContext().getSecondsPassed(); Type_Float duration = runtime.getContext().getSecondsPassed();
runtime.push (*reinterpret_cast<Type_Data *> (&duration)); runtime.push (duration);
} }
}; };
@ -167,7 +167,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
runtime.pop(); runtime.pop();
std::string id = runtime.getStringLiteral (index); std::string id = runtime.getStringLiteral (index);
@ -181,7 +181,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
runtime.pop(); runtime.pop();
std::string id = runtime.getStringLiteral (index); std::string id = runtime.getStringLiteral (index);
@ -195,7 +195,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
int index = runtime[0]; int index = runtime[0].mInteger;
runtime.pop(); runtime.pop();
std::string id = runtime.getStringLiteral (index); std::string id = runtime.getStringLiteral (index);

View file

@ -68,11 +68,25 @@ namespace Interpreter
mPC = PC; mPC = PC;
} }
void Runtime::push (Type_Data data) void Runtime::push (const Data& data)
{ {
mStack.push_back (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() void Runtime::pop()
{ {
if (mStack.empty()) if (mStack.empty())
@ -81,7 +95,7 @@ namespace Interpreter
mStack.resize (mStack.size()-1); mStack.resize (mStack.size()-1);
} }
Type_Data& Runtime::operator[] (int Index) Data& Runtime::operator[] (int Index)
{ {
if (Index<0 || Index>=static_cast<int> (mStack.size())) if (Index<0 || Index>=static_cast<int> (mStack.size()))
throw std::runtime_error ("stack index out of range"); throw std::runtime_error ("stack index out of range");

View file

@ -18,7 +18,7 @@ namespace Interpreter
const Type_Code *mCode; const Type_Code *mCode;
int mCodeSize; int mCodeSize;
int mPC; int mPC;
std::vector<Type_Data> mStack; std::vector<Data> mStack;
public: public:
@ -42,13 +42,19 @@ namespace Interpreter
void setPC (int PC); void setPC (int PC);
///< set program counter. ///< set program counter.
void push (Type_Data data); void push (const Data& data);
///< push data on stack ///< 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(); void pop();
///< pop stack ///< pop stack
Type_Data& operator[] (int Index); Data& operator[] (int Index);
///< Access stack member, counted from the top. ///< Access stack member, counted from the top.
Context& getContext(); Context& getContext();

View file

@ -13,8 +13,8 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
std::string name = runtime.getStringLiteral (runtime[0]); std::string name = runtime.getStringLiteral (runtime[0].mInteger);
runtime[0] = runtime.getContext().isScriptRunning (name); runtime[0].mInteger = runtime.getContext().isScriptRunning (name);
} }
}; };
@ -24,7 +24,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
std::string name = runtime.getStringLiteral (runtime[0]); std::string name = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
runtime.getContext().startScript (name); runtime.getContext().startScript (name);
} }
@ -36,7 +36,7 @@ namespace Interpreter
virtual void execute (Runtime& runtime) virtual void execute (Runtime& runtime)
{ {
std::string name = runtime.getStringLiteral (runtime[0]); std::string name = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
runtime.getContext().stopScript (name); runtime.getContext().stopScript (name);
} }

View file

@ -12,13 +12,31 @@ namespace Interpreter
virtual void execute (Runtime& runtime) 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<Type_Data *> (&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 #endif

View file

@ -1,6 +1,8 @@
#ifndef INTERPRETER_TYPES_H_INCLUDED #ifndef INTERPRETER_TYPES_H_INCLUDED
#define INTERPRETER_TYPES_H_INCLUDED #define INTERPRETER_TYPES_H_INCLUDED
#include <stdexcept>
namespace Interpreter namespace Interpreter
{ {
typedef unsigned int Type_Code; // 32 bit typedef unsigned int Type_Code; // 32 bit
@ -12,6 +14,30 @@ namespace Interpreter
typedef int Type_Integer; // 32 bit typedef int Type_Integer; // 32 bit
typedef float Type_Float; // 32 bit typedef float Type_Float; // 32 bit
union Data
{
Type_Integer mInteger;
Type_Float mFloat;
};
template<typename T>
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 #endif