diff options
-rw-r--r-- | engines/cine/anim.cpp | 1 | ||||
-rw-r--r-- | engines/cine/anim.h | 1 | ||||
-rw-r--r-- | engines/cine/bg.cpp | 6 | ||||
-rw-r--r-- | engines/cine/bg_list.cpp | 6 | ||||
-rw-r--r-- | engines/cine/cine.cpp | 6 | ||||
-rw-r--r-- | engines/cine/gfx.cpp | 135 | ||||
-rw-r--r-- | engines/cine/gfx.h | 3 | ||||
-rw-r--r-- | engines/cine/main_loop.cpp | 2 | ||||
-rw-r--r-- | engines/cine/module.mk | 3 | ||||
-rw-r--r-- | engines/cine/msg.cpp | 39 | ||||
-rw-r--r-- | engines/cine/msg.h | 6 | ||||
-rw-r--r-- | engines/cine/object.cpp | 160 | ||||
-rw-r--r-- | engines/cine/object.h | 17 | ||||
-rw-r--r-- | engines/cine/script.h | 1 | ||||
-rw-r--r-- | engines/cine/script_fw.cpp (renamed from engines/cine/script.cpp) | 870 | ||||
-rw-r--r-- | engines/cine/script_os.cpp | 793 | ||||
-rw-r--r-- | engines/cine/various.cpp | 531 | ||||
-rw-r--r-- | engines/cine/various.h | 11 | ||||
-rw-r--r-- | engines/cine/xref.txt | 7 |
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 |