1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-15 15:02:34 +02:00

Simplify Script system by removing SCMOpcodes

This was just a useless container for a set of modules. We only have
one module now so don't bother with it. This means we can remove some
more raw new & deletes from RWGame too.
This commit is contained in:
Daniel Evans 2016-10-20 23:10:52 +01:00
parent fb4d9ea8c3
commit 684e32f4a9
8 changed files with 43 additions and 78 deletions

View File

@ -1,8 +1,9 @@
#include <script/SCMFile.hpp> #include <script/SCMFile.hpp>
#include <script/ScriptDisassembly.hpp> #include <script/ScriptDisassembly.hpp>
#include <script/ScriptMachine.hpp> #include <script/ScriptMachine.hpp>
#include <script/ScriptModule.hpp>
ScriptDisassembly::ScriptDisassembly(SCMOpcodes* _codes, SCMFile* _scm) ScriptDisassembly::ScriptDisassembly(ScriptModule* _codes, SCMFile* _scm)
: codes(_codes), scm(_scm) { : codes(_codes), scm(_scm) {
} }

View File

@ -27,7 +27,7 @@ public:
uint8_t flags; uint8_t flags;
}; };
ScriptDisassembly(SCMOpcodes* codes, SCMFile* scm); ScriptDisassembly(ScriptModule* codes, SCMFile* scm);
/** /**
* Execute the disassembly routine. * Execute the disassembly routine.
@ -42,7 +42,7 @@ public:
} }
private: private:
SCMOpcodes* codes; ScriptModule* codes;
SCMFile* scm; SCMFile* scm;
std::map<SCMAddress, InstructionInfo> instructions; std::map<SCMAddress, InstructionInfo> instructions;

View File

@ -6,22 +6,6 @@
#include <script/ScriptMachine.hpp> #include <script/ScriptMachine.hpp>
#include <script/ScriptModule.hpp> #include <script/ScriptModule.hpp>
SCMOpcodes::~SCMOpcodes() {
for (auto m : modules) {
delete m;
}
}
bool SCMOpcodes::findOpcode(ScriptFunctionID id, ScriptFunctionMeta** out) {
for (ScriptModule* module : modules) {
if (module->findOpcode(id, out)) {
return true;
}
}
return false;
}
void ScriptMachine::executeThread(SCMThread& t, int msPassed) { void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
if (t.wakeCounter > 0) { if (t.wakeCounter > 0) {
t.wakeCounter = std::max(t.wakeCounter - msPassed, 0); t.wakeCounter = std::max(t.wakeCounter - msPassed, 0);
@ -30,14 +14,14 @@ void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
while (t.wakeCounter == 0) { while (t.wakeCounter == 0) {
auto pc = t.programCounter; auto pc = t.programCounter;
auto opcode = _file->read<SCMOpcode>(pc); auto opcode = file->read<SCMOpcode>(pc);
bool isNegatedConditional = ((opcode & SCM_NEGATE_CONDITIONAL_MASK) == bool isNegatedConditional = ((opcode & SCM_NEGATE_CONDITIONAL_MASK) ==
SCM_NEGATE_CONDITIONAL_MASK); SCM_NEGATE_CONDITIONAL_MASK);
opcode = opcode & ~SCM_NEGATE_CONDITIONAL_MASK; opcode = opcode & ~SCM_NEGATE_CONDITIONAL_MASK;
ScriptFunctionMeta* foundcode; ScriptFunctionMeta* foundcode;
if (!_ops->findOpcode(opcode, &foundcode)) { if (!module->findOpcode(opcode, &foundcode)) {
throw IllegalInstruction(opcode, pc, t.name); throw IllegalInstruction(opcode, pc, t.name);
} }
ScriptFunctionMeta& code = *foundcode; ScriptFunctionMeta& code = *foundcode;
@ -50,7 +34,7 @@ void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
auto requiredParams = std::abs(code.arguments); auto requiredParams = std::abs(code.arguments);
for (int p = 0; p < requiredParams || hasExtraParameters; ++p) { for (int p = 0; p < requiredParams || hasExtraParameters; ++p) {
auto type_r = _file->read<SCMByte>(pc); auto type_r = file->read<SCMByte>(pc);
auto type = static_cast<SCMType>(type_r); auto type = static_cast<SCMType>(type_r);
if (type_r > 42) { if (type_r > 42) {
@ -66,27 +50,27 @@ void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
hasExtraParameters = false; hasExtraParameters = false;
break; break;
case TInt8: case TInt8:
parameters.back().integer = _file->read<std::int8_t>(pc); parameters.back().integer = file->read<std::int8_t>(pc);
pc += sizeof(SCMByte); pc += sizeof(SCMByte);
break; break;
case TInt16: case TInt16:
parameters.back().integer = _file->read<std::int16_t>(pc); parameters.back().integer = file->read<std::int16_t>(pc);
pc += sizeof(SCMByte) * 2; pc += sizeof(SCMByte) * 2;
break; break;
case TGlobal: { case TGlobal: {
auto v = _file->read<std::uint16_t>(pc); auto v = file->read<std::uint16_t>(pc);
parameters.back().globalPtr = parameters.back().globalPtr =
globalData.data() + v; //* SCM_VARIABLE_SIZE; globalData.data() + v; //* SCM_VARIABLE_SIZE;
if (v >= _file->getGlobalsSize()) { if (v >= file->getGlobalsSize()) {
state->world->logger->error( state->world->logger->error(
"SCM", "Global Out of bounds! " + "SCM", "Global Out of bounds! " +
std::to_string(v) + " " + std::to_string(v) + " " +
std::to_string(_file->getGlobalsSize())); std::to_string(file->getGlobalsSize()));
} }
pc += sizeof(SCMByte) * 2; pc += sizeof(SCMByte) * 2;
} break; } break;
case TLocal: { case TLocal: {
auto v = _file->read<std::uint16_t>(pc); auto v = file->read<std::uint16_t>(pc);
parameters.back().globalPtr = parameters.back().globalPtr =
t.locals.data() + v * SCM_VARIABLE_SIZE; t.locals.data() + v * SCM_VARIABLE_SIZE;
if (v >= SCM_THREAD_LOCAL_SIZE) { if (v >= SCM_THREAD_LOCAL_SIZE) {
@ -96,17 +80,17 @@ void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
pc += sizeof(SCMByte) * 2; pc += sizeof(SCMByte) * 2;
} break; } break;
case TInt32: case TInt32:
parameters.back().integer = _file->read<std::int32_t>(pc); parameters.back().integer = file->read<std::int32_t>(pc);
pc += sizeof(SCMByte) * 4; pc += sizeof(SCMByte) * 4;
break; break;
case TString: case TString:
std::copy(_file->data() + pc, _file->data() + pc + 8, std::copy(file->data() + pc, file->data() + pc + 8,
parameters.back().string); parameters.back().string);
pc += sizeof(SCMByte) * 8; pc += sizeof(SCMByte) * 8;
break; break;
case TFloat16: case TFloat16:
parameters.back().real = parameters.back().real =
_file->read<std::int16_t>(pc) / 16.f; file->read<std::int16_t>(pc) / 16.f;
pc += sizeof(SCMByte) * 2; pc += sizeof(SCMByte) * 2;
break; break;
default: default:
@ -179,21 +163,17 @@ void ScriptMachine::executeThread(SCMThread& t, int msPassed) {
} }
} }
ScriptMachine::ScriptMachine(GameState* _state, SCMFile* file, SCMOpcodes* ops) ScriptMachine::ScriptMachine(GameState* _state, SCMFile* file,
: _file(file), _ops(ops), state(_state) { ScriptModule* ops)
: file(file), module(ops), state(_state) {
// Copy globals // Copy globals
auto size = _file->getGlobalsSize(); auto size = file->getGlobalsSize();
globalData.resize(size); globalData.resize(size);
auto offset = _file->getGlobalSection(); auto offset = file->getGlobalSection();
std::copy(_file->data() + offset, _file->data() + offset + size, std::copy(file->data() + offset, file->data() + offset + size,
globalData.begin()); globalData.begin());
} }
ScriptMachine::~ScriptMachine() {
delete _file;
delete _ops;
}
void ScriptMachine::startThread(SCMThread::pc_t start, bool mission) { void ScriptMachine::startThread(SCMThread::pc_t start, bool mission) {
SCMThread t; SCMThread t;
for (int i = 0; i < SCM_THREAD_LOCAL_SIZE * SCM_VARIABLE_SIZE; ++i) { for (int i = 0; i < SCM_THREAD_LOCAL_SIZE * SCM_VARIABLE_SIZE; ++i) {

View File

@ -120,15 +120,11 @@ struct SCMThread {
*/ */
class ScriptMachine { class ScriptMachine {
public: public:
ScriptMachine(GameState* state, SCMFile* file, SCMOpcodes* ops); ScriptMachine(GameState* state, SCMFile* file, ScriptModule* ops);
~ScriptMachine(); ~ScriptMachine() { }
SCMFile* getFile() const { SCMFile* getFile() const {
return _file; return file;
}
SCMOpcodes* getOpcodes() const {
return _ops;
} }
void startThread(SCMThread::pc_t start, bool mission = false); void startThread(SCMThread::pc_t start, bool mission = false);
@ -152,8 +148,8 @@ public:
void execute(float dt); void execute(float dt);
private: private:
SCMFile* _file; SCMFile* file;
SCMOpcodes* _ops; ScriptModule* module;
GameState* state; GameState* state;
std::list<SCMThread> _activeThreads; std::list<SCMThread> _activeThreads;

View File

@ -376,12 +376,4 @@ struct SCMMicrocode {
typedef std::map<SCMOpcode, SCMMicrocode> SCMMicrocodeTable; typedef std::map<SCMOpcode, SCMMicrocode> SCMMicrocodeTable;
struct SCMOpcodes {
std::vector<ScriptModule*> modules;
~SCMOpcodes();
bool findOpcode(ScriptFunctionID id, ScriptFunctionMeta** out);
};
#endif #endif

View File

@ -11,8 +11,7 @@
#include <engine/SaveGame.hpp> #include <engine/SaveGame.hpp>
#include <objects/GameObject.hpp> #include <objects/GameObject.hpp>
#include <script/ScriptMachine.hpp> #include <script/SCMFile.hpp>
#include <script/modules/GTA3Module.hpp>
#include <ai/PlayerController.hpp> #include <ai/PlayerController.hpp>
#include <data/CutsceneData.hpp> #include <data/CutsceneData.hpp>
@ -100,9 +99,6 @@ RWGame::~RWGame() {
log.info("Game", "Stopping work queue"); log.info("Game", "Stopping work queue");
work.stop(); work.stop();
log.info("Game", "Cleaning up scripts");
delete script;
} }
void RWGame::newGame() { void RWGame::newGame() {
@ -142,16 +138,11 @@ void RWGame::loadGame(const std::string& savename) {
} }
void RWGame::startScript(const std::string& name) { void RWGame::startScript(const std::string& name) {
SCMFile* f = data.loadSCM(name); script.reset(data.loadSCM(name));
if (f) { if (script) {
if (script) delete script; vm = std::make_unique<ScriptMachine>(&state, script.get(), &opcodes);
SCMOpcodes* opcodes = new SCMOpcodes; state.script = vm.get();
opcodes->modules.push_back(new GTA3Module);
script = new ScriptMachine(&state, f, opcodes);
state.script = script;
} else { } else {
log.error("Game", "Failed to load SCM: " + name); log.error("Game", "Failed to load SCM: " + name);
} }
@ -520,9 +511,9 @@ void RWGame::tick(float dt) {
world->dynamicsWorld->stepSimulation(dt, 2, dt); world->dynamicsWorld->stepSimulation(dt, 2, dt);
if (script) { if (vm) {
try { try {
script->execute(dt); vm->execute(dt);
} catch (SCMException& ex) { } catch (SCMException& ex) {
std::cerr << ex.what() << std::endl; std::cerr << ex.what() << std::endl;
log.error("Script", ex.what()); log.error("Script", ex.what());

View File

@ -8,6 +8,7 @@
#include <render/DebugDraw.hpp> #include <render/DebugDraw.hpp>
#include <render/GameRenderer.hpp> #include <render/GameRenderer.hpp>
#include <script/ScriptMachine.hpp> #include <script/ScriptMachine.hpp>
#include <script/modules/GTA3Module.hpp>
#include "game.hpp" #include "game.hpp"
#include "GameBase.hpp" #include "GameBase.hpp"
@ -22,7 +23,11 @@ class RWGame : public GameBase {
GameState state; GameState state;
std::unique_ptr<GameWorld> world; std::unique_ptr<GameWorld> world;
ScriptMachine* script = nullptr;
GTA3Module opcodes;
std::unique_ptr<ScriptMachine> vm;
std::unique_ptr<SCMFile> script;
std::chrono::steady_clock clock; std::chrono::steady_clock clock;
std::chrono::steady_clock::time_point last_clock_time; std::chrono::steady_clock::time_point last_clock_time;
@ -72,8 +77,8 @@ public:
return renderer; return renderer;
} }
ScriptMachine* getScript() const { ScriptMachine *getScriptVM() const {
return script; return vm.get();
} }
bool hitWorldRay(glm::vec3& hit, glm::vec3& normal, bool hitWorldRay(glm::vec3& hit, glm::vec3& normal,

View File

@ -124,7 +124,7 @@ void IngameState::startTest() {
void IngameState::startGame() { void IngameState::startGame() {
game->startScript("data/main.scm"); game->startScript("data/main.scm");
game->getScript()->startThread(0); game->getScriptVM()->startThread(0);
getWorld()->sound.playBackground(getWorld()->data->getDataPath() + getWorld()->sound.playBackground(getWorld()->data->getDataPath() +
"/audio/City.wav"); "/audio/City.wav");
} }