aboutsummaryrefslogtreecommitdiff
path: root/engines/cine
diff options
context:
space:
mode:
Diffstat (limited to 'engines/cine')
-rw-r--r--engines/cine/anim.cpp1
-rw-r--r--engines/cine/bg.cpp96
-rw-r--r--engines/cine/bg.h15
-rw-r--r--engines/cine/bg_list.cpp60
-rw-r--r--engines/cine/bg_list.h4
-rw-r--r--engines/cine/cine.cpp12
-rw-r--r--engines/cine/gfx.cpp1396
-rw-r--r--engines/cine/gfx.h158
-rw-r--r--engines/cine/main_loop.cpp16
-rw-r--r--engines/cine/object.cpp4
-rw-r--r--engines/cine/pal.cpp62
-rw-r--r--engines/cine/pal.h8
-rw-r--r--engines/cine/prc.cpp4
-rw-r--r--engines/cine/rel.cpp4
-rw-r--r--engines/cine/script.h3
-rw-r--r--engines/cine/script_fw.cpp67
-rw-r--r--engines/cine/script_os.cpp50
-rw-r--r--engines/cine/texte.cpp92
-rw-r--r--engines/cine/texte.h2
-rw-r--r--engines/cine/various.cpp833
-rw-r--r--engines/cine/various.h16
-rw-r--r--engines/cine/xref.txt37
22 files changed, 1743 insertions, 1197 deletions
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 6edc714da7..73837308ca 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -53,6 +53,7 @@ AnimData animDataTable[NUM_MAX_ANIMDATA];
static const AnimDataEntry transparencyData[] = {
{"ALPHA", 0xF},
+ {"TITRE", 0xF},
{"TITRE2", 0xF},
{"ET", 0xC},
{"L311", 0x3},
diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp
index b6c07a05cb..c5b7fb4e3d 100644
--- a/engines/cine/bg.cpp
+++ b/engines/cine/bg.cpp
@@ -37,7 +37,7 @@ uint16 bgVar0;
byte *additionalBgTable[9];
byte currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0;
-byte loadCt(const char *ctName) {
+byte loadCtFW(const char *ctName) {
uint16 header[32];
byte *ptr, *dataPtr;
@@ -46,79 +46,62 @@ byte loadCt(const char *ctName) {
ptr = dataPtr = readBundleFile(findFileInBundle(ctName));
- if (g_cine->getGameType() == Cine::GType_OS) {
- uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
- if (bpp == 8) {
- ctColorMode = 1;
- memcpy(newPalette, ptr, 256 * 3);
- ptr += 3 * 256;
- memcpy(page3Raw, ptr, 320 * 200);
- } else {
- ctColorMode = 0;
- for (int i = 0; i < 16; i++) {
- tempPalette[i] = READ_BE_UINT16(ptr);
- ptr += 2;
- }
-
- gfxResetRawPage(page3Raw);
- gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200);
- }
- } else {
- loadRelatedPalette(ctName);
+ loadRelatedPalette(ctName);
- assert(strstr(ctName, ".NEO"));
+ assert(strstr(ctName, ".NEO"));
- Common::MemoryReadStream readS(ptr, 32);
-
- for (int i = 0; i < 16; i++) {
- header[i] = readS.readUint16BE();
- }
+ Common::MemoryReadStream readS(ptr, 32);
- gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200);
+ for (int i = 0; i < 16; i++) {
+ header[i] = readS.readUint16BE();
}
+ gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200);
+
free(dataPtr);
return 0;
}
-void loadBgHigh(const char *currentPtr) {
- memcpy(newPalette, currentPtr, 256 * 3);
- currentPtr += 256 * 3;
+byte loadCtOS(const char *ctName) {
+ byte *ptr, *dataPtr;
- memcpy(page2Raw, currentPtr, 320 * 200);
+ if (currentCtName != ctName)
+ strcpy(currentCtName, ctName);
+
+ ptr = dataPtr = readBundleFile(findFileInBundle(ctName));
- newColorMode = 2;
- bgColorMode = 1;
+ uint16 bpp = READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ if (bpp == 8) {
+ memcpy(page3Raw, ptr + 256 * 3, 320 * 200);
+ renderer->loadCt256(ptr, ctName);
+ } else {
+ gfxConvertSpriteToRaw(page3Raw, ptr + 32, 160, 200);
+ renderer->loadCt16(ptr, ctName);
+ }
+ free(dataPtr);
+ return 0;
}
byte loadBg(const char *bgName) {
byte *ptr, *dataPtr;
- if (currentBgName[0] != bgName)
- strcpy(currentBgName[0], bgName);
-
byte fileIdx = findFileInBundle(bgName);
ptr = dataPtr = readBundleFile(fileIdx);
- uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
+ uint16 bpp = READ_BE_UINT16(ptr);
+ ptr += 2;
+
if (bpp == 8) {
- loadBgHigh((const char *)ptr);
+ renderer->loadBg256(ptr, bgName);
} else {
- newColorMode = 1;
- bgColorMode = 0;
-
- for (int i = 0; i < 16; i++) {
- tempPalette[i] = READ_BE_UINT16(ptr);
- ptr += 2;
- }
-
if (g_cine->getGameType() == Cine::GType_FW) {
loadRelatedPalette(bgName);
}
- gfxResetRawPage(page2Raw);
- gfxConvertSpriteToRaw(page2Raw, ptr, 160, 200);
+ renderer->loadBg16(ptr, bgName);
}
free(dataPtr);
return 0;
@@ -127,28 +110,15 @@ byte loadBg(const char *bgName) {
void addBackground(const char *bgName, uint16 bgIdx) {
byte *ptr, *dataPtr;
- strcpy(currentBgName[bgIdx], bgName);
-
byte fileIdx = findFileInBundle(bgName);
ptr = dataPtr = readBundleFile(fileIdx);
- additionalBgTable[bgIdx] = (byte *) malloc(320 * 200);
-
uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
if (bpp == 8) {
- bgColorMode = 1;
- memcpy(newPalette, ptr, 256 * 3);
- ptr += 3 * 256;
- memcpy(additionalBgTable[bgIdx], ptr, 320 * 200);
+ renderer->loadBg256(ptr, bgName, bgIdx);
} else {
- bgColorMode = 0;
- for (int i = 0; i < 16; i++) {
- tempPalette[i] = READ_BE_UINT16(ptr);
- ptr += 2;
- }
-
- gfxConvertSpriteToRaw(additionalBgTable[bgIdx], ptr, 160, 200);
+ renderer->loadBg16(ptr, bgName, bgIdx);
}
free(dataPtr);
}
diff --git a/engines/cine/bg.h b/engines/cine/bg.h
index ca5c222131..5fa8209131 100644
--- a/engines/cine/bg.h
+++ b/engines/cine/bg.h
@@ -27,20 +27,9 @@
#define CINE_BG_H
namespace Cine {
-struct bgData {
- byte *data;
- byte colorMode;
- byte *highPalette;
- uint16 *lowPalette;
-};
-
byte loadBg(const char *bgName);
-byte loadCt(const char *bgName);
-
-//extern bgData additionalBgTable[9];
-extern byte *additionalBgTable[9];
-extern byte currentAdditionalBgIdx;
-extern byte currentAdditionalBgIdx2;
+byte loadCtFW(const char *bgName);
+byte loadCtOS(const char *bgName);
void addBackground(const char *bgName, uint16 bgIdx);
diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp
index a70733dc68..cf25f1d355 100644
--- a/engines/cine/bg_list.cpp
+++ b/engines/cine/bg_list.cpp
@@ -40,62 +40,20 @@ Common::List<BGIncrust> bgIncrustList;
/*! \brief Add masked sprite to the background
* \param objIdx Sprite description
- * \param addList Add sprite to incrust list if true
- * \todo Fix incrust objects on CT background. Always drawing incrust elements
- * on CT background breaks game zones
*/
-void addToBGList(int16 objIdx, bool addList) {
- int16 x = objectTable[objIdx].x;
- int16 y = objectTable[objIdx].y;
- int16 width = animDataTable[objectTable[objIdx].frame]._var1;
- int16 height = animDataTable[objectTable[objIdx].frame]._height;
- const byte *data = animDataTable[objectTable[objIdx].frame].data();
- const byte *mask = animDataTable[objectTable[objIdx].frame].mask();
-// int16 part = objectTable[objIdx].part;
-
- // Operation Stealth may switch among multiple backgrounds
- if (g_cine->getGameType() == GType_OS) {
- for (int i = 0; i < 8; i++) {
- if (additionalBgTable[i]) {
- drawSpriteRaw2(data, objectTable[objIdx].part, width, height, additionalBgTable[i], x, y);
- }
- }
- } else {
- drawSpriteRaw(data, mask, width, height, page2Raw, x, y);
- }
+void addToBGList(int16 objIdx) {
+ renderer->incrustSprite(objectTable[objIdx]);
- if (addList)
- createBgIncrustListElement(objIdx, 0);
+ createBgIncrustListElement(objIdx, 0);
}
/*! \brief Add filled sprite to the background
* \param objIdx Sprite description
- * \param addList Add sprite to incrust list if true
- * \todo Fix incrust objects on CT background. Always drawing incrust elements
- * on CT background breaks game zones
*/
-void addSpriteFilledToBGList(int16 objIdx, bool addList) {
- int16 x = objectTable[objIdx].x;
- int16 y = objectTable[objIdx].y;
- int16 width = animDataTable[objectTable[objIdx].frame]._realWidth;
- int16 height = animDataTable[objectTable[objIdx].frame]._height;
- const byte *data = animDataTable[objectTable[objIdx].frame].data();
-
- if (data) {
- // Operation Stealth may switch among multiple backgrounds
- if (g_cine->getGameType() == GType_OS) {
- for (int i = 0; i < 8; i++) {
- if (additionalBgTable[i]) {
- gfxFillSprite(data, width, height, additionalBgTable[i], x, y);
- }
- }
- } else {
- gfxFillSprite(data, width, height, page2Raw, x, y);
- }
- }
+void addSpriteFilledToBGList(int16 objIdx) {
+ renderer->incrustMask(objectTable[objIdx]);
- if (addList)
- createBgIncrustListElement(objIdx, 1);
+ createBgIncrustListElement(objIdx, 1);
}
/*! \brief Add new element to incrust list
@@ -115,7 +73,7 @@ void createBgIncrustListElement(int16 objIdx, int16 param) {
bgIncrustList.push_back(tmp);
}
-/*! \brief Reset var8 (probably something related to bgIncrustList
+/*! \brief Reset var8 (probably something related to bgIncrustList)
*/
void resetBgIncrustList(void) {
var8 = 0;
@@ -142,9 +100,9 @@ void loadBgIncrustFromSave(Common::InSaveFile &fHandle) {
bgIncrustList.push_back(tmp);
if (tmp.param == 0) {
- addToBGList(tmp.objIdx, false);
+ renderer->incrustSprite(objectTable[tmp.objIdx]);
} else {
- addSpriteFilledToBGList(tmp.objIdx, false);
+ renderer->incrustMask(objectTable[tmp.objIdx]);
}
}
}
diff --git a/engines/cine/bg_list.h b/engines/cine/bg_list.h
index 9ceae0acf5..1849d6ec3d 100644
--- a/engines/cine/bg_list.h
+++ b/engines/cine/bg_list.h
@@ -46,8 +46,8 @@ struct BGIncrust {
extern Common::List<BGIncrust> bgIncrustList;
extern uint32 var8;
-void addToBGList(int16 objIdx, bool addList = true);
-void addSpriteFilledToBGList(int16 idx, bool addList = true);
+void addToBGList(int16 objIdx);
+void addSpriteFilledToBGList(int16 idx);
void createBgIncrustListElement(int16 objIdx, int16 param);
void resetBgIncrustList(void);
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index 41dd9be16f..efc33fadaf 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -95,7 +95,9 @@ int CineEngine::init() {
int CineEngine::go() {
CursorMan.showMouse(true);
mainLoop(1);
- gfxDestroy();
+
+ delete renderer;
+ delete[] page3Raw;
delete g_sound;
return 0;
}
@@ -105,8 +107,14 @@ void CineEngine::initialize() {
setupOpcodes();
initLanguage(g_cine->getLanguage());
- gfxInit();
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ renderer = new OSRenderer;
+ } else {
+ renderer = new FWRenderer;
+ }
+
+ page3Raw = new byte[320 * 200];
textDataPtr = (byte *)malloc(8000);
partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer));
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 2730a92e62..e20dd46c53 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -27,6 +27,7 @@
#include "cine/bg.h"
#include "cine/bg_list.h"
#include "cine/various.h"
+#include "cine/pal.h"
#include "common/endian.h"
#include "common/system.h"
@@ -35,18 +36,8 @@
namespace Cine {
-uint16 c_palette[256];
-byte colorMode256 = 0;
-byte palette256[256 * 3];
-byte newPalette[256 * 3];
-byte newColorMode = 0;
-byte ctColorMode = 0;
-byte bgColorMode = 0;
-
-byte *screenBuffer;
-byte *page1Raw;
-byte *page2Raw;
byte *page3Raw;
+FWRenderer *renderer = NULL;
static const byte mouseCursorNormal[] = {
0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00,
@@ -96,28 +87,1189 @@ static const byte cursorPalette[] = {
0xff, 0xff, 0xff, 0xff
};
-void gfxInit() {
- screenBuffer = (byte *)malloc(320 * 200);
- page1Raw = (byte *)malloc(320 * 200);
- page2Raw = (byte *)malloc(320 * 200);
- page3Raw = (byte *)malloc(320 * 200);
- if (!screenBuffer || !page1Raw || !page2Raw || !page3Raw) {
- error("Unable to allocate offscreen buffers");
+/*! \brief Initialize renderer
+ */
+FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""),
+ _cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]),
+ _activeLowPal(NULL), _changePal(0) {
+
+ assert(_backBuffer);
+
+ memset(_backBuffer, 0, _screenSize);
+ memset(_bgName, 0, sizeof (_bgName));
+}
+
+/* \brief Destroy renderer
+ */
+FWRenderer::~FWRenderer() {
+ delete[] _background;
+ delete[] _palette;
+ delete[] _backBuffer;
+ delete[] _activeLowPal;
+}
+
+/* \brief Reset renderer state
+ */
+void FWRenderer::clear() {
+ delete[] _background;
+ delete[] _palette;
+ delete[] _activeLowPal;
+
+ _background = NULL;
+ _palette = NULL;
+ _activeLowPal = NULL;
+
+ memset(_backBuffer, 0, _screenSize);
+
+ _cmd = "";
+ _cmdY = 0;
+ _messageBg = 0;
+ _changePal = 0;
+}
+
+/*! \brief Draw 1bpp sprite using selected color
+ * \param obj Object info
+ * \param fillColor Sprite color
+ */
+void FWRenderer::fillSprite(const objectStruct &obj, uint8 color) {
+ const byte *data = animDataTable[obj.frame].data();
+ int x, y, width, height;
+
+ x = obj.x;
+ y = obj.y;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ gfxFillSprite(data, width, height, _backBuffer, x, y, color);
+}
+
+/*! \brief Draw 1bpp sprite using selected color on background
+ * \param obj Object info
+ * \param fillColor Sprite color
+ */
+void FWRenderer::incrustMask(const objectStruct &obj, uint8 color) {
+ const byte *data = animDataTable[obj.frame].data();
+ int x, y, width, height;
+
+ x = obj.x;
+ y = obj.y;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ gfxFillSprite(data, width, height, _background, x, y, color);
+}
+
+/*! \brief Draw color sprite using with external mask
+ * \param obj Object info
+ * \param mask External mask
+ */
+void FWRenderer::drawMaskedSprite(const objectStruct &obj, const byte *mask) {
+ const byte *data = animDataTable[obj.frame].data();
+ int x, y, width, height;
+
+ x = obj.x;
+ y = obj.y;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ assert(mask);
+
+ drawSpriteRaw(data, mask, width, height, _backBuffer, x, y);
+}
+
+/*! \brief Draw color sprite
+ * \param obj Object info
+ */
+void FWRenderer::drawSprite(const objectStruct &obj) {
+ const byte *mask = animDataTable[obj.frame].mask();
+ drawMaskedSprite(obj, mask);
+}
+
+/*! \brief Draw color sprite on background
+ * \param obj Object info
+ */
+void FWRenderer::incrustSprite(const objectStruct &obj) {
+ const byte *data = animDataTable[obj.frame].data();
+ const byte *mask = animDataTable[obj.frame].mask();
+ int x, y, width, height;
+
+ x = obj.x;
+ y = obj.y;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ assert(mask);
+
+ drawSpriteRaw(data, mask, width, height, _background, x, y);
+}
+
+/*! \brief Draw command box on screen
+ */
+void FWRenderer::drawCommand() {
+ unsigned int i;
+ int x = 10, y = _cmdY;
+
+ drawPlainBox(x, y, 301, 11, 0);
+ drawBorder(x - 1, y - 1, 302, 12, 2);
+
+ x += 2;
+ y += 2;
+
+ for (i = 0; i < _cmd.size(); i++) {
+ x = drawChar(_cmd[i], x, y);
+ }
+}
+
+/*! \brief Draw message in a box
+ * \param str Message to draw
+ * \param x Top left message box corner coordinate
+ * \param y Top left message box corner coordinate
+ * \param width Message box width
+ * \param color Message box background color
+ */
+void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte color) {
+ int i, tx, ty, tw;
+ int line = 0, words = 0, cw = 0;
+ int space = 0, extraSpace = 0;
+
+ drawPlainBox(x, y, width, 4, color);
+ tx = x + 4;
+ ty = str[0] ? y - 5 : y + 4;
+ tw = width - 8;
+
+ for (i = 0; str[i]; i++, line--) {
+ // Fit line of text into textbox
+ if (!line) {
+ while (str[i] == ' ') i++;
+ line = fitLine(str + i, tw, words, cw);
+
+ if ( str[i + line] != '\0' && str[i + line] != 0x7C && words) {
+ space = (tw - cw) / words;
+ extraSpace = (tw - cw) % words;
+ } else {
+ space = 5;
+ extraSpace = 0;
+ }
+
+ ty += 9;
+ drawPlainBox(x, ty, width, 9, color);
+ tx = x + 4;
+ }
+
+ // draw characters
+ if (str[i] == ' ') {
+ tx += space + extraSpace;
+
+ if (extraSpace) {
+ extraSpace = 0;
+ }
+ } else {
+ tx = drawChar(str[i], tx, ty);
+ }
+ }
+
+ ty += 9;
+ drawPlainBox(x, ty, width, 4, color);
+ drawDoubleBorder(x, y, width, ty - y + 4, 2);
+}
+
+/*! \brief Draw rectangle on screen
+ * \param x Top left corner coordinate
+ * \param y Top left corner coordinate
+ * \param width Rectangle width
+ * \param height Rectangle height
+ * \param color Fill color
+ */
+void FWRenderer::drawPlainBox(int x, int y, int width, int height, byte color) {
+ int i;
+ byte *dest = _backBuffer + y * 320 + x;
+
+ if (width < 0) {
+ x += width;
+ width = -width;
+ }
+
+ if (height < 0) {
+ y += height;
+ height = -height;
+ }
+
+ for (i = 0; i < height; i++) {
+ memset(dest + i * 320, color, width);
+ }
+}
+
+/*! \brief Draw empty rectangle
+ * \param x Top left corner coordinate
+ * \param y Top left corner coordinate
+ * \param width Rectangle width
+ * \param height Rectangle height
+ * \param color Line color
+ */
+void FWRenderer::drawBorder(int x, int y, int width, int height, byte color) {
+ drawLine(x, y, width, 1, color);
+ drawLine(x, y + height, width, 1, color);
+ drawLine(x, y, 1, height, color);
+ drawLine(x + width, y, 1, height + 1, color);
+}
+
+/*! \brief Draw empty 2 color rectangle (inner line color is black)
+ * \param x Top left corner coordinate
+ * \param y Top left corner coordinate
+ * \param width Rectangle width
+ * \param height Rectangle height
+ * \param color Outter line color
+ */
+void FWRenderer::drawDoubleBorder(int x, int y, int width, int height, byte color) {
+ drawBorder(x + 1, y + 1, width - 2, height - 2, 0);
+ drawBorder(x, y, width, height, color);
+}
+
+/*! \brief Draw text character on screen
+ * \param character Character to draw
+ * \param x Character coordinate
+ * \param y Character coordinate
+ */
+int FWRenderer::drawChar(char character, int x, int y) {
+ int width, idx;
+
+ if (character == ' ') {
+ x += 5;
+ } else if ((width = fontParamTable[character].characterWidth)) {
+ idx = fontParamTable[character].characterIdx;
+ drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y);
+ x += width + 1;
+ }
+
+ return x;
+}
+
+/*! \brief Draw Line
+ * \param x Line end coordinate
+ * \param y Line end coordinate
+ * \param width Horizontal line length
+ * \param height Vertical line length
+ * \param color Line color
+ * \note Either width or height must be equal to 1
+ */
+void FWRenderer::drawLine(int x, int y, int width, int height, byte color) {
+ // this line is a special case of rectangle ;-)
+ drawPlainBox(x, y, width, height, color);
+}
+
+/*! \brief Hide invisible parts of the sprite
+ * \param[in,out] mask Mask to be updated
+ * \param it Overlay info from overlayList
+ */
+void FWRenderer::remaskSprite(byte *mask, Common::List<overlay>::iterator it) {
+ AnimData &sprite = animDataTable[objectTable[it->objIdx].frame];
+ int x, y, width, height, idx;
+ int mx, my, mw, mh;
+
+ x = objectTable[it->objIdx].x;
+ y = objectTable[it->objIdx].y;
+ width = sprite._realWidth;
+ height = sprite._height;
+
+ for (++it; it != overlayList.end(); ++it) {
+ if (it->type != 5) {
+ continue;
+ }
+
+ idx = ABS(objectTable[it->objIdx].frame);
+ mx = objectTable[it->objIdx].x;
+ my = objectTable[it->objIdx].y;
+ mw = animDataTable[idx]._realWidth;
+ mh = animDataTable[idx]._height;
+
+ gfxUpdateSpriteMask(mask, x, y, width, height, animDataTable[idx].data(), mx, my, mw, mh);
+ }
+}
+
+/*! \brief Draw background to backbuffer
+ */
+void FWRenderer::drawBackground() {
+ assert(_background);
+ memcpy(_backBuffer, _background, _screenSize);
+}
+
+/*! \brief Draw one overlay
+ * \param it Overlay info
+ */
+void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
+ int idx, len, width;
+ objectStruct *obj;
+ AnimData *sprite;
+ byte *mask;
+
+ switch (it->type) {
+ // color sprite
+ case 0:
+ sprite = animDataTable + objectTable[it->objIdx].frame;
+ len = sprite->_realWidth * sprite->_height;
+ mask = new byte[len];
+ memcpy(mask, sprite->mask(), len);
+ remaskSprite(mask, it);
+ drawMaskedSprite(objectTable[it->objIdx], mask);
+ delete[] mask;
+ break;
+
+ // game message
+ case 2:
+ if (it->objIdx >= messageTable.size()) {
+ return;
+ }
+
+ _messageLen += messageTable[it->objIdx].size();
+ drawMessage(messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color);
+ break;
+
+ // action failure message
+ case 3:
+ idx = it->objIdx * 4 + g_cine->_rnd.getRandomNumber(3);
+ len = strlen(failureMessages[idx]);
+ _messageLen += len;
+ width = 6 * len + 20;
+ width = width > 300 ? 300 : width;
+
+ drawMessage(failureMessages[idx], (320 - width) / 2, 80, width, 4);
+ break;
+
+ // bitmap
+ case 4:
+ assert(it->objIdx < NUM_MAX_OBJECT);
+ obj = objectTable + it->objIdx;
+
+ if (obj->frame < 0) {
+ return;
+ }
+
+ if (!animDataTable[obj->frame].data()) {
+ return;
+ }
+
+ fillSprite(*obj);
+ break;
+ }
+}
+
+/*! \brief Draw overlays
+ */
+void FWRenderer::drawOverlays() {
+ Common::List<overlay>::iterator it;
+
+ for (it = overlayList.begin(); it != overlayList.end(); ++it) {
+ renderOverlay(it);
+ }
+}
+
+/*! \brief Draw another frame
+ */
+void FWRenderer::drawFrame() {
+ drawBackground();
+ drawOverlays();
+
+ if (!_cmd.empty()) {
+ drawCommand();
+ }
+
+ if (_changePal) {
+ refreshPalette();
+ }
+
+ blit();
+}
+
+/*! \brief Update screen
+ */
+void FWRenderer::blit() {
+ g_system->copyRectToScreen(_backBuffer, 320, 0, 0, 320, 200);
+}
+
+/*! \brief Set player command string
+ * \param cmd New command string
+ */
+void FWRenderer::setCommand(const char *cmd) {
+ _cmd = cmd;
+}
+
+/*! \brief Refresh current palette
+ */
+void FWRenderer::refreshPalette() {
+ int i;
+ byte pal[16*4];
+
+ assert(_activeLowPal);
+
+ for (i = 0; i < 16; i++) {
+ // This seems to match the output from DOSbox.
+ pal[i * 4 + 2] = ((_activeLowPal[i] & 0x00f) >> 0) * 32;
+ pal[i * 4 + 1] = ((_activeLowPal[i] & 0x0f0) >> 4) * 32;
+ pal[i * 4 + 0] = ((_activeLowPal[i] & 0xf00) >> 8) * 32;
+ pal[i * 4 + 3] = 0;
+ }
+
+ g_system->setPalette(pal, 0, 16);
+ _changePal = 0;
+}
+
+/*! \brief Load palette of current background
+ */
+void FWRenderer::reloadPalette() {
+ assert(_palette);
+
+ if (!_activeLowPal) {
+ _activeLowPal = new uint16[_lowPalSize];
}
- memset(page1Raw, 0, 320 * 200);
- memset(page2Raw, 0, 320 * 200);
- memset(page3Raw, 0, 320 * 200);
- memset(additionalBgTable, 0, sizeof(additionalBgTable));
- additionalBgTable[0] = page2Raw;
- additionalBgTable[8] = page3Raw;
+ assert(_activeLowPal);
+
+ memcpy(_activeLowPal, _palette, _lowPalSize * sizeof (uint16));
+ _changePal = 1;
+}
+
+/*! \brief Load background into renderer
+ * \param bg Raw background data
+ */
+void FWRenderer::loadBg16(const byte *bg, const char *name) {
+ int i;
+
+ if (!_background) {
+ _background = new byte[_screenSize];
+ }
+
+ if (!_palette) {
+ _palette = new uint16[_lowPalSize];
+ }
+
+ assert(_background && _palette);
+
+ strcpy(_bgName, name);
+
+ for (i = 0; i < _lowPalSize; i++, bg += 2) {
+ _palette[i] = READ_BE_UINT16(bg);
+ }
+
+ gfxConvertSpriteToRaw(_background, bg, 160, 200);
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::loadCt16(const byte *ct, const char *name) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::loadBg256(const byte *bg, const char *name) {
+ error("Future Wars renderer doesn't support 256 color mode");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::loadCt256(const byte *ct, const char *name) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::selectBg(unsigned int idx) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
}
-void gfxDestroy() {
- free(screenBuffer);
- free(page1Raw);
- free(page2Raw);
- free(page3Raw);
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::selectScrollBg(unsigned int idx) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::setScroll(unsigned int shift) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+/*! \brief Placeholder for Operation Stealth implementation
+ */
+void FWRenderer::removeBg(unsigned int idx) {
+ error("Future Wars renderer doesn't support multiple backgrounds");
+}
+
+void FWRenderer::saveBg(Common::OutSaveFile &fHandle) {
+ fHandle.write(_bgName, 13);
+}
+
+/*! \brief Restore active and backup palette from save
+ * \param fHandle Savefile open for reading
+ */
+void FWRenderer::restorePalette(Common::InSaveFile &fHandle) {
+ int i;
+
+ if (!_palette) {
+ _palette = new uint16[_lowPalSize];
+ }
+
+ if (!_activeLowPal) {
+ _activeLowPal = new uint16[_lowPalSize];
+ }
+
+ assert(_palette && _activeLowPal);
+
+ for (i = 0; i < _lowPalSize; i++) {
+ _activeLowPal[i] = fHandle.readUint16BE();
+ }
+
+ for (i = 0; i < _lowPalSize; i++) {
+ _palette[i] = fHandle.readUint16BE();
+ }
+
+ _changePal = 1;
+}
+
+/*! \brief Write active and backup palette to save
+ * \param fHandle Savefile open for writing
+ */
+void FWRenderer::savePalette(Common::OutSaveFile &fHandle) {
+ int i;
+
+ assert(_palette && _activeLowPal);
+
+ for (i = 0; i < _lowPalSize; i++) {
+ fHandle.writeUint16BE(_activeLowPal[i]);
+ }
+
+ for (i = 0; i < _lowPalSize; i++) {
+ fHandle.writeUint16BE(_palette[i]);
+ }
+}
+
+/*! \brief Rotate active palette
+ * \param a First color to rotate
+ * \param b Last color to rotate
+ * \param c Possibly rotation step, must be equal to 1 at the moment
+ */
+void FWRenderer::rotatePalette(int a, int b, int c) {
+ palRotate(_activeLowPal, a, b, c);
+ refreshPalette();
+}
+
+/*! \brief Copy part of backup palette to active palette and transform
+ * \param first First color to transform
+ * \param last Last color to transform
+ * \param r Red channel transformation
+ * \param g Green channel transformation
+ * \param b Blue channel transformation
+ */
+void FWRenderer::transformPalette(int first, int last, int r, int g, int b) {
+ if (!_activeLowPal) {
+ _activeLowPal = new uint16[_lowPalSize];
+ memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16));
+ }
+
+ transformPaletteRange(_activeLowPal, _palette, first, last, r, g, b);
+ refreshPalette();
+}
+
+/*! \brief Draw menu box, one item per line with possible highlight
+ * \param items Menu items
+ * \param height Item count
+ * \param x Top left menu corner coordinate
+ * \param y Top left menu corner coordinate
+ * \param width Menu box width
+ * \param selected Index of highlighted item (no highlight if less than 0)
+ */
+void FWRenderer::drawMenu(const CommandeType *items, unsigned int height, int x, int y, int width, int selected) {
+ int tx, ty, th = height * 9 + 10;
+ unsigned int i, j;
+
+ if (x + width > 319) {
+ x = 319 - width;
+ }
+
+ if (y + th > 199) {
+ y = 199 - th;
+ }
+
+ drawPlainBox(x, y, width, 4, _messageBg);
+
+ ty = y + 4;
+
+ for (i = 0; i < height; i++, ty += 9) {
+ drawPlainBox(x, ty, width, 9, (int)i == selected ? 0 : _messageBg);
+ tx = x + 4;
+
+ for (j = 0; items[i][j]; j++) {
+ tx = drawChar(items[i][j], tx, ty);
+ }
+ }
+
+ drawPlainBox(x, ty, width, 4, _messageBg);
+ drawDoubleBorder(x, y, width, ty - y + 4, 2);
+}
+
+/*! \brief Draw text input box
+ * \param info Input box message
+ * \param input Text entered in the input area
+ * \param cursor Cursor position in the input area
+ * \param x Top left input box corner coordinate
+ * \param y Top left input box corner coordinate
+ * \param width Input box width
+ */
+void FWRenderer::drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width) {
+ int i, tx, ty, tw;
+ int line = 0, words = 0, cw = 0;
+ int space = 0, extraSpace = 0;
+
+ drawPlainBox(x, y, width, 4, _messageBg);
+ tx = x + 4;
+ ty = info[0] ? y - 5 : y + 4;
+ tw = width - 8;
+
+ // input box info message
+ for (i = 0; info[i]; i++, line--) {
+ // fit line of text
+ if (!line) {
+ line = fitLine(info + i, tw, words, cw);
+
+ if ( info[i + line] != '\0' && words) {
+ space = (tw - cw) / words;
+ extraSpace = (tw - cw) % words;
+ } else {
+ space = 5;
+ extraSpace = 0;
+ }
+
+ ty += 9;
+ drawPlainBox(x, ty, width, 9, _messageBg);
+ tx = x + 4;
+ }
+
+ // draw characters
+ if (info[i] == ' ') {
+ tx += space + extraSpace;
+
+ if (extraSpace) {
+ extraSpace = 0;
+ }
+ } else {
+ tx = drawChar(info[i], tx, ty);
+ }
+ }
+
+ // input area background
+ ty += 9;
+ drawPlainBox(x, ty, width, 9, _messageBg);
+ drawPlainBox(x + 16, ty - 1, width - 32, 9, 0);
+ tx = x + 20;
+
+ // text in input area
+ for (i = 0; input[i]; i++) {
+ tx = drawChar(input[i], tx, ty);
+
+ if (cursor == i + 2) {
+ drawLine(tx, ty - 1, 1, 9, 2);
+ }
+ }
+
+ if (!input[0] || cursor == 1) {
+ drawLine(x + 20, ty - 1, 1, 9, 2);
+ }
+
+ ty += 9;
+ drawPlainBox(x, ty, width, 4, _messageBg);
+ drawDoubleBorder(x, y, width, ty - y + 4, 2);
+}
+
+/*! \brief Fade to black
+ */
+void FWRenderer::fadeToBlack() {
+ assert(_activeLowPal);
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 16; j++) {
+ _activeLowPal[j] = transformColor(_activeLowPal[j], -1, -1, -1);
+ }
+
+ refreshPalette();
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+ }
+}
+
+/*! \brief Initialize Operation Stealth renderer
+ */
+OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0),
+ _bgShift(0) {
+
+ int i;
+ for (i = 0; i < 9; i++) {
+ _bgTable[i].bg = NULL;
+ _bgTable[i].lowPal = NULL;
+ _bgTable[i].hiPal = NULL;
+ memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name));
+ }
+}
+
+/*! \brief Destroy Operation Stealth renderer
+ */
+OSRenderer::~OSRenderer() {
+ delete[] _activeHiPal;
+
+ for (int i = 0; i < 9; i++) {
+ delete[] _bgTable[i].bg;
+ delete[] _bgTable[i].lowPal;
+ delete[] _bgTable[i].hiPal;
+ }
+}
+
+/*! \brief Reset Operation Stealth renderer state
+ */
+void OSRenderer::clear() {
+ delete[] _activeHiPal;
+ _activeHiPal = NULL;
+
+ for (int i = 0; i < 9; i++) {
+ delete[] _bgTable[i].bg;
+ delete[] _bgTable[i].lowPal;
+ delete[] _bgTable[i].hiPal;
+
+ _bgTable[i].bg = NULL;
+ _bgTable[i].lowPal = NULL;
+ _bgTable[i].hiPal = NULL;
+ memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name));
+ }
+
+ _currentBg = 0;
+ _scrollBg = 0;
+ _bgShift = 0;
+
+ FWRenderer::clear();
+}
+
+/*! \brief Draw 1bpp sprite using selected color on backgrounds
+ * \param obj Object info
+ * \param fillColor Sprite color
+ */
+void OSRenderer::incrustMask(const objectStruct &obj, uint8 color) {
+ const byte *data = animDataTable[obj.frame].data();
+ int x, y, width, height, i;
+
+ x = obj.x;
+ y = obj.y;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ for (i = 0; i < 8; i++) {
+ if (!_bgTable[i].bg) {
+ continue;
+ }
+
+ gfxFillSprite(data, width, height, _bgTable[i].bg, x, y, color);
+ }
+}
+
+/*! \brief Draw color sprite
+ * \param obj Object info
+ */
+void OSRenderer::drawSprite(const objectStruct &obj) {
+ const byte *data = animDataTable[obj.frame].data();
+ int x, y, width, height, transColor;
+
+ x = obj.x;
+ y = obj.y;
+ transColor = obj.part;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ drawSpriteRaw2(data, transColor, width, height, _backBuffer, x, y);
+}
+
+/*! \brief Draw color sprite
+ * \param obj Object info
+ */
+void OSRenderer::incrustSprite(const objectStruct &obj) {
+ const byte *data = animDataTable[obj.frame].data();
+ int x, y, width, height, transColor, i;
+
+ x = obj.x;
+ y = obj.y;
+ transColor = obj.part;
+ width = animDataTable[obj.frame]._realWidth;
+ height = animDataTable[obj.frame]._height;
+
+ for (i = 0; i < 8; i++) {
+ if (!_bgTable[i].bg) {
+ continue;
+ }
+
+ drawSpriteRaw2(data, transColor, width, height, _bgTable[i].bg, x, y);
+ }
+}
+
+/*! \brief Draw text character on screen
+ * \param character Character to draw
+ * \param x Character coordinate
+ * \param y Character coordinate
+ */
+int OSRenderer::drawChar(char character, int x, int y) {
+ int width, idx;
+
+ if (character == ' ') {
+ x += 5;
+ } else if ((width = fontParamTable[character].characterWidth)) {
+ idx = fontParamTable[character].characterIdx;
+ drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
+ x += width + 1;
+ }
+
+ return x;
+}
+
+/*! \brief Draw background to backbuffer
+ */
+void OSRenderer::drawBackground() {
+ byte *main;
+
+ main = _bgTable[_currentBg].bg;
+ assert(main);
+
+ if (!_bgShift) {
+ memcpy(_backBuffer, main, _screenSize);
+ } else {
+ byte *scroll = _bgTable[_scrollBg].bg;
+ int mainShift = _bgShift * _screenWidth;
+ int mainSize = _screenSize - mainShift;
+
+ assert(scroll);
+
+ memcpy(_backBuffer, main + mainShift, mainSize);
+ memcpy(_backBuffer + mainSize, scroll, mainShift);
+ }
+}
+
+/*! \brief Draw one overlay
+ * \param it Overlay info
+ */
+void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
+ int len;
+ objectStruct *obj;
+ AnimData *sprite;
+ byte *mask;
+
+ switch (it->type) {
+ // color sprite
+ case 0:
+ sprite = animDataTable + objectTable[it->objIdx].frame;
+ len = sprite->_realWidth * sprite->_height;
+ mask = new byte[len];
+ generateMask(sprite->data(), mask, len, objectTable[it->objIdx].part);
+ remaskSprite(mask, it);
+ drawMaskedSprite(objectTable[it->objIdx], mask);
+ delete[] mask;
+ break;
+
+ // masked background
+ case 20:
+ assert(it->objIdx < NUM_MAX_OBJECT);
+ obj = objectTable + it->objIdx;
+ sprite = animDataTable + obj->frame;
+
+ if (obj->frame < 0 || it->x > 8 || !_bgTable[it->x].bg || sprite->_bpp != 1) {
+ break;
+ }
+
+ maskBgOverlay(_bgTable[it->x].bg, sprite->data(), sprite->_realWidth, sprite->_height, _backBuffer, obj->x, obj->y);
+ break;
+
+ // something else
+ default:
+ FWRenderer::renderOverlay(it);
+ break;
+ }
+}
+
+/*! \brief Refresh current palette
+ */
+void OSRenderer::refreshPalette() {
+ if (!_activeHiPal) {
+ FWRenderer::refreshPalette();
+ return;
+ }
+
+ int i;
+ byte pal[256*4];
+
+ for (i = 0; i < 256; i++) {
+ pal[i * 4 + 0] = _activeHiPal[i * 3 + 0];
+ pal[i * 4 + 1] = _activeHiPal[i * 3 + 1];
+ pal[i * 4 + 2] = _activeHiPal[i * 3 + 2];
+ pal[i * 4 + 3] = 0;
+ }
+
+ g_system->setPalette(pal, 0, 256);
+ _changePal = 0;
+}
+
+/*! \brief Load palette of current background
+ */
+void OSRenderer::reloadPalette() {
+ // selected background in plane takeoff scene has swapped colors 12
+ // and 14, shift background has it right
+ palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg];
+
+ assert(bg->lowPal || bg->hiPal);
+
+ if (bg->lowPal) {
+ if (!_activeLowPal) {
+ _activeLowPal = new uint16[_lowPalSize];
+ }
+
+ assert(_activeLowPal);
+
+ delete[] _activeHiPal;
+ _activeHiPal = NULL;
+
+ memcpy(_activeLowPal, bg->lowPal, _lowPalSize * sizeof (uint16));
+ } else {
+ if (!_activeHiPal) {
+ _activeHiPal = new byte[_hiPalSize];
+ }
+
+ assert(_activeHiPal);
+
+ delete[] _activeLowPal;
+ _activeLowPal = NULL;
+
+ memcpy(_activeHiPal, bg->hiPal, _hiPalSize);
+ }
+ _changePal = 1;
+}
+
+/*! \brief Rotate active palette
+ * \param a First color to rotate
+ * \param b Last color to rotate
+ * \param c Possibly rotation step, must be equal to 1 at the moment
+ */
+void OSRenderer::rotatePalette(int a, int b, int c) {
+ if (_activeLowPal) {
+ FWRenderer::rotatePalette(a, b, c);
+ return;
+ }
+
+ palRotate(_activeHiPal, a, b, c);
+ refreshPalette();
+}
+
+/*! \brief Copy part of backup palette to active palette and transform
+ * \param first First color to transform
+ * \param last Last color to transform
+ * \param r Red channel transformation
+ * \param g Green channel transformation
+ * \param b Blue channel transformation
+ */
+void OSRenderer::transformPalette(int first, int last, int r, int g, int b) {
+ palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg];
+
+ if (!bg->lowPal) {
+ if (!_activeHiPal) {
+ _activeHiPal = new byte[_hiPalSize];
+ memset(_activeHiPal, 0, _hiPalSize);
+ }
+
+ delete[] _activeLowPal;
+ _activeLowPal = NULL;
+
+ transformPaletteRange(_activeHiPal, bg->hiPal, first, last, r, g, b);
+ } else {
+ if (!_activeLowPal) {
+ _activeLowPal = new uint16[_lowPalSize];
+ memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16));
+ }
+
+ delete[] _activeHiPal;
+ _activeHiPal = NULL;
+
+ transformPaletteRange(_activeLowPal, bg->lowPal, first, last, r, g, b);
+ }
+
+ refreshPalette();
+}
+
+/*! \brief Load 16 color background into renderer
+ * \param bg Raw background data
+ * \param name Background filename
+ */
+void OSRenderer::loadBg16(const byte *bg, const char *name) {
+ loadBg16(bg, name, 0);
+}
+
+/*! \brief Load 16 color background into renderer
+ * \param bg Raw background data
+ * \param name Background filename
+ * \param pos Background index
+ */
+void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
+ int i;
+ assert(idx < 9);
+
+ if (!_bgTable[idx].bg) {
+ _bgTable[idx].bg = new byte[_screenSize];
+ }
+
+ if (!_bgTable[idx].lowPal) {
+ _bgTable[idx].lowPal = new uint16[_lowPalSize];
+ }
+
+ assert(_bgTable[idx].bg && _bgTable[idx].lowPal);
+
+ delete[] _bgTable[idx].hiPal;
+ _bgTable[idx].hiPal = NULL;
+
+ strcpy(_bgTable[idx].name, name);
+
+ for (i = 0; i < _lowPalSize; i++, bg += 2) {
+ _bgTable[idx].lowPal[i] = READ_BE_UINT16(bg);
+ }
+
+ gfxConvertSpriteToRaw(_bgTable[idx].bg, bg, 160, 200);
+}
+
+/*! \brief Load 16 color CT data as background into renderer
+ * \param ct Raw CT data
+ * \param name Background filename
+ */
+void OSRenderer::loadCt16(const byte *ct, const char *name) {
+ loadBg16(ct, name, 8);
+}
+
+/*! \brief Load 256 color background into renderer
+ * \param bg Raw background data
+ * \param name Background filename
+ */
+void OSRenderer::loadBg256(const byte *bg, const char *name) {
+ loadBg256(bg, name, 0);
+}
+
+/*! \brief Load 256 color background into renderer
+ * \param bg Raw background data
+ * \param name Background filename
+ * \param pos Background index
+ */
+void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) {
+ assert(idx < 9);
+
+ if (!_bgTable[idx].bg) {
+ _bgTable[idx].bg = new byte[_screenSize];
+ }
+
+ if (!_bgTable[idx].hiPal) {
+ _bgTable[idx].hiPal = new byte[_hiPalSize];
+ }
+
+ assert(_bgTable[idx].bg && _bgTable[idx].hiPal);
+
+ delete[] _bgTable[idx].lowPal;
+ _bgTable[idx].lowPal = NULL;
+
+ strcpy(_bgTable[idx].name, name);
+ memcpy(_bgTable[idx].hiPal, bg, _hiPalSize);
+ memcpy(_bgTable[idx].bg, bg + _hiPalSize, _screenSize);
+}
+
+/*! \brief Load 256 color CT data as background into renderer
+ * \param ct Raw CT data
+ * \param name Background filename
+ */
+void OSRenderer::loadCt256(const byte *ct, const char *name) {
+ loadBg256(ct, name, 8);
+}
+
+/*! \brief Select active background and load its palette
+ * \param idx Background index
+ */
+void OSRenderer::selectBg(unsigned int idx) {
+ assert(idx < 9 && _bgTable[idx].bg);
+ assert(_bgTable[idx].lowPal || _bgTable[idx].hiPal);
+
+ _currentBg = idx;
+ reloadPalette();
+}
+
+/*! \brief Select scroll background
+ * \param idx Scroll background index
+ */
+void OSRenderer::selectScrollBg(unsigned int idx) {
+ assert(idx < 9);
+
+ if (_bgTable[idx].bg) {
+ _scrollBg = idx;
+ }
+ reloadPalette();
+}
+
+/*! \brief Set background scroll
+ * \param shift Background scroll in pixels
+ */
+void OSRenderer::setScroll(unsigned int shift) {
+ assert(shift <= 200);
+
+ _bgShift = shift;
+}
+
+/*! \brief Unload background from renderer
+ * \param idx Background to unload
+ */
+void OSRenderer::removeBg(unsigned int idx) {
+ assert(idx > 0 && idx < 9);
+
+ if (_currentBg == idx) {
+ _currentBg = 0;
+ }
+
+ if (_scrollBg == idx) {
+ _scrollBg = 0;
+ }
+
+ delete[] _bgTable[idx].bg;
+ delete[] _bgTable[idx].lowPal;
+ delete[] _bgTable[idx].hiPal;
+ _bgTable[idx].bg = NULL;
+ _bgTable[idx].lowPal = NULL;
+ _bgTable[idx].hiPal = NULL;
+ memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name));
+}
+
+/*! \brief Fade to black
+ * \bug Operation Stealth sometimes seems to fade to black using
+ * transformPalette resulting in double fadeout
+ */
+void OSRenderer::fadeToBlack() {
+ if (!_activeHiPal) {
+ FWRenderer::fadeToBlack();
+ return;
+ }
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < _hiPalSize; j++) {
+ _activeHiPal[j] = CLIP(_activeHiPal[j] - 32, 0, 255);
+ }
+
+ refreshPalette();
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+ }
}
void setMouseCursor(int cursor) {
@@ -147,21 +1299,6 @@ void setMouseCursor(int cursor) {
}
}
-static uint16 transformColor(uint16 baseColor, int8 r, int8 g, int8 b) {
- int8 oriR = CLIP( (baseColor & 0x007) + r, 0, 7);
- int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7);
- int8 oriB = CLIP(((baseColor & 0x700) >> 8) + b, 0, 7);
-
- return oriR | (oriG << 4) | (oriB << 8);
-}
-
-void transformPaletteRange(byte startColor, byte stopColor, int8 r, int8 g, int8 b) {
- for (byte i = startColor; i <= stopColor; i++) {
- c_palette[i] = transformColor(tempPalette[i], b, g, r);
- }
- //gfxFlipPage(page2);
-}
-
void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
int16 i, j;
@@ -170,17 +1307,12 @@ void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *pag
destPtr += i * 320;
for (j = 0; j < width; j++) {
- if (x + j >= 0 && x + j < 320 && i + y >= 0
- && i + y < 200) {
- if (!*(spritePtr++)) {
- *(destPtr++) = fillColor;
- } else {
- destPtr++;
- }
- } else {
- destPtr++;
- spritePtr++;
+ if (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200 && !*spritePtr) {
+ *destPtr = fillColor;
}
+
+ destPtr++;
+ spritePtr++;
}
}
}
@@ -360,53 +1492,7 @@ void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h) {
}
}
-void gfxCopyRawPage(byte *source, byte *dest) {
- memcpy(dest, source, 320 * 200);
-}
-
-void gfxFlipRawPage(byte *frontBuffer) {
- byte *page = frontBuffer;
- int x, y, i;
- byte *pixels = (byte *) screenBuffer;
- byte c;
- byte pal[256 * 4];
-
- for (y = 0; y < 200; y++) {
- for (x = 0; x < 320; x++) {
- c = *(page++);
-
- if (!colorMode256) {
- c = c & 15;
- }
-
- pixels[x + 0 + y * 320] = c;
- }
- }
-
- if (colorMode256) {
- for (i = 0; i < 256; i++) {
- pal[i * 4 + 0] = palette256[i * 3 + 0];
- pal[i * 4 + 1] = palette256[i * 3 + 1];
- pal[i * 4 + 2] = palette256[i * 3 + 2];
- pal[i * 4 + 3] = 0;
- }
- g_system->setPalette(pal, 0, 256);
- } else {
- for (i = 0; i < 16; i++) {
- // This seems to match the output from DOSbox.
- pal[i * 4 + 2] = ((c_palette[i] & 0x00f) >> 0) * 32;
- pal[i * 4 + 1] = ((c_palette[i] & 0x0f0) >> 4) * 32;
- pal[i * 4 + 0] = ((c_palette[i] & 0xf00) >> 8) * 32;
- pal[i * 4 + 3] = 0;
- }
- g_system->setPalette(pal, 0, 16);
- }
-
- g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200);
-}
-
-void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height,
- byte *page, int16 x, int16 y) {
+void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y) {
int16 i, j;
// FIXME: Is it a bug if maskPtr == NULL?
@@ -417,9 +1503,8 @@ void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int1
byte *destPtr = page + x + y * 320;
destPtr += i * 320;
- for (j = 0; j < width * 8; j++) {
- if (((g_cine->getGameType() == Cine::GType_FW && (!maskPtr || !(*maskPtr))) || (g_cine->getGameType() == Cine::GType_OS)) && (x + j >= 0
- && x + j < 320 && i + y >= 0 && i + y < 200)) {
+ for (j = 0; j < width; j++) {
+ if ((!maskPtr || !(*maskPtr)) && x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200) {
*(destPtr++) = *(spritePtr++);
} else {
destPtr++;
@@ -432,21 +1517,19 @@ void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int1
}
}
-void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height,
- byte *page, int16 x, int16 y) {
+void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y) {
int16 i, j;
for (i = 0; i < height; i++) {
byte *destPtr = page + x + y * 320;
destPtr += i * 320;
- for (j = 0; j < width * 8; j++) {
- if ((*(spritePtr) != transColor) && (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200)) {
- *(destPtr++) = *(spritePtr++);
- } else {
- destPtr++;
- spritePtr++;
+ for (j = 0; j < width; j++) {
+ if ((*spritePtr != transColor) && (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200)) {
+ *destPtr = *spritePtr;
}
+ destPtr++;
+ spritePtr++;
}
}
}
@@ -499,93 +1582,4 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he
}
}
-/*! \todo Fix rendering to prevent fadein artifacts
- */
-void fadeFromBlack() {
- int i, j;
- int r, g, b, tr, tg, tb;
- if (newColorMode == 2) {
- colorMode256 = 1;
- memset(palette256, 0, 256*3);
- } else if (newColorMode == 1) {
- colorMode256 = 0;
- memset(c_palette, 0, 16 * sizeof(uint16));
- }
-
- for (i = 0; i < 8; i++ ) {
- gfxFlipRawPage(page1Raw);
- g_system->updateScreen();
- g_system->delayMillis(50);
-
- if (colorMode256) {
- for (j = 0; j < 256*3; j++) {
- r = palette256[j] + (newPalette[j] + 7) / 8;
- palette256[j] = CLIP(r, 0, (int)newPalette[j]);
- }
- } else {
- for (j = 0; j < 16; j++) {
- r = c_palette[j] & 0xf;
- g = (c_palette[j] & 0xf0) >> 4;
- b = (c_palette[j] & 0xf00) >> 8;
-
- tr = tempPalette[j] & 0xf;
- tg = (tempPalette[j] & 0xf0) >> 4;
- tb = (tempPalette[j] & 0xf00) >> 8;
-
- r = CLIP(r + (tr + 7) / 8, 0, tr);
- g = CLIP(g + (tg + 7) / 8, 0, tg);
- b = CLIP(b + (tb + 7) / 8, 0, tb);
-
- c_palette[j] = r | (g << 4) | (b << 8);
- }
-
- }
- }
-
- if (colorMode256) {
- memcpy(palette256, newPalette, 256*3);
- } else {
- memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
- }
-}
-
-void fadeToBlack() {
- for (int i = 0; i < 8; i++) {
- if (colorMode256) {
- for (int j = 0; j < 256*3; j++) {
- palette256[j] = CLIP(palette256[j] - 32, 0, 255);
- }
- } else {
- for (int j = 0; j < 16; j++) {
- c_palette[j] = transformColor(c_palette[j], -1, -1, -1);
- }
- }
- gfxFlipRawPage(page1Raw);
- g_system->updateScreen();
- g_system->delayMillis(50);
- }
-}
-
-void blitRawScreen(byte *frontBuffer) {
- gfxFlipRawPage(frontBuffer);
-}
-
-void flip(void) {
- blitRawScreen(page1Raw);
- if (fadeRequired) {
- if (newColorMode == 3) {
- newColorMode = ctColorMode + 1;
- }
-
- if (newColorMode == 2) {
- colorMode256 = 1;
- memcpy(palette256, newPalette, 256*3);
- } else {
- colorMode256 = 0;
- memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
- }
- fadeRequired = false;
- }
-}
-
} // End of namespace Cine
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 3812b52113..c63c79ac82 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -26,24 +26,158 @@
#ifndef CINE_GFX_H
#define CINE_GFX_H
+#include "common/noncopyable.h"
+#include "cine/object.h"
+
namespace Cine {
+/*! \brief Background with palette
+ */
+struct palBg {
+ byte *bg; ///< Background data
+ byte *hiPal; ///< 256 color palette
+ uint16 *lowPal; ///< 16 color palette
+ char name[15]; ///< Background filename
+};
+
+/*! \brief Future Wars renderer
+ *
+ * Screen backbuffer is not cleared between frames, you can draw menus etc.
+ * without calling drawFrame() all the time
+ */
+class FWRenderer : public Common::NonCopyable {
+private:
+ byte *_background; ///< Current background
+ char _bgName[13]; ///< Background filename
+ uint16 *_palette; ///< 16 color backup palette
+
+ Common::String _cmd; ///< Player command string
+
+protected:
+ static const int _screenSize = 320 * 200; ///< Screen size
+ static const int _screenWidth = 320; ///< Screen width
+ static const int _screenHeight = 200; ///< Screen height
+ static const int _lowPalSize = 16; ///< 16 color palette size
+
+ byte *_backBuffer; ///< Screen backbuffer
+ uint16 *_activeLowPal; ///< Active 16 color palette
+ int _changePal; ///< Load active palette to video backend on next frame
+
+ void fillSprite(const objectStruct &obj, uint8 color = 0);
+ void drawMaskedSprite(const objectStruct &obj, const byte *mask);
+ virtual void drawSprite(const objectStruct &obj);
+
+ void drawCommand();
+ void drawMessage(const char *str, int x, int y, int width, byte color);
+ void drawPlainBox(int x, int y, int width, int height, byte color);
+ void drawBorder(int x, int y, int width, int height, byte color);
+ void drawDoubleBorder(int x, int y, int width, int height, byte color);
+ virtual int drawChar(char character, int x, int y);
+ void drawLine(int x, int y, int width, int height, byte color);
+ void remaskSprite(byte *mask, Common::List<overlay>::iterator it);
+ virtual void drawBackground();
+
+ virtual void renderOverlay(const Common::List<overlay>::iterator &it);
+ void drawOverlays();
+
+public:
+ uint16 _messageBg; ///< Message box background color
+ uint16 _cmdY; ///< Player command string position on screen
+
+ FWRenderer();
+ virtual ~FWRenderer();
+
+ /*! \brief Test if renderer is ready to draw */
+ virtual bool ready() { return _background != NULL; }
+
+ virtual void clear();
+
+ void drawFrame();
+ void blit();
+ void setCommand(const char *cmd);
+
+ virtual void incrustMask(const objectStruct &obj, uint8 color = 0);
+ virtual void incrustSprite(const objectStruct &obj);
+
+ virtual void loadBg16(const byte *bg, const char *name);
+ virtual void loadBg16(const byte *bg, const char *name, unsigned int idx);
+ virtual void loadCt16(const byte *ct, const char *name);
+ virtual void loadBg256(const byte *bg, const char *name);
+ virtual void loadBg256(const byte *bg, const char *name, unsigned int idx);
+ virtual void loadCt256(const byte *ct, const char *name);
+ virtual void selectBg(unsigned int idx);
+ virtual void selectScrollBg(unsigned int idx);
+ virtual void setScroll(unsigned int shift);
+ virtual void removeBg(unsigned int idx);
+ void saveBg(Common::OutSaveFile &fHandle);
+
+ virtual void refreshPalette();
+ virtual void reloadPalette();
+ void restorePalette(Common::InSaveFile &fHandle);
+ void savePalette(Common::OutSaveFile &fHandle);
+ virtual void rotatePalette(int a, int b, int c);
+ virtual void transformPalette(int first, int last, int r, int g, int b);
+
+ void drawMenu(const CommandeType *items, unsigned int height, int x, int y, int width, int selected);
+ void drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width);
+
+ virtual void fadeToBlack();
+};
+
+/*! \brief Operation Stealth renderer
+ */
+class OSRenderer : public FWRenderer {
+private:
+ palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer
+ byte *_activeHiPal; ///< Active 256 color palette
+ unsigned int _currentBg; ///< Current background
+ unsigned int _scrollBg; ///< Current scroll background
+ unsigned int _bgShift; ///< Background shift
+
+protected:
+ static const int _hiPalSize = 256 * 3; ///< 256 color palette size
+
+ void drawSprite(const objectStruct &obj);
+ int drawChar(char character, int x, int y);
+ void drawBackground();
+ void renderOverlay(const Common::List<overlay>::iterator &it);
+
+public:
+ OSRenderer();
+ ~OSRenderer();
+
+ /*! \brief Test if renderer is ready to draw */
+ bool ready() { return _bgTable[_currentBg].bg != NULL; }
+
+ void clear();
+
+ void incrustMask(const objectStruct &obj, uint8 color = 0);
+ void incrustSprite(const objectStruct &obj);
+
+ void loadBg16(const byte *bg, const char *name);
+ void loadBg16(const byte *bg, const char *name, unsigned int idx);
+ void loadCt16(const byte *ct, const char *name);
+ void loadBg256(const byte *bg, const char *name);
+ void loadBg256(const byte *bg, const char *name, unsigned int idx);
+ void loadCt256(const byte *ct, const char *name);
+ void selectBg(unsigned int idx);
+ void selectScrollBg(unsigned int idx);
+ void setScroll(unsigned int shift);
+ void removeBg(unsigned int idx);
+
+ void refreshPalette();
+ void reloadPalette();
+ void rotatePalette(int a, int b, int c);
+ void transformPalette(int first, int last, int r, int g, int b);
+
+ void fadeToBlack();
+};
+
void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy);
-extern byte *page1Raw;
-extern byte *page2Raw;
extern byte *page3Raw;
+extern FWRenderer *renderer;
-extern uint16 c_palette[256];
-extern byte colorMode256;
-extern byte palette256[256 * 3];
-extern byte newPalette[256 * 3];
-extern byte newColorMode;
-extern byte ctColorMode;
-extern byte bgColorMode;
-
-void gfxInit();
-void gfxDestroy();
void setMouseCursor(int cursor);
void gfxCopyPage(byte *source, byte *dest);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 6042849f59..cfb828cf3c 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -182,14 +182,12 @@ int getKeyData() {
void CineEngine::mainLoop(int bootScriptIdx) {
bool playerAction;
uint16 quitFlag;
- uint16 i;
byte di;
uint16 mouseButton;
quitFlag = 0;
if (_preLoad == false) {
- resetSeqList();
resetBgIncrustList();
setTextWindow(0, 0, 20, 200);
@@ -223,17 +221,10 @@ void CineEngine::mainLoop(int bootScriptIdx) {
globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc.
}
- for (i = 0; i < 16; i++) {
- c_palette[i] = 0;
- }
-
- _paletteNeedUpdate = true;
-
strcpy(newPrcName, "");
strcpy(newRelName, "");
strcpy(newObjectName, "");
strcpy(newMsgName, "");
- strcpy(currentBgName[0], "");
strcpy(currentCtName, "");
strcpy(currentPartName, "");
@@ -257,8 +248,9 @@ void CineEngine::mainLoop(int bootScriptIdx) {
setMouseCursor(MOUSE_CURSOR_CROSS);
}
- drawOverlays();
- flip();
+ if (renderer->ready()) {
+ renderer->drawFrame();
+ }
if (waitForPlayerClick) {
playerAction = false;
@@ -289,6 +281,8 @@ void CineEngine::mainLoop(int bootScriptIdx) {
} while (mouseButton != 0);
waitForPlayerClick = 0;
+
+ removeMessages();
}
if (checkForPendingDataLoadSwitch) {
diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp
index 36f7b17a69..89d6b99592 100644
--- a/engines/cine/object.cpp
+++ b/engines/cine/object.cpp
@@ -236,6 +236,10 @@ uint16 compareObjectParam(byte objIdx, byte type, int16 value) {
return compareResult;
}
+/*! \bug In Operation Stealth, if you try to go downstairs to the sea in the
+ * location between bank and hotel, getObjectParam is called with paramIdx 16
+ * and crashes
+ */
int16 getObjectParam(uint16 objIdx, uint16 paramIdx) {
assert(objIdx <= NUM_MAX_OBJECT);
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index 9341563898..3e6f5adf40 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -28,8 +28,6 @@
namespace Cine {
-uint16 tempPalette[256];
-
uint16 palEntriesCount;
PalEntry *palPtr = NULL;
@@ -113,4 +111,64 @@ void loadRelatedPalette(const char *fileName) {
}
}
+void palRotate(uint16 *pal, byte a, byte b, byte c) {
+ assert(pal);
+
+ if (c == 1) {
+ uint16 currentColor = pal[b];
+
+ for (int i = b; i > a; i--) {
+ pal[i] = pal[i - 1];
+ }
+
+ pal[a] = currentColor;
+ }
+}
+
+void palRotate(byte *pal, byte a, byte b, byte c) {
+ assert(pal);
+
+ if (c == 1) {
+ byte currentR = pal[3 * b + 0];
+ byte currentG = pal[3 * b + 1];
+ byte currentB = pal[3 * b + 2];
+
+ for (int i = b; i > a; i--) {
+ pal[3 * i + 0] = pal[3 * (i - 1) + 0];
+ pal[3 * i + 1] = pal[3 * (i - 1) + 1];
+ pal[3 * i + 2] = pal[3 * (i - 1) + 2];
+ }
+
+ pal[3 * a + 0] = currentR;
+ pal[3 * a + 1] = currentG;
+ pal[3 * a + 2] = currentB;
+ }
+}
+
+uint16 transformColor(uint16 baseColor, int r, int g, int b) {
+ int8 oriR = CLIP( (baseColor & 0x007) + b, 0, 7);
+ int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7);
+ int8 oriB = CLIP(((baseColor & 0x700) >> 8) + r, 0, 7);
+
+ return oriR | (oriG << 4) | (oriB << 8);
+}
+
+void transformPaletteRange(uint16 *dstPal, uint16 *srcPal, int startColor, int stopColor, int r, int g, int b) {
+ assert(srcPal && dstPal);
+
+ for (int i = startColor; i <= stopColor; i++) {
+ dstPal[i] = transformColor(srcPal[i], r, g, b);
+ }
+}
+
+void transformPaletteRange(byte *dstPal, byte *srcPal, int startColor, int stopColor, int r, int g, int b) {
+ assert(srcPal && dstPal);
+
+ for (int i = startColor; i <= stopColor; i++) {
+ dstPal[3 * i + 0] = CLIP(srcPal[3 * i + 0] + r * 32, 0, 255);
+ dstPal[3 * i + 1] = CLIP(srcPal[3 * i + 1] + g * 32, 0, 255);
+ dstPal[3 * i + 2] = CLIP(srcPal[3 * i + 2] + b * 32, 0, 255);
+ }
+}
+
} // End of namespace Cine
diff --git a/engines/cine/pal.h b/engines/cine/pal.h
index da822fa1a1..70fcc0d98a 100644
--- a/engines/cine/pal.h
+++ b/engines/cine/pal.h
@@ -36,10 +36,14 @@ struct PalEntry {
void loadPal(const char *fileName);
-extern uint16 tempPalette[256];
-
void loadRelatedPalette(const char *fileName);
+void palRotate(uint16 *pal, byte a, byte b, byte c);
+void palRotate(byte *pal, byte a, byte b, byte c);
+uint16 transformColor(uint16 baseColor, int r, int g, int b);
+void transformPaletteRange(uint16 *srcPal, uint16 *dstPal, int startColor, int stopColor, int r, int g, int b);
+void transformPaletteRange(byte *srcPal, byte *dstPal, int startColor, int stopColor, int r, int g, int b);
+
} // End of namespace Cine
#endif
diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp
index 0f068a197e..402c97b1a6 100644
--- a/engines/cine/prc.cpp
+++ b/engines/cine/prc.cpp
@@ -98,10 +98,10 @@ void loadPrc(const char *pPrcName) {
char buffer[256];
for (s = 0; s < numScripts; s++) {
- if (scriptTable[s].size) {
+ if (scriptTable[s]->_size) {
sprintf(buffer, "%s_%03d.txt", pPrcName, s);
- decompileScript(scriptTable[s].ptr, scriptTable[s].stack, scriptTable[s].size, s);
+ decompileScript((const byte *)scriptTable[s]->getString(0), scriptTable[s]->_size, s);
dumpScript(buffer);
}
}
diff --git a/engines/cine/rel.cpp b/engines/cine/rel.cpp
index f550efed27..dd2d0f68b6 100644
--- a/engines/cine/rel.cpp
+++ b/engines/cine/rel.cpp
@@ -81,10 +81,10 @@ void loadRel(char *pRelName) {
char buffer[256];
for (s = 0; s < numEntry; s++) {
- if (relTable[s].size) {
+ if (relTable[s]->_size) {
sprintf(buffer, "%s_%03d.txt", pRelName, s);
- decompileScript(relTable[s].data, NULL, relTable[s].size, s);
+ decompileScript((const byte *)relTable[s]->getString(0), relTable[s]->_size, s);
dumpScript(buffer);
}
}
diff --git a/engines/cine/script.h b/engines/cine/script.h
index 4a2e7072ee..23bb179ee5 100644
--- a/engines/cine/script.h
+++ b/engines/cine/script.h
@@ -230,6 +230,7 @@ protected:
int o1_unloadMask5();
// pointers to member functions in C++ suck...
+ int o2_loadCt();
int o2_loadPart();
int o2_addSeqListElement();
int o2_removeSeq();
@@ -362,7 +363,7 @@ extern ScriptVars globalVars;
void setupOpcodes();
-void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx);
+void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx);
void dumpScript(char *dumpName);
#define OP_loadPart 0x3F
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index f833d7c30b..4f6749517e 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -41,11 +41,6 @@ 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);
-uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
-void addGfxElementA0(int16 param1, int16 param2);
-void removeGfxElementA0(int16 idx, int16 param);
const Opcode FWScript::_opcodeTable[] = {
/* 00 */
@@ -1299,7 +1294,7 @@ int FWScript::o1_loadCt() {
const char *param = getNextString();
debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
- loadCt(param);
+ loadCtFW(param);
return 0;
}
@@ -1355,31 +1350,29 @@ int FWScript::o1_blitAndFade() {
debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
// TODO: use real code
- drawOverlays();
- fadeRequired = true;
- flip();
-
// fadeFromBlack();
+
+ renderer->reloadPalette();
return 0;
}
int FWScript::o1_fadeToBlack() {
debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
- fadeToBlack();
+ renderer->fadeToBlack();
return 0;
}
int FWScript::o1_transformPaletteRange() {
byte startColor = getNextByte();
byte numColor = getNextByte();
- uint16 r = getNextWord();
- uint16 g = getNextWord();
- uint16 b = getNextWord();
+ int16 r = getNextWord();
+ int16 g = getNextWord();
+ int16 b = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
- transformPaletteRange(startColor, numColor, r, g, b);
+ renderer->transformPalette(startColor, numColor, r, g, b);
return 0;
}
@@ -1387,7 +1380,8 @@ int FWScript::o1_setDefaultMenuColor2() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
- defaultMenuBoxColor2 = param;
+
+ renderer->_messageBg = param;
return 0;
}
@@ -1397,7 +1391,8 @@ int FWScript::o1_palRotate() {
byte c = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
- palRotate(a, b, c);
+
+ renderer->rotatePalette(a, b, c);
return 0;
}
@@ -1475,11 +1470,7 @@ int FWScript::o1_compareGlobalVar() {
debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
- if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix
- _compare = 1;
- } else {
- _compare = compareVars(_globalVars[varIdx], value);
- }
+ _compare = compareVars(_globalVars[varIdx], value);
}
return 0;
@@ -1558,7 +1549,8 @@ int FWScript::o1_setDefaultMenuColor() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
- defaultMenuBoxColor = param;
+
+ renderer->_cmdY = param;
return 0;
}
@@ -1728,18 +1720,6 @@ int FWScript::o1_unloadMask5() {
//-----------------------------------------------------------------------
-void palRotate(byte a, byte b, byte c) {
- if (c == 1) {
- uint16 currentColor = c_palette[b];
-
- for (int16 i = b; i > a; i--) {
- c_palette[i] = c_palette[i - 1];
- }
-
- c_palette[a] = currentColor;
- }
-}
-
void addScriptToList0(uint16 idx) {
ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
assert(tmp);
@@ -1863,14 +1843,13 @@ const char *getObjPramName(byte paramIdx) {
}
}
-void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx) {
+void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx) {
char lineBuffer[256];
- byte *localScriptPtr = scriptPtr;
+ const byte *localScriptPtr = scriptPtr;
uint16 exitScript;
uint32 position = 0;
assert(scriptPtr);
- // assert(stackPtr);
exitScript = 0;
@@ -2292,7 +2271,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position);
}
- position += strlen((char *)localScriptPtr + position) + 1;
+ position += strlen((const char *)localScriptPtr + position) + 1;
break;
}
case 0x40:
@@ -2309,7 +2288,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position);
- position += strlen((char *)localScriptPtr + position) + 1;
+ position += strlen((const char *)localScriptPtr + position) + 1;
break;
}
case OP_requestCheckPendingDataLoad: // nop
@@ -2461,7 +2440,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
{
sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position);
- position += strlen((char *)localScriptPtr + position);
+ position += strlen((const char *)localScriptPtr + position);
break;
}
case 0x5A:
@@ -2540,7 +2519,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
{
sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position);
- position += strlen((char *)localScriptPtr + position) + 1;
+ position += strlen((const char *)localScriptPtr + position) + 1;
break;
}
case 0x6E: // nop
@@ -2801,7 +2780,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position);
- position += strlen((char *)localScriptPtr + position);
+ position += strlen((const char *)localScriptPtr + position);
break;
}
@@ -2825,7 +2804,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16
sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position);
- position += strlen((char *)localScriptPtr + position);
+ position += strlen((const char *)localScriptPtr + position);
break;
}
diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp
index 1f5ea2b838..36eda007c6 100644
--- a/engines/cine/script_os.cpp
+++ b/engines/cine/script_os.cpp
@@ -116,7 +116,7 @@ const Opcode OSScript::_opcodeTable[] = {
{ &FWScript::o1_loadAnim, "s" },
/* 3C */
{ &FWScript::o1_loadBg, "s" },
- { &FWScript::o1_loadCt, "s" },
+ { &FWScript::o2_loadCt, "s" },
{ 0, 0 },
{ &FWScript::o2_loadPart, "s" },
/* 40 */
@@ -365,6 +365,14 @@ FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const
// OPERATION STEALTH opcodes
// ------------------------------------------------------------------------
+int FWScript::o2_loadCt() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
+ loadCtOS(param);
+ return 0;
+}
+
int FWScript::o2_loadPart() {
const char *param = getNextString();
@@ -615,20 +623,7 @@ int FWScript::o2_removeBackground() {
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], "");
+ renderer->removeBg(param);
return 0;
}
@@ -644,22 +639,11 @@ int FWScript::o2_loadAbs() {
int FWScript::o2_loadBg() {
byte param = getNextByte();
- assert(param <= 8);
+ assert(param < 9);
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;
- }
+ renderer->selectBg(param);
return 0;
}
@@ -699,13 +683,11 @@ int FWScript::o2_op9C() {
int FWScript::o2_useBgScroll() {
byte param = getNextByte();
- assert(param <= 8);
+ assert(param < 9);
debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
- if (additionalBgTable[param]) {
- currentAdditionalBgIdx2 = param;
- }
+ renderer->selectScrollBg(param);
return 0;
}
@@ -716,12 +698,12 @@ int FWScript::o2_setAdditionalBgVScroll() {
byte param2 = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
- additionalBgVScroll = _localVars[param2];
+ renderer->setScroll(_localVars[param2]);
} else {
uint16 param2 = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
- additionalBgVScroll = param2;
+ renderer->setScroll(param2);
}
return 0;
}
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index e41626cad1..91a209074d 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -611,65 +611,49 @@ void freePoldatDat() {
fontParamTable = 0;
}
-uint16 computeMessageLength(const byte *ptr, uint16 width, uint16 *numWords, uint16 *messageWidth, uint16 *lineResult) {
- const byte *localPtr = ptr;
-
- uint16 var_2 = 0;
- uint16 localLineResult = 0;
- uint16 var_6 = 0;
- uint16 var_8 = 0;
- uint16 localMessageWidth = 0;
- uint16 var_16 = 0;
- uint16 finished = 0;
- uint16 si = 0;
- uint16 di = 0;
-
- while (!finished) {
- byte character = *(localPtr++);
-
- if (character == ' ') {
- var_8 = var_16;
- var_6 = localMessageWidth;
- localLineResult = si;
- var_2 = di;
-
- if (si + 5 < width) {
- var_16++;
- si += 5;
- } else {
- finished = 1;
- }
- } else if (character == 0x7C || character == 0) {
- finished = 1;
- si = 0;
+/*! \brief Fit a substring of text into one line of fixed width text box
+ * \param str Text to fit
+ * \param maxWidth Text box width
+ * \param[out] words Number of words that fit
+ * \param[out] width Total width of nonblank characters that fit
+ * \return Length of substring which fits
+ */
+int fitLine(const char *str, int maxWidth, int &words, int &width) {
+ int i, bkpWords = 0, bkpWidth = 0, bkpLen = 0;
+ int charWidth = 0, fullWidth = 0;
+
+ words = 0;
+ width = 0;
+
+ for (i = 0; str[i]; i++) {
+ if (str[i] == 0x7C) {
+ i++;
+ break;
+ } else if (str[i] == ' ') {
+ charWidth = 5;
+ bkpWords = words++;
+ bkpWidth = width;
+ bkpLen = i + 1;
} else {
- if (fontParamTable[character].characterWidth) {
- uint16 var_C = fontParamTable[character].characterWidth + 1;
-
- if (si + var_C < width) {
- si += var_C;
- localMessageWidth += var_C;
- } else {
- finished = 1;
-
- if (localLineResult) {
- var_16 = var_8;
- localMessageWidth = var_6;
- si = localLineResult;
- di = var_2;
- }
- }
- }
+ charWidth = fontParamTable[str[i]].characterWidth + 1;
+ width += charWidth;
}
- di++;
- }
+ if (!charWidth) {
+ continue;
+ }
- *numWords = var_16;
- *messageWidth = localMessageWidth;
- *lineResult = si;
+ if (fullWidth + charWidth < maxWidth) {
+ fullWidth += charWidth;
+ } else if (fullWidth) {
+ words = bkpWords;
+ width = bkpWidth;
+ i = bkpLen;
+ break;
+ }
+ }
- return di;
+ return i;
}
} // End of namespace Cine
diff --git a/engines/cine/texte.h b/engines/cine/texte.h
index b5eaef9211..ae82832aea 100644
--- a/engines/cine/texte.h
+++ b/engines/cine/texte.h
@@ -56,7 +56,7 @@ void freeErrmessDat(void);
void loadPoldatDat(const char *fname);
void freePoldatDat(void);
-uint16 computeMessageLength(const byte *ptr, uint16 width, uint16 *numWords, uint16 *messageWidth, uint16 *lineResult);
+int fitLine(const char *ptr, int maxWidth, int &words, int &width);
} // End of namespace Cine
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index a6bd9964c0..9b98ddb253 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -87,7 +87,6 @@ char newPrcName[20];
char newRelName[20];
char newObjectName[20];
char newMsgName[20];
-char currentBgName[8][15];
char currentCtName[15];
char currentPartName[15];
char currentDatName[30];
@@ -96,8 +95,6 @@ int16 saveVar2;
byte isInPause = 0;
-uint16 defaultMenuBoxColor;
-
byte inputVar1 = 0;
uint16 inputVar2 = 0, inputVar3 = 0;
@@ -114,7 +111,6 @@ CommandeType objectListCommand[20];
int16 objListTab[20];
uint16 exitEngine;
-uint16 defaultMenuBoxColor2;
uint16 zoneData[NUM_MAX_ZONE];
@@ -140,6 +136,7 @@ void addPlayerCommandMessage(int16 cmd) {
tmp.type = 3;
overlayList.push_back(tmp);
+ waitForPlayerClick = 1;
}
int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
@@ -393,11 +390,14 @@ bool brokenSave(Common::InSaveFile &fHandle) {
return broken;
}
+/*! \todo Implement Operation Stealth loading, this is obviously Future Wars only
+ */
bool CineEngine::makeLoad(char *saveName) {
int16 i;
int16 size;
bool broken;
Common::InSaveFile *fHandle;
+ char bgName[13];
fHandle = g_saveFileMan->openForLoading(saveName);
@@ -440,7 +440,6 @@ bool CineEngine::makeLoad(char *saveName) {
strcpy(newRelName, "");
strcpy(newObjectName, "");
strcpy(newMsgName, "");
- strcpy(currentBgName[0], "");
strcpy(currentCtName, "");
allowPlayerInput = 0;
@@ -455,9 +454,7 @@ bool CineEngine::makeLoad(char *saveName) {
fadeRequired = false;
- for (i = 0; i < 16; i++) {
- c_palette[i] = 0;
- }
+ renderer->clear();
checkForPendingDataLoadSwitch = 0;
@@ -473,7 +470,7 @@ bool CineEngine::makeLoad(char *saveName) {
fHandle->read(currentPrcName, 13);
fHandle->read(currentRelName, 13);
fHandle->read(currentMsgName, 13);
- fHandle->read(currentBgName[0], 13);
+ fHandle->read(bgName, 13);
fHandle->read(currentCtName, 13);
checkDataDisk(currentDisk);
@@ -490,12 +487,12 @@ bool CineEngine::makeLoad(char *saveName) {
loadRel(currentRelName);
}
- if (strlen(currentBgName[0])) {
- loadBg(currentBgName[0]);
+ if (strlen(bgName)) {
+ loadBg(bgName);
}
if (strlen(currentCtName)) {
- loadCt(currentCtName);
+ loadCtFW(currentCtName);
}
fHandle->readUint16BE();
@@ -511,13 +508,7 @@ bool CineEngine::makeLoad(char *saveName) {
objectTable[i].part = fHandle->readUint16BE();
}
- for (i = 0; i < 16; i++) {
- c_palette[i] = fHandle->readUint16BE();
- }
-
- for (i = 0; i < 16; i++) {
- tempPalette[i] = fHandle->readUint16BE();
- }
+ renderer->restorePalette(*fHandle);
globalVars.load(*fHandle, NUM_MAX_VAR - 1);
@@ -530,8 +521,10 @@ bool CineEngine::makeLoad(char *saveName) {
}
fHandle->read(commandBuffer, 0x50);
+ renderer->setCommand(commandBuffer);
+
+ renderer->_cmdY = fHandle->readUint16BE();
- defaultMenuBoxColor = fHandle->readUint16BE();
bgVar0 = fHandle->readUint16BE();
allowPlayerInput = fHandle->readUint16BE();
playerCommand = fHandle->readSint16BE();
@@ -542,7 +535,8 @@ bool CineEngine::makeLoad(char *saveName) {
var3 = fHandle->readUint16BE();
var2 = fHandle->readUint16BE();
commandVar2 = fHandle->readSint16BE();
- defaultMenuBoxColor2 = fHandle->readUint16BE();
+
+ renderer->_messageBg = fHandle->readUint16BE();
fHandle->readUint16BE();
fHandle->readUint16BE();
@@ -615,7 +609,7 @@ void makeSave(char *saveFileName) {
fHandle->write(currentPrcName, 13);
fHandle->write(currentRelName, 13);
fHandle->write(currentMsgName, 13);
- fHandle->write(currentBgName[0], 13);
+ renderer->saveBg(*fHandle);
fHandle->write(currentCtName, 13);
fHandle->writeUint16BE(0xFF);
@@ -631,13 +625,7 @@ void makeSave(char *saveFileName) {
fHandle->writeUint16BE(objectTable[i].part);
}
- for (i = 0; i < 16; i++) {
- fHandle->writeUint16BE(c_palette[i]);
- }
-
- for (i = 0; i < 16; i++) {
- fHandle->writeUint16BE(tempPalette[i]);
- }
+ renderer->savePalette(*fHandle);
globalVars.save(*fHandle, NUM_MAX_VAR - 1);
@@ -651,7 +639,8 @@ void makeSave(char *saveFileName) {
fHandle->write(commandBuffer, 0x50);
- fHandle->writeUint16BE(defaultMenuBoxColor);
+ fHandle->writeUint16BE(renderer->_cmdY);
+
fHandle->writeUint16BE(bgVar0);
fHandle->writeUint16BE(allowPlayerInput);
fHandle->writeUint16BE(playerCommand);
@@ -662,7 +651,8 @@ void makeSave(char *saveFileName) {
fHandle->writeUint16BE(var3);
fHandle->writeUint16BE(var2);
fHandle->writeUint16BE(commandVar2);
- fHandle->writeUint16BE(defaultMenuBoxColor2);
+
+ fHandle->writeUint16BE(renderer->_messageBg);
fHandle->writeUint16BE(0xFF);
fHandle->writeUint16BE(0x1E);
@@ -864,26 +854,6 @@ void CineEngine::makeSystemMenu(void) {
}
}
-int drawChar(byte character, int16 x, int16 y) {
- if (character == ' ') {
- x += 5;
- } else {
- byte characterWidth = fontParamTable[character].characterWidth;
-
- if (characterWidth) {
- byte characterIdx = fontParamTable[character].characterIdx;
- if (g_cine->getGameType() == Cine::GType_OS) {
- drawSpriteRaw2(textTable[characterIdx][0], 0, 2, 8, page1Raw, x, y);
- } else {
- drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y);
- }
- x += characterWidth + 1;
- }
- }
-
- return x;
-}
-
void drawMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 offset, int16 color, byte* page) {
gfxDrawLine(x + offset, y + offset, x + width - offset, y + offset, color, page); // top
gfxDrawLine(x + offset, currentY + 4 - offset, x + width - offset, currentY + 4 - offset, color, page); // bottom
@@ -896,49 +866,6 @@ void drawDoubleMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 c
drawMessageBox(x, y, width, currentY, 0, color, page);
}
-void makeTextEntry(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width) {
- byte color = 2;
- byte color2 = defaultMenuBoxColor2;
- int16 paramY = (height * 9) + 10;
- int16 currentX, currentY;
- int16 i;
- uint16 j;
- byte currentChar;
-
- if (X + width > 319) {
- X = 319 - width;
- }
-
- if (Y + paramY > 199) {
- Y = 199 - paramY;
- }
-
- hideMouse();
- blitRawScreen(page1Raw);
-
- gfxDrawPlainBoxRaw(X, Y, X + width, Y + 4, color2, page1Raw);
-
- currentX = X + 4;
- currentY = Y + 4;
-
- for (i = 0; i < height; i++) {
- gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 9, color2, page1Raw);
- currentX = X + 4;
-
- for (j = 0; j < strlen(commandList[i]); j++) {
- currentChar = commandList[i][j];
- currentX = drawChar(currentChar, currentX, currentY);
- }
-
- currentY += 9;
- }
-
- gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 4, color2, page1Raw); // bottom part
- drawDoubleMessageBox(X, Y, width, currentY, color, page1Raw);
-
- blitRawScreen(page1Raw);
-}
-
void processInventory(int16 x, int16 y) {
int16 listSize = buildObjectListCommand(-2);
uint16 button;
@@ -946,7 +873,8 @@ void processInventory(int16 x, int16 y) {
if (!listSize)
return;
- makeTextEntry(objectListCommand, listSize, x, y, 140);
+ renderer->drawMenu(objectListCommand, listSize, x, y, 140, -1);
+ renderer->blit();
do {
manageEvents();
@@ -1085,7 +1013,7 @@ void makeCommandLine(void) {
}
if (!disableSystemMenu) {
- isDrawCommandEnabled = 1;
+ renderer->setCommand(commandBuffer);
}
}
@@ -1094,13 +1022,8 @@ uint16 needMouseSave = 0;
uint16 menuVar4 = 0;
uint16 menuVar5 = 0;
-int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y,
- uint16 width, bool recheckValue) {
- byte color = 2;
- byte color2 = defaultMenuBoxColor2;
+int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width, bool recheckValue) {
int16 paramY;
- int16 currentX, currentY;
- int16 i;
uint16 button;
int16 var_A;
int16 di;
@@ -1110,7 +1033,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
int16 var_14;
int16 currentSelection, oldSelection;
int16 var_4;
- byte currentChar;
if (disableSystemMenu)
return -1;
@@ -1125,30 +1047,8 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
Y = 199 - paramY;
}
- hideMouse();
- blitRawScreen(page1Raw);
-
- gfxDrawPlainBoxRaw(X, Y, X + width, Y + 4, color2, page1Raw);
-
- currentX = X + 4;
- currentY = Y + 4;
-
- for (i = 0; i < height; i++) {
- gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 9, color2, page1Raw);
- currentX = X + 4;
-
- for (j = 0; j < strlen(commandList[i]); j++) {
- currentChar = commandList[i][j];
- currentX = drawChar(currentChar, currentX, currentY);
- }
-
- currentY += 9;
- }
-
- gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 4, color2, page1Raw); // bottom part
- drawDoubleMessageBox(X, Y, width, currentY, color, page1Raw);
-
- blitRawScreen(page1Raw);
+ renderer->drawMenu(commandList, height, X, Y, width, -1);
+ renderer->blit();
do {
manageEvents();
@@ -1160,15 +1060,9 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
currentSelection = 0;
di = currentSelection * 9 + Y + 4;
- gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, 0, page1Raw); // draw black box behind selection
- currentX = X + 4;
-
- for (j = 0; j < strlen(commandList[currentSelection]); j++) {
- currentChar = commandList[currentSelection][j];
- currentX = drawChar(currentChar, currentX, di);
- }
- blitRawScreen(page1Raw);
+ renderer->drawMenu(commandList, height, X, Y, width, currentSelection);
+ renderer->blit();
manageEvents();
getMouseData(mouseUpdateStatus, &button, (uint16 *)&mouseX, (uint16 *)&mouseY);
@@ -1219,29 +1113,10 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
hideMouse();
}
- di = oldSelection * 9 + Y + 4;
-
- gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, color2, page1Raw); // restore color
-
- currentX = X + 4;
-
- for (j = 0; j < strlen(commandList[oldSelection]); j++) {
- currentChar = commandList[oldSelection][j];
- currentX = drawChar(currentChar, currentX, di);
- }
-
di = currentSelection * 9 + Y + 4;
- gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, 0, page1Raw); // black new
-
- currentX = X + 4;
-
- for (j = 0; j < strlen(commandList[currentSelection]); j++) {
- currentChar = commandList[currentSelection][j];
- currentX = drawChar(currentChar, currentX, di);
- }
-
- blitRawScreen(page1Raw);
+ renderer->drawMenu(commandList, height, X, Y, width, currentSelection);
+ renderer->blit();
// if (needMouseSave) {
// gfxRedrawMouseCursor();
@@ -1271,38 +1146,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
return currentSelection;
}
-void drawMenuBox(char *command, int16 x, int16 y) {
- byte j;
- byte lColor = 2;
-
- hideMouse();
-
- gfxDrawPlainBoxRaw(x, y, x + 300, y + 10, 0, page2Raw);
-
- drawMessageBox(x, y, 300, y + 6, -1, lColor, page2Raw);
-
- x += 2;
- y += 2;
-
- for (j = 0; j < strlen(command); j++) {
- byte currentChar = command[j];
-
- if (currentChar == ' ') {
- x += 5;
- } else {
- byte characterWidth = fontParamTable[currentChar].characterWidth;
-
- if (characterWidth) {
- byte characterIdx = fontParamTable[currentChar].characterIdx;
- drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page2Raw, x, y);
- x += characterWidth + 1;
- }
- }
- }
-
-// gfxRedrawMouseCursor();
-}
-
void makeActionMenu(void) {
uint16 mouseButton;
uint16 mouseX;
@@ -1342,11 +1185,6 @@ uint16 executePlayerInput(void) {
}
if (allowPlayerInput) {
- if (isDrawCommandEnabled) {
- drawMenuBox(commandBuffer, 10, defaultMenuBoxColor);
- isDrawCommandEnabled = 0;
- }
-
getMouseData(mouseUpdateStatus, &mouseButton, &mouseX, &mouseY);
while (mouseButton && currentEntry < 200) {
@@ -1393,7 +1231,6 @@ uint16 executePlayerInput(void) {
if (choiceResultTable[playerCommand] == commandVar1) {
int16 relEntry;
- drawMenuBox(commandBuffer, 10, defaultMenuBoxColor);
SelectedObjStruct obj;
obj.idx = commandVar3[0];
obj.param = commandVar3[1];
@@ -1410,41 +1247,40 @@ uint16 executePlayerInput(void) {
commandVar1 = 0;
strcpy(commandBuffer, "");
+ renderer->setCommand("");
}
} else {
globalVars[VAR_MOUSE_X_POS] = mouseX;
globalVars[VAR_MOUSE_Y_POS] = mouseY;
}
}
- } else {
- if (mouseButton & 2) {
- if (mouseButton & 1) {
- g_cine->makeSystemMenu();
- }
+ } else if (mouseButton & 2) {
+ if (mouseButton & 1) {
+ g_cine->makeSystemMenu();
+ }
- makeActionMenu();
- makeCommandLine();
- } else {
- int16 objIdx;
+ makeActionMenu();
+ makeCommandLine();
+ } else {
+ int16 objIdx;
- objIdx = getObjectUnderCursor(mouseX, mouseY);
+ objIdx = getObjectUnderCursor(mouseX, mouseY);
- if (commandVar2 != objIdx) {
- if (objIdx != -1) {
- char command[256];
+ if (commandVar2 != objIdx) {
+ if (objIdx != -1) {
+ char command[256];
- strcpy(command, commandBuffer);
- strcat(command, " ");
- strcat(command, objectTable[objIdx].name);
+ strcpy(command, commandBuffer);
+ strcat(command, " ");
+ strcat(command, objectTable[objIdx].name);
- drawMenuBox(command, 10, defaultMenuBoxColor);
- } else {
- isDrawCommandEnabled = 1;
- }
+ renderer->setCommand(command);
+ } else {
+ isDrawCommandEnabled = 1;
}
-
- commandVar2 = objIdx;
}
+
+ commandVar2 = objIdx;
}
} else {
if (mouseButton & 2) {
@@ -1653,257 +1489,9 @@ void drawSprite(Common::List<overlay>::iterator it, const byte *spritePtr, const
free(msk);
}
-int16 additionalBgVScroll = 0;
-
-void backupOverlayPage(void) {
- byte *scrollBg;
- byte *bgPage = additionalBgTable[currentAdditionalBgIdx];
-
- if (bgPage) {
- if (!additionalBgVScroll) {
- memcpy(page1Raw, bgPage, 320 * 200);
- } else {
- scrollBg = additionalBgTable[currentAdditionalBgIdx2];
-
- for (int16 i = additionalBgVScroll; i < 200 + additionalBgVScroll; i++) {
- if (i > 200) {
- memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320);
- } else {
- memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320);
- }
- }
- }
- }
-}
-
-void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 color) {
- byte color2 = 2;
- byte endOfMessageReached = 0;
- int16 localX, localY, localWidth;
- uint16 messageLength = 0, numWords = 0, messageWidth = 0;
- uint16 lineResult, fullLineWidth;
- uint16 interWordSize, interWordSizeRemain;
- const char *endOfMessagePtr;
- byte currentChar; //, characterWidth;
-
- gfxDrawPlainBoxRaw(x, y, x + width, y + 4, color, page1Raw);
-
- localX = x + 4;
- localY = y + 4;
- localWidth = width - 8;
-
- do {
- messageLength = 0;
-
- while (messagePtr[messageLength] == ' ') {
- messageLength++;
- }
-
- messagePtr += messageLength;
-
- messageLength = computeMessageLength((const byte *)messagePtr, localWidth, &numWords, &messageWidth, &lineResult);
-
- endOfMessagePtr = messagePtr + messageLength;
-
- if (lineResult) {
- fullLineWidth = localWidth - messageWidth;
-
- if (numWords) {
- interWordSize = fullLineWidth / numWords;
- interWordSizeRemain = fullLineWidth % numWords;
- } else {
- interWordSize = 5;
- interWordSizeRemain = 0;
- }
- } else {
- interWordSize = 5;
- interWordSizeRemain = 0;
- }
-
- gfxDrawPlainBoxRaw(x, localY, x + width, localY + 9, color, page1Raw);
-
- do {
- currentChar = *(messagePtr++);
-
- if (currentChar == 0) {
- endOfMessageReached = 1;
- } else if (currentChar == ' ') {
- localX += interWordSizeRemain + interWordSize;
-
- if (interWordSizeRemain)
- interWordSizeRemain = 0;
- } else {
- localX = drawChar(currentChar, localX, localY);
- }
- } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached);
-
- localX = x + 4;
- localY += 9;
- } while (!endOfMessageReached);
-
- gfxDrawPlainBoxRaw(x, localY, x + width, localY + 4, color, page1Raw);
-
- drawDoubleMessageBox(x, y, width, localY, color2, page1Raw);
-}
-
-void drawDialogueMessage(byte msgIdx, int16 x, int16 y, int16 width, int16 color) {
- if (msgIdx >= messageTable.size()) {
-// removeOverlay(msgIdx, 2);
- return;
- }
-
- _messageLen += messageTable[msgIdx].size();
- drawMessage(messageTable[msgIdx].c_str(), x, y, width, color);
-
- // this invalidates the iterator in drawOverlays()
-// removeOverlay(msgIdx, 2);
-}
-
-void drawFailureMessage(byte cmd) {
- byte msgIdx = cmd * 4 + g_cine->_rnd.getRandomNumber(3);
-
- const char *messagePtr = failureMessages[msgIdx];
- int len = strlen(messagePtr);
-
- _messageLen += len;
-
- int16 width = 6 * len + 20;
-
- if (width > 300)
- width = 300;
-
- int16 x = (320 - width) / 2;
- int16 y = 80;
- int16 color = 4;
-
- drawMessage(messagePtr, x, y, width, color);
-
- // this invalidates the iterator in drawOverlays()
-// removeOverlay(cmd, 3);
-}
-
-void drawOverlays(void) {
- uint16 width, height;
- AnimData *pPart;
- int16 x, y;
- objectStruct *objPtr;
- byte messageIdx;
+void removeMessages() {
Common::List<overlay>::iterator it;
- backupOverlayPage();
-
- _messageLen = 0;
-
- for (it = overlayList.begin(); it != overlayList.end(); ++it) {
- switch (it->type) {
- case 0: // sprite
- assert(it->objIdx < NUM_MAX_OBJECT);
-
- objPtr = &objectTable[it->objIdx];
- x = objPtr->x;
- y = objPtr->y;
-
- if (objPtr->frame < 0) {
- continue;
- }
-
- pPart = &animDataTable[objPtr->frame];
- width = pPart->_realWidth;
- height = pPart->_height;
-
- if (!pPart->data()) {
- continue;
- }
-
- // drawSprite ignores masks of Operation Stealth sprites
- drawSprite(it, pPart->data(), pPart->mask(), width, height, page1Raw, x, y);
- break;
-
- case 2: // text
- // gfxWaitVSync();
- // hideMouse();
-
- messageIdx = it->objIdx;
- x = it->x;
- y = it->y;
- width = it->width;
- height = it->color;
-
- blitRawScreen(page1Raw);
-
- drawDialogueMessage(messageIdx, x, y, width, height);
-
- // blitScreen(page0, NULL);
- // gfxRedrawMouseCursor();
-
- waitForPlayerClick = 1;
-
- break;
-
- case 3:
- // gfxWaitSync()
- // hideMouse();
-
- blitRawScreen(page1Raw);
-
- drawFailureMessage(it->objIdx);
-
- // blitScreen(page0, NULL);
- // gfxRedrawMouseCursor();
-
- waitForPlayerClick = 1;
-
- break;
-
- case 4:
- assert(it->objIdx < NUM_MAX_OBJECT);
-
- objPtr = &objectTable[it->objIdx];
- x = objPtr->x;
- y = objPtr->y;
-
- if (objPtr->frame < 0) {
- continue;
- }
-
- assert(objPtr->frame < NUM_MAX_ANIMDATA);
-
- pPart = &animDataTable[objPtr->frame];
-
- width = pPart->_realWidth;
- height = pPart->_height;
-
- if (!pPart->data()) {
- continue;
- }
-
- gfxFillSprite(pPart->data(), width, height, page1Raw, x, y);
- break;
-
- case 20:
- assert(it->objIdx < NUM_MAX_OBJECT);
-
- 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) {
- continue;
- }
-
- width = animDataTable[objPtr->frame]._realWidth;
- height = animDataTable[objPtr->frame]._height;
-
- if (!animDataTable[objPtr->frame].data()) {
- continue;
- }
-
- maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), width, height, page1Raw, x, y);
- break;
- }
- }
-
for (it = overlayList.begin(); it != overlayList.end(); ) {
if (it->type == 2 || it->type == 3) {
it = overlayList.erase(it);
@@ -1978,115 +1566,96 @@ void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 par
tmp.color = param5;
overlayList.push_back(tmp);
+ waitForPlayerClick = 1;
}
-SeqListElement seqList;
+Common::List<SeqListElement> seqList;
void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
- SeqListElement *currentHead = &seqList;
- SeqListElement *tempHead = currentHead;
+ Common::List<SeqListElement>::iterator it;
- 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;
+ for (it = seqList.begin(); it != seqList.end(); ++it) {
+ if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) {
+ it->var4 = -1;
+ break;
+ }
}
}
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;
- }
+ Common::List<SeqListElement>::iterator it;
- if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
- return 1;
+ for (it = seqList.begin(); it != seqList.end(); ++it) {
+ if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) {
+ return 1;
+ }
}
return 0;
}
-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;
- SeqListElement *newElement;
-
- currentHead = tempHead->next;
-
- while (currentHead && currentHead->varE < param7) {
- tempHead = currentHead;
- currentHead = tempHead->next;
- }
-
- newElement = new SeqListElement;
-
- newElement->next = tempHead->next;
- tempHead->next = newElement;
-
- newElement->var6 = param0;
- newElement->var4 = param1;
- newElement->var8 = param2;
- newElement->varA = param3;
- newElement->varC = param4;
- newElement->var14 = 0;
- newElement->var16 = 0;
- newElement->var18 = param5;
- newElement->var1A = param6;
- newElement->varE = param7;
- newElement->var10 = param8;
- newElement->var12 = param8;
- newElement->var1C = 0;
- newElement->var1E = 0;
-}
-
-void resetSeqList() {
- seqList.next = NULL;
+void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) {
+ Common::List<SeqListElement>::iterator it;
+ SeqListElement tmp;
+
+ for (it = seqList.begin(); it != seqList.end() && it->varE < param7; ++it) ;
+
+ tmp.objIdx = objIdx;
+ tmp.var4 = param1;
+ tmp.var8 = param2;
+ tmp.frame = frame;
+ tmp.varC = param4;
+ tmp.var14 = 0;
+ tmp.var16 = 0;
+ tmp.var18 = param5;
+ tmp.var1A = param6;
+ tmp.varE = param7;
+ tmp.var10 = param8;
+ tmp.var12 = param8;
+ tmp.var1C = 0;
+ tmp.var1E = 0;
+
+ seqList.insert(it, tmp);
}
-void computeMove1(SeqListElement *element, int16 x, int16 y, int16 param1,
+void computeMove1(SeqListElement &element, int16 x, int16 y, int16 param1,
int16 param2, int16 x2, int16 y2) {
- element->var16 = 0;
- element->var14 = 0;
+ element.var16 = 0;
+ element.var14 = 0;
if (y2) {
if (y - param2 > y2) {
- element->var16 = 2;
+ element.var16 = 2;
}
if (y + param2 < y2) {
- element->var16 = 1;
+ element.var16 = 1;
}
}
if (x2) {
if (x - param1 > x2) {
- element->var14 = 2;
+ element.var14 = 2;
}
if (x + param1 < x2) {
- element->var14 = 1;
+ element.var14 = 1;
}
}
}
-uint16 computeMove2(SeqListElement *element) {
+uint16 computeMove2(SeqListElement &element) {
int16 returnVar = 0;
- if (element->var16 == 1) {
+ if (element.var16 == 1) {
returnVar = 4;
- } else if (element->var16 == 2) {
+ } else if (element.var16 == 2) {
returnVar = 3;
}
- if (element->var14 == 1) {
+ if (element.var14 == 1) {
returnVar = 1;
- } else if (element->var14 == 2) {
+ } else if (element.var14 == 2) {
returnVar = 2;
}
@@ -2165,14 +1734,13 @@ void resetGfxEntityEntry(uint16 objIdx) {
#endif
}
-uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
+uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &element, uint16 param3, int16 *param4) {
const byte *currentPtr = ptr;
const byte *ptrData;
const byte *ptr2;
int16 di;
assert(ptr);
- assert(element);
assert(param4);
dummyU16 = READ_BE_UINT16((currentPtr + param1 * 2) + 8);
@@ -2181,25 +1749,25 @@ uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *ele
assert(*ptrData);
- di = (objectTable[param2].costume + 1) % (*ptrData);
+ di = (objectTable[objIdx].costume + 1) % (*ptrData);
ptr2 = (ptrData + (di * 8)) + 1;
- if ((checkCollision(param2, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) {
+ if ((checkCollision(objIdx, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) {
return 0;
}
- objectTable[param2].x += (int8)ptr2[4];
- objectTable[param2].y += (int8)ptr2[5];
- objectTable[param2].mask += (int8)ptr2[6];
+ objectTable[objIdx].x += (int8)ptr2[4];
+ objectTable[objIdx].y += (int8)ptr2[5];
+ objectTable[objIdx].mask += (int8)ptr2[6];
- if (objectTable[param2].frame) {
- resetGfxEntityEntry(param2);
+ if (objectTable[objIdx].frame) {
+ resetGfxEntityEntry(objIdx);
}
- objectTable[param2].frame = ptr2[7] + element->var8;
+ objectTable[objIdx].frame = ptr2[7] + element.var8;
- if (param3 || !element->var14) {
- objectTable[param2].costume = di;
+ if (param3 || !element.var14) {
+ objectTable[objIdx].costume = di;
} else {
*param4 = di;
}
@@ -2207,86 +1775,86 @@ uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *ele
return 1;
}
-void processSeqListElement(SeqListElement *element) {
- int16 x = objectTable[element->var6].x;
- int16 y = objectTable[element->var6].y;
- const byte *ptr1 = animDataTable[element->varA].data();
+void processSeqListElement(SeqListElement &element) {
+ int16 x = objectTable[element.objIdx].x;
+ int16 y = objectTable[element.objIdx].y;
+ const byte *ptr1 = animDataTable[element.frame].data();
int16 var_10;
int16 var_4;
int16 var_2;
- if (element->var12 < element->var10) {
- element->var12++;
+ if (element.var12 < element.var10) {
+ element.var12++;
return;
}
- element->var12 = 0;
+ element.var12 = 0;
if (ptr1) {
uint16 param1 = ptr1[1];
uint16 param2 = ptr1[2];
- if (element->varC != 255) {
+ if (element.varC != 255) {
// FIXME: Why is this here? Fingolfin gets lots of these
// in his copy of Operation Stealth (value 0 or 236) under
// Mac OS X. Maybe it's a endian issue? At least the graphics
// in the copy protection screen are partially messed up.
- warning("processSeqListElement: varC = %d", element->varC);
+ warning("processSeqListElement: varC = %d", element.varC);
}
if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) {
computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, globalVars[VAR_MOUSE_X_POS], globalVars[VAR_MOUSE_Y_POS]);
} else {
- element->var16 = 0;
- element->var14 = 0;
+ element.var16 = 0;
+ element.var14 = 0;
}
var_10 = computeMove2(element);
if (var_10) {
- element->var1C = var_10;
- element->var1E = var_10;
+ element.var1C = var_10;
+ element.var1E = var_10;
}
var_4 = -1;
- if ((element->var16 == 1
- && !addAni(3, element->var6, ptr1, element, 0, &var_4)) || (element->var16 == 2 && !addAni(2, element->var6, ptr1, element, 0,
+ if ((element.var16 == 1
+ && !addAni(3, element.objIdx, ptr1, element, 0, &var_4)) || (element.var16 == 2 && !addAni(2, element.objIdx, ptr1, element, 0,
&var_4))) {
- if (element->varC == 255) {
+ if (element.varC == 255) {
globalVars[VAR_MOUSE_Y_POS] = 0;
}
}
- if ((element->var14 == 1
- && !addAni(0, element->var6, ptr1, element, 1, &var_2))) {
- if (element->varC == 255) {
+ if ((element.var14 == 1
+ && !addAni(0, element.objIdx, ptr1, element, 1, &var_2))) {
+ if (element.varC == 255) {
globalVars[VAR_MOUSE_X_POS] = 0;
if (var_4 != -1) {
- objectTable[element->var6].costume = var_4;
+ objectTable[element.objIdx].costume = var_4;
}
}
}
- if ((element->var14 == 2 && !addAni(1, element->var6, ptr1, element, 1, &var_2))) {
- if (element->varC == 255) {
+ if ((element.var14 == 2 && !addAni(1, element.objIdx, ptr1, element, 1, &var_2))) {
+ if (element.varC == 255) {
globalVars[VAR_MOUSE_X_POS] = 0;
if (var_4 != -1) {
- objectTable[element->var6].costume = var_4;
+ objectTable[element.objIdx].costume = var_4;
}
}
}
- if (element->var16 + element->var14) {
- if (element->var1C) {
- if (element->var1E) {
- objectTable[element->var6].costume = 0;
- element->var1E = 0;
+ if (element.var16 + element.var14) {
+ if (element.var1C) {
+ if (element.var1E) {
+ objectTable[element.objIdx].costume = 0;
+ element.var1E = 0;
}
- addAni(element->var1C + 3, element->var6, ptr1, element, 1, (int16 *) & var2);
+ addAni(element.var1C + 3, element.objIdx, ptr1, element, 1, (int16 *) & var2);
}
}
@@ -2295,119 +1863,28 @@ void processSeqListElement(SeqListElement *element) {
}
void processSeqList(void) {
- SeqListElement *currentHead = &seqList;
- SeqListElement *tempHead = currentHead;
+ Common::List<SeqListElement>::iterator it;
- currentHead = tempHead->next;
-
- while (currentHead) {
- if (currentHead->var4 != -1) {
- processSeqListElement(currentHead);
+ for (it = seqList.begin(); it != seqList.end(); ++it) {
+ if (it->var4 == -1) {
+ continue;
}
- tempHead = currentHead;
- currentHead = tempHead->next;
+ processSeqListElement(*it);
}
}
bool makeTextEntryMenu(const char *messagePtr, char *inputString, int stringMaxLength, int y) {
- int16 color = 2;
- byte color2 = defaultMenuBoxColor2;
- byte endOfMessageReached = 0;
- int16 localX, localY, localWidth;
- int margins = 16;
int len = strlen(messagePtr);
int16 width = 6 * len + 20;
- uint16 messageLength = 0, numWords = 0, messageWidth = 0;
- uint16 lineResult, fullLineWidth;
- uint16 interWordSize, interWordSizeRemain;
- const char *endOfMessagePtr;
- byte currentChar, characterWidth;
width = CLIP((int)width, 180, 250);
int16 x = (320 - width) / 2;
- gfxDrawPlainBoxRaw(x - margins, y, x + width + margins, y + 4, color2, page1Raw);
-
- localX = x + 4;
- localY = y + 4;
- localWidth = width;
-
getKeyData(); // clear input key
- do {
- messageLength = 0;
-
- while (messagePtr[messageLength] == ' ') {
- messageLength++;
- }
-
- messagePtr += messageLength;
-
- messageLength = computeMessageLength((const byte *)messagePtr, localWidth, &numWords, &messageWidth, &lineResult);
-
- endOfMessagePtr = messagePtr + messageLength;
-
- if (lineResult) {
- fullLineWidth = localWidth - messageWidth;
-
- if (numWords) {
- interWordSize = fullLineWidth / numWords;
- interWordSizeRemain = fullLineWidth % numWords;
- } else {
- interWordSize = 5;
- interWordSizeRemain = 0;
- }
- } else {
- interWordSize = 5;
- interWordSizeRemain = 0;
- }
-
- gfxDrawPlainBoxRaw(x - margins, localY, x + width + margins, localY + 9, color2, page1Raw);
-
- do {
- currentChar = *(messagePtr++);
-
- if (currentChar == 0) {
- endOfMessageReached = 1;
- } else if (currentChar == ' ') {
- localX += interWordSizeRemain + interWordSize;
-
- if (interWordSizeRemain)
- interWordSizeRemain = 0;
- } else {
- characterWidth = fontParamTable[currentChar].characterWidth;
-
- if (characterWidth) {
- byte characterIdx = fontParamTable[currentChar].characterIdx;
- drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, localX, localY);
- localX += characterWidth + 1;
- }
- }
- } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached);
-
- localX = x + 4;
- localY += 9;
- } while (!endOfMessageReached);
-
- // Input string
- gfxDrawPlainBoxRaw(x - margins, localY, x + width + margins, localY + 9, color2, page1Raw);
- localY += 9;
-
- x -= margins;
- width += margins * 2;
-
- gfxDrawPlainBoxRaw(x, localY, x + width, localY + 4, color2, page1Raw);
-
- drawDoubleMessageBox(x, y, width, localY, color, page1Raw);
-
- x += margins;
- width -= margins * 2;
- localY -= 9;
-
-
int quit = 0;
bool redraw = true;
CommandeType tempString;
@@ -2416,24 +1893,8 @@ bool makeTextEntryMenu(const char *messagePtr, char *inputString, int stringMaxL
while (!quit) {
if (redraw) {
- gfxDrawPlainBoxRaw(x, localY - 1, x + width, localY + 8, 0, page1Raw);
-
- int currentX = x + 4;
-
- for (uint j = 0; j < strlen(inputString); j++) {
- currentChar = inputString[j];
- currentX = drawChar(currentChar, currentX, localY);
-
- // draw cursor here
- if (inputPos == (int)(j + 2))
- gfxDrawLine(currentX, localY - 1, currentX, localY + 8, color, page1Raw);
-
- }
-
- if (strlen(inputString) == 0 || inputPos == 1) // cursor wasn't yet drawn
- gfxDrawLine(x + 4, localY - 1, x + 4, localY + 8, color, page1Raw);
-
- blitRawScreen(page1Raw);
+ renderer->drawInputBox(messagePtr, inputString, inputPos, x - 16, y, width + 32);
+ renderer->blit();
redraw = false;
}
diff --git a/engines/cine/various.h b/engines/cine/various.h
index f906b2aa19..91662c16ff 100644
--- a/engines/cine/various.h
+++ b/engines/cine/various.h
@@ -43,11 +43,10 @@ extern bool disableSystemMenu;
extern bool inMenu;
struct SeqListElement {
- struct SeqListElement *next;
int16 var4;
- int16 var6;
+ uint16 objIdx;
int16 var8;
- int16 varA;
+ int16 frame;
int16 varC;
int16 varE;
int16 var10;
@@ -60,7 +59,7 @@ struct SeqListElement {
int16 var1E;
};
-extern SeqListElement seqList;
+extern Common::List<SeqListElement> seqList;
extern uint16 var2;
extern uint16 var3;
@@ -97,7 +96,6 @@ extern char newRelName[20];
extern char newObjectName[20];
extern char newMsgName[20];
-extern char currentBgName[8][15];
extern char currentCtName[15];
extern char currentPartName[15];
@@ -130,20 +128,16 @@ struct SelectedObjStruct {
int16 param;
};
-extern uint16 defaultMenuBoxColor;
-extern uint16 defaultMenuBoxColor2;
-
#define NUM_MAX_ZONE 16
extern uint16 zoneData[NUM_MAX_ZONE];
void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5);
-extern int16 additionalBgVScroll;
+void removeMessages();
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 addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8);
void processSeqList(void);
bool makeTextEntryMenu(const char *caption, char *string, int strLen, int y);
diff --git a/engines/cine/xref.txt b/engines/cine/xref.txt
index 3640ef83d6..5a8d2eef0f 100644
--- a/engines/cine/xref.txt
+++ b/engines/cine/xref.txt
@@ -1,4 +1,4 @@
-script.cpp:
+script_fw.cpp:
setupOpcodes() - replaced with FWScript/OSScript class members
getNextByte() - replaced with RawScript/FWScript class members
getNextWord() - replaced with RawScript/FWScript class members
@@ -89,6 +89,9 @@ o1_disableSystemMenu() - replaced with FWScript::o1_disableSystemMenu()
o1_loadMask5() - replaced with FWScript::o1_loadMask5()
o1_unloadMask5() - replaced with FWScript::o1_unloadMask5()
+palRotate() - modified and moved to pal.cpp
+
+script_os.cpp:
o2_loadPart() - replaced with FWScript::o2_loadPart()
o2_addSeqListElement() - replaced with FWScript::o2_addSeqListElement()
o2_removeSeq() - replaced with FWScript::o2_removeSeq()
@@ -134,20 +137,48 @@ releaseObjectScripts() - removed (obsoleted by Common::List::clear())
various.cpp:
setupScriptList() - removed (obsoleted by new makeLoad() and
loadScriptFromSave() implementation)
+drawChar() - removed (obsoleted by FWRenderer::drawChar())
+makeTextEntry() - removed (obsoleted by FWRenderer::drawMenu())
+drawMenuBox() - removed (obsoleted by FWRenderer::drawCommand())
+backupOverlayPage() - removed (obsoleted by FWRenderer::drawBackground())
+drawMessage() - removed (obsoleted by FWRenderer::drawMessage())
+drawDialogueMessage() - removed (obsoleted by FWRenderer::renderOverlay())
+drawFailureMessage() - removed (obsoleted by FWRenderer::renderOverlay())
+drawOverlays() - removed (obsoleted by FWRenderer::drawOverlays())
+resetSeqList() - removed (obsoleted by Common::List)
anim.cpp:
freeAnimData() - replaced with animData::clear()
allocFrame() - replaced with animData::load()
reserveFrame() - replaced with animData::load()
-bg_list.cpp
+bg_list.cpp:
reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and
loadBgIncrustFromSave() implementation)
freeBgIncrustList() - removed (obsoleted by Common::List::clear())
-object.cpp
+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
+
+gfx.cpp:
+gfxInit() - removed (obsoleted by FWRenderer)
+gfxDestroy() - removed (obsoleted by FWRenderer)
+transformColor() - moved to pal.cpp
+transformPaletteRange() - modified and moved to pal.cpp
+gfxCopyRawPage() - removed (obsoleted by FWRenderer)
+gfxFlipRawPage() - removed (obsoleted by FWRenderer::blit() and
+ FWRenderer::refreshPalette())
+fadeToBlack() - removed (obsoleted by FWRenderer::fadeToBlack())
+blitRawScreen() - removed (obsoleted by FWRenderer)
+flip() - removed (obsoleted by FWRenderer::reloadPalette())
+
+bg.cpp:
+loadCt() - split into loadCtFW() and loadCtOS()
+loadBgHigh() - removed (obsoleted by OSRenderer::loadBg256())
+
+texte.cpp:
+computeMessageLength() - replaced with fitLine()