Initial commit
This commit is contained in:
270
engines/dragons/font.cpp
Normal file
270
engines/dragons/font.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "common/memstream.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "dragons/bigfile.h"
|
||||
#include "dragons/cursor.h"
|
||||
#include "dragons/font.h"
|
||||
#include "dragons/scene.h"
|
||||
#include "dragons/screen.h"
|
||||
#include "dragons/dragons.h"
|
||||
|
||||
namespace Dragons {
|
||||
|
||||
Font::Font(Common::SeekableReadStream &stream, uint32 mapSize, uint32 pixelOffset, uint32 pixelSize) {
|
||||
_size = mapSize / 2;
|
||||
_map = (uint16 *)malloc(mapSize);
|
||||
if (!_map) {
|
||||
error("Allocating memory for font map.");
|
||||
}
|
||||
|
||||
for (uint i = 0; i < _size; i++) {
|
||||
_map[i] = stream.readUint16LE();
|
||||
}
|
||||
|
||||
_pixels = (byte *)malloc(pixelSize);
|
||||
if (!_pixels) {
|
||||
error("Allocating memory for font pixels.");
|
||||
}
|
||||
stream.seek(pixelOffset);
|
||||
stream.read(_pixels, pixelSize);
|
||||
_numChars = pixelSize / 64;
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
free(_map);
|
||||
free(_pixels);
|
||||
}
|
||||
|
||||
uint16 Font::mapChar(uint16 in) {
|
||||
return _map[in - _map[0x03] + 0x05];
|
||||
}
|
||||
|
||||
Graphics::Surface *Font::render(uint16 *text, uint16 length) {
|
||||
Graphics::Surface *surface = new Graphics::Surface();
|
||||
surface->create(length * 8, 8, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
renderToSurface(surface, 0, 0, text, length);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void Font::renderToSurface(Graphics::Surface *surface, int16 x, int16 y, uint16 *text, uint16 length) {
|
||||
if (x < 0 || y < 0 || x + length * 8 > surface->w || y + 8 > surface->h) {
|
||||
return;
|
||||
}
|
||||
byte *startPixelOffset = (byte *)surface->getPixels() + y * surface->pitch + x * surface->format.bytesPerPixel;
|
||||
for (int i = 0; i < length; i++) {
|
||||
byte *pixels = startPixelOffset;
|
||||
pixels += i * 8;
|
||||
byte *data = _pixels + mapChar(text[i]) * 64;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
memcpy(pixels, data, 8);
|
||||
data += 8;
|
||||
pixels += surface->pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontManager::FontManager(DragonsEngine *vm, Screen *screen, BigfileArchive *bigfileArchive): _vm(vm), _screen(screen), _numTextEntries(0) {
|
||||
uint32 fileSize;
|
||||
byte *data = bigfileArchive->load("fntfiles.dat", fileSize);
|
||||
Common::SeekableReadStream *readStream = new Common::MemoryReadStream(data, fileSize, DisposeAfterUse::YES);
|
||||
|
||||
_fonts[0] = loadFont(0, *readStream);
|
||||
_fonts[1] = loadFont(1, *readStream);
|
||||
_fonts[2] = loadFont(2, *readStream);
|
||||
|
||||
delete readStream;
|
||||
|
||||
_dat_80086f48_fontColor_flag = 0;
|
||||
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(DRAGONS_SCREEN_WIDTH, DRAGONS_SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
|
||||
clearText(); //clear backing surface.
|
||||
|
||||
_boxFontChr = bigfileArchive->load("boxfont.chr", fileSize);
|
||||
}
|
||||
|
||||
FontManager::~FontManager() {
|
||||
delete _fonts[0];
|
||||
delete _fonts[1];
|
||||
delete _fonts[2];
|
||||
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
|
||||
free(_boxFontChr);
|
||||
}
|
||||
|
||||
void FontManager::addText(int16 x, int16 y, uint16 *text, uint16 length, uint8 fontType) {
|
||||
assert(length < 1024);
|
||||
assert(fontType < 4);
|
||||
_fonts[fontType]->renderToSurface(_surface, x, y, text, length);
|
||||
++_numTextEntries;
|
||||
}
|
||||
|
||||
void FontManager::draw() {
|
||||
if(_numTextEntries > 0) {
|
||||
_screen->copyRectToSurface8bpp(*_surface, _screen->getPalette(2), 0, 0, Common::Rect(_surface->w, _surface->h), false, NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void FontManager::clearText() {
|
||||
_numTextEntries = 0;
|
||||
_surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
|
||||
}
|
||||
|
||||
Font *FontManager::loadFont(uint16 index, Common::SeekableReadStream &stream) {
|
||||
Common::File fd;
|
||||
if (!fd.open("dragon.exe")) {
|
||||
error("Failed to open dragon.exe");
|
||||
}
|
||||
fd.seek(_vm->getFontOffsetFromDragonEXE());
|
||||
fd.skip((index * 2) * 28);
|
||||
|
||||
fd.skip(16); //filename
|
||||
uint32 mapOffset = fd.readUint32LE();
|
||||
uint32 mapSize = fd.readUint32LE();
|
||||
fd.skip(4); //unk
|
||||
|
||||
fd.skip(16); //filename
|
||||
uint32 pixelsOffset = fd.readUint32LE();
|
||||
uint32 pixelsSize = fd.readUint32LE();
|
||||
|
||||
fd.close();
|
||||
|
||||
stream.seek(mapOffset);
|
||||
return new Font(stream, mapSize, pixelsOffset, pixelsSize);
|
||||
}
|
||||
|
||||
void updatePalEntry(uint16 *pal, uint16 index, uint16 newValue) {
|
||||
newValue = (uint16)(((uint16)newValue & 0x1f) << 10) | (uint16)(((uint16)newValue & 0x7c00) >> 10) |
|
||||
(newValue & 0x3e0) | (newValue & 0x8000);
|
||||
WRITE_LE_INT16(pal + index, newValue);
|
||||
}
|
||||
|
||||
void FontManager::updatePalette() {
|
||||
uint16 *palette_f2_font_maybe = (uint16 *)_screen->getPalette(2);
|
||||
const uint16 cursor3 = 0x14a5 | 0x8000;
|
||||
if (_vm->isInMenu() || _vm->isFlagSet(ENGINE_FLAG_200)) {
|
||||
updatePalEntry(palette_f2_font_maybe, 3, cursor3); //TODO move this to palette initialisation
|
||||
if (!_vm->isUnkFlagSet(ENGINE_UNK1_FLAG_1)) {
|
||||
updatePalEntry(palette_f2_font_maybe, 16, cursor3);
|
||||
} else {
|
||||
updatePalEntry(palette_f2_font_maybe, 16, 0);
|
||||
}
|
||||
if (_vm->isUnkFlagSet(ENGINE_UNK1_FLAG_4) && _dat_80086f48_fontColor_flag != 0) {
|
||||
updatePalEntry(palette_f2_font_maybe, 17, 0x421);
|
||||
} else {
|
||||
updatePalEntry(palette_f2_font_maybe, 17, 0xfff);
|
||||
}
|
||||
updatePalEntry(palette_f2_font_maybe, 18, 0x421);
|
||||
updatePalEntry(palette_f2_font_maybe, 19, 0x3def);
|
||||
updatePalEntry(palette_f2_font_maybe, 32, cursor3);
|
||||
updatePalEntry(palette_f2_font_maybe, 49, 0xfff);
|
||||
updatePalEntry(palette_f2_font_maybe, 1, 0x8000);
|
||||
|
||||
updatePalEntry(palette_f2_font_maybe, 34, 0x421);
|
||||
updatePalEntry(palette_f2_font_maybe, 35, 0x3def);
|
||||
updatePalEntry(palette_f2_font_maybe, 48, cursor3);
|
||||
updatePalEntry(palette_f2_font_maybe, 50, 0x421);
|
||||
updatePalEntry(palette_f2_font_maybe, 51, 0x3def);
|
||||
//TODO WRITE_LE_INT16(&palette_f2_font_maybe[33], READ_LE_INT16(&palette_f0[_dat_80084f58 >> 8]) & 0x7fff); //_dat_80084f58 is set in ActuallyShowMessage()
|
||||
updatePalEntry(palette_f2_font_maybe, 33, 0x3def); //temporarily put in standard gray
|
||||
if (_vm->isUnkFlagSet(ENGINE_UNK1_FLAG_1)) {
|
||||
updatePalEntry(palette_f2_font_maybe, 17, 0x3bee);
|
||||
updatePalEntry(palette_f2_font_maybe, 33, 0x3bee);
|
||||
updatePalEntry(palette_f2_font_maybe, 49, 0x3bee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FontManager::drawTextDialogBox(uint32 x1, uint32 y1, uint32 x2, uint32 y2) {
|
||||
const uint16 kTileBaseIndex = 1;
|
||||
const uint16 kTileIndexTop = kTileBaseIndex + 10;
|
||||
const uint16 kTileIndexBottom = kTileBaseIndex + 16;
|
||||
const uint16 kTileIndexLeft = kTileBaseIndex + 12;
|
||||
const uint16 kTileIndexRight = kTileBaseIndex + 14;
|
||||
const uint16 kTileIndexBackground = kTileBaseIndex + 13;
|
||||
const uint16 kTileIndexTopLeft = kTileBaseIndex + 9;
|
||||
const uint16 kTileIndexTopRight = kTileBaseIndex + 11;
|
||||
const uint16 kTileIndexBottomLeft = kTileBaseIndex + 15;
|
||||
const uint16 kTileIndexBottomRight = kTileBaseIndex + 17;
|
||||
// Fill background
|
||||
for (uint yc = y1 + 1; yc <= y2 - 1; ++yc) {
|
||||
for (uint xc = x1 + 1; xc <= x2 - 1; ++xc) {
|
||||
drawBoxChar(xc, yc, kTileIndexBackground);
|
||||
}
|
||||
}
|
||||
// Fill top and bottom rows
|
||||
for (uint xc = x1 + 1; xc <= x2 - 1; ++xc) {
|
||||
drawBoxChar(xc, y1, kTileIndexTop);
|
||||
drawBoxChar(xc, y2, kTileIndexBottom);
|
||||
}
|
||||
// Fill left and right columns
|
||||
for (uint yc = y1 + 1; yc <= y2 - 1; ++yc) {
|
||||
drawBoxChar(x1, yc, kTileIndexLeft);
|
||||
drawBoxChar(x2, yc, kTileIndexRight);
|
||||
}
|
||||
// Fill corners
|
||||
drawBoxChar(x1, y1, kTileIndexTopLeft);
|
||||
drawBoxChar(x2, y1, kTileIndexTopRight);
|
||||
drawBoxChar(x1, y2, kTileIndexBottomLeft);
|
||||
drawBoxChar(x2, y2, kTileIndexBottomRight);
|
||||
_numTextEntries++;
|
||||
}
|
||||
|
||||
void FontManager::clearTextDialog(uint32 x1, uint32 y1, uint32 x2, uint32 y2) {
|
||||
debug(3, "Clear text (%d,%d) -> (%d,%d)", x1, y1, x2, y2);
|
||||
// assert(x1 > 0);
|
||||
// assert(y1 > 0);
|
||||
_surface->fillRect(Common::Rect((x1-1) * 8, (y1-1) * 8, (x2 + 1) * 8 + 1, (y2 + 1) * 8 + 1), 0);
|
||||
if (_numTextEntries > 0) {
|
||||
_numTextEntries--; //TODO need a better way to check if we should still draw the font surface.
|
||||
}
|
||||
}
|
||||
|
||||
void FontManager::drawBoxChar(uint32 x, uint32 y, uint8 tileIndex) {
|
||||
byte *pixels = (byte *)_surface->getBasePtr(x * 8, y * 8);
|
||||
byte *data = _boxFontChr + tileIndex * 64;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
memcpy(pixels, data, 8);
|
||||
data += 8;
|
||||
pixels += _surface->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void FontManager::addAsciiText(int16 x, int16 y, const char *text, uint16 length, uint8 fontType) {
|
||||
uint16 wText[41];
|
||||
memset(wText, 0, sizeof(wText));
|
||||
if (length > 40) {
|
||||
length = 40;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
wText[i] = text[i] & 0xFFU;
|
||||
}
|
||||
|
||||
addText(x, y, wText, length, fontType);
|
||||
}
|
||||
|
||||
} // End of namespace Dragons
|
||||
Reference in New Issue
Block a user