mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-27 04:07:05 +00:00
8a82e59065
svn-id: r7787
705 lines
18 KiB
C++
705 lines
18 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2001-2003 The ScummVM project
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "charset.h"
|
|
#include "scumm.h"
|
|
#include "nut_renderer.h"
|
|
|
|
CharsetRenderer::CharsetRenderer(Scumm *vm) {
|
|
|
|
_nextLeft = 0;
|
|
_nextTop = 0;
|
|
|
|
_top = 0;
|
|
_left = 0;
|
|
_startLeft = 0;
|
|
_right = 0;
|
|
|
|
_color = 0;
|
|
|
|
_dropShadow = false;
|
|
_center = false;
|
|
_hasMask = false;
|
|
_ignoreCharsetMask = false;
|
|
_blitAlso = false;
|
|
_firstChar = false;
|
|
_disableOffsX = false;
|
|
|
|
_vm = vm;
|
|
_curId = 0;
|
|
}
|
|
|
|
void CharsetRendererCommon::setCurID(byte id) {
|
|
_vm->checkRange(_vm->_maxCharsets - 1, 0, id, "Printing with bad charset %d");
|
|
|
|
_curId = id;
|
|
|
|
_fontPtr = _vm->getResourceAddress(rtCharset, id);
|
|
if (_fontPtr == 0)
|
|
error("CharsetRendererCommon::setCurID: charset %d not found!\n", id);
|
|
|
|
if (_vm->_features & GF_AFTER_V4)
|
|
_fontPtr += 17;
|
|
else
|
|
_fontPtr += 29;
|
|
}
|
|
|
|
void CharsetRendererV3::setCurID(byte id) {
|
|
_vm->checkRange(_vm->_maxCharsets - 1, 0, id, "Printing with bad charset %d");
|
|
|
|
_curId = id;
|
|
|
|
_fontPtr = _vm->getResourceAddress(rtCharset, id);
|
|
if (_fontPtr == 0)
|
|
error("CharsetRendererCommon::setCurID: charset %d not found!\n", id);
|
|
|
|
_nbChars = _fontPtr[4];
|
|
_fontPtr += 6;
|
|
_widthTable = _fontPtr;
|
|
_fontPtr += _nbChars;
|
|
}
|
|
|
|
// do spacing for variable width old-style font
|
|
int CharsetRendererClassic::getCharWidth(byte chr) {
|
|
int spacing = 0;
|
|
|
|
int offs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
|
|
if (offs) {
|
|
spacing = _fontPtr[offs];
|
|
if (_fontPtr[offs + 2] >= 0x80) {
|
|
spacing += _fontPtr[offs + 2] - 0x100;
|
|
} else {
|
|
spacing += _fontPtr[offs + 2];
|
|
}
|
|
}
|
|
|
|
return spacing;
|
|
}
|
|
|
|
int CharsetRenderer::getStringWidth(int arg, const byte *text) {
|
|
int pos = 0;
|
|
int width = 1;
|
|
byte chr;
|
|
int oldID = getCurID();
|
|
|
|
while ((chr = text[pos++]) != 0) {
|
|
if (chr == 0xD)
|
|
break;
|
|
if (chr == '@')
|
|
continue;
|
|
if (chr == 254 || chr == 255) {
|
|
chr = text[pos++];
|
|
if (chr == 3) // 'WAIT'
|
|
break;
|
|
if (chr == 8) { // 'Verb on next line'
|
|
if (arg == 1)
|
|
break;
|
|
while (text[pos++] == ' ')
|
|
;
|
|
continue;
|
|
}
|
|
if (chr == 10 || chr == 21 || chr == 12 || chr == 13) {
|
|
pos += 2;
|
|
continue;
|
|
}
|
|
if (chr == 9 || chr == 1 || chr == 2) // 'Newline'
|
|
break;
|
|
if (chr == 14) {
|
|
int set = text[pos] | (text[pos + 1] << 8);
|
|
pos += 2;
|
|
setCurID(set);
|
|
continue;
|
|
}
|
|
}
|
|
width += getCharWidth(chr);
|
|
}
|
|
|
|
setCurID(oldID);
|
|
|
|
return width;
|
|
}
|
|
|
|
void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
|
|
int lastspace = -1;
|
|
int curw = 1;
|
|
byte chr;
|
|
int oldID = getCurID();
|
|
|
|
while ((chr = str[pos++]) != 0) {
|
|
if (chr == '@')
|
|
continue;
|
|
if (chr == 254)
|
|
chr = 255;
|
|
if (chr == 255) {
|
|
chr = str[pos++];
|
|
if (chr == 3) // 'Wait'
|
|
break;
|
|
if (chr == 8) { // 'Verb on next line'
|
|
if (a == 1) {
|
|
curw = 1;
|
|
} else {
|
|
while (str[pos] == ' ')
|
|
str[pos++] = '@';
|
|
}
|
|
continue;
|
|
}
|
|
if (chr == 10 || chr == 21 || chr == 12 || chr == 13) {
|
|
pos += 2;
|
|
continue;
|
|
}
|
|
if (chr == 1) { // 'Newline'
|
|
curw = 1;
|
|
continue;
|
|
}
|
|
if (chr == 2) // 'Don't terminate with \n'
|
|
break;
|
|
if (chr == 14) {
|
|
int set = str[pos] | (str[pos + 1] << 8);
|
|
pos += 2;
|
|
setCurID(set);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (chr == ' ')
|
|
lastspace = pos - 1;
|
|
|
|
curw += getCharWidth(chr);
|
|
if (lastspace == -1)
|
|
continue;
|
|
if (curw > maxwidth) {
|
|
str[lastspace] = 0xD;
|
|
curw = 1;
|
|
pos = lastspace + 1;
|
|
lastspace = -1;
|
|
}
|
|
}
|
|
|
|
setCurID(oldID);
|
|
}
|
|
|
|
// German Zak font (should work for US version too).
|
|
static byte charsetDataV2[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x01, 0x03, 0x06, 0x0c, 0x18, 0x3e, 0x03, 0x00,
|
|
0x80, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0x00,
|
|
0x00, 0x03, 0x3e, 0x18, 0x0c, 0x06, 0x03, 0x01,
|
|
0x00, 0xc0, 0x7c, 0x18, 0x30, 0x60, 0xc0, 0x80,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x7f,
|
|
0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0,
|
|
0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07,
|
|
0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18,
|
|
0x00, 0x00, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18,
|
|
0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00,
|
|
0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18,
|
|
0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18,
|
|
0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00,
|
|
0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x03, 0x07, 0x0c, 0x18, 0x18,
|
|
0x00, 0x00, 0x00, 0xc0, 0xe0, 0x30, 0x18, 0x18,
|
|
0x18, 0x18, 0x30, 0xe0, 0xc0, 0x00, 0x00, 0x00,
|
|
0x18, 0x18, 0x0c, 0x07, 0x03, 0x00, 0x00, 0x00,
|
|
0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18,
|
|
0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18,
|
|
0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18,
|
|
0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18,
|
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18,
|
|
0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18,
|
|
0x18, 0x66, 0xc3, 0xdb, 0xdb, 0xc3, 0x66, 0x18,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00,
|
|
0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00,
|
|
0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00,
|
|
0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00,
|
|
0x3c, 0x66, 0x3c, 0x38, 0x67, 0x66, 0x3f, 0x00,
|
|
0x30, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00,
|
|
0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00,
|
|
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
|
|
0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30,
|
|
0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
|
|
0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00,
|
|
0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00,
|
|
0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00,
|
|
0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00,
|
|
0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00,
|
|
0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00,
|
|
0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00,
|
|
0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00,
|
|
0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00,
|
|
0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00,
|
|
0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00,
|
|
0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30,
|
|
0x0e, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0e, 0x00,
|
|
0x7c, 0x82, 0xba, 0xa2, 0xa2, 0xba, 0x82, 0x7c,
|
|
0x70, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x70, 0x00,
|
|
0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00,
|
|
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
|
0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00,
|
|
0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00,
|
|
0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00,
|
|
0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00,
|
|
0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00,
|
|
0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00,
|
|
0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00,
|
|
0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00,
|
|
0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
|
0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00,
|
|
0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00,
|
|
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00,
|
|
0x63, 0x77, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x00,
|
|
0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x00,
|
|
0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00,
|
|
0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x0e, 0x00,
|
|
0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x66, 0x00,
|
|
0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00,
|
|
0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
|
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00,
|
|
0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00,
|
|
0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00,
|
|
0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00,
|
|
0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00,
|
|
0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
|
|
0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
|
|
0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00,
|
|
0x00, 0x10, 0x30, 0x7f, 0x7f, 0x30, 0x10, 0x00,
|
|
0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
|
|
0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00,
|
|
0x00, 0x00, 0x3c, 0x60, 0x60, 0x60, 0x3c, 0x00,
|
|
0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00,
|
|
0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
|
|
0x00, 0x0e, 0x18, 0x3e, 0x18, 0x18, 0x18, 0x00,
|
|
0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x7c,
|
|
0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x00,
|
|
0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
|
|
0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3c,
|
|
0x00, 0x60, 0x60, 0x6c, 0x78, 0x6c, 0x66, 0x00,
|
|
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
|
0x00, 0x00, 0x66, 0x7f, 0x7f, 0x6b, 0x63, 0x00,
|
|
0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00,
|
|
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60,
|
|
0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x06,
|
|
0x00, 0x00, 0x7c, 0x66, 0x60, 0x60, 0x60, 0x00,
|
|
0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00,
|
|
0x00, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x0e, 0x00,
|
|
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
|
|
0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00,
|
|
0x00, 0x00, 0x63, 0x6b, 0x7f, 0x3e, 0x36, 0x00,
|
|
0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00,
|
|
0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x0c, 0x78,
|
|
0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00,
|
|
0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x66, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x00,
|
|
0x42, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
|
0x1c, 0x36, 0x36, 0x7c, 0x66, 0x66, 0x7c, 0x40,
|
|
0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08
|
|
};
|
|
|
|
void CharsetRendererV2::setCurID(byte id) {
|
|
_fontPtr = charsetDataV2;
|
|
|
|
#if 0
|
|
// Decompress weird encoding in which the Zak executable contains the font.
|
|
// I leave the code around in case we need to use it again (e.g. we might
|
|
// have to include different fonts for french/spanish/russian/... version
|
|
// of MM / Zak
|
|
//
|
|
int count = 0, len;
|
|
byte b;
|
|
for (int offset = 0; offset < (int)sizeof(charsetDataV2); offset++) {
|
|
if (charsetDataV2[offset+1] == 0x00 && charsetDataV2[offset+2] == 0xB2) {
|
|
b = charsetDataV2[offset+3];
|
|
len = charsetDataV2[offset+4];
|
|
while (len--) {
|
|
printf("0x%02x, ", b);
|
|
count++;
|
|
if (count % 8 == 0)
|
|
printf("\n");
|
|
}
|
|
offset += 6;
|
|
} else {
|
|
printf("0x%02x, ", charsetDataV2[offset]);
|
|
count++;
|
|
if (count % 8 == 0)
|
|
printf("\n");
|
|
}
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
}
|
|
|
|
int CharsetRendererV3::getCharWidth(byte chr) {
|
|
int spacing = 0;
|
|
|
|
spacing = *(_widthTable + chr);
|
|
|
|
return spacing;
|
|
}
|
|
|
|
void CharsetRendererV3::setColor(byte color)
|
|
{
|
|
_color = color;
|
|
if (_vm->_features & GF_16COLOR) {
|
|
_dropShadow = ((_color & 0xF0) != 0);
|
|
_color &= 0x0f;
|
|
} else
|
|
_dropShadow = false;
|
|
}
|
|
|
|
void CharsetRendererV3::printChar(int chr) {
|
|
// Indy3 / Zak256 / Loom
|
|
VirtScreen *vs;
|
|
byte *char_ptr, *dest_ptr, *mask_ptr;
|
|
unsigned int buffer = 0, bit = 0, x = 0, y = 0;
|
|
bool useMask;
|
|
int w, h;
|
|
|
|
if (!_dropShadow) {
|
|
w = h = 8;
|
|
} else {
|
|
w = h = 9;
|
|
}
|
|
|
|
_vm->checkRange(_vm->_maxCharsets - 1, 0, _curId, "Printing with bad charset %d");
|
|
|
|
if ((vs = _vm->findVirtScreen(_top)) == NULL)
|
|
return;
|
|
|
|
if (chr == '@')
|
|
return;
|
|
|
|
if (_firstChar) {
|
|
_str.left = _left;
|
|
_str.top = _top;
|
|
_str.right = _left;
|
|
_str.bottom = _top;
|
|
_firstChar = false;
|
|
}
|
|
|
|
char_ptr = _fontPtr + chr * 8;
|
|
dest_ptr = vs->screenPtr + vs->xstart + (_top - vs->topline) * _vm->_screenWidth + _left;
|
|
mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + _vm->_screenStartStrip + (_top - vs->topline) * _vm->gdi._numStrips + _left / 8;
|
|
useMask = (vs->number == 0 && !_ignoreCharsetMask);
|
|
|
|
_vm->updateDirtyRect(vs->number, _left, _left + w, _top - vs->topline, _top - vs->topline + h, 0);
|
|
if (vs->number == 0)
|
|
_hasMask = true;
|
|
|
|
for (y = 0; y < 8; y++) {
|
|
byte maskmask = revBitMask[_left & 7];
|
|
int maskpos = 0;
|
|
|
|
for (x = 0; x < 8; x++) {
|
|
if ((bit >>= 1) == 0) {
|
|
buffer = *char_ptr++;
|
|
bit = 0x80;
|
|
}
|
|
if (buffer & bit) {
|
|
if (_dropShadow) {
|
|
*(dest_ptr + x + 1) = 0;
|
|
*(dest_ptr + x + _vm->_screenWidth) = 0;
|
|
*(dest_ptr + x + _vm->_screenWidth + 1) = 0;
|
|
}
|
|
*(dest_ptr + x) = _color;
|
|
|
|
if (useMask) {
|
|
mask_ptr[maskpos] |= maskmask;
|
|
if (_dropShadow) {
|
|
mask_ptr[maskpos + _vm->gdi._numStrips] |= maskmask;
|
|
if (maskmask == 1) {
|
|
mask_ptr[maskpos + 1] |= 0x80;
|
|
mask_ptr[maskpos + _vm->gdi._numStrips + 1] |= 0x80;
|
|
} else {
|
|
mask_ptr[maskpos] |= (maskmask >> 1);
|
|
mask_ptr[maskpos + _vm->gdi._numStrips] |= (maskmask >> 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
maskmask >>= 1;
|
|
if (maskmask == 0) {
|
|
maskmask = 0x80;
|
|
maskpos++;
|
|
}
|
|
}
|
|
dest_ptr += _vm->_screenWidth;
|
|
mask_ptr += _vm->gdi._numStrips;
|
|
}
|
|
|
|
if (_str.left > _left)
|
|
_str.left = _left;
|
|
|
|
_left += getCharWidth(chr);
|
|
|
|
if (_str.right < _left) {
|
|
_str.right = _left;
|
|
if (_dropShadow)
|
|
_str.right++;
|
|
}
|
|
|
|
if (_str.bottom < _top + h)
|
|
_str.bottom = _top + h;
|
|
}
|
|
|
|
void CharsetRendererClassic::printChar(int chr) {
|
|
int width, height;
|
|
int offsX, offsY;
|
|
int d;
|
|
VirtScreen *vs;
|
|
|
|
_vm->checkRange(_vm->_maxCharsets - 1, 1, _curId, "Printing with bad charset %d");
|
|
|
|
if ((vs = _vm->findVirtScreen(_top)) == NULL)
|
|
return;
|
|
|
|
if (chr == '@')
|
|
return;
|
|
|
|
_bpp = *_fontPtr;
|
|
_vm->_charsetColorMap[1] = _color;
|
|
|
|
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
|
|
|
|
if (!charOffs)
|
|
return;
|
|
|
|
assert(charOffs < 0x10000);
|
|
|
|
_charPtr = _fontPtr + charOffs;
|
|
|
|
width = _charPtr[0];
|
|
height = _charPtr[1];
|
|
if (_firstChar) {
|
|
_str.left = 0;
|
|
_str.top = 0;
|
|
_str.right = 0;
|
|
_str.bottom = 0;
|
|
}
|
|
|
|
if (_disableOffsX) {
|
|
offsX = 0;
|
|
} else {
|
|
d = _charPtr[2];
|
|
if (d >= 0x80)
|
|
d -= 0x100;
|
|
offsX = d;
|
|
}
|
|
|
|
d = _charPtr[3];
|
|
if (d >= 0x80)
|
|
d -= 0x100;
|
|
offsY = d;
|
|
|
|
_top += offsY;
|
|
_left += offsX;
|
|
|
|
if (_left + width > _right + 1 || _left < 0) {
|
|
_left += width;
|
|
_top -= offsY;
|
|
return;
|
|
}
|
|
|
|
_disableOffsX = false;
|
|
|
|
if (_firstChar) {
|
|
_str.left = _left;
|
|
_str.top = _top;
|
|
_str.right = _left;
|
|
_str.bottom = _top;
|
|
_firstChar = false;
|
|
}
|
|
|
|
if (_left < _str.left)
|
|
_str.left = _left;
|
|
|
|
if (_top < _str.top)
|
|
_str.top = _top;
|
|
|
|
int drawTop = _top - vs->topline;
|
|
if (drawTop < 0)
|
|
drawTop = 0;
|
|
int bottom = drawTop + height + offsY;
|
|
|
|
_vm->updateDirtyRect(vs->number, _left, _left + width, drawTop, bottom, 0);
|
|
|
|
if (vs->number != 0)
|
|
_blitAlso = false;
|
|
if (vs->number == 0 && !_blitAlso)
|
|
_hasMask = true;
|
|
|
|
_charPtr += 4;
|
|
|
|
byte *mask = _vm->getResourceAddress(rtBuffer, 9)
|
|
+ drawTop * _vm->gdi._numStrips + _left / 8 + _vm->_screenStartStrip;
|
|
|
|
byte *dst = vs->screenPtr + vs->xstart + drawTop * _vm->_screenWidth + _left;
|
|
|
|
if (_blitAlso) {
|
|
byte *back = dst;
|
|
dst = _vm->getResourceAddress(rtBuffer, vs->number + 5)
|
|
+ vs->xstart + drawTop * _vm->_screenWidth + _left;
|
|
|
|
drawBits(vs, dst, mask, drawTop, width, height);
|
|
|
|
_vm->blit(back, dst, width, height);
|
|
} else {
|
|
drawBits(vs, dst, mask, drawTop, width, height);
|
|
}
|
|
|
|
_left += width;
|
|
if (_left > _str.right)
|
|
_str.right = _left;
|
|
|
|
if (_top + height > _str.bottom)
|
|
_str.bottom = _top + height;
|
|
|
|
_top -= offsY;
|
|
}
|
|
|
|
void CharsetRendererClassic::drawBits(VirtScreen *vs, byte *dst, byte *mask, int drawTop, int width, int height) {
|
|
byte maskmask;
|
|
int y, x;
|
|
int maskpos;
|
|
int color;
|
|
byte numbits, bits;
|
|
bool useMask = (vs->number == 0 && !_ignoreCharsetMask);
|
|
|
|
bits = *_charPtr++;
|
|
numbits = 8;
|
|
|
|
y = 0;
|
|
|
|
for (y = 0; y < height && y + drawTop < vs->height; y++) {
|
|
maskmask = revBitMask[_left & 7];
|
|
maskpos = 0;
|
|
|
|
for (x = 0; x < width; x++) {
|
|
int myMask = (0xFF << (8 - _bpp)) & 0xFF;
|
|
int myColor = (bits & myMask) >> (8 - _bpp);
|
|
color = (bits >> (8 - _bpp)) & 0xFF;
|
|
assert(color == myColor);
|
|
|
|
if (color) {
|
|
if (useMask) {
|
|
mask[maskpos] |= maskmask;
|
|
}
|
|
*dst = _vm->_charsetColorMap[color];
|
|
}
|
|
dst++;
|
|
bits <<= _bpp;
|
|
numbits -= _bpp;
|
|
if (numbits == 0) {
|
|
bits = *_charPtr++;
|
|
numbits = 8;
|
|
}
|
|
maskmask >>= 1;
|
|
if (maskmask == 0) {
|
|
maskmask = 0x80;
|
|
maskpos++;
|
|
}
|
|
}
|
|
dst += _vm->_screenWidth - width;
|
|
mask += _vm->gdi._numStrips;
|
|
}
|
|
}
|
|
|
|
CharsetRendererNut::CharsetRendererNut(Scumm *vm)
|
|
: CharsetRenderer(vm) {
|
|
_current = 0;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
char fontname[256];
|
|
sprintf(fontname, "font%d.nut", i);
|
|
_fr[i] = new NutRenderer(_vm);
|
|
if (!(_fr[i]->loadFont(fontname, _vm->getGameDataPath()))) {
|
|
delete _fr[i];
|
|
_fr[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
CharsetRendererNut::~CharsetRendererNut() {
|
|
for (int i = 0; i < 5; i++)
|
|
delete _fr[i];
|
|
}
|
|
|
|
void CharsetRendererNut::setCurID(byte id) {
|
|
assert(id < 5);
|
|
_curId = id;
|
|
_current = _fr[id];
|
|
assert(_current);
|
|
}
|
|
|
|
int CharsetRendererNut::getCharWidth(byte chr) {
|
|
assert(_current);
|
|
return _current->getCharWidth(chr);
|
|
}
|
|
|
|
int CharsetRendererNut::getFontHeight() {
|
|
// FIXME / TODO: how to implement this properly???
|
|
assert(_current);
|
|
return _current->getCharHeight('|');
|
|
}
|
|
|
|
void CharsetRendererNut::printChar(int chr) {
|
|
assert(_current);
|
|
if (chr == '@')
|
|
return;
|
|
|
|
if (_firstChar) {
|
|
_str.left = _left;
|
|
_str.top = _top;
|
|
_str.right = _left;
|
|
_str.bottom = _top;
|
|
_firstChar = false;
|
|
}
|
|
|
|
int width = _current->getCharWidth(chr);
|
|
int height = _current->getCharHeight(chr);
|
|
|
|
_hasMask = true;
|
|
_current->drawChar((char)chr, _left, _top, _color, !_ignoreCharsetMask);
|
|
_vm->updateDirtyRect(0, _left, _left + width, _top, _top + height, 0);
|
|
|
|
_left += width;
|
|
if (_left > _str.right)
|
|
_str.right = _left;
|
|
|
|
if (_top + height > _str.bottom)
|
|
_str.bottom = _top + height;
|
|
}
|
|
|