PRINCE: script code refactored

This commit is contained in:
Kamil Zbróg 2013-12-10 00:26:42 +00:00
parent 7add223d85
commit 14566d5c27
4 changed files with 627 additions and 577 deletions

View file

@ -74,10 +74,10 @@ void PrinceEngine::debugEngine(const char *s, ...) {
} }
PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) : PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _graph(NULL), _script(NULL), Engine(syst), _gameDescription(gameDesc), _graph(nullptr), _script(nullptr), _interpreter(nullptr), _flags(nullptr),
_locationNr(0), _debugger(NULL), _midiPlayer(NULL), _locationNr(0), _debugger(nullptr), _midiPlayer(nullptr),
_cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(NULL), _cursor2(NULL), _font(NULL), _cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(nullptr), _cursor2(nullptr), _font(nullptr),
_walizkaBmp(NULL), _roomBmp(NULL), _cursorNr(0) { _walizkaBmp(nullptr), _roomBmp(nullptr), _cursorNr(0) {
// Debug/console setup // Debug/console setup
DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel"); DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel");
@ -99,6 +99,8 @@ PrinceEngine::~PrinceEngine() {
delete _cursor2; delete _cursor2;
delete _midiPlayer; delete _midiPlayer;
delete _script; delete _script;
delete _flags;
delete _interpreter;
delete _font; delete _font;
delete _roomBmp; delete _roomBmp;
delete _walizkaBmp; delete _walizkaBmp;
@ -153,9 +155,12 @@ void PrinceEngine::init() {
_walizkaBmp = new MhwanhDecoder(); _walizkaBmp = new MhwanhDecoder();
Resource::loadResource(_walizkaBmp, "all/walizka"); Resource::loadResource(_walizkaBmp, "all/walizka");
_script = new Script(this); _script = new Script();
Resource::loadResource(_script, "all/skrypt.dat"); Resource::loadResource(_script, "all/skrypt.dat");
_flags = new InterpreterFlags();
_interpreter = new Interpreter(this, _script, _flags);
_variaTxt = new VariaTxt(); _variaTxt = new VariaTxt();
Resource::loadResource(_variaTxt, "all/variatxt.dat"); Resource::loadResource(_variaTxt, "all/variatxt.dat");
@ -249,8 +254,8 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
_cameraX = 0; _cameraX = 0;
_newCameraX = 0; _newCameraX = 0;
_script->setFlagValue(Flags::CURRROOM, _locationNr); _flags->setFlagValue(Flags::CURRROOM, _locationNr);
_script->stopBg(); _interpreter->stopBg();
changeCursor(0); changeCursor(0);
@ -290,7 +295,7 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
void PrinceEngine::changeCursor(uint16 curId) { void PrinceEngine::changeCursor(uint16 curId) {
_debugger->_cursorNr = curId; _debugger->_cursorNr = curId;
const Graphics::Surface *curSurface = NULL; const Graphics::Surface *curSurface = nullptr;
uint16 hotspotX = 0; uint16 hotspotX = 0;
uint16 hotspotY = 0; uint16 hotspotY = 0;
@ -353,7 +358,7 @@ void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
void PrinceEngine::stopSample(uint16 sampleId) { void PrinceEngine::stopSample(uint16 sampleId) {
_mixer->stopID(sampleId); _mixer->stopID(sampleId);
_voiceStream[sampleId] = NULL; _voiceStream[sampleId] = nullptr;
} }
bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) { bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
@ -364,12 +369,12 @@ bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamNam
debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str()); debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
_mixer->stopID(sampleSlot); _mixer->stopID(sampleSlot);
_voiceStream[sampleSlot] = NULL; _voiceStream[sampleSlot] = nullptr;
_voiceStream[sampleSlot] = SearchMan.createReadStreamForMember(normalizedPath); _voiceStream[sampleSlot] = SearchMan.createReadStreamForMember(normalizedPath);
if (_voiceStream[sampleSlot] == NULL) { if (_voiceStream[sampleSlot] == nullptr) {
error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot); error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
} }
return _voiceStream[sampleSlot] == NULL; return _voiceStream[sampleSlot] == nullptr;
} }
bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) { bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
@ -466,7 +471,7 @@ void PrinceEngine::keyHandler(Common::Event event) {
scrollCameraRight(32); scrollCameraRight(32);
break; break;
case Common::KEYCODE_ESCAPE: case Common::KEYCODE_ESCAPE:
_script->setFlagValue(Flags::ESCAPED2, 1); _flags->setFlagValue(Flags::ESCAPED2, 1);
break; break;
} }
} }
@ -551,7 +556,7 @@ void PrinceEngine::showTexts() {
--text._time; --text._time;
if (text._time == 0) { if (text._time == 0) {
text._str = NULL; text._str = nullptr;
} }
} }
} }
@ -587,7 +592,6 @@ void PrinceEngine::drawScreen() {
void PrinceEngine::mainLoop() { void PrinceEngine::mainLoop() {
loadLocation(4);
changeCursor(0); changeCursor(0);
while (!shouldQuit()) { while (!shouldQuit()) {
@ -622,7 +626,7 @@ void PrinceEngine::mainLoop() {
// TODO: Update all structures, animations, naks, heros etc. // TODO: Update all structures, animations, naks, heros etc.
_script->step(); _interpreter->step();
drawScreen(); drawScreen();

View file

@ -53,6 +53,8 @@ struct PrinceGameDescription;
class PrinceEngine; class PrinceEngine;
class GraphicsMan; class GraphicsMan;
class Script; class Script;
class Interpreter;
class InterpreterFlags;
class Debugger; class Debugger;
class MusicPlayer; class MusicPlayer;
class VariaTxt; class VariaTxt;
@ -162,6 +164,8 @@ private:
Debugger *_debugger; Debugger *_debugger;
GraphicsMan *_graph; GraphicsMan *_graph;
Script *_script; Script *_script;
InterpreterFlags *_flags;
Interpreter *_interpreter;
Font *_font; Font *_font;
MusicPlayer *_midiPlayer; MusicPlayer *_midiPlayer;

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,7 @@
#define PRINCE_SCRIPT_H #define PRINCE_SCRIPT_H
#include "common/random.h" #include "common/random.h"
#include "common/endian.h"
#include "audio/mixer.h" #include "audio/mixer.h"
@ -37,25 +38,68 @@ namespace Prince {
class PrinceEngine; class PrinceEngine;
namespace Detail {
template <typename T> T LittleEndianReader(void *data);
template <> inline uint8 LittleEndianReader<uint8>(void *data) { return *(uint8*)(data); }
template <> inline uint16 LittleEndianReader<uint16>(void *data) { return READ_LE_UINT16(data); }
template <> inline uint32 LittleEndianReader<uint32>(void *data) { return READ_LE_UINT32(data); }
}
class Script { class Script {
public: public:
Script(PrinceEngine *vm); Script();
virtual ~Script(); ~Script();
bool loadFromStream(Common::SeekableReadStream &stream); bool loadFromStream(Common::SeekableReadStream &stream);
void step(); template <typename T>
T read(uint32 address) {
assert((_data + address + sizeof(T)) <= (_data + _dataSize));
return Detail::LittleEndianReader<T>(&_data[address]);
}
// Some magic numbers for now, data stored in header
uint32 getRoomTableOffset() { return read<uint32>(0); }
uint32 getStartGameOffset() { return read<uint32>(4); }
const char *getString(uint32 offset) {
return (const char *)(&_data[offset]);
}
private:
uint8 *_data;
uint32 _dataSize;
};
class InterpreterFlags {
public:
InterpreterFlags();
void setFlagValue(Flags::Id flag, uint16 value); void setFlagValue(Flags::Id flag, uint16 value);
uint16 getFlagValue(Flags::Id flag); uint16 getFlagValue(Flags::Id flag);
void resetAllFlags();
static const uint16 FLAG_MASK = 0x8000;
private:
static const uint16 MAX_FLAGS = 2000;
int16 _flags[MAX_FLAGS];
};
class Interpreter {
public:
Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags);
void stopBg() { _bgOpcodePC = 0; } void stopBg() { _bgOpcodePC = 0; }
void step();
private: private:
PrinceEngine *_vm; PrinceEngine *_vm;
Script *_script;
InterpreterFlags *_flags;
byte *_code;
uint32 _codeSize;
uint32 _currentInstruction; uint32 _currentInstruction;
uint32 _bgOpcodePC; uint32 _bgOpcodePC;
@ -64,13 +108,9 @@ private:
uint16 _lastOpcode; uint16 _lastOpcode;
uint32 _lastInstruction; uint32 _lastInstruction;
byte _result; byte _result;
static const uint16 MAX_FLAGS = 2000;
static const uint16 FLAG_MASK = 0x8000;
int16 _flags[MAX_FLAGS];
bool _opcodeNF;
bool _opcodeNF; // break interpreter loop
// Stack
static const uint32 _STACK_SIZE = 500; static const uint32 _STACK_SIZE = 500;
uint32 _stack[_STACK_SIZE]; uint32 _stack[_STACK_SIZE];
uint8 _stacktop; uint8 _stacktop;
@ -83,21 +123,19 @@ private:
// Helper functions // Helper functions
uint32 step(uint32 opcodePC); uint32 step(uint32 opcodePC);
void checkPC(uint32 address);
uint8 getCodeByte(uint32 address);
uint8 readScript8bits();
uint16 readScript16bits();
uint32 readScript32bits(); void checkPC(uint32 address);
uint16 readScript8or16bits();
uint16 readScriptValue(); uint16 readScriptValue();
Flags::Id readScriptFlagId() { return (Flags::Id)readScript16bits(); } Flags::Id readScriptFlagId();
void debugScript(const char *s, ...); // instantiation not needed here
template <typename T> T readScript();
void debugInterpreter(const char *s, ...);
void SetVoice(uint32 slot); void SetVoice(uint32 slot);
typedef void (Script::*OpcodeFunc)(); typedef void (Interpreter::*OpcodeFunc)();
static OpcodeFunc _opcodes[]; static OpcodeFunc _opcodes[];
// Keep opcode handlers names as they are in original code // Keep opcode handlers names as they are in original code
@ -246,6 +284,7 @@ private:
void O_INPUTLINE(); void O_INPUTLINE();
void O_SETVOICED(); void O_SETVOICED();
void O_BREAK_POINT(); void O_BREAK_POINT();
}; };
} }