mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-20 16:59:06 +00:00
408 lines
9.5 KiB
C++
408 lines
9.5 KiB
C++
/* 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 skipX, 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]);
|
|
}
|
|
int16 getTextWidth(byte *text) {
|
|
int16 width = 0;
|
|
while (*text && *text < 0xF0) {
|
|
byte ch = *text++;
|
|
if (ch <= 0x20) {
|
|
width += getWidth();
|
|
} else {
|
|
width += getCharWidth(ch) + getSpacing() - 1;
|
|
}
|
|
}
|
|
return width;
|
|
}
|
|
|
|
protected:
|
|
byte *_fontData;
|
|
};
|
|
|
|
//*BEGIN*TEST*CODE********************************************************************************************
|
|
|
|
struct PixelPacket {
|
|
byte count;
|
|
byte pixel;
|
|
};
|
|
|
|
enum SpriteReaderStatus {
|
|
kSrsPixelsLeft,
|
|
kSrsEndOfLine,
|
|
kSrsEndOfSprite
|
|
};
|
|
|
|
class SpriteFilter {
|
|
public:
|
|
SpriteFilter(SpriteDrawItem *sprite) : _sprite(sprite) {
|
|
}
|
|
virtual SpriteReaderStatus readPacket(PixelPacket &packet) = 0;
|
|
protected:
|
|
SpriteDrawItem *_sprite;
|
|
};
|
|
|
|
class SpriteReader : public SpriteFilter {
|
|
public:
|
|
SpriteReader(byte *source, SpriteDrawItem *sprite) : SpriteFilter(sprite), _source(source) {
|
|
_curWidth = _sprite->origWidth;
|
|
_curHeight = _sprite->origHeight;
|
|
}
|
|
SpriteReaderStatus readPacket(PixelPacket &packet) {
|
|
if (_sprite->flags & 0x40) {
|
|
// shadow sprite
|
|
packet.count = _source[0] & 0x7F;
|
|
if (_source[0] & 0x80)
|
|
packet.pixel = 1;
|
|
else
|
|
packet.pixel = 0;
|
|
_source++;
|
|
} else if (_sprite->flags & 0x10) {
|
|
// 256-color sprite
|
|
packet.pixel = *_source++;
|
|
packet.count = *_source++;
|
|
} else {
|
|
// 16-color sprite
|
|
packet.count = _source[0] & 0x0F;
|
|
packet.pixel = (_source[0] & 0xF0) >> 4;
|
|
_source++;
|
|
}
|
|
_curWidth -= packet.count;
|
|
if (_curWidth <= 0) {
|
|
_curHeight--;
|
|
if (_curHeight == 0) {
|
|
return kSrsEndOfSprite;
|
|
} else {
|
|
_curWidth = _sprite->origWidth;
|
|
return kSrsEndOfLine;
|
|
}
|
|
} else {
|
|
return kSrsPixelsLeft;
|
|
}
|
|
}
|
|
byte *getSource() {
|
|
return _source;
|
|
}
|
|
void setSource(byte *source) {
|
|
_source = source;
|
|
_curHeight++;
|
|
}
|
|
protected:
|
|
byte *_source;
|
|
int16 _curWidth, _curHeight;
|
|
};
|
|
|
|
class SpriteFilterScaleDown : public SpriteFilter {
|
|
public:
|
|
SpriteFilterScaleDown(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
|
|
_height = _sprite->height;
|
|
_yerror = _sprite->yerror;
|
|
_origHeight = _sprite->origHeight;
|
|
_scalerStatus = 0;
|
|
}
|
|
SpriteReaderStatus readPacket(PixelPacket &packet) {
|
|
SpriteReaderStatus status;
|
|
if (_scalerStatus == 0) {
|
|
_xerror = _sprite->xdelta;
|
|
_yerror -= 100;
|
|
while (_yerror <= 0) {
|
|
do {
|
|
status = _reader->readPacket(packet);
|
|
} while (status == kSrsPixelsLeft);
|
|
_yerror += _sprite->ydelta - 100;
|
|
}
|
|
if (status == kSrsEndOfSprite)
|
|
return kSrsEndOfSprite;
|
|
_scalerStatus = 1;
|
|
}
|
|
if (_scalerStatus == 1) {
|
|
status = _reader->readPacket(packet);
|
|
byte updcount = packet.count;
|
|
while (updcount--) {
|
|
_xerror -= 100;
|
|
if (_xerror <= 0) {
|
|
if (packet.count > 0)
|
|
packet.count--;
|
|
_xerror += _sprite->xdelta;
|
|
}
|
|
}
|
|
if (status == kSrsEndOfLine) {
|
|
if (--_height == 0)
|
|
return kSrsEndOfSprite;
|
|
_scalerStatus = 0;
|
|
return kSrsEndOfLine;
|
|
}
|
|
}
|
|
return kSrsPixelsLeft;
|
|
}
|
|
protected:
|
|
SpriteReader *_reader;
|
|
int16 _xerror, _yerror;
|
|
int16 _height;
|
|
int16 _origHeight;
|
|
int _scalerStatus;
|
|
};
|
|
|
|
class SpriteFilterScaleUp : public SpriteFilter {
|
|
public:
|
|
SpriteFilterScaleUp(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
|
|
_height = _sprite->height;
|
|
_yerror = _sprite->yerror;
|
|
_origHeight = _sprite->origHeight;
|
|
_scalerStatus = 0;
|
|
}
|
|
SpriteReaderStatus readPacket(PixelPacket &packet) {
|
|
SpriteReaderStatus status;
|
|
if (_scalerStatus == 0) {
|
|
_xerror = _sprite->xdelta;
|
|
_sourcep = _reader->getSource();
|
|
_scalerStatus = 1;
|
|
}
|
|
if (_scalerStatus == 1) {
|
|
status = _reader->readPacket(packet);
|
|
byte updcount = packet.count;
|
|
while (updcount--) {
|
|
_xerror -= 100;
|
|
if (_xerror <= 0) {
|
|
packet.count++;
|
|
_xerror += _sprite->xdelta;
|
|
}
|
|
}
|
|
if (status == kSrsEndOfLine) {
|
|
if (--_height == 0)
|
|
return kSrsEndOfSprite;
|
|
_yerror -= 100;
|
|
if (_yerror <= 0) {
|
|
_reader->setSource(_sourcep);
|
|
_yerror += _sprite->ydelta + 100;
|
|
}
|
|
_scalerStatus = 0;
|
|
return kSrsEndOfLine;
|
|
}
|
|
}
|
|
return kSrsPixelsLeft;
|
|
}
|
|
protected:
|
|
SpriteReader *_reader;
|
|
byte *_sourcep;
|
|
int16 _xerror, _yerror;
|
|
int16 _height;
|
|
int16 _origHeight;
|
|
int _scalerStatus;
|
|
};
|
|
|
|
//*END*TEST*CODE**********************************************************************************************
|
|
|
|
struct TextRect {
|
|
int16 x, y;
|
|
int16 width, length;
|
|
};
|
|
|
|
struct TalkTextItem {
|
|
int16 duration;
|
|
int16 slotIndex;
|
|
int16 slotOffset;
|
|
int16 fontNum;
|
|
byte color;
|
|
byte lineCount;
|
|
TextRect lines[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
|
|
void drawSprite(SpriteDrawItem *sprite);
|
|
void drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite);
|
|
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();
|
|
void finishTextDrawItems();
|
|
|
|
// Font/text
|
|
void registerFont(uint fontIndex, uint resIndex);
|
|
void drawGuiTextMulti(byte *textData);
|
|
void wrapGuiText(uint fontResIndex, int maxWidth, int &width, byte *&sourceString, byte *&destString, byte &len);
|
|
void drawGuiText(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex);
|
|
|
|
int16 drawString(int16 x, int16 y, byte color, uint fontResIndex, byte *text, int len = -1, int16 *ywobble = NULL, bool outline = false);
|
|
void drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color, bool outline);
|
|
|
|
void saveState(Common::WriteStream *out);
|
|
void loadState(Common::ReadStream *in);
|
|
|
|
//protected:
|
|
public:
|
|
|
|
struct VerbLineItem {
|
|
int16 slotIndex;
|
|
int16 slotOffset;
|
|
};
|
|
|
|
struct Rect {
|
|
int16 x, y, width, height;
|
|
};
|
|
|
|
ToltecsEngine *_vm;
|
|
|
|
byte *_frontScreen, *_backScreen;
|
|
|
|
Common::List<SpriteDrawItem> _spriteDrawList;
|
|
|
|
uint _fontResIndexArray[10];
|
|
byte _fontColor1, _fontColor2;
|
|
|
|
// TODO: Remove this _tempXXX stuff
|
|
byte _tempString[100];
|
|
byte _tempStringLen1, _tempStringLen2;
|
|
|
|
// 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 */
|