aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorEugene Sandulenko2008-04-21 20:51:17 +0000
committerEugene Sandulenko2008-04-21 20:51:17 +0000
commit57a9ef3a8f42a7bb71d17f6150dce1e652ce33c0 (patch)
tree9f4fa14956a07d9c668b9e5abffa3323b42c9411 /engines
parent54485c24c530288280174f6d286c8c0b367a8206 (diff)
downloadscummvm-rg350-57a9ef3a8f42a7bb71d17f6150dce1e652ce33c0.tar.gz
scummvm-rg350-57a9ef3a8f42a7bb71d17f6150dce1e652ce33c0.tar.bz2
scummvm-rg350-57a9ef3a8f42a7bb71d17f6150dce1e652ce33c0.zip
Patch #1941066: "CinE sprite overlay rewrite" courtsey of next_ghost
svn-id: r31651
Diffstat (limited to 'engines')
-rw-r--r--engines/cine/anim.cpp1
-rw-r--r--engines/cine/anim.h1
-rw-r--r--engines/cine/bg.cpp6
-rw-r--r--engines/cine/bg_list.cpp6
-rw-r--r--engines/cine/cine.cpp6
-rw-r--r--engines/cine/gfx.cpp135
-rw-r--r--engines/cine/gfx.h3
-rw-r--r--engines/cine/main_loop.cpp2
-rw-r--r--engines/cine/module.mk3
-rw-r--r--engines/cine/msg.cpp39
-rw-r--r--engines/cine/msg.h6
-rw-r--r--engines/cine/object.cpp160
-rw-r--r--engines/cine/object.h17
-rw-r--r--engines/cine/script.h1
-rw-r--r--engines/cine/script_fw.cpp (renamed from engines/cine/script.cpp)870
-rw-r--r--engines/cine/script_os.cpp793
-rw-r--r--engines/cine/various.cpp531
-rw-r--r--engines/cine/various.h11
-rw-r--r--engines/cine/xref.txt7
19 files changed, 1226 insertions, 1372 deletions
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 312de4a6db..f17c7a92fc 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -186,7 +186,6 @@ static const AnimDataEntry transparencyData[] = {
};
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);
diff --git a/engines/cine/anim.h b/engines/cine/anim.h
index c15ab2eabd..0406f3159b 100644
--- a/engines/cine/anim.h
+++ b/engines/cine/anim.h
@@ -102,6 +102,7 @@ void freeAnimDataRange(byte startIdx, byte numIdx);
void loadResource(const char *animName);
void loadAbs(const char *resourceName, uint16 idx);
void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken);
+void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
} // End of namespace Cine
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index 351a633b5e..b6c07a05cb 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -50,7 +50,7 @@ byte loadCt(const char *ctName) {
uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
if (bpp == 8) {
ctColorMode = 1;
- memcpy(newPalette, ptr, 256*3);
+ memcpy(newPalette, ptr, 256 * 3);
ptr += 3 * 256;
memcpy(page3Raw, ptr, 320 * 200);
} else {
@@ -134,13 +134,11 @@ 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);
+ memcpy(newPalette, ptr, 256 * 3);
ptr += 3 * 256;
memcpy(additionalBgTable[bgIdx], ptr, 320 * 200);
} else {
diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp
index 7d35f9981e..a70733dc68 100644
--- a/engines/cine/bg_list.cpp
+++ b/engines/cine/bg_list.cpp
@@ -77,7 +77,7 @@ void addToBGList(int16 objIdx, bool addList) {
void addSpriteFilledToBGList(int16 objIdx, bool addList) {
int16 x = objectTable[objIdx].x;
int16 y = objectTable[objIdx].y;
- int16 width = animDataTable[objectTable[objIdx].frame]._width;
+ int16 width = animDataTable[objectTable[objIdx].frame]._realWidth;
int16 height = animDataTable[objectTable[objIdx].frame]._height;
const byte *data = animDataTable[objectTable[objIdx].frame].data();
@@ -86,11 +86,11 @@ void addSpriteFilledToBGList(int16 objIdx, bool addList) {
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);
+ gfxFillSprite(data, width, height, additionalBgTable[i], x, y);
}
}
} else {
- gfxFillSprite(data, width / 2, height, page2Raw, x, y);
+ gfxFillSprite(data, width, height, page2Raw, x, y);
}
}
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index ffcbfbaa82..41dd9be16f 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -129,14 +129,12 @@ void CineEngine::initialize() {
globalScripts.clear();
bgIncrustList.clear();
freeAnimDataTable();
+ overlayList.clear();
+ messageTable.clear();
memset(objectTable, 0, sizeof(objectTable));
- memset(messageTable, 0, sizeof(messageTable));
-
- overlayHead.next = overlayHead.previous = NULL;
var8 = 0;
-// bgIncrustList = NULL;
var2 = var3 = var4 = var5 = 0;
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 8db4456485..2730a92e62 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -25,6 +25,7 @@
#include "cine/cine.h"
#include "cine/bg.h"
+#include "cine/bg_list.h"
#include "cine/various.h"
#include "common/endian.h"
@@ -168,7 +169,7 @@ void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *pag
byte *destPtr = page + x + y * 320;
destPtr += i * 320;
- for (j = 0; j < width * 8; j++) {
+ for (j = 0; j < width; j++) {
if (x + j >= 0 && x + j < 320 && i + y >= 0
&& i + y < 200) {
if (!*(spritePtr++)) {
@@ -191,7 +192,7 @@ void gfxDrawMaskedSprite(const byte *spritePtr, const byte *maskPtr, uint16 widt
byte *destPtr = page + x + y * 320;
destPtr += i * 320;
- for (j = 0; j < width * 8; j++) {
+ for (j = 0; j < width; j++) {
if (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200 && *maskPtr == 0) {
*destPtr = *spritePtr;
}
@@ -202,61 +203,82 @@ void gfxDrawMaskedSprite(const byte *spritePtr, const byte *maskPtr, uint16 widt
}
}
-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 gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *srcMask, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight) {
int16 i, j, d, spritePitch, maskPitch;
- width *= 8;
- maskWidth *= 8;
-
spritePitch = width;
maskPitch = maskWidth;
- if (maskIdx == 0) {
- memcpy(bufferSprPtr, spritePtr, spritePitch * height);
- memcpy(bufferMskPtr, spriteMskPtr, spritePitch * height);
- }
-
- if (ys > ym) {
- d = ys - ym;
- maskPtr += d * maskPitch;
+ // crop update area to overlapping parts of masks
+ if (y > ym) {
+ d = y - ym;
+ srcMask += d * maskPitch;
maskHeight -= d;
+ } else if (y < ym) {
+ d = ym - y;
+ destMask += d * spritePitch;
+ height -= d;
}
- if (maskHeight <= 0) {
- return;
- }
- if (xs > xm) {
- d = xs - xm;
- maskPtr += d;
+
+ if (x > xm) {
+ d = x - xm;
+ srcMask += d;
maskWidth -= d;
+ } else if (x < xm) {
+ d = xm - x;
+ destMask += d;
+ width -= d;
}
- if (maskWidth <= 0) {
- return;
+
+ // update mask
+ for (j = 0; j < MIN(maskHeight, height); ++j) {
+ for (i = 0; i < MIN(maskWidth, width); ++i) {
+ destMask[i] |= srcMask[i] ^ 1;
+ }
+ destMask += spritePitch;
+ srcMask += maskPitch;
}
- if (ys < ym) {
- d = ym - ys;
- spriteMskPtr += d * spritePitch;
- bufferMskPtr += d * spritePitch;
+}
+
+void gfxUpdateIncrustMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *srcMask, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight) {
+ int16 i, j, d, spritePitch, maskPitch;
+
+ spritePitch = width;
+ maskPitch = maskWidth;
+
+ // crop update area to overlapping parts of masks
+ if (y > ym) {
+ d = y - ym;
+ srcMask += d * maskPitch;
+ maskHeight -= d;
+ } else if (y < ym) {
+ d = ym - y > height ? height : ym - y;
+ memset(destMask, 1, d * spritePitch);
+ destMask += d * spritePitch;
height -= d;
}
- if (height <= 0) {
- return;
- }
- if (xs < xm) {
- d = xm - xs;
- spriteMskPtr += d;
- bufferMskPtr += d;
- width -= d;
- }
- if (width <= 0) {
- return;
+
+ if (x > xm) {
+ d = x - xm;
+ xm = x;
+ srcMask += d;
+ maskWidth -= d;
}
+
+ d = xm - x;
+ maskWidth += d;
+
+ // update mask
for (j = 0; j < MIN(maskHeight, height); ++j) {
- for (i = 0; i < MIN(maskWidth, width); ++i) {
- bufferMskPtr[i] |= maskPtr[i] ^ 1;
+ for (i = 0; i < width; ++i) {
+ destMask[i] |= i < d || i >= maskWidth ? 1 : srcMask[i - d];
}
- bufferMskPtr += spritePitch;
- maskPtr += maskPitch;
+ destMask += spritePitch;
+ srcMask += maskPitch;
+ }
+
+ if (j < height) {
+ memset(destMask, 1, (height - j) * spritePitch);
}
}
@@ -431,15 +453,19 @@ void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 h
void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 height,
byte *page, int16 x, int16 y) {
- int16 i, j;
+ int16 i, j, tmpWidth, tmpHeight;
+ Common::List<BGIncrust>::iterator it;
+ byte *mask;
+ const byte *backup = maskPtr;
+ // background pass
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++) {
+ for (j = 0; j < width; j++) {
if ((!maskPtr || !(*maskPtr)) && (x + j >= 0
&& x + j < 320 && i + y >= 0 && i + y < 200)) {
*destPtr = *srcPtr;
@@ -450,6 +476,27 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he
maskPtr++;
}
}
+
+ maskPtr = backup;
+
+ // incrust pass
+ for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) {
+ tmpWidth = animDataTable[it->frame]._realWidth;
+ tmpHeight = animDataTable[it->frame]._height;
+ mask = (byte*)malloc(tmpWidth * tmpHeight);
+
+ if (it->param == 0) {
+ generateMask(animDataTable[it->frame].data(), mask, tmpWidth * tmpHeight, it->part);
+ gfxUpdateIncrustMask(mask, it->x, it->y, tmpWidth, tmpHeight, maskPtr, x, y, width, height);
+ gfxDrawMaskedSprite(animDataTable[it->frame].data(), mask, tmpWidth, tmpHeight, page, it->x, it->y);
+ } else {
+ memcpy(mask, animDataTable[it->frame].data(), tmpWidth * tmpHeight);
+ gfxUpdateIncrustMask(mask, it->x, it->y, tmpWidth, tmpHeight, maskPtr, x, y, width, height);
+ gfxFillSprite(mask, tmpWidth, tmpHeight, page, it->x, it->y);
+ }
+
+ free(mask);
+ }
}
/*! \todo Fix rendering to prevent fadein artifacts
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 9e03f351f9..3812b52113 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -53,8 +53,7 @@ void gfxFlipPage(void);
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(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 gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *maskPtr, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight);
void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
void gfxDrawPlainBox(int16 x1, int16 y1, int16 x2, int16 y2, byte color);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index c74dde0310..6042849f59 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -189,7 +189,6 @@ void CineEngine::mainLoop(int bootScriptIdx) {
quitFlag = 0;
if (_preLoad == false) {
- resetMessageHead();
resetSeqList();
resetBgIncrustList();
@@ -315,7 +314,6 @@ void CineEngine::mainLoop(int bootScriptIdx) {
hideMouse();
g_sound->stopMusic();
- unloadAllMasks();
// if (g_cine->getGameType() == Cine::GType_OS) {
// freeUnkList();
// }
diff --git a/engines/cine/module.mk b/engines/cine/module.mk
index 23792a17b9..347af2dae1 100644
--- a/engines/cine/module.mk
+++ b/engines/cine/module.mk
@@ -14,7 +14,8 @@ MODULE_OBJS = \
part.o \
prc.o \
rel.o \
- script.o \
+ script_fw.o \
+ script_os.o \
sound.o \
texte.o \
unpack.o \
diff --git a/engines/cine/msg.cpp b/engines/cine/msg.cpp
index 212b9ffd7c..55eb627309 100644
--- a/engines/cine/msg.cpp
+++ b/engines/cine/msg.cpp
@@ -31,45 +31,32 @@
namespace Cine {
-uint16 messageCount;
+Common::StringList messageTable;
void loadMsg(char *pMsgName) {
- uint16 i;
+ int i, count, len;
byte *ptr, *dataPtr;
+ const char *messagePtr;
checkDataDisk(-1);
- messageCount = 0;
-
- for (i = 0; i < NUM_MAX_MESSAGE; i++) {
- messageTable[i].len = 0;
- if (messageTable[i].ptr) {
- free(messageTable[i].ptr);
- messageTable[i].ptr = NULL;
- }
- }
+ messageTable.clear();
ptr = dataPtr = readBundleFile(findFileInBundle(pMsgName));
setMouseCursor(MOUSE_CURSOR_DISK);
- messageCount = READ_BE_UINT16(ptr); ptr += 2;
-
- assert(messageCount <= NUM_MAX_MESSAGE);
-
- for (i = 0; i < messageCount; i++) {
- messageTable[i].len = READ_BE_UINT16(ptr); ptr += 2;
- }
-
- for (i = 0; i < messageCount; i++) {
- if (messageTable[i].len) {
- messageTable[i].ptr = (byte *) malloc(messageTable[i].len);
+ count = READ_BE_UINT16(ptr);
+ ptr += 2;
- assert(messageTable[i].ptr);
+ messagePtr = (const char*)(ptr + 2 * count);
- memcpy(messageTable[i].ptr, ptr, messageTable[i].len);
- ptr += messageTable[i].len;
- }
+ for (i = 0; i < count; i++) {
+ len = READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ messageTable.push_back(messagePtr);
+ messagePtr += len;
}
free(dataPtr);
diff --git a/engines/cine/msg.h b/engines/cine/msg.h
index 9828da8bab..ddf8ade8c2 100644
--- a/engines/cine/msg.h
+++ b/engines/cine/msg.h
@@ -26,8 +26,14 @@
#ifndef CINE_MSG_H
#define CINE_MSG_H
+#include "common/str.h"
+
namespace Cine {
+#define NUM_MAX_MESSAGE 255
+
+extern Common::StringList messageTable;
+
void loadMsg(char *pMsgName);
} // End of namespace Cine
diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp
index bba1c094f1..36f7b17a69 100644
--- a/engines/cine/object.cpp
+++ b/engines/cine/object.cpp
@@ -36,27 +36,7 @@
namespace Cine {
objectStruct objectTable[NUM_MAX_OBJECT];
-ScriptVars globalVars(NUM_MAX_VAR);
-overlayHeadElement overlayHead;
-
-void unloadAllMasks(void) {
- overlayHeadElement *current = overlayHead.next;
-
- while (current) {
- overlayHeadElement *next = current->next;
-
- delete current;
-
- current = next;
- }
-
- resetMessageHead();
-}
-
-void resetMessageHead(void) {
- overlayHead.next = NULL;
- overlayHead.previous = NULL;
-}
+Common::List<overlay> overlayList;
void loadObject(char *pObjectName) {
uint16 numEntry;
@@ -100,92 +80,88 @@ void loadObject(char *pObjectName) {
free(dataPtr);
}
-int8 removeOverlayElement(uint16 objIdx, uint16 param) {
- overlayHeadElement *currentHeadPtr = &overlayHead;
- overlayHeadElement *tempHead = currentHeadPtr;
- overlayHeadElement *tempPtr2;
-
- currentHeadPtr = tempHead->next;
-
- while (currentHeadPtr && (currentHeadPtr->objIdx != objIdx || currentHeadPtr->type != param)) {
- tempHead = currentHeadPtr;
- currentHeadPtr = tempHead->next;
- }
-
- if (!currentHeadPtr || currentHeadPtr->objIdx != objIdx || currentHeadPtr->type != param) {
- return -1;
- }
-
- tempHead->next = tempPtr2 = currentHeadPtr->next;
+/*! \brief Remove overlay sprite from the list
+ * \param objIdx Remove overlay associated with this object
+ * \param param Remove overlay of this type
+ */
+int removeOverlay(uint16 objIdx, uint16 param) {
+ Common::List<overlay>::iterator it;
- if (!tempPtr2) {
- tempPtr2 = &overlayHead;
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ if (it->objIdx == objIdx && it->type == param) {
+ overlayList.erase(it);
+ return 1;
+ }
}
- tempPtr2->previous = currentHeadPtr->previous;
-
- delete currentHeadPtr;
-
return 0;
}
-int16 freeOverlay(uint16 objIdx, uint16 param) {
- overlayHeadElement *currentHeadPtr = overlayHead.next;
- overlayHeadElement *previousPtr = &overlayHead;
- overlayHeadElement *tempPtr2;
-
- while (currentHeadPtr && ((currentHeadPtr->objIdx != objIdx) || (currentHeadPtr->type != param))) {
- previousPtr = currentHeadPtr;
- currentHeadPtr = previousPtr->next;
- }
-
- if (!currentHeadPtr || !((currentHeadPtr->objIdx == objIdx) && (currentHeadPtr->type == param))) {
- return -1;
- }
-
- previousPtr->next = tempPtr2 = currentHeadPtr->next;
+/*! \brief Add new overlay sprite to the list
+ * \param objIdx Associate the overlay with this object
+ * \param param Type of new overlay
+ * \todo Why are x, y, width and color left uninitialized?
+ */
+void addOverlay(uint16 objIdx, uint16 param) {
+ Common::List<overlay>::iterator it;
+ overlay tmp;
- if (!tempPtr2) {
- tempPtr2 = &overlayHead;
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask) {
+ break;
+ }
}
- tempPtr2->previous = currentHeadPtr->previous;
+ tmp.objIdx = objIdx;
+ tmp.type = param;
- delete currentHeadPtr;
- return 0;
+ overlayList.insert(it, tmp);
}
-void loadOverlayElement(uint16 objIdx, uint16 param) {
- overlayHeadElement *currentHeadPtr = &overlayHead;
- overlayHeadElement *pNewElement;
-
- uint16 si = objectTable[objIdx].mask;
-
- overlayHeadElement *tempHead = currentHeadPtr;
-
- currentHeadPtr = tempHead->next;
-
- while (currentHeadPtr && (objectTable[currentHeadPtr->objIdx].mask < si)) {
- tempHead = currentHeadPtr;
- currentHeadPtr = tempHead->next;
+/*! \brief Add new background mask overlay
+ * \param objIdx Associate the overlay with this object
+ * \param param source background index
+ */
+void addGfxElementA0(int16 objIdx, int16 param) {
+ Common::List<overlay>::iterator it;
+ overlay tmp;
+
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ // wtf?!
+ if (objectTable[it->objIdx].mask == objectTable[objIdx].mask &&
+ (it->type == 2 || it->type == 3)) {
+ break;
+ }
}
- pNewElement = new overlayHeadElement;
+ if (it != overlayList.end() && it->objIdx == objIdx && it->type == 20 && it->x == param) {
+ return;
+ }
- assert(pNewElement);
+ tmp.objIdx = objIdx;
+ tmp.type = 20;
+ tmp.x = param;
+ tmp.y = 0;
+ tmp.width = 0;
+ tmp.color = 0;
- pNewElement->next = tempHead->next;
- tempHead->next = pNewElement;
+ overlayList.insert(it, tmp);
+}
- pNewElement->objIdx = objIdx;
- pNewElement->type = param;
+/*! \brief Remove background mask overlay
+ * \param objIdx Remove overlay associated with this object
+ * \param param Remove overlay using this background
+ * \todo Check that it works
+ */
+void removeGfxElementA0(int16 objIdx, int16 param) {
+ Common::List<overlay>::iterator it;
- if (!currentHeadPtr) {
- currentHeadPtr = &overlayHead;
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ if (it->objIdx == objIdx && it->type == 20 && it->x == param) {
+ overlayList.erase(it);
+ return;
+ }
}
-
- pNewElement->previous = currentHeadPtr->previous;
- currentHeadPtr->previous = pNewElement;
}
void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4) {
@@ -194,8 +170,8 @@ void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint1
objectTable[objIdx].mask = param3;
objectTable[objIdx].frame = param4;
- if (!removeOverlayElement(objIdx, 0)) {
- loadOverlayElement(objIdx, 0);
+ if (removeOverlay(objIdx, 0)) {
+ addOverlay(objIdx, 0);
}
}
@@ -223,8 +199,8 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
case 2:
objectTable[objIdx].mask = newValue;
- if (!removeOverlayElement(objIdx, 0)) {
- loadOverlayElement(objIdx, 0);
+ if (removeOverlay(objIdx, 0)) {
+ addOverlay(objIdx, 0);
}
break;
case 3:
diff --git a/engines/cine/object.h b/engines/cine/object.h
index e4ab1377ff..e7de39649d 100644
--- a/engines/cine/object.h
+++ b/engines/cine/object.h
@@ -40,9 +40,7 @@ struct objectStruct {
uint16 part;
};
-struct overlayHeadElement {
- struct overlayHeadElement *next;
- struct overlayHeadElement *previous;
+struct overlay {
uint16 objIdx;
uint16 type;
int16 x;
@@ -55,22 +53,19 @@ struct overlayHeadElement {
#define NUM_MAX_VAR 256
extern objectStruct objectTable[NUM_MAX_OBJECT];
-extern ScriptVars globalVars;
-extern overlayHeadElement overlayHead;
-
-void unloadAllMasks(void);
-void resetMessageHead(void);
+extern Common::List<overlay> overlayList;
void loadObject(char *pObjectName);
void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4);
void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue);
-void loadOverlayElement(uint16 objIdx, uint16 param);
-int8 removeOverlayElement(uint16 objIdx, uint16 param);
+void addOverlay(uint16 objIdx, uint16 param);
+int removeOverlay(uint16 objIdx, uint16 param);
+void addGfxElementA0(int16 objIdx, int16 param);
+void removeGfxElementA0(int16 objIdx, int16 param);
int16 getObjectParam(uint16 objIdx, uint16 paramIdx);
-int16 freeOverlay(uint16 objIdx, uint16 param);
void addObjectParam(byte objIdx, byte paramIdx, int16 newValue);
void subObjectParam(byte objIdx, byte paramIdx, int16 newValue);
diff --git a/engines/cine/script.h b/engines/cine/script.h
index 4bcf4b6ccb..4a2e7072ee 100644
--- a/engines/cine/script.h
+++ b/engines/cine/script.h
@@ -358,6 +358,7 @@ typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;
extern RawScriptArray scriptTable;
extern FWScriptInfo *scriptInfo;
+extern ScriptVars globalVars;
void setupOpcodes();
diff --git a/engines/cine/script.cpp b/engines/cine/script_fw.cpp
index 8ccd0ce3a1..f833d7c30b 100644
--- a/engines/cine/script.cpp
+++ b/engines/cine/script_fw.cpp
@@ -24,7 +24,7 @@
*/
/*! \file
- * Script interpreter file
+ * Future Wars script interpreter file
*/
#include "common/endian.h"
@@ -38,6 +38,8 @@
namespace Cine {
+ScriptVars globalVars(NUM_MAX_VAR);
+
uint16 compareVars(int16 a, int16 b);
void palRotate(byte a, byte b, byte c);
void removeSeq(uint16 param1, uint16 param2, uint16 param3);
@@ -161,7 +163,7 @@ const Opcode FWScript::_opcodeTable[] = {
{ &FWScript::o1_declareFunctionName, "s" },
{ &FWScript::o1_freePartRange, "bb" },
{ &FWScript::o1_unloadAllMasks, "" },
- // 5C */
+ /* 5C */
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
@@ -204,224 +206,6 @@ const Opcode FWScript::_opcodeTable[] = {
};
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);
-
FWScriptInfo *scriptInfo; ///< Script factory
RawScriptArray scriptTable; ///< Table of script bytecode
@@ -898,33 +682,6 @@ void FWScript::save(Common::OutSaveFile &fHandle) const {
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
*/
@@ -1003,84 +760,6 @@ FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index, const
return tmp;
}
-/*! \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;
- }
-
- if (!OSScript::_opcodeTable[opcode - 1].args) {
- warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
- return NULL;
- }
-
- return OSScript::_opcodeTable[opcode - 1].args;
-}
-
-/*! \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;
- }
-
- if (!OSScript::_opcodeTable[opcode - 1].proc) {
- warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
- return NULL;
- }
-
- return OSScript::_opcodeTable[opcode - 1].proc;
-}
-
-/*! \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);
-}
-
-/*! \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);
-}
-
-/*! \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
// ------------------------------------------------------------------------
@@ -1375,7 +1054,7 @@ int FWScript::o1_loadMask0() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
- loadOverlayElement(param, 0);
+ addOverlay(param, 0);
return 0;
}
@@ -1383,7 +1062,8 @@ int FWScript::o1_unloadMask0() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
- freeOverlay(param, 0);
+ removeOverlay(param, 0);
+ return 0;
return 0;
}
@@ -1399,7 +1079,7 @@ int FWScript::o1_loadMask1() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
- loadOverlayElement(param, 1);
+ addOverlay(param, 1);
return 0;
}
@@ -1407,7 +1087,7 @@ int FWScript::o1_unloadMask1() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
- freeOverlay(param, 1);
+ removeOverlay(param, 1);
return 0;
}
@@ -1415,7 +1095,7 @@ int FWScript::o1_loadMask4() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
- loadOverlayElement(param, 4);
+ addOverlay(param, 4);
return 0;
}
@@ -1423,7 +1103,7 @@ int FWScript::o1_unloadMask4() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
- freeOverlay(param, 4);
+ removeOverlay(param, 4);
return 0;
}
@@ -1825,7 +1505,7 @@ int FWScript::o1_freePartRange() {
int FWScript::o1_unloadAllMasks() {
debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
- unloadAllMasks();
+ overlayList.clear();
return 0;
}
@@ -2034,7 +1714,7 @@ int FWScript::o1_loadMask5() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
- loadOverlayElement(param, 5);
+ addOverlay(param, 5);
return 0;
}
@@ -2042,534 +1722,12 @@ int FWScript::o1_unloadMask5() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
- freeOverlay(param, 5);
- return 0;
-}
-
-// ------------------------------------------------------------------------
-// OPERATION STEALTH opcodes
-// ------------------------------------------------------------------------
-
-int FWScript::o2_loadPart() {
- const char *param = getNextString();
-
- debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
- return 0;
-}
-
-int FWScript::o2_playSample() {
- if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
- // no-op in these versions
- getNextByte();
- getNextByte();
- getNextWord();
- getNextByte();
- getNextWord();
- getNextWord();
- return 0;
- }
- return o1_playSample();
-}
-
-int FWScript::o2_playSampleAlt() {
- byte num = getNextByte();
- byte channel = getNextByte();
- uint16 frequency = getNextWord();
- getNextByte();
- getNextWord();
- uint16 size = getNextWord();
-
- if (size == 0xFFFF) {
- size = animDataTable[num]._width * animDataTable[num]._height;
- }
- 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].data(), size, 0, 0, 63, 0);
- }
- }
- return 0;
-}
-
-int FWScript::o2_addSeqListElement() {
- byte param1 = getNextByte();
- byte param2 = getNextByte();
- byte param3 = getNextByte();
- byte param4 = getNextByte();
- uint16 param5 = getNextWord();
- uint16 param6 = getNextWord();
- uint16 param7 = getNextWord();
-
- 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;
-}
-
-int FWScript::o2_removeSeq() {
- byte a = getNextByte();
- byte b = getNextByte();
-
- debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
- removeSeq(a, 0, b);
- return 0;
-}
-
-/*! \todo Implement this instruction
- */
-int FWScript::o2_op81() {
- warning("STUB: o2_op81()");
- // freeUnkList();
- return 0;
-}
-
-/*! \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;
-}
-
-int FWScript::o2_isSeqRunning() {
- byte a = getNextByte();
- byte b = getNextByte();
-
- debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
-
- if (isSeqRunning(a, 0, b)) {
- _compare = 1;
- } else {
- _compare = 0;
- }
- return 0;
-}
-
-/*! \todo The assert may produce false positives and requires testing
- */
-int FWScript::o2_gotoIfSupNearest() {
- byte labelIdx = getNextByte();
-
- if (_compare == kCmpGT) {
- assert(_labels[labelIdx] != -1);
-
- 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)", _line, labelIdx);
- }
- return 0;
-}
-
-/*! \todo The assert may produce false positives and requires testing
- */
-int FWScript::o2_gotoIfSupEquNearest() {
- byte labelIdx = getNextByte();
-
- if (_compare & (kCmpGT | kCmpEQ)) {
- assert(_labels[labelIdx] != -1);
-
- 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)", _line, labelIdx);
- }
- return 0;
-}
-
-/*! \todo The assert may produce false positives and requires testing
- */
-int FWScript::o2_gotoIfInfNearest() {
- byte labelIdx = getNextByte();
-
- if (_compare == kCmpLT) {
- assert(_labels[labelIdx] != -1);
-
- 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)", _line, labelIdx);
- }
- return 0;
-}
-
-/*! \todo The assert may produce false positives and requires testing
- */
-int FWScript::o2_gotoIfInfEquNearest() {
- byte labelIdx = getNextByte();
-
- if (_compare & (kCmpLT | kCmpEQ)) {
- assert(_labels[labelIdx] != -1);
-
- 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)", _line, labelIdx);
- }
- return 0;
-}
-
-/*! \todo The assert may produce false positives and requires testing
- */
-int FWScript::o2_gotoIfEquNearest() {
- byte labelIdx = getNextByte();
-
- if (_compare == kCmpEQ) {
- assert(_labels[labelIdx] != -1);
-
- 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)", _line, labelIdx);
- }
- return 0;
-}
-
-/*! \todo The assert may produce false positives and requires testing
- */
-int FWScript::o2_gotoIfDiffNearest() {
- byte labelIdx = getNextByte();
-
- if (_compare != kCmpEQ) {
- assert(_labels[labelIdx] != -1);
-
- 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)", _line, labelIdx);
- }
- return 0;
-}
-
-int FWScript::o2_startObjectScript() {
- byte param = getNextByte();
-
- debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
- runObjectScript(param);
- return 0;
-}
-
-int FWScript::o2_stopObjectScript() {
- byte param = getNextByte();
-
- 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;
-}
-
-/*! \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;
-}
-
-int FWScript::o2_addBackground() {
- byte param1 = getNextByte();
- const char *param2 = getNextString();
-
- debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
- addBackground(param2, param1);
- return 0;
-}
-
-int FWScript::o2_removeBackground() {
- byte param = getNextByte();
-
- assert(param);
-
- debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
-
- if (additionalBgTable[param]) {
- free(additionalBgTable[param]);
- additionalBgTable[param] = NULL;
- }
-
- if (currentAdditionalBgIdx == param) {
- currentAdditionalBgIdx = 0;
- }
-
- if (currentAdditionalBgIdx2 == param) {
- currentAdditionalBgIdx2 = 0;
- }
-
- strcpy(currentBgName[param], "");
- return 0;
-}
-
-int FWScript::o2_loadAbs() {
- byte param1 = getNextByte();
- const char *param2 = getNextString();
-
- debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
- loadAbs(param2, param1);
- return 0;
-}
-
-int FWScript::o2_loadBg() {
- byte param = getNextByte();
-
- assert(param <= 8);
-
- 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;
-}
-
-/*! \todo Implement this instruction
- */
-int FWScript::o2_wasZoneChecked() {
- warning("STUB: o2_wasZoneChecked()");
- return 0;
-}
-
-/*! \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;
-}
-
-/*! \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;
-}
-
-int FWScript::o2_useBgScroll() {
- byte param = getNextByte();
-
- assert(param <= 8);
-
- debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
-
- if (additionalBgTable[param]) {
- currentAdditionalBgIdx2 = param;
- }
- return 0;
-}
-
-int FWScript::o2_setAdditionalBgVScroll() {
- byte param1 = getNextByte();
-
- if (param1) {
- byte param2 = getNextByte();
-
- debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
- additionalBgVScroll = _localVars[param2];
- } else {
- uint16 param2 = getNextWord();
-
- debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
- additionalBgVScroll = param2;
- }
- return 0;
-}
-
-/*! \todo Implement this instruction
- */
-int FWScript::o2_op9F() {
- warning("o2_op9F()");
- getNextWord();
- getNextWord();
- return 0;
-}
-
-int FWScript::o2_addGfxElementA0() {
- uint16 param1 = getNextWord();
- uint16 param2 = getNextWord();
-
- debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
- addGfxElementA0(param1, param2);
- return 0;
-}
-
-/*! \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;
-}
-
-/*! \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;
-}
-
-/*! \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;
-}
-
-int FWScript::o2_loadMask22() {
- byte param = getNextByte();
-
- debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
- loadOverlayElement(param, 22);
- return 0;
-}
-
-int FWScript::o2_unloadMask22() {
- byte param = getNextByte();
-
- debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
- freeOverlay(param, 22);
+ removeOverlay(param, 5);
return 0;
}
//-----------------------------------------------------------------------
-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;
-
- 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;
- }
-}
-
-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;
- }
-
- if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
- currentHead->var4 = -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;
-}
-
void palRotate(byte a, byte b, byte c) {
if (c == 1) {
uint16 currentColor = c_palette[b];
diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp
new file mode 100644
index 0000000000..1f5ea2b838
--- /dev/null
+++ b/engines/cine/script_os.cpp
@@ -0,0 +1,793 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/*! \file
+ * Operation Stealth script interpreter file
+ */
+
+#include "common/endian.h"
+
+#include "cine/cine.h"
+#include "cine/bg_list.h"
+#include "cine/object.h"
+#include "cine/sound.h"
+#include "cine/various.h"
+#include "cine/script.h"
+
+namespace Cine {
+
+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);
+
+/*! \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 *OSScriptInfo::opcodeInfo(byte opcode) const {
+ if (opcode == 0 || opcode > OSScript::_numOpcodes) {
+ return NULL;
+ }
+
+ if (!OSScript::_opcodeTable[opcode - 1].args) {
+ warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
+ return NULL;
+ }
+
+ return OSScript::_opcodeTable[opcode - 1].args;
+}
+
+/*! \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;
+ }
+
+ if (!OSScript::_opcodeTable[opcode - 1].proc) {
+ warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
+ return NULL;
+ }
+
+ return OSScript::_opcodeTable[opcode - 1].proc;
+}
+
+/*! \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);
+}
+
+/*! \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);
+}
+
+/*! \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;
+}
+
+// ------------------------------------------------------------------------
+// OPERATION STEALTH opcodes
+// ------------------------------------------------------------------------
+
+int FWScript::o2_loadPart() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
+ return 0;
+}
+
+int FWScript::o2_playSample() {
+ if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
+ // no-op in these versions
+ getNextByte();
+ getNextByte();
+ getNextWord();
+ getNextByte();
+ getNextWord();
+ getNextWord();
+ return 0;
+ }
+ return o1_playSample();
+}
+
+int FWScript::o2_playSampleAlt() {
+ byte num = getNextByte();
+ byte channel = getNextByte();
+ uint16 frequency = getNextWord();
+ getNextByte();
+ getNextWord();
+ uint16 size = getNextWord();
+
+ if (size == 0xFFFF) {
+ size = animDataTable[num]._width * animDataTable[num]._height;
+ }
+ 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].data(), size, 0, 0, 63, 0);
+ }
+ }
+ return 0;
+}
+
+int FWScript::o2_addSeqListElement() {
+ byte param1 = getNextByte();
+ byte param2 = getNextByte();
+ byte param3 = getNextByte();
+ byte param4 = getNextByte();
+ uint16 param5 = getNextWord();
+ uint16 param6 = getNextWord();
+ uint16 param7 = getNextWord();
+
+ 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;
+}
+
+int FWScript::o2_removeSeq() {
+ byte a = getNextByte();
+ byte b = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
+ removeSeq(a, 0, b);
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op81() {
+ warning("STUB: o2_op81()");
+ // freeUnkList();
+ return 0;
+}
+
+/*! \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;
+}
+
+int FWScript::o2_isSeqRunning() {
+ byte a = getNextByte();
+ byte b = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
+
+ if (isSeqRunning(a, 0, b)) {
+ _compare = 1;
+ } else {
+ _compare = 0;
+ }
+ return 0;
+}
+
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfSupNearest() {
+ byte labelIdx = getNextByte();
+
+ if (_compare == kCmpGT) {
+ assert(_labels[labelIdx] != -1);
+
+ 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)", _line, labelIdx);
+ }
+ return 0;
+}
+
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfSupEquNearest() {
+ byte labelIdx = getNextByte();
+
+ if (_compare & (kCmpGT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
+
+ 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)", _line, labelIdx);
+ }
+ return 0;
+}
+
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfInfNearest() {
+ byte labelIdx = getNextByte();
+
+ if (_compare == kCmpLT) {
+ assert(_labels[labelIdx] != -1);
+
+ 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)", _line, labelIdx);
+ }
+ return 0;
+}
+
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfInfEquNearest() {
+ byte labelIdx = getNextByte();
+
+ if (_compare & (kCmpLT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
+
+ 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)", _line, labelIdx);
+ }
+ return 0;
+}
+
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfEquNearest() {
+ byte labelIdx = getNextByte();
+
+ if (_compare == kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
+
+ 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)", _line, labelIdx);
+ }
+ return 0;
+}
+
+/*! \todo The assert may produce false positives and requires testing
+ */
+int FWScript::o2_gotoIfDiffNearest() {
+ byte labelIdx = getNextByte();
+
+ if (_compare != kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
+
+ 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)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o2_startObjectScript() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
+ runObjectScript(param);
+ return 0;
+}
+
+int FWScript::o2_stopObjectScript() {
+ byte param = getNextByte();
+
+ 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;
+}
+
+/*! \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;
+}
+
+int FWScript::o2_addBackground() {
+ byte param1 = getNextByte();
+ const char *param2 = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
+ addBackground(param2, param1);
+ return 0;
+}
+
+int FWScript::o2_removeBackground() {
+ byte param = getNextByte();
+
+ assert(param);
+
+ debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
+
+ if (additionalBgTable[param]) {
+ free(additionalBgTable[param]);
+ additionalBgTable[param] = NULL;
+ }
+
+ if (currentAdditionalBgIdx == param) {
+ currentAdditionalBgIdx = 0;
+ }
+
+ if (currentAdditionalBgIdx2 == param) {
+ currentAdditionalBgIdx2 = 0;
+ }
+
+ strcpy(currentBgName[param], "");
+ return 0;
+}
+
+int FWScript::o2_loadAbs() {
+ byte param1 = getNextByte();
+ const char *param2 = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
+ loadAbs(param2, param1);
+ return 0;
+}
+
+int FWScript::o2_loadBg() {
+ byte param = getNextByte();
+
+ assert(param <= 8);
+
+ 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;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_wasZoneChecked() {
+ warning("STUB: o2_wasZoneChecked()");
+ return 0;
+}
+
+/*! \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;
+}
+
+/*! \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;
+}
+
+int FWScript::o2_useBgScroll() {
+ byte param = getNextByte();
+
+ assert(param <= 8);
+
+ debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
+
+ if (additionalBgTable[param]) {
+ currentAdditionalBgIdx2 = param;
+ }
+ return 0;
+}
+
+int FWScript::o2_setAdditionalBgVScroll() {
+ byte param1 = getNextByte();
+
+ if (param1) {
+ byte param2 = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
+ additionalBgVScroll = _localVars[param2];
+ } else {
+ uint16 param2 = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
+ additionalBgVScroll = param2;
+ }
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o2_op9F() {
+ warning("o2_op9F()");
+ getNextWord();
+ getNextWord();
+ return 0;
+}
+
+int FWScript::o2_addGfxElementA0() {
+ uint16 param1 = getNextWord();
+ uint16 param2 = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
+ addGfxElementA0(param1, param2);
+ return 0;
+}
+
+/*! \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;
+}
+
+/*! \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;
+}
+
+/*! \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;
+}
+
+int FWScript::o2_loadMask22() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
+ addOverlay(param, 22);
+ return 0;
+}
+
+int FWScript::o2_unloadMask22() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
+ removeOverlay(param, 22);
+ return 0;
+}
+
+} // End of namespace Cine
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 38c5677569..b288cd2a47 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -44,7 +44,7 @@ int16 commandVar3[4];
int16 commandVar1;
int16 commandVar2;
-Message messageTable[NUM_MAX_MESSAGE];
+//Message messageTable[NUM_MAX_MESSAGE];
uint16 var2;
uint16 var3;
@@ -130,32 +130,16 @@ void runObjectScript(int16 entryIdx) {
objectScripts.push_back(tmp);
}
+/*! \brief Add action result message to overlay list
+ * \param cmd Message description
+ * \todo Why are x, y, width and color left uninitialized?
+ */
void addPlayerCommandMessage(int16 cmd) {
- overlayHeadElement *currentHeadPtr = overlayHead.next;
- overlayHeadElement *tempHead = &overlayHead;
- overlayHeadElement *pNewElement;
-
- while (currentHeadPtr) {
- tempHead = currentHeadPtr;
- currentHeadPtr = tempHead->next;
- }
-
- pNewElement = new overlayHeadElement;
-
- assert(pNewElement);
-
- pNewElement->next = tempHead->next;
- tempHead->next = pNewElement;
-
- pNewElement->objIdx = cmd;
- pNewElement->type = 3;
-
- if (!currentHeadPtr) {
- currentHeadPtr = &overlayHead;
- }
+ overlay tmp;
+ tmp.objIdx = cmd;
+ tmp.type = 3;
- pNewElement->previous = currentHeadPtr->previous;
- currentHeadPtr->previous = pNewElement;
+ overlayList.push_back(tmp);
}
int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
@@ -180,55 +164,64 @@ int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSel
return found;
}
+/*! \brief Find index of the object under cursor
+ * \param x Mouse cursor coordinate
+ * \param y Mouse cursor coordinate
+ * \todo Fix displaced type 1 objects
+ */
int16 getObjectUnderCursor(uint16 x, uint16 y) {
- overlayHeadElement *currentHead = overlayHead.previous;
+ Common::List<overlay>::iterator it;
int16 objX, objY, frame, part, threshold, height, xdif, ydif;
int width;
- while (currentHead) {
- if (currentHead->type < 2) {
- if (objectTable[currentHead->objIdx].name[0]) {
- objX = objectTable[currentHead->objIdx].x;
- objY = objectTable[currentHead->objIdx].y;
+ // reverse_iterator would be nice
+ for (it = overlayList.reverse_begin(); it != overlayList.end(); --it) {
+ if (it->type >= 2 || !objectTable[it->objIdx].name[0]) {
+ continue;
+ }
- frame = ABS((int16)(objectTable[currentHead->objIdx].frame));
+ objX = objectTable[it->objIdx].x;
+ objY = objectTable[it->objIdx].y;
- part = objectTable[currentHead->objIdx].part;
+ frame = ABS((int16)(objectTable[it->objIdx].frame));
+ part = objectTable[it->objIdx].part;
- if (currentHead->type == 0) {
- threshold = animDataTable[frame]._var1;
- } else {
- threshold = animDataTable[frame]._width / 2;
- }
+ if (it->type == 0) {
+ threshold = animDataTable[frame]._var1;
+ } else {
+ threshold = animDataTable[frame]._width / 2;
+ }
- height = animDataTable[frame]._height;
- width = animDataTable[frame]._realWidth;
+ height = animDataTable[frame]._height;
+ width = animDataTable[frame]._realWidth;
- xdif = x - objX;
- ydif = y - objY;
+ xdif = x - objX;
+ ydif = y - objY;
- if ((xdif >= 0) && ((threshold << 4) > xdif) && (ydif > 0) && (ydif < height)) {
- 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].data(), animDataTable[frame]._width * 4)) {
- return currentHead->objIdx;
- }
- }
- }
- }
- }
+ if ((xdif < 0) || ((threshold << 4) <= xdif) || (ydif < 0) || (ydif >= height) || !animDataTable[frame].data()) {
+ continue;
}
- currentHead = currentHead->previous;
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ if (xdif >= width) {
+ continue;
+ }
+
+ if (it->type == 0 && animDataTable[frame].getColor(xdif, ydif) != part) {
+ return it->objIdx;
+ } else if (it->type == 1 && gfxGetBit(xdif, ydif, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
+ return it->objIdx;
+ }
+ } else if (it->type == 0) { // use generated mask
+ if (gfxGetBit(xdif, ydif, animDataTable[frame].mask(), animDataTable[frame]._width)) {
+ return it->objIdx;
+ }
+ } else if (it->type == 1) { // is mask
+ if (gfxGetBit(xdif, ydif, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
+ return it->objIdx;
+ }
+ }
}
return -1;
@@ -285,38 +278,23 @@ void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) {
}
}
-void loadOverlayFromSave(Common::InSaveFile *fHandle) {
- overlayHeadElement *newElement;
- overlayHeadElement *currentHead = &overlayHead;
- overlayHeadElement *tempHead = currentHead;
-
- currentHead = tempHead->next;
-
- while (currentHead) {
- tempHead = currentHead;
- currentHead = tempHead->next;
- }
-
- newElement = new overlayHeadElement;
-
- fHandle->readUint32BE();
- fHandle->readUint32BE();
+/*! \brief Restore overlay sprites from savefile
+ * \param fHandle Savefile open for reading
+ */
+void loadOverlayFromSave(Common::InSaveFile &fHandle) {
+ overlay tmp;
- newElement->objIdx = fHandle->readUint16BE();
- newElement->type = fHandle->readUint16BE();
- newElement->x = fHandle->readSint16BE();
- newElement->y = fHandle->readSint16BE();
- newElement->width = fHandle->readSint16BE();
- newElement->color = fHandle->readSint16BE();
+ fHandle.readUint32BE();
+ fHandle.readUint32BE();
- newElement->next = tempHead->next;
- tempHead->next = newElement;
+ tmp.objIdx = fHandle.readUint16BE();
+ tmp.type = fHandle.readUint16BE();
+ tmp.x = fHandle.readSint16BE();
+ tmp.y = fHandle.readSint16BE();
+ tmp.width = fHandle.readSint16BE();
+ tmp.color = fHandle.readSint16BE();
- if (!currentHead)
- currentHead = &overlayHead;
-
- newElement->previous = currentHead->previous;
- currentHead->previous = newElement;
+ overlayList.push_back(tmp);
}
/*! \brief Savefile format tester
@@ -433,7 +411,7 @@ bool CineEngine::makeLoad(char *saveName) {
g_sound->stopMusic();
freeAnimDataTable();
- unloadAllMasks();
+ overlayList.clear();
// if (g_cine->getGameType() == Cine::GType_OS) {
// freeUnkList();
// }
@@ -444,15 +422,7 @@ bool CineEngine::makeLoad(char *saveName) {
globalScripts.clear();
relTable.clear();
scriptTable.clear();
-
- for (i = 0; i < NUM_MAX_MESSAGE; i++) {
- messageTable[i].len = 0;
-
- if (messageTable[i].ptr) {
- free(messageTable[i].ptr);
- messageTable[i].ptr = NULL;
- }
- }
+ messageTable.clear();
for (i = 0; i < NUM_MAX_OBJECT; i++) {
objectTable[i].part = 0;
@@ -599,7 +569,7 @@ bool CineEngine::makeLoad(char *saveName) {
size = fHandle->readSint16BE();
for (i = 0; i < size; i++) {
- loadOverlayFromSave(fHandle);
+ loadOverlayFromSave(*fHandle);
}
loadBgIncrustFromSave(*fHandle);
@@ -722,30 +692,19 @@ void makeSave(char *saveFileName) {
}
{
- int16 numScript = 0;
- overlayHeadElement *currentHead = overlayHead.next;
-
- while (currentHead) {
- numScript++;
- currentHead = currentHead->next;
- }
+ Common::List<overlay>::iterator it;
- fHandle->writeUint16BE(numScript);
+ fHandle->writeUint16BE(overlayList.size());
- // actual save
- currentHead = overlayHead.next;
-
- while (currentHead) {
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
fHandle->writeUint32BE(0);
fHandle->writeUint32BE(0);
- fHandle->writeUint16BE(currentHead->objIdx);
- fHandle->writeUint16BE(currentHead->type);
- fHandle->writeSint16BE(currentHead->x);
- fHandle->writeSint16BE(currentHead->y);
- fHandle->writeSint16BE(currentHead->width);
- fHandle->writeSint16BE(currentHead->color);
-
- currentHead = currentHead->next;
+ fHandle->writeUint16BE(it->objIdx);
+ fHandle->writeUint16BE(it->type);
+ fHandle->writeSint16BE(it->x);
+ fHandle->writeSint16BE(it->y);
+ fHandle->writeSint16BE(it->width);
+ fHandle->writeSint16BE(it->color);
}
}
@@ -762,30 +721,6 @@ void makeSave(char *saveFileName) {
fHandle->writeUint16BE(it->frame);
fHandle->writeUint16BE(it->part);
}
-/*
- int numBgIncrustList = 0;
- BGIncrustList *bgIncrustPtr = bgIncrustList;
-
- while (bgIncrustPtr) {
- numBgIncrustList++;
- bgIncrustPtr = bgIncrustPtr->next;
- }
-
- fHandle->writeUint16BE(numBgIncrustList);
- bgIncrustPtr = bgIncrustList;
- while (bgIncrustPtr) {
- fHandle->writeUint32BE(0); // next
- fHandle->writeUint32BE(0); // unkPtr
- fHandle->writeUint16BE(bgIncrustPtr->objIdx);
- fHandle->writeUint16BE(bgIncrustPtr->param);
- fHandle->writeUint16BE(bgIncrustPtr->x);
- fHandle->writeUint16BE(bgIncrustPtr->y);
- fHandle->writeUint16BE(bgIncrustPtr->frame);
- fHandle->writeUint16BE(bgIncrustPtr->part);
-
- bgIncrustPtr = bgIncrustPtr->next;
- }
-*/
delete fHandle;
@@ -1682,52 +1617,40 @@ uint16 executePlayerInput(void) {
return var_5E;
}
-void drawSprite(overlayHeadElement *currentOverlay, const byte *spritePtr,
- const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
- byte *ptr = NULL;
+void drawSprite(Common::List<overlay>::iterator it, const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
byte *msk = NULL;
- byte i = 0;
- uint16 si = 0;
- overlayHeadElement *pCurrentOverlay = currentOverlay;
int16 maskX, maskY, maskWidth, maskHeight;
uint16 maskSpriteIdx;
+ msk = (byte *)malloc(width * height);
+
if (g_cine->getGameType() == Cine::GType_OS) {
- drawSpriteRaw2(spritePtr, objectTable[currentOverlay->objIdx].part, width, height, page, x, y);
- return;
+ generateMask(spritePtr, msk, width * height, objectTable[it->objIdx].part);
+ } else {
+ memcpy(msk, maskPtr, width * height);
}
- while (pCurrentOverlay) {
- if (pCurrentOverlay->type == 5) {
- if (!si) {
- ptr = (byte *)malloc(width * 8 * height);
- msk = (byte *)malloc(width * 8 * height);
- si = 1;
- }
+ for (++it; it != overlayList.end(); ++it) {
+ if (it->type != 5) {
+ continue;
+ }
- maskX = objectTable[pCurrentOverlay->objIdx].x;
- maskY = objectTable[pCurrentOverlay->objIdx].y;
+ maskX = objectTable[it->objIdx].x;
+ maskY = objectTable[it->objIdx].y;
- maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame;
+ maskSpriteIdx = ABS((int16)(objectTable[it->objIdx].frame));
+
+ maskWidth = animDataTable[maskSpriteIdx]._realWidth;
+ maskHeight = animDataTable[maskSpriteIdx]._height;
+ gfxUpdateSpriteMask(msk, x, y, width, height, animDataTable[maskSpriteIdx].data(), maskX, maskY, maskWidth, maskHeight);
- 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].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
+ gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
#endif
- }
-
- pCurrentOverlay = pCurrentOverlay->next;
}
- if (si) {
- gfxDrawMaskedSprite(ptr, msk, width, height, page, x, y);
- free(ptr);
- free(msk);
- } else {
- gfxDrawMaskedSprite(spritePtr, maskPtr, width, height, page, x, y);
- }
+ gfxDrawMaskedSprite(spritePtr, msk, width, height, page, x, y);
+ free(msk);
}
int16 additionalBgVScroll = 0;
@@ -1824,18 +1747,15 @@ void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 co
}
void drawDialogueMessage(byte msgIdx, int16 x, int16 y, int16 width, int16 color) {
- const char *messagePtr = (const char *)messageTable[msgIdx].ptr;
-
- if (!messagePtr) {
- freeOverlay(msgIdx, 2);
+ if (msgIdx >= messageTable.size()) {
+ removeOverlay(msgIdx, 2);
return;
}
- _messageLen += strlen(messagePtr);
+ _messageLen += messageTable[msgIdx].size();
+ drawMessage(messageTable[msgIdx].c_str(), x, y, width, color);
- drawMessage(messagePtr, x, y, width, color);
-
- freeOverlay(msgIdx, 2);
+ removeOverlay(msgIdx, 2);
}
void drawFailureMessage(byte cmd) {
@@ -1857,161 +1777,129 @@ void drawFailureMessage(byte cmd) {
drawMessage(messagePtr, x, y, width, color);
- freeOverlay(cmd, 3);
+ removeOverlay(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;
+ uint16 width, height;
AnimData *pPart;
- overlayHeadElement *currentOverlay, *nextOverlay;
int16 x, y;
objectStruct *objPtr;
byte messageIdx;
- int16 part;
+ Common::List<overlay>::iterator it;
backupOverlayPage();
_messageLen = 0;
- currentOverlay = (&overlayHead)->next;
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ switch (it->type) {
+ case 0: // sprite
+ assert(it->objIdx < NUM_MAX_OBJECT);
- while (currentOverlay) {
- nextOverlay = currentOverlay->next;
+ objPtr = &objectTable[it->objIdx];
+ x = objPtr->x;
+ y = objPtr->y;
- switch (currentOverlay->type) {
- case 0: // sprite
- {
- assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);
-
- objPtr = &objectTable[currentOverlay->objIdx];
-
- x = objPtr->x;
- y = objPtr->y;
-
- if (objPtr->frame >= 0) {
- if (g_cine->getGameType() == Cine::GType_OS) {
- pPart = &animDataTable[objPtr->frame];
-
- partVar1 = pPart->_var1;
- partVar2 = pPart->_height;
-
- 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;
+ if (objPtr->frame < 0) {
+ continue;
+ }
- assert(part >= 0 && part <= NUM_MAX_ANIMDATA);
+ pPart = &animDataTable[objPtr->frame];
+ width = pPart->_realWidth;
+ height = pPart->_height;
- pPart = &animDataTable[objPtr->frame];
+ if (!pPart->data()) {
+ continue;
+ }
- partVar1 = pPart->_var1;
- partVar2 = pPart->_height;
+ // drawSprite ignores masks of Operation Stealth sprites
+ drawSprite(it, pPart->data(), pPart->mask(), width, height, page1Raw, x, y);
+ break;
- if (pPart->data()) {
- drawSprite(currentOverlay, pPart->data(), pPart->mask(), partVar1, partVar2, page1Raw, x, y);
- }
- }
- }
- break;
- }
case 2: // text
- {
- // gfxWaitVSync();
- // hideMouse();
+ // gfxWaitVSync();
+ // hideMouse();
- messageIdx = currentOverlay->objIdx;
- x = currentOverlay->x;
- y = currentOverlay->y;
- partVar1 = currentOverlay->width;
- partVar2 = currentOverlay->color;
+ messageIdx = it->objIdx;
+ x = it->x;
+ y = it->y;
+ width = it->width;
+ height = it->color;
- blitRawScreen(page1Raw);
+ blitRawScreen(page1Raw);
- drawDialogueMessage(messageIdx, x, y, partVar1, partVar2);
+ drawDialogueMessage(messageIdx, x, y, width, height);
- // blitScreen(page0, NULL);
- // gfxRedrawMouseCursor();
+ // blitScreen(page0, NULL);
+ // gfxRedrawMouseCursor();
- waitForPlayerClick = 1;
+ waitForPlayerClick = 1;
+
+ break;
- break;
- }
case 3:
- {
- // gfxWaitSync()
- // hideMouse();
+ // gfxWaitSync()
+ // hideMouse();
- blitRawScreen(page1Raw);
+ blitRawScreen(page1Raw);
- drawFailureMessage(currentOverlay->objIdx);
+ drawFailureMessage(it->objIdx);
- // blitScreen(page0, NULL);
- // gfxRedrawMouseCursor();
+ // blitScreen(page0, NULL);
+ // gfxRedrawMouseCursor();
- waitForPlayerClick = 1;
+ waitForPlayerClick = 1;
- break;
- }
- case 4:
- {
- assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);
-
- objPtr = &objectTable[currentOverlay->objIdx];
+ break;
- x = objPtr->x;
- y = objPtr->y;
+ case 4:
+ assert(it->objIdx < NUM_MAX_OBJECT);
+ objPtr = &objectTable[it->objIdx];
+ x = objPtr->x;
+ y = objPtr->y;
- if (objPtr->frame >= 0) {
- part = objPtr->part;
+ if (objPtr->frame < 0) {
+ continue;
+ }
- assert(part >= 0 && part <= NUM_MAX_ANIMDATA);
+ assert(objPtr->frame < NUM_MAX_ANIMDATA);
- pPart = &animDataTable[objPtr->frame];
+ pPart = &animDataTable[objPtr->frame];
- partVar1 = pPart->_width / 2;
- partVar2 = pPart->_height;
+ width = pPart->_realWidth;
+ height = pPart->_height;
- if (pPart->data()) {
- gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y);
- }
- }
- break;
+ if (!pPart->data()) {
+ continue;
}
- case 20:
- {
- assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);
- objPtr = &objectTable[currentOverlay->objIdx];
+ gfxFillSprite(pPart->data(), width, height, page1Raw, x, y);
+ break;
- x = objPtr->x;
- y = objPtr->y;
+ case 20:
+ assert(it->objIdx < NUM_MAX_OBJECT);
- var5 = currentOverlay->x;
+ objPtr = &objectTable[it->objIdx];
+ x = objPtr->x;
+ y = objPtr->y;
+ var5 = it->x;
- if (objPtr->frame >= 0 && var5 <= 8 && additionalBgTable[var5] && animDataTable[objPtr->frame]._bpp == 1) {
- int16 x2;
- int16 y2;
+ if (objPtr->frame < 0 || var5 > 8 || !additionalBgTable[var5] || animDataTable[objPtr->frame]._bpp != 1) {
+ continue;
+ }
- x2 = animDataTable[objPtr->frame]._width / 2;
- y2 = animDataTable[objPtr->frame]._height;
+ width = animDataTable[objPtr->frame]._realWidth;
+ height = animDataTable[objPtr->frame]._height;
- if (animDataTable[objPtr->frame].data()) {
- maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), x2, y2, page1Raw, x, y);
- }
- }
- break;
+ if (!animDataTable[objPtr->frame].data()) {
+ continue;
}
- }
- currentOverlay = nextOverlay;
+ maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), width, height, page1Raw, x, y);
+ break;
+ }
}
}
@@ -2040,8 +1928,7 @@ void checkForPendingDataLoad(void) {
}
if (newObjectName[0] != 0) {
- unloadAllMasks();
- resetMessageHead();
+ overlayList.clear();
loadObject(newObjectName);
@@ -2071,40 +1958,50 @@ void removeExtention(char *dest, const char *source) {
}
void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5) {
- overlayHeadElement *currentHead = &overlayHead;
- overlayHeadElement *tempHead = currentHead;
- overlayHeadElement *newElement;
+ overlay tmp;
- currentHead = tempHead->next;
+ tmp.objIdx = param1;
+ tmp.type = 2;
+ tmp.x = param2;
+ tmp.y = param3;
+ tmp.width = param4;
+ tmp.color = param5;
- while (currentHead) {
+ overlayList.push_back(tmp);
+}
+
+SeqListElement seqList;
+
+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;
}
- newElement = new overlayHeadElement;
-
- newElement->next = tempHead->next;
- tempHead->next = newElement;
-
- newElement->objIdx = param1;
- newElement->type = 2;
+ if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
+ currentHead->var4 = -1;
+ }
+}
- newElement->x = param2;
- newElement->y = param3;
- newElement->width = param4;
- newElement->color = param5;
+uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
+ SeqListElement *currentHead = &seqList;
+ SeqListElement *tempHead = currentHead;
- if (!currentHead)
- currentHead = &overlayHead;
+ while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
+ tempHead = currentHead;
+ currentHead = tempHead->next;
+ }
- newElement->previous = currentHead->previous;
+ if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
+ return 1;
+ }
- currentHead->previous = newElement;
+ return 0;
}
-SeqListElement seqList;
-
void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) {
SeqListElement *currentHead = &seqList;
SeqListElement *tempHead = currentHead;
diff --git a/engines/cine/various.h b/engines/cine/various.h
index 314a0bd24b..f906b2aa19 100644
--- a/engines/cine/various.h
+++ b/engines/cine/various.h
@@ -42,15 +42,6 @@ void makeActionMenu(void);
extern bool disableSystemMenu;
extern bool inMenu;
-struct Message {
- byte *ptr;
- uint16 len;
-};
-
-#define NUM_MAX_MESSAGE 255
-
-extern Message messageTable[NUM_MAX_MESSAGE];
-
struct SeqListElement {
struct SeqListElement *next;
int16 var4;
@@ -149,6 +140,8 @@ void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 par
extern int16 additionalBgVScroll;
+void removeSeq(uint16 param1, uint16 param2, uint16 param3);
+uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8);
void resetSeqList();
void processSeqList(void);
diff --git a/engines/cine/xref.txt b/engines/cine/xref.txt
index fd76f7eaaf..3640ef83d6 100644
--- a/engines/cine/xref.txt
+++ b/engines/cine/xref.txt
@@ -144,3 +144,10 @@ bg_list.cpp
reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and
loadBgIncrustFromSave() implementation)
freeBgIncrustList() - removed (obsoleted by Common::List::clear())
+
+object.cpp
+unloadAllMasks() - removed (obsoleted by Common::List::clear())
+resetMessageHead() - removed (obsoleted by Common::List)
+freeOverlay() - removed (duplicate of removeOverlay)
+removeOverlayElement() - renamed to removeOverlay
+loadOverlayElement() - renamed to addOverlay