PRINCE: script code refactored
This commit is contained in:
parent
7add223d85
commit
14566d5c27
4 changed files with 627 additions and 577 deletions
|
@ -74,10 +74,10 @@ void PrinceEngine::debugEngine(const char *s, ...) {
|
|||
}
|
||||
|
||||
PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc), _graph(NULL), _script(NULL),
|
||||
_locationNr(0), _debugger(NULL), _midiPlayer(NULL),
|
||||
_cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(NULL), _cursor2(NULL), _font(NULL),
|
||||
_walizkaBmp(NULL), _roomBmp(NULL), _cursorNr(0) {
|
||||
Engine(syst), _gameDescription(gameDesc), _graph(nullptr), _script(nullptr), _interpreter(nullptr), _flags(nullptr),
|
||||
_locationNr(0), _debugger(nullptr), _midiPlayer(nullptr),
|
||||
_cameraX(0), _newCameraX(0), _frameNr(0), _cursor1(nullptr), _cursor2(nullptr), _font(nullptr),
|
||||
_walizkaBmp(nullptr), _roomBmp(nullptr), _cursorNr(0) {
|
||||
|
||||
// Debug/console setup
|
||||
DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel");
|
||||
|
@ -99,6 +99,8 @@ PrinceEngine::~PrinceEngine() {
|
|||
delete _cursor2;
|
||||
delete _midiPlayer;
|
||||
delete _script;
|
||||
delete _flags;
|
||||
delete _interpreter;
|
||||
delete _font;
|
||||
delete _roomBmp;
|
||||
delete _walizkaBmp;
|
||||
|
@ -153,9 +155,12 @@ void PrinceEngine::init() {
|
|||
_walizkaBmp = new MhwanhDecoder();
|
||||
Resource::loadResource(_walizkaBmp, "all/walizka");
|
||||
|
||||
_script = new Script(this);
|
||||
_script = new Script();
|
||||
Resource::loadResource(_script, "all/skrypt.dat");
|
||||
|
||||
_flags = new InterpreterFlags();
|
||||
_interpreter = new Interpreter(this, _script, _flags);
|
||||
|
||||
_variaTxt = new VariaTxt();
|
||||
Resource::loadResource(_variaTxt, "all/variatxt.dat");
|
||||
|
||||
|
@ -249,8 +254,8 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
|
|||
_cameraX = 0;
|
||||
_newCameraX = 0;
|
||||
|
||||
_script->setFlagValue(Flags::CURRROOM, _locationNr);
|
||||
_script->stopBg();
|
||||
_flags->setFlagValue(Flags::CURRROOM, _locationNr);
|
||||
_interpreter->stopBg();
|
||||
|
||||
changeCursor(0);
|
||||
|
||||
|
@ -290,7 +295,7 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
|
|||
void PrinceEngine::changeCursor(uint16 curId) {
|
||||
_debugger->_cursorNr = curId;
|
||||
|
||||
const Graphics::Surface *curSurface = NULL;
|
||||
const Graphics::Surface *curSurface = nullptr;
|
||||
|
||||
uint16 hotspotX = 0;
|
||||
uint16 hotspotY = 0;
|
||||
|
@ -353,7 +358,7 @@ void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
|
|||
|
||||
void PrinceEngine::stopSample(uint16 sampleId) {
|
||||
_mixer->stopID(sampleId);
|
||||
_voiceStream[sampleId] = NULL;
|
||||
_voiceStream[sampleId] = nullptr;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
_mixer->stopID(sampleSlot);
|
||||
_voiceStream[sampleSlot] = NULL;
|
||||
_voiceStream[sampleSlot] = nullptr;
|
||||
_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);
|
||||
}
|
||||
return _voiceStream[sampleSlot] == NULL;
|
||||
return _voiceStream[sampleSlot] == nullptr;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
|
||||
|
@ -466,7 +471,7 @@ void PrinceEngine::keyHandler(Common::Event event) {
|
|||
scrollCameraRight(32);
|
||||
break;
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
_script->setFlagValue(Flags::ESCAPED2, 1);
|
||||
_flags->setFlagValue(Flags::ESCAPED2, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -551,7 +556,7 @@ void PrinceEngine::showTexts() {
|
|||
|
||||
--text._time;
|
||||
if (text._time == 0) {
|
||||
text._str = NULL;
|
||||
text._str = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -587,7 +592,6 @@ void PrinceEngine::drawScreen() {
|
|||
|
||||
void PrinceEngine::mainLoop() {
|
||||
|
||||
loadLocation(4);
|
||||
changeCursor(0);
|
||||
|
||||
while (!shouldQuit()) {
|
||||
|
@ -622,7 +626,7 @@ void PrinceEngine::mainLoop() {
|
|||
|
||||
// TODO: Update all structures, animations, naks, heros etc.
|
||||
|
||||
_script->step();
|
||||
_interpreter->step();
|
||||
|
||||
drawScreen();
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ struct PrinceGameDescription;
|
|||
class PrinceEngine;
|
||||
class GraphicsMan;
|
||||
class Script;
|
||||
class Interpreter;
|
||||
class InterpreterFlags;
|
||||
class Debugger;
|
||||
class MusicPlayer;
|
||||
class VariaTxt;
|
||||
|
@ -162,6 +164,8 @@ private:
|
|||
Debugger *_debugger;
|
||||
GraphicsMan *_graph;
|
||||
Script *_script;
|
||||
InterpreterFlags *_flags;
|
||||
Interpreter *_interpreter;
|
||||
Font *_font;
|
||||
MusicPlayer *_midiPlayer;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,7 @@
|
|||
#define PRINCE_SCRIPT_H
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/endian.h"
|
||||
|
||||
#include "audio/mixer.h"
|
||||
|
||||
|
@ -37,25 +38,68 @@ namespace Prince {
|
|||
|
||||
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 {
|
||||
public:
|
||||
Script(PrinceEngine *vm);
|
||||
virtual ~Script();
|
||||
Script();
|
||||
~Script();
|
||||
|
||||
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);
|
||||
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 step();
|
||||
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
Script *_script;
|
||||
InterpreterFlags *_flags;
|
||||
|
||||
byte *_code;
|
||||
uint32 _codeSize;
|
||||
uint32 _currentInstruction;
|
||||
|
||||
uint32 _bgOpcodePC;
|
||||
|
@ -64,13 +108,9 @@ private:
|
|||
uint16 _lastOpcode;
|
||||
uint32 _lastInstruction;
|
||||
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;
|
||||
uint32 _stack[_STACK_SIZE];
|
||||
uint8 _stacktop;
|
||||
|
@ -83,21 +123,19 @@ private:
|
|||
|
||||
// Helper functions
|
||||
uint32 step(uint32 opcodePC);
|
||||
void checkPC(uint32 address);
|
||||
uint8 getCodeByte(uint32 address);
|
||||
uint8 readScript8bits();
|
||||
uint16 readScript16bits();
|
||||
|
||||
uint32 readScript32bits();
|
||||
uint16 readScript8or16bits();
|
||||
void checkPC(uint32 address);
|
||||
|
||||
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);
|
||||
|
||||
typedef void (Script::*OpcodeFunc)();
|
||||
typedef void (Interpreter::*OpcodeFunc)();
|
||||
static OpcodeFunc _opcodes[];
|
||||
|
||||
// Keep opcode handlers names as they are in original code
|
||||
|
@ -246,6 +284,7 @@ private:
|
|||
void O_INPUTLINE();
|
||||
void O_SETVOICED();
|
||||
void O_BREAK_POINT();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue