Merge branch 'master' into oengine

pull/7/head
Nicolay Korslund 15 years ago
commit 186bf8c1a1

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

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

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

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

@ -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);
}
}

@ -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<MWWorld::Ptr, MWWorld::World::CellStore *> 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);
}

@ -22,12 +22,10 @@ namespace MWScript
Locals *mLocals;
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);
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;

@ -15,8 +15,7 @@
#include <components/interpreter/installopcodes.hpp>
#include <components/interpreter/interpreter.hpp>
#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);
}
}

@ -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);
}
}
}

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

@ -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);
}
}

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

@ -15,13 +15,18 @@ namespace MWWorld
class Ptr
{
public:
typedef ESMS::CellStore<RefData> 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<typename T>
Ptr (ESMS::LiveCellRef<T, RefData> *liveCellRef)
Ptr (ESMS::LiveCellRef<T, RefData> *liveCellRef, CellStore *cell)
{
mPtr = liveCellRef;
mCellRef = &liveCellRef->ref;
mRefData = &liveCellRef->mData;
mCell = cell;
}
template<typename T>
@ -53,6 +59,12 @@ namespace MWWorld
assert (mRefData);
return *mRefData;
}
Ptr::CellStore *getCell() const
{
assert (mCell);
return mCell;
}
};
}

@ -15,7 +15,8 @@ namespace
{
template<typename T>
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 (
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<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
{
void World::insertInteriorScripts (ESMS::CellStore<RefData>& 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<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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
return ref;
return Ptr (ref, &cell);
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))
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<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.
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<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");
}
}

@ -36,20 +36,20 @@ namespace MWWorld
public:
typedef std::vector<std::pair<std::string, Ptr> > ScriptList;
typedef ESMS::CellStore<RefData> CellStore;
private:
typedef std::map<CellStore *, MWRender::CellRender *> CellRenderCollection;
typedef std::map<Ptr::CellStore *, MWRender::CellRender *> 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<std::string, CellStore> mInteriors;
std::map<std::string, Ptr::CellStore> mInteriors;
ScriptList mLocalScripts;
std::map<std::string, Interpreter::Type_Data> mGlobalVariables;
@ -59,9 +59,9 @@ namespace MWWorld
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:
@ -82,16 +82,13 @@ namespace MWWorld
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.
/// \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);
CellStore *find (const Ptr& ptr);
///< Only active cells are searched.
void disable (Ptr reference);
};
}

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

@ -5,6 +5,7 @@
#include <stdexcept>
#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<int, Function>::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<int, Instruction>::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<Interpreter::Type_Code>& code)
const
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
Literals& literals, const std::string& id) const
{
std::map<int, Function>::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<Interpreter::Type_Code>& code)
std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id)
const
{
std::map<int, Instruction>::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));
}
}

@ -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<Interpreter::Type_Code>& code)
const;
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
Literals& literals, const std::string& id) const;
///< Append code for function to \a code.
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
const;
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
Literals& literals, const std::string& id) const;
///< Append code for function to \a code.
};
}

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

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

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

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

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

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

@ -12,7 +12,7 @@ namespace Interpreter
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)
{
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[0]);
Type_Integer data = runtime[0].mInteger;
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)
{
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[0]);
Type_Float data = runtime[0].mFloat;
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)
{
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[0]);
Type_Integer data = runtime[0].mInteger;
data = -data;
runtime[0] = *reinterpret_cast<Type_Data *> (&data);
runtime[0].mInteger = data;
}
};
@ -58,9 +58,9 @@ namespace Interpreter
virtual void execute (Runtime& runtime)
{
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[0]);
Type_Float data = runtime[0].mFloat;
data = -data;
runtime[0] = *reinterpret_cast<Type_Data *> (&data);
runtime[0].mFloat = data;
}
};
@ -70,9 +70,9 @@ namespace Interpreter
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);
runtime[1] = *reinterpret_cast<Type_Data *> (&floatValue);
runtime[1].mFloat = floatValue;
}
};
@ -82,9 +82,9 @@ namespace Interpreter
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);
runtime[1] = *reinterpret_cast<Type_Data *> (&integerValue);
runtime[1].mInteger = integerValue;
}
};
}

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

@ -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<int *> (&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<int *> (&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<float *> (&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<Type_Data *> (&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<Type_Data *> (&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<Type_Data *> (&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<Type_Data *> (&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<int *> (&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<int *> (&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<float *> (&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<Type_Data *> (&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<Type_Data *> (&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<Type_Data *> (&value);
Type_Float value = runtime.getContext().getGlobalFloat (name);
runtime[0].mFloat = value;
}
};
}

@ -16,14 +16,11 @@ namespace Interpreter
virtual void execute (Runtime& runtime)
{
T result =
*reinterpret_cast<T *> (&runtime[1])
+
*reinterpret_cast<T *> (&runtime[0]);
T result = getData<T> (runtime[1]) + getData<T> (runtime[0]);
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)
{
T result =
*reinterpret_cast<T *> (&runtime[1])
-
*reinterpret_cast<T *> (&runtime[0]);
T result = getData<T> (runtime[1]) - getData<T> (runtime[0]);
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)
{
T result =
*reinterpret_cast<T *> (&runtime[1])
*
*reinterpret_cast<T *> (&runtime[0]);
T result = getData<T> (runtime[1]) * getData<T> (runtime[0]);
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)
{
T left = *reinterpret_cast<T *> (&runtime[0]);
T left = getData<T> (runtime[0]);
if (left==0)
throw std::runtime_error ("division by zero");
T result =
*reinterpret_cast<T *> (&runtime[1])
/
left;
T result = getData<T> (runtime[1]) / left;
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)
{
Type_Float value = *reinterpret_cast<Type_Float *> (&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<Type_Data *> (&value);
runtime[0].mFloat = value;
}
};
@ -111,13 +99,11 @@ namespace Interpreter
virtual void execute (Runtime& runtime)
{
int result = C() (
*reinterpret_cast<T *> (&runtime[1]),
*reinterpret_cast<T *> (&runtime[0]));
int result = C() (getData<T> (runtime[1]), getData<T> (runtime[0]));
runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result);
runtime[0].mInteger = result;
}
};
}

@ -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<const int *> (&runtime[0]);
Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::ostringstream out;
@ -64,7 +64,7 @@ namespace Interpreter
++i;
}
float value = *reinterpret_cast<const float *> (&runtime[0]);
float value = runtime[0].mFloat;
runtime.pop();
std::ostringstream out;
@ -107,7 +107,7 @@ namespace Interpreter
{
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)
throw std::runtime_error (
@ -115,7 +115,7 @@ namespace Interpreter
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)
{
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)
{
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);

@ -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<int> (mStack.size()))
throw std::runtime_error ("stack index out of range");

@ -18,7 +18,7 @@ namespace Interpreter
const Type_Code *mCode;
int mCodeSize;
int mPC;
std::vector<Type_Data> mStack;
std::vector<Data> 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();

@ -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);
}

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

@ -1,6 +1,8 @@
#ifndef INTERPRETER_TYPES_H_INCLUDED
#define INTERPRETER_TYPES_H_INCLUDED
#include <stdexcept>
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<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

Loading…
Cancel
Save