scummvm/engines/toltecs/screen.h

383 lines
8.9 KiB
C
Raw Normal View History

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.
*
*
*/
#ifndef TOLTECS_SCREEN_H
#define TOLTECS_SCREEN_H
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/util.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
#include "common/hash-str.h"
#include "common/events.h"
#include "common/keyboard.h"
#include "common/list.h"
#include "common/array.h"
#include "graphics/surface.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "sound/voc.h"
#include "sound/audiocd.h"
#include "engines/engine.h"
namespace Toltecs {
struct DrawRequest {
int16 x, y;
int16 resIndex;
uint16 flags;
int16 baseColor;
int8 scaling;
};
struct SpriteDrawItem {
int16 x, y;
int16 width, height;
int16 origWidth, origHeight;
int16 resIndex;
uint32 offset;
int16 xdelta, ydelta;
uint16 flags;
int16 value1, yerror;
int16 ybottom;
int16 baseColor;
};
struct SpriteFrameEntry {
int16 y, x, h, w;
uint32 offset;
SpriteFrameEntry() {
}
SpriteFrameEntry(byte *data) {
y = READ_LE_UINT16(data + 0);
x = READ_LE_UINT16(data + 2);
h = READ_LE_UINT16(data + 4);
w = READ_LE_UINT16(data + 6);
offset = READ_LE_UINT32(data + 8);
}
};
class Font {
public:
Font(byte *fontData) : _fontData(fontData) {
}
~Font() {
}
int16 getSpacing() const {
return _fontData[1];
}
int16 getHeight() const {
return _fontData[2];
}
int16 getWidth() const {
return _fontData[3];
}
int16 getCharWidth(byte ch) const {
return _fontData[4 + (ch - 0x21)];
}
byte *getCharData(byte ch) const {
return _fontData + 0x298 + READ_LE_UINT16(&_fontData[0xE0 + (ch - 0x21) * 2]);
}
protected:
byte *_fontData;
};
//*BEGIN*TEST*CODE********************************************************************************************
struct PixelPacket {
byte count;
byte pixel;
};
enum SpriteReaderStatus {
kSrsPixelsLeft,
kSrsEndOfLine,
kSrsEndOfSprite
};
class SpriteFilter {
public:
2008-08-04 12:18:15 +00:00
SpriteFilter(SpriteDrawItem *sprite) : _sprite(sprite) {
2008-08-04 11:28:57 +00:00
}
virtual SpriteReaderStatus readPacket(PixelPacket &packet) = 0;
protected:
2008-08-04 12:18:15 +00:00
SpriteDrawItem *_sprite;
2008-08-04 11:28:57 +00:00
};
class SpriteReader : public SpriteFilter {
public:
2008-08-04 12:18:15 +00:00
SpriteReader(byte *source, SpriteDrawItem *sprite) : SpriteFilter(sprite), _source(source) {
2008-08-04 11:28:57 +00:00
_curWidth = _sprite->origWidth;
_curHeight = _sprite->origHeight;
}
SpriteReaderStatus readPacket(PixelPacket &packet) {
if ((_sprite->flags & 0x40) || (_sprite->flags & 0x10)) {
packet.pixel = *_source++;
packet.count = *_source++;
} else {
packet.count = _source[0] & 0x0F;
packet.pixel = (_source[0] & 0xF0) >> 4;
_source++;
}
_curWidth -= packet.count;
if (_curWidth <= 0) {
2008-08-04 12:18:15 +00:00
_curHeight--;
if (_curHeight == 0) {
return kSrsEndOfSprite;
2008-08-04 11:28:57 +00:00
} else {
2008-08-04 12:18:15 +00:00
_curWidth = _sprite->origWidth;
return kSrsEndOfLine;
2008-08-04 11:28:57 +00:00
}
} else {
2008-08-04 12:18:15 +00:00
return kSrsPixelsLeft;
2008-08-04 11:28:57 +00:00
}
}
byte *getSource() {
2008-08-04 12:18:15 +00:00
return _source;
2008-08-04 11:28:57 +00:00
}
void setSource(byte *source) {
2008-08-04 12:18:15 +00:00
_source = source;
_curHeight++;
2008-08-04 11:28:57 +00:00
}
protected:
byte *_source;
int16 _curWidth, _curHeight;
};
class SpriteFilterScaleDown : public SpriteFilter {
public:
2008-08-04 12:18:15 +00:00
SpriteFilterScaleDown(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
2008-08-04 11:28:57 +00:00
_height = _sprite->height;
_yerror = _sprite->yerror;
_origHeight = _sprite->origHeight;
_scalerStatus = 0;
}
SpriteReaderStatus readPacket(PixelPacket &packet) {
2008-08-04 12:18:15 +00:00
SpriteReaderStatus status;
2008-08-04 11:28:57 +00:00
if (_scalerStatus == 0) {
_xerror = _sprite->xdelta;
_yerror -= 100;
while (_yerror <= 0) {
2008-08-04 12:18:15 +00:00
do {
status = _reader->readPacket(packet);
2008-08-04 11:28:57 +00:00
} while (status == kSrsPixelsLeft);
_yerror += _sprite->ydelta - 100;
}
if (status == kSrsEndOfSprite)
2008-08-04 12:18:15 +00:00
return kSrsEndOfSprite;
_scalerStatus = 1;
2008-08-04 11:28:57 +00:00
}
if (_scalerStatus == 1) {
2008-08-04 12:18:15 +00:00
status = _reader->readPacket(packet);
byte updcount = packet.count;
while (updcount--) {
2008-08-04 11:28:57 +00:00
_xerror -= 100;
if (_xerror <= 0) {
2008-08-04 12:18:15 +00:00
if (packet.count > 0)
packet.count--;
_xerror += _sprite->xdelta;
2008-08-04 11:28:57 +00:00
}
}
if (status == kSrsEndOfLine) {
if (--_height == 0)
return kSrsEndOfSprite;
2008-08-04 12:18:15 +00:00
_scalerStatus = 0;
return kSrsEndOfLine;
2008-08-04 11:28:57 +00:00
}
}
return kSrsPixelsLeft;
}
protected:
2008-08-04 12:18:15 +00:00
SpriteReader *_reader;
2008-08-04 11:28:57 +00:00
int16 _xerror, _yerror;
int16 _height;
int16 _origHeight;
int _scalerStatus;
};
class SpriteFilterScaleUp : public SpriteFilter {
public:
2008-08-04 12:18:15 +00:00
SpriteFilterScaleUp(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
2008-08-04 11:28:57 +00:00
_height = _sprite->height;
_yerror = _sprite->yerror;
_origHeight = _sprite->origHeight;
_scalerStatus = 0;
}
SpriteReaderStatus readPacket(PixelPacket &packet) {
2008-08-04 12:18:15 +00:00
SpriteReaderStatus status;
if (_scalerStatus == 0) {
2008-08-04 11:28:57 +00:00
_xerror = _sprite->xdelta;
_sourcep = _reader->getSource();
2008-08-04 12:18:15 +00:00
_scalerStatus = 1;
2008-08-04 11:28:57 +00:00
}
if (_scalerStatus == 1) {
2008-08-04 12:18:15 +00:00
status = _reader->readPacket(packet);
byte updcount = packet.count;
2008-08-04 11:28:57 +00:00
while (updcount--) {
2008-08-04 12:18:15 +00:00
_xerror -= 100;
if (_xerror <= 0) {
packet.count++;
_xerror += _sprite->xdelta;
2008-08-04 11:28:57 +00:00
}
}
if (status == kSrsEndOfLine) {
if (--_height == 0)
return kSrsEndOfSprite;
2008-08-04 12:18:15 +00:00
_yerror -= 100;
2008-08-04 11:28:57 +00:00
if (_yerror <= 0) {
2008-08-04 12:18:15 +00:00
_reader->setSource(_sourcep);
2008-08-04 11:28:57 +00:00
_yerror += _sprite->ydelta + 100;
}
2008-08-04 12:18:15 +00:00
_scalerStatus = 0;
return kSrsEndOfLine;
2008-08-04 11:28:57 +00:00
}
}
return kSrsPixelsLeft;
}
protected:
2008-08-04 12:18:15 +00:00
SpriteReader *_reader;
byte *_sourcep;
2008-08-04 11:28:57 +00:00
int16 _xerror, _yerror;
int16 _height;
int16 _origHeight;
int _scalerStatus;
};
//*END*TEST*CODE**********************************************************************************************
struct TextRect {
2008-08-04 12:18:15 +00:00
int16 x, y;
2008-08-04 11:28:57 +00:00
int16 width, length;
};
struct TalkTextItem {
int16 duration;
int16 slotIndex;
int16 slotOffset;
int16 fontNum;
byte color;
byte rectCount;
TextRect rects[15];
};
class Screen {
public:
Screen(ToltecsEngine *vm);
~Screen();
void unpackRle(byte *source, byte *dest, uint16 width, uint16 height);
void loadMouseCursor(uint resIndex);
void drawGuiImage(int16 x, int16 y, uint resIndex);
void startShakeScreen(int16 shakeCounter);
void stopShakeScreen();
void updateShakeScreen();
// Sprite list
void addStaticSprite(byte *spriteItem);
void addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode);
void clearSprites();
// Sprite drawing
2008-08-04 12:18:15 +00:00
void drawSprite(SpriteDrawItem *sprite);
void drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite);
2008-08-04 11:28:57 +00:00
void drawSprites();
// Verb line
void updateVerbLine(int16 slotIndex, int16 slotOffset);
// Talk text
void updateTalkText(int16 slotIndex, int16 slotOffset);
void addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item);
void drawTalkTextItems();
int16 getTalkTextDuration();
// Font/text
void registerFont(uint fontIndex, uint resIndex);
void printText(byte *textData);
void preprocessText(uint fontResIndex, int maxWidth, int &width, byte *&sourceString, byte *&destString, byte &len);
void drawString(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex);
void drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color);
void drawChar2(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color);
void saveState(Common::WriteStream *out);
void loadState(Common::ReadStream *in);
2008-08-04 11:28:57 +00:00
//protected:
public:
struct VerbLineItem {
2008-08-04 12:18:15 +00:00
int16 slotIndex;
2008-08-04 11:28:57 +00:00
int16 slotOffset;
};
struct Rect {
2008-08-04 12:18:15 +00:00
int16 x, y, width, height;
2008-08-04 11:28:57 +00:00
};
ToltecsEngine *_vm;
byte *_frontScreen, *_backScreen;
Common::List<SpriteDrawItem> _spriteDrawList;
2008-08-04 12:18:15 +00:00
uint _fontResIndexArray[10];
byte _fontColor1, _fontColor2;
// TODO: Remove this _tempXXX stuff
2008-08-04 12:18:15 +00:00
byte _tempString[100];
byte _tempStringLen1, _tempStringLen2;
2008-08-04 11:28:57 +00:00
// Screen shaking
bool _shakeActive;
int16 _shakeCounterInit, _shakeCounter;
int _shakePos;
// Verb line
int16 _verbLineNum;
VerbLineItem _verbLineItems[8];
int16 _verbLineX, _verbLineY, _verbLineWidth;
int16 _verbLineCount;
// Talk text
int16 _talkTextX, _talkTextY;
int16 _talkTextMaxWidth;
byte _talkTextFontColor;
int16 _talkTextItemNum;
TalkTextItem _talkTextItems[5];
void addDrawRequest(const DrawRequest &drawRequest);
};
} // End of namespace Toltecs
#endif /* TOLTECS_SCREEN_H */