scummvm/engines/kyra/gui/gui_eob_segacd.cpp

1096 lines
39 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/gui/gui_eob_segacd.h"
#include "kyra/resource/resource.h"
#include "kyra/resource/resource_segacd.h"
#include "common/system.h"
namespace Kyra {
int EoBEngine::clickedCamp(Button *button) {
gui_resetAnimations();
if (_flags.platform == Common::kPlatformSegaCD)
snd_playSong(11);
EoBCoreEngine::clickedCamp(button);
if (_flags.platform != Common::kPlatformSegaCD)
return button->arg;
gui_resetAnimations();
return button->arg;
}
void EoBEngine::gui_drawPlayField(bool refresh) {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::gui_drawPlayField(refresh);
return;
}
_screen->sega_fadeToBlack(_loading ? 0 : 1);
_screen->sega_selectPalette(6, 1);
_screen->sega_selectPalette(7, 3);
// transposeScreenOutputY(8);
_txt->clearDim(0);
_screen->sega_getAnimator()->clearSprites();
_screen->sega_getAnimator()->update();
SegaRenderer *r = _screen->sega_getRenderer();
r->fillRectWithTiles(0, 0, 0, 40, 28, 0);
r->fillRectWithTiles(1, 0, 0, 40, 28, 0);
uint8 *data = _res->fileData("PLAYFLD", 0);
for (int i = 0; i < 256; ++i)
r->loadToVRAM(&data[i << 5], 32, _addrTbl1[i] << 5);
memcpy(_compassData, data + 0x2000, 0x5000);
delete[] data;
const uint16 *pattern = _playFldPattern1;
uint16 *dst = _playFldPattern2;
for (int i = 0; i < 1040; ++i) {
int ix = (*pattern++) - 11;
*dst++ = (ix < 0) ? 0 : _addrTbl1[ix];
}
static const uint16 ps[6] = { 0xCE, 0xE0, 0x2FE, 0x310, 0x52E, 0x540 };
for (int i = 0; i < 4; ++i) {
dst = &_playFldPattern2[ps[i] >> 1];
memset(dst, 0, 8);
memset(&dst[40], 0, 8);
memset(&dst[80], 0, 8);
memset(&dst[120], 0, 8);
}
_sres->loadContainer("ITEM");
Common::SeekableReadStreamEndian *str = _sres->resStreamEndian(7);
r->loadStreamToVRAM(str, 0x8880, true);
delete str;
str = _sres->resStreamEndian(9);
r->loadStreamToVRAM(str, 0xA4A0, false);
delete str;
str = _sres->resStreamEndian(10);
r->loadStreamToVRAM(str, 0x7920, false);
delete str;
gui_setupPlayFieldHelperPages();
if (refresh && !_sceneDrawPage2)
drawScene(1);
_screen->copyRegionToBuffer(0, 173, 0, 6, 120, _shakeBackBuffer1);
_screen->copyRegionToBuffer(0, 0, 117, 179, 6, _shakeBackBuffer2);
// Since we're not going to draw the character portrait boxes with the SegaRenderer but rather with our "normal" code, we have to backup
// some parts of the background between the character portraits. Unlike in the other versions the red splat shapes overlaps with that space.
for (int i = 0; i < 6; ++i) {
delete[] _redSplatBG[i];
_redSplatBG[i] = new uint8[_redSplatShape[2] << 5];
_screen->copyRegionToBuffer(0, guiSettings()->charBoxCoords.boxX[i & 1] + guiSettings()->charBoxCoords.redSplatOffsetX, guiSettings()->charBoxCoords.boxY[i >> 1] + guiSettings()->charBoxCoords.boxHeight - 1, _redSplatShape[2] << 3, 4, _redSplatBG[i]);
}
for (int i = 2; i < 4; ++i) {
if (_characters[i + 2].flags & 1)
memcpy(_redSplatBG[i] + _redSplatShape[2] * 24, _redSplatBG[0] + _redSplatShape[2] * 24, _redSplatShape[2] << 3);
}
_compassDirection2 = -1;
gui_drawCompass(false);
_screen->sega_fadeToNeutral(1);
}
void EoBEngine::gui_setupPlayFieldHelperPages(bool keepText) {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::gui_setupPlayFieldHelperPages();
return;
}
if (!keepText)
_txt->clearDim(0);
SegaRenderer *r = _screen->sega_getRenderer();
r->loadToVRAM(_scrYellow, 4992, 0x3CE0);
r->fillRectWithTiles(0, 0, 0, 22, 21, 0);
r->fillRectWithTiles(0, 22, 0, 18, 21, 0);
r->fillRectWithTiles(1, 0, 0, 40, 26, 0x2000, true, false, _playFldPattern2);
r->fillRectWithTiles(0, 0, 21, 40, 5, 0x2000, true, false, _textFieldPattern);
// Nametables for scene window vcn block tiles. We don't need that. We draw the blocks with our "normal" graphics code.
// r->fillRectWithTiles(1, 0, 0, 22, 15, 0xC14B, true, true);
// Nametables for scene window shapes tiles. We don't need that, since we're not going to draw any scene shapes with the renderer.
// r->fillRectWithTiles(0, 0, 1, 22, 14, 0xE295, true, true);
// Text field tiles
r->fillRectWithTiles(0, 1, 22, 35, 3, 0x2597, true);
r->render(0);
r->fillRectWithTiles(1, 22, 0, 18, 21, 0x6444, true, true, _invPattern);
r->render(2);
r->fillRectWithTiles(1, 22, 0, 18, 21, 0x6444, true, true, _statsPattern);
r->render(Screen_EoB::kSegaRenderPage);
_screen->copyRegion(184, 1, 176, 168, guiSettings()->charBoxCoords.boxWidth, 24, 0, 2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(184, 25, 240, 168, guiSettings()->charBoxCoords.boxWidth, guiSettings()->charBoxCoords.boxHeight - 24, 0, 2, Screen::CR_NO_P_CHECK);
}
void EoBEngine::gui_drawWeaponSlotStatus(int x, int y, int status) {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::gui_drawWeaponSlotStatus(x, y, status);
return;
}
if (status < 0) {
_screen->drawShape(_screen->_curPage, _weaponSlotShapes[status < -2 ? -status - 1 : 3 - status], x - 1, y, 0);
} else {
_screen->drawShape(_screen->_curPage, _weaponSlotShapes[0], x - 1, y, 0);
gui_printInventoryDigits(x + 8, y + 6, status);
}
}
void EoBEngine::gui_printInventoryDigits(int x, int y, int val) {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::gui_printInventoryDigits(x, y, val);
return;
}
_screen->drawShape(_screen->_curPage, _invSmallDigits[(val < 10) ? 22 + val : (val >= 100 ? 1 : 2 + val / 10)], x, y, 0);
_screen->drawShape(_screen->_curPage, (val >= 10 && val < 100) ? _invSmallDigits[12 + (val % 10)] : 0, x, y, 0);
}
void EoBEngine::gui_drawCharacterStatsPage() {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::gui_drawCharacterStatsPage();
return;
}
SegaRenderer *r = _screen->sega_getRenderer();
EoBCharacter *c = &_characters[_updateCharNum];
memset(_tempPattern, 0, 792);
for (int i = 0; i < 11; ++i) {
_tempPattern[5 * 18 + i + 1] = 0x6555 + i;
_tempPattern[6 * 18 + i + 1] = 0x6565 + i;
}
for (int i = 0; i < 4; i++)
printStatsString(_chargenStatStrings[6 + i], 1, 11 + i);
printStatsString(_chargenStatStrings[10], 7, 16);
printStatsString(_chargenClassStrings[c->cClass == 9 ? 27 : (c->cClass == 12 ? 28 : c->cClass)], 2, 7);
printStatsString(_chargenAlignmentStrings[c->alignment], 2, 8);
printStatsString(_chargenRaceSexStrings[c->raceSex], 2, 9);
// FIXME? For now I have kept the exact original layout. If the character has a strengthExt stat there will be
// no space left between the digits and the right stats row ("DEX" etc.). Maybe I should move that row one tile
// further to the right? There is space enough left over there.
printStatsString(getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), c->strengthExtCur ? 4 : 5, 11);
printStatsString(Common::String::format("%2d", c->intelligenceCur).c_str(), 5, 12);
printStatsString(Common::String::format("%2d", c->wisdomCur).c_str(), 5, 13);
printStatsString(Common::String::format("%2d", c->dexterityCur).c_str(), 13, 11);
printStatsString(Common::String::format("%2d", c->constitutionCur).c_str(), 13, 12);
printStatsString(Common::String::format("%2d", c->charismaCur).c_str(), 13, 13);
printStatsString(Common::String::format("%2d", c->armorClass).c_str(), _flags.lang == Common::JA_JPN ? 9 : 5, 14);
for (int i = 0; i < 3; i++) {
int t = getCharacterClassType(c->cClass, i);
if (t == -1)
continue;
printStatsString(_chargenClassStrings[t + 21], 1, 17 + i);
printStatsString(Common::String::format("%2d", c->level[i]).c_str(), 14, 17 + i);
printStatsString(Common::String::format("%6d", c->experience[i]).c_str(), 7, 17 + i);
}
r->fillRectWithTiles(0, 22, 0, 18, 21, 0, true, true, _tempPattern);
r->render(2, 22, 5, 18, 16);
}
void EoBEngine::gui_displayMap() {
disableSysTimer(2);
_screen->sega_fadeToBlack(2);
Button b;
clickedSpellbookAbort(&b);
gui_resetAnimations();
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
_characters[i].damageTaken = 0;
_characters[i].slotStatus[0] = _characters[i].slotStatus[1] = 0;
gui_drawCharPortraitWithStats(i);
}
SegaRenderer *r = _screen->sega_getRenderer();
r->fillRectWithTiles(0, 0, 0, 40, 28, 0);
r->fillRectWithTiles(1, 0, 0, 40, 28, 0);
_screen->sega_getAnimator()->clearSprites();
_screen->sega_getAnimator()->update();
_screen->sega_selectPalette(55, 1);
_screen->sega_selectPalette(56, 2);
snd_stopSound();
_sres->loadContainer("MAP");
Common::SeekableReadStreamEndian *in = _sres->resStreamEndian(0);
r->loadStreamToVRAM(in, 0x20);
delete in;
in = _sres->resStreamEndian(1);
r->loadStreamToVRAM(in, 0x80);
delete in;
int cs = _screen->setFontStyles(_screen->_currentFont, _flags.lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth);
_screen->sega_clearTextBuffer(0);
for (int i = 0; i < 3; ++i)
drawMapButton(_mapStrings1[i], 0, i << 4);
_screen->sega_loadTextBufferToVRAM(0, 0x7E20, 1536);
r->fillRectWithTiles(0, 31, 19, 8, 6, 0x63F1, true);
_screen->sega_clearTextBuffer(0);
_screen->sega_clearTextBuffer(0);
_txt->printShadedText(_mapStrings2[_currentLevel - 1], 0, 0, 0xFF, 0, 64, 16, 0, false);
_screen->sega_loadTextBufferToVRAM(0, 0x7C20, 512);
r->fillRectWithTiles(0, 31, 16, 8, 2, 0x63E1, true);
drawMapPage(_currentLevel);
r->render(0);
_screen->sega_fadeToNeutral(3);
gui_resetButtonList();
for (int i = 96; i < 99; ++i)
gui_initButton(i);
int animState = 0;
for (int level = _currentLevel; level && !shouldQuit(); ) {
uint32 del = _system->getMillis() + 16;
int inputFlag = checkInput(_activeButtons, false, 0);
removeInputTop();
drawMapSpots(level, animState < 20 ? 0 : 1);
bool needupdate = (animState == 0 || animState == 20);
if (++animState == 40)
animState = 0;
int op = (inputFlag & 0x8000) ? (int16)gui_getButton(_activeButtons, inputFlag & 0xFF)->arg : 0;
if (op) {
snd_playSoundEffect(0x81);
level = (op == 2) ? 0 : CLIP(level + op, 1, 12);
if (level)
drawMapPage(level);
}
if (needupdate) {
r->render(0);
_screen->updateScreen();
}
delayUntil(del);
}
_screen->setFontStyles(_screen->_currentFont, cs);
_screen->sega_fadeToBlack(3);
setLevelPalettes(_currentLevel);
gui_drawPlayField(true);
gui_drawAllCharPortraitsWithStats();
gui_setInventoryButtons();
snd_playLevelScore();
enableSysTimer(2);
}
void EoBEngine::gui_drawSpellbook() {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::gui_drawSpellbook();
return;
}
SegaRenderer *r = _screen->sega_getRenderer();
r->fillRectWithTiles(0, 10, 15, 12, 7, 0);
r->fillRectWithTiles(1, 10, 15, 12, 7, 0x6429);
memset(_tempPattern, 0, 168);
uint16 *dst = _tempPattern;
for (int i = 0; i < 6; ++i) {
dst[0] = 0x642B + 2 * i + (i == _openBookSpellLevel ? 0 : 12);
dst[1] = dst[0] + 1;
dst += 2;
}
for (int i = 0; i < 6; ++i) {
int d = _openBookAvailableSpells[_openBookSpellLevel * 10 + i];
if (d < 0)
continue;
printSpellbookString(&_tempPattern[(i + 1) * 12], _openBookSpellList[d], (i == _openBookSpellSelectedItem) ? 0x6223 : 0x63C9);
}
r->fillRectWithTiles(0, 10, 15, 12, 7, 0, true, false, _tempPattern);
r->render(Screen_EoB::kSegaRenderPage, 10, 15, 12, 7);
// The original SegaCD version actually doesn't disable the spell book after use but closes it instead.
if (!_closeSpellbookAfterUse) {
if (_characters[_openBookChar].disabledSlots & 4) {
static const uint8 xpos[] = { 0x44, 0x62, 0x80, 0x90 };
static const uint8 ypos[] = { 0x80, 0x90, 0xA0 };
for (int yc = 0; yc < 3; yc++) {
for (int xc = 0; xc < 4; xc++)
_screen->drawShape(Screen_EoB::kSegaRenderPage, _weaponSlotGrid, xpos[xc], ypos[yc], 0);
}
}
}
_screen->copyRegion(80, 120, 80, 120, 96, 56, Screen_EoB::kSegaRenderPage, 0, Screen::CR_NO_P_CHECK);
if (!_loading)
_screen->updateScreen();
}
void EoBEngine::gui_updateAnimations() {
if (_flags.platform != Common::kPlatformSegaCD)
return;
bool updScreen = false;
bool redrawCompass = false;
// Compass
if (_compassDirection != _compassDirection2) {
_compassAnimDest = _compassDirection << 2;
int diff = _compassAnimDest - _compassAnimPhase;
if (diff < 0)
diff += 16;
if (diff) {
_compassAnimStep = (diff < 8) ? 1 : -1;
_compassAnimDone = false;
}
_compassDirection2 = _compassDirection;
redrawCompass = true;
}
if (_compassAnimDelayCounter) {
--_compassAnimDelayCounter;
} else if (!redrawCompass) {
if (_compassAnimDest != _compassAnimPhase) {
_compassAnimPhase = (_compassAnimPhase + _compassAnimStep) & 0x0F;
_compassAnimDelayCounter = 6;
redrawCompass = true;
} else if (!_compassAnimDone) {
if (_compassAnimSwitch) {
_compassAnimPhase = (_compassAnimPhase + _compassAnimStep) & 0x0F;
_compassAnimDelayCounter = 6;
_compassAnimStep = -_compassAnimStep;
_compassAnimSwitch = false;
} else {
_compassAnimDone = _compassAnimSwitch = true;
}
redrawCompass = true;
}
}
if (_updateFlags)
_compassTilesRestore = true;
else if (_compassTilesRestore) {
_screen->sega_getRenderer()->fillRectWithTiles(0, 10, 15, 12, 7, 0);
for (int i = 15; i < 22; ++i)
_screen->sega_getRenderer()->fillRectWithTiles(1, 10, i, 12, 1, 0x2000, true, true, &_playFldPattern2[i * 40 + 10]);
_compassTilesRestore = false;
}
if (redrawCompass) {
_screen->sega_getRenderer()->loadToVRAM(_compassData + (_compassAnimPhase & 0x0F) * 0x500, 0x500, 0xEE00);
_screen->sega_getRenderer()->render(0, 11, 15, 10, 6);
updScreen = true;
}
// Red grid effect
for (int i = 0; i < 6; ++i) {
if (!_characters[i].gfxUpdateCountdown)
continue;
_characters[i].gfxUpdateCountdown--;
int cp = _screen->setCurPage(0);
if (!_currentControlMode && (_characters[i].gfxUpdateCountdown & 1))
_screen->drawShape(0, _redGrid, 176 + guiSettings()->charBoxCoords.facePosX_1[i & 1], guiSettings()->charBoxCoords.facePosY_1[i >> 1], 0);
else if (_currentControlMode && _updateCharNum == i && (_characters[i].gfxUpdateCountdown & 1))
_screen->drawShape(0, _redGrid, guiSettings()->charBoxCoords.facePosX_2[0], guiSettings()->charBoxCoords.facePosY_2[0], 0);
else
gui_drawFaceShape(i);
_screen->setCurPage(cp);
updScreen = true;
}
// Scene shake
if (_sceneShakeCountdown) {
--_sceneShakeCountdown;
_sceneShakeOffsetX = _sceneShakeOffsets[_sceneShakeCountdown << 1];
_sceneShakeOffsetY = _sceneShakeOffsets[(_sceneShakeCountdown << 1) + 1];
_screen->fillRect(0, 0, 2, 119, 0, _sceneDrawPage1);
_screen->fillRect(0, 0, 175, 2, 0, _sceneDrawPage1);
_screen->copyBlockToPage(_sceneDrawPage1, 173, 0, 6, 120, _shakeBackBuffer1);
_screen->copyBlockToPage(_sceneDrawPage1, 0, 117, 179, 6, _shakeBackBuffer2);
if (_updateFlags)
_screen->copyRegion(64, 120, 64, 120, 112, 3, Screen_EoB::kSegaRenderPage, _sceneDrawPage1);
_screen->copyBlockToPage(_sceneDrawPage1, _sceneXoffset + _sceneShakeOffsetX, _sceneShakeOffsetY, 176, 120, _sceneWindowBuffer);
// For whatever reason the original shakes all types of shapes (decorations, doors, etc.) except the monsters and
// the items lying on the floor. So we do the same. I've added drawing flags to drawSceneShapes() which allow
// separate drawing passes for the different shape types.
for (int i = 0; i < 18; i++) {
_shapeShakeOffsetX = _sceneShakeOffsetX;
_shapeShakeOffsetY = _sceneShakeOffsetY;
// All shapes except monsters and items
drawSceneShapes(i, i + 1, 0xFF & ~0x2A);
_shapeShakeOffsetX = _shapeShakeOffsetY = 0;
// Monsters and items
drawSceneShapes(i, i + 1, 0x2A);
}
_screen->copyRegion(0, 0, 0, 0, 179, 123, _sceneDrawPage1, 0, Screen::CR_NO_P_CHECK);
updScreen = true;
}
if (updScreen)
_screen->updateScreen();
}
void EoBEngine::gui_resetAnimations() {
if (_flags.platform != Common::kPlatformSegaCD)
return;
for (int i = 0; i < 6; ++i)
_characters[i].gfxUpdateCountdown = 1;
_sceneShakeCountdown = 1;
_compassAnimDelayCounter = _compassAnimSwitch = 0;
_compassAnimPhase = _compassAnimDest;
}
void EoBEngine::makeNameShapes(int charId) {
if (_flags.platform != Common::kPlatformSegaCD)
return;
int first = 0;
int last = 5;
if (charId != -1)
first = last = charId;
int cd = _txt->clearDim(4);
int cp = _screen->setCurPage(2);
_screen->sega_getRenderer()->fillRectWithTiles(1, 0, 0, 40, 28, 0x2000);
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, 0, 30, 28, 0x600A, true);
_screen->sega_clearTextBuffer(0);
int cs = _screen->setFontStyles(_screen->_currentFont, Font::kStyleForceOneByte);
uint8 *in = _res->fileData("FACE", 0);
for (int i = first; i <= last; ++i) {
if (!_characters[i].flags)
continue;
if (_characters[i].portrait < 0) {
_screen->sega_getRenderer()->loadToVRAM(in + 27424 - _characters[i].portrait * 224, 224, 0x3F00 + i * 0xE0);
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, i << 1, 7, 1, 0x61F8 + i * 7, true);
} else {
_txt->printShadedText(_characters[i].name, 0, i << 4, 0xFF, 0xCC);
}
}
delete[] in;
_screen->sega_getRenderer()->render(_screen->_curPage, 0, 0, 8, 12);
for (int i = first; i <= last; ++i) {
if (!_characters[i].flags)
continue;
delete[] _characters[i].nameShape;
_characters[i].nameShape = _screen->encodeShape(0, i << 4, 8, 13);
}
_screen->clearPage(2);
_screen->setCurPage(cp);
_screen->sega_clearTextBuffer(0);
_screen->setFontStyles(_screen->_currentFont, cs);
_txt->clearDim(4);
_txt->clearDim(cd);
}
void EoBEngine::makeFaceShapes(int charId) {
if (_flags.platform != Common::kPlatformSegaCD) {
EoBCoreEngine::makeFaceShapes();
return;
}
int first = 0;
int last = 5;
if (charId != -1)
first = last = charId;
uint8 *in = _res->fileData("FACE", 0);
for (int i = first; i <= last; i++) {
EoBCharacter *c = &_characters[i];
if (!c->flags)
continue;
_screen->sega_encodeShapesFromSprites(&c->faceShape, &in[(c->portrait < 0 ? -c->portrait + 43 : c->portrait) << 9], 1, 32, 32, 3);
}
delete[] in;
}
void EoBEngine::printStatsString(const char *str, int x, int y) {
uint16 *dst = &_tempPattern[y * 18 + x];
for (const uint8 *pos = (const uint8*)str; *pos; ++pos)
*dst++ = 0x6525 + _charTilesTable[*pos];
}
void EoBEngine::printSpellbookString(uint16 *dst, const char *str, uint16 ntbl) {
assert(str);
const uint8 *in = (const uint8*)str;
for (uint8 c = *in++; c; c = *in++) {
if (_flags.lang == Common::JA_JPN) {
if (c > 165 && c < 222)
*dst = ntbl + c - 166;
else if (c == 32)
*dst = ntbl + 82;
else if (c > 47 && c < 58)
*dst = ntbl + c + 35;
else if (c == 47)
*dst = ntbl + 93;
else if (c == 165)
*dst = ntbl + 94;
else if (c == 43)
*dst = ntbl + 95;
if (*in == 222) {
if (c > 181 && c < 197) {
*dst = ntbl + c - 121;
++in;
} else if (c > 201 && c < 207) {
*dst = ntbl + c - 126;
++in;
} else if (c == 179) {
*dst = ntbl + c + 81;
++in;
}
} else if (*in == 223 && c > 201 && c < 207) {
*dst = ntbl + c - 146;
++in;
}
} else {
if (c > 31 && c < 128)
*dst = ntbl + c - 32;
}
dst++;
}
}
void EoBEngine::drawMapButton(const char *str, int x, int y) {
_screen->sega_drawClippedLine(8, 9, x, y, 64, 14, 0x99);
_screen->sega_drawClippedLine(8, 9, x, y + 1, 63, 13, 0xBB);
_screen->sega_drawClippedLine(8, 9, x + 1, y + 1, 62, 12, 0xAA);
_txt->printShadedText(str, x + 14, y + 1, 0xFF, 0xCC, 64, 72, 0, false);
}
void EoBEngine::drawMapPage(int level) {
_screen->sega_clearTextBuffer(0);
int cs = _screen->setFontStyles(_screen->_currentFont, (_flags.lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth) | Font::kStyleNarrow1);
_txt->printShadedText(_mapStrings3[level - 1], 0, 0, 0xCC, 0, 48, 16, 0, false);
_screen->setFontStyles(_screen->_currentFont, cs);
_screen->sega_loadTextBufferToVRAM(0, 0x7920, 384);
SegaRenderer *r = _screen->sega_getRenderer();
r->fillRectWithTiles(0, 23, 8, 6, 2, 0x63C9, true);
Common::SeekableReadStreamEndian *in = _sres->resStreamEndian(hasLevelMap(level) ? 2 + level : 2);
r->loadStreamToVRAM(in, 0x5500, true);
delete in;
r->fillRectWithTiles(1, 3, 0, 26, 26, 0x2004, true);
r->fillRectWithTiles(0, 5, 6, 17, 17, 0x42A8, true);
}
void EoBEngine::drawMapSpots(int level, int animState) {
SegaAnimator *a = _screen->sega_getAnimator();
const EoBItem &m = _items[447 + level];
int curX = _currentBlock & 0x1F;
int curY = _currentBlock >> 5;
int mX = m.block & 0x1F;
int mY = m.block >> 5;
if (hasLevelMap(level)) {
if (!animState && level == _currentLevel)
a->initSprite(0, (curX << 2) + 48, (curY << 2) + 56, 0x6001, 0);
else
a->initSprite(0, 0x4000, 0, 0, 0);
a->initSprite(1, 0x4000, 0, 0, 0);
} else {
a->initSprite(0, 0x4000, 0, 0, 0);
if (level == _currentLevel)
a->initSprite(0, (curX << 2) + 48, (curY << 2) + 56, animState ? 0x2002 : 0x2001, 0);
a->initSprite(1, (mX << 2) + 48, (mY << 2) + 56, animState ? 0x2002 : 0x2003, 0);
}
a->update();
}
void EoBEngine::drawDialogueButtons() {
if (_flags.platform != Common::kPlatformSegaCD) {
KyraRpgEngine::drawDialogueButtons();
return;
}
_screen->sega_clearTextBuffer(0);
for (int i = 0; i < _dialogueNumButtons; i++) {
int cs = _screen->setFontStyles(_screen->_currentFont, (_flags.lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth) | Font::kStyleNarrow2);
if (_screen->getTextWidth(_dialogueButtonString[i]) > 90)
_screen->setFontStyles(_screen->_currentFont, (_flags.lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth) | Font::kStyleNarrow1);
_screen->sega_drawClippedLine(38, 6, _dialogueButtonPosX[i], _dialogueButtonPosY[i], 90, 14, 0x99);
_screen->sega_drawClippedLine(38, 6, _dialogueButtonPosX[i], _dialogueButtonPosY[i] + 1, 89, 13, 0xBB);
_screen->sega_drawClippedLine(38, 6, _dialogueButtonPosX[i] + 1, _dialogueButtonPosY[i] + 1, 88, 12, 0xAA);
_txt->printShadedText(_dialogueButtonString[i], _dialogueButtonPosX[i] + (_dialogueButtonWidth >> 1) - MIN<int>(_dialogueButtonWidth, _screen->getTextWidth(_dialogueButtonString[i])) / 2,
_dialogueButtonPosY[i] + 1, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0xEE, 304, 48, 0, false);
_screen->setFontStyles(_screen->_currentFont, cs);
}
_screen->sega_loadTextBufferToVRAM(0, 0xA380, 7296);
_screen->sega_getRenderer()->render(0);
}
GUI_EoB_SegaCD::GUI_EoB_SegaCD(EoBEngine *vm) : GUI_EoB(vm), _vm(vm), _clickableCharactersNumPages(vm->_textInputCharacterLinesSize) {
_vm->_sres->loadContainer("ITEM");
uint8 *cm = _vm->_sres->resData(8, 0);
uint8 *cmdec = new uint8[47925];
uint16 decodeSize = READ_LE_UINT16(cm + 2);
_screen->decodeBIN(cm + 4, cmdec, decodeSize);
_campMenu = cmdec;
delete[] cm;
const EoBMenuButtonDef* df = &_vm->_menuButtonDefs[6];
_saveLoadCancelButton = new Button();
_saveLoadCancelButton->index = 7;
_saveLoadCancelButton->width = df->width;
_saveLoadCancelButton->height = df->height;
_saveLoadCancelButton->flags = df->flags;
_saveLoadCancelButton->extButtonDef = df;
}
GUI_EoB_SegaCD::~GUI_EoB_SegaCD() {
delete[] _campMenu;
delete _saveLoadCancelButton;
}
void GUI_EoB_SegaCD::drawCampMenu() {
_screen->sega_getRenderer()->loadToVRAM(_campMenu, 14784, 0x20);
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, 0, 22, 21, 0);
_screen->sega_getRenderer()->fillRectWithTiles(1, 0, 0, 22, 21, 0x4001, true);
_screen->sega_selectPalette(40, 2, true);
}
void GUI_EoB_SegaCD::initMemorizePrayMenu(int spellType) {
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, 0, 22, 21, 0);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 8, 20, 2, 0x62AB, true);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 4, 20, 4, 0x6283, true);
_screen->sega_getRenderer()->memsetVRAM(0x5060, 0, 2560);
_screen->sega_getRenderer()->memsetVRAM(0x5560, 0, 1280);
_screen->sega_getRenderer()->loadToVRAM(&_campMenu[0x87C0], 4992, 0x3CE0);
_screen->sega_clearTextBuffer(0);
_vm->_txt->printShadedText(_vm->_menuStringsSpells[spellType ? 17 : 14], 0, 2, 0xFF, 0xCC, 160, 16, 0, false);
_screen->sega_loadTextBufferToVRAM(0, 0x5060, 2560);
_screen->sega_getRenderer()->render(0, 1, 4, 20, 2);
}
void GUI_EoB_SegaCD::initScribeScrollMenu() {
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, 0, 22, 21, 0);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 4, 20, 4, 0x6283, true);
_screen->sega_getRenderer()->loadToVRAM(&_campMenu[0x87C0], 4992, 0x3CE0);
_screen->sega_clearTextBuffer(0);
_vm->_txt->printShadedText(getMenuString(48), 0, 3, 0xFF, 0xCC, 160, 16, 0, false);
_screen->sega_loadTextBufferToVRAM(0, 0x5060, 2560);
_screen->sega_getRenderer()->render(0, 1, 4, 20, 2);
}
void GUI_EoB_SegaCD::printScribeScrollSpellString(const int16 *menuItems, int id, bool highlight) {
assert(menuItems);
uint16 buf[22];
memset(buf, 0, sizeof(buf));
_vm->printSpellbookString(&buf[1], _vm->_mageSpellList[menuItems[id]], highlight ? 0x6223 : 0x63C9);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 10 + id, 20, 1, 0, true, false, buf);
_screen->sega_getRenderer()->render(0, 1, 10 + id, 20, 1);
}
void GUI_EoB_SegaCD::drawSaveSlotDialog(int x, int y, int id) {
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, 0, 22, 21, 0);
_screen->sega_getRenderer()->fillRectWithTiles(0, (x >> 3) + 1, (y >> 3) + (y ? 3 : 4), 20, 2, 0x6283, true);
_screen->sega_getRenderer()->fillRectWithTiles(0, (x >> 3) + (x ? 5 : 6), (y >> 3) + (y ? 6 : 7), 15, 10, 0x62AB, true);
_screen->sega_getRenderer()->fillRectWithTiles(0, (x >> 3) + 1, (y >> 3) + 19, 7, 1, 0x6002, true);
_screen->sega_getRenderer()->loadToVRAM(&_campMenu[0x87C0], 4992, 0x3CE0);
_screen->sega_getRenderer()->memsetVRAM(0x5560, 0, 4480);
_screen->sega_clearTextBuffer(0);
_saveLoadCancelButton->x = ((const EoBMenuButtonDef*)_saveLoadCancelButton->extButtonDef)->x + x - (x ? 8 : 0);
_saveLoadCancelButton->y = ((const EoBMenuButtonDef*)_saveLoadCancelButton->extButtonDef)->y + y;
int cs = _screen->setFontStyles(_screen->_currentFont, _vm->gameFlags().lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth);
_vm->_txt->printShadedText(_vm->_saveLoadStrings[2 + id], 0, 3, 0xFF, 0xCC, 160, 16, 0, false);
_screen->setFontStyles(_screen->_currentFont, cs);
_screen->sega_loadTextBufferToVRAM(0, 0x5060, 1280);
_screen->sega_getRenderer()->render(0, x >> 3, (y >> 3) + 1, 22, 21);
}
bool GUI_EoB_SegaCD::confirmDialogue(int id) {
_screen->sega_clearTextBuffer(0);
int cs = _vm->gameFlags().lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth;
if (id == 47) {
cs |= Font::kStyleNarrow2;
_screen->_charSpacing = 1;
}
cs = _screen->setFontStyles(_screen->_currentFont, cs);
_vm->_txt->printShadedText(getMenuString(id), 0, 3, 0xFF, 0xCC, 160, 40, 0, false);
_screen->_charSpacing = 0;
_screen->setFontStyles(_screen->_currentFont, cs);
_screen->sega_loadTextBufferToVRAM(0, 0x5060, 10240);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 0, 20, 20, 0);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 5, 20, 8, 0x6283, true);
_screen->sega_getRenderer()->render(0, 1, 0, 22, 20);
_screen->updateScreen();
Button *buttonList = initMenu(5);
int newHighlight = 0;
int lastHighlight = -1;
bool result = false;
for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
if (newHighlight != lastHighlight) {
if (lastHighlight != -1)
drawMenuButton(_vm->gui_getButton(buttonList, lastHighlight + 33), false, false, true);
drawMenuButton(_vm->gui_getButton(buttonList, newHighlight + 33), false, true, true);
_screen->updateScreen();
lastHighlight = newHighlight;
}
int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80FF;
_vm->removeInputTop();
if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
result = lastHighlight == 0;
inputFlag = 0x8012 + lastHighlight;
runLoop = false;
} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
newHighlight ^= 1;
} else if (inputFlag == 0x8012) {
result = true;
runLoop = false;
} else if (inputFlag == 0x8013) {
result = false;
runLoop = false;
} else {
Common::Point p = _vm->getMousePos();
for (Button *b = buttonList; b; b = b->nextButton) {
if ((b->arg & 2) && _vm->posWithinRect(p.x, p.y, b->x, b->y, b->x + b->width, b->y + b->height))
newHighlight = b->index - 18;
}
}
if (!runLoop) {
Button *b = _vm->gui_getButton(buttonList, lastHighlight + 18);
drawMenuButton(b, true, true, true);
_screen->updateScreen();
_vm->_system->delayMillis(80);
drawMenuButton(b, false, true, true);
_screen->updateScreen();
}
}
releaseButtons(buttonList);
return result;
}
void GUI_EoB_SegaCD::displayTextBox(int id, int textColor, bool wait) {
_screen->sega_getRenderer()->fillRectWithTiles(0, 0, 0, 22, 20, 0);
_screen->sega_clearTextBuffer(0);
int cs = _vm->gameFlags().lang == Common::JA_JPN ? Font::kStyleNone : Font::kStyleFullWidth;
if (id == 23 || id == 26 || id == 49)
cs |= Font::kStyleNarrow2;
cs = _screen->setFontStyles(_screen->_currentFont, cs);
_vm->_txt->printShadedText(getMenuString(id), 0, 0, textColor, 0xCC, 160, 40, 0, false);
_screen->sega_loadTextBufferToVRAM(0, 0x5060, 3200);
_screen->setFontStyles(_screen->_currentFont, cs);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 6, 20, 5, 0x6283, true);
_screen->sega_getRenderer()->render(0, 0, 1, 22, 19);
_screen->updateScreen();
if (!wait)
return;
_vm->resetSkipFlag();
while (!(_vm->shouldQuit() || _vm->skipFlag()))
_vm->delay(20);
_vm->resetSkipFlag();
}
void GUI_EoB_SegaCD::drawMenuButton(Button *b, bool clicked, bool highlight, bool noFill) {
if (!b)
return;
const MenuButtonTiles &t = _menuButtonTiles[b->index - 1];
if (!t.nameTbl)
return;
_screen->sega_getRenderer()->loadToVRAM(&_campMenu[(0x1CE + t.srcOffs + (clicked ? 1 : 0) * ((b->width * b->height) >> 6)) << 5], (b->width * b->height) >> 1, t.nameTbl << 5);
_screen->sega_getRenderer()->fillRectWithTiles(0, b->x >> 3, b->y >> 3, b->width >> 3, b->height >> 3, 0x4000 + t.nameTbl, true);
_screen->sega_getRenderer()->render(0, b->x >> 3, b->y >> 3, b->width >> 3, b->height >> 3);
}
void GUI_EoB_SegaCD::drawSaveSlotButton(int slot, int redrawBox, bool highlight) {
if (slot < 0)
return;
if (slot == 5) {
drawMenuButton(_saveLoadCancelButton, redrawBox == 2, false, false);
return;
}
_screen->sega_getRenderer()->fillRectWithTiles(0, (_saveSlotX >> 3) + (_saveSlotX ? 1 : 2), (_saveSlotY >> 3) + (_saveSlotY ? 6 : 7) + (slot << 1), 3, 2, 0x41E7 + slot * 12 + (redrawBox == 2 ? 6 : 0), true);
_screen->sega_clearTextBuffer(0);
Common::String s1;
Common::String s2(slot < 5 ? _saveSlotStringsTemp[slot] : _vm->_saveLoadStrings[0]);
if (_vm->gameFlags().lang == Common::JA_JPN) {
if (s2.contains('\r')) {
// Savegame generated from ingame menu. The first part of the auto-generated save description (character name)
// is not a 2-byte encoding, but rather a special 1-byte encoding. We cut that part off and print it separately,
// since we have to notify the glyph renderer of the special encoding.
uint len = s2.findFirstOf('\r');
s1 = s2.substr(0, len);
s2.erase(0, len);
while (len--)
s2.insertChar(' ', 0);
} else {
// Savegame generated via the GMM save dialog. The Japanese font only has upper case ASCII glyphs, so we have to uppercase the string.
s2.toUppercase();
}
}
_vm->_txt->printShadedText(s2.c_str(), 0, (slot << 4) + (slot < 5 ? 0 : 2), highlight ? 0x55 : 0xFF, 0xCC, 121, 80, 0, false);
if (!s1.empty()) {
int cs = _screen->setFontStyles(_screen->_currentFont, Font::kStyleForceOneByte);
_vm->_txt->printShadedText(s1.c_str(), 0, (slot << 4) + (slot < 5 ? 0 : 2), highlight ? 0x55 : 0xFF, 0xCC, 121, 80, 0, false);
_screen->setFontStyles(_screen->_currentFont, cs);
}
_screen->sega_loadTextBufferToVRAM(0, 0x5560, 4800);
_screen->sega_getRenderer()->render(0, (_saveSlotX >> 3) + (_saveSlotX ? 1 : 2), (_saveSlotY >> 3) + (_saveSlotY ? 6 : 7) + (slot << 1), 21, 2);
}
int GUI_EoB_SegaCD::getHighlightSlot() {
int res = -1;
Common::Point p = _vm->getMousePos();
for (int i = 0; i < 5; i++) {
int y = _saveSlotY + i * 16 + (_saveSlotY ? 48 : 56);
if (_vm->posWithinRect(p.x, p.y, _saveSlotX + (_saveSlotX ? 8 : 16), y, _saveSlotX + 167, y + 15)) {
res = i;
break;
}
}
if (_vm->posWithinRect(p.x, p.y, _saveLoadCancelButton->x, _saveLoadCancelButton->y, _saveLoadCancelButton->x + _saveLoadCancelButton->width - 1, _saveLoadCancelButton->y + _saveLoadCancelButton->height - 1))
res = 5;
return res;
}
int GUI_EoB_SegaCD::mapPointToEntry(const Common::Point &p) const {
if (_vm->posWithinRect(p.x, p.y, 8, 80, 168, 152))
return (p.y - 80) / 8;
return -1;
}
void GUI_EoB_SegaCD::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int spellType, bool noFill, bool highLight) {
if (bookPageIndex < 0)
return;
if (spellId) {
memset(_vm->_tempPattern, 0, 924);
Common::String s = Common::String::format(_vm->_menuStringsMgc[0], spellType ? _vm->_clericSpellList[spellId] : _vm->_mageSpellList[spellId], _numAssignedSpellsOfType[spellId * 2 - 2]);
if (_vm->gameFlags().lang == Common::JA_JPN) {
for (int i = 0; i < 19; ++i) {
if ((int8)s[i] == -34 || (int8)s[i] == -33)
s.insertChar(' ', 18);
}
}
_vm->printSpellbookString(_vm->_tempPattern, s.c_str(), highLight ? 0x6223 : 0x63C9);
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 10 + bookPageIndex, 20, 1, 0, true, true, _vm->_tempPattern);
} else {
_screen->sega_getRenderer()->fillRectWithTiles(0, 1, 10 + bookPageIndex, 20, 1, 0);
}
_screen->sega_getRenderer()->render(0, 1, 10 + bookPageIndex, 20, 1);
}
void GUI_EoB_SegaCD::updateOptionsStrings() {
uint16 ntblInputMode[3] = { 0x34C, 0x360, 0x30C };
int speed = _vm->_configMouse ? _vm->_mouseSpeed : _vm->_padSpeed;
SegaRenderer *r = _screen->sega_getRenderer();
r->loadToVRAM(&_campMenu[(0x1CE + (_vm->_configMouse ? 0x240 : 0x24C)) << 5], 0x180, 0x42E0);
r->loadToVRAM(&_campMenu[(0x1CE + (_vm->_configMusic ? 0x258 : 0x264)) << 5], 0x180, 0x4460);
r->loadToVRAM(&_campMenu[(0x1CE + (_vm->_configSounds ? 0x258 : 0x264)) << 5], 0x180, 0x45E0);
r->loadToVRAM(&_campMenu[(0x1CE + ntblInputMode[_vm->_inputMode]) << 5], 0x280, 0x49A0);
r->loadToVRAM(&_campMenu[(0x444 + speed * 12) << 5], 0xC0, 0x48E0);
r->fillRectWithTiles(0, 15, 5, 3, 2, 0x4247, true);
r->fillRectWithTiles(0, 8, 5, 6, 2, 0x4217, true);
r->fillRectWithTiles(0, 8, 8, 6, 2, 0x4223, true);
r->fillRectWithTiles(0, 8, 11, 6, 2, 0x422F, true);
r->fillRectWithTiles(0, 8, 14, 10, 2, 0x424D, true);
}
void GUI_EoB_SegaCD::restParty_updateRestTime(int hours, bool init) {
SegaRenderer *r = _screen->sega_getRenderer();
if (init)
r->fillRectWithTiles(0, 1, 4, 20, 17, 0);
_screen->sega_clearTextBuffer(0);
int cs = _screen->setFontStyles(_screen->_currentFont, Font::kStyleFullWidth);
_vm->_txt->printShadedText(getMenuString(42), 0, 0, 0xFF, 0xCC, 160, 48, 0, false);
_vm->_txt->printShadedText(_vm->_menuStringsRest2[3], 0, 16, 0xFF, 0xCC, 160, 48, 0, false);
_vm->_txt->printShadedText(Common::String::format("%3d", hours).c_str(), _vm->gameFlags().lang == Common::JA_JPN ? 60 : 117, 16, 0xFF, 0xCC, 160, 48, 0, false);
_screen->setFontStyles(_screen->_currentFont, cs);
_screen->sega_loadTextBufferToVRAM(0, 0x5060, 5120);
r->fillRectWithTiles(0, 1, 4, 20, 2, 0x6000);
r->fillRectWithTiles(0, 1, 6, 20, 6, 0x6283, true);
r->render(0, 0, 0, 22, 17);
_screen->updateScreen();
_vm->delay(160);
}
uint16 GUI_EoB_SegaCD::checkClickableCharactersSelection() {
Common::Point mousePos = _vm->getMousePos();
int highlight = -1;
for (int i = 0; i < 60; ++i) {
int x = (i % 12) * 12 + 152;
int y = (i / 12) * 12 + 96;
if (!_vm->posWithinRect(mousePos.x, mousePos.y, x, y, x + 11, y + 7))
continue;
highlight = i;
break;
}
if (highlight == -1) {
for (int i = 0; i < 3; ++i) {
int x = 200 + i * 36;
if (!_vm->posWithinRect(mousePos.x, mousePos.y, x, 164, x + _screen->getTextWidth(_vm->_textInputSelectStrings[i ? i + 2 : _clickableCharactersPage]) - 1, 171))
continue;
highlight = 200 + i;
break;
}
}
if (highlight != _menuCur) {
printClickableCharacters(_clickableCharactersPage);
if (highlight != -1)
printClickableCharacter(highlight, 0x55);
_screen->sega_getRenderer()->render(0, 18, 10, 20, 14);
_menuCur = highlight;
}
_csjis[0] = _csjis[1] = _csjis[2] = 0;
int in = 0;
for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); ++evt) {
if (evt->event.type == Common::EVENT_LBUTTONDOWN)
in = 1;
}
if (in && highlight != -1) {
_menuCur = -1;
switch (highlight) {
case 200:
printClickableCharacters((_clickableCharactersPage + 1) % _clickableCharactersNumPages);
break;
case 201:
_keyPressed.keycode = Common::KEYCODE_BACKSPACE;
break;
case 202:
_keyPressed.keycode = Common::KEYCODE_RETURN;
break;
default:
_csjis[0] = fetchClickableCharacter(highlight);
_csjis[1] = '\x1';
return 0x89;
}
}
return in;
}
void GUI_EoB_SegaCD::printClickableCharacters(int page) {
if (_clickableCharactersPage != page) {
_clickableCharactersPage = page;
assert(_vm->_wndBackgrnd);
_screen->sega_loadTextBackground(_vm->_wndBackgrnd, 10240);
}
for (int i = 0; i < 60; ++i)
printClickableCharacter(i, 0xFF);
for (int i = 200; i < 203; ++i)
printClickableCharacter(i, 0xFF);
_screen->sega_getRenderer()->render(0, 18, 10, 20, 14);
}
void GUI_EoB_SegaCD::printClickableCharacter(int id, int col) {
char ch[3] = "\0\0";
if (id < 60) {
ch[0] = fetchClickableCharacter(id);
_vm->_txt->printShadedText(ch, (id % 12) * 12 + 12, (id / 12) * 12 + 32, col);
} else if (id >= 200) {
id -= 200;
_vm->_txt->printShadedText(_vm->_textInputSelectStrings[id ? id + 2 : _clickableCharactersPage], 60 + id * 36, 100, col);
}
}
char GUI_EoB_SegaCD::fetchClickableCharacter(int id) const {
if (id >= 200)
return (char)id;
if (id >= 60)
return 0;
uint8 c = (uint8)_vm->_textInputCharacterLines[_clickableCharactersPage][id];
if (_clickableCharactersPage == 1) {
if (c > 159 && c < 192)
c -= 32;
else if (c > 191 && c < 224)
c += 32;
}
return (char)c;
}
const GUI_EoB_SegaCD::MenuButtonTiles GUI_EoB_SegaCD::_menuButtonTiles[40] = {
{ 0x01e7, 0x0000 }, { 0x01fb, 0x0028 }, { 0x020f, 0x0050 }, { 0x0223, 0x0078 },
{ 0x0237, 0x00a0 }, { 0x0000, 0x0000 }, { 0x01cf, 0x01c8 }, { 0x025f, 0x0118 },
{ 0x024b, 0x00c8 }, { 0x0273, 0x0140 }, { 0x020b, 0x0198 }, { 0x01cf, 0x01c8 },
{ 0x01f3, 0x01e0 }, { 0x01ff, 0x01f8 }, { 0x0000, 0x0000 }, { 0x01e7, 0x0210 },
{ 0x0000, 0x0000 }, { 0x01CF, 0x0168 }, { 0x01db, 0x0180 }, { 0x01cf, 0x01c8 },
{ 0x0000, 0x0000 }, { 0x0000, 0x0000 }, { 0x0000, 0x0000 }, { 0x0000, 0x0000 },
{ 0x0000, 0x0000 }, { 0x0000, 0x0000 }, { 0x01db, 0x01b0 }, { 0x01cf, 0x01c8 },
{ 0x0000, 0x0000 }, { 0x01e7, 0x0270 }, { 0x01f3, 0x027C }, { 0x01ff, 0x0288 },
{ 0x020b, 0x0294 }, { 0x0217, 0x02A0 }, { 0x024d, 0x030c }, { 0x0000, 0x0000 },
{ 0x0000, 0x0000 }, { 0x0000, 0x0000 }, { 0x01CF, 0x01C8 }, { 0x0000, 0x0000 }
};
} // End of namespace Kyra
#endif // ENABLE_EOB