Files
scummvm-cursorfix/engines/kyra/text/text_eob_segacd.cpp
2026-02-02 04:50:13 +01:00

252 lines
7.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 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/>.
*
*/
#ifdef ENABLE_EOB
#include "kyra/engine/eob.h"
#include "kyra/graphics/screen_eob.h"
#include "kyra/graphics/screen_eob_segacd.h"
#include "kyra/text/text_eob_segacd.h"
namespace Kyra {
TextDisplayer_SegaCD::TextDisplayer_SegaCD(EoBEngine *engine, Screen_EoB *scr) : TextDisplayer_rpg(engine, scr), _engine(engine), _screen(scr), _renderer(scr->sega_getRenderer()),
_curDim(0), _textColor(0xFF), _curPosY(0), _curPosX(0) {
assert(_renderer);
_msgRenderBufferSize = 320 * 48;
_msgRenderBuffer = new uint8[_msgRenderBufferSize]();
}
TextDisplayer_SegaCD::~TextDisplayer_SegaCD() {
delete[] _msgRenderBuffer;
}
void TextDisplayer_SegaCD::printDialogueText(int id, const char *string1, const char *string2) {
if (string1 && string2) {
_engine->runDialogue(id, 2, 2, string1, string2);
} else {
_screen->hideMouse();
_engine->seq_segaPlaySequence(id);
_screen->showMouse();
}
}
void TextDisplayer_SegaCD::printDialogueText(const char *str, bool wait) {
int cs = _screen->setFontStyles(Screen::FID_8_FNT, _vm->gameFlags().lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth);
clearDim(_curDim);
if (wait) {
printShadedText(str, 32, 12);
_engine->resetSkipFlag();
_renderer->render(0);
_screen->updateScreen();
_engine->delay(500);
} else {
printShadedText(str, 0, 0);
_renderer->render(0);
_screen->updateScreen();
}
_screen->setFontStyles(Screen::FID_8_FNT, cs);
}
void TextDisplayer_SegaCD::printShadedText(const char *str, int x, int y, int textColor, int shadowColor, int pitchW, int pitchH, int marginRight, bool screenUpdate) {
const ScreenDim *s = &_dimTable[_curDim];
if (x == -1)
x = s->sx;
if (y == -1)
y = s->sy;
if (textColor == -1)
textColor = s->col1;
if (shadowColor == -1)
shadowColor = 0;
if (pitchW == -1)
pitchW = s->w;
if (pitchH == -1)
pitchH = s->h;
_screen->setTextMarginRight(pitchW - marginRight);
_screen->printShadedText(str, x, y, textColor, 0, shadowColor, pitchW >> 3);
if (!screenUpdate)
return;
if (s->column) {
for (int i = 0; i < (pitchH >> 3); ++i)
_screen->sega_loadTextBufferToVRAM(i * (pitchW << 2), ((s->line & 0x7FF) + i * s->column) << 5, pitchW << 2);
} else {
_screen->sega_loadTextBufferToVRAM(0, (s->line & 0x7FF) << 5, (pitchW * pitchH) >> 1);
}
}
int TextDisplayer_SegaCD::clearDim(int dim) {
int res = _curDim;
_curDim = dim;
_curPosY = _curPosX = 0;
const ScreenDim *s = &_dimTable[dim];
_renderer->memsetVRAM((s->line & 0x7FF) << 5, s->col2, (s->w * s->h) >> 1);
_screen->sega_clearTextBuffer(s->col2);
memset(_msgRenderBuffer, s->col2, _msgRenderBufferSize);
return res;
}
void TextDisplayer_SegaCD::displayText(char *str, ...) {
_screen->sega_setTextBuffer(_msgRenderBuffer, _msgRenderBufferSize);
int cs = _screen->setFontStyles(Screen::FID_8_FNT, Font::kStyleFullWidth);
_screen->setFontStyles(Screen::FID_8_FNT, cs | Font::kStyleFullWidth);
char tmp[3] = " ";
int posX = _curPosX;
bool updated = false;
va_list args;
va_start(args, str);
int tc = va_arg(args, int);
va_end(args);
if (tc != -1)
SWAP(_textColor, tc);
for (const char *pos = str; *pos; ) {
uint8 cmd = fetchCharacter(tmp, pos);
updated = false;
if (_dimTable[_curDim].h < _curPosY + _screen->getFontHeight()) {
_curPosY -= _screen->getFontHeight();
linefeed();
}
if (cmd == 6) {
_textColor = (uint8)*pos++;
} else if (cmd == 2) {
pos++;
} else if (cmd == 13) {
_curPosX = 0;
_curPosY += _screen->getFontHeight();
} else if (cmd == 9) {
_curPosX = posX;
_curPosY += _screen->getFontHeight();
} else {
if (((tmp[0] == ' ' || (tmp[0] == '\x81' && tmp[1] == '\x40')) && (_curPosX + _screen->getTextWidth(tmp) + _screen->getTextWidth((const char*)(pos), true) >= _dimTable[_curDim].w)) || (_curPosX + _screen->getTextWidth(tmp) >= _dimTable[_curDim].w)) {
// Skip space at the beginning of the new line
if (tmp[0] == ' ' || (tmp[0] == '\x81' && tmp[1] == '\x40'))
fetchCharacter(tmp, pos);
_curPosX = 0;
_curPosY += _screen->getFontHeight();
if (_dimTable[_curDim].h < _curPosY + _screen->getFontHeight()) {
_curPosY -= _screen->getFontHeight();
linefeed();
}
}
printShadedText(tmp, _curPosX, _curPosY, _textColor);
_curPosX += _screen->getTextWidth(tmp);
updated = true;
}
}
if (!updated)
printShadedText("", _curPosX, _curPosY, _textColor);
if (tc != -1)
SWAP(_textColor, tc);
_renderer->render(Screen_EoB::kSegaRenderPage);
_screen->setFontStyles(Screen::FID_8_FNT, cs);
_screen->copyRegion(8, 176, 8, 176, 280, 24, Screen_EoB::kSegaRenderPage, 0, Screen::CR_NO_P_CHECK);
_screen->sega_setTextBuffer(0, 0);
}
uint8 TextDisplayer_SegaCD::fetchCharacter(char *dest, const char *&src) {
uint8 c = (uint8)*src++;
if (c <= (uint8)'\r') {
dest[0] = '\0';
return c;
}
dest[0] = (char)c;
dest[1] = (c <= 0x7F || (c >= 0xA1 && c <= 0xDF)) ? '\0' : *src++;
return 0;
}
void TextDisplayer_SegaCD::linefeed() {
copyTextBufferLine(_screen->getFontHeight(), 0, (_dimTable[_curDim].h & ~7) - _screen->getFontHeight(), _dimTable[_curDim].w >> 3);
clearTextBufferLine(_screen->getFontHeight(), _screen->getFontHeight(), _dimTable[_curDim].w >> 3, _dimTable[_curDim].col2);
}
void TextDisplayer_SegaCD::clearTextBufferLine(uint16 y, uint16 lineHeight, uint16 pitch, uint8 col) {
uint32 *dst = (uint32*)(_msgRenderBuffer + (((y >> 3) * pitch) << 5) + ((y & 7) << 2));
int ln = y;
uint32 c = col | (col << 8) | (col << 16) | (col << 24);
while (lineHeight--) {
uint32 *dst2 = dst;
for (uint16 w = pitch; w; --w) {
*dst = c;
dst += 8;
}
dst = dst2 + 1;
if (((++ln) & 7) == 0)
dst += ((pitch - 1) << 3);
}
}
void TextDisplayer_SegaCD::copyTextBufferLine(uint16 srcY, uint16 dstY, uint16 lineHeight, uint16 pitch) {
uint32 *src = (uint32*)(_msgRenderBuffer + (((srcY >> 3) * pitch) << 5) + ((srcY & 7) << 2));
uint32 *dst = (uint32*)(_msgRenderBuffer + (((dstY >> 3) * pitch) << 5) + ((dstY & 7) << 2));
int src_ln = srcY;
int dst_ln = dstY;
while (lineHeight--) {
uint32 *src2 = src;
uint32 *dst2 = dst;
for (uint16 w = pitch; w; --w) {
*dst = *src;
src += 8;
dst += 8;
}
src = src2 + 1;
dst = dst2 + 1;
if (((++dst_ln) & 7) == 0)
dst += ((pitch - 1) << 3);
if (((++src_ln) & 7) == 0)
src += ((pitch - 1) << 3);
}
}
const ScreenDim TextDisplayer_SegaCD::_dimTable[6] = {
{ 0x0001, 0x0017, 0x0118, 0x0018, 0xff, 0x44, 0x2597, 0x0000 },
{ 0x0012, 0x0009, 0x00a0, 0x0080, 0xff, 0x99, 0x0153, 0x0028 },
{ 0x0001, 0x0014, 0x0130, 0x0030, 0xff, 0xee, 0xe51c, 0x0000 },
{ 0x0001, 0x0017, 0x00D0, 0x0030, 0xff, 0x00, 0x0461, 0x0000 },
{ 0x0000, 0x0000, 0x00F0, 0x0100, 0xff, 0x00, 0x600A, 0x0000 },
{ 0x0000, 0x0000, 0x0140, 0x00B0, 0xff, 0x11, 0x4001, 0x0000 }
};
} // End of namespace Kyra
#endif // ENABLE_EOB