diff options
| -rw-r--r-- | engines/cine/anim.cpp | 1 | ||||
| -rw-r--r-- | engines/cine/bg.cpp | 96 | ||||
| -rw-r--r-- | engines/cine/bg.h | 15 | ||||
| -rw-r--r-- | engines/cine/bg_list.cpp | 60 | ||||
| -rw-r--r-- | engines/cine/bg_list.h | 4 | ||||
| -rw-r--r-- | engines/cine/cine.cpp | 12 | ||||
| -rw-r--r-- | engines/cine/gfx.cpp | 1396 | ||||
| -rw-r--r-- | engines/cine/gfx.h | 158 | ||||
| -rw-r--r-- | engines/cine/main_loop.cpp | 16 | ||||
| -rw-r--r-- | engines/cine/object.cpp | 4 | ||||
| -rw-r--r-- | engines/cine/pal.cpp | 62 | ||||
| -rw-r--r-- | engines/cine/pal.h | 8 | ||||
| -rw-r--r-- | engines/cine/prc.cpp | 4 | ||||
| -rw-r--r-- | engines/cine/rel.cpp | 4 | ||||
| -rw-r--r-- | engines/cine/script.h | 3 | ||||
| -rw-r--r-- | engines/cine/script_fw.cpp | 67 | ||||
| -rw-r--r-- | engines/cine/script_os.cpp | 50 | ||||
| -rw-r--r-- | engines/cine/texte.cpp | 92 | ||||
| -rw-r--r-- | engines/cine/texte.h | 2 | ||||
| -rw-r--r-- | engines/cine/various.cpp | 833 | ||||
| -rw-r--r-- | engines/cine/various.h | 16 | ||||
| -rw-r--r-- | engines/cine/xref.txt | 37 | 
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()  | 
