2008-08-04 11:28:57 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common/events.h"
|
|
|
|
#include "common/keyboard.h"
|
|
|
|
#include "common/file.h"
|
|
|
|
#include "common/savefile.h"
|
|
|
|
#include "common/config-manager.h"
|
|
|
|
|
|
|
|
#include "base/plugins.h"
|
|
|
|
#include "base/version.h"
|
|
|
|
|
|
|
|
#include "graphics/cursorman.h"
|
|
|
|
|
|
|
|
#include "sound/mixer.h"
|
|
|
|
|
|
|
|
#include "toltecs/toltecs.h"
|
|
|
|
#include "toltecs/palette.h"
|
|
|
|
#include "toltecs/resource.h"
|
|
|
|
#include "toltecs/screen.h"
|
|
|
|
#include "toltecs/script.h"
|
|
|
|
#include "toltecs/segmap.h"
|
|
|
|
|
|
|
|
namespace Toltecs {
|
|
|
|
|
|
|
|
Screen::Screen(ToltecsEngine *vm) : _vm(vm) {
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
_frontScreen = new byte[268800];
|
2008-08-04 11:28:57 +00:00
|
|
|
_backScreen = new byte[870400];
|
|
|
|
|
|
|
|
memset(_fontResIndexArray, 0, sizeof(_fontResIndexArray));
|
2008-08-04 12:18:15 +00:00
|
|
|
_fontColor1 = 0;
|
|
|
|
_fontColor2 = 0;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
// Screen shaking
|
|
|
|
_shakeActive = false;
|
|
|
|
_shakeCounterInit = 0;
|
|
|
|
_shakeCounter = 0;
|
|
|
|
_shakePos = 0;
|
|
|
|
|
|
|
|
// Verb line
|
|
|
|
_verbLineNum = 0;
|
|
|
|
memset(_verbLineItems, 0, sizeof(_verbLineItems));
|
|
|
|
_verbLineX = 160;
|
|
|
|
_verbLineY = 2;
|
|
|
|
_verbLineWidth = 20;
|
|
|
|
_verbLineCount = 0;
|
|
|
|
|
|
|
|
// Talk text
|
|
|
|
_talkTextItemNum = 0;
|
|
|
|
memset(_talkTextItems, 0, sizeof(_talkTextItems));
|
|
|
|
_talkTextX = 0;//TODO correct init values
|
|
|
|
_talkTextY = 0;
|
|
|
|
_talkTextFontColor = 0;
|
|
|
|
_talkTextMaxWidth = 520;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Screen::~Screen() {
|
|
|
|
|
|
|
|
delete[] _frontScreen;
|
|
|
|
delete[] _backScreen;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::unpackRle(byte *source, byte *dest, uint16 width, uint16 height) {
|
|
|
|
int32 size = width * height;
|
2008-08-04 12:18:15 +00:00
|
|
|
while (size > 0) {
|
|
|
|
byte a = *source++;
|
|
|
|
byte b = *source++;
|
|
|
|
if (a == 0) {
|
|
|
|
dest += b;
|
|
|
|
size -= b;
|
|
|
|
} else {
|
|
|
|
b = ((b << 4) & 0xF0) | ((b >> 4) & 0x0F);
|
|
|
|
memset(dest, b, a);
|
|
|
|
dest += a;
|
|
|
|
size -= a;
|
|
|
|
}
|
|
|
|
}
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::loadMouseCursor(uint resIndex) {
|
|
|
|
byte mouseCursor[16 * 16], *mouseCursorP = mouseCursor;
|
|
|
|
byte *cursorData = _vm->_res->load(resIndex);
|
|
|
|
for (int i = 0; i < 32; i++) {
|
2008-08-04 12:18:15 +00:00
|
|
|
byte pixel;
|
|
|
|
byte mask1 = *cursorData++;
|
|
|
|
byte mask2 = *cursorData++;
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
pixel = 0xE5;
|
|
|
|
if ((mask2 & 0x80) == 0)
|
|
|
|
pixel = 0xE0;
|
|
|
|
mask2 <<= 1;
|
|
|
|
if ((mask1 & 0x80) == 0)
|
|
|
|
pixel = 0;
|
|
|
|
mask1 <<= 1;
|
|
|
|
*mouseCursorP++ = pixel;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//CursorMan.replaceCursor((const byte*)mouseCursor, 16, 16, 0, 0, 0);
|
|
|
|
// FIXME: Where's the cursor hotspot? Using 8, 8 seems good enough for now.
|
|
|
|
CursorMan.replaceCursor((const byte*)mouseCursor, 16, 16, 8, 8, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) {
|
|
|
|
|
|
|
|
byte *imageData = _vm->_res->load(resIndex);
|
|
|
|
int16 headerSize = READ_LE_UINT16(imageData);
|
|
|
|
int16 width = imageData[2];
|
|
|
|
int16 height = imageData[3];
|
|
|
|
int16 workWidth = width, workHeight = height;
|
|
|
|
imageData += headerSize;
|
|
|
|
|
|
|
|
byte *dest = _frontScreen + x + (y + _vm->_cameraHeight) * 640;
|
|
|
|
|
|
|
|
debug(0, "Screen::drawGuiImage() x = %d; y = %d; w = %d; h = %d; resIndex = %d", x, y, width, height, resIndex);
|
|
|
|
|
|
|
|
//_vm->_arc->dump(resIndex, "gui");
|
|
|
|
|
|
|
|
while (workHeight > 0) {
|
|
|
|
int count = 1;
|
|
|
|
byte pixel = *imageData++;
|
|
|
|
if (pixel & 0x80) {
|
|
|
|
pixel &= 0x7F;
|
|
|
|
count = *imageData++;
|
|
|
|
count += 2;
|
|
|
|
}
|
|
|
|
pixel = pixel + 0xE0;
|
|
|
|
while (count-- && workHeight > 0) {
|
|
|
|
*dest++ = pixel;
|
|
|
|
workWidth--;
|
|
|
|
if (workWidth == 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
workHeight--;
|
|
|
|
dest += 640 - width;
|
|
|
|
workWidth = width;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::startShakeScreen(int16 shakeCounter) {
|
|
|
|
_shakeActive = true;
|
|
|
|
_shakeCounterInit = shakeCounter;
|
|
|
|
_shakeCounter = shakeCounter;
|
|
|
|
_shakePos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::stopShakeScreen() {
|
|
|
|
_shakeActive = false;
|
|
|
|
_vm->_system->setShakePos(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::updateShakeScreen() {
|
|
|
|
if (_shakeActive) {
|
2008-08-04 12:18:15 +00:00
|
|
|
_shakeCounter--;
|
|
|
|
if (_shakeCounter == 0) {
|
|
|
|
_shakeCounter = _shakeCounterInit;
|
|
|
|
_shakePos ^= 8;
|
|
|
|
_vm->_system->setShakePos(_shakePos);
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::addStaticSprite(byte *spriteItem) {
|
|
|
|
|
|
|
|
DrawRequest drawRequest;
|
|
|
|
memset(&drawRequest, 0, sizeof(drawRequest));
|
|
|
|
|
|
|
|
drawRequest.y = READ_LE_UINT16(spriteItem + 0);
|
|
|
|
drawRequest.x = READ_LE_UINT16(spriteItem + 2);
|
|
|
|
int16 fragmentId = READ_LE_UINT16(spriteItem + 4);
|
|
|
|
drawRequest.baseColor = _vm->_palette->findFragment(fragmentId) & 0xFF;
|
|
|
|
drawRequest.resIndex = READ_LE_UINT16(spriteItem + 6);
|
|
|
|
drawRequest.flags = READ_LE_UINT16(spriteItem + 8);
|
|
|
|
drawRequest.scaling = 0;
|
|
|
|
|
|
|
|
debug(0, "Screen::addStaticSprite() x = %d; y = %d; baseColor = %d; resIndex = %d; flags = %04X", drawRequest.x, drawRequest.y, drawRequest.baseColor, drawRequest.resIndex, drawRequest.flags);
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
addDrawRequest(drawRequest);
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode) {
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
debug(0, "Screen::addAnimatedSprite(%d, %d, %d)", x, y, fragmentId);
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
DrawRequest drawRequest;
|
|
|
|
memset(&drawRequest, 0, sizeof(drawRequest));
|
|
|
|
|
|
|
|
drawRequest.x = x;
|
|
|
|
drawRequest.y = y;
|
|
|
|
drawRequest.baseColor = _vm->_palette->findFragment(fragmentId) & 0xFF;
|
|
|
|
|
|
|
|
if (mode == 1) {
|
|
|
|
drawRequest.scaling = _vm->_segmap->getScalingAtPoint(drawRequest.x, drawRequest.y);
|
|
|
|
} else if (mode == 2) {
|
|
|
|
drawRequest.scaling = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int16 count = spriteArray[0];
|
|
|
|
|
|
|
|
debug(0, "count = %d", count);
|
|
|
|
|
|
|
|
for (int16 index = 1; index <= count; index++) {
|
|
|
|
|
|
|
|
byte *spriteItem = data + spriteArray[index];
|
|
|
|
|
|
|
|
uint16 loopNum = READ_LE_UINT16(spriteItem + 0) & 0x7FFF;
|
|
|
|
uint16 loopCount = READ_LE_UINT16(spriteItem + 2);
|
|
|
|
uint16 frameNum = READ_LE_UINT16(spriteItem + 4);
|
|
|
|
uint16 frameCount = READ_LE_UINT16(spriteItem + 6);
|
|
|
|
drawRequest.resIndex = READ_LE_UINT16(spriteItem + 8);
|
|
|
|
drawRequest.flags = READ_LE_UINT16(spriteItem + 10 + loopNum * 2);
|
|
|
|
|
|
|
|
debug(0, "Screen::addAnimatedSprite(%d of %d) loopNum = %d; loopCount = %d; frameNum = %d; frameCount = %d; resIndex = %d; flags = %04X, mode = %d",
|
|
|
|
index, count, loopNum, loopCount, frameNum, frameCount, drawRequest.resIndex, drawRequest.flags, mode);
|
|
|
|
|
|
|
|
addDrawRequest(drawRequest);
|
|
|
|
|
|
|
|
frameNum++;
|
|
|
|
if (frameNum == frameCount) {
|
|
|
|
frameNum = 0;
|
|
|
|
loopNum++;
|
|
|
|
if (loopNum == loopCount) {
|
|
|
|
if (loop) {
|
2008-08-04 12:18:15 +00:00
|
|
|
loopNum = 0;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
loopNum--;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
loopNum |= 0x8000;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WRITE_LE_UINT16(spriteItem + 0, loopNum);
|
|
|
|
WRITE_LE_UINT16(spriteItem + 4, frameNum);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::clearSprites() {
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
_spriteDrawList.clear();
|
|
|
|
// TODO
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::addDrawRequest(const DrawRequest &drawRequest) {
|
|
|
|
|
|
|
|
int16 scaleValueX, scaleValueY;
|
|
|
|
int16 spriteDraw_X, spriteDraw_Y;
|
|
|
|
byte *spriteData;
|
|
|
|
int16 frameNum;
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
SpriteDrawItem sprite;
|
|
|
|
memset(&sprite, 0, sizeof(SpriteDrawItem));
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
if (drawRequest.flags == 0xFFFF)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
|
|
|
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite.flags = 0;
|
|
|
|
sprite.baseColor = drawRequest.baseColor;
|
|
|
|
sprite.x = drawRequest.x;
|
|
|
|
sprite.y = drawRequest.y;
|
|
|
|
sprite.ybottom = drawRequest.y;
|
|
|
|
sprite.resIndex = drawRequest.resIndex;
|
|
|
|
|
|
|
|
spriteData = _vm->_res->load(drawRequest.resIndex);
|
|
|
|
|
|
|
|
if (drawRequest.flags & 0x2000) {
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.flags |= 0x10;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (drawRequest.flags & 0x4000) {
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.flags |= 0x40;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
frameNum = drawRequest.flags & 0x0FFF;
|
|
|
|
|
|
|
|
// First initialize the sprite item with the values from the sprite resource
|
|
|
|
|
|
|
|
SpriteFrameEntry spriteFrameEntry(spriteData + frameNum * 12);
|
|
|
|
|
|
|
|
if (spriteFrameEntry.w == 0 || spriteFrameEntry.h == 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
sprite.offset = spriteFrameEntry.offset;
|
|
|
|
|
|
|
|
sprite.width = spriteFrameEntry.w;
|
|
|
|
sprite.height = spriteFrameEntry.h;
|
|
|
|
|
|
|
|
sprite.origWidth = spriteFrameEntry.w;
|
|
|
|
sprite.origHeight = spriteFrameEntry.h;
|
|
|
|
|
|
|
|
if (drawRequest.flags & 0x1000) {
|
2008-08-04 12:18:15 +00:00
|
|
|
spriteDraw_X = spriteFrameEntry.w - spriteFrameEntry.x;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
spriteDraw_X = spriteFrameEntry.x;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
spriteDraw_Y = spriteFrameEntry.y;
|
|
|
|
|
|
|
|
// If the sprite should be scaled we need to initialize some values now
|
|
|
|
|
|
|
|
if (drawRequest.scaling != 0) {
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
byte scaleValue = ABS(drawRequest.scaling);
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
scaleValueX = scaleValue * sprite.origWidth;
|
|
|
|
sprite.xdelta = (10000 * sprite.origWidth) / scaleValueX;
|
|
|
|
scaleValueX /= 100;
|
|
|
|
|
|
|
|
scaleValueY = scaleValue * sprite.origHeight;
|
|
|
|
sprite.ydelta = (10000 * sprite.origHeight) / scaleValueY;
|
|
|
|
scaleValueY /= 100;
|
|
|
|
|
|
|
|
if (drawRequest.scaling > 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.flags |= 2;
|
|
|
|
sprite.width = sprite.origWidth + scaleValueX;
|
|
|
|
sprite.height = sprite.origHeight + scaleValueY;
|
|
|
|
spriteDraw_X += (spriteDraw_X * scaleValue) / 100;
|
|
|
|
spriteDraw_Y += (spriteDraw_Y * scaleValue) / 100;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.flags |= 1;
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite.width = sprite.origWidth - scaleValueX;
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.height = sprite.origHeight - 1 - scaleValueY;
|
2008-08-04 11:28:57 +00:00
|
|
|
if (sprite.width <= 0 || sprite.height <= 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
|
|
|
spriteDraw_X -= (spriteDraw_X * scaleValue) / 100;
|
|
|
|
spriteDraw_Y -= (spriteDraw_Y * scaleValue) / 100;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sprite.x -= spriteDraw_X;
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.y -= spriteDraw_Y;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.yerror = sprite.ydelta;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
// Now we check if the sprite needs to be clipped
|
|
|
|
|
|
|
|
// Clip Y
|
2008-08-04 12:18:15 +00:00
|
|
|
if (sprite.y - _vm->_cameraY < 0) {
|
|
|
|
|
|
|
|
int16 clipHeight = ABS(sprite.y - _vm->_cameraY);
|
|
|
|
int16 chopHeight, skipHeight, lineWidth;
|
|
|
|
byte *spriteFrameData;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
sprite.height -= clipHeight;
|
|
|
|
if (sprite.height <= 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.y = _vm->_cameraY;
|
|
|
|
|
|
|
|
// If the sprite is scaled
|
|
|
|
if (sprite.flags & 3) {
|
|
|
|
chopHeight = sprite.ydelta;
|
2008-08-04 11:28:57 +00:00
|
|
|
skipHeight = clipHeight;
|
2008-08-04 12:18:15 +00:00
|
|
|
if ((sprite.flags & 2) == 0) {
|
|
|
|
do {
|
|
|
|
chopHeight -= 100;
|
|
|
|
if (chopHeight <= 0) {
|
|
|
|
skipHeight++;
|
|
|
|
chopHeight += sprite.ydelta;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
clipHeight--;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
} while (clipHeight > 0);
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
do {
|
|
|
|
chopHeight -= 100;
|
|
|
|
if (chopHeight < 0) {
|
|
|
|
skipHeight--;
|
|
|
|
chopHeight += sprite.ydelta + 100;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
clipHeight--;
|
|
|
|
} while (clipHeight > 0);
|
|
|
|
}
|
|
|
|
sprite.yerror = chopHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
spriteFrameData = spriteData + sprite.offset;
|
|
|
|
|
|
|
|
// Now the sprite's offset is adjusted to point to the starting line
|
|
|
|
if ((sprite.flags & 0x10) == 0) {
|
|
|
|
while (clipHeight--) {
|
2008-08-04 12:18:15 +00:00
|
|
|
lineWidth = 0;
|
|
|
|
while (lineWidth </*CHECKME was != */ sprite.origWidth) {
|
|
|
|
sprite.offset++;
|
|
|
|
lineWidth += (*spriteFrameData++) & 0x0F;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
lineWidth = 0;
|
2008-08-04 11:28:57 +00:00
|
|
|
while (clipHeight--) {
|
2008-08-04 12:18:15 +00:00
|
|
|
while (lineWidth < sprite.origWidth) {
|
|
|
|
sprite.offset += 2;
|
|
|
|
spriteFrameData++;
|
2008-08-04 11:28:57 +00:00
|
|
|
lineWidth += *spriteFrameData++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight > 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.height -= sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight;
|
2008-08-04 11:28:57 +00:00
|
|
|
if (sprite.height <= 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
|
|
|
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite.value1 = 0;
|
|
|
|
|
|
|
|
if (drawRequest.flags & 0x1000) {
|
2008-08-04 12:18:15 +00:00
|
|
|
// Left border
|
|
|
|
sprite.flags |= 4;
|
|
|
|
if (sprite.x - _vm->_cameraX < 0) {
|
|
|
|
sprite.width -= ABS(sprite.x - _vm->_cameraX);
|
|
|
|
if (sprite.width <= 0)
|
|
|
|
return;
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite.x = _vm->_cameraX;
|
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
// Right border
|
2008-08-04 11:28:57 +00:00
|
|
|
if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.flags |= 8;
|
|
|
|
sprite.width -= sprite.x + sprite.width - _vm->_cameraX - 640;
|
|
|
|
if (sprite.width <= 0)
|
|
|
|
return;
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite.value1 = sprite.x + sprite.width - _vm->_cameraX - 640;
|
|
|
|
}
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
// Left border
|
|
|
|
if (sprite.x - _vm->_cameraX < 0) {
|
|
|
|
sprite.flags |= 8;
|
|
|
|
sprite.width -= ABS(sprite.x - _vm->_cameraX);
|
|
|
|
if (sprite.width <= 0)
|
|
|
|
return;
|
|
|
|
sprite.value1 = ABS(sprite.x - _vm->_cameraX);
|
|
|
|
sprite.x = _vm->_cameraX;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
// Right border
|
2008-08-04 11:28:57 +00:00
|
|
|
if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
sprite.flags |= 8;
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite.width -= sprite.x + sprite.width - _vm->_cameraX - 640;
|
2008-08-04 12:18:15 +00:00
|
|
|
if (sprite.width <= 0)
|
|
|
|
return;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add sprite sorted by priority
|
|
|
|
Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin();
|
|
|
|
while (iter != _spriteDrawList.end() && (*iter).ybottom <= sprite.ybottom) {
|
2008-08-04 12:18:15 +00:00
|
|
|
iter++;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
_spriteDrawList.insert(iter, sprite);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawSprite(SpriteDrawItem *sprite) {
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
debug(0, "Screen::drawSprite() x = %d; y = %d; flags = %04X; resIndex = %d; offset = %08X; drawX = %d; drawY = %d",
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite->x, sprite->y, sprite->flags, sprite->resIndex, sprite->offset,
|
|
|
|
sprite->x - _vm->_cameraX, sprite->y - _vm->_cameraY);
|
2008-08-04 12:18:15 +00:00
|
|
|
debug(0, "Screen::drawSprite() width = %d; height = %d; origWidth = %d; origHeight = %d",
|
2008-08-04 11:28:57 +00:00
|
|
|
sprite->width, sprite->height, sprite->origWidth, sprite->origHeight);
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
byte *source = _vm->_res->load(sprite->resIndex) + sprite->offset;
|
|
|
|
byte *dest = _frontScreen + (sprite->x - _vm->_cameraX) + (sprite->y - _vm->_cameraY) * 640;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
// FIXME: Temporary hack until proper clipping is implemented
|
|
|
|
/*
|
|
|
|
int16 dx = sprite->x - _vm->_cameraX, dy = sprite->y - _vm->_cameraY;
|
|
|
|
if (dx < 0 || dy < 0 || dx + sprite->width >= 640 || dy + sprite->height >= 400)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
|
|
|
*/
|
|
|
|
|
|
|
|
SpriteReader spriteReader(source, sprite);
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
if (sprite->flags & 0x40) {
|
2008-08-04 12:18:15 +00:00
|
|
|
// TODO: Shadow sprites
|
2008-08-04 11:28:57 +00:00
|
|
|
} else if (sprite->flags & 0x10) {
|
2008-08-04 12:18:15 +00:00
|
|
|
// 256 color sprite
|
|
|
|
drawSpriteCore(dest, spriteReader, sprite);
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
// 16 color sprite
|
|
|
|
if (sprite->flags & 1) {
|
|
|
|
SpriteFilterScaleDown spriteScaler(sprite, &spriteReader);
|
|
|
|
drawSpriteCore(dest, spriteScaler, sprite);
|
2008-08-04 11:28:57 +00:00
|
|
|
} else if (sprite->flags & 2) {
|
2008-08-04 12:18:15 +00:00
|
|
|
SpriteFilterScaleUp spriteScaler(sprite, &spriteReader);
|
|
|
|
drawSpriteCore(dest, spriteScaler, sprite);
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
drawSpriteCore(dest, spriteReader, sprite);
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
debug(0, "Screen::drawSprite() ok");
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite) {
|
|
|
|
|
|
|
|
int16 destInc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
if ((sprite->flags & 8))
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
|
|
|
*/
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
if (sprite->flags & 4) {
|
2008-08-04 12:18:15 +00:00
|
|
|
destInc = -1;
|
2008-08-04 11:28:57 +00:00
|
|
|
dest += sprite->width;
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
destInc = 1;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SpriteReaderStatus status;
|
|
|
|
PixelPacket packet;
|
|
|
|
|
|
|
|
byte *destp = dest;
|
|
|
|
int16 skipX = sprite->value1;
|
|
|
|
|
|
|
|
do {
|
|
|
|
status = reader.readPacket(packet);
|
|
|
|
|
|
|
|
if (skipX > 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
while (skipX > 0) {
|
|
|
|
skipX -= packet.count;
|
|
|
|
if (skipX < 0) {
|
2008-08-04 11:28:57 +00:00
|
|
|
packet.count = ABS(skipX);
|
|
|
|
break;
|
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
status = reader.readPacket(packet);
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((sprite->flags & 0x10) && (packet.pixel != 0xFF)) || !(sprite->flags & 0x10) && (packet.pixel != 0)) {
|
|
|
|
if (sprite->flags & 0x40) {
|
|
|
|
} else if (sprite->flags & 0x10) {
|
2008-08-04 12:18:15 +00:00
|
|
|
packet.pixel = ((packet.pixel << 4) & 0xF0) | ((packet.pixel >> 4) & 0x0F);
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
packet.pixel += sprite->baseColor - 1;
|
|
|
|
}
|
|
|
|
while (packet.count--) {
|
|
|
|
*dest = packet.pixel;
|
2008-08-04 11:28:57 +00:00
|
|
|
dest += destInc;
|
|
|
|
}
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
dest += packet.count * destInc;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (status == kSrsEndOfLine) {
|
|
|
|
dest = destp + 640;
|
|
|
|
destp = dest;
|
|
|
|
skipX = sprite->value1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (status != kSrsEndOfSprite);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawSprites() {
|
|
|
|
for (Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin(); iter != _spriteDrawList.end(); iter++) {
|
2008-08-04 12:18:15 +00:00
|
|
|
SpriteDrawItem *sprite = &(*iter);
|
2008-08-04 11:28:57 +00:00
|
|
|
drawSprite(sprite);
|
|
|
|
_vm->_segmap->restoreMasksBySprite(sprite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) {
|
|
|
|
|
|
|
|
debug(0, "Screen::updateVerbLine() _verbLineNum = %d; _verbLineX = %d; _verbLineY = %d; _verbLineWidth = %d; _verbLineCount = %d",
|
|
|
|
_verbLineNum, _verbLineX, _verbLineY, _verbLineWidth, _verbLineCount);
|
|
|
|
|
|
|
|
Font font(_vm->_res->load(_fontResIndexArray[0]));
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
_verbLineItems[_verbLineNum].slotIndex = slotIndex;
|
|
|
|
_verbLineItems[_verbLineNum].slotOffset = slotOffset;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
// First clear the line
|
|
|
|
int16 y = _verbLineY;
|
|
|
|
for (int16 i = 0; i < _verbLineCount; i++) {
|
|
|
|
byte *dest = _frontScreen + _verbLineX - _verbLineWidth / 2 + (y - 1 + _vm->_cameraHeight) * 640;
|
|
|
|
for (int16 j = 0; j < 20; j++) {
|
2008-08-04 12:18:15 +00:00
|
|
|
memset(dest, 0xE0, _verbLineWidth);
|
|
|
|
dest += 640;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
y += 18;
|
|
|
|
}
|
|
|
|
|
|
|
|
int width = 0;
|
|
|
|
byte *sourceString;
|
|
|
|
byte *destString;
|
|
|
|
byte len;
|
|
|
|
|
|
|
|
_tempStringLen1 = 0;
|
|
|
|
destString = _tempString;
|
|
|
|
y = _verbLineY;
|
|
|
|
|
|
|
|
memset(_tempString, 0, sizeof(_tempString));
|
|
|
|
|
|
|
|
for (int16 i = 0; i <= _verbLineNum; i++) {
|
2008-08-04 12:18:15 +00:00
|
|
|
sourceString = _vm->_script->getSlotData(_verbLineItems[i].slotIndex) + _verbLineItems[i].slotOffset;
|
2008-08-04 11:28:57 +00:00
|
|
|
preprocessText(_fontResIndexArray[0], _verbLineWidth, width, sourceString, destString, len);
|
|
|
|
_tempStringLen1 += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_verbLineCount != 1) {
|
2008-08-04 12:18:15 +00:00
|
|
|
int16 charWidth;
|
|
|
|
if (*sourceString < 0xF0) {
|
2008-08-04 11:28:57 +00:00
|
|
|
while (*sourceString > 0x20 && *sourceString < 0xF0 && len > 0/*CHECKME, len check added*/) {
|
2008-08-04 12:18:15 +00:00
|
|
|
byte ch = *sourceString--;
|
|
|
|
_tempStringLen1--;
|
|
|
|
len--;
|
|
|
|
charWidth = font.getCharWidth(ch) + font.getSpacing() - 1;
|
2008-08-04 11:28:57 +00:00
|
|
|
width -= charWidth;
|
|
|
|
}
|
|
|
|
width += charWidth;
|
|
|
|
sourceString++;
|
|
|
|
_tempStringLen1 -= len;
|
|
|
|
_tempStringLen2 = len + 1;
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
drawString(_verbLineX - 1 - (width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0]);
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
destString = _tempString;
|
|
|
|
width = 0;
|
|
|
|
preprocessText(_fontResIndexArray[0], _verbLineWidth, width, sourceString, destString, len);
|
|
|
|
|
|
|
|
_tempStringLen1 += len;
|
2008-08-04 12:18:15 +00:00
|
|
|
y += 9;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
y += 9;
|
|
|
|
}
|
|
|
|
|
|
|
|
_tempStringLen1 -= len;
|
|
|
|
_tempStringLen2 = len;
|
|
|
|
|
|
|
|
drawString(_verbLineX - 1 - (width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::updateTalkText(int16 slotIndex, int16 slotOffset) {
|
|
|
|
|
|
|
|
int16 x, y, maxWidth, width, length;
|
|
|
|
byte durationModifier = 1;
|
|
|
|
byte *textData = _vm->_script->getSlotData(slotIndex) + slotOffset;
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
TalkTextItem *item = &_talkTextItems[_talkTextItemNum];
|
2008-08-04 11:28:57 +00:00
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
item->fontNum = 0;
|
|
|
|
item->color = _talkTextFontColor;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
//debug(0, "## _talkTextMaxWidth = %d", _talkTextMaxWidth);
|
|
|
|
|
|
|
|
x = CLIP<int16>(_talkTextX - _vm->_cameraX, 120, _talkTextMaxWidth);
|
|
|
|
y = CLIP<int16>(_talkTextY - _vm->_cameraY, 4, _vm->_cameraHeight - 16);
|
|
|
|
|
|
|
|
maxWidth = 624 - ABS(x - 320) * 2;
|
|
|
|
|
|
|
|
while (1) {
|
2008-08-04 12:18:15 +00:00
|
|
|
if (*textData == 0x0A) {
|
2008-08-04 11:28:57 +00:00
|
|
|
x = CLIP<int16>(textData[3], 120, _talkTextMaxWidth);
|
|
|
|
y = CLIP<int16>(READ_LE_UINT16(&textData[1]), 4, _vm->_cameraHeight - 16);
|
|
|
|
maxWidth = 624 - ABS(x - 320) * 2;
|
|
|
|
textData += 4;
|
|
|
|
} else if (*textData == 0x14) {
|
2008-08-04 12:18:15 +00:00
|
|
|
item->color = textData[1];
|
|
|
|
textData += 2;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else if (*textData == 0x19) {
|
2008-08-04 12:18:15 +00:00
|
|
|
durationModifier = textData[1];
|
|
|
|
textData += 2;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else if (*textData < 0x0A) {
|
2008-08-04 12:18:15 +00:00
|
|
|
item->fontNum = textData[1];
|
|
|
|
textData += 2;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else
|
2008-08-04 12:18:15 +00:00
|
|
|
break;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
item->slotIndex = slotIndex;
|
|
|
|
item->slotOffset = textData - _vm->_script->getSlotData(slotIndex);
|
|
|
|
|
|
|
|
width = 0;
|
|
|
|
length = 0;
|
|
|
|
|
|
|
|
item->rectCount = 0;
|
|
|
|
|
|
|
|
Font font(_vm->_res->load(_fontResIndexArray[item->fontNum]));
|
2008-08-04 11:28:57 +00:00
|
|
|
int16 wordLength, wordWidth;
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
while (*textData < 0xF0) {
|
2008-08-04 11:28:57 +00:00
|
|
|
if (*textData == 0x1E) {
|
2008-08-04 12:18:15 +00:00
|
|
|
textData++;
|
|
|
|
addTalkTextRect(font, x, y, length, width, item);
|
|
|
|
// CHECKME?
|
2008-08-04 11:28:57 +00:00
|
|
|
width = 0;
|
|
|
|
length = 0;
|
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
wordLength = 0;
|
|
|
|
wordWidth = 0;
|
|
|
|
while (*textData >= 0x20 && *textData < 0xF0) {
|
|
|
|
byte ch = *textData++;
|
|
|
|
wordLength++;
|
|
|
|
if (ch == 0x20) {
|
|
|
|
wordWidth += font.getWidth();
|
|
|
|
break;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
wordWidth += font.getCharWidth(ch) + font.getSpacing() - 1;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug(0, "## width = %d; wordWidth = %d; width + wordWidth = %d; maxWidth + font.getWidth() = %d",
|
|
|
|
width, wordWidth, width + wordWidth, maxWidth + font.getWidth());
|
|
|
|
|
|
|
|
if (width + wordWidth > maxWidth + font.getWidth()) {
|
|
|
|
addTalkTextRect(font, x, y, length, width, item);
|
|
|
|
width = wordWidth;
|
|
|
|
length = wordLength;
|
|
|
|
} else {
|
|
|
|
width += wordWidth;
|
|
|
|
length += wordLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addTalkTextRect(font, x, y, length, width, item);
|
|
|
|
|
|
|
|
debug(0, "## item->rectCount = %d", item->rectCount);
|
|
|
|
|
|
|
|
int16 textDurationMultiplier = item->duration + 8;
|
|
|
|
// TODO: Check sound/text flags
|
|
|
|
if (*textData == 0xFE) {
|
2008-08-04 12:18:15 +00:00
|
|
|
//textDurationMultiplier += 100;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
item->duration = 4 * textDurationMultiplier * durationModifier;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item) {
|
|
|
|
|
|
|
|
if (width > 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
TextRect *textRect = &item->rects[item->rectCount];
|
|
|
|
width = width + 1 - font.getSpacing();
|
|
|
|
textRect->width = width;
|
|
|
|
item->duration += length;
|
|
|
|
textRect->length = length;
|
|
|
|
textRect->y = y;
|
|
|
|
textRect->x = CLIP<int16>(x - width / 2, 0, 640);
|
|
|
|
item->rectCount++;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
y += font.getHeight() - 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawTalkTextItems() {
|
|
|
|
|
|
|
|
//debug(0, "## _talkTextItemNum = %d", _talkTextItemNum);
|
|
|
|
|
|
|
|
for (int16 i = 0; i <= _talkTextItemNum; i++) {
|
|
|
|
TalkTextItem *item = &_talkTextItems[i];
|
|
|
|
byte *text = _vm->_script->getSlotData(item->slotIndex) + item->slotOffset;
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
if (item->fontNum == -1 || item->duration == 0)
|
|
|
|
continue;
|
2008-08-04 11:28:57 +00:00
|
|
|
|
|
|
|
item->duration -= _vm->_counter01;
|
|
|
|
if (item->duration < 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
item->duration = 0;
|
|
|
|
|
|
|
|
Font font(_vm->_res->load(_fontResIndexArray[item->fontNum]));
|
2008-08-04 11:28:57 +00:00
|
|
|
for (byte j = 0; j < item->rectCount; j++) {
|
|
|
|
int16 x = item->rects[j].x;
|
|
|
|
for (byte pos = 0; pos < item->rects[j].length; pos++) {
|
2008-08-04 12:18:15 +00:00
|
|
|
byte ch = *text++;
|
|
|
|
if (ch < 0x20)
|
|
|
|
continue;
|
|
|
|
if (ch == 0x20) {
|
|
|
|
x += font.getWidth();
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
drawChar2(font, _frontScreen, x, item->rects[j].y, ch, item->color);
|
|
|
|
x += font.getCharWidth(ch) + font.getSpacing() - 1;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int16 Screen::getTalkTextDuration() {
|
|
|
|
return _talkTextItems[_talkTextItemNum].duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::registerFont(uint fontIndex, uint resIndex) {
|
|
|
|
_fontResIndexArray[fontIndex] = resIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::printText(byte *textData) {
|
|
|
|
|
|
|
|
int16 x = 0, y = 0;
|
|
|
|
|
|
|
|
// Really strange stuff.
|
|
|
|
for (int i = 30; i >= 0; i--) {
|
2008-08-04 12:18:15 +00:00
|
|
|
if (textData[i] >= 0xF0)
|
|
|
|
break;
|
2008-08-04 11:28:57 +00:00
|
|
|
if (i == 0)
|
2008-08-04 12:18:15 +00:00
|
|
|
return;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
if (*textData == 0x0A) {
|
|
|
|
// Set text position
|
|
|
|
y = textData[1];
|
|
|
|
x = READ_LE_UINT32(textData + 2);
|
|
|
|
textData += 4;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else if (*textData == 0x0B) {
|
2008-08-04 12:18:15 +00:00
|
|
|
// Inc text position
|
|
|
|
y += textData[1]; // CHECKME: Maybe these are signed?
|
|
|
|
x += textData[2];
|
|
|
|
textData += 3;
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
|
|
|
byte *destString = _tempString;
|
|
|
|
int width = 0;
|
|
|
|
_tempStringLen1 = 0;
|
2008-08-04 12:18:15 +00:00
|
|
|
preprocessText(_fontResIndexArray[1], 640, width, textData, destString, _tempStringLen2);
|
|
|
|
drawString(x - width / 2, y, _fontColor1, _fontColor2, _fontResIndexArray[1]);
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} while (*textData != 0xFF);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::preprocessText(uint fontResIndex, int maxWidth, int &width, byte *&sourceString, byte *&destString, byte &len) {
|
|
|
|
|
|
|
|
Font font(_vm->_res->load(fontResIndex));
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
while (*sourceString >= 0x20 && *sourceString < 0xF0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
byte ch = *sourceString;
|
2008-08-04 11:28:57 +00:00
|
|
|
byte charWidth;
|
2008-08-04 12:18:15 +00:00
|
|
|
if (ch <= 0x20)
|
|
|
|
charWidth = font.getWidth();
|
2008-08-04 11:28:57 +00:00
|
|
|
else
|
|
|
|
charWidth = font.getCharWidth(ch) + font.getSpacing() - 1;
|
|
|
|
if (width + charWidth >= maxWidth)
|
2008-08-04 12:18:15 +00:00
|
|
|
break;
|
2008-08-04 11:28:57 +00:00
|
|
|
len++;
|
|
|
|
width += charWidth;
|
2008-08-04 12:18:15 +00:00
|
|
|
*destString++ = *sourceString++;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawString(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex) {
|
|
|
|
|
|
|
|
debug(0, "Screen::drawString(%d, %d, %d, %d, %d) _tempStringLen1 = %d; _tempStringLen2 = %d", x, y, fontColor1, fontColor2, fontResIndex, _tempStringLen1, _tempStringLen2);
|
|
|
|
|
|
|
|
Font font(_vm->_res->load(fontResIndex));
|
|
|
|
|
|
|
|
byte color = fontColor1;
|
|
|
|
byte *text = _tempString;
|
|
|
|
byte len = _tempStringLen1 + _tempStringLen2;
|
|
|
|
int16 yadd = 1;
|
|
|
|
|
|
|
|
for (byte pos = 0; pos < len; pos++) {
|
2008-08-04 12:18:15 +00:00
|
|
|
if (pos == _tempStringLen1) {
|
|
|
|
color = fontColor2;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
byte ch = *text++;
|
|
|
|
if (ch <= 0x20) {
|
|
|
|
x += font.getWidth();
|
2008-08-04 11:28:57 +00:00
|
|
|
} else {
|
2008-08-04 12:18:15 +00:00
|
|
|
drawChar(font, _frontScreen, x + 1, y + _vm->_cameraHeight - yadd, ch, color);
|
|
|
|
x += font.getCharWidth(ch) + font.getSpacing() - 1;
|
|
|
|
yadd = -yadd;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Merge drawChar and drawChar2
|
|
|
|
|
|
|
|
void Screen::drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color) {
|
|
|
|
|
|
|
|
int16 charWidth, charHeight;
|
|
|
|
byte *charData;
|
|
|
|
|
|
|
|
dest += x + (y * 640);
|
|
|
|
|
|
|
|
charWidth = font.getCharWidth(ch);
|
|
|
|
charHeight = font.getHeight() - 2;
|
|
|
|
charData = font.getCharData(ch);
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
while (charHeight--) {
|
|
|
|
byte lineWidth = charWidth;
|
|
|
|
while (lineWidth > 0) {
|
|
|
|
byte count = charData[0] & 0x0F;
|
|
|
|
byte flags = charData[0] & 0xF0;
|
2008-08-04 11:28:57 +00:00
|
|
|
charData++;
|
|
|
|
lineWidth -= count;
|
|
|
|
if (!(flags & 0x80) && (flags & 0x10)) {
|
2008-08-04 12:18:15 +00:00
|
|
|
memset(dest, color, count);
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
dest += count;
|
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
dest += 640 - charWidth;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::drawChar2(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color) {
|
|
|
|
|
|
|
|
int16 charWidth, charHeight;
|
|
|
|
byte *charData;
|
|
|
|
|
|
|
|
dest += x + (y * 640);
|
|
|
|
|
|
|
|
charWidth = font.getCharWidth(ch);
|
|
|
|
charHeight = font.getHeight() - 2;
|
|
|
|
charData = font.getCharData(ch);
|
|
|
|
|
2008-08-04 12:18:15 +00:00
|
|
|
while (charHeight--) {
|
|
|
|
byte lineWidth = charWidth;
|
|
|
|
while (lineWidth > 0) {
|
|
|
|
byte count = charData[0] & 0x0F;
|
|
|
|
byte flags = charData[0] & 0xF0;
|
2008-08-04 11:28:57 +00:00
|
|
|
charData++;
|
|
|
|
lineWidth -= count;
|
|
|
|
|
|
|
|
if ((flags & 0x80) == 0) {
|
|
|
|
if ((flags & 0x10) == 0) {
|
2008-08-04 12:18:15 +00:00
|
|
|
memset(dest, 0, count);
|
|
|
|
} else {
|
|
|
|
memset(dest, color, count);
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dest += count;
|
|
|
|
}
|
2008-08-04 12:18:15 +00:00
|
|
|
dest += 640 - charWidth;
|
2008-08-04 11:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-08-11 12:43:00 +00:00
|
|
|
void Screen::saveState(Common::WriteStream *out) {
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
out->writeUint16LE(_verbLineItems[i].slotIndex);
|
|
|
|
out->writeUint16LE(_verbLineItems[i].slotOffset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::loadState(Common::ReadStream *in) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-04 11:28:57 +00:00
|
|
|
/*
|
|
|
|
void Screen::update() {
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
} // End of namespace Toltecs
|