aboutsummaryrefslogtreecommitdiff
path: root/kyra/script.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kyra/script.cpp')
-rw-r--r--kyra/script.cpp706
1 files changed, 221 insertions, 485 deletions
diff --git a/kyra/script.cpp b/kyra/script.cpp
index 358d65b1bb..4f941241e5 100644
--- a/kyra/script.cpp
+++ b/kyra/script.cpp
@@ -22,538 +22,274 @@
#include "common/stdafx.h"
#include "common/stream.h"
#include "common/util.h"
+#include "common/system.h"
#include "kyra/kyra.h"
-#include "kyra/script.h"
#include "kyra/resource.h"
+#include "kyra/script.h"
-#define COMMAND(x) { &VMContext::x, #x }
-#define OPCODE(x) { &VMContext::x, #x }
+#define FORM_CHUNK 0x4D524F46
+#define TEXT_CHUNK 0x54584554
+#define DATA_CHUNK 0x41544144
+#define ORDR_CHUNK 0x5244524F
namespace Kyra {
-VMContext::VMContext(KyraEngine* engine) {
- _engine = engine;
- _error = false;
-
+ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) {
+#define COMMAND(x) { &ScriptHelper::x, #x }
// now we create a list of all Command/Opcode procs and so
static CommandEntry commandProcs[] = {
// 0x00
- COMMAND(c1_goToLine),
- COMMAND(c1_setReturn),
- COMMAND(c1_pushRetRec),
+ COMMAND(c1_jmpTo),
+ COMMAND(c1_setRetValue),
+ COMMAND(c1_pushRetOrPos),
COMMAND(c1_push),
// 0x04
COMMAND(c1_push),
COMMAND(c1_pushVar),
- COMMAND(c1_pushFrameNeg),
- COMMAND(c1_pushFramePos),
+ COMMAND(c1_pushBPNeg),
+ COMMAND(c1_pushBPAdd),
// 0x08
- COMMAND(c1_popRetRec),
+ COMMAND(c1_popRetOrPos),
COMMAND(c1_popVar),
- COMMAND(c1_popFrameNeg),
- COMMAND(c1_popFramePos),
+ COMMAND(c1_popBPNeg),
+ COMMAND(c1_popBPAdd),
// 0x0C
- COMMAND(c1_addToSP),
- COMMAND(c1_subFromSP),
+ COMMAND(c1_addSP),
+ COMMAND(c1_subSP),
COMMAND(c1_execOpcode),
- COMMAND(c1_ifNotGoTo),
+ COMMAND(c1_ifNotJmp),
// 0x10
COMMAND(c1_negate),
- COMMAND(c1_evaluate)
+ COMMAND(c1_eval),
+ COMMAND(c1_setRetAndJmp)
};
- _numCommands = ARRAYSIZE(commandProcs);
_commands = commandProcs;
-
- static OpcodeEntry opcodeProcs[] = {
- // 0x00
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x04
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x08
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x0C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x10
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x14
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x18
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x1C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x20
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x24
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x28
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x2C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x30
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x34
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x38
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x3C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x40
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x44
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x48
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x4C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x50
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x54
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x58
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x5C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x60
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x64
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x68
- OPCODE(o1_0x68),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x6C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x70
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x74
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x78
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x7C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x80
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x84
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x88
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x8C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x90
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x94
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x98
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0x9C
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xA0
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xA4
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xA8
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xAC
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xB0
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xB4
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xB8
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xBC
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xC0
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xC4
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xC8
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xCC
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xD0
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xD4
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xD8
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xDC
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xE0
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xE4
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xE8
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xEC
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xF0
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xF4
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xF8
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- // 0xFC
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode),
- OPCODE(o1_unknownOpcode)
- };
- _numOpcodes = ARRAYSIZE(opcodeProcs);
- _opcodes = opcodeProcs;
-
- _scriptFile = NULL;
- _scriptFileSize = 0;
+#undef COMMAND
}
-void VMContext::loadScript(const char* file) {
- if (_scriptFile) {
- delete [] _scriptFile;
- _scriptFileSize = 0;
- }
-
- memset(_stack, 0, sizeof(int32) * ARRAYSIZE(_stack));
-
- // loads the new file
- _scriptFile = _engine->resource()->fileData(file, &_scriptFileSize);
+ScriptHelper::~ScriptHelper() {
+}
- if (!_scriptFileSize || !_scriptFile) {
- error("couldn't load script file '%s'", file);
+bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, byte *specialPtr) {
+ uint32 size = 0;
+ uint8 *data = _vm->resource()->fileData(filename, &size);
+ byte *curData = data;
+
+ uint32 formBlockSize = getFORMBlockSize(curData);
+ if (formBlockSize == (uint32)-1) {
+ delete [] data;
+ error("No FORM chunk found in file: '%s'", filename);
+ return false;
}
-
- Common::MemoryReadStream script(_scriptFile, _scriptFileSize);
- memset(_chunks, 0, sizeof(ScriptChunk) * kCountChunkTypes);
- uint8 chunkName[sizeof("EMC2ORDR") + 1];
-
- // so lets look for our chunks :)
- while (!script.eos()) {
- // lets read only the first 4 chars
- script.read(chunkName, sizeof(uint8) * 4);
- chunkName[4] = '\0';
-
- // check name of chunk
- if (!scumm_stricmp((const char *)chunkName, "FORM")) {
- // FreeKyra swaps the size I only read it in BigEndian :)
- _chunks[kForm]._size = script.readUint32BE();
- } else if (!scumm_stricmp((const char *)chunkName, "TEXT")) {
- uint32 text_size = script.readUint32BE();
- text_size += text_size % 2 != 0 ? 1 : 0;
-
- _chunks[kText]._data = _scriptFile + script.pos();
- _chunks[kText]._size = READ_BE_UINT16(_chunks[kText]._data) >> 1;
- _chunks[kText]._additional = _chunks[kText]._data + (_chunks[kText]._size << 1);
- script.seek(script.pos() + text_size);
- } else if (!scumm_stricmp((const char *)chunkName, "DATA")) {
- _chunks[kData]._size = script.readUint32BE();
- _chunks[kData]._data = _scriptFile + script.pos();
- // mostly it will be the end of the file because all files should end with a 'DATA' chunk
- script.seek(script.pos() + _chunks[kData]._size);
+
+ uint32 chunkSize = getIFFBlockSize(data, curData, size, TEXT_CHUNK);
+ if (chunkSize != (uint32)-1) {
+ if (specialPtr) {
+ scriptData->mustBeFreed = 0;
+ scriptData->text = specialPtr;
+ specialPtr += chunkSize;
} else {
- // read next 4 chars
- script.read(&chunkName[4], sizeof(uint8) * 4);
- chunkName[8] = '\0';
-
- if (!scumm_stricmp((const char *)chunkName, "EMC2ORDR")) {
- _chunks[kEmc2Ordr]._size = script.readUint32BE() >> 1;
- _chunks[kEmc2Ordr]._data = _scriptFile + script.pos();
- script.seek(script.pos() + _chunks[kEmc2Ordr]._size * 2);
- } else {
- // any unkown chunk or problems with seeking through the file
- error("unknown chunk(%s)", chunkName);
- }
+ scriptData->mustBeFreed = 1;
+ scriptData->text = new byte[chunkSize];
+ }
+ if (!loadIFFBlock(data, curData, size, TEXT_CHUNK, scriptData->text, chunkSize)) {
+ delete [] data;
+ unloadScript(scriptData);
+ error("Couldn't load TEXT chunk from file: '%s'", filename);
+ return false;
}
}
+
+ chunkSize = getIFFBlockSize(data, curData, size, ORDR_CHUNK);
+ if (chunkSize == (uint32)-1) {
+ delete [] data;
+ unloadScript(scriptData);
+ error("No ORDR chunk found in file: '%s'", filename);
+ return false;
+ }
+ if (specialPtr) {
+ scriptData->mustBeFreed = 0;
+ scriptData->ordr = specialPtr;
+ specialPtr += chunkSize;
+ } else {
+ scriptData->mustBeFreed = 1;
+ scriptData->ordr = new byte[chunkSize];
+ }
+ if (!loadIFFBlock(data, curData, size, ORDR_CHUNK, scriptData->ordr, chunkSize)) {
+ delete [] data;
+ unloadScript(scriptData);
+ error("Couldn't load ORDR chunk from file: '%s'", filename);
+ return false;
+ }
+ chunkSize = chunkSize / 2;
+ while (chunkSize--) {
+ ((uint16*)scriptData->ordr)[chunkSize] = READ_BE_UINT16(&((uint16*)scriptData->ordr)[chunkSize]);
+ }
+
+ chunkSize = getIFFBlockSize(data, curData, size, DATA_CHUNK);
+ if (chunkSize == (uint32)-1) {
+ delete [] data;
+ unloadScript(scriptData);
+ error("No DATA chunk found in file: '%s'", filename);
+ return false;
+ }
+ if (specialPtr) {
+ scriptData->mustBeFreed = 0;
+ scriptData->data = specialPtr;
+ specialPtr += chunkSize;
+ } else {
+ scriptData->mustBeFreed = 1;
+ scriptData->data = new byte[chunkSize];
+ }
+ if (!loadIFFBlock(data, curData, size, DATA_CHUNK, scriptData->data, chunkSize)) {
+ delete [] data;
+ unloadScript(scriptData);
+ error("Couldn't load DATA chunk from file: '%s'", filename);
+ return false;
+ }
+ scriptData->dataSize = chunkSize / 2;
+
+ delete [] data;
+ return true;
}
-int32 VMContext::param(int32 index) {
- if (_stackPos - index - 1 >= ARRAYSIZE(_stack) || _stackPos - index - 1 < 0)
- return -0xFFFF;
- return _stack[_stackPos - index - 1];
+void ScriptHelper::unloadScript(ScriptData *data) {
+ if (data->mustBeFreed) {
+ delete [] data->text;
+ delete [] data->ordr;
+ delete [] data->data;
+ }
+
+ data->mustBeFreed = 0;
+ data->text = data->ordr = data->data = 0;
}
-const char* VMContext::stringAtIndex(int32 index) {
- if (index < 0 || (uint32)index >= _chunks[kText]._size)
- return 0;
-
- return (const char *)(_chunks[kText]._additional + _chunks[kText]._data[index]);
+void ScriptHelper::initScript(ScriptState *scriptStat, ScriptData *data) {
+ scriptStat->dataPtr = data;
+ scriptStat->ip = 0;
+ scriptStat->stack[60] = 0;
+ scriptStat->bp = 62;
+ scriptStat->sp = 60;
}
-bool VMContext::startScript(int32 func) {
- if ((uint32)func >= _chunks[kEmc2Ordr]._size || func < 0) {
- debug("script doesn't support function %d", func);
+bool ScriptHelper::startScript(ScriptState *script, int function) {
+ if (!script->dataPtr) {
return false;
}
-
- _instructionPos = READ_BE_UINT16(&_chunks[kEmc2Ordr]._data[func]) << 1;
- _stackPos = 0;
- _tempPos = 0;
- _delay = 0;
- _error = false;
- _scriptState = kScriptRunning;
-
- uint32 pos = 0xFFFFFFFE;
-
- // get start of next script
- for (uint32 tmp = 0; tmp < _chunks[kEmc2Ordr]._size; ++tmp) {
- if ((uint32)((READ_BE_UINT16(&_chunks[kEmc2Ordr]._data[tmp]) << 1)) > (uint32)_instructionPos &&
- (uint32)((READ_BE_UINT16(&_chunks[kEmc2Ordr]._data[tmp]) << 1)) < pos) {
- pos = ((READ_BE_UINT16(&_chunks[kEmc2Ordr]._data[tmp]) << 1));
- }
- }
-
- if (pos > _scriptFileSize) {
- pos = _scriptFileSize;
+ uint16 functionOffset = ((uint16*)script->dataPtr->ordr)[function];
+ if (functionOffset == (uint16)-1) {
+ return false;
}
-
- _nextScriptPos = pos;
-
+ script->ip = &script->dataPtr->data[functionOffset*2+2];
return true;
}
-uint32 VMContext::contScript(void) {
- uint8* script_start = _chunks[kData]._data;
- assert(script_start);
-
- uint32 scriptStateAtStart = _scriptState;
-
- // runs the script
- while (true) {
- if ((uint32)_instructionPos > _chunks[kData]._size) {
- debug("_instructionPos( = %d) > _chunks[kData]._size( = %d)", _instructionPos, _chunks[kData]._size);
- _error = true;
- break;
- } else if (_instructionPos >= _nextScriptPos) {
- _scriptState = kScriptStopped;
- break;
- }
-
- _currentCommand = *(script_start + _instructionPos++);
-
- // gets out
- if (_currentCommand & 0x80) {
- _argument = ((_currentCommand & 0x0F) << 8) | *(script_start + _instructionPos++);
- _currentCommand &= 0xF0;
- } else if (_currentCommand & 0x40) {
- _argument = *(script_start + _instructionPos++);
- } else if (_currentCommand & 0x20) {
- _instructionPos++;
-
- uint16 tmp = *(uint16*)(script_start + _instructionPos);
- tmp &= 0xFF7F;
+bool ScriptHelper::validScript(ScriptState *script) {
+ if (!script->ip || !script->dataPtr)
+ return false;
+ return true;
+}
- _argument = READ_BE_UINT16(&tmp);
- _instructionPos += 2;
- } else {
- debug("unknown way of getting the command (0x%X)", _currentCommand);
- // next thing
- continue;
- }
+bool ScriptHelper::runScript(ScriptState *script) {
+ _curScript = script;
+ _parameter = 0;
+ _continue = true;
+
+ if (!_curScript->ip) {
+ return false;
+ }
+
+ int16 code = READ_BE_UINT16(_curScript->ip); _curScript->ip += 2;
+ int16 opcode = (code >> 8) & 0x1F;
+
+ if (code & 0x8000) {
+ opcode = 0;
+ _parameter = code & 0x7FFF;
+ } else if (code & 0x4000) {
+ _parameter = code & 0xFF;
+ } else if (code & 0x2000) {
+ _parameter = READ_BE_UINT16(_curScript->ip); _curScript->ip += 2;
+ } else {
+ _parameter = 0;
+ }
+
+ if (opcode > 18) {
+ error("Script unknown command: %d", opcode);
+ } else {
+ debug(5, "%s(%d)", _commands[opcode].desc, _parameter);
+ (this->*(_commands[opcode].proc))();
+ }
+
+ _curScript = 0;
+ return _continue;
+}
- _currentCommand &= 0x1f;
+uint32 ScriptHelper::getFORMBlockSize(byte *&data) const {
+ static const uint32 chunkName = FORM_CHUNK;
+ if (READ_LE_UINT32(data) != chunkName) {
+ return (uint32)-1;
+ }
+ data += 4;
+ uint32 retValue = READ_BE_UINT32(data); data += 4;
+ return retValue;
+}
- if (_currentCommand < _numCommands) {
- CommandProc currentProc = _commands[_currentCommand].proc;
- (this->*currentProc)();
+uint32 ScriptHelper::getIFFBlockSize(byte *start, byte *&data, uint32 maxSize, const uint32 chunkName) const {
+ uint32 size = (uint32)-1;
+ bool special = false;
+
+ if (data == (start + maxSize)) {
+ data = start + 0x0C;
+ }
+ while (data < (start + maxSize)) {
+ uint32 chunk = READ_LE_UINT32(data); data += 4;
+ uint32 size_temp = READ_BE_UINT32(data); data += 4;
+ if (chunk != chunkName) {
+ if (special) {
+ data += (size_temp + 1) & 0xFFFFFFFE;
+ } else {
+ data = start + 0x0C;
+ special = true;
+ }
} else {
- c1_unknownCommand();
- }
-
- if (_error) {
- _scriptState = kScriptError;
+ // kill our data
+ data = start;
+ size = size_temp;
break;
}
+ }
+ return size;
+}
- if (scriptStateAtStart != _scriptState) {
- break;
+bool ScriptHelper::loadIFFBlock(byte *start, byte *&data, uint32 maxSize, const uint32 chunkName, byte *loadTo, uint32 ptrSize) const {
+ bool special = false;
+
+ if (data == (start + maxSize)) {
+ data = start + 0x0C;
+ }
+ while (data < (start + maxSize)) {
+ uint32 chunk = READ_LE_UINT32(data); data += 4;
+ uint32 chunkSize = READ_BE_UINT32(data); data += 4;
+ if (chunk != chunkName) {
+ if (special) {
+ data += (chunkSize + 1) & 0xFFFFFFFE;
+ } else {
+ data = start + 0x0C;
+ special = true;
+ }
+ } else {
+ uint32 loadSize = 0;
+ if (chunkSize < ptrSize)
+ loadSize = chunkSize;
+ else
+ loadSize = ptrSize;
+ memcpy(loadTo, data, loadSize);
+ chunkSize = (chunkSize + 1) & 0xFFFFFFFE;
+ if (chunkSize > loadSize) {
+ data += (chunkSize - loadSize);
+ }
+ return true;
}
}
-
- return _scriptState;
+ return false;
}
} // end of namespace Kyra