From e31e9dbae17ab707fd50b7a29bdbdf0889fe1811 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 2 Jul 2019 00:46:12 +0200 Subject: HDB: Renamed draw-manager.* -> gfx.* --- engines/hdb/draw-manager.cpp | 793 ------------------------------------------- engines/hdb/draw-manager.h | 242 ------------- engines/hdb/gfx.cpp | 793 +++++++++++++++++++++++++++++++++++++++++++ engines/hdb/gfx.h | 242 +++++++++++++ engines/hdb/hdb.h | 2 +- engines/hdb/module.mk | 2 +- 6 files changed, 1037 insertions(+), 1037 deletions(-) delete mode 100644 engines/hdb/draw-manager.cpp delete mode 100644 engines/hdb/draw-manager.h create mode 100644 engines/hdb/gfx.cpp create mode 100644 engines/hdb/gfx.h diff --git a/engines/hdb/draw-manager.cpp b/engines/hdb/draw-manager.cpp deleted file mode 100644 index 852718f101..0000000000 --- a/engines/hdb/draw-manager.cpp +++ /dev/null @@ -1,793 +0,0 @@ -/* 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 "hdb/hdb.h" - -namespace HDB { - -DrawMan::DrawMan() { - _tLookupArray = NULL; - _gfxCache = new Common::Array; - _globalSurface.create(kScreenWidth, kScreenHeight, g_hdb->_format); - _pointerDisplayable = 1; - _systemInit = false; -} - -DrawMan::~DrawMan() { - delete _gfxCache; - _globalSurface.free(); -} - -bool DrawMan::init() { - - // Set the default cursor pos & char clipping - setCursor(0, 0); - - _eLeft = 0; - _eRight = kScreenWidth; - _eTop = 0; - _eBottom = kScreenHeight; - - // Load Game Font - if (!loadFont("normalprop")) - return false; - - // Read total number of tiles in game - _numTiles = g_hdb->_fileMan->getCount("t32_", TYPE_TILE32); - if (!_numTiles) { - return false; - } - - // Setup Tile Lookup Array - _tLookupArray = new TileLookup[_numTiles]; - Common::Array tileData = *g_hdb->_fileMan->findFiles("t32_", TYPE_TILE32); - - assert((uint)_numTiles == tileData.size()); - - int index = 0, skyIndex = 0; - for (; index < _numTiles; index++) { - _tLookupArray[index].filename = tileData[index]; - _tLookupArray[index].tData = NULL; - _tLookupArray[index].skyIndex = 0; - _tLookupArray[index].animIndex = index; - // Check if the loaded Tile is a Sky Tile - if (((Common::String)tileData[index]).contains("sky") && (skyIndex < kMaxSkies)) { - _tLookupArray[index].skyIndex = skyIndex + 1; - _skyTiles[skyIndex] = index; - skyIndex++; - } - } - - - // Add Animating Tile Info - int found = -1; - char search[32]; - strcpy(search, "anim_"); - for (index = 0; index < _numTiles; index++) { - // IF we have not found a start, look for it - // ELSE IF we have found a start and are in the middle of an anim group - // ELSE IF we're in an anim group and have just reached the end - if (!strncmp(_tLookupArray[index].filename, search, strlen(search)) && found == -1) { - found = index; - strncpy(search, _tLookupArray[index].filename, strlen(_tLookupArray[index].filename) - 2); - } else if (!strncmp(_tLookupArray[index].filename, search, strlen(search)) && found >= 0) - _tLookupArray[index - 1].animIndex = index; - else if (strncmp(_tLookupArray[index].filename, search, strlen(search)) && found >= 0) { - _tLookupArray[index - 1].animIndex = found; - strcpy(search, "anim_"); - found = -1; - if (!strncmp(_tLookupArray[index].filename, search, strlen(search))) - index--; - } - } - - // Init Sky Data - _currentSky = 0; - _tileSkyStars = getTileIndex("t32_sky_stars"); - _tileSkyStarsLeft = getTileIndex("t32_sky_stars_left_slow"); - _tileSkyClouds = getTileIndex("t32_sky_clouds"); // Not completely sure about this filename. - _skyClouds = NULL; - - /* - TODO: Setup Gamma Table - */ - - // Load Mouse Pointer and Display Cursor - _mousePointer[0] = loadPic(PIC_MOUSE_CURSOR1); - _mousePointer[1] = loadPic(PIC_MOUSE_CURSOR2); - _mousePointer[2] = loadPic(PIC_MOUSE_CURSOR3); - _mousePointer[3] = loadPic(PIC_MOUSE_CURSOR4); - _mousePointer[4] = loadPic(PIC_MOUSE_CURSOR5); - _mousePointer[5] = loadPic(PIC_MOUSE_CURSOR6); - _mousePointer[6] = loadPic(PIC_MOUSE_CURSOR7); - _mousePointer[7] = loadPic(PIC_MOUSE_CURSOR8); - _showCursor = true; - - // Load all 4 levels of star colors - _starField[0] = getPicture("pic_star64"); - _starField[1] = getPicture("pic_star128"); - _starField[2] = getPicture("pic_star192"); - _starField[3] = getPicture("pic_star256"); - - /* - TODO: Load the snowflake - */ - - _systemInit = true; - return true; -} - -void DrawMan::fillScreen(uint32 color) { - _globalSurface.fillRect(Common::Rect(kScreenWidth, kScreenHeight), color); - g_system->fillScreen(color); -} - -void DrawMan::updateVideo() { - updateFade(); - debug(9, "STUB: DrawMan::updateVideo incomplete"); -} - -void DrawMan::drawPointer() { - static int anim = 0; - static uint32 animTime = 0; - - if (animTime < g_system->getMillis()) { - animTime = g_system->getMillis() + 50; - anim = (anim + 1) & 7; - } - - // If pointer is not displayable and we are in game, exit - if (!_pointerDisplayable && g_hdb->getGameState() == GAME_PLAY) - return; - - // If we are in game and the cursor should be displayed, draw it - if (_showCursor || g_hdb->getGameState() != GAME_PLAY) - _mousePointer[anim]->drawMasked(g_hdb->_input->getMouseX() - 16, g_hdb->_input->getMouseY() - 16); -} - -void DrawMan::setPointerState(int value) { - _pointerDisplayable = value; -} - -void DrawMan::setFade(bool fadeIn, bool black, int steps) { - _fadeInfo.isFadeIn = fadeIn; - _fadeInfo.isBlack = black; - - if (!steps) { - steps = 1; - } - _fadeInfo.speed = steps; - - if (fadeIn) { - _fadeInfo.curStep = 0; - } else { - _fadeInfo.curStep = 255; - } - - _fadeInfo.active = true; -} - -void DrawMan::updateFade() { - _fadeInfo.active = false; - debug(9, "STUB: DrawMan::updateFade incomplete"); -} - -Picture *DrawMan::loadPic(const char *picName) { - Picture *pic = new Picture; - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(picName, TYPE_PIC); - if (!stream) - return NULL; - pic->load(stream); - return pic; -} - -Tile *DrawMan::loadTile(const char *tileName) { - Tile *tile = new Tile; - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(tileName, TYPE_TILE32); - if (!stream) - return NULL; - tile->load(stream); - return tile; -} - -Tile *DrawMan::getTile(int index) { - - if (index < 0 || index > _numTiles) { - if (index != 0xFFFF) - debug(6, "getTile(%d): wrong index > %d", index, _numTiles); - return NULL; - } - if (_tLookupArray[index].skyIndex) { - debug(6, "getTile(%d): sky tile (%d)", index, _tLookupArray[index].skyIndex); - // We don't draw Sky Tiles, so return NULL - return NULL; - } - - if (_tLookupArray[index].tData == NULL) { - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(_tLookupArray[index].filename, TYPE_TILE32); - Tile *tile = new Tile; - tile->load(stream); - _tLookupArray[index].tData = tile; - } - - return _tLookupArray[index].tData; -} - -void DrawMan::cacheTileSequence(int tileIndex, int count) { - for (int i = tileIndex; i < tileIndex + count; i++) - getTile(i); -} - -int DrawMan::getTileIndex(const char *name) { - if (!name) { - return -1; - } - for (int i = 0; i < _numTiles; i++) { - if (Common::matchString(_tLookupArray[i].filename, name)) { - return i; - } - } - return -1; -} - -Picture *DrawMan::getPicture(const char *name) { - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(name, TYPE_PIC); - Picture *picture = new Picture; - picture->load(stream); - return picture; -} - -// Returns: true->Tile, false->Pic -bool DrawMan::selectGfxType(const char *name) { - // Check for Pic types - if (Common::matchString(name, "clubup1")) - return false; - if (Common::matchString(name, "clubup2")) - return false; - if (Common::matchString(name, "clubup3")) - return false; - if (Common::matchString(name, "clubup4")) - return false; - if (Common::matchString(name, "clubdown1")) - return false; - if (Common::matchString(name, "clubdown2")) - return false; - if (Common::matchString(name, "clubdown3")) - return false; - if (Common::matchString(name, "clubdown4")) - return false; - if (Common::matchString(name, "clubleft1")) - return false; - if (Common::matchString(name, "clubleft2")) - return false; - if (Common::matchString(name, "clubleft3")) - return false; - if (Common::matchString(name, "clubleft4")) - return false; - if (Common::matchString(name, "clubright1")) - return false; - if (Common::matchString(name, "clubright2")) - return false; - if (Common::matchString(name, "clubright3")) - return false; - if (Common::matchString(name, "clubright4")) - return false; - if (Common::matchString(name, "slug_shot1")) - return false; - if (Common::matchString(name, "slug_shot2")) - return false; - if (Common::matchString(name, "slug_shot3")) - return false; - if (Common::matchString(name, "slug_shot4")) - return false; - - return true; -} - -Tile *DrawMan::getTileGfx(const char *name, uint32 size) { - // Try to find graphic - for (Common::Array::iterator it = _gfxCache->begin(); it != _gfxCache->end(); it++) { - if (Common::matchString((*it)->name, name)) { - if ((*it)->loaded == -1) { // Marked for Deletetion? - (*it)->loaded = 1; // Reactivate it - return (*it)->tileGfx; - } - } - } - - GfxCache *gc = new GfxCache; - strcpy(gc->name, name); - - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(name, TYPE_TILE32); - - Tile *gfxTile = new Tile; - gfxTile->load(stream); - - gc->tileGfx = gfxTile; - gc->size = size; - gc->loaded = 1; - - _gfxCache->push_back(gc); - - return gc->tileGfx; -} - -Picture *DrawMan::getPicGfx(const char *name, uint32 size) { - // Try to find graphic - for (Common::Array::iterator it = _gfxCache->begin(); it != _gfxCache->end(); it++) { - if (Common::matchString((*it)->name, name)) { - if ((*it)->loaded == -1) { // Marked for Deletetion? - (*it)->loaded = 1; // Reactivate it - return (*it)->picGfx; - } - } - } - - GfxCache *gc = new GfxCache; - strcpy(gc->name, name); - - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(name, TYPE_TILE32); - - Picture *gfxPic = new Picture; - gfxPic->load(stream); - - gc->picGfx = gfxPic; - gc->size = size; - gc->loaded = 1; - - _gfxCache->push_back(gc); - - return gc->picGfx; -} - -int DrawMan::isSky(int index) { - if (!index) { - return 0; - } - - for (int i = 0; i < kMaxSkies; i++) { - if(_skyTiles[i] == index) { - return i + 1; // The skyTiles are indexed from 1. 0 => No Sky tile - } - } - - return 0; -} - -void DrawMan::setSky(int skyIndex) { - int tileIndex = _skyTiles[skyIndex - 1]; - _currentSky = skyIndex; - - // Clear memory used by last sky - if (tileIndex != _tileSkyClouds && _skyClouds) { - delete _skyClouds; - _skyClouds = NULL; - } - - // Setup current sky - if (tileIndex == _tileSkyStars) { - setup3DStars(); - return; - } else if (skyIndex == _tileSkyStarsLeft) { - setup3DStarsLeft(); - return; - } else if (skyIndex == _tileSkyStars) { - _skyClouds = getPicture("cloudy_skies"); - return; - } -} - -void DrawMan::setup3DStars() { - for (int i = 0; i < kNum3DStars; i++) { - _stars3D[i].x = g_hdb->_rnd->getRandomNumber(kScreenWidth); - _stars3D[i].y = g_hdb->_rnd->getRandomNumber(kScreenHeight); - _stars3D[i].speed = g_hdb->_rnd->getRandomNumber(256); - _stars3D[i].speed >>= 1; - _stars3D[i].color = _stars3D[i].speed / 64; - } -} - -void DrawMan::setup3DStarsLeft() { - for (int i = 0; i < kNum3DStars; i++) { - _stars3DSlow[i].x = g_hdb->_rnd->getRandomNumber(kScreenWidth); - _stars3DSlow[i].y = g_hdb->_rnd->getRandomNumber(kScreenHeight); - _stars3DSlow[i].speed = ((double) (1 + g_hdb->_rnd->getRandomNumber(5))) / 6.0; - _stars3DSlow[i].color = (int) (_stars3DSlow[i].speed * 4.00); - } -} - -void DrawMan::draw3DStars() { - fillScreen(0); - for (int i = 0; i < kNum3DStars; i++) { - _starField[_stars3D[i].color]->drawMasked((int)_stars3D[i].x, (int)_stars3D[i].y); - _stars3D[i].y += (_stars3D[i].speed >> 5) + 1; - if (_stars3D[i].y > kScreenHeight) { - _stars3D[i].y = 0; - } - } -} - -void DrawMan::draw3DStarsLeft() { - fillScreen(0); - for (int i = 0; i < kNum3DStars; i++) { - _starField[_stars3DSlow[i].color]->drawMasked((int)_stars3DSlow[i].x, (int)_stars3DSlow[i].y); - _stars3DSlow[i].x -= _stars3DSlow[i].speed; - if (_stars3DSlow[i].x < kScreenWidth) { - _stars3DSlow[i].x = kScreenWidth - 1; - } - } -} - -void DrawMan::drawSky() { - int tile = _skyTiles[_currentSky - 1]; - - if (tile == _tileSkyStars) { - draw3DStars(); - } - else if (tile == _tileSkyStarsLeft) { - draw3DStarsLeft(); - } - else if (tile == _tileSkyClouds) { - static int offset = 0, wait = 0; - for (int j = -64; j < kScreenHeight; j += 64) { - for (int i = -64; i < kScreenWidth; i += 64) { - _skyClouds->draw(i + offset, j + offset); - } - } - wait--; - if (wait < 1) { - offset = (offset + 1) & 63; - wait = 5; - } - } -} - -int DrawMan::animateTile(int tileIndex) { - return _tLookupArray[tileIndex].animIndex; -} - -bool DrawMan::loadFont(const char *string) { - Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(string, TYPE_FONT); - if (!stream) - return false; - - // Loading _fontHeader - _fontHeader.type = (int)stream->readUint32LE(); - _fontHeader.numChars = (int)stream->readUint32LE(); - _fontHeader.height = (int)stream->readUint32LE(); - _fontHeader.kerning = (int)stream->readUint32LE(); - _fontHeader.leading = (int)stream->readUint32LE(); - - debug(3, "Loaded _fontHeader with following data"); - debug(3, "type: %d", _fontHeader.type); - debug(3, "numChars: %d", _fontHeader.numChars); - debug(3, "height: %d", _fontHeader.height); - debug(3, "kerning: %d", _fontHeader.kerning); - debug(3, "leading: %d", _fontHeader.leading); - - // Loading _charInfoBlocks & creating character surfaces - CharInfo *cInfo; - int startPos = stream->pos(); // Position after _fontHeader - int curPos; // Position after reading cInfo - uint16 *ptr; - for (int i = 0; i < _fontHeader.numChars; i++) { - cInfo = new CharInfo; - cInfo->width = (int16)stream->readUint32LE(); - cInfo->offset = (int32)stream->readUint32LE(); - - debug(3, "Loaded _charInfoBlocks[%d]: width: %d, offset: %d", i, cInfo->width, cInfo->offset); - - curPos = stream->pos(); - - _fontSurfaces[i].create(cInfo->width, _fontHeader.height, g_hdb->_format); - - // Go to character location - stream->seek(startPos+cInfo->offset); - - for (int y = 0; y < _fontHeader.height; y++) { - ptr = (uint16 *)_fontSurfaces[i].getBasePtr(0, y); - for (int x = 0; x < cInfo->width; x++) { - *ptr = TO_LE_16(stream->readUint16LE()); - ptr++; - } - } - - stream->seek(curPos); - - _charInfoBlocks.push_back(cInfo); - } - - // Loading _fontGfx - _fontGfx = stream->readUint16LE(); - - return true; -} - -void DrawMan::drawText(const char *string) { - if (!_systemInit) - return; - - if (_cursorX < _eLeft) - _cursorX = _eLeft; - if (_cursorY < _eTop) - _cursorY = _eTop; - - // Word Wrapping - int width = _eLeft; - unsigned char c; - char cr[256]; // Carriage Return Array - - for (int i = 0; i < (int)strlen(string); i++) { - c = string[i]; - width += _charInfoBlocks[c]->width + _fontHeader.kerning + kFontIncrement; - if (c == ' ') - width += kFontSpace; - - cr[i] = 0; - if (c == '\n') { - cr[i] = 1; - width = _eLeft; - } else if (width > _eRight) { - i--; - while (string[i] != ' ' && i > 0) - i--; - cr[i] = 1; - width = _eLeft; - } - } - - // Draw the characters - for (int j = 0; j < (int)strlen(string); j++) { - c = string[j]; - if (c == '\n' || cr[j]) { - _cursorX = _eLeft; - _cursorY += _fontHeader.height + _fontHeader.leading; - if (_cursorY + _fontHeader.height > _eBottom) - _cursorY = _eTop; - continue; - } - - width = _charInfoBlocks[c]->width; - if (c == ' ') - width = kFontSpace; - - // Blit the character - g_hdb->_drawMan->_globalSurface.transBlitFrom(_fontSurfaces[c], Common::Point(_cursorX, _cursorY), 0xf81f); - - Common::Rect clip(0, 0, width, _fontHeader.height); - clip.moveTo(_cursorX, _cursorY); - clip.clip(_globalSurface.getBounds()); - if (!clip.isEmpty()) { - g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); - } - - // Advance the cursor - _cursorX += width + _fontHeader.kerning + kFontIncrement; - if (_cursorX > kScreenWidth) { - _cursorX = 0; - _cursorY += _fontHeader.height + _fontHeader.leading; - if (_cursorY + _fontHeader.height > kScreenHeight) - _cursorY = 0; - } - } -} - -// Calculates pixel width of a string -void DrawMan::getDimensions(const char *string, int *pixelsWide, int *lines) { - if (!string) { - *pixelsWide = kFontSpace; - *lines = 1; - return; - } - - int width, maxWidth, height; - unsigned char c; - maxWidth = 0; - width = _eLeft; - height = 1; - - for (int i = 0; i < (int)strlen(string); i++) { - c = string[i]; - width += _charInfoBlocks[c]->width + _fontHeader.kerning + kFontIncrement; - if (c == ' ') - width += kFontSpace; - - if (c == '\n') { - height++; - if (width > maxWidth) - maxWidth = width; - width = _eLeft; - } else if (width > _eRight) { - int oldWidth = width; - i--; - while (string[i] != ' ' && i > 0) { - c = string[i]; - width -= _charInfoBlocks[c]->width + _fontHeader.kerning + kFontIncrement; - i--; - } - if (!i) { - maxWidth = oldWidth; - break; - } - height++; - if (width > maxWidth) - maxWidth = width; - width = _eLeft; - } - } - - if (width > maxWidth) - maxWidth = width; - - // If its one line, add 8 pixels - if (height == 1) - maxWidth += 8; - - *pixelsWide = maxWidth - _eLeft; - *lines = height; -} - -int DrawMan::stringLength(const char *string) { - int w, h; - getDimensions(string, &w, &h); - return w; -} - -void DrawMan::setTextEdges(int left, int right, int top, int bottom) { - _eLeft = left; - _eRight = right; - _eTop = top; - _eBottom = bottom; -} - -void DrawMan::getTextEdges(int *left, int *right, int *top, int *bottom) { - *left = _eLeft; - *right = _eRight; - *top = _eTop; - *bottom = _eBottom; -} - -void DrawMan::setKernLead(int kern, int lead) { - _fontHeader.kerning = kern; - _fontHeader.leading = lead; -} - -void DrawMan::getKernLead(int *kern, int *lead) { - *kern = _fontHeader.kerning; - *lead = _fontHeader.leading; -} - -void DrawMan::setCursor(int x, int y) { - _cursorX = x; - _cursorY = y; -} - -void DrawMan::getCursor(int *x, int *y) { - *x = _cursorX; - *y = _cursorY; -} - -Picture::Picture() : _width(0), _height(0), _name("") { - _surface.create(_width, _height, g_hdb->_format); -} - -Picture::~Picture() { - _surface.free(); -} - -Graphics::Surface Picture::load(Common::SeekableReadStream *stream) { - _width = stream->readUint32LE(); - _height = stream->readUint32LE(); - stream->read(_name, 64); - - debug(8, "Picture: _width: %d, _height: %d", _width, _height); - debug(8, "Picture: _name: %s", _name); - - _surface.create(_width, _height, g_hdb->_format); - stream->readUint32LE(); // Skip Win32 Surface - - uint16 *ptr; - - for (uint y = 0; y < _height; y++) { - ptr = (uint16 *)_surface.getBasePtr(0, y); - for (uint x = 0; x < _width; x++) { - *ptr = TO_LE_16(stream->readUint16LE()); - ptr++; - } - } - - return _surface; -} - -void Picture::draw(int x, int y) { - g_hdb->_drawMan->_globalSurface.blitFrom(_surface, Common::Point(x, y)); - - Common::Rect clip(_surface.getBounds()); - clip.moveTo(x, y); - clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); - if (!clip.isEmpty()) { - g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); - } -} - -void Picture::drawMasked(int x, int y) { - g_hdb->_drawMan->_globalSurface.transBlitFrom(_surface, Common::Point(x, y), 0xf81f); - - Common::Rect clip(_surface.getBounds()); - clip.moveTo(x, y); - clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); - if (!clip.isEmpty()) { - g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); - } -} - -Tile::Tile() : _flags(0), _name("") { - _surface.create(32, 32, g_hdb->_format); -} - -Tile::~Tile() { - _surface.free(); -} - -Graphics::Surface Tile::load(Common::SeekableReadStream *stream) { - _flags = stream->readUint32LE(); - stream->read(_name, 64); - - _surface.create(32, 32, g_hdb->_format); - stream->readUint32LE(); // Skip Win32 Surface - - uint16 *ptr; - - for (uint y = 0; y < 32; y++) { - ptr = (uint16 *)_surface.getBasePtr(0, y); - for (uint x = 0; x < 32; x++) { - *ptr = TO_LE_16(stream->readUint16LE()); - ptr++; - } - } - - return _surface; -} - -void Tile::draw(int x, int y) { - g_hdb->_drawMan->_globalSurface.blitFrom(_surface, Common::Point(x, y)); - - Common::Rect clip(_surface.getBounds()); - clip.moveTo(x, y); - clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); - if (!clip.isEmpty()) { - g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); - } -} - -void Tile::drawMasked(int x, int y) { - g_hdb->_drawMan->_globalSurface.transBlitFrom(_surface, Common::Point(x, y), 0xf81f); - - Common::Rect clip(_surface.getBounds()); - clip.moveTo(x, y); - clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); - if (!clip.isEmpty()) { - g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); - } -} - -} diff --git a/engines/hdb/draw-manager.h b/engines/hdb/draw-manager.h deleted file mode 100644 index 1ace112993..0000000000 --- a/engines/hdb/draw-manager.h +++ /dev/null @@ -1,242 +0,0 @@ -/* 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 HDB_DRAW_MANAGER_H -#define HDB_DRAW_MANAGER_H - -#include "graphics/managed_surface.h" - -#include "hdb/hdb.h" - -namespace HDB { - -enum { - kScreenWidth = 640, - kScreenHeight = 480, - kTileWidth = 32, - kTileHeight = 32, - kMaxSkies = 10, - kNum3DStars = 300, - kFontSpace = 5, - kFontIncrement = 1, - kGameFPS = 60, - kAnimFrameDelay = kGameFPS / 30, - kAnimSlowFrames = kAnimFrameDelay * 10, - kAnimMediumFrames = kAnimFrameDelay * 6, - kAnimFastFrames = kAnimFrameDelay * 2 -}; - -class Tile; -class Picture; - -struct TileLookup { - const char *filename; - Tile *tData; - uint16 skyIndex; - uint16 animIndex; - - TileLookup() : filename(NULL), tData(NULL), skyIndex(0), animIndex(0) {} -}; - -struct GfxCache { - char name[32]; - union { - Tile *tileGfx; - Picture *picGfx; - }; - uint32 size; - int16 loaded; - - GfxCache() : name(""), tileGfx(NULL), size(0), loaded(0) {} -}; - -struct FontInfo { - int type; // 0 = mono, 1 = proportional - int numChars; // how many characters in font - int height; // height of entire font - int kerning; // space between chars - int leading; // space between lines -}; - -struct CharInfo { - int16 width; // Character width in pixels - int32 offset; // From the start of the font charInfo chunk -}; - -class DrawMan { -public: - - DrawMan(); - ~DrawMan(); - - Graphics::ManagedSurface _globalSurface; - - bool init(); - void fillScreen(uint32 color); - void updateVideo(); - void setPointerState(int value); - void drawPointer(); - void showPointer(bool status) { - _showCursor = status; - } - bool getPointer() { - return _showCursor; - } - - void setFade(bool fadeIn, bool black, int steps); - void updateFade(); - bool isFadeActive() { return _fadeInfo.active; } - bool isFadeStaying() { return _fadeInfo.stayFaded; } - void turnOffFade() { _fadeInfo.active = _fadeInfo.stayFaded = false; } - - Picture *loadPic(const char *picName); - Tile *loadTile(const char *tileName); - - Tile *getTile(int index); - void cacheTileSequence(int index, int count); - int getTileIndex(const char *name); - Picture *getPicture(const char *name); - - // Returns: true->Tile, false->Pic - bool selectGfxType(const char *name); - Tile *getTileGfx(const char *name, uint32 size); - Picture *getPicGfx(const char *name, uint32 size); - - int isSky(int skyIndex); - void setSky(int skyIndex); - void setup3DStars(); - void setup3DStarsLeft(); - void draw3DStars(); - void draw3DStarsLeft(); - void drawSky(); - - int animateTile(int tileIndex); - - // Font Functions - - bool loadFont(const char *string); - void drawText(const char *string); - void getDimensions(const char *string, int *pixelsWide, int *lines); - int stringLength(const char *string); - void setTextEdges(int left, int right, int top, int bottom); - void getTextEdges(int *left, int *right, int *top, int *bottom); - void setKernLead(int kern, int lead); - void getKernLead(int *kern, int *lead); - void setCursor(int x, int y); - void getCursor(int *x, int *y); - -private: - int _numTiles; - TileLookup *_tLookupArray; - uint16 _skyTiles[kMaxSkies]; - - Common::Array *_gfxCache; - - int _currentSky; // 0 if no Sky, 1+ for which Sky to use - struct { - bool active; - bool stayFaded; - bool isBlack; - int speed; - bool isFadeIn; - - int curStep; - } _fadeInfo; - - struct { - int x, y, speed; - uint16 color; - } _stars3D[kNum3DStars]; - - struct { - double x, y, speed; - uint16 color; - } _stars3DSlow[kNum3DStars]; - - int _tileSkyStars; // Index of sky_stars tile - int _tileSkyStarsLeft; // Left-scrolling stars, slow - int _tileSkyClouds; // Index of sky_stars tile - Picture *_starField[4]; - Picture *_skyClouds; - - // Cursor - int _cursorX, _cursorY; - Picture *_mousePointer[8]; // Gfx for screen pointer (4 Animations) - int _pointerDisplayable; - bool _showCursor; - - // Font Data - - FontInfo _fontHeader; - Common::Array _charInfoBlocks; - Graphics::Surface _fontSurfaces[256]; - uint16 _fontGfx; - int _eLeft, _eRight, _eTop, _eBottom; - - bool _systemInit; - -}; - -class Picture { -public: - - Picture(); - ~Picture(); - - Graphics::Surface load(Common::SeekableReadStream *stream); - void draw(int x, int y); - void drawMasked(int x, int y); - - uint _width, _height; - - char *getName() { return _name; } - -private: - - char _name[64]; - - Graphics::ManagedSurface _surface; - -}; - -class Tile { -public: - - Tile(); - ~Tile(); - - Graphics::Surface load(Common::SeekableReadStream *stream); - void draw(int x, int y); - void drawMasked(int x, int y); - - uint32 _flags; - - char *getName() { return _name; } -private: - char _name[64]; - - Graphics::ManagedSurface _surface; -}; - -} // End of Namespace HDB - -#endif // !HDB_DRAW_MANAGER_H diff --git a/engines/hdb/gfx.cpp b/engines/hdb/gfx.cpp new file mode 100644 index 0000000000..852718f101 --- /dev/null +++ b/engines/hdb/gfx.cpp @@ -0,0 +1,793 @@ +/* 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 "hdb/hdb.h" + +namespace HDB { + +DrawMan::DrawMan() { + _tLookupArray = NULL; + _gfxCache = new Common::Array; + _globalSurface.create(kScreenWidth, kScreenHeight, g_hdb->_format); + _pointerDisplayable = 1; + _systemInit = false; +} + +DrawMan::~DrawMan() { + delete _gfxCache; + _globalSurface.free(); +} + +bool DrawMan::init() { + + // Set the default cursor pos & char clipping + setCursor(0, 0); + + _eLeft = 0; + _eRight = kScreenWidth; + _eTop = 0; + _eBottom = kScreenHeight; + + // Load Game Font + if (!loadFont("normalprop")) + return false; + + // Read total number of tiles in game + _numTiles = g_hdb->_fileMan->getCount("t32_", TYPE_TILE32); + if (!_numTiles) { + return false; + } + + // Setup Tile Lookup Array + _tLookupArray = new TileLookup[_numTiles]; + Common::Array tileData = *g_hdb->_fileMan->findFiles("t32_", TYPE_TILE32); + + assert((uint)_numTiles == tileData.size()); + + int index = 0, skyIndex = 0; + for (; index < _numTiles; index++) { + _tLookupArray[index].filename = tileData[index]; + _tLookupArray[index].tData = NULL; + _tLookupArray[index].skyIndex = 0; + _tLookupArray[index].animIndex = index; + // Check if the loaded Tile is a Sky Tile + if (((Common::String)tileData[index]).contains("sky") && (skyIndex < kMaxSkies)) { + _tLookupArray[index].skyIndex = skyIndex + 1; + _skyTiles[skyIndex] = index; + skyIndex++; + } + } + + + // Add Animating Tile Info + int found = -1; + char search[32]; + strcpy(search, "anim_"); + for (index = 0; index < _numTiles; index++) { + // IF we have not found a start, look for it + // ELSE IF we have found a start and are in the middle of an anim group + // ELSE IF we're in an anim group and have just reached the end + if (!strncmp(_tLookupArray[index].filename, search, strlen(search)) && found == -1) { + found = index; + strncpy(search, _tLookupArray[index].filename, strlen(_tLookupArray[index].filename) - 2); + } else if (!strncmp(_tLookupArray[index].filename, search, strlen(search)) && found >= 0) + _tLookupArray[index - 1].animIndex = index; + else if (strncmp(_tLookupArray[index].filename, search, strlen(search)) && found >= 0) { + _tLookupArray[index - 1].animIndex = found; + strcpy(search, "anim_"); + found = -1; + if (!strncmp(_tLookupArray[index].filename, search, strlen(search))) + index--; + } + } + + // Init Sky Data + _currentSky = 0; + _tileSkyStars = getTileIndex("t32_sky_stars"); + _tileSkyStarsLeft = getTileIndex("t32_sky_stars_left_slow"); + _tileSkyClouds = getTileIndex("t32_sky_clouds"); // Not completely sure about this filename. + _skyClouds = NULL; + + /* + TODO: Setup Gamma Table + */ + + // Load Mouse Pointer and Display Cursor + _mousePointer[0] = loadPic(PIC_MOUSE_CURSOR1); + _mousePointer[1] = loadPic(PIC_MOUSE_CURSOR2); + _mousePointer[2] = loadPic(PIC_MOUSE_CURSOR3); + _mousePointer[3] = loadPic(PIC_MOUSE_CURSOR4); + _mousePointer[4] = loadPic(PIC_MOUSE_CURSOR5); + _mousePointer[5] = loadPic(PIC_MOUSE_CURSOR6); + _mousePointer[6] = loadPic(PIC_MOUSE_CURSOR7); + _mousePointer[7] = loadPic(PIC_MOUSE_CURSOR8); + _showCursor = true; + + // Load all 4 levels of star colors + _starField[0] = getPicture("pic_star64"); + _starField[1] = getPicture("pic_star128"); + _starField[2] = getPicture("pic_star192"); + _starField[3] = getPicture("pic_star256"); + + /* + TODO: Load the snowflake + */ + + _systemInit = true; + return true; +} + +void DrawMan::fillScreen(uint32 color) { + _globalSurface.fillRect(Common::Rect(kScreenWidth, kScreenHeight), color); + g_system->fillScreen(color); +} + +void DrawMan::updateVideo() { + updateFade(); + debug(9, "STUB: DrawMan::updateVideo incomplete"); +} + +void DrawMan::drawPointer() { + static int anim = 0; + static uint32 animTime = 0; + + if (animTime < g_system->getMillis()) { + animTime = g_system->getMillis() + 50; + anim = (anim + 1) & 7; + } + + // If pointer is not displayable and we are in game, exit + if (!_pointerDisplayable && g_hdb->getGameState() == GAME_PLAY) + return; + + // If we are in game and the cursor should be displayed, draw it + if (_showCursor || g_hdb->getGameState() != GAME_PLAY) + _mousePointer[anim]->drawMasked(g_hdb->_input->getMouseX() - 16, g_hdb->_input->getMouseY() - 16); +} + +void DrawMan::setPointerState(int value) { + _pointerDisplayable = value; +} + +void DrawMan::setFade(bool fadeIn, bool black, int steps) { + _fadeInfo.isFadeIn = fadeIn; + _fadeInfo.isBlack = black; + + if (!steps) { + steps = 1; + } + _fadeInfo.speed = steps; + + if (fadeIn) { + _fadeInfo.curStep = 0; + } else { + _fadeInfo.curStep = 255; + } + + _fadeInfo.active = true; +} + +void DrawMan::updateFade() { + _fadeInfo.active = false; + debug(9, "STUB: DrawMan::updateFade incomplete"); +} + +Picture *DrawMan::loadPic(const char *picName) { + Picture *pic = new Picture; + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(picName, TYPE_PIC); + if (!stream) + return NULL; + pic->load(stream); + return pic; +} + +Tile *DrawMan::loadTile(const char *tileName) { + Tile *tile = new Tile; + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(tileName, TYPE_TILE32); + if (!stream) + return NULL; + tile->load(stream); + return tile; +} + +Tile *DrawMan::getTile(int index) { + + if (index < 0 || index > _numTiles) { + if (index != 0xFFFF) + debug(6, "getTile(%d): wrong index > %d", index, _numTiles); + return NULL; + } + if (_tLookupArray[index].skyIndex) { + debug(6, "getTile(%d): sky tile (%d)", index, _tLookupArray[index].skyIndex); + // We don't draw Sky Tiles, so return NULL + return NULL; + } + + if (_tLookupArray[index].tData == NULL) { + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(_tLookupArray[index].filename, TYPE_TILE32); + Tile *tile = new Tile; + tile->load(stream); + _tLookupArray[index].tData = tile; + } + + return _tLookupArray[index].tData; +} + +void DrawMan::cacheTileSequence(int tileIndex, int count) { + for (int i = tileIndex; i < tileIndex + count; i++) + getTile(i); +} + +int DrawMan::getTileIndex(const char *name) { + if (!name) { + return -1; + } + for (int i = 0; i < _numTiles; i++) { + if (Common::matchString(_tLookupArray[i].filename, name)) { + return i; + } + } + return -1; +} + +Picture *DrawMan::getPicture(const char *name) { + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(name, TYPE_PIC); + Picture *picture = new Picture; + picture->load(stream); + return picture; +} + +// Returns: true->Tile, false->Pic +bool DrawMan::selectGfxType(const char *name) { + // Check for Pic types + if (Common::matchString(name, "clubup1")) + return false; + if (Common::matchString(name, "clubup2")) + return false; + if (Common::matchString(name, "clubup3")) + return false; + if (Common::matchString(name, "clubup4")) + return false; + if (Common::matchString(name, "clubdown1")) + return false; + if (Common::matchString(name, "clubdown2")) + return false; + if (Common::matchString(name, "clubdown3")) + return false; + if (Common::matchString(name, "clubdown4")) + return false; + if (Common::matchString(name, "clubleft1")) + return false; + if (Common::matchString(name, "clubleft2")) + return false; + if (Common::matchString(name, "clubleft3")) + return false; + if (Common::matchString(name, "clubleft4")) + return false; + if (Common::matchString(name, "clubright1")) + return false; + if (Common::matchString(name, "clubright2")) + return false; + if (Common::matchString(name, "clubright3")) + return false; + if (Common::matchString(name, "clubright4")) + return false; + if (Common::matchString(name, "slug_shot1")) + return false; + if (Common::matchString(name, "slug_shot2")) + return false; + if (Common::matchString(name, "slug_shot3")) + return false; + if (Common::matchString(name, "slug_shot4")) + return false; + + return true; +} + +Tile *DrawMan::getTileGfx(const char *name, uint32 size) { + // Try to find graphic + for (Common::Array::iterator it = _gfxCache->begin(); it != _gfxCache->end(); it++) { + if (Common::matchString((*it)->name, name)) { + if ((*it)->loaded == -1) { // Marked for Deletetion? + (*it)->loaded = 1; // Reactivate it + return (*it)->tileGfx; + } + } + } + + GfxCache *gc = new GfxCache; + strcpy(gc->name, name); + + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(name, TYPE_TILE32); + + Tile *gfxTile = new Tile; + gfxTile->load(stream); + + gc->tileGfx = gfxTile; + gc->size = size; + gc->loaded = 1; + + _gfxCache->push_back(gc); + + return gc->tileGfx; +} + +Picture *DrawMan::getPicGfx(const char *name, uint32 size) { + // Try to find graphic + for (Common::Array::iterator it = _gfxCache->begin(); it != _gfxCache->end(); it++) { + if (Common::matchString((*it)->name, name)) { + if ((*it)->loaded == -1) { // Marked for Deletetion? + (*it)->loaded = 1; // Reactivate it + return (*it)->picGfx; + } + } + } + + GfxCache *gc = new GfxCache; + strcpy(gc->name, name); + + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(name, TYPE_TILE32); + + Picture *gfxPic = new Picture; + gfxPic->load(stream); + + gc->picGfx = gfxPic; + gc->size = size; + gc->loaded = 1; + + _gfxCache->push_back(gc); + + return gc->picGfx; +} + +int DrawMan::isSky(int index) { + if (!index) { + return 0; + } + + for (int i = 0; i < kMaxSkies; i++) { + if(_skyTiles[i] == index) { + return i + 1; // The skyTiles are indexed from 1. 0 => No Sky tile + } + } + + return 0; +} + +void DrawMan::setSky(int skyIndex) { + int tileIndex = _skyTiles[skyIndex - 1]; + _currentSky = skyIndex; + + // Clear memory used by last sky + if (tileIndex != _tileSkyClouds && _skyClouds) { + delete _skyClouds; + _skyClouds = NULL; + } + + // Setup current sky + if (tileIndex == _tileSkyStars) { + setup3DStars(); + return; + } else if (skyIndex == _tileSkyStarsLeft) { + setup3DStarsLeft(); + return; + } else if (skyIndex == _tileSkyStars) { + _skyClouds = getPicture("cloudy_skies"); + return; + } +} + +void DrawMan::setup3DStars() { + for (int i = 0; i < kNum3DStars; i++) { + _stars3D[i].x = g_hdb->_rnd->getRandomNumber(kScreenWidth); + _stars3D[i].y = g_hdb->_rnd->getRandomNumber(kScreenHeight); + _stars3D[i].speed = g_hdb->_rnd->getRandomNumber(256); + _stars3D[i].speed >>= 1; + _stars3D[i].color = _stars3D[i].speed / 64; + } +} + +void DrawMan::setup3DStarsLeft() { + for (int i = 0; i < kNum3DStars; i++) { + _stars3DSlow[i].x = g_hdb->_rnd->getRandomNumber(kScreenWidth); + _stars3DSlow[i].y = g_hdb->_rnd->getRandomNumber(kScreenHeight); + _stars3DSlow[i].speed = ((double) (1 + g_hdb->_rnd->getRandomNumber(5))) / 6.0; + _stars3DSlow[i].color = (int) (_stars3DSlow[i].speed * 4.00); + } +} + +void DrawMan::draw3DStars() { + fillScreen(0); + for (int i = 0; i < kNum3DStars; i++) { + _starField[_stars3D[i].color]->drawMasked((int)_stars3D[i].x, (int)_stars3D[i].y); + _stars3D[i].y += (_stars3D[i].speed >> 5) + 1; + if (_stars3D[i].y > kScreenHeight) { + _stars3D[i].y = 0; + } + } +} + +void DrawMan::draw3DStarsLeft() { + fillScreen(0); + for (int i = 0; i < kNum3DStars; i++) { + _starField[_stars3DSlow[i].color]->drawMasked((int)_stars3DSlow[i].x, (int)_stars3DSlow[i].y); + _stars3DSlow[i].x -= _stars3DSlow[i].speed; + if (_stars3DSlow[i].x < kScreenWidth) { + _stars3DSlow[i].x = kScreenWidth - 1; + } + } +} + +void DrawMan::drawSky() { + int tile = _skyTiles[_currentSky - 1]; + + if (tile == _tileSkyStars) { + draw3DStars(); + } + else if (tile == _tileSkyStarsLeft) { + draw3DStarsLeft(); + } + else if (tile == _tileSkyClouds) { + static int offset = 0, wait = 0; + for (int j = -64; j < kScreenHeight; j += 64) { + for (int i = -64; i < kScreenWidth; i += 64) { + _skyClouds->draw(i + offset, j + offset); + } + } + wait--; + if (wait < 1) { + offset = (offset + 1) & 63; + wait = 5; + } + } +} + +int DrawMan::animateTile(int tileIndex) { + return _tLookupArray[tileIndex].animIndex; +} + +bool DrawMan::loadFont(const char *string) { + Common::SeekableReadStream *stream = g_hdb->_fileMan->findFirstData(string, TYPE_FONT); + if (!stream) + return false; + + // Loading _fontHeader + _fontHeader.type = (int)stream->readUint32LE(); + _fontHeader.numChars = (int)stream->readUint32LE(); + _fontHeader.height = (int)stream->readUint32LE(); + _fontHeader.kerning = (int)stream->readUint32LE(); + _fontHeader.leading = (int)stream->readUint32LE(); + + debug(3, "Loaded _fontHeader with following data"); + debug(3, "type: %d", _fontHeader.type); + debug(3, "numChars: %d", _fontHeader.numChars); + debug(3, "height: %d", _fontHeader.height); + debug(3, "kerning: %d", _fontHeader.kerning); + debug(3, "leading: %d", _fontHeader.leading); + + // Loading _charInfoBlocks & creating character surfaces + CharInfo *cInfo; + int startPos = stream->pos(); // Position after _fontHeader + int curPos; // Position after reading cInfo + uint16 *ptr; + for (int i = 0; i < _fontHeader.numChars; i++) { + cInfo = new CharInfo; + cInfo->width = (int16)stream->readUint32LE(); + cInfo->offset = (int32)stream->readUint32LE(); + + debug(3, "Loaded _charInfoBlocks[%d]: width: %d, offset: %d", i, cInfo->width, cInfo->offset); + + curPos = stream->pos(); + + _fontSurfaces[i].create(cInfo->width, _fontHeader.height, g_hdb->_format); + + // Go to character location + stream->seek(startPos+cInfo->offset); + + for (int y = 0; y < _fontHeader.height; y++) { + ptr = (uint16 *)_fontSurfaces[i].getBasePtr(0, y); + for (int x = 0; x < cInfo->width; x++) { + *ptr = TO_LE_16(stream->readUint16LE()); + ptr++; + } + } + + stream->seek(curPos); + + _charInfoBlocks.push_back(cInfo); + } + + // Loading _fontGfx + _fontGfx = stream->readUint16LE(); + + return true; +} + +void DrawMan::drawText(const char *string) { + if (!_systemInit) + return; + + if (_cursorX < _eLeft) + _cursorX = _eLeft; + if (_cursorY < _eTop) + _cursorY = _eTop; + + // Word Wrapping + int width = _eLeft; + unsigned char c; + char cr[256]; // Carriage Return Array + + for (int i = 0; i < (int)strlen(string); i++) { + c = string[i]; + width += _charInfoBlocks[c]->width + _fontHeader.kerning + kFontIncrement; + if (c == ' ') + width += kFontSpace; + + cr[i] = 0; + if (c == '\n') { + cr[i] = 1; + width = _eLeft; + } else if (width > _eRight) { + i--; + while (string[i] != ' ' && i > 0) + i--; + cr[i] = 1; + width = _eLeft; + } + } + + // Draw the characters + for (int j = 0; j < (int)strlen(string); j++) { + c = string[j]; + if (c == '\n' || cr[j]) { + _cursorX = _eLeft; + _cursorY += _fontHeader.height + _fontHeader.leading; + if (_cursorY + _fontHeader.height > _eBottom) + _cursorY = _eTop; + continue; + } + + width = _charInfoBlocks[c]->width; + if (c == ' ') + width = kFontSpace; + + // Blit the character + g_hdb->_drawMan->_globalSurface.transBlitFrom(_fontSurfaces[c], Common::Point(_cursorX, _cursorY), 0xf81f); + + Common::Rect clip(0, 0, width, _fontHeader.height); + clip.moveTo(_cursorX, _cursorY); + clip.clip(_globalSurface.getBounds()); + if (!clip.isEmpty()) { + g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); + } + + // Advance the cursor + _cursorX += width + _fontHeader.kerning + kFontIncrement; + if (_cursorX > kScreenWidth) { + _cursorX = 0; + _cursorY += _fontHeader.height + _fontHeader.leading; + if (_cursorY + _fontHeader.height > kScreenHeight) + _cursorY = 0; + } + } +} + +// Calculates pixel width of a string +void DrawMan::getDimensions(const char *string, int *pixelsWide, int *lines) { + if (!string) { + *pixelsWide = kFontSpace; + *lines = 1; + return; + } + + int width, maxWidth, height; + unsigned char c; + maxWidth = 0; + width = _eLeft; + height = 1; + + for (int i = 0; i < (int)strlen(string); i++) { + c = string[i]; + width += _charInfoBlocks[c]->width + _fontHeader.kerning + kFontIncrement; + if (c == ' ') + width += kFontSpace; + + if (c == '\n') { + height++; + if (width > maxWidth) + maxWidth = width; + width = _eLeft; + } else if (width > _eRight) { + int oldWidth = width; + i--; + while (string[i] != ' ' && i > 0) { + c = string[i]; + width -= _charInfoBlocks[c]->width + _fontHeader.kerning + kFontIncrement; + i--; + } + if (!i) { + maxWidth = oldWidth; + break; + } + height++; + if (width > maxWidth) + maxWidth = width; + width = _eLeft; + } + } + + if (width > maxWidth) + maxWidth = width; + + // If its one line, add 8 pixels + if (height == 1) + maxWidth += 8; + + *pixelsWide = maxWidth - _eLeft; + *lines = height; +} + +int DrawMan::stringLength(const char *string) { + int w, h; + getDimensions(string, &w, &h); + return w; +} + +void DrawMan::setTextEdges(int left, int right, int top, int bottom) { + _eLeft = left; + _eRight = right; + _eTop = top; + _eBottom = bottom; +} + +void DrawMan::getTextEdges(int *left, int *right, int *top, int *bottom) { + *left = _eLeft; + *right = _eRight; + *top = _eTop; + *bottom = _eBottom; +} + +void DrawMan::setKernLead(int kern, int lead) { + _fontHeader.kerning = kern; + _fontHeader.leading = lead; +} + +void DrawMan::getKernLead(int *kern, int *lead) { + *kern = _fontHeader.kerning; + *lead = _fontHeader.leading; +} + +void DrawMan::setCursor(int x, int y) { + _cursorX = x; + _cursorY = y; +} + +void DrawMan::getCursor(int *x, int *y) { + *x = _cursorX; + *y = _cursorY; +} + +Picture::Picture() : _width(0), _height(0), _name("") { + _surface.create(_width, _height, g_hdb->_format); +} + +Picture::~Picture() { + _surface.free(); +} + +Graphics::Surface Picture::load(Common::SeekableReadStream *stream) { + _width = stream->readUint32LE(); + _height = stream->readUint32LE(); + stream->read(_name, 64); + + debug(8, "Picture: _width: %d, _height: %d", _width, _height); + debug(8, "Picture: _name: %s", _name); + + _surface.create(_width, _height, g_hdb->_format); + stream->readUint32LE(); // Skip Win32 Surface + + uint16 *ptr; + + for (uint y = 0; y < _height; y++) { + ptr = (uint16 *)_surface.getBasePtr(0, y); + for (uint x = 0; x < _width; x++) { + *ptr = TO_LE_16(stream->readUint16LE()); + ptr++; + } + } + + return _surface; +} + +void Picture::draw(int x, int y) { + g_hdb->_drawMan->_globalSurface.blitFrom(_surface, Common::Point(x, y)); + + Common::Rect clip(_surface.getBounds()); + clip.moveTo(x, y); + clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); + if (!clip.isEmpty()) { + g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); + } +} + +void Picture::drawMasked(int x, int y) { + g_hdb->_drawMan->_globalSurface.transBlitFrom(_surface, Common::Point(x, y), 0xf81f); + + Common::Rect clip(_surface.getBounds()); + clip.moveTo(x, y); + clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); + if (!clip.isEmpty()) { + g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); + } +} + +Tile::Tile() : _flags(0), _name("") { + _surface.create(32, 32, g_hdb->_format); +} + +Tile::~Tile() { + _surface.free(); +} + +Graphics::Surface Tile::load(Common::SeekableReadStream *stream) { + _flags = stream->readUint32LE(); + stream->read(_name, 64); + + _surface.create(32, 32, g_hdb->_format); + stream->readUint32LE(); // Skip Win32 Surface + + uint16 *ptr; + + for (uint y = 0; y < 32; y++) { + ptr = (uint16 *)_surface.getBasePtr(0, y); + for (uint x = 0; x < 32; x++) { + *ptr = TO_LE_16(stream->readUint16LE()); + ptr++; + } + } + + return _surface; +} + +void Tile::draw(int x, int y) { + g_hdb->_drawMan->_globalSurface.blitFrom(_surface, Common::Point(x, y)); + + Common::Rect clip(_surface.getBounds()); + clip.moveTo(x, y); + clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); + if (!clip.isEmpty()) { + g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); + } +} + +void Tile::drawMasked(int x, int y) { + g_hdb->_drawMan->_globalSurface.transBlitFrom(_surface, Common::Point(x, y), 0xf81f); + + Common::Rect clip(_surface.getBounds()); + clip.moveTo(x, y); + clip.clip(g_hdb->_drawMan->_globalSurface.getBounds()); + if (!clip.isEmpty()) { + g_system->copyRectToScreen(g_hdb->_drawMan->_globalSurface.getBasePtr(clip.left, clip.top), g_hdb->_drawMan->_globalSurface.pitch, clip.left, clip.top, clip.width(), clip.height()); + } +} + +} diff --git a/engines/hdb/gfx.h b/engines/hdb/gfx.h new file mode 100644 index 0000000000..1ace112993 --- /dev/null +++ b/engines/hdb/gfx.h @@ -0,0 +1,242 @@ +/* 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 HDB_DRAW_MANAGER_H +#define HDB_DRAW_MANAGER_H + +#include "graphics/managed_surface.h" + +#include "hdb/hdb.h" + +namespace HDB { + +enum { + kScreenWidth = 640, + kScreenHeight = 480, + kTileWidth = 32, + kTileHeight = 32, + kMaxSkies = 10, + kNum3DStars = 300, + kFontSpace = 5, + kFontIncrement = 1, + kGameFPS = 60, + kAnimFrameDelay = kGameFPS / 30, + kAnimSlowFrames = kAnimFrameDelay * 10, + kAnimMediumFrames = kAnimFrameDelay * 6, + kAnimFastFrames = kAnimFrameDelay * 2 +}; + +class Tile; +class Picture; + +struct TileLookup { + const char *filename; + Tile *tData; + uint16 skyIndex; + uint16 animIndex; + + TileLookup() : filename(NULL), tData(NULL), skyIndex(0), animIndex(0) {} +}; + +struct GfxCache { + char name[32]; + union { + Tile *tileGfx; + Picture *picGfx; + }; + uint32 size; + int16 loaded; + + GfxCache() : name(""), tileGfx(NULL), size(0), loaded(0) {} +}; + +struct FontInfo { + int type; // 0 = mono, 1 = proportional + int numChars; // how many characters in font + int height; // height of entire font + int kerning; // space between chars + int leading; // space between lines +}; + +struct CharInfo { + int16 width; // Character width in pixels + int32 offset; // From the start of the font charInfo chunk +}; + +class DrawMan { +public: + + DrawMan(); + ~DrawMan(); + + Graphics::ManagedSurface _globalSurface; + + bool init(); + void fillScreen(uint32 color); + void updateVideo(); + void setPointerState(int value); + void drawPointer(); + void showPointer(bool status) { + _showCursor = status; + } + bool getPointer() { + return _showCursor; + } + + void setFade(bool fadeIn, bool black, int steps); + void updateFade(); + bool isFadeActive() { return _fadeInfo.active; } + bool isFadeStaying() { return _fadeInfo.stayFaded; } + void turnOffFade() { _fadeInfo.active = _fadeInfo.stayFaded = false; } + + Picture *loadPic(const char *picName); + Tile *loadTile(const char *tileName); + + Tile *getTile(int index); + void cacheTileSequence(int index, int count); + int getTileIndex(const char *name); + Picture *getPicture(const char *name); + + // Returns: true->Tile, false->Pic + bool selectGfxType(const char *name); + Tile *getTileGfx(const char *name, uint32 size); + Picture *getPicGfx(const char *name, uint32 size); + + int isSky(int skyIndex); + void setSky(int skyIndex); + void setup3DStars(); + void setup3DStarsLeft(); + void draw3DStars(); + void draw3DStarsLeft(); + void drawSky(); + + int animateTile(int tileIndex); + + // Font Functions + + bool loadFont(const char *string); + void drawText(const char *string); + void getDimensions(const char *string, int *pixelsWide, int *lines); + int stringLength(const char *string); + void setTextEdges(int left, int right, int top, int bottom); + void getTextEdges(int *left, int *right, int *top, int *bottom); + void setKernLead(int kern, int lead); + void getKernLead(int *kern, int *lead); + void setCursor(int x, int y); + void getCursor(int *x, int *y); + +private: + int _numTiles; + TileLookup *_tLookupArray; + uint16 _skyTiles[kMaxSkies]; + + Common::Array *_gfxCache; + + int _currentSky; // 0 if no Sky, 1+ for which Sky to use + struct { + bool active; + bool stayFaded; + bool isBlack; + int speed; + bool isFadeIn; + + int curStep; + } _fadeInfo; + + struct { + int x, y, speed; + uint16 color; + } _stars3D[kNum3DStars]; + + struct { + double x, y, speed; + uint16 color; + } _stars3DSlow[kNum3DStars]; + + int _tileSkyStars; // Index of sky_stars tile + int _tileSkyStarsLeft; // Left-scrolling stars, slow + int _tileSkyClouds; // Index of sky_stars tile + Picture *_starField[4]; + Picture *_skyClouds; + + // Cursor + int _cursorX, _cursorY; + Picture *_mousePointer[8]; // Gfx for screen pointer (4 Animations) + int _pointerDisplayable; + bool _showCursor; + + // Font Data + + FontInfo _fontHeader; + Common::Array _charInfoBlocks; + Graphics::Surface _fontSurfaces[256]; + uint16 _fontGfx; + int _eLeft, _eRight, _eTop, _eBottom; + + bool _systemInit; + +}; + +class Picture { +public: + + Picture(); + ~Picture(); + + Graphics::Surface load(Common::SeekableReadStream *stream); + void draw(int x, int y); + void drawMasked(int x, int y); + + uint _width, _height; + + char *getName() { return _name; } + +private: + + char _name[64]; + + Graphics::ManagedSurface _surface; + +}; + +class Tile { +public: + + Tile(); + ~Tile(); + + Graphics::Surface load(Common::SeekableReadStream *stream); + void draw(int x, int y); + void drawMasked(int x, int y); + + uint32 _flags; + + char *getName() { return _name; } +private: + char _name[64]; + + Graphics::ManagedSurface _surface; +}; + +} // End of Namespace HDB + +#endif // !HDB_DRAW_MANAGER_H diff --git a/engines/hdb/hdb.h b/engines/hdb/hdb.h index e9f0548869..3c90cdfbdb 100644 --- a/engines/hdb/hdb.h +++ b/engines/hdb/hdb.h @@ -38,7 +38,7 @@ #include "console.h" #include "hdb/mpc.h" -#include "hdb/draw-manager.h" +#include "hdb/gfx.h" #include "hdb/ai.h" #include "hdb/ai-player.h" #include "hdb/file-manager.h" diff --git a/engines/hdb/module.mk b/engines/hdb/module.mk index af3236149a..e55658f7d1 100644 --- a/engines/hdb/module.mk +++ b/engines/hdb/module.mk @@ -11,9 +11,9 @@ MODULE_OBJS := \ ai-use.o \ ai-waypoint.o \ console.o \ - draw-manager.o \ detection.o \ file-manager.o \ + gfx.o \ hdb.o \ input.o \ lua-script.o \ -- cgit v1.2.3