aboutsummaryrefslogtreecommitdiff
path: root/engines/cine
diff options
context:
space:
mode:
authorEugene Sandulenko2008-04-07 20:24:40 +0000
committerEugene Sandulenko2008-04-07 20:24:40 +0000
commit732774fd8de3cb6cebcd78730813d26e0330e66e (patch)
tree4576a02c29f1b62ad4da8c49c3225096dba256aa /engines/cine
parent9377fc7dc8548eb5369c99f5ab3e2437e756a003 (diff)
downloadscummvm-rg350-732774fd8de3cb6cebcd78730813d26e0330e66e.tar.gz
scummvm-rg350-732774fd8de3cb6cebcd78730813d26e0330e66e.tar.bz2
scummvm-rg350-732774fd8de3cb6cebcd78730813d26e0330e66e.zip
Patch #1913862: "CinE Script system"
svn-id: r31444
Diffstat (limited to 'engines/cine')
-rw-r--r--engines/cine/anim.cpp693
-rw-r--r--engines/cine/anim.h45
-rw-r--r--engines/cine/bg.cpp37
-rw-r--r--engines/cine/bg.h7
-rw-r--r--engines/cine/bg_list.cpp165
-rw-r--r--engines/cine/bg_list.h10
-rw-r--r--engines/cine/cine.cpp26
-rw-r--r--engines/cine/gfx.cpp107
-rw-r--r--engines/cine/gfx.h22
-rw-r--r--engines/cine/main_loop.cpp7
-rw-r--r--engines/cine/object.cpp8
-rw-r--r--engines/cine/object.h2
-rw-r--r--engines/cine/part.cpp1
-rw-r--r--engines/cine/part.h18
-rw-r--r--engines/cine/prc.cpp53
-rw-r--r--engines/cine/prc.h18
-rw-r--r--engines/cine/rel.cpp64
-rw-r--r--engines/cine/rel.h17
-rw-r--r--engines/cine/script.cpp2739
-rw-r--r--engines/cine/script.h428
-rw-r--r--engines/cine/sound.cpp4
-rw-r--r--engines/cine/texte.cpp2
-rw-r--r--engines/cine/various.cpp549
-rw-r--r--engines/cine/xref.txt146
24 files changed, 3075 insertions, 2093 deletions
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 698022cc1b..0d1bd20e7a 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -23,6 +23,9 @@
*
*/
+/*! \file
+ * \todo Make resource manager class and make load* functions its members
+ */
#include "common/endian.h"
#include "common/stream.h"
@@ -46,11 +49,9 @@ struct AnimHeader2Struct {
uint16 field_E;
};
-static uint16 animDataCount = 0;
-
-AnimHeaderStruct animHeader;
+AnimData animDataTable[NUM_MAX_ANIMDATA];
-static const AnimDataEntry animData[] = {
+static const AnimDataEntry transparencyData[] = {
{"ALPHA", 0xF},
{"TITRE2", 0xF},
{"ET", 0xC},
@@ -184,135 +185,250 @@ static const AnimDataEntry animData[] = {
{"FIN", 0x9},
};
-static void freeAnimData(byte idx) {
- assert(idx < NUM_MAX_ANIMDATA);
- if (animDataTable[idx].ptr1) {
- free(animDataTable[idx].ptr1);
- free(animDataTable[idx].ptr2);
- memset(&animDataTable[idx], 0, sizeof(AnimData));
- animDataTable[idx].fileIdx = -1;
- animDataTable[idx].frameIdx = -1;
- if (animDataCount > 0)
- animDataCount--;
- }
-}
+void convertMask(byte *dest, const byte *source, int16 width, int16 height);
+void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
+void convert8BBP(byte *dest, const byte *source, int16 width, int16 height);
+void convert8BBP2(byte *dest, byte *source, int16 width, int16 height);
-void freeAnimDataRange(byte startIdx, byte numIdx) {
- for (byte i = 0; i < numIdx; i++) {
- freeAnimData(i + startIdx);
- }
-}
+AnimData::AnimData() : _width(0), _height(0), _bpp(0), _var1(0), _data(NULL),
+ _mask(NULL), _fileIdx(-1), _frameIdx(-1), _realWidth(0), _size(0) {
-void freeAnimDataTable() {
- freeAnimDataRange(0, NUM_MAX_ANIMDATA);
+ memset(_name, 0, 10);
}
-static byte getAnimTransparentColor(const char *animName) {
- char name[15];
-
- removeExtention(name, animName);
-
- for (int i = 0; i < ARRAYSIZE(animData); i++) {
- if (!strcmp(name, animData[i].name)) {
- return animData[i].color;
- }
+/*! \brief Copy constructor
+ */
+AnimData::AnimData(const AnimData &src) : _width(src._width),
+ _height(src._height), _bpp(src._bpp), _var1(src._var1),
+ _data(NULL), _mask(NULL), _fileIdx(src._fileIdx),
+ _frameIdx(src._frameIdx), _realWidth(src._realWidth), _size(src._size) {
+
+ if (src._data) {
+ _data = new byte[_size];
+ assert(_data);
+ memcpy(_data, src._data, _size*sizeof(byte));
}
- return 0;
-}
-int16 allocFrame(uint16 width, uint16 height, int8 isMask) {
- uint16 i;
- uint32 frameSize;
-
- for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
- if (!animDataTable[i].ptr1)
- break;
+ if(src._mask) {
+ _mask = new byte[_size];
+ assert(_mask);
+ memcpy(_mask, src._mask, _size*sizeof(byte));
}
- if (i == NUM_MAX_ANIMDATA)
- return -1;
+ memset(_name, 0, 10);
+ strcpy(_name, src._name);
+}
- if (!isMask) { // sprite + generated mask
- frameSize = width * height;
+/*! \brief Destructor
+ */
+AnimData::~AnimData() {
+ clear();
+}
- animDataTable[i].ptr1 = (byte *)malloc(frameSize);
- animDataTable[i].ptr2 = (byte *)malloc(frameSize);
- } else {
- // mask
- frameSize = width * height * 8;
+/*! \brief Assingment operator
+ */
+AnimData &AnimData::operator=(const AnimData &src) {
+ AnimData tmp = src;
+ byte *ptr;
- animDataTable[i].ptr1 = (byte *)malloc(frameSize);
- animDataTable[i].ptr2 = NULL;
- }
+ _width = tmp._width;
+ _height = tmp._height;
+ _bpp = tmp._bpp;
+ _var1 = tmp._var1;
- animDataTable[i].width = width;
- animDataTable[i].var1 = width >> 3;
- animDataTable[i].bpp = 4;
- animDataTable[i].height = height;
+ ptr = _data;
+ _data = tmp._data;
+ tmp._data = ptr;
- animDataTable[i].fileIdx = -1;
- animDataTable[i].frameIdx = -1;
+ ptr = _mask;
+ _mask = tmp._mask;
+ tmp._mask = ptr;
- animDataCount++;
+ _fileIdx = tmp._fileIdx;
+ _frameIdx = tmp._frameIdx;
+ memset(_name, 0, 10);
+ strcpy(_name, tmp._name);
+ _realWidth = tmp._realWidth;
+ _size = tmp._size;
- return i;
+ return *this;
}
-int16 reserveFrame(uint16 width, uint16 height, uint16 type, int16 idx) {
- uint16 i;
- uint32 frameSize;
+byte AnimData::getColor(int x, int y) {
+ assert(_data);
+ assert(x >= 0 && x < _realWidth && y >= 0 && y <= _height);
+ assert(x + y * _realWidth < _size);
- if (idx >= 0) {
- i = (uint16) idx;
- } else {
- for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
- if (!animDataTable[i].ptr1)
- break;
- }
+ return _data[x + y * _realWidth];
+}
- if (i == NUM_MAX_ANIMDATA)
- return -1;
- }
+/*! \brief Load and decode image frame
+ * \param d Encoded image data
+ * \param type Encoding type
+ * \param w Image width
+ * \param h Image height
+ * \param file Data file index in bundle
+ * \param frame Image frame index
+ * \param n Part name
+ * \param transparent Transparent color (for ANIM_MASKSPRITE)
+ */
+void AnimData::load(byte *d, int type, uint16 w, uint16 h, int16 file,
+ int16 frame, const char *n, byte transparent) {
- frameSize = width * height;
+ assert(d);
- if (type == 4) { // 256 color sprites
- frameSize *= 2;
- type = 8;
- width *= 2;
+ if (_data) {
+ clear();
}
- if (type == 5) {
- frameSize += 16;
+ _width = w * 2;
+ _height = h;
+ _var1 = _width >> 3;
+ _data = NULL;
+ _mask = NULL;
+ _fileIdx = file;
+ _frameIdx = frame;
+ memset(_name, 0, 10);
+ strcpy(_name, n);
+ _realWidth = w;
+
+ switch (type) {
+ case ANIM_RAW:
+ _width = w;
+ _var1 = w >> 3;
+ _bpp = 4;
+ _size = w * h;
+ _data = new byte[_size];
+ assert(_data);
+ memcpy(_data, d, _size*sizeof(byte));
+ break;
+
+ case ANIM_MASK:
+ _bpp = 1;
+ _size = w * h * 8;
+ _data = new byte[_size];
+ _realWidth = w * 8;
+ assert(_data);
+ convertMask(_data, d, w, h);
+ break;
+
+ case ANIM_SPRITE:
+ _bpp = 4;
+ _size = w * h * 2;
+ _data = new byte[_size];
+ _realWidth = w * 2;
+ assert(_data);
+ gfxConvertSpriteToRaw(_data, d, w, h);
+ break;
+
+ case ANIM_MASKSPRITE:
+ _bpp = 4;
+ _size = w * h * 2;
+ _data = new byte[_size];
+ _mask = new byte[_size];
+ _realWidth = w * 2;
+ assert(_data && _mask);
+ gfxConvertSpriteToRaw(_data, d, w, h);
+ generateMask(_data, _mask, _size, transparent);
+ break;
+
+ case ANIM_PALSPRITE:
+ _bpp = 5;
+ _size = w * h * 2;
+ _data = new byte[_size];
+ _realWidth = w * 2;
+ assert(_data);
+ convert8BBP(_data, d, w, h);
+ break;
+
+ case ANIM_FULLSPRITE:
+ _bpp = 8;
+ _var1 = _width >> 4;
+ _size = w * h;
+ _data = new byte[_size];
+ assert(_data);
+ convert8BBP2(_data, d, w, h);
+ break;
+
+ default:
+ error("AnimData::load: unknown image type");
}
+}
- frameSize *= 2;
-
- animDataTable[i].ptr1 = (byte *)malloc(frameSize);
-
- assert(animDataTable[i].ptr1);
+/*! \brief Reset image
+ */
+void AnimData::clear() {
+ delete[] _data;
+ delete [] _mask;
+
+ _width = 0;
+ _height = 0;
+ _bpp = 0;
+ _var1 = 0;
+ _data = NULL;
+ _mask = NULL;
+ _fileIdx = -1;
+ _frameIdx = -1;
+ memset(_name, 0, 10);
+ _size = 0;
+}
- animDataTable[i].width = width;
+/*! \brief Write image identifiers to savefile
+ * \param fHandle Savefile open for writing
+ */
+void AnimData::save(Common::OutSaveFile &fHandle) const {
+ fHandle.writeUint16BE(_width);
+ fHandle.writeUint16BE(_var1);
+ fHandle.writeUint16BE(_bpp);
+ fHandle.writeUint16BE(_height);
+ // Just because I write pointers to a file doesn't mean
+ // anyone should actually read those values back!
+ fHandle.writeUint32BE((uint32)_data);
+ fHandle.writeUint32BE((uint32)_mask);
+ fHandle.writeUint16BE(_fileIdx);
+ fHandle.writeUint16BE(_frameIdx);
+ fHandle.write(_name, 10);
+}
- if (type == 5) {
- animDataTable[i].var1 = width / 8;
- } else {
- animDataTable[i].var1 = width / 16;
+/*! \brief Clear part of animDataTable
+ * \param startIdx First image frame to be cleared
+ * \param numIdx Number of image frames to be cleared
+ */
+void freeAnimDataRange(byte startIdx, byte numIdx) {
+ for (byte i = 0; i < numIdx; i++) {
+ animDataTable[startIdx + i].clear();
}
+}
- animDataTable[i].bpp = type;
-
- animDataTable[i].height = height;
+/*! \brief Clear whole animDataTable
+ */
+void freeAnimDataTable() {
+ freeAnimDataRange(0, NUM_MAX_ANIMDATA);
+}
- animDataTable[i].fileIdx = -1;
- animDataTable[i].frameIdx = -1;
+/*! \brief Find transparent color index for image
+ * \brief animName Image file name
+ */
+static byte getAnimTransparentColor(const char *animName) {
+ char name[15];
- animDataCount++;
+ removeExtention(name, animName);
- return i;
+ for (int i = 0; i < ARRAYSIZE(transparencyData); i++) {
+ if (!strcmp(name, transparencyData[i].name)) {
+ return transparencyData[i].color;
+ }
+ }
+ return 0;
}
-void generateMask(byte * sprite, byte * mask, uint16 size, byte transparency) {
+/*! \brief Generate mask for image
+ * \param[in] sprite Image data
+ * \param[out] mask Image mask
+ * \param size Image data length
+ * \param transparency Transparent color index
+ */
+void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency) {
for (uint16 i = 0; i < size; i++) {
if (*(sprite++) != transparency) {
*(mask++) = 0;
@@ -322,7 +438,13 @@ void generateMask(byte * sprite, byte * mask, uint16 size, byte transparency) {
}
}
-void convertMask(byte * dest, byte * source, int16 width, int16 height) {
+/*! \brief Decode 1bpp mask
+ * \param[out] dest Decoded mask
+ * \param[in] source Encoded mask
+ * \param width Mask width
+ * \param height Mask height
+ */
+void convertMask(byte *dest, const byte *source, int16 width, int16 height) {
int16 i, j;
byte maskEntry;
@@ -335,7 +457,13 @@ void convertMask(byte * dest, byte * source, int16 width, int16 height) {
}
}
-void convert4BBP(byte * dest, byte * source, int16 width, int16 height) {
+/*! \brief Decode 4bpp sprite
+ * \param[out] dest Decoded image
+ * \param[in] source Encoded image
+ * \param width Image width
+ * \param height Image height
+ */
+void convert4BBP(byte *dest, const byte *source, int16 width, int16 height) {
byte maskEntry;
for (int16 i = 0; i < width * height; i++) {
@@ -345,7 +473,11 @@ void convert4BBP(byte * dest, byte * source, int16 width, int16 height) {
}
}
-void loadAnimHeader(Common::MemoryReadStream readS) {
+/*! \brief Read image header
+ * \param[out] animHeader Image header reference
+ * \param readS Input stream open for reading
+ */
+void loadAnimHeader(AnimHeaderStruct &animHeader, Common::MemoryReadStream readS) {
animHeader.field_0 = readS.readByte();
animHeader.field_1 = readS.readByte();
animHeader.field_2 = readS.readByte();
@@ -366,115 +498,109 @@ void loadAnimHeader(Common::MemoryReadStream readS) {
animHeader.field_14 = readS.readUint16BE();
}
+/*! \brief Find next empty space animDataTable
+ * \param start First index to check
+ */
+int emptyAnimSpace(int start = 0) {
+ for (; start < NUM_MAX_ANIMDATA; start++) {
+ if (!animDataTable[start].data()) {
+ return start;
+ }
+ }
+
+ return -1;
+}
+
+/*! \brief Load SPL data into animDataTable
+ * \param resourceName SPL filename
+ * \param idx Target index in animDataTable
+ */
void loadSpl(const char *resourceName, int16 idx) {
int16 foundFileIdx = findFileInBundle(resourceName);
- int16 entry;
- byte *dataPtr = readBundleFile(foundFileIdx);
+ int entry;
- if (idx >= 0) {
- entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx);
- memcpy(animDataTable[entry].ptr1, dataPtr, partBuffer[foundFileIdx].unpackedSize);
- } else {
- entry = allocFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, -1);
- assert(entry != -1);
- memcpy(animDataTable[entry].ptr1, dataPtr, (uint16) partBuffer[foundFileIdx].unpackedSize);
-
- animDataTable[entry].fileIdx = foundFileIdx;
- animDataTable[entry].frameIdx = 0;
- strcpy(animDataTable[entry].name, currentPartName);
+ if (foundFileIdx < 0) {
+ return;
}
+ byte *dataPtr = readBundleFile(foundFileIdx);
+
+ entry = idx < 0 ? emptyAnimSpace() : idx;
+ assert(entry >= 0);
+ animDataTable[entry].load(dataPtr, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
+
free(dataPtr);
}
+/*! \brief Load 1bpp mask
+ * \param resourceName Mask filename
+ */
void loadMsk(const char *resourceName) {
int16 foundFileIdx = findFileInBundle(resourceName);
- int16 entry;
+ int entry = 0;
byte *dataPtr = readBundleFile(foundFileIdx);
byte *ptr;
+ AnimHeaderStruct animHeader;
Common::MemoryReadStream readS(dataPtr, 0x16);
- loadAnimHeader(readS);
+ loadAnimHeader(animHeader, readS);
ptr = dataPtr + 0x16;
- for (int16 i = 0; i < animHeader.numFrames; i++) {
- entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 1);
-
- assert(entry != -1);
-
- convertMask(animDataTable[entry].ptr1, ptr, animHeader.frameWidth, animHeader.frameHeight);
+ for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
+ entry = emptyAnimSpace(entry);
+ assert(entry >= 0);
+ animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
ptr += animHeader.frameWidth * animHeader.frameHeight;
-
- animDataTable[entry].fileIdx = foundFileIdx;
- animDataTable[entry].frameIdx = i;
- strcpy(animDataTable[entry].name, currentPartName);
}
free(dataPtr);
}
+/*! \brief Load animation
+ * \param resourceName Animation filename
+ */
void loadAni(const char *resourceName) {
int16 foundFileIdx = findFileInBundle(resourceName);
- int16 entry;
+ int entry = 0;
byte *dataPtr = readBundleFile(foundFileIdx);
- byte *ptr, *animPtr;
+ byte *ptr;
byte transparentColor;
- uint32 fullSize;
+ AnimHeaderStruct animHeader;
Common::MemoryReadStream readS(dataPtr, 0x16);
- loadAnimHeader(readS);
+ loadAnimHeader(animHeader, readS);
ptr = dataPtr + 0x16;
transparentColor = getAnimTransparentColor(resourceName);
- fullSize = animHeader.frameWidth * animHeader.frameHeight;
-
- for (int16 i = 0; i < animHeader.numFrames; i++) {
- entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 0);
-
- assert(entry != -1);
+ for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
+ entry = emptyAnimSpace(entry);
+ assert(entry >= 0);
// special case transparency handling
if (!strcmp(resourceName, "L2202.ANI")) {
- if (i < 2) {
- transparentColor = 0;
- } else {
- transparentColor = 7;
- }
- }
-
- if (!strcmp(resourceName, "L4601.ANI")) {
- if (i < 1) {
- transparentColor = 0xE;
- } else {
- transparentColor = 0;
- }
+ transparentColor = i < 2 ? 0 : 7;
+ } else if (!strcmp(resourceName, "L4601.ANI")) {
+ transparentColor = i < 1 ? 0xE : 0;
}
- animPtr = (byte *)malloc(fullSize);
-
- memcpy(animPtr, ptr, fullSize);
- ptr += fullSize;
-
- gfxConvertSpriteToRaw(animDataTable[entry].ptr1, animPtr, animHeader.frameWidth, animHeader.frameHeight);
-
- generateMask(animDataTable[entry].ptr1, animDataTable[entry].ptr2, animHeader.frameWidth * 2 * animHeader.frameHeight, transparentColor);
-
- free(animPtr);
-
- animDataTable[entry].fileIdx = foundFileIdx;
- animDataTable[entry].frameIdx = i;
- strcpy(animDataTable[entry].name, currentPartName);
+ animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor);
+ ptr += animHeader.frameWidth * animHeader.frameHeight;
}
free(dataPtr);
}
-void convert8BBP(byte * dest, byte * source, int16 width, int16 height) {
- byte table[16];
+/*! \brief Decode 16 color image with palette
+ * \param[out] dest Decoded image
+ * \param[in] source Encoded image
+ * \param width Image width
+ * \param height Image height
+ */
+void convert8BBP(byte *dest, const byte *source, int16 width, int16 height) {
+ const byte *table = source;
byte color;
- memcpy(table, source, 16);
source += 16;
for (uint16 i = 0; i < width * height; i++) {
@@ -485,16 +611,24 @@ void convert8BBP(byte * dest, byte * source, int16 width, int16 height) {
}
}
-void convert8BBP2(byte * dest, byte * source, int16 width, int16 height) {
- uint16 i, j, k, m;
+/*! \brief Decode 8bit image
+ * \param[out] dest Decoded image
+ * \param[in] source Encoded image
+ * \param width Image width
+ * \param height Image height
+ * \attention Data in source are destroyed during decoding
+ */
+void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
+ uint16 i, j;
+ int k, m;
byte color;
for (j = 0; j < (width * height) / 16; j++) {
// m = 0: even bits, m = 1: odd bits
- for (m = 0; m < 2; m++) {
+ for (m = 0; m <= 1; m++) {
for (i = 0; i < 8; i++) {
color = 0;
- for (k = 14 + m; k >= 0 + m; k = k - 2) {
+ for (k = 14 + m; k >= 0; k -= 2) {
color |= ((*(source + k) & 0x080) >> 7);
*(source + k) <<= 1;
if (k > 0 + m)
@@ -508,14 +642,17 @@ void convert8BBP2(byte * dest, byte * source, int16 width, int16 height) {
} // end j
}
+/*! \brief Load image set
+ * \param resourceName Image set filename
+ * \param idx Target index in animDataTable
+ */
void loadSet(const char *resourceName, int16 idx) {
AnimHeader2Struct header2;
- uint32 fullSize;
uint16 numSpriteInAnim;
int16 foundFileIdx = findFileInBundle(resourceName);
- int16 entry, typeParam;
+ int16 entry = idx >= 0 ? idx : 0;
byte *ptr, *startOfDataPtr, *dataPtr, *origDataPtr;
- byte table[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ int type;
origDataPtr = dataPtr = readBundleFile(foundFileIdx);
assert(!memcmp(dataPtr, "SET", 3));
@@ -526,9 +663,7 @@ void loadSet(const char *resourceName, int16 idx) {
startOfDataPtr = ptr + numSpriteInAnim * 0x10;
- for (int16 i = 0; i < numSpriteInAnim; i++) {
- typeParam = 0;
-
+ for (int16 i = 0; i < numSpriteInAnim; i++, entry++) {
Common::MemoryReadStream readS(ptr, 0x10);
header2.field_0 = readS.readUint32BE();
@@ -541,56 +676,37 @@ void loadSet(const char *resourceName, int16 idx) {
ptr += 0x10;
- fullSize = header2.width * header2.height;
-
- if (header2.type == 5) {
- fullSize += 16;
- }
-
- if (header2.type == 4) {
- header2.type = 5;
- typeParam = 1;
- }
-
- if (idx >= 0)
- entry = reserveFrame(header2.width * 2, header2.height, header2.type, idx + i);
- else
- entry = reserveFrame(header2.width * 2, header2.height, header2.type, -1);
-
- assert(entry != -1);
+ entry = idx < 0 ? emptyAnimSpace(entry) : idx + i;
+ assert(entry >= 0);
dataPtr = startOfDataPtr + header2.field_0;
- if (typeParam) {
- memcpy(animDataTable[entry].ptr1, table, 0x10);
- gfxConvertSpriteToRaw(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
- //memcpy(animDataTable[entry].ptr1 + 0x10, dataPtr, fullSize);
+ if (header2.type == 1) {
+ type = ANIM_MASK;
+ } else if (header2.type == 4) {
+ type = ANIM_SPRITE;
+ } else if (header2.type == 5) {
+ type = ANIM_PALSPRITE;
} else {
- if (header2.type == 1) {
- convert4BBP(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
- } else if (header2.type == 5) {
- convert8BBP(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
- } else if (header2.type == 4) {
- error("loadSet: header2.type == 4");
- } else {
- convert8BBP2(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
- }
+ type = ANIM_FULLSPRITE;
}
- animDataTable[entry].fileIdx = foundFileIdx;
- animDataTable[entry].frameIdx = i;
- strcpy(animDataTable[entry].name, currentPartName);
+ animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName);
}
free(origDataPtr);
}
+/*! \brief Load SEQ data into animDataTable
+ * \param resourceName SEQ data filename
+ * \param idx Target index in animDataTable
+ */
void loadSeq(const char *resourceName, int16 idx) {
int16 foundFileIdx = findFileInBundle(resourceName);
byte *dataPtr = readBundleFile(foundFileIdx);
- int16 entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx);
+ int entry = idx < 0 ? emptyAnimSpace() : idx;
- memcpy(animDataTable[entry].ptr1, dataPtr + 0x16, (uint16) partBuffer[foundFileIdx].unpackedSize - 0x16);
+ animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName);
free(dataPtr);
}
@@ -624,6 +740,8 @@ void loadResource(const char *resourceName) {
error("loadResource: Cannot determine type for '%s'", resourceName);
}
+/*! \todo There seems to be some additional resource file that is not loaded
+ */
void loadAbs(const char *resourceName, uint16 idx) {
/* byte isMask = 0; */
/* byte isSpl = 0; */
@@ -632,6 +750,7 @@ void loadAbs(const char *resourceName, uint16 idx) {
loadSet(resourceName, idx);
return;
} else if (strstr(resourceName, ".H32")) {
+ warning("Ignoring file %s (load at %d)", resourceName, idx);
return;
} else if (strstr(resourceName, ".SEQ")) {
loadSeq(resourceName, idx);
@@ -640,116 +759,108 @@ void loadAbs(const char *resourceName, uint16 idx) {
loadSpl(resourceName, idx);
return;
} else if (strstr(resourceName, ".AMI")) {
+ warning("Ignoring file %s (load at %d)", resourceName, idx);
return;
} else if (strstr(resourceName, ".ANI")) {
+ warning("Ignoring file %s (load at %d)", resourceName, idx);
return;
}
error("loadAbs: Cannot determine type for '%s'", resourceName);
}
-void loadResourcesFromSave() {
- int16 currentAnim, foundFileIdx, fullSize, entry, i;
+/*! \brief Load animDataTable from save
+ * \param fHandle Savefile open for reading
+ * \param broken Broken/correct file format switch
+ * \todo Add Operation Stealth savefile support
+ *
+ * Unlike the old code, this one actually rebuilds the table one frame
+ * at a time.
+ */
+void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
+ int16 currentAnim, foundFileIdx;
int8 isMask = 0, isSpl = 0;
- byte *dataPtr, *ptr, *animPtr;
- char animName[256], part[256];
+ byte *dataPtr, *ptr;
+ char *animName, part[256];
byte transparentColor;
AnimData *currentPtr;
+ AnimHeaderStruct animHeader;
+
+ uint16 width, height, bpp, var1;
+ int16 frame;
+ char name[10];
+ int type;
strcpy(part, currentPartName);
for (currentAnim = 0; currentAnim < NUM_MAX_ANIMDATA; currentAnim++) {
currentPtr = &animDataTable[currentAnim];
- if (currentPtr->refresh && currentPtr->fileIdx != -1) {
- if (strcmp(currentPartName, currentPtr->name)) {
- closePart();
- loadPart(currentPtr->name);
+
+ width = fHandle.readUint16BE();
+ var1 = fHandle.readUint16BE();
+ bpp = fHandle.readUint16BE();
+ height = fHandle.readUint16BE();
+
+ if (!broken) {
+ if (!fHandle.readUint32BE()) {
+ fHandle.skip(18);
+ continue;
}
+ fHandle.readUint32BE();
+ }
- foundFileIdx = currentPtr->fileIdx;
+ foundFileIdx = fHandle.readSint16BE();
+ frame = fHandle.readSint16BE();
+ fHandle.read(name, 10);
- strcpy(animName, partBuffer[foundFileIdx].partName);
- ptr = dataPtr = readBundleFile(foundFileIdx);
+ if (foundFileIdx < 0 || (broken && !fHandle.readByte())) {
+ continue;
+ }
- isSpl = (strstr(animName, ".SPL")) ? 1 : 0;
- isMask = (strstr(animName, ".MSK")) ? 1 : 0;
+ if (strcmp(currentPartName, name)) {
+ closePart();
+ loadPart(name);
+ }
- if (isSpl) {
- animHeader.frameWidth = (uint16) partBuffer[foundFileIdx].unpackedSize;
- animHeader.frameHeight = 1;
- animHeader.numFrames = 1;
- isMask = -1;
- } else {
- Common::MemoryReadStream readS(ptr, 0x22);
+ animName = partBuffer[foundFileIdx].partName;
+ ptr = dataPtr = readBundleFile(foundFileIdx);
- loadAnimHeader(readS);
+ isSpl = (strstr(animName, ".SPL")) ? 1 : 0;
+ isMask = (strstr(animName, ".MSK")) ? 1 : 0;
- ptr += 0x16;
- }
+ if (isSpl) {
+ width = (uint16) partBuffer[foundFileIdx].unpackedSize;
+ height = 1;
+ frame = 0;
+ type = ANIM_RAW;
+ } else {
+ Common::MemoryReadStream readS(ptr, 0x16);
+ loadAnimHeader(animHeader, readS);
+ ptr += 0x16;
- {
- fullSize = animHeader.frameWidth * animHeader.frameHeight;
+ width = animHeader.frameWidth;
+ height = animHeader.frameHeight;
- loadRelatedPalette(animName);
+ if (isMask) {
+ type = ANIM_MASK;
+ } else {
+ type = ANIM_MASKSPRITE;
+ loadRelatedPalette(animName);
transparentColor = getAnimTransparentColor(animName);
- for (i = 0; i < animHeader.numFrames; i++) { // load all the frames
- // special case transparency handling
- if (!strcmp(animName, "L2202.ANI")) {
- if (i < 2) {
- transparentColor = 0;
- } else {
- transparentColor = 7;
- }
- }
-
- if (!strcmp(animName, "L4601.ANI")) {
- if (i < 1) {
- transparentColor = 0xE;
- } else {
- transparentColor = 0;
- }
- }
-
- currentPtr[i].ptr1 = NULL;
- entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, isMask);
-
- currentPtr->fileIdx = foundFileIdx;
-
- assert(entry != -1);
-
- if (isSpl) {
- memcpy(animDataTable[entry].ptr1, ptr, fullSize);
- ptr += fullSize;
- } else {
- if (!isMask) {
- animPtr = (byte *)malloc(fullSize);
- memcpy(animPtr, ptr, fullSize);
- ptr += fullSize;
-
- gfxConvertSpriteToRaw(animDataTable[entry].ptr1, animPtr,
- animHeader.frameWidth, animHeader.frameHeight);
- generateMask(animDataTable[entry].ptr1, animDataTable[entry].ptr2,
- animHeader.frameWidth * 2 *animHeader.frameHeight, transparentColor);
-
- free(animPtr);
- } else {
- convertMask(animDataTable[entry].ptr1, ptr, animHeader.frameWidth,
- animHeader.frameHeight);
- ptr += fullSize;
- }
- }
-
- //animDataTable[entry].fileIdx = foundFileIdx; // Only when reading from bundles
-
- animDataTable[entry].frameIdx = i;
- strcpy(animDataTable[entry].name, currentPartName);
+ // special case transparency handling
+ if (!strcmp(animName, "L2202.ANI")) {
+ transparentColor = (frame < 2) ? 0 : 7;
+ } else if (!strcmp(animName, "L4601.ANI")) {
+ transparentColor = (frame < 1) ? 0xE : 0;
}
}
-
- free(dataPtr);
}
+
+ ptr += frame * width * height;
+ currentPtr->load(ptr, type, width, height, foundFileIdx, frame, name, transparentColor);
+ free(dataPtr);
}
loadPart(part);
diff --git a/engines/cine/anim.h b/engines/cine/anim.h
index 92dbb2aaea..c15ab2eabd 100644
--- a/engines/cine/anim.h
+++ b/engines/cine/anim.h
@@ -54,11 +54,54 @@ struct AnimDataEntry {
byte color;
};
+#define ANIM_RAW 0 // memcpy
+#define ANIM_MASK 1 // convertMask
+#define ANIM_SPRITE 2 // gfxConvertSpriteToRaw
+#define ANIM_MASKSPRITE 3 // gfxConvertSpriteToRaw + generateMask
+#define ANIM_PALSPRITE 5 // convert8BBP
+#define ANIM_FULLSPRITE 8 // convert8BBP2
+
+class AnimData {
+private:
+ byte *_data; ///< Image data
+ byte *_mask; ///< Image mask (may be NULL)
+ int16 _fileIdx; ///< Source file index in bundle
+ int16 _frameIdx; ///< Frame number in animation
+ char _name[10]; ///< Part filename
+ int _size; ///< _data/_mask size, internal only
+
+public:
+ uint16 _width; ///< Image width (ussually twice the real size)
+ uint16 _height; ///< Image height
+ uint16 _bpp; ///< Bit depth/type information
+ uint16 _var1; ///< Something related to width
+ int _realWidth; ///< Real image width in bytes
+
+ AnimData();
+ AnimData(const AnimData &src);
+ ~AnimData();
+
+ AnimData &operator=(const AnimData &src);
+
+ const byte *data() const { return _data; } ///< Image data
+ const byte *mask() const { return _mask; } ///< Image mask (may be NULL)
+ byte getColor(int x, int y);
+
+ void load(byte *d, int type, uint16 w, uint16 h, int16 file, int16 frame, const char *n, byte transparent = 0);
+ void clear();
+
+ void save(Common::OutSaveFile &fHandle) const;
+};
+
+#define NUM_MAX_ANIMDATA 255
+
+extern AnimData animDataTable[NUM_MAX_ANIMDATA];
+
void freeAnimDataTable(void);
void freeAnimDataRange(byte startIdx, byte numIdx);
void loadResource(const char *animName);
void loadAbs(const char *resourceName, uint16 idx);
-void loadResourcesFromSave();
+void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken);
} // End of namespace Cine
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index f5b64573af..351a633b5e 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -29,6 +29,7 @@
#include "cine/cine.h"
#include "cine/various.h"
+#include "cine/bg.h"
namespace Cine {
@@ -36,10 +37,6 @@ uint16 bgVar0;
byte *additionalBgTable[9];
byte currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0;
-void loadCtHigh(byte * currentPtr) {
- memcpy(page3Raw, currentPtr, 320 * 200);
-}
-
byte loadCt(const char *ctName) {
uint16 header[32];
byte *ptr, *dataPtr;
@@ -52,10 +49,17 @@ byte loadCt(const char *ctName) {
if (g_cine->getGameType() == Cine::GType_OS) {
uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
if (bpp == 8) {
+ ctColorMode = 1;
+ memcpy(newPalette, ptr, 256*3);
ptr += 3 * 256;
- loadCtHigh(ptr);
+ memcpy(page3Raw, ptr, 320 * 200);
} else {
- ptr += 32;
+ ctColorMode = 0;
+ for (int i = 0; i < 16; i++) {
+ tempPalette[i] = READ_BE_UINT16(ptr);
+ ptr += 2;
+ }
+
gfxResetRawPage(page3Raw);
gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200);
}
@@ -78,12 +82,14 @@ byte loadCt(const char *ctName) {
}
void loadBgHigh(const char *currentPtr) {
- memcpy(palette256, currentPtr, 256 * 3);
+ memcpy(newPalette, currentPtr, 256 * 3);
currentPtr += 256 * 3;
memcpy(page2Raw, currentPtr, 320 * 200);
- colorMode256 = 1;
+ newColorMode = 2;
+ bgColorMode = 1;
+
}
byte loadBg(const char *bgName) {
@@ -99,7 +105,8 @@ byte loadBg(const char *bgName) {
if (bpp == 8) {
loadBgHigh((const char *)ptr);
} else {
- colorMode256 = 0;
+ newColorMode = 1;
+ bgColorMode = 0;
for (int i = 0; i < 16; i++) {
tempPalette[i] = READ_BE_UINT16(ptr);
@@ -127,12 +134,22 @@ void addBackground(const char *bgName, uint16 bgIdx) {
additionalBgTable[bgIdx] = (byte *) malloc(320 * 200);
+ debug("addBackground %d", bgIdx);
+
uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
+
if (bpp == 8) {
+ bgColorMode = 1;
+ memcpy(newPalette, ptr, 256*3);
ptr += 3 * 256;
memcpy(additionalBgTable[bgIdx], ptr, 320 * 200);
} else {
- ptr += 32;
+ bgColorMode = 0;
+ for (int i = 0; i < 16; i++) {
+ tempPalette[i] = READ_BE_UINT16(ptr);
+ ptr += 2;
+ }
+
gfxConvertSpriteToRaw(additionalBgTable[bgIdx], ptr, 160, 200);
}
free(dataPtr);
diff --git a/engines/cine/bg.h b/engines/cine/bg.h
index 7145af467a..ca5c222131 100644
--- a/engines/cine/bg.h
+++ b/engines/cine/bg.h
@@ -27,10 +27,17 @@
#define CINE_BG_H
namespace Cine {
+struct bgData {
+ byte *data;
+ byte colorMode;
+ byte *highPalette;
+ uint16 *lowPalette;
+};
byte loadBg(const char *bgName);
byte loadCt(const char *bgName);
+//extern bgData additionalBgTable[9];
extern byte *additionalBgTable[9];
extern byte currentAdditionalBgIdx;
extern byte currentAdditionalBgIdx2;
diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp
index 1d69407c8a..7d35f9981e 100644
--- a/engines/cine/bg_list.cpp
+++ b/engines/cine/bg_list.cpp
@@ -36,129 +36,116 @@
namespace Cine {
uint32 var8;
-BGIncrustList *bgIncrustList;
+Common::List<BGIncrust> bgIncrustList;
+/*! \brief Add masked sprite to the background
+ * \param objIdx Sprite description
+ * \param addList Add sprite to incrust list if true
+ * \todo Fix incrust objects on CT background. Always drawing incrust elements
+ * on CT background breaks game zones
+ */
void addToBGList(int16 objIdx, bool addList) {
int16 x = objectTable[objIdx].x;
int16 y = objectTable[objIdx].y;
- int16 width = animDataTable[objectTable[objIdx].frame].var1;
- int16 height = animDataTable[objectTable[objIdx].frame].height;
+ int16 width = animDataTable[objectTable[objIdx].frame]._var1;
+ int16 height = animDataTable[objectTable[objIdx].frame]._height;
+ const byte *data = animDataTable[objectTable[objIdx].frame].data();
+ const byte *mask = animDataTable[objectTable[objIdx].frame].mask();
// int16 part = objectTable[objIdx].part;
+ // Operation Stealth may switch among multiple backgrounds
if (g_cine->getGameType() == GType_OS) {
- drawSpriteRaw2(animDataTable[objectTable[objIdx].frame].ptr1, objectTable[objIdx].part, width, height, page2Raw, x, y);
+ for (int i = 0; i < 8; i++) {
+ if (additionalBgTable[i]) {
+ drawSpriteRaw2(data, objectTable[objIdx].part, width, height, additionalBgTable[i], x, y);
+ }
+ }
} else {
- drawSpriteRaw(animDataTable[objectTable[objIdx].frame].ptr1, animDataTable[objectTable[objIdx].frame].ptr2, width, height, page2Raw, x, y);
+ drawSpriteRaw(data, mask, width, height, page2Raw, x, y);
}
if (addList)
createBgIncrustListElement(objIdx, 0);
}
+/*! \brief Add filled sprite to the background
+ * \param objIdx Sprite description
+ * \param addList Add sprite to incrust list if true
+ * \todo Fix incrust objects on CT background. Always drawing incrust elements
+ * on CT background breaks game zones
+ */
void addSpriteFilledToBGList(int16 objIdx, bool addList) {
int16 x = objectTable[objIdx].x;
int16 y = objectTable[objIdx].y;
- int16 width = animDataTable[objectTable[objIdx].frame].width;
- int16 height = animDataTable[objectTable[objIdx].frame].height;
-
- if (animDataTable[objectTable[objIdx].frame].ptr1) {
- gfxFillSprite(animDataTable[objectTable[objIdx].frame].ptr1, width / 2, height, page2Raw, x, y);
+ int16 width = animDataTable[objectTable[objIdx].frame]._width;
+ int16 height = animDataTable[objectTable[objIdx].frame]._height;
+ const byte *data = animDataTable[objectTable[objIdx].frame].data();
+
+ if (data) {
+ // Operation Stealth may switch among multiple backgrounds
+ if (g_cine->getGameType() == GType_OS) {
+ for (int i = 0; i < 8; i++) {
+ if (additionalBgTable[i]) {
+ gfxFillSprite(data, width / 2, height, additionalBgTable[i], x, y);
+ }
+ }
+ } else {
+ gfxFillSprite(data, width / 2, height, page2Raw, x, y);
+ }
}
if (addList)
createBgIncrustListElement(objIdx, 1);
}
+/*! \brief Add new element to incrust list
+ * \param objIdx Element description
+ * \param param Type of element
+ */
void createBgIncrustListElement(int16 objIdx, int16 param) {
- BGIncrustList *bgIncrustPtr = bgIncrustList;
- BGIncrustList *bgIncrustPtrP = 0;
-
- // Find first empty element
- while (bgIncrustPtr) {
- bgIncrustPtrP = bgIncrustPtr;
- bgIncrustPtr = bgIncrustPtr->next;
- }
-
- bgIncrustPtr = new BGIncrustList;
- if (bgIncrustPtrP)
- bgIncrustPtrP->next = bgIncrustPtr;
- else
- bgIncrustList = bgIncrustPtr;
-
- bgIncrustPtr->next = 0;
-
- bgIncrustPtr->objIdx = objIdx;
- bgIncrustPtr->param = param;
- bgIncrustPtr->x = objectTable[objIdx].x;
- bgIncrustPtr->y = objectTable[objIdx].y;
- bgIncrustPtr->frame = objectTable[objIdx].frame;
- bgIncrustPtr->part = objectTable[objIdx].part;
-}
+ BGIncrust tmp;
-void freeBgIncrustList(void) {
- BGIncrustList *bgIncrustPtr = bgIncrustList;
- BGIncrustList *bgIncrustPtrN;
+ tmp.objIdx = objIdx;
+ tmp.param = param;
+ tmp.x = objectTable[objIdx].x;
+ tmp.y = objectTable[objIdx].y;
+ tmp.frame = objectTable[objIdx].frame;
+ tmp.part = objectTable[objIdx].part;
- while (bgIncrustPtr) {
- bgIncrustPtrN = bgIncrustPtr->next;
- delete bgIncrustPtr;
- bgIncrustPtr = bgIncrustPtrN;
- }
-
- resetBgIncrustList();
+ bgIncrustList.push_back(tmp);
}
+/*! \brief Reset var8 (probably something related to bgIncrustList
+ */
void resetBgIncrustList(void) {
- bgIncrustList = NULL;
var8 = 0;
}
-void loadBgIncrustFromSave(Common::InSaveFile *fHandle) {
- BGIncrustList *bgIncrustPtr = bgIncrustList;
- BGIncrustList *bgIncrustPtrP = 0;
-
- // Find first empty element
- while (bgIncrustPtr) {
- bgIncrustPtrP = bgIncrustPtr;
- bgIncrustPtr = bgIncrustPtr->next;
- }
-
- bgIncrustPtr = new BGIncrustList;
- if (bgIncrustPtrP)
- bgIncrustPtrP->next = bgIncrustPtr;
- else
- bgIncrustList = bgIncrustPtr;
-
- bgIncrustPtr->next = 0;
-
- fHandle->readUint32BE();
- fHandle->readUint32BE();
-
- bgIncrustPtr->objIdx = fHandle->readUint16BE();
- bgIncrustPtr->param = fHandle->readUint16BE();
- bgIncrustPtr->x = fHandle->readUint16BE();
- bgIncrustPtr->y = fHandle->readUint16BE();
- bgIncrustPtr->frame = fHandle->readUint16BE();
- bgIncrustPtr->part = fHandle->readUint16BE();
-}
-
-void reincrustAllBg(void) {
- BGIncrustList *bgIncrustPtr = bgIncrustList;
-
- while (bgIncrustPtr) {
-#if 0
- objectTable[bgIncrustPtr->objIdx].x = bgIncrustPtr->x;
- objectTable[bgIncrustPtr->objIdx].y = bgIncrustPtr->y;
- objectTable[bgIncrustPtr->objIdx].frame = bgIncrustPtr->frame;
- objectTable[bgIncrustPtr->objIdx].part = bgIncrustPtr->part;
-#endif
- if (bgIncrustPtr->param == 0) {
- addToBGList(bgIncrustPtr->objIdx, false);
+/*! \brief Restore incrust list from savefile
+ * \param fHandle Savefile open for reading
+ */
+void loadBgIncrustFromSave(Common::InSaveFile &fHandle) {
+ BGIncrust tmp;
+ int size = fHandle.readSint16BE();
+
+ for (int i = 0; i < size; i++) {
+ fHandle.readUint32BE();
+ fHandle.readUint32BE();
+
+ tmp.objIdx = fHandle.readUint16BE();
+ tmp.param = fHandle.readUint16BE();
+ tmp.x = fHandle.readUint16BE();
+ tmp.y = fHandle.readUint16BE();
+ tmp.frame = fHandle.readUint16BE();
+ tmp.part = fHandle.readUint16BE();
+
+ bgIncrustList.push_back(tmp);
+
+ if (tmp.param == 0) {
+ addToBGList(tmp.objIdx, false);
} else {
- addSpriteFilledToBGList(bgIncrustPtr->objIdx, false);
+ addSpriteFilledToBGList(tmp.objIdx, false);
}
-
- bgIncrustPtr = bgIncrustPtr->next;
}
}
diff --git a/engines/cine/bg_list.h b/engines/cine/bg_list.h
index a4b8b44a4c..9ceae0acf5 100644
--- a/engines/cine/bg_list.h
+++ b/engines/cine/bg_list.h
@@ -29,11 +29,11 @@
#include "common/scummsys.h"
#include "common/savefile.h"
+#include "common/list.h"
namespace Cine {
-struct BGIncrustList {
- struct BGIncrustList *next;
+struct BGIncrust {
byte *unkPtr;
int16 objIdx;
int16 param;
@@ -43,17 +43,15 @@ struct BGIncrustList {
int16 part;
};
-extern BGIncrustList *bgIncrustList;
+extern Common::List<BGIncrust> bgIncrustList;
extern uint32 var8;
void addToBGList(int16 objIdx, bool addList = true);
void addSpriteFilledToBGList(int16 idx, bool addList = true);
void createBgIncrustListElement(int16 objIdx, int16 param);
-void freeBgIncrustList(void);
void resetBgIncrustList(void);
-void loadBgIncrustFromSave(Common::InSaveFile *fHandle);
-void reincrustAllBg(void);
+void loadBgIncrustFromSave(Common::InSaveFile &fHandle);
} // End of namespace Cine
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index 8037502b96..ffcbfbaa82 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -111,8 +111,6 @@ void CineEngine::initialize() {
partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer));
- animDataTable = (AnimData *)malloc(NUM_MAX_ANIMDATA * sizeof(AnimData));
-
if (g_cine->getGameType() == Cine::GType_OS) {
readVolCnf();
}
@@ -124,30 +122,24 @@ void CineEngine::initialize() {
loadErrmessDat("errmess.dat");
}
+ // in case ScummVM engines can be restarted in the future
+ scriptTable.clear();
+ relTable.clear();
+ objectScripts.clear();
+ globalScripts.clear();
+ bgIncrustList.clear();
+ freeAnimDataTable();
+
memset(objectTable, 0, sizeof(objectTable));
- memset(scriptTable, 0, sizeof(scriptTable));
memset(messageTable, 0, sizeof(messageTable));
- memset(relTable, 0, sizeof(relTable));
-
- for (int i = 0; i < NUM_MAX_ANIMDATA; i++) {
- animDataTable[i].ptr1 = animDataTable[i].ptr2 = NULL;
- }
overlayHead.next = overlayHead.previous = NULL;
var8 = 0;
- bgIncrustList = NULL;
-
- objScriptList.next = NULL;
- objScriptList.scriptPtr = NULL;
-
- globalScriptsHead.next = NULL;
- globalScriptsHead.scriptPtr = NULL;
+// bgIncrustList = NULL;
var2 = var3 = var4 = var5 = 0;
- freePrcLinkedList();
-
_preLoad = false;
if (ConfMan.hasKey("save_slot")) {
char saveNameBuffer[256];
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index c76f62cdd7..8db4456485 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -37,6 +37,10 @@ namespace Cine {
uint16 c_palette[256];
byte colorMode256 = 0;
byte palette256[256 * 3];
+byte newPalette[256 * 3];
+byte newColorMode = 0;
+byte ctColorMode = 0;
+byte bgColorMode = 0;
byte *screenBuffer;
byte *page1Raw;
@@ -157,7 +161,7 @@ void transformPaletteRange(byte startColor, byte stopColor, int8 r, int8 g, int8
//gfxFlipPage(page2);
}
-void gfxFillSprite(byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
+void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
int16 i, j;
for (i = 0; i < height; i++) {
@@ -180,7 +184,7 @@ void gfxFillSprite(byte *spritePtr, uint16 width, uint16 height, byte *page, int
}
}
-void gfxDrawMaskedSprite(byte *spritePtr, byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
+void gfxDrawMaskedSprite(const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
int16 i, j;
for (i = 0; i < height; i++) {
@@ -198,7 +202,7 @@ void gfxDrawMaskedSprite(byte *spritePtr, byte *maskPtr, uint16 width, uint16 he
}
}
-void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr,
+void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx) {
int16 i, j, d, spritePitch, maskPitch;
@@ -299,8 +303,8 @@ void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte
}
}
-int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width) {
- byte *ptrToData = (ptr) + y * width + x;
+int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width) {
+ const byte *ptrToData = (ptr) + y * width + x;
if (x > width) {
return 0;
@@ -379,7 +383,7 @@ void gfxFlipRawPage(byte *frontBuffer) {
g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200);
}
-void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height,
+void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height,
byte *page, int16 x, int16 y) {
int16 i, j;
@@ -406,7 +410,7 @@ void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height,
}
}
-void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height,
+void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height,
byte *page, int16 x, int16 y) {
int16 i, j;
@@ -425,11 +429,84 @@ void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height,
}
}
+void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 height,
+ byte *page, int16 x, int16 y) {
+ int16 i, j;
+
+ for (i = 0; i < height; i++) {
+ byte *destPtr = page + x + y * 320;
+ const byte *srcPtr = bgPtr + x + y * 320;
+ destPtr += i * 320;
+ srcPtr += i * 320;
+
+ for (j = 0; j < width * 8; j++) {
+ if ((!maskPtr || !(*maskPtr)) && (x + j >= 0
+ && x + j < 320 && i + y >= 0 && i + y < 200)) {
+ *destPtr = *srcPtr;
+ }
+
+ destPtr++;
+ srcPtr++;
+ maskPtr++;
+ }
+ }
+}
+
+/*! \todo Fix rendering to prevent fadein artifacts
+ */
+void fadeFromBlack() {
+ int i, j;
+ int r, g, b, tr, tg, tb;
+ if (newColorMode == 2) {
+ colorMode256 = 1;
+ memset(palette256, 0, 256*3);
+ } else if (newColorMode == 1) {
+ colorMode256 = 0;
+ memset(c_palette, 0, 16 * sizeof(uint16));
+ }
+
+ for (i = 0; i < 8; i++ ) {
+ gfxFlipRawPage(page1Raw);
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+
+ if (colorMode256) {
+ for (j = 0; j < 256*3; j++) {
+ r = palette256[j] + (newPalette[j] + 7) / 8;
+ palette256[j] = CLIP(r, 0, (int)newPalette[j]);
+ }
+ } else {
+ for (j = 0; j < 16; j++) {
+ r = c_palette[j] & 0xf;
+ g = (c_palette[j] & 0xf0) >> 4;
+ b = (c_palette[j] & 0xf00) >> 8;
+
+ tr = tempPalette[j] & 0xf;
+ tg = (tempPalette[j] & 0xf0) >> 4;
+ tb = (tempPalette[j] & 0xf00) >> 8;
+
+ r = CLIP(r + (tr + 7) / 8, 0, tr);
+ g = CLIP(g + (tg + 7) / 8, 0, tg);
+ b = CLIP(b + (tb + 7) / 8, 0, tb);
+
+ c_palette[j] = r | (g << 4) | (b << 8);
+ }
+
+ }
+ }
+
+ if (colorMode256) {
+ memcpy(palette256, newPalette, 256*3);
+ } else {
+ memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
+ }
+}
+
void fadeToBlack() {
for (int i = 0; i < 8; i++) {
if (colorMode256) {
- for (int j = 0; j < 256; j++) {
- palette256[j] = transformColor(palette256[j], -1, -1, -1);
+ for (int j = 0; j < 256*3; j++) {
+ palette256[j] = CLIP(palette256[j] - 32, 0, 255);
}
} else {
for (int j = 0; j < 16; j++) {
@@ -449,7 +526,17 @@ void blitRawScreen(byte *frontBuffer) {
void flip(void) {
blitRawScreen(page1Raw);
if (fadeRequired) {
- memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
+ if (newColorMode == 3) {
+ newColorMode = ctColorMode + 1;
+ }
+
+ if (newColorMode == 2) {
+ colorMode256 = 1;
+ memcpy(palette256, newPalette, 256*3);
+ } else {
+ colorMode256 = 0;
+ memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
+ }
fadeRequired = false;
}
}
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index b2dc70f360..9e03f351f9 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -37,6 +37,10 @@ extern byte *page3Raw;
extern uint16 c_palette[256];
extern byte colorMode256;
extern byte palette256[256 * 3];
+extern byte newPalette[256 * 3];
+extern byte newColorMode;
+extern byte ctColorMode;
+extern byte bgColorMode;
void gfxInit();
void gfxDestroy();
@@ -46,10 +50,10 @@ void gfxCopyPage(byte *source, byte *dest);
void transformPaletteRange(byte startColor, byte numColor, int8 r, int8 g, int8 b);
void gfxFlipPage(void);
-void gfxDrawMaskedSprite(byte *ptr, byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
-void gfxFillSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
+void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
+void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
-void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr,
+void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx);
void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
@@ -57,19 +61,23 @@ void gfxDrawPlainBox(int16 x1, int16 y1, int16 x2, int16 y2, byte color);
void gfxResetPage(byte *pagePtr);
-int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width);
+int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width);
+byte gfxGetColor(int16 x, int16 y, const byte *ptr, int16 width);
void gfxResetRawPage(byte *pageRaw);
void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h);
void gfxCopyRawPage(byte *source, byte * dest);
void gfxFlipRawPage(byte *frontBuffer);
-void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
+void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
-void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y);
+void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y);
+void maskBgOverlay(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
+void fadeFromBlack(void);
void fadeToBlack(void);
-void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
+// wtf?!
+//void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
void gfxWaitVBL(void);
void gfxRedrawMouseCursor(void);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 263a5a2e49..c74dde0310 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -189,11 +189,8 @@ void CineEngine::mainLoop(int bootScriptIdx) {
quitFlag = 0;
if (_preLoad == false) {
- freeAnimDataTable();
resetMessageHead();
resetSeqList();
- resetglobalScriptsHead();
- resetObjectScriptHead();
resetBgIncrustList();
setTextWindow(0, 0, 20, 200);
@@ -318,14 +315,10 @@ void CineEngine::mainLoop(int bootScriptIdx) {
hideMouse();
g_sound->stopMusic();
- freeAnimDataTable();
unloadAllMasks();
- freePrcLinkedList();
- releaseObjectScripts();
// if (g_cine->getGameType() == Cine::GType_OS) {
// freeUnkList();
// }
- freeBgIncrustList();
closePart();
}
diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp
index 59adae6fc9..bba1c094f1 100644
--- a/engines/cine/object.cpp
+++ b/engines/cine/object.cpp
@@ -231,7 +231,9 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
objectTable[objIdx].frame = newValue;
break;
case 4:
- if (newValue == -1) {
+ // is it really in Future Wars? it breaks the newspaper machine
+ // on the airport in Operation Stealth
+ if (newValue == -1 && g_cine->getGameType() != Cine::GType_OS) {
objectTable[objIdx].costume = globalVars[0];
} else {
objectTable[objIdx].costume = newValue;
@@ -243,8 +245,8 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
}
}
-byte compareObjectParam(byte objIdx, byte type, int16 value) {
- byte compareResult = 0;
+uint16 compareObjectParam(byte objIdx, byte type, int16 value) {
+ uint16 compareResult = 0;
int16 objectParam = getObjectParam(objIdx, type);
if (objectParam > value) {
diff --git a/engines/cine/object.h b/engines/cine/object.h
index 92b3111841..e4ab1377ff 100644
--- a/engines/cine/object.h
+++ b/engines/cine/object.h
@@ -74,7 +74,7 @@ int16 freeOverlay(uint16 objIdx, uint16 param);
void addObjectParam(byte objIdx, byte paramIdx, int16 newValue);
void subObjectParam(byte objIdx, byte paramIdx, int16 newValue);
-byte compareObjectParam(byte objIdx, byte param1, int16 param2);
+uint16 compareObjectParam(byte objIdx, byte param1, int16 param2);
} // End of namespace Cine
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index 369ca8759d..43656460c5 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -33,7 +33,6 @@ namespace Cine {
uint16 numElementInPart;
-AnimData *animDataTable;
PartBuffer *partBuffer;
void loadPart(const char *partName) {
diff --git a/engines/cine/part.h b/engines/cine/part.h
index fae044afb1..2a979e4879 100644
--- a/engines/cine/part.h
+++ b/engines/cine/part.h
@@ -35,26 +35,8 @@ struct PartBuffer {
uint32 unpackedSize;
};
-struct AnimData {
- uint16 width;
- uint16 var1;
- uint16 bpp;
- uint16 height;
-
- byte *ptr1;
- byte *ptr2;
- int16 fileIdx;
- int16 frameIdx;
- char name[10];
-
- // Not part of the data, but used when saving/restoring it.
- bool refresh;
-};
-
#define NUM_MAX_PARTDATA 255
-#define NUM_MAX_ANIMDATA 255
-extern AnimData *animDataTable;
extern PartBuffer *partBuffer;
void loadPart(const char *partName);
diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp
index a8a14cc013..0f068a197e 100644
--- a/engines/cine/prc.cpp
+++ b/engines/cine/prc.cpp
@@ -33,34 +33,14 @@
namespace Cine {
-prcLinkedListStruct globalScriptsHead;
-prcLinkedListStruct objScriptList;
+ScriptList globalScripts;
+ScriptList objectScripts;
//char currentPrcName[20];
-void resetglobalScriptsHead(void) {
- globalScriptsHead.next = NULL;
- globalScriptsHead.scriptIdx = -1;
-}
-
-void freePrcLinkedList(void) {
- prcLinkedListStruct *currentHead = globalScriptsHead.next;
-
- while (currentHead) {
- prcLinkedListStruct *temp;
-
- assert(currentHead);
-
- temp = currentHead->next;
-
- delete currentHead;
-
- currentHead = temp;
- }
-
- resetglobalScriptsHead();
-}
-
+/*! \todo Is script size of 0 valid?
+ * \todo Fix script dump code
+ */
void loadPrc(const char *pPrcName) {
byte i;
uint16 numScripts;
@@ -68,14 +48,8 @@ void loadPrc(const char *pPrcName) {
assert(pPrcName);
- for (i = 0; i < NUM_MAX_SCRIPT; i++) {
- if (scriptTable[i].ptr) {
- assert(scriptTable[i].ptr);
- free(scriptTable[i].ptr);
- scriptTable[i].ptr = NULL;
- scriptTable[i].size = 0;
- }
- }
+ globalScripts.clear();
+ scriptTable.clear();
// This is copy protection. Used to hang the machine
if (!scumm_stricmp(pPrcName, "L201.ANI")) {
@@ -100,17 +74,18 @@ void loadPrc(const char *pPrcName) {
assert(numScripts <= NUM_MAX_SCRIPT);
for (i = 0; i < numScripts; i++) {
- scriptTable[i].size = READ_BE_UINT16(scriptPtr); scriptPtr += 2;
+ RawScriptPtr tmp(new RawScript(READ_BE_UINT16(scriptPtr)));
+ scriptPtr += 2;
+ assert(tmp);
+ scriptTable.push_back(tmp);
}
for (i = 0; i < numScripts; i++) {
- uint16 size = scriptTable[i].size;
+ uint16 size = scriptTable[i]->_size;
+ // TODO: delete the test?
if (size) {
- scriptTable[i].ptr = (byte *) malloc(size);
- assert(scriptTable[i].ptr);
- memcpy(scriptTable[i].ptr, scriptPtr, size);
+ scriptTable[i]->setData(*scriptInfo, scriptPtr);
scriptPtr += size;
- computeScriptStack(scriptTable[i].ptr, scriptTable[i].stack, size);
}
}
diff --git a/engines/cine/prc.h b/engines/cine/prc.h
index 2ec4ed6f95..f5129d28b1 100644
--- a/engines/cine/prc.h
+++ b/engines/cine/prc.h
@@ -28,21 +28,9 @@
namespace Cine {
-struct prcLinkedListStruct {
- struct prcLinkedListStruct *next;
- int16 stack[SCRIPT_STACK_SIZE];
- ScriptVars localVars;
- uint16 compareResult;
- uint16 scriptPosition;
- byte *scriptPtr;
- int16 scriptIdx;
-};
-
-extern prcLinkedListStruct globalScriptsHead;
-extern prcLinkedListStruct objScriptList;
-
-void resetglobalScriptsHead(void);
-void freePrcLinkedList(void);
+extern ScriptList globalScripts;
+extern ScriptList objectScripts;
+
void loadPrc(const char *pPrcName);
} // End of namespace Cine
diff --git a/engines/cine/rel.cpp b/engines/cine/rel.cpp
index c9c5755ac6..f550efed27 100644
--- a/engines/cine/rel.cpp
+++ b/engines/cine/rel.cpp
@@ -31,45 +31,21 @@
namespace Cine {
-RelObjectScript relTable[NUM_MAX_REL];
-
-void resetObjectScriptHead(void) {
- objScriptList.next = NULL;
- objScriptList.scriptIdx = -1;
-}
-
-void releaseObjectScripts(void) {
- prcLinkedListStruct *currentHead = objScriptList.next;
-
- while (currentHead) {
- prcLinkedListStruct *temp;
-
- assert(currentHead);
-
- temp = currentHead->next;
-
- delete currentHead;
-
- currentHead = temp;
- }
-
- resetObjectScriptHead();
-}
+RawObjectScriptArray relTable; ///< Object script bytecode table
+/*! \todo Is script size of 0 valid?
+ * \todo Fix script dump code
+ */
void loadRel(char *pRelName) {
uint16 numEntry;
uint16 i;
+ uint16 size, p1, p2, p3;
byte *ptr, *dataPtr;
checkDataDisk(-1);
- for (i = 0; i < NUM_MAX_REL; i++) {
- if (relTable[i].data) {
- free(relTable[i].data);
- relTable[i].data = NULL;
- relTable[i].size = 0;
- }
- }
+ objectScripts.clear();
+ relTable.clear();
ptr = dataPtr = readBundleFile(findFileInBundle(pRelName));
@@ -77,24 +53,22 @@ void loadRel(char *pRelName) {
numEntry = READ_BE_UINT16(ptr); ptr += 2;
- assert(numEntry <= NUM_MAX_REL);
-
for (i = 0; i < numEntry; i++) {
- relTable[i].size = READ_BE_UINT16(ptr); ptr += 2;
- relTable[i].obj1Param1 = READ_BE_UINT16(ptr); ptr += 2;
- relTable[i].obj1Param2 = READ_BE_UINT16(ptr); ptr += 2;
- relTable[i].obj2Param = READ_BE_UINT16(ptr); ptr += 2;
- relTable[i].runCount = 0;
+ size = READ_BE_UINT16(ptr); ptr += 2;
+ p1 = READ_BE_UINT16(ptr); ptr += 2;
+ p2 = READ_BE_UINT16(ptr); ptr += 2;
+ p3 = READ_BE_UINT16(ptr); ptr += 2;
+ RawObjectScriptPtr tmp(new RawObjectScript(size, p1, p2, p3));
+ assert(tmp);
+ relTable.push_back(tmp);
}
for (i = 0; i < numEntry; i++) {
- if (relTable[i].size) {
- relTable[i].data = (byte *)malloc(relTable[i].size);
-
- assert(relTable[i].data);
-
- memcpy(relTable[i].data, ptr, relTable[i].size);
- ptr += relTable[i].size;
+ size = relTable[i]->_size;
+ // TODO: delete the test?
+ if (size) {
+ relTable[i]->setData(*scriptInfo, ptr);
+ ptr += size;
}
}
diff --git a/engines/cine/rel.h b/engines/cine/rel.h
index 3e8332a55e..84926f76c4 100644
--- a/engines/cine/rel.h
+++ b/engines/cine/rel.h
@@ -26,23 +26,10 @@
#ifndef CINE_REL_H
#define CINE_REL_H
+#include "cine/script.h"
namespace Cine {
-struct RelObjectScript {
- byte *data;
- uint16 size;
- uint16 obj1Param1;
- uint16 obj1Param2;
- uint16 obj2Param;
- uint16 runCount;
-};
-
-#define NUM_MAX_REL 255
-
-extern RelObjectScript relTable[NUM_MAX_REL];
-
-void releaseObjectScripts(void);
-void resetObjectScriptHead(void);
+extern RawObjectScriptArray relTable;
void loadRel(char *pRelName);
diff --git a/engines/cine/script.cpp b/engines/cine/script.cpp
index c1bfee317a..8ccd0ce3a1 100644
--- a/engines/cine/script.cpp
+++ b/engines/cine/script.cpp
@@ -23,6 +23,9 @@
*
*/
+/*! \file
+ * Script interpreter file
+ */
#include "common/endian.h"
@@ -31,435 +34,423 @@
#include "cine/object.h"
#include "cine/sound.h"
#include "cine/various.h"
+#include "cine/script.h"
namespace Cine {
-prcLinkedListStruct *_currentScriptElement;
-byte *_currentScriptPtr;
-uint16 _currentScriptParams;
-uint16 _currentPosition;
-uint16 _currentLine;
-uint16 _closeScript;
-
-struct Opcode {
- void (*proc)();
- const char *args;
+uint16 compareVars(int16 a, int16 b);
+void palRotate(byte a, byte b, byte c);
+void removeSeq(uint16 param1, uint16 param2, uint16 param3);
+uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
+void addGfxElementA0(int16 param1, int16 param2);
+void removeGfxElementA0(int16 idx, int16 param);
+
+const Opcode FWScript::_opcodeTable[] = {
+ /* 00 */
+ { &FWScript::o1_modifyObjectParam, "bbw" },
+ { &FWScript::o1_getObjectParam, "bbb" },
+ { &FWScript::o1_addObjectParam, "bbw" },
+ { &FWScript::o1_subObjectParam, "bbw" },
+ /* 04 */
+ { &FWScript::o1_add2ObjectParam, "bbw" },
+ { &FWScript::o1_sub2ObjectParam, "bbw" },
+ { &FWScript::o1_compareObjectParam, "bbw" },
+ { &FWScript::o1_setupObject, "bwwww" },
+ /* 08 */
+ { &FWScript::o1_checkCollision, "bwwww" },
+ { &FWScript::o1_loadVar, "bc" },
+ { &FWScript::o1_addVar, "bc" },
+ { &FWScript::o1_subVar, "bc" },
+ /* 0C */
+ { &FWScript::o1_mulVar, "bc" },
+ { &FWScript::o1_divVar, "bc" },
+ { &FWScript::o1_compareVar, "bc" },
+ { &FWScript::o1_modifyObjectParam2, "bbb" },
+ /* 10 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_loadMask0, "b" },
+ /* 14 */
+ { &FWScript::o1_unloadMask0, "b" },
+ { &FWScript::o1_addToBgList, "b" },
+ { &FWScript::o1_loadMask1, "b" },
+ { &FWScript::o1_unloadMask1, "b" },
+ /* 18 */
+ { &FWScript::o1_loadMask4, "b" },
+ { &FWScript::o1_unloadMask4, "b" },
+ { &FWScript::o1_addSpriteFilledToBgList, "b" },
+ { &FWScript::o1_op1B, "" },
+ /* 1C */
+ { 0, 0 },
+ { &FWScript::o1_label, "l" },
+ { &FWScript::o1_goto, "b" },
+ { &FWScript::o1_gotoIfSup, "b" },
+ /* 20 */
+ { &FWScript::o1_gotoIfSupEqu, "b" },
+ { &FWScript::o1_gotoIfInf, "b" },
+ { &FWScript::o1_gotoIfInfEqu, "b" },
+ { &FWScript::o1_gotoIfEqu, "b" },
+ /* 24 */
+ { &FWScript::o1_gotoIfDiff, "b" },
+ { &FWScript::o1_removeLabel, "b" },
+ { &FWScript::o1_loop, "bb" },
+ { 0, 0 },
+ /* 28 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 2C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 30 */
+ { 0, 0 },
+ { &FWScript::o1_startGlobalScript, "b" },
+ { &FWScript::o1_endGlobalScript, "b" },
+ { 0, 0 },
+ /* 34 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 38 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_loadAnim, "s" },
+ /* 3C */
+ { &FWScript::o1_loadBg, "s" },
+ { &FWScript::o1_loadCt, "s" },
+ { 0, 0 },
+ { &FWScript::o1_loadPart, "s" },
+ /* 40 */
+ { &FWScript::o1_closePart, "" },
+ { &FWScript::o1_loadNewPrcName, "bs" },
+ { &FWScript::o1_requestCheckPendingDataLoad, "" },
+ { 0, 0 },
+ /* 44 */
+ { 0, 0 },
+ { &FWScript::o1_blitAndFade, "" },
+ { &FWScript::o1_fadeToBlack, "" },
+ { &FWScript::o1_transformPaletteRange, "bbwww" },
+ /* 48 */
+ { 0, 0 },
+ { &FWScript::o1_setDefaultMenuColor2, "b" },
+ { &FWScript::o1_palRotate, "bbb" },
+ { 0, 0 },
+ /* 4C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_break, "" },
+ /* 50 */
+ { &FWScript::o1_endScript, "x" },
+ { &FWScript::o1_message, "bwwww" },
+ { &FWScript::o1_loadGlobalVar, "bc" },
+ { &FWScript::o1_compareGlobalVar, "bc" },
+ /* 54 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 58 */
+ { 0, 0 },
+ { &FWScript::o1_declareFunctionName, "s" },
+ { &FWScript::o1_freePartRange, "bb" },
+ { &FWScript::o1_unloadAllMasks, "" },
+ // 5C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 60 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_setScreenDimensions, "wwww" },
+ /* 64 */
+ { &FWScript::o1_displayBackground, "" },
+ { &FWScript::o1_initializeZoneData, "" },
+ { &FWScript::o1_setZoneDataEntry, "bw" },
+ { &FWScript::o1_getZoneDataEntry, "bb" },
+ /* 68 */
+ { &FWScript::o1_setDefaultMenuColor, "b" },
+ { &FWScript::o1_allowPlayerInput, "" },
+ { &FWScript::o1_disallowPlayerInput, "" },
+ { &FWScript::o1_changeDataDisk, "b" },
+ /* 6C */
+ { 0, 0 },
+ { &FWScript::o1_loadMusic, "s" },
+ { &FWScript::o1_playMusic, "" },
+ { &FWScript::o1_fadeOutMusic, "" },
+ /* 70 */
+ { &FWScript::o1_stopSample, "" },
+ { &FWScript::o1_op71, "bw" },
+ { &FWScript::o1_op72, "wbw" },
+ { &FWScript::o1_op73, "wbw" },
+ /* 74 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_playSample, "bbwbww" },
+ /* 78 */
+ { &FWScript::o1_playSample, "bbwbww" },
+ { &FWScript::o1_disableSystemMenu, "b" },
+ { &FWScript::o1_loadMask5, "b" },
+ { &FWScript::o1_unloadMask5, "b" }
+};
+const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable);
+
+
+const Opcode OSScript::_opcodeTable[] = {
+ /* 00 */
+ { &FWScript::o1_modifyObjectParam, "bbw" },
+ { &FWScript::o1_getObjectParam, "bbb" },
+ { &FWScript::o1_addObjectParam, "bbw" },
+ { &FWScript::o1_subObjectParam, "bbw" },
+ /* 04 */
+ { &FWScript::o1_add2ObjectParam, "bbw" },
+ { &FWScript::o1_sub2ObjectParam, "bbw" },
+ { &FWScript::o1_compareObjectParam, "bbw" },
+ { &FWScript::o1_setupObject, "bwwww" },
+ /* 08 */
+ { &FWScript::o1_checkCollision, "bwwww" },
+ { &FWScript::o1_loadVar, "bc" },
+ { &FWScript::o1_addVar, "bc" },
+ { &FWScript::o1_subVar, "bc" },
+ /* 0C */
+ { &FWScript::o1_mulVar, "bc" },
+ { &FWScript::o1_divVar, "bc" },
+ { &FWScript::o1_compareVar, "bc" },
+ { &FWScript::o1_modifyObjectParam2, "bbb" },
+ /* 10 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_loadMask0, "b" },
+ /* 14 */
+ { &FWScript::o1_unloadMask0, "b" },
+ { &FWScript::o1_addToBgList, "b" },
+ { &FWScript::o1_loadMask1, "b" },
+ { &FWScript::o1_unloadMask1, "b" },
+ /* 18 */
+ { &FWScript::o1_loadMask4, "b" },
+ { &FWScript::o1_unloadMask4, "b" },
+ { &FWScript::o1_addSpriteFilledToBgList, "b" },
+ { &FWScript::o1_op1B, "" },
+ /* 1C */
+ { 0, 0 },
+ { &FWScript::o1_label, "l" },
+ { &FWScript::o1_goto, "b" },
+ { &FWScript::o1_gotoIfSup, "b" },
+ /* 20 */
+ { &FWScript::o1_gotoIfSupEqu, "b" },
+ { &FWScript::o1_gotoIfInf, "b" },
+ { &FWScript::o1_gotoIfInfEqu, "b" },
+ { &FWScript::o1_gotoIfEqu, "b" },
+ /* 24 */
+ { &FWScript::o1_gotoIfDiff, "b" },
+ { &FWScript::o1_removeLabel, "b" },
+ { &FWScript::o1_loop, "bb" },
+ { 0, 0 },
+ /* 28 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 2C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 30 */
+ { 0, 0 },
+ { &FWScript::o1_startGlobalScript, "b" },
+ { &FWScript::o1_endGlobalScript, "b" },
+ { 0, 0 },
+ /* 34 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 38 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_loadAnim, "s" },
+ /* 3C */
+ { &FWScript::o1_loadBg, "s" },
+ { &FWScript::o1_loadCt, "s" },
+ { 0, 0 },
+ { &FWScript::o2_loadPart, "s" },
+ /* 40 */
+ { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
+ { &FWScript::o1_loadNewPrcName, "bs" },
+ { &FWScript::o1_requestCheckPendingDataLoad, "" },
+ { 0, 0 },
+ /* 44 */
+ { 0, 0 },
+ { &FWScript::o1_blitAndFade, "" },
+ { &FWScript::o1_fadeToBlack, "" },
+ { &FWScript::o1_transformPaletteRange, "bbwww" },
+ /* 48 */
+ { 0, 0 },
+ { &FWScript::o1_setDefaultMenuColor2, "b" },
+ { &FWScript::o1_palRotate, "bbb" },
+ { 0, 0 },
+ /* 4C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_break, "" },
+ /* 50 */
+ { &FWScript::o1_endScript, "x" },
+ { &FWScript::o1_message, "bwwww" },
+ { &FWScript::o1_loadGlobalVar, "bc" },
+ { &FWScript::o1_compareGlobalVar, "bc" },
+ /* 54 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 58 */
+ { 0, 0 },
+ { &FWScript::o1_declareFunctionName, "s" },
+ { &FWScript::o1_freePartRange, "bb" },
+ { &FWScript::o1_unloadAllMasks, "" },
+ // 5C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 60 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_setScreenDimensions, "wwww" },
+ /* 64 */
+ { &FWScript::o1_displayBackground, "" },
+ { &FWScript::o1_initializeZoneData, "" },
+ { &FWScript::o1_setZoneDataEntry, "bw" },
+ { &FWScript::o1_getZoneDataEntry, "bb" },
+ /* 68 */
+ { &FWScript::o1_setDefaultMenuColor, "b" },
+ { &FWScript::o1_allowPlayerInput, "" },
+ { &FWScript::o1_disallowPlayerInput, "" },
+ { &FWScript::o1_changeDataDisk, "b" },
+ /* 6C */
+ { 0, 0 },
+ { &FWScript::o1_loadMusic, "s" },
+ { &FWScript::o1_playMusic, "" },
+ { &FWScript::o1_fadeOutMusic, "" },
+ /* 70 */
+ { &FWScript::o1_stopSample, "" },
+ { &FWScript::o1_op71, "bw" },
+ { &FWScript::o1_op72, "wbw" },
+ { &FWScript::o1_op72, "wbw" },
+ /* 74 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o2_playSample, "bbwbww" },
+ /* 78 */
+ { &FWScript::o2_playSampleAlt, "bbwbww" },
+ { &FWScript::o1_disableSystemMenu, "b" },
+ { &FWScript::o1_loadMask5, "b" },
+ { &FWScript::o1_unloadMask5, "b" },
+ /* 7C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o2_addSeqListElement, "bbbbwww" },
+ /* 80 */
+ { &FWScript::o2_removeSeq, "bb" },
+ { &FWScript::o2_op81, "" },
+ { &FWScript::o2_op82, "bbw" },
+ { &FWScript::o2_isSeqRunning, "bb" },
+ /* 84 */
+ { &FWScript::o2_gotoIfSupNearest, "b" },
+ { &FWScript::o2_gotoIfSupEquNearest, "b" },
+ { &FWScript::o2_gotoIfInfNearest, "b" },
+ { &FWScript::o2_gotoIfInfEquNearest, "b" },
+ /* 88 */
+ { &FWScript::o2_gotoIfEquNearest, "b" },
+ { &FWScript::o2_gotoIfDiffNearest, "b" },
+ { 0, 0 },
+ { &FWScript::o2_startObjectScript, "b" },
+ /* 8C */
+ { &FWScript::o2_stopObjectScript, "b" },
+ { &FWScript::o2_op8D, "wwwwwwww" },
+ { &FWScript::o2_addBackground, "bs" },
+ { &FWScript::o2_removeBackground, "b" },
+ /* 90 */
+ { &FWScript::o2_loadAbs, "bs" },
+ { &FWScript::o2_loadBg, "b" },
+ { 0, 0 },
+ { 0, 0 },
+ /* 94 */
+ { 0, 0 },
+ { &FWScript::o1_changeDataDisk, "b" },
+ { 0, 0 },
+ { 0, 0 },
+ /* 98 */
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o2_wasZoneChecked, "" },
+ { &FWScript::o2_op9B, "wwwwwwww" },
+ /* 9C */
+ { &FWScript::o2_op9C, "wwww" },
+ { &FWScript::o2_useBgScroll, "b" },
+ { &FWScript::o2_setAdditionalBgVScroll, "c" },
+ { &FWScript::o2_op9F, "ww" },
+ /* A0 */
+ { &FWScript::o2_addGfxElementA0, "ww" },
+ { &FWScript::o2_removeGfxElementA0, "ww" },
+ { &FWScript::o2_opA2, "ww" },
+ { &FWScript::o2_opA3, "ww" },
+ /* A4 */
+ { &FWScript::o2_loadMask22, "b" },
+ { &FWScript::o2_unloadMask22, "b" },
+ { 0, 0 },
+ { 0, 0 },
+ /* A8 */
+ { 0, 0 },
+ { &FWScript::o1_changeDataDisk, "b" }
};
+const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable);
-const Opcode *_opcodeTable;
-int _numOpcodes;
+FWScriptInfo *scriptInfo; ///< Script factory
+RawScriptArray scriptTable; ///< Table of script bytecode
+/*! \todo: replace with script subsystem
+ */
void setupOpcodes() {
- static const Opcode opcodeTableFW[] = {
- /* 00 */
- { o1_modifyObjectParam, "bbw" },
- { o1_getObjectParam, "bbb" },
- { o1_addObjectParam, "bbw" },
- { o1_subObjectParam, "bbw" },
- /* 04 */
- { o1_add2ObjectParam, "bbw" },
- { o1_sub2ObjectParam, "bbw" },
- { o1_compareObjectParam, "bbw" },
- { o1_setupObject, "bwwww" },
- /* 08 */
- { o1_checkCollision, "bwwww" },
- { o1_loadVar, "bc" },
- { o1_addVar, "bc" },
- { o1_subVar, "bc" },
- /* 0C */
- { o1_mulVar, "bc" },
- { o1_divVar, "bc" },
- { o1_compareVar, "bc" },
- { o1_modifyObjectParam2, "bbb" },
- /* 10 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_loadMask0, "b" },
- /* 14 */
- { o1_unloadMask0, "b" },
- { o1_addToBgList, "b" },
- { o1_loadMask1, "b" },
- { o1_unloadMask1, "b" },
- /* 18 */
- { o1_loadMask4, "b" },
- { o1_unloadMask4, "b" },
- { o1_addSpriteFilledToBgList, "b" },
- { o1_op1B, "" },
- /* 1C */
- { 0, 0 },
- { o1_label, "l" },
- { o1_goto, "b" },
- { o1_gotoIfSup, "b" },
- /* 20 */
- { o1_gotoIfSupEqu, "b" },
- { o1_gotoIfInf, "b" },
- { o1_gotoIfInfEqu, "b" },
- { o1_gotoIfEqu, "b" },
- /* 24 */
- { o1_gotoIfDiff, "b" },
- { o1_removeLabel, "b" },
- { o1_loop, "bb" },
- { 0, 0 },
- /* 28 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 2C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 30 */
- { 0, 0 },
- { o1_startGlobalScript, "b" },
- { o1_endGlobalScript, "b" },
- { 0, 0 },
- /* 34 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 38 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_loadAnim, "s" },
- /* 3C */
- { o1_loadBg, "s" },
- { o1_loadCt, "s" },
- { 0, 0 },
- { o1_loadPart, "s" },
- /* 40 */
- { o1_closePart, "" },
- { o1_loadNewPrcName, "bs" },
- { o1_requestCheckPendingDataLoad, "" },
- { 0, 0 },
- /* 44 */
- { 0, 0 },
- { o1_blitAndFade, "" },
- { o1_fadeToBlack, "" },
- { o1_transformPaletteRange, "bbwww" },
- /* 48 */
- { 0, 0 },
- { o1_setDefaultMenuColor2, "b" },
- { o1_palRotate, "bbb" },
- { 0, 0 },
- /* 4C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_break, "" },
- /* 50 */
- { o1_endScript, "x" },
- { o1_message, "bwwww" },
- { o1_loadGlobalVar, "bc" },
- { o1_compareGlobalVar, "bc" },
- /* 54 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 58 */
- { 0, 0 },
- { o1_declareFunctionName, "s" },
- { o1_freePartRange, "bb" },
- { o1_unloadAllMasks, "" },
- // 5C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 60 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_setScreenDimensions, "wwww" },
- /* 64 */
- { o1_displayBackground, "" },
- { o1_initializeZoneData, "" },
- { o1_setZoneDataEntry, "bw" },
- { o1_getZoneDataEntry, "bb" },
- /* 68 */
- { o1_setDefaultMenuColor, "b" },
- { o1_allowPlayerInput, "" },
- { o1_disallowPlayerInput, "" },
- { o1_changeDataDisk, "b" },
- /* 6C */
- { 0, 0 },
- { o1_loadMusic, "s" },
- { o1_playMusic, "" },
- { o1_fadeOutMusic, "" },
- /* 70 */
- { o1_stopSample, "" },
- { o1_op71, "bw" },
- { o1_op72, "wbw" },
- { o1_op73, "wbw" },
- /* 74 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_playSample, "bbwbww" },
- /* 78 */
- { o1_playSample, "bbwbww" },
- { o1_disableSystemMenu, "b" },
- { o1_loadMask5, "b" },
- { o1_unloadMask5, "b" }
- };
-
- // TODO: We need to verify the Operation Stealth opcodes.
-
- static const Opcode opcodeTableOS[] = {
- /* 00 */
- { o1_modifyObjectParam, "bbw" },
- { o1_getObjectParam, "bbb" },
- { o1_addObjectParam, "bbw" },
- { o1_subObjectParam, "bbw" },
- /* 04 */
- { o1_add2ObjectParam, "bbw" },
- { o1_sub2ObjectParam, "bbw" },
- { o1_compareObjectParam, "bbw" },
- { o1_setupObject, "bwwww" },
- /* 08 */
- { o1_checkCollision, "bwwww" },
- { o1_loadVar, "bc" },
- { o1_addVar, "bc" },
- { o1_subVar, "bc" },
- /* 0C */
- { o1_mulVar, "bc" },
- { o1_divVar, "bc" },
- { o1_compareVar, "bc" },
- { o1_modifyObjectParam2, "bbb" },
- /* 10 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_loadMask0, "b" },
- /* 14 */
- { o1_unloadMask0, "b" },
- { o1_addToBgList, "b" },
- { o1_loadMask1, "b" },
- { o1_unloadMask1, "b" },
- /* 18 */
- { o1_loadMask4, "b" },
- { o1_unloadMask4, "b" },
- { o1_addSpriteFilledToBgList, "b" },
- { o1_op1B, "" },
- /* 1C */
- { 0, 0 },
- { o1_label, "l" },
- { o1_goto, "b" },
- { o1_gotoIfSup, "b" },
- /* 20 */
- { o1_gotoIfSupEqu, "b" },
- { o1_gotoIfInf, "b" },
- { o1_gotoIfInfEqu, "b" },
- { o1_gotoIfEqu, "b" },
- /* 24 */
- { o1_gotoIfDiff, "b" },
- { o1_removeLabel, "b" },
- { o1_loop, "bb" },
- { 0, 0 },
- /* 28 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 2C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 30 */
- { 0, 0 },
- { o1_startGlobalScript, "b" },
- { o1_endGlobalScript, "b" },
- { 0, 0 },
- /* 34 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 38 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_loadAnim, "s" },
- /* 3C */
- { o1_loadBg, "s" },
- { o1_loadCt, "s" },
- { 0, 0 },
- { o2_loadPart, "s" },
- /* 40 */
- { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
- { o1_loadNewPrcName, "bs" },
- { o1_requestCheckPendingDataLoad, "" },
- { 0, 0 },
- /* 44 */
- { 0, 0 },
- { o1_blitAndFade, "" },
- { o1_fadeToBlack, "" },
- { o1_transformPaletteRange, "bbwww" },
- /* 48 */
- { 0, 0 },
- { o1_setDefaultMenuColor2, "b" },
- { o1_palRotate, "bbb" },
- { 0, 0 },
- /* 4C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_break, "" },
- /* 50 */
- { o1_endScript, "x" },
- { o1_message, "bwwww" },
- { o1_loadGlobalVar, "bc" },
- { o1_compareGlobalVar, "bc" },
- /* 54 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 58 */
- { 0, 0 },
- { o1_declareFunctionName, "s" },
- { o1_freePartRange, "bb" },
- { o1_unloadAllMasks, "" },
- // 5C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- /* 60 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o1_setScreenDimensions, "wwww" },
- /* 64 */
- { o1_displayBackground, "" },
- { o1_initializeZoneData, "" },
- { o1_setZoneDataEntry, "bw" },
- { o1_getZoneDataEntry, "bb" },
- /* 68 */
- { o1_setDefaultMenuColor, "b" },
- { o1_allowPlayerInput, "" },
- { o1_disallowPlayerInput, "" },
- { o1_changeDataDisk, "b" },
- /* 6C */
- { 0, 0 },
- { o1_loadMusic, "s" },
- { o1_playMusic, "" },
- { o1_fadeOutMusic, "" },
- /* 70 */
- { o1_stopSample, "" },
- { o1_op71, "bw" },
- { o1_op72, "wbw" },
- { o1_op72, "wbw" },
- /* 74 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o2_playSample, "bbwbww" },
- /* 78 */
- { o2_playSampleAlt, "bbwbww" },
- { o1_disableSystemMenu, "b" },
- { o1_loadMask5, "b" },
- { o1_unloadMask5, "b" },
- /* 7C */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { o2_addSeqListElement, "bbbbwww" },
- /* 80 */
- { o2_removeSeq, "bb" },
- { o2_op81, "" },
- { o2_op82, "bbw" },
- { o2_isSeqRunning, "bb" },
- /* 84 */
- { o2_gotoIfSupNearest, "b" },
- { o2_gotoIfSupEquNearest, "b" },
- { o2_gotoIfInfNearest, "b" },
- { o2_gotoIfInfEquNearest, "b" },
- /* 88 */
- { o2_gotoIfEquNearest, "b" },
- { o2_gotoIfDiffNearest, "b" },
- { 0, 0 },
- { o2_startObjectScript, "b" },
- /* 8C */
- { o2_stopObjectScript, "b" },
- { o2_op8D, "wwwwwwww" },
- { o2_addBackground, "bs" },
- { o2_removeBackground, "b" },
- /* 90 */
- { o2_loadAbs, "bs" },
- { o2_loadBg, "b" },
- { 0, 0 },
- { 0, 0 },
- /* 94 */
- { 0, 0 },
- { o1_changeDataDisk, "b" },
- { 0, 0 },
- { 0, 0 },
- /* 98 */
- { 0, 0 },
- { 0, 0 },
- { o2_wasZoneChecked, "" },
- { o2_op9B, "wwwwwwww" },
- /* 9C */
- { o2_op9C, "wwww" },
- { o2_useBgScroll, "b" },
- { o2_setAdditionalBgVScroll, "c" },
- { o2_op9F, "ww" },
- /* A0 */
- { o2_addGfxElementA0, "ww" },
- { o2_opA1, "ww" },
- { o2_opA2, "ww" },
- { o2_opA3, "ww" },
- /* A4 */
- { o2_loadMask22, "b" },
- { o2_unloadMask22, "b" },
- { 0, 0 },
- { 0, 0 },
- /* A8 */
- { 0, 0 },
- { o1_changeDataDisk, "b" }
- };
-
+ static FWScriptInfo fw;
+ static OSScriptInfo os;
if (g_cine->getGameType() == Cine::GType_FW) {
- _opcodeTable = opcodeTableFW;
- _numOpcodes = ARRAYSIZE(opcodeTableFW);
+ scriptInfo = &fw;
} else {
- _opcodeTable = opcodeTableOS;
- _numOpcodes = ARRAYSIZE(opcodeTableOS);
+ scriptInfo = &os;
}
}
-byte getNextByte() {
- byte val = *(_currentScriptPtr + _currentPosition);
- _currentPosition++;
- return val;
-}
-
-uint16 getNextWord() {
- uint16 val = READ_BE_UINT16(_currentScriptPtr + _currentPosition);
- _currentPosition += 2;
- return val;
-}
-
-const char *getNextString() {
- const char *val = (const char *)(_currentScriptPtr + _currentPosition);
- _currentPosition += strlen(val) + 1;
- return val;
-}
-
-// empty array
+/*! \brief Allocate empty array
+ * \param len Size of array
+ *
+ * Explicit to prevent var=0 instead of var[i]=0 typos.
+ */
ScriptVars::ScriptVars(unsigned int len) : _size(len), _vars(new int16[len]) {
assert(_vars);
reset();
}
-// read game save, for later use
+/*! \brief Allocate array and read contents from savefile
+ * \param fHandle Savefile open for reading
+ * \param len Size of array
+ */
ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len)
: _size(len), _vars(new int16[len]) {
@@ -468,16 +459,21 @@ ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len)
load(fHandle);
}
-// copy constructor
+/*! \brief Copy constructor
+ */
ScriptVars::ScriptVars(const ScriptVars &src) : _size(src._size), _vars(new int16[_size]) {
assert(_vars);
memcpy(_vars, src._vars, _size * sizeof(int16));
}
+/*! \brief Destructor
+ */
ScriptVars::~ScriptVars(void) {
delete[] _vars;
}
+/*! \brief Assignment operator
+ */
ScriptVars &ScriptVars::operator=(const ScriptVars &src) {
ScriptVars tmp(src);
int16 *tmpvars = _vars;
@@ -489,462 +485,708 @@ ScriptVars &ScriptVars::operator=(const ScriptVars &src) {
return *this;
}
-// array access
+/*! \brief Direct array item access
+ * \param idx Item index
+ * \return Reference to item
+ */
int16 &ScriptVars::operator[](unsigned int idx) {
- debugN(5, "assert(%d < %d)", idx, _size);
+ debug(6, "assert(%d < %d)", idx, _size);
assert(idx < _size);
return _vars[idx];
}
+/*! \brief Direct read-only array item access
+ * \param idx Item index
+ * \return Copy of item
+ */
int16 ScriptVars::operator[](unsigned int idx) const {
- debugN(5, "assert(%d < %d)\n", idx, _size);
+ debug(6, "assert(%d < %d)", idx, _size);
assert(idx < _size);
return _vars[idx];
}
-// dump to savefile
-void ScriptVars::save(Common::OutSaveFile &fHandle) {
+/*! \brief Savefile writer
+ * \param fHandle Savefile open for writing
+ */
+void ScriptVars::save(Common::OutSaveFile &fHandle) const {
save(fHandle, _size);
}
-// globalVars[255] is not written to savefiles...
-void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) {
- debugN(5, "assert(%d <= %d)\n", len, _size);
+/*! \brief Savefile writer with data length limit
+ * \param fHandle Savefile open for writing
+ * \param len Length of data to be written (len <= _size)
+ */
+void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) const {
+ debug(6, "assert(%d <= %d)", len, _size);
assert(len <= _size);
for (unsigned int i = 0; i < len; i++) {
fHandle.writeUint16BE(_vars[i]);
}
}
-// read from savefile
+/*! \brief Restore array from savefile
+ * \param fHandle Savefile open for reading
+ */
void ScriptVars::load(Common::InSaveFile &fHandle) {
load(fHandle, _size);
}
+/*! \brief Restore part of array from savefile
+ * \param fHandle Savefile open for reading
+ * \param len Length of data to be read
+ */
void ScriptVars::load(Common::InSaveFile &fHandle, unsigned int len) {
- debugN(5, "assert(%d <= %d)\n", len, _size);
+ debug(6, "assert(%d <= %d)", len, _size);
assert(len <= _size);
for (unsigned int i = 0; i < len; i++) {
_vars[i] = fHandle.readUint16BE();
}
}
+/*! \brief Reset all values to 0
+ */
void ScriptVars::reset(void) {
memset( _vars, 0, _size * sizeof(int16));
}
-void addGfxElementA0(int16 param1, int16 param2) {
- overlayHeadElement *currentHead = &overlayHead;
- overlayHeadElement *tempHead = currentHead;
- overlayHeadElement *newElement;
-
- currentHead = tempHead->next;
-
- while (currentHead) {
- if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
- if (currentHead->type == 2 || currentHead->objIdx == 3) {
- break;
- }
- }
-
- tempHead = currentHead;
- currentHead = currentHead->next;
- }
-
- if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2)
- return;
-
- newElement = new overlayHeadElement;
-
- newElement->next = tempHead->next;
- tempHead->next = newElement;
-
- newElement->objIdx = param1;
- newElement->type = 20;
-
- newElement->x = param2;
- newElement->y = 0;
- newElement->width = 0;
- newElement->color = 0;
-
- if (!currentHead)
- currentHead = &overlayHead;
+/*! \brief Constructor for partial loading
+ * \param s Size of bytecode which will be added later
+ *
+ * This constructor _MUST_ be followed by setdata() method call before the
+ * instance can be used. It leaves the instance in partially invalid state.
+ */
+RawScript::RawScript(uint16 s) : _size(s), _data(NULL),
+ _labels(SCRIPT_STACK_SIZE) { }
- newElement->previous = currentHead->previous;
+/*! \brief Complete constructor
+ * \param data Script bytecode
+ * \param s Bytecode length
+ */
+RawScript::RawScript(const FWScriptInfo &info, const byte *data, uint16 s) :
+ _size(s), _data(NULL), _labels(SCRIPT_STACK_SIZE) {
- currentHead->previous = newElement;
+ setData(info, data);
}
-void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
- SeqListElement *currentHead = &seqList;
- SeqListElement *tempHead = currentHead;
-
- while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
- tempHead = currentHead;
- currentHead = tempHead->next;
- }
+/*! \brief Copy constructor
+ */
+RawScript::RawScript(const RawScript &src) : _size(src._size),
+ _data(new byte[_size+1]), _labels(src._labels) {
- if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
- currentHead->var4 = -1;
- }
+ assert(_data);
+ memcpy(_data, src._data, _size+1);
}
-uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
- SeqListElement *currentHead = &seqList;
- SeqListElement *tempHead = currentHead;
-
- while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
- tempHead = currentHead;
- currentHead = tempHead->next;
- }
-
- if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
- return 1;
- }
-
- return 0;
+/*! \brief Destructor
+ */
+RawScript::~RawScript(void) {
+ delete[] _data;
}
-ScriptStruct scriptTable[NUM_MAX_SCRIPT];
-
-void stopGlobalScript(uint16 scriptIdx) {
- prcLinkedListStruct *currentHead = &globalScriptsHead;
- prcLinkedListStruct *tempHead = currentHead;
+/*! \brief Assignment operator
+ */
+RawScript &RawScript::operator=(const RawScript &src) {
+ assert(src._data);
+ byte *tmp = new byte[src._size+1];
- currentHead = tempHead->next;
+ assert(tmp);
+ _labels = src._labels;
+ _size = src._size;
- while (currentHead && (currentHead->scriptIdx != scriptIdx)) {
- tempHead = currentHead;
- currentHead = tempHead->next;
- }
+ delete[] _data;
+ _data = tmp;
+ memcpy(_data, src._data, _size);
+ _data[_size] = 0;
- if (!currentHead) {
- return;
- }
+ return *this;
+}
- if (currentHead->scriptIdx != scriptIdx) {
- return;
- }
+/*! \brief Get the next label in bytecode
+ * \param info Script info instance
+ * \param offset Starting offset
+ * \return Index of the next label in bytecode or _size on end of bytecode
+ *
+ * computeScriptStackSub replacement
+ */
+int RawScript::getNextLabel(const FWScriptInfo &info, int offset) const {
+ assert(_data);
+ int pos = offset;
- currentHead->scriptIdx = -1;
-}
+ assert(pos >= 0);
-uint16 computeScriptStackSub(bool computeAllLabels, byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, byte labelIndex, uint16 startOffset) {
- uint16 position;
+ while (pos < _size) {
+ uint8 opcode = _data[pos++];
+ const char *ptr = info.opcodeInfo(opcode);
- if (computeAllLabels) {
- for (int i = 0; i < SCRIPT_STACK_SIZE; i++) {
- stackPtr[i] = -1;
- }
- position = 0;
- } else {
- position = startOffset;
- }
- while (position < scriptSize) {
- uint8 opcode = scriptPtr[position];
- position++;
- if (opcode == 0 || opcode > _numOpcodes) {
- continue;
- }
- if (!_opcodeTable[opcode - 1].args) {
- warning("Undefined opcode 0x%02X in computeScriptStackSub", opcode - 1);
+ if (!ptr) {
continue;
}
- for (const char *p = _opcodeTable[opcode - 1].args; *p; ++p) {
- switch (*p) {
+
+ for (; *ptr; ++ptr) {
+ switch (*ptr) {
case 'b': // byte
- position++;
+ pos++;
break;
case 'w': // word
- position += 2;
+ pos += 2;
break;
case 'c': { // byte != 0 ? byte : word
- uint8 test = scriptPtr[position];
- position++;
+ uint8 test = _data[pos];
+ pos++;
if (test) {
- position++;
+ pos++;
} else {
- position += 2;
- }
- }
- break;
- case 'l': { // label
- uint8 index = scriptPtr[position];
- position++;
- if (computeAllLabels) {
- stackPtr[index] = position;
- } else {
- if (labelIndex == index) {
- return position;
- }
+ pos += 2;
}
}
break;
+ case 'l': // label
+ return pos;
case 's': // string
- while (scriptPtr[position++] != 0);
+ while (_data[pos++] != 0);
break;
case 'x': // exit script
- return position;
+ return -pos-1;
}
}
}
- return position;
+ return _size;
}
-void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) {
- computeScriptStackSub(true, scriptPtr, stackPtr, scriptSize, 0, 0);
-}
+/*! \brief Calculate initial script labels
+ * \param info Script info instance
+ *
+ * computeScriptStack replacement
+ */
+void RawScript::computeLabels(const FWScriptInfo &info) {
+ assert(_data);
+ int pos = 0;
+ int i;
+
+ // reset labels
+ for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
+ _labels[i] = -1;
+ }
-uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) {
- return computeScriptStackSub(false, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition);
+ // parse bytecode
+ while ((pos = getNextLabel(info, pos)) >= 0) {
+ i = _data[pos];
+ _labels[i] = ++pos;
+ }
}
-void palRotate(byte a, byte b, byte c) {
- if (c == 1) {
- uint16 currentColor = c_palette[b];
+/*! \brief find the next label from current position
+ * \param info Script info instance
+ * \param index Label index to look for
+ * \param offset Current position in script
+ * \return Position of next instruction following the label
+ *
+ * computeScriptStackFromScript replacement
+ */
+uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
+ const {
- for (int16 i = b; i > a; i--) {
- c_palette[i] = c_palette[i - 1];
- }
+ assert(_data);
+ int pos = offset;
- c_palette[a] = currentColor;
+ while ((pos = getNextLabel(info, pos)) >= 0) {
+ if (_data[pos++] == index) {
+ return pos;
+ }
}
+
+ return -pos - 1;
}
-void addScriptToList0(uint16 idx) {
- uint16 i;
- prcLinkedListStruct *pNewElement;
- prcLinkedListStruct *currentHead = &globalScriptsHead;
- prcLinkedListStruct *tempHead = currentHead;
+/*! \brief Copy bytecode and calculate labels
+ * \param data Bytecode to copy, must be _size long
+ */
+void RawScript::setData(const FWScriptInfo &info, const byte *data) {
+ assert(!_data); // this function should be called only once per instance
+ _data = new byte[_size+1];
- assert(idx <= NUM_MAX_SCRIPT);
+ assert(data && _data);
+ memcpy(_data, data, _size * sizeof(byte));
+ _data[_size] = 0;
- currentHead = tempHead->next;
+ computeLabels(info);
+}
- while (currentHead) {
- tempHead = currentHead;
+/*! \brief Initial script labels
+ * \return Precalculated script labels
+ */
+const ScriptVars &RawScript::labels(void) const {
+ assert(_data);
+ return _labels;
+}
- assert(tempHead);
+/*! \brief One byte of bytecode
+ * \param pos Index in bytecode
+ * \return Byte from bytecode
+ */
+byte RawScript::getByte(unsigned int pos) const {
+ assert(_data && pos < _size);
- currentHead = tempHead->next;
- }
+ return _data[pos];
+}
- pNewElement = new prcLinkedListStruct;
+/*! \brief One word of bytecode
+ * \param pos Index of the first byte in bytecode
+ * \return Word of bytecode
+ */
+uint16 RawScript::getWord(unsigned int pos) const {
+ assert(_data && pos+1 < _size);
- assert(pNewElement);
+ return READ_BE_UINT16(_data + pos);
+}
- pNewElement->next = tempHead->next;
- tempHead->next = pNewElement;
+/*! \brief String in bytecode
+ * \param pos Index of the first char in string
+ * \return Pointer to part of bytecode
+ */
+const char *RawScript::getString(unsigned int pos) const {
+ assert(_data && pos < _size);
- // copy the stack into the script instance
- for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
- pNewElement->stack[i] = scriptTable[idx].stack[i];
- }
+ return (const char*)(_data+pos);
+}
- pNewElement->compareResult = 0;
- pNewElement->scriptPosition = 0;
+/*! \brief Constructor for partial loading
+ * \param size Size of bytecode which will be added later
+ * \param p1 First object script parameter
+ * \param p2 Second object script parameter
+ * \param p3 Third object script parameter
+ *
+ * This constructor _MUST_ be followed by setdata() method call before the
+ * instance can be used. It leaves the instance in partially invalid state.
+ */
+RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
+ : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3)
+{ }
+
+/*! \brief Complete constructor
+ * \param data Script bytecode
+ * \param s Bytecode length
+ * \param p1 First object script parameter
+ * \param p2 Second object script parameter
+ * \param p3 Third object script parameter
+ */
+RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
+ uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s),
+ _runCount(0), _param1(p1), _param2(p2), _param3(p3) { }
- pNewElement->scriptPtr = scriptTable[idx].ptr;
- pNewElement->scriptIdx = idx;
-}
+/*! \brief Contructor for global scripts
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
+ _pos(0), _line(0), _compare(0), _index(idx),
+ _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
+ _globalVars(globalVars), _info(new FWScriptInfo) { }
-int16 endScript0(uint16 scriptIdx) {
- prcLinkedListStruct *currentHead = &globalScriptsHead;
- prcLinkedListStruct *tempHead = currentHead;
+/*! \brief Copy constructor
+ */
+FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
+ _line(src._line), _compare(src._compare), _index(src._index),
+ _labels(src._labels), _localVars(src._localVars),
+ _globalVars(src._globalVars), _info(new FWScriptInfo) { }
+
+/*! \brief Contructor for global scripts in derived classes
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
+ _script(script), _pos(0), _line(0), _compare(0), _index(idx),
+ _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
+ _globalVars(globalVars), _info(info) { }
+
+/*! \brief Constructor for object scripts in derived classes
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
+ _script(script), _pos(0), _line(0), _compare(0), _index(idx),
+ _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
+ _globalVars(globalVars), _info(info) {
- //assert(scriptIdx <= NUM_MAX_SCRIPT);
+ _localVars[0] = script.run();
+}
- currentHead = tempHead->next;
+/*! \brief Copy constructor for derived classes
+ */
+FWScript::FWScript(const FWScript &src, FWScriptInfo *info) :
+ _script(src._script), _pos(src._pos), _line(src._line),
+ _compare(src._compare), _index(src._index), _labels(src._labels),
+ _localVars(src._localVars), _globalVars(src._globalVars), _info(info) { }
- while (currentHead && currentHead->scriptIdx != scriptIdx) {
- tempHead = currentHead;
- currentHead = tempHead->next;
- }
+FWScript::~FWScript(void) {
+ delete _info;
+}
- if (!currentHead) {
- return -1;
- }
+/*! \brief Read next byte from bytecode
+ * \return Byte from bytecode
+ */
+byte FWScript::getNextByte() {
+ byte val = _script.getByte(_pos);
+ _pos++;
+ return val;
+}
- if (currentHead->scriptIdx != scriptIdx) {
- return -1;
- }
+/*! \brief Read next word from bytecode
+ * \return Word from bytecode
+ */
+uint16 FWScript::getNextWord() {
+ uint16 val = _script.getWord(_pos);
+ _pos += 2;
+ return val;
+}
- currentHead->scriptIdx = -1;
+/*! \brief Read next string from bytecode
+ * \return Pointer to string
+ */
+const char *FWScript::getNextString() {
+ const char *val = _script.getString(_pos);
+ _pos += strlen(val) + 1;
+ return val;
+}
- return 0;
+/*! \brief Restore script state from savefile
+ * \param labels Restored script labels
+ * \param local Restored local script variables
+ * \param compare Restored last comparison result
+ * \param pos Restored script position
+ */
+void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
+ assert(pos < _script._size);
+ _labels = labels;
+ _localVars = local;
+ _compare = compare;
+ _pos = _line = pos;
}
-int16 endScript1(uint16 scriptIdx) {
- prcLinkedListStruct *currentHead = &objScriptList;
- prcLinkedListStruct *tempHead = currentHead;
+/*! \brief Execute script
+ * \return <0 on script termination, >0 on script pause
+ *
+ * executeScript replacement.
+ * Instruction handler must return 0 if the script should continue or
+ * nonzero with the same meaning as return value of this function
+ */
+int FWScript::execute() {
+ int ret = 0;
- currentHead = tempHead->next;
+ while (!ret) {
+ _line = _pos;
+ byte opcode = getNextByte();
+ opFunc handler = _info->opcodeHandler(opcode);
- while (currentHead && currentHead->scriptIdx != scriptIdx) {
- tempHead = currentHead;
- currentHead = tempHead->next;
+ if (handler) {
+ ret = (this->*handler)();
+ }
}
- if (!currentHead) {
- return -1;
- }
+ return ret;
+}
- if (currentHead->scriptIdx != scriptIdx) {
- return -1;
+/*! \brief Save script to savefile
+ * \param fHandle Savefile handle
+ */
+void FWScript::save(Common::OutSaveFile &fHandle) const {
+ _labels.save(fHandle);
+ _localVars.save(fHandle);
+ fHandle.writeUint16BE(_compare);
+ fHandle.writeUint16BE(_pos);
+ // data order sucks...
+ fHandle.writeUint16BE(_index);
+}
+
+/*! \brief Contructor for global scripts
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+OSScript::OSScript(const RawScript &script, int16 idx) :
+ FWScript(script, idx, new OSScriptInfo) {}
+
+/*! \brief Constructor for object scripts
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+OSScript::OSScript(RawObjectScript &script, int16 idx) :
+ FWScript(script, idx, new OSScriptInfo) {}
+
+/*! \brief Copy constructor
+ */
+OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
+
+/*! \brief Restore script state from savefile
+ * \param labels Restored script labels
+ * \param local Restored local script variables
+ * \param compare Restored last comparison result
+ * \param pos Restored script position
+ */
+void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
+ FWScript::load(labels, local, compare, pos);
+}
+/*! \brief Get opcode info string
+ * \param opcode Opcode to look for in opcode table
+ */
+const char *FWScriptInfo::opcodeInfo(byte opcode) const {
+ if (opcode == 0 || opcode > FWScript::_numOpcodes) {
+ return NULL;
}
- currentHead->scriptIdx = -1;
+ if (!FWScript::_opcodeTable[opcode - 1].args) {
+ warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1);
+ return NULL;
+ }
- return 0;
+ return FWScript::_opcodeTable[opcode - 1].args;
}
-int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
- byte *ptr = page + (y * width) + x / 2;
- byte zoneVar;
+/*! \brief Get opcode handler pointer
+ * \param opcode Opcode to look for in opcode table
+ */
+opFunc FWScriptInfo::opcodeHandler(byte opcode) const {
+ if (opcode == 0 || opcode > FWScript::_numOpcodes) {
+ return NULL;
+ }
- if (!(x % 2)) {
- zoneVar = (*(ptr) >> 4) & 0xF;
- } else {
- zoneVar = (*(ptr)) & 0xF;
+ if (!FWScript::_opcodeTable[opcode - 1].proc) {
+ warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1);
+ return NULL;
}
- return zoneVar;
+ return FWScript::_opcodeTable[opcode - 1].proc;
}
-int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
- byte *ptr = page + (y * width) + x;
- byte zoneVar;
+/*! \brief Create new FWScript instance
+ * \param script Script bytecode
+ * \param index Bytecode index
+ */
+FWScript *FWScriptInfo::create(const RawScript &script, int16 index) const {
+ return new FWScript(script, index);
+}
- zoneVar = (*(ptr)) & 0xF;
+/*! \brief Create new FWScript instance
+ * \param script Object script bytecode
+ * \param index Bytecode index
+ */
+FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index) const {
+ return new FWScript(script, index);
+}
- return zoneVar;
+/*! \brief Load saved FWScript instance
+ * \param script Script bytecode
+ * \param index Bytecode index
+ * \param local Local variables
+ * \param labels Script labels
+ * \param compare Last compare result
+ * \param pos Position in script
+ */
+FWScript *FWScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
+ FWScript *tmp = new FWScript(script, index);
+ assert(tmp);
+ tmp->load(labels, local, compare, pos);
+ return tmp;
+}
+
+/*! \brief Load saved FWScript instance
+ * \param script Object script bytecode
+ * \param index Bytecode index
+ * \param local Local variables
+ * \param labels Script labels
+ * \param compare Last compare result
+ * \param pos Position in script
+ */
+FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
+ FWScript *tmp = new FWScript(script, index);
+ assert(tmp);
+ tmp->load(labels, local, compare, pos);
+ return tmp;
}
-int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
- int16 lx = objectTable[objIdx].x + x;
- int16 ly = objectTable[objIdx].y + y;
- int16 idx;
+/*! \brief Get opcode info string
+ * \param opcode Opcode to look for in opcode table
+ */
+const char *OSScriptInfo::opcodeInfo(byte opcode) const {
+ if (opcode == 0 || opcode > OSScript::_numOpcodes) {
+ return NULL;
+ }
- for (int16 i = 0; i < numZones; i++) {
- idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
+ if (!OSScript::_opcodeTable[opcode - 1].args) {
+ warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
+ return NULL;
+ }
- assert(idx >= 0 && idx <= NUM_MAX_ZONE);
+ return OSScript::_opcodeTable[opcode - 1].args;
+}
- if (zoneData[idx] == zoneIdx) {
- return 1;
- }
+/*! \brief Get opcode handler pointer
+ * \param opcode Opcode to look for in opcode table
+ */
+opFunc OSScriptInfo::opcodeHandler(byte opcode) const {
+ if (opcode == 0 || opcode > OSScript::_numOpcodes) {
+ return NULL;
}
- return 0;
+ if (!OSScript::_opcodeTable[opcode - 1].proc) {
+ warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
+ return NULL;
+ }
+
+ return OSScript::_opcodeTable[opcode - 1].proc;
}
-uint16 compareVars(int16 a, int16 b) {
- uint16 flag = 0;
+/*! \brief Create new OSScript instance
+ * \param script Script bytecode
+ * \param index Bytecode index
+ */
+FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
+ return new OSScript(script, index);
+}
- if (a == b) {
- flag |= kCmpEQ;
- } else if (a > b) {
- flag |= kCmpGT;
- } else if (a < b) {
- flag |= kCmpLT;
- }
+/*! \brief Create new OSScript instance
+ * \param script Object script bytecode
+ * \param index Bytecode index
+ */
+FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
+ return new OSScript(script, index);
+}
- return flag;
+/*! \brief Load saved OSScript instance
+ * \param script Script bytecode
+ * \param index Bytecode index
+ * \param local Local variables
+ * \param labels Script labels
+ * \param compare Last compare result
+ * \param pos Position in script
+ */
+FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
+ OSScript *tmp = new OSScript(script, index);
+ assert(tmp);
+ tmp->load(labels, local, compare, pos);
+ return tmp;
+}
+
+/*! \brief Load saved OSScript instance
+ * \param script Object script bytecode
+ * \param index Bytecode index
+ * \param local Local variables
+ * \param labels Script labels
+ * \param compare Last compare result
+ * \param pos Position in script
+ */
+FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
+ OSScript *tmp = new OSScript(script, index);
+ assert(tmp);
+ tmp->load(labels, local, compare, pos);
+ return tmp;
}
// ------------------------------------------------------------------------
// FUTURE WARS opcodes
// ------------------------------------------------------------------------
-void o1_modifyObjectParam() {
+int FWScript::o1_modifyObjectParam() {
byte objIdx = getNextByte();
byte paramIdx = getNextByte();
int16 newValue = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
+ debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
modifyObjectParam(objIdx, paramIdx, newValue);
+ return 0;
}
-void o1_getObjectParam() {
+int FWScript::o1_getObjectParam() {
byte objIdx = getNextByte();
byte paramIdx = getNextByte();
byte newValue = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _currentLine, objIdx, paramIdx, newValue);
+ debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue);
- _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx);
+ _localVars[newValue] = getObjectParam(objIdx, paramIdx);
+ return 0;
}
-void o1_addObjectParam() {
+int FWScript::o1_addObjectParam() {
byte objIdx = getNextByte();
byte paramIdx = getNextByte();
int16 newValue = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
+ debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
addObjectParam(objIdx, paramIdx, newValue);
+ return 0;
}
-void o1_subObjectParam() {
+int FWScript::o1_subObjectParam() {
byte objIdx = getNextByte();
byte paramIdx = getNextByte();
int16 newValue = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
+ debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
subObjectParam(objIdx, paramIdx, newValue);
+ return 0;
}
-void o1_add2ObjectParam() {
- getNextByte();
- getNextByte();
- getNextWord();
- warning("STUB: o1_add2ObjectParam()");
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_add2ObjectParam() {
+ uint16 a = getNextByte();
+ uint16 b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_add2ObjectParam(%x, %x, %x)", a, b, c);
+ return 0;
}
-void o1_sub2ObjectParam() {
- getNextByte();
- getNextByte();
- getNextWord();
- warning("STUB: o1_sub2ObjectParam()");
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_sub2ObjectParam() {
+ uint16 a = getNextByte();
+ uint16 b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_sub2ObjectParam(%x, %x, %x)", a, b, c);
+ return 0;
}
-void o1_compareObjectParam() {
+int FWScript::o1_compareObjectParam() {
byte objIdx = getNextByte();
byte param1 = getNextByte();
int16 param2 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _currentLine, objIdx, param1, param2);
+ debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2);
- _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2);
+ _compare = compareObjectParam(objIdx, param1, param2);
+ return 0;
}
-void o1_setupObject() {
+int FWScript::o1_setupObject() {
byte objIdx = getNextByte();
int16 param1 = getNextWord();
int16 param2 = getNextWord();
int16 param3 = getNextWord();
int16 param4 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
+ debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
setupObject(objIdx, param1, param2, param3, param4);
+ return 0;
}
-void o1_checkCollision() {
+int FWScript::o1_checkCollision() {
byte objIdx = getNextByte();
int16 param1 = getNextWord();
int16 param2 = getNextWord();
int16 param3 = getNextWord();
int16 param4 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
+ debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
- _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4);
+ _compare = checkCollision(objIdx, param1, param2, param3, param4);
+ return 0;
}
-void o1_loadVar() {
+int FWScript::o1_loadVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
@@ -954,34 +1196,34 @@ void o1_loadVar() {
switch (varType) {
case 1:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx];
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] = _localVars[dataIdx];
break;
case 2:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] = globalVars[dataIdx];
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] = _globalVars[dataIdx];
break;
case 3:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _currentLine, varIdx);
- getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, (uint16 *)&dummyU16);
- _currentScriptElement->localVars[varIdx] = var;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _line, varIdx);
+ getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, &dummyU16);
+ _localVars[varIdx] = var;
break;
case 4:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _currentLine, varIdx);
- getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&dummyU16, (uint16 *)&var);
- _currentScriptElement->localVars[varIdx] = var;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _line, varIdx);
+ getMouseData(mouseUpdateStatus, &dummyU16, &dummyU16, (uint16 *)&var);
+ _localVars[varIdx] = var;
break;
case 5:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _line, varIdx, dataIdx);
+ _localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
break;
case 8:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx);
+ _localVars[varIdx] = partBuffer[dataIdx].packedSize;
break;
case 9:
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx);
+ _localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
break;
default:
error("executeScript: o1_loadVar: Unknown variable type %d", varType);
@@ -989,352 +1231,413 @@ void o1_loadVar() {
} else {
int16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value);
- _currentScriptElement->localVars[varIdx] = value;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value);
+ _localVars[varIdx] = value;
}
+
+ return 0;
}
-void o1_addVar() {
+int FWScript::o1_addVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
if (varType) {
byte dataIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx];
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] += _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] += globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] += _globalVars[dataIdx];
+ }
} else {
int16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _currentLine, varIdx, value);
- _currentScriptElement->localVars[varIdx] += value;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value);
+ _localVars[varIdx] += value;
}
+
+ return 0;
}
-void o1_subVar() {
+int FWScript::o1_subVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
if (varType) {
byte dataIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx];
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] -= _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] -= globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] -= _globalVars[dataIdx];
+ }
+
} else {
int16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _currentLine, varIdx, value);
- _currentScriptElement->localVars[varIdx] -= value;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value);
+ _localVars[varIdx] -= value;
}
+
+ return 0;
}
-void o1_mulVar() {
+int FWScript::o1_mulVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
if (varType) {
byte dataIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx];
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] *= _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] *= globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] *= _globalVars[dataIdx];
+ }
} else {
int16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _currentLine, varIdx, value);
- _currentScriptElement->localVars[varIdx] *= value;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value);
+ _localVars[varIdx] *= value;
}
+
+ return 0;
}
-void o1_divVar() {
+int FWScript::o1_divVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
if (varType) {
byte dataIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx];
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] /= _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] /= globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] /= _globalVars[dataIdx];
+ }
} else {
int16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _currentLine, varIdx, value);
- _currentScriptElement->localVars[varIdx] /= value;
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value);
+ _localVars[varIdx] /= value;
}
+
+ return 0;
}
-void o1_compareVar() {
+int FWScript::o1_compareVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
if (varType) {
byte dataIdx = getNextByte();
- // printf("Val: %d\n", dataIdx);
-
if (varType == 1) {
- assert(varIdx < 50);
- assert(dataIdx < 50);
-
- debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], _currentScriptElement->localVars[dataIdx]);
+ debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx);
+ _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]);
} else if (varType == 2) {
- assert(varIdx < 50);
-
- debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _currentLine, varIdx, dataIdx);
- _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], globalVars[dataIdx]);
+ debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _line, varIdx, dataIdx);
+ _compare = compareVars(_localVars[varIdx], _globalVars[dataIdx]);
}
} else {
int16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _currentLine, varIdx, value);
- _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value);
+ debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value);
+ _compare = compareVars(_localVars[varIdx], value);
}
+
+ return 0;
}
-void o1_modifyObjectParam2() {
+int FWScript::o1_modifyObjectParam2() {
byte objIdx = getNextByte();
byte paramIdx = getNextByte();
byte newValue = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _currentLine, objIdx, paramIdx, newValue);
+ debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue);
- modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]);
+ modifyObjectParam(objIdx, paramIdx, _localVars[newValue]);
+ return 0;
}
-void o1_loadMask0() {
+int FWScript::o1_loadMask0() {
// OP_loadV7Element
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
loadOverlayElement(param, 0);
+ return 0;
}
-void o1_unloadMask0() {
+int FWScript::o1_unloadMask0() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
freeOverlay(param, 0);
+ return 0;
}
-void o1_addToBgList() {
+int FWScript::o1_addToBgList() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param);
addToBGList(param);
+ return 0;
}
-void o1_loadMask1() {
+int FWScript::o1_loadMask1() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
loadOverlayElement(param, 1);
+ return 0;
}
-void o1_unloadMask1() {
+int FWScript::o1_unloadMask1() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
freeOverlay(param, 1);
+ return 0;
}
-void o1_loadMask4() {
+int FWScript::o1_loadMask4() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
loadOverlayElement(param, 4);
+ return 0;
}
-void o1_unloadMask4() {
+int FWScript::o1_unloadMask4() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
freeOverlay(param, 4);
+ return 0;
}
-void o1_addSpriteFilledToBgList() {
+int FWScript::o1_addSpriteFilledToBgList() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param);
addSpriteFilledToBGList(param);
+ return 0;
}
-void o1_op1B() {
- debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _currentLine);
- freeBgIncrustList();
+int FWScript::o1_op1B() {
+ debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line);
+ bgIncrustList.clear();
+ return 0;
}
-void o1_label() {
+int FWScript::o1_label() {
byte labelIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx);
- _currentScriptElement->stack[labelIdx] = _currentPosition;
+ debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx);
+ _labels[labelIdx] = _pos;
+ return 0;
}
-void o1_goto() {
+int FWScript::o1_goto() {
byte labelIdx = getNextByte();
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ return 0;
}
-void o1_gotoIfSup() {
+int FWScript::o1_gotoIfSup() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult == kCmpGT) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare == kCmpGT) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o1_gotoIfSupEqu() {
+int FWScript::o1_gotoIfSupEqu() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare & (kCmpGT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o1_gotoIfInf() {
+int FWScript::o1_gotoIfInf() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult == kCmpLT) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare == kCmpLT) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o1_gotoIfInfEqu() {
+int FWScript::o1_gotoIfInfEqu() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare & (kCmpLT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o1_gotoIfEqu() {
+int FWScript::o1_gotoIfEqu() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult == kCmpEQ) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare == kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o1_gotoIfDiff() {
+int FWScript::o1_gotoIfDiff() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult != kCmpEQ) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare != kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o1_removeLabel() {
+int FWScript::o1_removeLabel() {
byte labelIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx);
- _currentScriptElement->stack[labelIdx] = -1;
+ debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx);
+ _labels[labelIdx] = -1;
+ return 0;
}
-void o1_loop() {
+int FWScript::o1_loop() {
byte varIdx = getNextByte();
byte labelIdx = getNextByte();
- _currentScriptElement->localVars[varIdx]--;
+ _localVars[varIdx]--;
- if (_currentScriptElement->localVars[varIdx] >= 0) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_localVars[varIdx] >= 0) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx);
- _currentPosition = _currentScriptElement->stack[labelIdx];
+ debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _line, varIdx, labelIdx);
+ _pos = _labels[labelIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _currentLine, varIdx, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx);
}
+ return 0;
}
-void o1_startGlobalScript() {
+int FWScript::o1_startGlobalScript() {
// OP_startScript
byte param = getNextByte();
assert(param < NUM_MAX_SCRIPT);
- debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param);
addScriptToList0(param);
+ return 0;
}
-void o1_endGlobalScript() {
+int FWScript::o1_endGlobalScript() {
byte scriptIdx = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx);
- stopGlobalScript(scriptIdx);
+ debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx);
+
+ ScriptList::iterator it = globalScripts.begin();
+
+ for (; it != globalScripts.end(); ++it) {
+ if ((*it)->_index == scriptIdx) {
+ (*it)->_index = -1;
+ }
+ }
+
+ return 0;
}
-void o1_loadAnim() {
+int FWScript::o1_loadAnim() {
// OP_loadResource
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param);
loadResource(param);
+ return 0;
}
-void o1_loadBg() {
+int FWScript::o1_loadBg() {
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
loadBg(param);
- freeBgIncrustList();
+ bgIncrustList.clear();
bgVar0 = 0;
+ return 0;
}
-void o1_loadCt() {
+int FWScript::o1_loadCt() {
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
loadCt(param);
+ return 0;
}
-void o1_loadPart() {
+int FWScript::o1_loadPart() {
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
loadPart(param);
+ return 0;
}
-void o1_closePart() {
- debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine);
+int FWScript::o1_closePart() {
+ debugC(5, kCineDebugScript, "Line: %d: closePart", _line);
closePart();
+ return 0;
}
-void o1_loadNewPrcName() {
+int FWScript::o1_loadNewPrcName() {
// OP_loadData
byte param1 = getNextByte();
const char *param2 = getNextString();
@@ -1343,104 +1646,113 @@ void o1_loadNewPrcName() {
switch (param1) {
case 0:
- debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2);
+ debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2);
strcpy(newPrcName, param2);
break;
case 1:
- debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2);
+ debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2);
strcpy(newRelName, param2);
break;
case 2:
- debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2);
+ debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2);
strcpy(newObjectName, param2);
break;
case 3:
- debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2);
+ debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2);
strcpy(newMsgName, param2);
break;
}
+ return 0;
}
-void o1_requestCheckPendingDataLoad() {
- debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine);
+int FWScript::o1_requestCheckPendingDataLoad() {
+ debugC(5, kCineDebugScript, "Line: %d: request data load", _line);
checkForPendingDataLoadSwitch = 1;
+ return 0;
}
-void o1_blitAndFade() {
- debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine);
+int FWScript::o1_blitAndFade() {
+ debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
// TODO: use real code
drawOverlays();
fadeRequired = true;
flip();
+
+// fadeFromBlack();
+ return 0;
}
-void o1_fadeToBlack() {
- debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine);
+int FWScript::o1_fadeToBlack() {
+ debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
fadeToBlack();
+ return 0;
}
-void o1_transformPaletteRange() {
+int FWScript::o1_transformPaletteRange() {
byte startColor = getNextByte();
byte numColor = getNextByte();
uint16 r = getNextWord();
uint16 g = getNextWord();
uint16 b = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _currentLine, startColor, numColor, r, g, b);
+ debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
transformPaletteRange(startColor, numColor, r, g, b);
+ return 0;
}
-void o1_setDefaultMenuColor2() {
+int FWScript::o1_setDefaultMenuColor2() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
defaultMenuBoxColor2 = param;
+ return 0;
}
-void o1_palRotate() {
+int FWScript::o1_palRotate() {
byte a = getNextByte();
byte b = getNextByte();
byte c = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c);
+ debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
palRotate(a, b, c);
+ return 0;
}
-void o1_break() {
- debugC(5, kCineDebugScript, "Line: %d: break", _currentLine);
+/*!\brief Pause script
+ * \todo Make sure it works
+ */
+int FWScript::o1_break() {
+ debugC(5, kCineDebugScript, "Line: %d: break", _line);
- _currentScriptElement->scriptPosition = _currentPosition;
- _closeScript = 1;
+ return 1;
}
-void o1_endScript() {
- debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine);
-
- if (_currentScriptParams == 0) {
- endScript0(_currentScriptElement->scriptIdx);
- } else {
- endScript1(_currentScriptElement->scriptIdx);
- }
+/*! \brief Terminate script
+ * \todo Make sure it works
+ */
+int FWScript::o1_endScript() {
+ debugC(5, kCineDebugScript, "Line: %d: endScript", _line);
- _closeScript = 1;
+ return -1;
}
-void o1_message() {
+int FWScript::o1_message() {
byte param1 = getNextByte();
uint16 param2 = getNextWord();
uint16 param3 = getNextWord();
uint16 param4 = getNextWord();
uint16 param5 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5);
+ debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5);
addMessage(param1, param2, param3, param4, param5);
+ return 0;
}
-void o1_loadGlobalVar() {
+int FWScript::o1_loadGlobalVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
@@ -1448,169 +1760,207 @@ void o1_loadGlobalVar() {
byte dataIdx = getNextByte();
if (varType == 1) {
- debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx);
- globalVars[varIdx] = _currentScriptElement->localVars[dataIdx];
+ debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _line, varIdx, dataIdx);
+ _globalVars[varIdx] = _localVars[dataIdx];
} else {
- debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
- globalVars[varIdx] = globalVars[dataIdx];
+ debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _line, varIdx, dataIdx);
+ _globalVars[varIdx] = _globalVars[dataIdx];
}
} else {
uint16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _currentLine, varIdx, value);
- globalVars[varIdx] = value;
+ debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value);
+ _globalVars[varIdx] = value;
}
+
+ return 0;
}
-void o1_compareGlobalVar() {
+int FWScript::o1_compareGlobalVar() {
byte varIdx = getNextByte();
byte varType = getNextByte();
if (varType) {
byte value = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value);
- _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]);
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _line, varIdx, value);
+ _compare = compareVars(_globalVars[varIdx], _localVars[value]);
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and globalVars[%d]", _line, varIdx, value);
+ _compare = compareVars(_globalVars[varIdx], _globalVars[value]);
+ }
} else {
uint16 value = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _currentLine, varIdx, value);
+ debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix
- _currentScriptElement->compareResult = 1;
+ _compare = 1;
} else {
- _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value);
+ _compare = compareVars(_globalVars[varIdx], value);
}
}
+
+ return 0;
}
-void o1_declareFunctionName() {
+int FWScript::o1_declareFunctionName() {
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param);
+ return 0;
}
-void o1_freePartRange() {
+int FWScript::o1_freePartRange() {
byte startIdx = getNextByte();
byte numIdx = getNextByte();
assert(startIdx + numIdx <= NUM_MAX_ANIMDATA);
- debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx);
+ debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx);
freeAnimDataRange(startIdx, numIdx);
+ return 0;
}
-void o1_unloadAllMasks() {
- debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine);
+int FWScript::o1_unloadAllMasks() {
+ debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
unloadAllMasks();
+ return 0;
}
-void o1_setScreenDimensions() {
- warning("STUB: o1_setScreenDimensions()");
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_setScreenDimensions() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ uint16 c = getNextWord();
+ uint16 d = getNextWord();
+ warning("STUB: o1_setScreenDimensions(%x, %x, %x, %x)", a, b, c, d);
// setupScreenParam
+ return 0;
}
-void o1_displayBackground() {
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_displayBackground() {
warning("STUB: o1_displayBackground()");
+ return 0;
}
-void o1_initializeZoneData() {
- debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine);
+int FWScript::o1_initializeZoneData() {
+ debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line);
for (int i = 0; i < NUM_MAX_ZONE; i++) {
zoneData[i] = i;
}
+ return 0;
}
-void o1_setZoneDataEntry() {
+int FWScript::o1_setZoneDataEntry() {
byte zoneIdx = getNextByte();
uint16 var = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var);
+ debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var);
zoneData[zoneIdx] = var;
+ return 0;
}
-void o1_getZoneDataEntry() {
+int FWScript::o1_getZoneDataEntry() {
byte zoneIdx = getNextByte();
byte var = getNextByte();
- _currentScriptElement->localVars[var] = zoneData[zoneIdx];
+ _localVars[var] = zoneData[zoneIdx];
+ return 0;
}
-void o1_setDefaultMenuColor() {
+int FWScript::o1_setDefaultMenuColor() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
defaultMenuBoxColor = param;
+ return 0;
}
-void o1_allowPlayerInput() {
- debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine);
+int FWScript::o1_allowPlayerInput() {
+ debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line);
allowPlayerInput = 1;
+ return 0;
}
-void o1_disallowPlayerInput() {
- debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine);
+int FWScript::o1_disallowPlayerInput() {
+ debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line);
allowPlayerInput = 0;
+ return 0;
}
-void o1_changeDataDisk() {
+int FWScript::o1_changeDataDisk() {
byte newDisk = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk);
+ debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk);
checkDataDisk(newDisk);
+ return 0;
}
-void o1_loadMusic() {
+int FWScript::o1_loadMusic() {
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param);
g_sound->loadMusic(param);
+ return 0;
}
-void o1_playMusic() {
- debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine);
+int FWScript::o1_playMusic() {
+ debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line);
g_sound->playMusic();
+ return 0;
}
-void o1_fadeOutMusic() {
- debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine);
+int FWScript::o1_fadeOutMusic() {
+ debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line);
g_sound->fadeOutMusic();
+ return 0;
}
-void o1_stopSample() {
- debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine);
+int FWScript::o1_stopSample() {
+ debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line);
g_sound->stopMusic();
+ return 0;
}
-void o1_op71() {
- warning("STUB: o1_op71()");
- getNextByte();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_op71() {
+ byte a = getNextByte();
+ uint16 b = getNextWord();
+ warning("STUB: o1_op71(%x, %x)", a, b);
+ return 0;
}
-void o1_op72() {
- warning("STUB: o1_op72()");
- getNextWord();
- getNextByte();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_op72() {
+ uint16 a = getNextWord();
+ byte b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
+ return 0;
}
-void o1_op73() {
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_op73() {
// I believe this opcode is identical to o1_op72(). In fact, Operation
// Stealth doesn't even have it. It uses o1_op72() instead.
- warning("STUB: o1_op73()");
- getNextWord();
- getNextByte();
- getNextWord();
+ uint16 a = getNextWord();
+ byte b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
+ return 0;
}
-void o1_playSample() {
- debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine);
+int FWScript::o1_playSample() {
+ debugC(5, kCineDebugScript, "Line: %d: playSample()", _line);
byte anim = getNextByte();
byte channel = getNextByte();
@@ -1621,13 +1971,15 @@ void o1_playSample() {
int16 volume = getNextWord();
uint16 size = getNextWord();
- if (!animDataTable[anim].ptr1) {
- return;
+ const byte *data = animDataTable[anim].data();
+
+ if (!data) {
+ return 0;
}
if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
if (size == 0xFFFF) {
- size = animDataTable[anim].width * animDataTable[anim].height;
+ size = animDataTable[anim]._width * animDataTable[anim]._height;
}
if (channel < 10) { // || _currentOpcode == 0x78
int channel1, channel2;
@@ -1638,14 +1990,14 @@ void o1_playSample() {
channel1 = 2;
channel2 = 3;
}
- g_sound->playSound(channel1, freq, animDataTable[anim].ptr1, size, -1, volume, 63, repeat);
- g_sound->playSound(channel2, freq, animDataTable[anim].ptr1, size, 1, volume, 0, repeat);
+ g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat);
+ g_sound->playSound(channel2, freq, data, size, 1, volume, 0, repeat);
} else {
channel -= 10;
if (volume > 63) {
volume = 63;
}
- g_sound->playSound(channel, freq, animDataTable[anim].ptr1, size, 0, 0, volume, repeat);
+ g_sound->playSound(channel, freq, data, size, 0, 0, volume, repeat);
}
} else {
if (volume > 63 || volume < 0) {
@@ -1658,49 +2010,54 @@ void o1_playSample() {
volume = 50;
}
if (g_cine->getGameType() == Cine::GType_OS && size == 0) {
- return;
+ return 0;
}
g_sound->stopMusic();
if (size == 0xFFFF) {
- g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0);
+ g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0);
} else {
g_sound->stopSound(channel);
}
}
+ return 0;
}
-void o1_disableSystemMenu() {
+int FWScript::o1_disableSystemMenu() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param);
disableSystemMenu = (param != 0);
+ return 0;
}
-void o1_loadMask5() {
+int FWScript::o1_loadMask5() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
loadOverlayElement(param, 5);
+ return 0;
}
-void o1_unloadMask5() {
+int FWScript::o1_unloadMask5() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
freeOverlay(param, 5);
+ return 0;
}
// ------------------------------------------------------------------------
// OPERATION STEALTH opcodes
// ------------------------------------------------------------------------
-void o2_loadPart() {
+int FWScript::o2_loadPart() {
const char *param = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
+ return 0;
}
-void o2_playSample() {
+int FWScript::o2_playSample() {
if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
// no-op in these versions
getNextByte();
@@ -1709,12 +2066,12 @@ void o2_playSample() {
getNextByte();
getNextWord();
getNextWord();
- return;
+ return 0;
}
- o1_playSample();
+ return o1_playSample();
}
-void o2_playSampleAlt() {
+int FWScript::o2_playSampleAlt() {
byte num = getNextByte();
byte channel = getNextByte();
uint16 frequency = getNextWord();
@@ -1723,21 +2080,22 @@ void o2_playSampleAlt() {
uint16 size = getNextWord();
if (size == 0xFFFF) {
- size = animDataTable[num].width * animDataTable[num].height;
+ size = animDataTable[num]._width * animDataTable[num]._height;
}
- if (animDataTable[num].ptr1) {
+ if (animDataTable[num].data()) {
if (g_cine->getPlatform() == Common::kPlatformPC) {
// if speaker output is available, play sound on it
// if it's another device, don't play anything
// TODO: implement this, it's used in the introduction for example
// on each letter displayed
} else {
- g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0);
+ g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0);
}
}
+ return 0;
}
-void o2_addSeqListElement() {
+int FWScript::o2_addSeqListElement() {
byte param1 = getNextByte();
byte param2 = getNextByte();
byte param3 = getNextByte();
@@ -1746,162 +2104,201 @@ void o2_addSeqListElement() {
uint16 param6 = getNextWord();
uint16 param7 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7);
+ debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
+ return 0;
}
-void o2_removeSeq() {
+int FWScript::o2_removeSeq() {
byte a = getNextByte();
byte b = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b);
+ debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
removeSeq(a, 0, b);
+ return 0;
}
-void o2_op81() {
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op81() {
warning("STUB: o2_op81()");
// freeUnkList();
+ return 0;
}
-void o2_op82() {
- warning("STUB: o2_op82()");
- getNextByte();
- getNextByte();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op82() {
+ byte a = getNextByte();
+ byte b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o2_op82(%x, %x, %x)", a, b, c);
+ return 0;
}
-void o2_isSeqRunning() {
+int FWScript::o2_isSeqRunning() {
byte a = getNextByte();
byte b = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b);
+ debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
if (isSeqRunning(a, 0, b)) {
- _currentScriptElement->compareResult = 1;
+ _compare = 1;
} else {
- _currentScriptElement->compareResult = 0;
+ _compare = 0;
}
+ return 0;
}
-void o2_gotoIfSupNearest() {
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfSupNearest() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult == kCmpGT) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare == kCmpGT) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx);
- _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
+ debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
+ _pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o2_gotoIfSupEquNearest() {
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfSupEquNearest() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare & (kCmpGT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx);
- _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
+ debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
+ _pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o2_gotoIfInfNearest() {
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfInfNearest() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult == kCmpLT) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare == kCmpLT) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx);
- _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
+ debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
+ _pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o2_gotoIfInfEquNearest() {
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfInfEquNearest() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare & (kCmpLT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx);
- _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
+ debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
+ _pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o2_gotoIfEquNearest() {
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfEquNearest() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult == kCmpEQ) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare == kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx);
- _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
+ debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
+ _pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o2_gotoIfDiffNearest() {
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfDiffNearest() {
byte labelIdx = getNextByte();
- if (_currentScriptElement->compareResult != kCmpEQ) {
- assert(_currentScriptElement->stack[labelIdx] != -1);
+ if (_compare != kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
- debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx);
- _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
+ debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
+ _pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
- debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _currentLine, labelIdx);
+ debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
}
+ return 0;
}
-void o2_startObjectScript() {
+int FWScript::o2_startObjectScript() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
runObjectScript(param);
+ return 0;
}
-void o2_stopObjectScript() {
+int FWScript::o2_stopObjectScript() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param);
- stopObjectScript(param);
+ debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
+ ScriptList::iterator it = objectScripts.begin();
+
+ for (; it != objectScripts.end(); ++it) {
+ if ((*it)->_index == param) {
+ (*it)->_index = -1;
+ }
+ }
+ return 0;
}
-void o2_op8D() {
- warning("STUB: o2_op8D()");
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op8D() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ uint16 c = getNextWord();
+ uint16 d = getNextWord();
+ uint16 e = getNextWord();
+ uint16 f = getNextWord();
+ uint16 g = getNextWord();
+ uint16 h = getNextWord();
+ warning("STUB: o2_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
// _currentScriptElement->compareResult = ...
+ return 0;
}
-void o2_addBackground() {
+int FWScript::o2_addBackground() {
byte param1 = getNextByte();
const char *param2 = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1);
+ debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
addBackground(param2, param1);
+ return 0;
}
-void o2_removeBackground() {
+int FWScript::o2_removeBackground() {
byte param = getNextByte();
assert(param);
- debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
if (additionalBgTable[param]) {
free(additionalBgTable[param]);
@@ -1917,192 +2314,358 @@ void o2_removeBackground() {
}
strcpy(currentBgName[param], "");
+ return 0;
}
-void o2_loadAbs() {
+int FWScript::o2_loadAbs() {
byte param1 = getNextByte();
const char *param2 = getNextString();
- debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2);
+ debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
loadAbs(param2, param1);
+ return 0;
}
-void o2_loadBg() {
+int FWScript::o2_loadBg() {
byte param = getNextByte();
assert(param <= 8);
- debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
if (additionalBgTable[param]) {
currentAdditionalBgIdx = param;
+ if (param == 8) {
+ newColorMode = 3;
+ } else {
+ newColorMode = bgColorMode + 1;
+ }
//if (_screenNeedFadeOut == 0) {
// adBgVar1 = 1;
//}
fadeRequired = true;
}
+ return 0;
}
-void o2_wasZoneChecked() {
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_wasZoneChecked() {
warning("STUB: o2_wasZoneChecked()");
+ return 0;
}
-void o2_op9B() {
- warning("STUB: o2_op9B()");
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op9B() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ uint16 c = getNextWord();
+ uint16 d = getNextWord();
+ uint16 e = getNextWord();
+ uint16 f = getNextWord();
+ uint16 g = getNextWord();
+ uint16 h = getNextWord();
+ warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
+ return 0;
}
-void o2_op9C() {
- warning("STUB: o2_op9C()");
- getNextWord();
- getNextWord();
- getNextWord();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op9C() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ uint16 c = getNextWord();
+ uint16 d = getNextWord();
+ warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d);
+ return 0;
}
-void o2_useBgScroll() {
+int FWScript::o2_useBgScroll() {
byte param = getNextByte();
assert(param <= 8);
- debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
if (additionalBgTable[param]) {
currentAdditionalBgIdx2 = param;
}
+ return 0;
}
-void o2_setAdditionalBgVScroll() {
+int FWScript::o2_setAdditionalBgVScroll() {
byte param1 = getNextByte();
if (param1) {
byte param2 = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2);
- additionalBgVScroll = _currentScriptElement->localVars[param2];
+ debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
+ additionalBgVScroll = _localVars[param2];
} else {
uint16 param2 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2);
+ debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
additionalBgVScroll = param2;
}
+ return 0;
}
-void o2_op9F() {
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op9F() {
warning("o2_op9F()");
getNextWord();
getNextWord();
+ return 0;
}
-void o2_addGfxElementA0() {
+int FWScript::o2_addGfxElementA0() {
uint16 param1 = getNextWord();
uint16 param2 = getNextWord();
- debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2);
+ debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
addGfxElementA0(param1, param2);
+ return 0;
}
-void o2_opA1() {
- warning("STUB: o2_opA1()");
- getNextWord();
- getNextWord();
- // removeGfxElementA0( ... );
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_removeGfxElementA0() {
+ uint16 idx = getNextWord();
+ uint16 param = getNextWord();
+ warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param);
+ removeGfxElementA0(idx, param);
+ return 0;
}
-void o2_opA2() {
- warning("STUB: o2_opA2()");
- getNextWord();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_opA2() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ warning("STUB: o2_opA2(%x, %x)", a, b);
// addGfxElementA2();
+ return 0;
}
-void o2_opA3() {
- warning("STUB: o2_opA3()");
- getNextWord();
- getNextWord();
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_opA3() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ warning("STUB: o2_opA3(%x, %x)", a, b);
// removeGfxElementA2();
+ return 0;
}
-void o2_loadMask22() {
+int FWScript::o2_loadMask22() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
loadOverlayElement(param, 22);
+ return 0;
}
-void o2_unloadMask22() {
+int FWScript::o2_unloadMask22() {
byte param = getNextByte();
- debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param);
+ debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
freeOverlay(param, 22);
+ return 0;
}
-// ------------------------------------------------------------------------
+//-----------------------------------------------------------------------
-void executeScript(prcLinkedListStruct *scriptElement, uint16 params) {
- assert(scriptElement);
+void addGfxElementA0(int16 param1, int16 param2) {
+ overlayHeadElement *currentHead = &overlayHead;
+ overlayHeadElement *tempHead = currentHead;
+ overlayHeadElement *newElement;
+
+ currentHead = tempHead->next;
+
+ while (currentHead) {
+ if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
+ if (currentHead->type == 2 || currentHead->objIdx == 3) {
+ break;
+ }
+ }
+
+ tempHead = currentHead;
+ currentHead = currentHead->next;
+ }
- if (scriptElement->scriptIdx == -1) {
+ if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2)
return;
+
+ newElement = new overlayHeadElement;
+
+ newElement->next = tempHead->next;
+ tempHead->next = newElement;
+
+ newElement->objIdx = param1;
+ newElement->type = 20;
+
+ newElement->x = param2;
+ newElement->y = 0;
+ newElement->width = 0;
+ newElement->color = 0;
+
+ if (!currentHead)
+ currentHead = &overlayHead;
+
+ newElement->previous = currentHead->previous;
+
+ currentHead->previous = newElement;
+}
+
+/*! \todo Check that it works
+ */
+void removeGfxElementA0(int16 idx, int16 param) {
+ overlayHeadElement *parent = &overlayHead;
+ overlayHeadElement *head = overlayHead.next;
+ overlayHeadElement *tmp;
+
+ while (head) {
+ if (head->objIdx == idx && head->x == param) {
+ parent->next = head->next;
+ tmp = head->next ? head->next : &overlayHead;
+ tmp->previous = parent;
+ delete head;
+ return;
+ }
+
+ parent = head;
+ head = head->next;
}
+}
- assert(scriptElement->scriptPtr);
+void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
+ SeqListElement *currentHead = &seqList;
+ SeqListElement *tempHead = currentHead;
- _currentScriptElement = scriptElement;
- _currentScriptParams = params;
- _currentScriptPtr = scriptElement->scriptPtr;
- _currentPosition = scriptElement->scriptPosition;
+ while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
+ tempHead = currentHead;
+ currentHead = tempHead->next;
+ }
- _closeScript = 0;
+ if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
+ currentHead->var4 = -1;
+ }
+}
- while (!_closeScript) {
- _currentLine = _currentPosition;
+uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
+ SeqListElement *currentHead = &seqList;
+ SeqListElement *tempHead = currentHead;
- byte opcode = getNextByte();
+ while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
+ tempHead = currentHead;
+ currentHead = tempHead->next;
+ }
+
+ if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void palRotate(byte a, byte b, byte c) {
+ if (c == 1) {
+ uint16 currentColor = c_palette[b];
- if (opcode && opcode < _numOpcodes) {
- if (_opcodeTable[opcode - 1].proc)
- (_opcodeTable[opcode - 1].proc) ();
- else
- warning("Undefined opcode 0x%02X in executeScript", opcode - 1);
+ for (int16 i = b; i > a; i--) {
+ c_palette[i] = c_palette[i - 1];
}
+
+ c_palette[a] = currentColor;
}
}
-void executeList1(void) {
- prcLinkedListStruct *currentHead = objScriptList.next;
+void addScriptToList0(uint16 idx) {
+ ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
+ assert(tmp);
+ globalScripts.push_back(tmp);
+}
- while (currentHead) {
- prcLinkedListStruct *tempHead;
+int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
+ byte *ptr = page + (y * width) + x / 2;
+ byte zoneVar;
+
+ if (!(x % 2)) {
+ zoneVar = (*(ptr) >> 4) & 0xF;
+ } else {
+ zoneVar = (*(ptr)) & 0xF;
+ }
+
+ return zoneVar;
+}
+
+int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
+ byte *ptr = page + (y * width) + x;
+ byte zoneVar;
+
+ zoneVar = (*(ptr)) & 0xF;
+
+ return zoneVar;
+}
+
+int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
+ int16 lx = objectTable[objIdx].x + x;
+ int16 ly = objectTable[objIdx].y + y;
+ int16 idx;
- tempHead = currentHead->next;
+ for (int16 i = 0; i < numZones; i++) {
+ idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
- executeScript(currentHead, 1);
+ assert(idx >= 0 && idx <= NUM_MAX_ZONE);
- currentHead = tempHead;
+ if (zoneData[idx] == zoneIdx) {
+ return 1;
+ }
}
+
+ return 0;
}
-void executeList0(void) {
- prcLinkedListStruct *currentHead = globalScriptsHead.next;
+uint16 compareVars(int16 a, int16 b) {
+ uint16 flag = 0;
- while (currentHead) {
- prcLinkedListStruct *tempHead;
+ if (a == b) {
+ flag |= kCmpEQ;
+ } else if (a > b) {
+ flag |= kCmpGT;
+ } else if (a < b) {
+ flag |= kCmpLT;
+ }
+
+ return flag;
+}
- executeScript(currentHead, 0);
+void executeList1(void) {
+ ScriptList::iterator it = objectScripts.begin();
+ for (; it != objectScripts.end();) {
+ if ((*it)->_index < 0 || (*it)->execute() < 0) {
+ it = objectScripts.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
- tempHead = currentHead->next;
- currentHead = tempHead;
+void executeList0(void) {
+ ScriptList::iterator it = globalScripts.begin();
+ for (; it != globalScripts.end();) {
+ if ((*it)->_index < 0 || (*it)->execute() < 0) {
+ it = globalScripts.erase(it);
+ } else {
+ ++it;
+ }
}
}
+/*! \todo objectScripts.clear()?
+ */
void purgeList1(void) {
}
@@ -2463,7 +3026,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
}
case 0x1B:
{
- sprintf(lineBuffer, "freeBgIncrustList()\n");
+ sprintf(lineBuffer, "bgIncrustList.clear()\n");
break;
}
case 0x1D:
@@ -2804,7 +3367,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
sprintf(lineBuffer, "disallowPlayerInput()\n");
break;
}
- case OP_changeDataDisk:
+ case 0x6B:
{
byte newDisk;
@@ -2878,7 +3441,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
if (opcode - 1 == 0x77) {
sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
- else if (opcode - 1 == 0x78) {
+ } else if (opcode - 1 == 0x78) {
sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
}
diff --git a/engines/cine/script.h b/engines/cine/script.h
index b6f3c79219..4bcf4b6ccb 100644
--- a/engines/cine/script.h
+++ b/engines/cine/script.h
@@ -27,17 +27,39 @@
#define CINE_SCRIPT_H
#include "common/savefile.h"
+#include "common/array.h"
+#include "common/list.h"
+#include "common/ptr.h"
namespace Cine {
#define SCRIPT_STACK_SIZE 50
+#define LOCAL_VARS_SIZE 50
+/*! \brief Fixed size array of script variables.
+ *
+ * Array size can be set in constructors, once the instance is created,
+ * it cannot be changed directly.
+ */
+
+class FWScript;
+
+typedef int (FWScript::*opFunc)();
+
+struct Opcode {
+ opFunc proc;
+ const char *args;
+};
+
+/*! \brief Fixed size array for script variables
+ */
class ScriptVars {
private:
- unsigned int _size;
- int16 *_vars;
+ unsigned int _size; ///< Size of array
+ int16 *_vars; ///< Variable values
public:
+ // Explicit to prevent var=0 instead of var[i]=0 typos.
explicit ScriptVars(unsigned int len = 50);
ScriptVars(Common::InSaveFile &fHandle, unsigned int len = 50);
ScriptVars(const ScriptVars &src);
@@ -47,26 +69,298 @@ public:
int16 &operator[](unsigned int idx);
int16 operator[](unsigned int idx) const;
- void save(Common::OutSaveFile &fHandle);
- void save(Common::OutSaveFile &fHandle, unsigned int len);
+ void save(Common::OutSaveFile &fHandle) const;
+ void save(Common::OutSaveFile &fHandle, unsigned int len) const;
void load(Common::InSaveFile &fHandle);
void load(Common::InSaveFile &fHandle, unsigned int len);
void reset(void);
};
-struct ScriptStruct {
- byte *ptr;
- uint16 size;
- int16 stack[SCRIPT_STACK_SIZE];
+class FWScriptInfo;
+
+/*! \brief Script bytecode and initial labels, ScriptStruct replacement.
+ *
+ * _data is one byte longer to make sure strings in bytecode are properly
+ * terminated
+ */
+class RawScript {
+private:
+ byte *_data; ///< Script bytecode
+ ScriptVars _labels; ///< Initial script labels
+
+protected:
+ void computeLabels(const FWScriptInfo &info);
+ int getNextLabel(const FWScriptInfo &info, int offset) const;
+
+public:
+ uint16 _size; ///< Bytecode length
+
+ explicit RawScript(uint16 size);
+ RawScript(const FWScriptInfo &info, const byte *data, uint16 size);
+ RawScript(const RawScript &src);
+ ~RawScript(void);
+
+ RawScript &operator=(const RawScript &src);
+
+ void setData(const FWScriptInfo &info, const byte *data);
+ /*! \brief Size of script
+ * \return Size of script
+ */
+ const ScriptVars &labels(void) const;
+ byte getByte(unsigned int pos) const;
+ uint16 getWord(unsigned int pos) const;
+ const char *getString(unsigned int pos) const;
+ uint16 getLabel(const FWScriptInfo &info, byte index, uint16 offset) const;
+};
+
+/*! \brief Object script class, RelObjectScript replacement
+ *
+ * Script parameters are not used, this class is required by different
+ * script initialization of object scripts
+ */
+class RawObjectScript : public RawScript {
+public:
+ int16 _runCount; ///< How many times the script was used
+ uint16 _param1; ///< Additional parameter not used at the moment
+ uint16 _param2; ///< Additional parameter not used at the moment
+ uint16 _param3; ///< Additional parameter not used at the moment
+
+ RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3);
+ RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3);
+
+ /// \brief Run the script one more time
+ /// \return Run count before incrementation
+ int16 run(void) { return _runCount++; }
};
+/*! \brief Future Wars script, prcLinkedListStruct replacement
+ * \todo Rewrite _globalVars initialization
+ */
+class FWScript {
+private:
+ const RawScript &_script; ///< Script bytecode reference
+ uint16 _pos; ///< Current position in script
+ uint16 _line; ///< Current opcode index in bytecode for debugging
+ uint16 _compare; ///< Last compare result
+ ScriptVars _labels; ///< Current script labels
+ ScriptVars _localVars; ///< Local script variables
+ ScriptVars &_globalVars; ///< Global variables reference
+ FWScriptInfo *_info; ///< Script info
+
+ static const Opcode _opcodeTable[];
+ static const unsigned int _numOpcodes;
+
+protected:
+ int o1_modifyObjectParam();
+ int o1_getObjectParam();
+ int o1_addObjectParam();
+ int o1_subObjectParam();
+ int o1_add2ObjectParam();
+ int o1_sub2ObjectParam();
+ int o1_compareObjectParam();
+ int o1_setupObject();
+ int o1_checkCollision();
+ int o1_loadVar();
+ int o1_addVar();
+ int o1_subVar();
+ int o1_mulVar();
+ int o1_divVar();
+ int o1_compareVar();
+ int o1_modifyObjectParam2();
+ int o1_loadMask0();
+ int o1_unloadMask0();
+ int o1_addToBgList();
+ int o1_loadMask1();
+ int o1_unloadMask1();
+ int o1_loadMask4();
+ int o1_unloadMask4();
+ int o1_addSpriteFilledToBgList();
+ int o1_op1B();
+ int o1_label();
+ int o1_goto();
+ int o1_gotoIfSup();
+ int o1_gotoIfSupEqu();
+ int o1_gotoIfInf();
+ int o1_gotoIfInfEqu();
+ int o1_gotoIfEqu();
+ int o1_gotoIfDiff();
+ int o1_removeLabel();
+ int o1_loop();
+ int o1_startGlobalScript();
+ int o1_endGlobalScript();
+ int o1_loadAnim();
+ int o1_loadBg();
+ int o1_loadCt();
+ int o1_loadPart();
+ int o1_closePart();
+ int o1_loadNewPrcName();
+ int o1_requestCheckPendingDataLoad();
+ int o1_blitAndFade();
+ int o1_fadeToBlack();
+ int o1_transformPaletteRange();
+ int o1_setDefaultMenuColor2();
+ int o1_palRotate();
+ int o1_break();
+ int o1_endScript();
+ int o1_message();
+ int o1_loadGlobalVar();
+ int o1_compareGlobalVar();
+ int o1_declareFunctionName();
+ int o1_freePartRange();
+ int o1_unloadAllMasks();
+ int o1_setScreenDimensions();
+ int o1_displayBackground();
+ int o1_initializeZoneData();
+ int o1_setZoneDataEntry();
+ int o1_getZoneDataEntry();
+ int o1_setDefaultMenuColor();
+ int o1_allowPlayerInput();
+ int o1_disallowPlayerInput();
+ int o1_changeDataDisk();
+ int o1_loadMusic();
+ int o1_playMusic();
+ int o1_fadeOutMusic();
+ int o1_stopSample();
+ int o1_op71();
+ int o1_op72();
+ int o1_op73();
+ int o1_playSample();
+ int o1_disableSystemMenu();
+ int o1_loadMask5();
+ int o1_unloadMask5();
+
+ // pointers to member functions in C++ suck...
+ int o2_loadPart();
+ int o2_addSeqListElement();
+ int o2_removeSeq();
+ int o2_playSample();
+ int o2_playSampleAlt();
+ int o2_op81();
+ int o2_op82();
+ int o2_isSeqRunning();
+ int o2_gotoIfSupNearest();
+ int o2_gotoIfSupEquNearest();
+ int o2_gotoIfInfNearest();
+ int o2_gotoIfInfEquNearest();
+ int o2_gotoIfEquNearest();
+ int o2_gotoIfDiffNearest();
+ int o2_startObjectScript();
+ int o2_stopObjectScript();
+ int o2_op8D();
+ int o2_addBackground();
+ int o2_removeBackground();
+ int o2_loadAbs();
+ int o2_loadBg();
+ int o2_wasZoneChecked();
+ int o2_op9B();
+ int o2_op9C();
+ int o2_useBgScroll();
+ int o2_setAdditionalBgVScroll();
+ int o2_op9F();
+ int o2_addGfxElementA0();
+ int o2_removeGfxElementA0();
+ int o2_opA2();
+ int o2_opA3();
+ int o2_loadMask22();
+ int o2_unloadMask22();
+
+ byte getNextByte();
+ uint16 getNextWord();
+ const char *getNextString();
+
+ void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
+
+ FWScript(const RawScript &script, int16 index, FWScriptInfo *info);
+ FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info);
+ FWScript(const FWScript &src, FWScriptInfo *info);
+
+public:
+ int16 _index; ///< Index in script table
+
+ FWScript(const RawScript &script, int16 index);
+// FWScript(const RawObjectScript &script, int16 index);
+ FWScript(const FWScript &src);
+ ~FWScript(void);
+
+ int execute();
+ void save(Common::OutSaveFile &fHandle) const;
+
+ friend class FWScriptInfo;
+
+ // workaround for bug in g++ which prevents protected member functions
+ // of FWScript from being used in OSScript::_opcodeTable[]
+ // initialization ("error: protected within this context")
+ friend class OSScript;
+};
+
+/*! \brief Operation Stealth script, prcLinkedListStruct replacement
+ */
+class OSScript : public FWScript {
+private:
+ static const Opcode _opcodeTable[];
+ static const unsigned int _numOpcodes;
+
+protected:
+ void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
+
+public:
+ OSScript(const RawScript &script, int16 index);
+ OSScript(RawObjectScript &script, int16 index);
+ OSScript(const OSScript &src);
+
+ friend class OSScriptInfo;
+};
+
+/*! \brief Future Wars script factory and info
+ */
+class FWScriptInfo {
+protected:
+ virtual opFunc opcodeHandler(byte opcode) const;
+
+public:
+ virtual ~FWScriptInfo() {}
+
+ virtual const char *opcodeInfo(byte opcode) const;
+ virtual FWScript *create(const RawScript &script, int16 index) const;
+ virtual FWScript *create(const RawObjectScript &script, int16 index) const;
+ virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
+ virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
+
+ friend class FWScript;
+};
+
+/*! \brief Operation Stealth script factory and info
+ */
+class OSScriptInfo : public FWScriptInfo {
+protected:
+ virtual opFunc opcodeHandler(byte opcode) const;
+
+public:
+ virtual ~OSScriptInfo() {}
+
+ virtual const char *opcodeInfo(byte opcode) const;
+ virtual FWScript *create(const RawScript &script, int16 index) const;
+ virtual FWScript *create(const RawObjectScript &script, int16 index) const;
+ virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
+ virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
+
+ friend class FWScript;
+};
+
+typedef Common::SharedPtr<FWScript> ScriptPtr;
+typedef Common::SharedPtr<RawScript> RawScriptPtr;
+typedef Common::SharedPtr<RawObjectScript> RawObjectScriptPtr;
+typedef Common::List<ScriptPtr> ScriptList;
+typedef Common::Array<RawScriptPtr> RawScriptArray;
+typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;
+
#define NUM_MAX_SCRIPT 50
-extern ScriptStruct scriptTable[NUM_MAX_SCRIPT];
+extern RawScriptArray scriptTable;
+extern FWScriptInfo *scriptInfo;
void setupOpcodes();
-void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize);
void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx);
void dumpScript(char *dumpName);
@@ -79,7 +373,6 @@ void addScriptToList0(uint16 idx);
int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx);
void runObjectScript(int16 entryIdx);
-int16 stopObjectScript(int16 entryIdx);
void executeList1(void);
void executeList0(void);
@@ -87,119 +380,6 @@ void executeList0(void);
void purgeList1(void);
void purgeList0(void);
-void o1_modifyObjectParam();
-void o1_getObjectParam();
-void o1_addObjectParam();
-void o1_subObjectParam();
-void o1_add2ObjectParam();
-void o1_sub2ObjectParam();
-void o1_compareObjectParam();
-void o1_setupObject();
-void o1_checkCollision();
-void o1_loadVar();
-void o1_addVar();
-void o1_subVar();
-void o1_mulVar();
-void o1_divVar();
-void o1_compareVar();
-void o1_modifyObjectParam2();
-void o1_loadMask0();
-void o1_unloadMask0();
-void o1_addToBgList();
-void o1_loadMask1();
-void o1_unloadMask1();
-void o1_loadMask4();
-void o1_unloadMask4();
-void o1_addSpriteFilledToBgList();
-void o1_op1B();
-void o1_label();
-void o1_goto();
-void o1_gotoIfSup();
-void o1_gotoIfSupEqu();
-void o1_gotoIfInf();
-void o1_gotoIfInfEqu();
-void o1_gotoIfEqu();
-void o1_gotoIfDiff();
-void o1_removeLabel();
-void o1_loop();
-void o1_startGlobalScript();
-void o1_endGlobalScript();
-void o1_loadAnim();
-void o1_loadBg();
-void o1_loadCt();
-void o1_loadPart();
-void o1_closePart();
-void o1_loadNewPrcName();
-void o1_requestCheckPendingDataLoad();
-void o1_blitAndFade();
-void o1_fadeToBlack();
-void o1_transformPaletteRange();
-void o1_setDefaultMenuColor2();
-void o1_palRotate();
-void o1_break();
-void o1_endScript();
-void o1_message();
-void o1_loadGlobalVar();
-void o1_compareGlobalVar();
-void o1_declareFunctionName();
-void o1_freePartRange();
-void o1_unloadAllMasks();
-void o1_setScreenDimensions();
-void o1_displayBackground();
-void o1_initializeZoneData();
-void o1_setZoneDataEntry();
-void o1_getZoneDataEntry();
-void o1_setDefaultMenuColor();
-void o1_allowPlayerInput();
-void o1_disallowPlayerInput();
-void o1_changeDataDisk();
-void o1_loadMusic();
-void o1_playMusic();
-void o1_fadeOutMusic();
-void o1_stopSample();
-void o1_op71();
-void o1_op72();
-void o1_op73();
-void o1_playSample();
-void o1_playSample();
-void o1_disableSystemMenu();
-void o1_loadMask5();
-void o1_unloadMask5();
-
-void o2_loadPart();
-void o2_addSeqListElement();
-void o2_removeSeq();
-void o2_playSample();
-void o2_playSampleAlt();
-void o2_op81();
-void o2_op82();
-void o2_isSeqRunning();
-void o2_gotoIfSupNearest();
-void o2_gotoIfSupEquNearest();
-void o2_gotoIfInfNearest();
-void o2_gotoIfInfEquNearest();
-void o2_gotoIfEquNearest();
-void o2_gotoIfDiffNearest();
-void o2_startObjectScript();
-void o2_stopObjectScript();
-void o2_op8D();
-void o2_addBackground();
-void o2_removeBackground();
-void o2_loadAbs();
-void o2_loadBg();
-void o2_wasZoneChecked();
-void o2_op9B();
-void o2_op9C();
-void o2_useBgScroll();
-void o2_setAdditionalBgVScroll();
-void o2_op9F();
-void o2_addGfxElementA0();
-void o2_opA1();
-void o2_opA2();
-void o2_opA3();
-void o2_loadMask22();
-void o2_unloadMask22();
-
} // End of namespace Cine
#endif
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 7f303a1b79..e808de6922 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -602,9 +602,9 @@ bool PCSoundFxPlayer::load(const char *song) {
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
_instrumentsData[i] = NULL;
- char instrument[13];
+ char instrument[64];
memcpy(instrument, _sfxData + 20 + i * 30, 12);
- instrument[12] = '\0';
+ instrument[63] = '\0';
if (strlen(instrument) != 0) {
char *dot = strrchr(instrument, '.');
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index 066eab48e3..e41626cad1 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -40,7 +40,7 @@ const CommandeType *confirmMenu;
const char **otherMessages;
const char *commandPrepositionOn;
-void generateMask(byte *sprite, byte *mask, uint16 size, byte transparency);
+void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
void loadTextData(const char *pFileName, byte *pDestinationBuffer) {
Common::File pFileHandle;
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 50846f7321..38c5677569 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -124,64 +124,10 @@ void stopMusicAfterFadeOut(void) {
// }
}
-int16 stopObjectScript(int16 entryIdx) {
- prcLinkedListStruct *currentHead = &objScriptList;
- prcLinkedListStruct *tempHead = currentHead;
-
- currentHead = tempHead->next;
-
- while (currentHead) {
- if (currentHead->scriptIdx == entryIdx) {
- currentHead->scriptIdx = -1;
- return 0;
- }
-
- currentHead = currentHead->next;
- }
-
- return -1;
-}
-
void runObjectScript(int16 entryIdx) {
- uint16 i;
- prcLinkedListStruct *pNewElement;
- prcLinkedListStruct *currentHead = &objScriptList;
- prcLinkedListStruct *tempHead = currentHead;
-
- currentHead = tempHead->next;
-
- while (currentHead) {
- tempHead = currentHead;
-
- assert(tempHead);
-
- currentHead = tempHead->next;
- }
-
- pNewElement = new prcLinkedListStruct;
-
- assert(pNewElement);
-
- pNewElement->next = tempHead->next;
- tempHead->next = pNewElement;
-
- // copy the stack into the script instance
- for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
- pNewElement->stack[i] = 0;
- }
-
- pNewElement->compareResult = 0;
- pNewElement->scriptPosition = 0;
-
- pNewElement->scriptPtr = (byte *)relTable[entryIdx].data;
- pNewElement->scriptIdx = entryIdx;
-
- if (g_cine->getGameType() == Cine::GType_OS) {
- pNewElement->localVars[0] = relTable[entryIdx].runCount;
- ++relTable[entryIdx].runCount;
- }
-
- computeScriptStack(pNewElement->scriptPtr, pNewElement->stack, relTable[entryIdx].size);
+ ScriptPtr tmp(scriptInfo->create(*relTable[entryIdx], entryIdx));
+ assert(tmp);
+ objectScripts.push_back(tmp);
}
void addPlayerCommandMessage(int16 cmd) {
@@ -214,30 +160,31 @@ void addPlayerCommandMessage(int16 cmd) {
int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
int16 i;
- int16 di = -1;
+ int16 found = -1;
- for (i = 0; i < NUM_MAX_REL; i++) {
- if (relTable[i].data && relTable[i].obj1Param1 == param1 && relTable[i].obj1Param2 == pSelectedObject->idx) {
+ for (i = 0; i < (int16)relTable.size(); i++) {
+ if (relTable[i]->_param1 == param1 && relTable[i]->_param2 == pSelectedObject->idx) {
if (param2 == 1) {
- di = i;
+ found = i;
} else if (param2 == 2) {
- if (relTable[i].obj2Param == pSelectedObject->param) {
- di = i;
+ if (relTable[i]->_param3 == pSelectedObject->param) {
+ found = i;
}
}
}
- if (di != -1)
+ if (found != -1)
break;
}
- return di;
+ return found;
}
int16 getObjectUnderCursor(uint16 x, uint16 y) {
overlayHeadElement *currentHead = overlayHead.previous;
int16 objX, objY, frame, part, threshold, height, xdif, ydif;
+ int width;
while (currentHead) {
if (currentHead->type < 2) {
@@ -250,27 +197,29 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) {
part = objectTable[currentHead->objIdx].part;
if (currentHead->type == 0) {
- threshold = animDataTable[frame].var1;
+ threshold = animDataTable[frame]._var1;
} else {
- threshold = animDataTable[frame].width / 2;
+ threshold = animDataTable[frame]._width / 2;
}
- height = animDataTable[frame].height;
+ height = animDataTable[frame]._height;
+ width = animDataTable[frame]._realWidth;
xdif = x - objX;
ydif = y - objY;
if ((xdif >= 0) && ((threshold << 4) > xdif) && (ydif > 0) && (ydif < height)) {
- if (animDataTable[frame].ptr1) {
- if (g_cine->getGameType() == Cine::GType_OS)
- return currentHead->objIdx;
-
- if (currentHead->type == 0) { // use generated mask
- if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr2, animDataTable[frame].width)) {
+ if (animDataTable[frame].data()) {
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ if(xdif < width && (currentHead->type == 1 || animDataTable[frame].getColor(xdif, ydif) != objectTable[currentHead->objIdx].part)) {
+ return currentHead->objIdx;
+ }
+ } else if (currentHead->type == 0) { // use generated mask
+ if (gfxGetBit(x - objX, y - objY, animDataTable[frame].mask(), animDataTable[frame]._width)) {
return currentHead->objIdx;
}
} else if (currentHead->type == 1) { // is mask
- if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr1, animDataTable[frame].width * 4)) {
+ if (gfxGetBit(x - objX, y - objY, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
return currentHead->objIdx;
}
}
@@ -302,38 +251,38 @@ bool CineEngine::loadSaveDirectory(void) {
return true;
}
+/*! \brief Restore script list item from savefile
+ * \param fHandle Savefile handlem open for reading
+ * \param isGlobal Restore object or global script?
+ */
void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) {
- int16 i;
+ ScriptVars localVars, labels;
+ uint16 compare, pos;
+ int16 idx;
- prcLinkedListStruct *newElement;
- prcLinkedListStruct *currentHead = &globalScriptsHead;
- prcLinkedListStruct *tempHead = currentHead;
+ labels.load(*fHandle);
+ localVars.load(*fHandle);
- currentHead = tempHead->next;
+ compare = fHandle->readUint16BE();
+ pos = fHandle->readUint16BE();
+ idx = fHandle->readUint16BE();
- while (currentHead) {
- tempHead = currentHead;
- currentHead = tempHead->next;
+ // no way to reinitialize these
+ if (idx < 0) {
+ return;
}
- newElement = new prcLinkedListStruct;
-
- newElement->next = tempHead->next;
- tempHead->next = newElement;
-
- for (i = 0; i < SCRIPT_STACK_SIZE; i++)
- newElement->stack[i] = fHandle->readUint16BE();
-
- newElement->localVars.load(*fHandle);
-
- newElement->compareResult = fHandle->readUint16BE();
- newElement->scriptPosition = fHandle->readUint16BE();
- newElement->scriptIdx = fHandle->readUint16BE();
-
- if (isGlobal)
- newElement->scriptPtr = scriptTable[newElement->scriptIdx].ptr;
- else
- newElement->scriptPtr = (byte *)relTable[newElement->scriptIdx].data;
+ // original code loaded everything into globalScripts, this should be
+ // the correct behavior
+ if (isGlobal) {
+ ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx, labels, localVars, compare, pos));
+ assert(tmp);
+ globalScripts.push_back(tmp);
+ } else {
+ ScriptPtr tmp(scriptInfo->create(*relTable[idx], idx, labels, localVars, compare, pos));
+ assert(tmp);
+ objectScripts.push_back(tmp);
+ }
}
void loadOverlayFromSave(Common::InSaveFile *fHandle) {
@@ -370,26 +319,106 @@ void loadOverlayFromSave(Common::InSaveFile *fHandle) {
currentHead->previous = newElement;
}
-void setupScriptList(bool isGlobal) {
- prcLinkedListStruct *currentHead;
-
- if (isGlobal)
- currentHead = globalScriptsHead.next;
- else
- currentHead = objScriptList.next;
-
- while (currentHead) {
- if (isGlobal)
- currentHead->scriptPtr = scriptTable[currentHead->scriptIdx].ptr;
- else
- currentHead->scriptPtr = (byte *)relTable[currentHead->scriptIdx].data;
- currentHead = currentHead->next;
- }
+/*! \brief Savefile format tester
+ * \param fHandle Savefile to check
+ *
+ * This function seeks through savefile and tries to guess if it's the original
+ * savegame format or broken format from ScummVM 0.10/0.11
+ * The test is incomplete but this should cover 99.99% of cases.
+ * If anyone makes a savefile which could confuse this test, assert will
+ * report it
+ */
+bool brokenSave(Common::InSaveFile &fHandle) {
+ // Backward seeking not supported in compressed savefiles
+ // if you really want it, finish it yourself
+ return false;
+
+ // fixed size part: 14093 bytes (12308 bytes in broken save)
+ // animDataTable begins at byte 6431
+
+ int filesize = fHandle.size();
+ int startpos = fHandle.pos();
+ int pos, tmp;
+ bool correct = false, broken = false;
+
+ // check for correct format
+ while (filesize > 14093) {
+ pos = 14093;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 206;
+ if (pos >= filesize) break;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 206;
+ if (pos >= filesize) break;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 20;
+ if (pos >= filesize) break;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 20;
+
+ if (pos == filesize) correct = true;
+ break;
+ }
+ debug(5, "brokenSave: correct format check %s: size=%d, pos=%d",
+ correct ? "passed" : "failed", filesize, pos);
+
+ // check for broken format
+ while (filesize > 12308) {
+ pos = 12308;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 206;
+ if (pos >= filesize) break;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 206;
+ if (pos >= filesize) break;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 20;
+ if (pos >= filesize) break;
+
+ fHandle.seek(pos);
+ tmp = fHandle.readUint16BE();
+ pos += 2 + tmp * 20;
+
+ if (pos == filesize) broken = true;
+ break;
+ }
+ debug(5, "brokenSave: broken format check %s: size=%d, pos=%d",
+ broken ? "passed" : "failed", filesize, pos);
+
+ // there's a very small chance that both cases will match
+ // if anyone runs into it, you'll have to walk through
+ // the animDataTable and try to open part file for each entry
+ if (!correct && !broken) {
+ error("brokenSave: file format check failed");
+ } else if (correct && broken) {
+ error("brokenSave: both file formats seem to apply");
+ }
+
+ fHandle.seek(startpos);
+ debug(5, "brokenSave: detected %s file format",
+ correct ? "correct" : "broken");
+
+ return broken;
}
bool CineEngine::makeLoad(char *saveName) {
int16 i;
int16 size;
+ bool broken;
Common::InSaveFile *fHandle;
fHandle = g_saveFileMan->openForLoading(saveName);
@@ -408,29 +437,13 @@ bool CineEngine::makeLoad(char *saveName) {
// if (g_cine->getGameType() == Cine::GType_OS) {
// freeUnkList();
// }
- freePrcLinkedList();
- releaseObjectScripts();
- freeBgIncrustList();
+ bgIncrustList.clear();
closePart();
- for (i = 0; i < NUM_MAX_REL; i++) {
- if (relTable[i].data) {
- free(relTable[i].data);
- relTable[i].data = NULL;
- relTable[i].size = 0;
- relTable[i].obj1Param1 = 0;
- relTable[i].obj1Param2 = 0;
- relTable[i].obj2Param = 0;
- }
- }
-
- for (i = 0; i < NUM_MAX_SCRIPT; i++) {
- if (scriptTable[i].ptr) {
- free(scriptTable[i].ptr);
- scriptTable[i].ptr = NULL;
- scriptTable[i].size = 0;
- }
- }
+ objectScripts.clear();
+ globalScripts.clear();
+ relTable.clear();
+ scriptTable.clear();
for (i = 0; i < NUM_MAX_MESSAGE; i++) {
messageTable[i].len = 0;
@@ -478,6 +491,8 @@ bool CineEngine::makeLoad(char *saveName) {
checkForPendingDataLoadSwitch = 0;
+ broken = brokenSave(*fHandle);
+
currentDisk = fHandle->readUint16BE();
fHandle->read(currentPartName, 13);
@@ -491,6 +506,28 @@ bool CineEngine::makeLoad(char *saveName) {
fHandle->read(currentBgName[0], 13);
fHandle->read(currentCtName, 13);
+ checkDataDisk(currentDisk);
+
+ if (strlen(currentPartName)) {
+ loadPart(currentPartName);
+ }
+
+ if (strlen(currentPrcName)) {
+ loadPrc(currentPrcName);
+ }
+
+ if (strlen(currentRelName)) {
+ loadRel(currentRelName);
+ }
+
+ if (strlen(currentBgName[0])) {
+ loadBg(currentBgName[0]);
+ }
+
+ if (strlen(currentCtName)) {
+ loadCt(currentCtName);
+ }
+
fHandle->readUint16BE();
fHandle->readUint16BE();
@@ -540,18 +577,7 @@ bool CineEngine::makeLoad(char *saveName) {
fHandle->readUint16BE();
fHandle->readUint16BE();
- for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
- animDataTable[i].width = fHandle->readUint16BE();
- animDataTable[i].var1 = fHandle->readUint16BE();
- animDataTable[i].bpp = fHandle->readUint16BE();
- animDataTable[i].height = fHandle->readUint16BE();
- animDataTable[i].ptr1 = NULL;
- animDataTable[i].ptr2 = NULL;
- animDataTable[i].fileIdx = fHandle->readSint16BE();
- animDataTable[i].frameIdx = fHandle->readSint16BE();
- fHandle->read(animDataTable[i].name, 10);
- animDataTable[i].refresh = (fHandle->readByte() != 0);
- }
+ loadResourcesFromSave(*fHandle, broken);
// TODO: handle screen params (really required ?)
fHandle->readUint16BE();
@@ -576,44 +602,14 @@ bool CineEngine::makeLoad(char *saveName) {
loadOverlayFromSave(fHandle);
}
- size = fHandle->readSint16BE();
- for (i = 0; i < size; i++) {
- loadBgIncrustFromSave(fHandle);
- }
+ loadBgIncrustFromSave(*fHandle);
delete fHandle;
- checkDataDisk(currentDisk);
-
- if (strlen(currentPartName)) {
- loadPart(currentPartName);
- }
-
- if (strlen(currentPrcName)) {
- loadPrc(currentPrcName);
- setupScriptList(true);
- }
-
- if (strlen(currentRelName)) {
- loadRel(currentRelName);
- setupScriptList(false);
- }
-
if (strlen(currentMsgName)) {
loadMsg(currentMsgName);
}
- if (strlen(currentBgName[0])) {
- loadBg(currentBgName[0]);
- }
-
- if (strlen(currentCtName)) {
- loadCt(currentCtName);
- }
-
- loadResourcesFromSave();
- reincrustAllBg();
-
setMouseCursor(MOUSE_CURSOR_NORMAL);
if (strlen(currentDatName)) {
@@ -702,21 +698,7 @@ void makeSave(char *saveFileName) {
fHandle->writeUint16BE(0x1E);
for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
- fHandle->writeUint16BE(animDataTable[i].width);
- fHandle->writeUint16BE(animDataTable[i].var1);
- fHandle->writeUint16BE(animDataTable[i].bpp);
- fHandle->writeUint16BE(animDataTable[i].height);
- fHandle->writeSint16BE(animDataTable[i].fileIdx);
- fHandle->writeSint16BE(animDataTable[i].frameIdx);
- fHandle->write(animDataTable[i].name, 10);
-
- // Horrifyingly, cinE used to dump the entire struct to the
- // save file, including the data pointers. While these pointers
- // would be invalid after loading, the loadResourcesFromSave()
- // function would still test if ptr1 was non-NULL, presumably
- // to see if the object was present in the room.
-
- fHandle->writeByte(animDataTable[i].ptr1 ? 1 : 0);
+ animDataTable[i].save(*fHandle);
}
fHandle->writeUint16BE(0); // Screen params, unhandled
@@ -727,60 +709,15 @@ void makeSave(char *saveFileName) {
fHandle->writeUint16BE(0);
{
- int16 numScript = 0;
- prcLinkedListStruct *currentHead = globalScriptsHead.next;
-
- while (currentHead) {
- numScript++;
- currentHead = currentHead->next;
- }
-
- fHandle->writeUint16BE(numScript);
-
- // actual save
- currentHead = globalScriptsHead.next;
-
- while (currentHead) {
- for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
- fHandle->writeUint16BE(currentHead->stack[i]);
- }
-
- currentHead->localVars.save(*fHandle);
-
- fHandle->writeUint16BE(currentHead->compareResult);
- fHandle->writeUint16BE(currentHead->scriptPosition);
- fHandle->writeUint16BE(currentHead->scriptIdx);
-
- currentHead = currentHead->next;
- }
- }
-
- {
- int16 numScript = 0;
- prcLinkedListStruct *currentHead = objScriptList.next;
-
- while (currentHead) {
- numScript++;
- currentHead = currentHead->next;
+ ScriptList::iterator it;
+ fHandle->writeUint16BE(globalScripts.size());
+ for (it = globalScripts.begin(); it != globalScripts.end(); ++it) {
+ (*it)->save(*fHandle);
}
- fHandle->writeUint16BE(numScript);
-
- // actual save
- currentHead = objScriptList.next;
-
- while (currentHead) {
- for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
- fHandle->writeUint16BE(currentHead->stack[i]);
- }
-
- currentHead->localVars.save(*fHandle);
-
- fHandle->writeUint16BE(currentHead->compareResult);
- fHandle->writeUint16BE(currentHead->scriptPosition);
- fHandle->writeUint16BE(currentHead->scriptIdx);
-
- currentHead = currentHead->next;
+ fHandle->writeUint16BE(objectScripts.size());
+ for (it = objectScripts.begin(); it != objectScripts.end(); ++it) {
+ (*it)->save(*fHandle);
}
}
@@ -812,6 +749,20 @@ void makeSave(char *saveFileName) {
}
}
+ Common::List<BGIncrust>::iterator it;
+ fHandle->writeUint16BE(bgIncrustList.size());
+
+ for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) {
+ fHandle->writeUint32BE(0); // next
+ fHandle->writeUint32BE(0); // unkPtr
+ fHandle->writeUint16BE(it->objIdx);
+ fHandle->writeUint16BE(it->param);
+ fHandle->writeUint16BE(it->x);
+ fHandle->writeUint16BE(it->y);
+ fHandle->writeUint16BE(it->frame);
+ fHandle->writeUint16BE(it->part);
+ }
+/*
int numBgIncrustList = 0;
BGIncrustList *bgIncrustPtr = bgIncrustList;
@@ -834,6 +785,7 @@ void makeSave(char *saveFileName) {
bgIncrustPtr = bgIncrustPtr->next;
}
+*/
delete fHandle;
@@ -985,7 +937,11 @@ int drawChar(byte character, int16 x, int16 y) {
if (characterWidth) {
byte characterIdx = fontParamTable[character].characterIdx;
- drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y);
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ drawSpriteRaw2(textTable[characterIdx][0], 0, 2, 8, page1Raw, x, y);
+ } else {
+ drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y);
+ }
x += characterWidth + 1;
}
}
@@ -1726,8 +1682,8 @@ uint16 executePlayerInput(void) {
return var_5E;
}
-void drawSprite(overlayHeadElement *currentOverlay, byte *spritePtr,
- byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
+void drawSprite(overlayHeadElement *currentOverlay, const byte *spritePtr,
+ const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
byte *ptr = NULL;
byte *msk = NULL;
byte i = 0;
@@ -1754,11 +1710,11 @@ void drawSprite(overlayHeadElement *currentOverlay, byte *spritePtr,
maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame;
- maskWidth = animDataTable[maskSpriteIdx].width / 2;
- maskHeight = animDataTable[maskSpriteIdx].height;
- gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++);
+ maskWidth = animDataTable[maskSpriteIdx]._width / 2;
+ maskHeight = animDataTable[maskSpriteIdx]._height;
+ gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++);
#ifdef DEBUG_SPRITE_MASK
- gfxFillSprite(animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, page, maskX, maskY, 1);
+ gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
#endif
}
@@ -1790,7 +1746,7 @@ void backupOverlayPage(void) {
if (i > 200) {
memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320);
} else {
- memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i) * 320, 320);
+ memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320);
}
}
}
@@ -1805,7 +1761,7 @@ void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 co
uint16 lineResult, fullLineWidth;
uint16 interWordSize, interWordSizeRemain;
const char *endOfMessagePtr;
- byte currentChar, characterWidth;
+ byte currentChar; //, characterWidth;
gfxDrawPlainBoxRaw(x, y, x + width, y + 4, color, page1Raw);
@@ -1854,13 +1810,7 @@ void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 co
if (interWordSizeRemain)
interWordSizeRemain = 0;
} else {
- characterWidth = fontParamTable[currentChar].characterWidth;
-
- if (characterWidth) {
- byte characterIdx = fontParamTable[currentChar].characterIdx;
- drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, localX, localY);
- localX += characterWidth + 1;
- }
+ localX = drawChar(currentChar, localX, localY);
}
} while ((messagePtr < endOfMessagePtr) && !endOfMessageReached);
@@ -1910,6 +1860,10 @@ void drawFailureMessage(byte cmd) {
freeOverlay(cmd, 3);
}
+/*! \todo Fix Operation Stealth logo in intro (the green text after the plane
+ * takes off). Each letter should slowly grow top-down, it has something to
+ * do with object 10 (some mask or something)
+ */
void drawOverlays(void) {
uint16 partVar1, partVar2;
AnimData *pPart;
@@ -1942,12 +1896,13 @@ void drawOverlays(void) {
if (g_cine->getGameType() == Cine::GType_OS) {
pPart = &animDataTable[objPtr->frame];
- partVar1 = pPart->var1;
- partVar2 = pPart->height;
+ partVar1 = pPart->_var1;
+ partVar2 = pPart->_height;
- if (pPart->ptr1) {
- // NOTE: is the mask supposed to be in ptr1? Shouldn't that be ptr2, like below?
- drawSprite(currentOverlay, pPart->ptr1, pPart->ptr1, partVar1, partVar2, page1Raw, x, y);
+ if (pPart->data()) {
+ // NOTE: is the mask supposed to be in data()? Shouldn't that be mask(), like below?
+ // OS sprites don't use masks, see drawSprite() -- next_ghost
+ drawSprite(currentOverlay, pPart->data(), pPart->data(), partVar1, partVar2, page1Raw, x, y);
}
} else {
part = objPtr->part;
@@ -1956,11 +1911,11 @@ void drawOverlays(void) {
pPart = &animDataTable[objPtr->frame];
- partVar1 = pPart->var1;
- partVar2 = pPart->height;
+ partVar1 = pPart->_var1;
+ partVar2 = pPart->_height;
- if (pPart->ptr1) {
- drawSprite(currentOverlay, pPart->ptr1, pPart->ptr2, partVar1, partVar2, page1Raw, x, y);
+ if (pPart->data()) {
+ drawSprite(currentOverlay, pPart->data(), pPart->mask(), partVar1, partVar2, page1Raw, x, y);
}
}
}
@@ -2013,6 +1968,7 @@ void drawOverlays(void) {
x = objPtr->x;
y = objPtr->y;
+
if (objPtr->frame >= 0) {
part = objPtr->part;
@@ -2020,11 +1976,11 @@ void drawOverlays(void) {
pPart = &animDataTable[objPtr->frame];
- partVar1 = pPart->width / 2;
- partVar2 = pPart->height;
+ partVar1 = pPart->_width / 2;
+ partVar2 = pPart->_height;
- if (pPart->ptr1) {
- gfxFillSprite(pPart->ptr1, partVar1, partVar2, page1Raw, x, y);
+ if (pPart->data()) {
+ gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y);
}
}
break;
@@ -2040,22 +1996,15 @@ void drawOverlays(void) {
var5 = currentOverlay->x;
- if (objPtr->frame >= 0) {
- if (var5 <= 8) {
- if (additionalBgTable[var5]) {
- if (animDataTable[objPtr->frame].bpp == 1) {
- int16 x2;
- int16 y2;
-
- x2 = animDataTable[objPtr->frame].width / 2;
- y2 = animDataTable[objPtr->frame].height;
-
- if (animDataTable[objPtr->frame].ptr1) {
- // drawSpriteRaw(animDataTable[objPtr->frame].ptr1, animDataTable[objPtr->frame].ptr1, x2, y2,
- // additionalBgTable[currentAdditionalBgIdx], x, y);
- }
- }
- }
+ if (objPtr->frame >= 0 && var5 <= 8 && additionalBgTable[var5] && animDataTable[objPtr->frame]._bpp == 1) {
+ int16 x2;
+ int16 y2;
+
+ x2 = animDataTable[objPtr->frame]._width / 2;
+ y2 = animDataTable[objPtr->frame]._height;
+
+ if (animDataTable[objPtr->frame].data()) {
+ maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), x2, y2, page1Raw, x, y);
}
}
break;
@@ -2075,9 +2024,6 @@ void mainLoopSub6(void) {
void checkForPendingDataLoad(void) {
if (newPrcName[0] != 0) {
- freePrcLinkedList();
- resetglobalScriptsHead();
-
loadPrc(newPrcName);
strcpy(currentPrcName, newPrcName);
@@ -2087,9 +2033,6 @@ void checkForPendingDataLoad(void) {
}
if (newRelName[0] != 0) {
- releaseObjectScripts();
- resetObjectScriptHead();
-
loadRel(newRelName);
strcpy(currentRelName, newRelName);
@@ -2315,10 +2258,10 @@ void resetGfxEntityEntry(uint16 objIdx) {
#endif
}
-uint16 addAni(uint16 param1, uint16 param2, byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
- byte *currentPtr = ptr;
- byte *ptrData;
- byte *ptr2;
+uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
+ const byte *currentPtr = ptr;
+ const byte *ptrData;
+ const byte *ptr2;
int16 di;
assert(ptr);
@@ -2360,7 +2303,7 @@ uint16 addAni(uint16 param1, uint16 param2, byte *ptr, SeqListElement *element,
void processSeqListElement(SeqListElement *element) {
int16 x = objectTable[element->var6].x;
int16 y = objectTable[element->var6].y;
- byte *ptr1 = animDataTable[element->varA].ptr1;
+ const byte *ptr1 = animDataTable[element->varA].data();
int16 var_10;
int16 var_4;
int16 var_2;
diff --git a/engines/cine/xref.txt b/engines/cine/xref.txt
new file mode 100644
index 0000000000..fd76f7eaaf
--- /dev/null
+++ b/engines/cine/xref.txt
@@ -0,0 +1,146 @@
+script.cpp:
+setupOpcodes() - replaced with FWScript/OSScript class members
+getNextByte() - replaced with RawScript/FWScript class members
+getNextWord() - replaced with RawScript/FWScript class members
+getNextString() - replaced with RawScript/FWScript class members
+computeScriptStackSub() - replaced with RawScript::getNextLabel()
+computeScriptStack() - replaced with RawScript::computeLabels()
+computeScriptStackFromScript() - replaced with RawScript::getLabel()
+executeScript() - replaced with FWScript::execute()
+endScript0() - removed (obsoleted by new executeList0() implementation)
+endScript1() - removed (obsoleted by new executeList1() implementation)
+
+o1_modifyObjectParam() - replaced with FWScript::o1_modifyObjectParam()
+o1_getObjectParam() - replaced with FWScript::o1_getObjectParam()
+o1_addObjectParam() - replaced with FWScript::o1_addObjectParam()
+o1_subObjectParam() - replaced with FWScript::o1_subObjectParam()
+o1_add2ObjectParam() - replaced with FWScript::o1_add2ObjectParam()
+o1_sub2ObjectParam() - replaced with FWScript::o1_sub2ObjectParam()
+o1_compareObjectParam() - replaced with FWScript::o1_compareObjectParam()
+o1_setupObject() - replaced with FWScript::o1_setupObject()
+o1_checkCollision() - replaced with FWScript::o1_checkCollision()
+o1_loadVar() - replaced with FWScript::o1_loadVar()
+o1_addVar() - replaced with FWScript::o1_addVar()
+o1_subVar() - replaced with FWScript::o1_subVar()
+o1_mulVar() - replaced with FWScript::o1_mulVar()
+o1_divVar() - replaced with FWScript::o1_divVar()
+o1_compareVar() - replaced with FWScript::o1_compareVar()
+o1_modifyObjectParam2() - replaced with FWScript::o1_modifyObjectParam2()
+o1_loadMask0() - replaced with FWScript::o1_loadMask0()
+o1_unloadMask0() - replaced with FWScript::o1_unloadMask0()
+o1_addToBgList() - replaced with FWScript::o1_addToBgList()
+o1_loadMask1() - replaced with FWScript::o1_loadMask1()
+o1_unloadMask1() - replaced with FWScript::o1_unloadMask1()
+o1_loadMask4() - replaced with FWScript::o1_loadMask4()
+o1_unloadMask4() - replaced with FWScript::o1_unloadMask4()
+o1_addSpriteFilledToBgList() - replaced with FWScript::o1_addSpriteFilledToBgList()
+o1_op1B() - replaced with FWScript::o1_op1B()
+o1_label() - replaced with FWScript::o1_label()
+o1_goto() - replaced with FWScript::o1_goto()
+o1_gotoIfSup() - replaced with FWScript::o1_gotoIfSup()
+o1_gotoIfSupEqu() - replaced with FWScript::o1_gotoIfSupEqu()
+o1_gotoIfInf() - replaced with FWScript::o1_gotoIfInf()
+o1_gotoIfInfEqu() - replaced with FWScript::o1_gotoIfInfEqu()
+o1_gotoIfEqu() - replaced with FWScript::o1_gotoIfEqu()
+o1_gotoIfDiff() - replaced with FWScript::o1_gotoIfDiff()
+o1_removeLabel() - replaced with FWScript::o1_removeLabel()
+o1_loop() - replaced with FWScript::o1_loop()
+o1_startGlobalScript() - replaced with FWScript::o1_startGlobalScript()
+o1_endGlobalScript() - replaced with FWScript::o1_endGlobalScript()
+o1_loadAnim() - replaced with FWScript::o1_loadAnim()
+o1_loadBg() - replaced with FWScript::o1_loadBg()
+o1_loadCt() - replaced with FWScript::o1_loadCt()
+o1_loadPart() - replaced with FWScript::o1_loadPart()
+o1_closePart() - replaced with FWScript::o1_closePart()
+o1_loadNewPrcName() - replaced with FWScript::o1_loadNewPrcName()
+o1_requestCheckPendingDataLoad() - replaced with FWScript::o1_requestCheckPendingDataLoad()
+o1_blitAndFade() - replaced with FWScript::o1_blitAndFade()
+o1_fadeToBlack() - replaced with FWScript::o1_fadeToBlack()
+o1_transformPaletteRange() - replaced with FWScript::o1_transformPaletteRange()
+o1_setDefaultMenuColor2() - replaced with FWScript::o1_setDefaultMenuColor2()
+o1_palRotate() - replaced with FWScript::o1_palRotate()
+o1_break() - replaced with FWScript::o1_break()
+o1_endScript() - replaced with FWScript::o1_endScript()
+o1_message() - replaced with FWScript::o1_message()
+o1_loadGlobalVar() - replaced with FWScript::o1_loadGlobalVar()
+o1_compareGlobalVar() - replaced with FWScript::o1_compareGlobalVar()
+o1_declareFunctionName() - replaced with FWScript::o1_declareFunctionName()
+o1_freePartRange() - replaced with FWScript::o1_freePartRange()
+o1_unloadAllMasks() - replaced with FWScript::o1_unloadAllMasks()
+o1_setScreenDimensions() - replaced with FWScript::o1_setScreenDimensions()
+o1_displayBackground() - replaced with FWScript::o1_displayBackground()
+o1_initializeZoneData() - replaced with FWScript::o1_initializeZoneData()
+o1_setZoneDataEntry() - replaced with FWScript::o1_setZoneDataEntry()
+o1_getZoneDataEntry() - replaced with FWScript::o1_getZoneDataEntry()
+o1_setDefaultMenuColor() - replaced with FWScript::o1_setDefaultMenuColor()
+o1_allowPlayerInput() - replaced with FWScript::o1_allowPlayerInput()
+o1_disallowPlayerInput() - replaced with FWScript::o1_disallowPlayerInput()
+o1_changeDataDisk() - replaced with FWScript::o1_changeDataDisk()
+o1_loadMusic() - replaced with FWScript::o1_loadMusic()
+o1_playMusic() - replaced with FWScript::o1_playMusic()
+o1_fadeOutMusic() - replaced with FWScript::o1_fadeOutMusic()
+o1_stopSample() - replaced with FWScript::o1_stopSample()
+o1_op71() - replaced with FWScript::o1_op71()
+o1_op72() - replaced with FWScript::o1_op72()
+o1_op73() - replaced with FWScript::o1_op73()
+o1_playSample() - replaced with FWScript::o1_playSample()
+o1_playSample() - replaced with FWScript::o1_playSample()
+o1_disableSystemMenu() - replaced with FWScript::o1_disableSystemMenu()
+o1_loadMask5() - replaced with FWScript::o1_loadMask5()
+o1_unloadMask5() - replaced with FWScript::o1_unloadMask5()
+
+o2_loadPart() - replaced with FWScript::o2_loadPart()
+o2_addSeqListElement() - replaced with FWScript::o2_addSeqListElement()
+o2_removeSeq() - replaced with FWScript::o2_removeSeq()
+o2_playSample() - replaced with FWScript::o2_playSample()
+o2_playSampleAlt() - replaced with FWScript::o2_playSampleAlt()
+o2_op81() - replaced with FWScript::o2_op81()
+o2_op82() - replaced with FWScript::o2_op82()
+o2_isSeqRunning() - replaced with FWScript::o2_isSeqRunning()
+o2_gotoIfSupNearest() - replaced with FWScript::o2_gotoIfSupNearest()
+o2_gotoIfSupEquNearest() - replaced with FWScript::o2_gotoIfSupEquNearest()
+o2_gotoIfInfNearest() - replaced with FWScript::o2_gotoIfInfNearest()
+o2_gotoIfInfEquNearest() - replaced with FWScript::o2_gotoIfInfEquNearest()
+o2_gotoIfEquNearest() - replaced with FWScript::o2_gotoIfEquNearest()
+o2_gotoIfDiffNearest() - replaced with FWScript::o2_gotoIfDiffNearest()
+o2_startObjectScript() - replaced with FWScript::o2_startObjectScript()
+o2_stopObjectScript() - replaced with FWScript::o2_stopObjectScript()
+o2_op8D() - replaced with FWScript::o2_op8D()
+o2_addBackground() - replaced with FWScript::o2_addBackground()
+o2_removeBackground() - replaced with FWScript::o2_removeBackground()
+o2_loadAbs() - replaced with FWScript::o2_loadAbs()
+o2_loadBg() - replaced with FWScript::o2_loadBg()
+o2_wasZoneChecked() - replaced with FWScript::o2_wasZoneChecked()
+o2_op9B() - replaced with FWScript::o2_op9B()
+o2_op9C() - replaced with FWScript::o2_op9C()
+o2_useBgScroll() - replaced with FWScript::o2_useBgScroll()
+o2_setAdditionalBgVScroll() - replaced with FWScript::o2_setAdditionalBgVScroll()
+o2_op9F() - replaced with FWScript::o2_op9F()
+o2_addGfxElementA0() - replaced with FWScript::o2_addGfxElementA0()
+o2_opA1() - replaced with FWScript::o2_opA1()
+o2_opA2() - replaced with FWScript::o2_opA2()
+o2_opA3() - replaced with FWScript::o2_opA3()
+o2_loadMask22() - replaced with FWScript::o2_loadMask22()
+o2_unloadMask22() - replaced with FWScript::o2_unloadMask22()
+
+prc.cpp:
+resetGlobalScriptsHead() - removed (obsoleted by Common::List)
+freePrcLinkedList(void) - removed (obsoleted by Common::List::clear())
+
+rel.cpp:
+resetObjectScriptHead() - removed (obsoleted by Common::List)
+releaseObjectScripts() - removed (obsoleted by Common::List::clear())
+
+various.cpp:
+setupScriptList() - removed (obsoleted by new makeLoad() and
+ loadScriptFromSave() implementation)
+
+anim.cpp:
+freeAnimData() - replaced with animData::clear()
+allocFrame() - replaced with animData::load()
+reserveFrame() - replaced with animData::load()
+
+bg_list.cpp
+reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and
+ loadBgIncrustFromSave() implementation)
+freeBgIncrustList() - removed (obsoleted by Common::List::clear())