aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorathrxx2016-01-09 22:00:51 +0100
committerathrxx2018-11-14 17:22:22 +0100
commitf49eaa5654b2ee2e41b1794a4576d24967e2f7d7 (patch)
tree9366d630ba3fc4d5f7579bc2602075e6dfe35c6b /engines
parent61bd730bcf4ee311e79ab2fc49e3eca21018cdfe (diff)
downloadscummvm-rg350-f49eaa5654b2ee2e41b1794a4576d24967e2f7d7.tar.gz
scummvm-rg350-f49eaa5654b2ee2e41b1794a4576d24967e2f7d7.tar.bz2
scummvm-rg350-f49eaa5654b2ee2e41b1794a4576d24967e2f7d7.zip
KYRA: (EOB) - add support for FM-Towns version of EOB II
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/chargen.cpp65
-rw-r--r--engines/kyra/darkmoon.cpp49
-rw-r--r--engines/kyra/darkmoon.h24
-rw-r--r--engines/kyra/detection.cpp6
-rw-r--r--engines/kyra/detection_tables.h18
-rw-r--r--engines/kyra/eobcommon.cpp384
-rw-r--r--engines/kyra/eobcommon.h19
-rw-r--r--engines/kyra/gui_eob.cpp353
-rw-r--r--engines/kyra/gui_eob.h7
-rw-r--r--engines/kyra/items_eob.cpp2
-rw-r--r--engines/kyra/kyra_rpg.cpp18
-rw-r--r--engines/kyra/kyra_rpg.h3
-rw-r--r--engines/kyra/kyra_v1.cpp44
-rw-r--r--engines/kyra/magic_eob.cpp8
-rw-r--r--engines/kyra/module.mk1
-rw-r--r--engines/kyra/resource.h256
-rw-r--r--engines/kyra/saveload.cpp2
-rw-r--r--engines/kyra/saveload_eob.cpp83
-rw-r--r--engines/kyra/scene_eob.cpp28
-rw-r--r--engines/kyra/scene_lol.cpp2
-rw-r--r--engines/kyra/scene_rpg.cpp141
-rw-r--r--engines/kyra/screen.cpp54
-rw-r--r--engines/kyra/screen.h26
-rw-r--r--engines/kyra/screen_eob.cpp215
-rw-r--r--engines/kyra/screen_eob.h48
-rw-r--r--engines/kyra/script_eob.cpp3
-rw-r--r--engines/kyra/sequences_darkmoon.cpp323
-rw-r--r--engines/kyra/sound.h7
-rw-r--r--engines/kyra/sound_intern.h53
-rw-r--r--engines/kyra/sound_towns_darkmoon.cpp276
-rw-r--r--engines/kyra/sprites_eob.cpp46
-rw-r--r--engines/kyra/staticres.cpp2
-rw-r--r--engines/kyra/staticres_eob.cpp144
-rw-r--r--engines/kyra/staticres_rpg.cpp2
-rw-r--r--engines/kyra/text_rpg.cpp34
35 files changed, 2127 insertions, 619 deletions
diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp
index 2454909440..4724770782 100644
--- a/engines/kyra/chargen.cpp
+++ b/engines/kyra/chargen.cpp
@@ -66,7 +66,7 @@ private:
int getNextFreeFaceShape(int shpIndex, int charSex, int step, int8 *selectedPortraits);
void processFaceMenuSelection(int index);
void printStats(int index, int mode);
- void processNameInput(int index, int len, int textColor);
+ void processNameInput(int index, int textColor);
int rollDice();
int modifyStat(int index, int8 *stat1, int8 *stat2);
int getMaxHp(int cclass, int constitution, int level1, int level2, int level3);
@@ -99,7 +99,10 @@ private:
const uint8 *_chargenRaceMinStats;
const uint16 *_chargenRaceMaxStats;
- static const EoBChargenButtonDef _chargenButtonDefs[];
+ const EoBChargenButtonDef *_chargenButtonDefs;
+
+ static const EoBChargenButtonDef _chargenButtonDefsDOS[];
+ static const uint16 _chargenButtonKeyCodesFMTOWNS[];
static const CreatePartyModButton _chargenModButtons[];
static const EoBRect8 _chargenButtonBodyCoords[];
static const int16 _chargenBoxX[];
@@ -141,6 +144,19 @@ CharacterGenerator::CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen) :
_chargenClassMinStats = _vm->staticres()->loadRawData(kEoBBaseChargenClassMinStats, temp);
_chargenRaceMinStats = _vm->staticres()->loadRawData(kEoBBaseChargenRaceMinStats, temp);
_chargenRaceMaxStats = _vm->staticres()->loadRawDataBe16(kEoBBaseChargenRaceMaxStats, temp);
+
+ EoBChargenButtonDef *chargenButtonDefs = new EoBChargenButtonDef[41];
+ memcpy(chargenButtonDefs, _chargenButtonDefsDOS, 41 * sizeof(EoBChargenButtonDef));
+
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ const uint16 *c = _chargenButtonKeyCodesFMTOWNS;
+ for (int i = 0; i < 41; ++i) {
+ if (chargenButtonDefs[i].keyCode)
+ chargenButtonDefs[i].keyCode = *c++;
+ }
+ }
+
+ _chargenButtonDefs = chargenButtonDefs;
}
CharacterGenerator::~CharacterGenerator() {
@@ -152,6 +168,10 @@ CharacterGenerator::~CharacterGenerator() {
for (int i = 0; i < 17; i++)
delete[] _chargenButtonLabels[i];
+
+ delete[] _chargenButtonDefs;
+
+ _screen->clearPage(2);
}
bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
@@ -241,6 +261,10 @@ bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
}
void CharacterGenerator::init() {
+ /*_screen->loadEoBBitmap("MENU", 0, 3, 3, 2);
+ Common::SeekableReadStream *s = _res->createReadStream("facedat.dmp");
+ _screen->loadFileDataToPage(s, 2, 64000);*/
+
_screen->loadShapeSetBitmap("CHARGENA", 3, 3);
if (_faceShapes) {
for (int i = 0; i < 44; i++)
@@ -269,9 +293,11 @@ void CharacterGenerator::init() {
const CreatePartyModButton *c = &_chargenModButtons[i];
_chargenButtonLabels[i] = c->labelW ? _screen->encodeShape(c->encodeLabelX, c->encodeLabelY, c->labelW, c->labelH, true, _vm->_cgaMappingDefault) : 0;
}
-
+
_screen->convertPage(3, 2, _vm->_cgaMappingDefault);
_screen->_curPage = 0;
+ _screen->convertToHiColor(2);
+ _screen->shadeRect(142, 63, 306, 193, 4);
_screen->copyRegion(144, 64, 0, 0, 180, 128, 0, 2, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
}
@@ -323,7 +349,8 @@ void CharacterGenerator::initButton(int index, int x, int y, int w, int h, int k
void CharacterGenerator::checkForCompleteParty() {
_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
int cp = _screen->setCurPage(2);
- _screen->printShadedText(_chargenStrings1[8], 168, 16, 15, 0);
+ int x = (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168;
+ _screen->printShadedText(_chargenStrings1[8], x, 16, 15, 0);
_screen->setCurPage(cp);
_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
@@ -335,7 +362,7 @@ void CharacterGenerator::checkForCompleteParty() {
if (numChars == 4) {
_screen->setCurPage(2);
- _screen->printShadedText(_chargenStrings1[0], 168, 61, 15, 0);
+ _screen->printShadedText(_chargenStrings1[0], x, 61, 15, 0);
_screen->setCurPage(0);
_screen->copyRegion(168, 61, 152, 125, 136, 40, 2, 0, Screen::CR_NO_P_CHECK);
toggleSpecialButton(15, 0, 0);
@@ -416,7 +443,7 @@ int CharacterGenerator::viewDeleteCharacter() {
if (_characters[_activeBox].name[0]) {
processSpecialButton(16);
_characters[_activeBox].name[0] = 0;
- processNameInput(_activeBox, 1, 12);
+ processNameInput(_activeBox, 12);
processFaceMenuSelection(_activeBox + 50);
}
} else {
@@ -478,8 +505,10 @@ void CharacterGenerator::createPartyMember() {
processFaceMenuSelection(_chargenMinStats[6]);
printStats(_activeBox, 0);
_screen->printShadedText(_chargenStrings2[11], 149, 100, 9, 0);
- if (!_vm->shouldQuit())
- processNameInput(_activeBox, _vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, 15, 0, 8), 2);
+ if (!_vm->shouldQuit()) {
+ _vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, 15, 0, 8);
+ processNameInput(_activeBox, 2);
+ }
}
}
}
@@ -887,7 +916,7 @@ void CharacterGenerator::printStats(int index, int mode) {
if (mode != 4)
_screen->drawShape(2, c->faceShape, 224, 2, 0);
- _screen->printShadedText(c->name, 160 + ((20 - strlen(c->name)) << 2), 35, 15, 0);
+ _screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, 15, 0);
_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, 15, 0);
_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, 15, 0);
@@ -937,14 +966,10 @@ void CharacterGenerator::printStats(int index, int mode) {
_screen->_curPage = 0;
}
-void CharacterGenerator::processNameInput(int index, int len, int textColor) {
+void CharacterGenerator::processNameInput(int index, int textColor) {
Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
-
- // WORKAROUND for bug in original code:
- len = strlen(_characters[index].name);
-
- int xOffs = (60 - _screen->getFontWidth() * len) >> 1;
- _screen->printText(_chargenStrings1[1], _chargenNameFieldX[index], _chargenNameFieldY[index], 12, 12);
+ _screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, 12);
+ int xOffs = (60 - _screen->getTextWidth(_characters[index].name)) >> 1;
_screen->printText(_characters[index].name, _chargenNameFieldX[index] + xOffs, _chargenNameFieldY[index], textColor, 0);
_screen->updateScreen();
_screen->setFont(of);
@@ -1140,7 +1165,7 @@ int CharacterGenerator::getMinHp(int cclass, int constitution, int level1, int l
void CharacterGenerator::finish() {
_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
int cp = _screen->setCurPage(2);
- _screen->printShadedText(_chargenEnterGameStrings[0], 168, 32, 15, 0);
+ _screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, 15, 0);
_screen->setCurPage(cp);
_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
@@ -1341,7 +1366,7 @@ void CharacterGenerator::finish() {
}
}
-const EoBChargenButtonDef CharacterGenerator::_chargenButtonDefs[] = {
+const EoBChargenButtonDef CharacterGenerator::_chargenButtonDefsDOS[] = {
{ 0x01, 0x37, 0x31, 0x32, 0x70 },
{ 0x09, 0x37, 0x31, 0x32, 0x71 },
{ 0x01, 0x77, 0x31, 0x32, 0x72 },
@@ -1385,6 +1410,10 @@ const EoBChargenButtonDef CharacterGenerator::_chargenButtonDefs[] = {
{ 0x21, 0xAC, 0x25, 0x10, 0x19 }
};
+const uint16 CharacterGenerator::_chargenButtonKeyCodesFMTOWNS[] = {
+ 93, 94, 95, 96, 80, 79, 68, 66, 82, 77, 70, 75, 43, 45, 79
+};
+
const CreatePartyModButton CharacterGenerator::_chargenModButtons[] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x40 },
diff --git a/engines/kyra/darkmoon.cpp b/engines/kyra/darkmoon.cpp
index e15a290f86..12508546a0 100644
--- a/engines/kyra/darkmoon.cpp
+++ b/engines/kyra/darkmoon.cpp
@@ -29,23 +29,17 @@
namespace Kyra {
DarkMoonEngine::DarkMoonEngine(OSystem *system, const GameFlags &flags) : EoBCoreEngine(system, flags) {
- _animIntro = _animFinale = 0;
- _shapesIntro = _shapesFinale = 0;
_dscDoorType5Offs = 0;
_numSpells = 70;
_menuChoiceInit = 4;
- _introStrings = _cpsFilesIntro = _cpsFilesFinale = _finaleStrings = _kheldranStrings = _npcStrings[0] = _npcStrings[1] = _hornStrings = 0;
- _shapesIntro = _shapesFinale = 0;
- _creditsData = _npcShpData = _dscDoorType5Offs = _hornSounds = 0;
+ _kheldranStrings = _npcStrings[0] = _npcStrings[1] = _hornStrings = 0;
+ _utilMenuStrings = _ascii2SjisTables = _ascii2SjisTables2 = 0;
+ _npcShpData = _dscDoorType5Offs = _hornSounds = 0;
_dreamSteps = 0;
}
DarkMoonEngine::~DarkMoonEngine() {
- delete[] _animIntro;
- delete[] _animFinale;
- delete[] _shapesIntro;
- delete[] _shapesFinale;
}
Common::Error DarkMoonEngine::init() {
@@ -63,9 +57,15 @@ Common::Error DarkMoonEngine::init() {
_screen->setScreenPalette(pal);
}
- _screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
+ _screen->loadPalette(_flags.platform == Common::kPlatformFMTowns ? "MENU.PAL" : "PALETTE.COL", _screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
+ // adjust menu settings for EOB II FM-Towns
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ _screen->modifyScreenDim(6, 10, 100, 21, 40);
+ _screen->modifyScreenDim(27, 0, 0, 21, 2);
+ }
+
return Common::kNoError;
}
@@ -193,29 +193,32 @@ void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterInde
_screen->setCurPage(cp);
}
-void DarkMoonEngine::loadMonsterDecoration(const char *file, int16 monsterIndex) {
- Common::SeekableReadStream *s = _res->createReadStream(Common::String::format("%s.dcr", file));
- if (!s)
- return;
-
- int len = s->readUint16LE();
+void DarkMoonEngine::loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex) {
+ int len = stream->readUint16LE();
+ Common::List<SpriteDecoration*> activeDecorations;
for (int i = 0; i < len; i++) {
for (int ii = 0; ii < 6; ii++) {
uint8 dc[6];
- s->read(dc, 6);
+ stream->read(dc, 6);
if (!dc[2] || !dc[3])
continue;
SpriteDecoration *m = &_monsterDecorations[i * 6 + ii + monsterIndex];
-
- m->shp = _screen->encodeShape(dc[0], dc[1], dc[2], dc[3]);
+ if (_flags.platform != Common::kPlatformFMTowns)
+ m->shp = _screen->encodeShape(dc[0], dc[1], dc[2], dc[3]);
m->x = (int8)dc[4];
m->y = (int8)dc[5];
+ activeDecorations.push_back(m);
}
}
- delete s;
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ while (!activeDecorations.empty()) {
+ activeDecorations.front()->shp = loadTownsShape(stream);
+ activeDecorations.pop_front();
+ }
+ }
}
void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
@@ -382,6 +385,10 @@ void DarkMoonEngine::restParty_npc() {
gui_drawAllCharPortraitsWithStats();
_screen->setClearScreenDim(10);
+ _screen->set16bitShadingLevel(4);
+ gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1);
+ gui_drawBox((_screen->_curDim->sx << 3) + 1, _screen->_curDim->sy + 1, (_screen->_curDim->w << 3) - 2, _screen->_curDim->h - 2, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
_gui->messageDialogue2(11, 63, 6);
_gui->messageDialogue2(11, 64, 6);
}
@@ -478,7 +485,7 @@ void DarkMoonEngine::characterLevelGain(int charIndex) {
}
const KyraRpgGUISettings *DarkMoonEngine::guiSettings() {
- return &_guiSettings;
+ return (_flags.platform == Common::kPlatformFMTowns) ? &_guiSettingsFMTowns : &_guiSettingsDOS;
}
} // End of namespace Kyra
diff --git a/engines/kyra/darkmoon.h b/engines/kyra/darkmoon.h
index f23787d865..f7065da8d6 100644
--- a/engines/kyra/darkmoon.h
+++ b/engines/kyra/darkmoon.h
@@ -60,6 +60,7 @@ private:
// Main Menu
int mainMenu();
int mainMenuLoop();
+ void townsUtilitiesMenu();
int _menuChoiceInit;
@@ -72,22 +73,6 @@ private:
void seq_playFinale();
void seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *data, int sd, int backupPage, int tempPage, int speed);
- const char *const *_introStrings;
- const char *const *_cpsFilesIntro;
- const DarkMoonAnimCommand **_animIntro;
- const DarkMoonShapeDef **_shapesIntro;
-
- const char *const *_finaleStrings;
- const uint8 *_creditsData;
- const char *const *_cpsFilesFinale;
- const DarkMoonAnimCommand **_animFinale;
- const DarkMoonShapeDef **_shapesFinale;
-
- static const char *const _palFilesIntroVGA[];
- static const char *const _palFilesIntroEGA[];
- static const char *const _palFilesFinaleVGA[];
- static const char *const _palFilesFinaleEGA[];
-
// Ingame sequence
void seq_nightmare();
void seq_kheldran();
@@ -108,7 +93,7 @@ private:
// Monsters
void generateMonsterPalettes(const char *file, int16 monsterIndex);
- void loadMonsterDecoration(const char *file, int16 monsterIndex);
+ void loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex);
void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
bool killMonsterExtra(EoBMonsterInPlay *m);
@@ -140,7 +125,10 @@ private:
const char *const *_hornStrings;
const uint8 *_hornSounds;
- static const KyraRpgGUISettings _guiSettings;
+ const char *const *_utilMenuStrings;
+
+ static const KyraRpgGUISettings _guiSettingsDOS;
+ static const KyraRpgGUISettings _guiSettingsFMTowns;
static const uint8 _egaDefaultPalette[];
};
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 79e1d9f494..9f1b694006 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -206,6 +206,10 @@ bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
flags.lang = Common::EN_ANY;
}
+#ifndef USE_RGB_COLOR
+ flags.useHiColorMode = false;
+#endif
+
switch (flags.gameID) {
case Kyra::GI_KYRA1:
*engine = new Kyra::KyraEngine_LoK(syst, flags);
@@ -228,6 +232,8 @@ bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
case Kyra::GI_EOB2:
if (Common::parseRenderMode(ConfMan.get("render_mode")) == Common::kRenderEGA)
flags.useHiRes = true;
+ if (platform == Common::kPlatformFMTowns && !flags.useHiColorMode)
+ error("EOB ĢI FM-TOWNS requires support of 16bit color modes which has not been activated in your ScummVM build (The 'USE_RGB_COLOR' define has not been set).");
*engine = new Kyra::DarkMoonEngine(syst, flags);
break;
#endif // ENABLE_EOB
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index 0b45977d22..81dd56f798 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -22,7 +22,6 @@
namespace {
-#define EOB2_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_EOB2)
#define FLAGS(x, y, z, a, b, c, d, e, f, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, f, id }
#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, e, f, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, f, id }
@@ -62,6 +61,7 @@ namespace {
#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_EOB1)
#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_EOB2)
+#define EOB2_FMTOWNS_FLAGS FLAGS(false, false, false, false, true, false, true, false, false, Kyra::GI_EOB2)
#define GAMEOPTION_KYRA3_AUDIENCE GUIO_GAMEOPTIONS1
#define GAMEOPTION_KYRA3_SKIP GUIO_GAMEOPTIONS2
@@ -1684,6 +1684,22 @@ const KYRAGameDescription adGameDescs[] = {
},
EOB2_FLAGS
},
+
+ {
+ {
+ "eob2",
+ 0,
+ {
+ { "AZURE.SDT", 0, "2915098f2d1bdcfa518f857a26bb3324", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::JA_JPN,
+ Common::kPlatformFMTowns,
+ ADGF_NO_FLAGS,
+ GUIO4(GUIO_NOSPEECH, GUIO_MIDITOWNS, GUIO_RENDERFMTOWNS, GAMEOPTION_EOB_HPGRAPHS)
+ },
+ EOB2_FMTOWNS_FLAGS
+ },
#endif // ENABLE_EOB
{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }
diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp
index 4f5dfcdd47..11bdafabb3 100644
--- a/engines/kyra/eobcommon.cpp
+++ b/engines/kyra/eobcommon.cpp
@@ -24,7 +24,7 @@
#include "kyra/kyra_rpg.h"
#include "kyra/resource.h"
-#include "engines/kyra/sound.h"
+#include "engines/kyra/sound_intern.h"
#include "engines/kyra/sound_adlib.h"
#include "kyra/script_eob.h"
#include "kyra/timer.h"
@@ -52,7 +52,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
_playFinale = false;
_runFlag = true;
- _configMouse = true;
+ _configMouse = _config2431 = true;
_loading = false;
_enableHiResDithering = false;
@@ -195,7 +195,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
_abortStrings = _saveLoadStrings = _mnWord = _mnPrompt = _bookNumbers = 0;
_mageSpellList = _clericSpellList = _spellNames = _magicStrings1 = 0;
_magicStrings2 = _magicStrings3 = _magicStrings4 = _magicStrings6 = 0;
- _magicStrings7 = _magicStrings8 = 0;
+ _magicStrings7 = _magicStrings8 = _saveNamePatterns = 0;
_spellAnimBuffer = 0;
_sparkEffectDefSteps = _sparkEffectDefSubSteps = _sparkEffectDefShift = 0;
_sparkEffectDefAdd = _sparkEffectDefX = _sparkEffectDefY = _sparkEffectOfShift = 0;
@@ -211,7 +211,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
_menuStringsScribe = _menuStringsDrop2 = _menuStringsHead = _menuStringsPoison = 0;
_menuStringsMgc = _menuStringsPrefs = _menuStringsRest2 = _menuStringsRest3 = 0;
_menuStringsRest4 = _menuStringsDefeat = _menuStringsTransfer = _menuStringsSpec = 0;
- _menuStringsSpellNo = _menuYesNoStrings = 0;
+ _menuStringsSpellNo = _menuYesNoStrings = _2431Strings = _katakanaLines = _katakanaSelectStrings = 0;
_errorSlotEmptyString = _errorSlotNoNameString = _menuOkString = 0;
_spellLevelsMage = _spellLevelsCleric = _numSpellsCleric = _numSpellsWisAdj = _numSpellsPal = _numSpellsMage = 0;
_mnNumWord = _numSpells = _mageSpellListSize = _spellLevelsMageSize = _spellLevelsClericSize = 0;
@@ -308,6 +308,7 @@ EoBCoreEngine::~EoBCoreEngine() {
delete[] _spells;
delete[] _spellAnimBuffer;
delete[] _wallsOfForce;
+ delete[] _buttonDefs;
delete _gui;
_gui = 0;
@@ -385,14 +386,6 @@ Common::Error EoBCoreEngine::init() {
assert(_screen);
_screen->setResolution();
- //MidiDriverType midiDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB);
- _sound = new SoundAdLibPC(this, _mixer);
- assert(_sound);
- _sound->init();
-
- // Setup volume settings (and read in all ConfigManager settings)
- syncSoundSettings();
-
_res = new Resource(this);
assert(_res);
_res->reset();
@@ -402,6 +395,22 @@ Common::Error EoBCoreEngine::init() {
if (!_staticres->init())
error("_staticres->init() failed");
+ // SoundTowns_Darkmoon requires initialized _staticres
+ if (_flags.platform == Common::kPlatformDOS) {
+ //MidiDriverType midiDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB);
+ _sound = new SoundAdLibPC(this, _mixer);
+ } else if (_flags.platform == Common::kPlatformFMTowns) {
+ _sound = new SoundTowns_Darkmoon(this, _mixer);
+ } else if (_flags.platform == Common::kPlatformPC98) {
+
+ }
+
+ assert(_sound);
+ _sound->init();
+
+ // Setup volume settings (and read in all ConfigManager settings)
+ syncSoundSettings();
+
if (!_screen->init())
error("screen()->init() failed");
@@ -453,13 +462,14 @@ Common::Error EoBCoreEngine::init() {
memset(&_wllShapeMap[3], -1, 5);
memset(&_wllShapeMap[13], -1, 5);
- _wllVcnOffset = 16;
-
- _greenFadingTable = new uint8[256];
- _blueFadingTable = new uint8[256];
- _lightBlueFadingTable = new uint8[256];
- _blackFadingTable = new uint8[256];
- _greyFadingTable = new uint8[256];
+ _wllVcnOffset = (_flags.platform == Common::kPlatformFMTowns) ? 0 : 16;
+ int bpp = (_flags.platform == Common::kPlatformFMTowns) ? 2 : 1;
+
+ _greenFadingTable = new uint8[256 * bpp];
+ _blueFadingTable = new uint8[256 * bpp];
+ _lightBlueFadingTable = new uint8[256 * bpp];
+ _blackFadingTable = new uint8[256 * bpp];
+ _greyFadingTable = new uint8[256 * bpp];
_monsters = new EoBMonsterInPlay[30];
memset(_monsters, 0, 30 * sizeof(EoBMonsterInPlay));
@@ -480,8 +490,9 @@ Common::Error EoBCoreEngine::init() {
_flyingObjectsPtr = _flyingObjects;
memset(_flyingObjects, 0, _numFlyingObjects * sizeof(EoBFlyingObject));
- _spellAnimBuffer = new uint8[4096];
- memset(_spellAnimBuffer, 0, 4096);
+ int bufferSize = _flags.useHiColorMode ? 8192 : 4096;
+ _spellAnimBuffer = new uint8[bufferSize];
+ memset(_spellAnimBuffer, 0, bufferSize);
_wallsOfForce = new WallOfForce[5];
memset(_wallsOfForce, 0, 5 * sizeof(WallOfForce));
@@ -518,11 +529,8 @@ Common::Error EoBCoreEngine::init() {
Common::Error EoBCoreEngine::go() {
_debugger->initialize();
-
_txt->removePageBreakFlag();
-
_screen->setFont(Screen::FID_8_FNT);
-
loadItemsAndDecorationsShapes();
_screen->setMouseCursor(0, 0, _itemIconShapes[0]);
@@ -540,6 +548,7 @@ Common::Error EoBCoreEngine::go() {
action = 0;
if (_gameToLoad != -1) {
+ _sound->selectAudioResourceSet(kMusicIngame);
if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
error("Couldn't load game slot %d on startup", _gameToLoad);
startupLoad();
@@ -549,6 +558,8 @@ Common::Error EoBCoreEngine::go() {
action = mainMenu();
}
+ _sound->selectAudioResourceSet(kMusicIngame);
+
if (action == -1) {
// load game
repeatLoop = _gui->runLoadMenu(72, 14);
@@ -573,6 +584,7 @@ Common::Error EoBCoreEngine::go() {
if (_playFinale) {
// make final save for party transfer
saveGameStateIntern(-1, 0, 0);
+ _sound->selectAudioResourceSet(kMusicFinale);
seq_playFinale();
}
}
@@ -601,7 +613,7 @@ void EoBCoreEngine::writeSettings() {
if (_sound) {
if (!_configSounds)
- _sound->beginFadeOut();
+ _sound->haltTrack();
_sound->enableMusic(_configSounds ? 1 : 0);
_sound->enableSFX(_configSounds);
}
@@ -683,167 +695,219 @@ bool EoBCoreEngine::checkPartyStatus(bool handleDeath) {
void EoBCoreEngine::loadItemsAndDecorationsShapes() {
releaseItemsAndDecorationsShapes();
-
- _screen->loadShapeSetBitmap("ITEML1", 5, 3);
- _largeItemShapes = new const uint8*[_numLargeItemShapes];
int div = (_flags.gameID == GI_EOB1) ? 3 : 8;
int mul = (_flags.gameID == GI_EOB1) ? 64 : 24;
+ int size = 0;
- for (int i = 0; i < _numLargeItemShapes; i++)
- _largeItemShapes[i] = _screen->encodeShape((i / div) << 3, (i % div) * mul, 8, 24, false, _cgaMappingItemsL);
+ _largeItemShapes = new const uint8*[_numLargeItemShapes];
+ if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+ for (int i = 0; i < _numLargeItemShapes; i++)
+ _largeItemShapes[i] = _staticres->loadRawData(kEoB2LargeItemsShapeData00 + i, size);
+ } else {
+ _screen->loadShapeSetBitmap("ITEML1", 5, 3);
+ for (int i = 0; i < _numLargeItemShapes; i++)
+ _largeItemShapes[i] = _screen->encodeShape((i / div) << 3, (i % div) * mul, 8, 24, false, _cgaMappingItemsL);
+ }
- _screen->loadShapeSetBitmap("ITEMS1", 5, 3);
_smallItemShapes = new const uint8*[_numSmallItemShapes];
- for (int i = 0; i < _numSmallItemShapes; i++)
- _smallItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingItemsS);
+ if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+ for (int i = 0; i < _numSmallItemShapes; i++)
+ _smallItemShapes[i] = _staticres->loadRawData(kEoB2SmallItemsShapeData00 + i, size);
+ } else {
+ _screen->loadShapeSetBitmap("ITEMS1", 5, 3);
+ for (int i = 0; i < _numSmallItemShapes; i++)
+ _smallItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingItemsS);
+ }
- _screen->loadShapeSetBitmap("THROWN", 5, 3);
_thrownItemShapes = new const uint8*[_numThrownItemShapes];
- for (int i = 0; i < _numThrownItemShapes; i++)
- _thrownItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingThrown);
-
_spellShapes = new const uint8*[4];
- for (int i = 0; i < 4; i++)
- _spellShapes[i] = _screen->encodeShape(8, i << 5, 6, 32, false, _cgaMappingThrown);
-
_firebeamShapes = new const uint8*[3];
- _firebeamShapes[0] = _screen->encodeShape(16, 0, 4, 24, false, _cgaMappingThrown);
- _firebeamShapes[1] = _screen->encodeShape(16, 24, 4, 24, false, _cgaMappingThrown);
- _firebeamShapes[2] = _screen->encodeShape(16, 48, 3, 24, false, _cgaMappingThrown);
- _redSplatShape = _screen->encodeShape(16, _flags.gameID == GI_EOB1 ? 144 : 72, 5, 24, false, _cgaMappingThrown);
- _greenSplatShape = _screen->encodeShape(16, _flags.gameID == GI_EOB1 ? 168 : 96, 5, 16, false, _cgaMappingThrown);
-
- _screen->loadShapeSetBitmap("ITEMICN", 5, 3);
- _itemIconShapes = new const uint8*[_numItemIconShapes];
- for (int i = 0; i < _numItemIconShapes; i++)
- _itemIconShapes[i] = _screen->encodeShape((i % 0x14) << 1, (i / 0x14) << 4, 2, 0x10, false, _cgaMappingIcons);
+ if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+ for (int i = 0; i < _numThrownItemShapes; i++)
+ _thrownItemShapes[i] = _staticres->loadRawData(kEoB2ThrownShapeData00 + i, size);
+ for (int i = 0; i < 4; i++)
+ _spellShapes[i] = _staticres->loadRawData(kEoB2SpellShapeData00 + i, size);
+ for (int i = 0; i < 3; i++)
+ _firebeamShapes[i] = _staticres->loadRawData(kEoB2FirebeamShapeData00 + i, size);
+ _redSplatShape = _staticres->loadRawData(kEoB2RedSplatShapeData, size);
+ _greenSplatShape = _staticres->loadRawData(kEoB2GreenSplatShapeData, size);
+ } else {
+ _screen->loadShapeSetBitmap("THROWN", 5, 3);
+ for (int i = 0; i < _numThrownItemShapes; i++)
+ _thrownItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingThrown);
+ for (int i = 0; i < 4; i++)
+ _spellShapes[i] = _screen->encodeShape(8, i << 5, 6, 32, false, _cgaMappingThrown);
- _screen->loadShapeSetBitmap("DECORATE", 5, 3);
+ _firebeamShapes[0] = _screen->encodeShape(16, 0, 4, 24, false, _cgaMappingThrown);
+ _firebeamShapes[1] = _screen->encodeShape(16, 24, 4, 24, false, _cgaMappingThrown);
+ _firebeamShapes[2] = _screen->encodeShape(16, 48, 3, 24, false, _cgaMappingThrown);
+ _redSplatShape = _screen->encodeShape(16, _flags.gameID == GI_EOB1 ? 144 : 72, 5, 24, false, _cgaMappingThrown);
+ _greenSplatShape = _screen->encodeShape(16, _flags.gameID == GI_EOB1 ? 168 : 96, 5, 16, false, _cgaMappingThrown);
+ }
- if (_flags.gameID == GI_EOB2) {
- _lightningColumnShape = _screen->encodeShape(18, 88, 4, 64);
- _wallOfForceShapes = new const uint8*[6];
- for (int i = 0; i < 6; i++)
- _wallOfForceShapes[i] = _screen->encodeShape(_wallOfForceShapeDefs[(i << 2)], _wallOfForceShapeDefs[(i << 2) + 1], _wallOfForceShapeDefs[(i << 2) + 2], _wallOfForceShapeDefs[(i << 2) + 3]);
+ _itemIconShapes = new const uint8*[_numItemIconShapes];
+ if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+ for (int i = 0; i < _numItemIconShapes; i++)
+ _itemIconShapes[i] = _staticres->loadRawData(kEoB2ItemIconShapeData00 + i, size);
+ } else {
+ _screen->loadShapeSetBitmap("ITEMICN", 5, 3);
+ for (int i = 0; i < _numItemIconShapes; i++)
+ _itemIconShapes[i] = _screen->encodeShape((i % 0x14) << 1, (i / 0x14) << 4, 2, 0x10, false, _cgaMappingIcons);
}
_teleporterShapes = new const uint8*[6];
- for (int i = 0; i < 6; i++)
- _teleporterShapes[i] = _screen->encodeShape(_teleporterShapeDefs[(i << 2)], _teleporterShapeDefs[(i << 2) + 1], _teleporterShapeDefs[(i << 2) + 2], _teleporterShapeDefs[(i << 2) + 3], false, _cgaMappingDefault);
_sparkShapes = new const uint8*[3];
- _sparkShapes[0] = _screen->encodeShape(29, 0, 2, 16, false, _cgaMappingDeco);
- _sparkShapes[1] = _screen->encodeShape(31, 0, 2, 16, false, _cgaMappingDeco);
- _sparkShapes[2] = _screen->encodeShape(33, 0, 2, 16, false, _cgaMappingDeco);
- _deadCharShape = _screen->encodeShape(0, 88, 4, 32, false, _cgaMappingDeco);
- _disabledCharGrid = _screen->encodeShape(4, 88, 4, 32, false, _cgaMappingDeco);
- _blackBoxSmallGrid = _screen->encodeShape(9, 88, 2, 8, false, _cgaMappingDeco);
- _weaponSlotGrid = _screen->encodeShape(8, 88, 4, 16, false, _cgaMappingDeco);
- _blackBoxWideGrid = _screen->encodeShape(8, 104, 4, 8, false, _cgaMappingDeco);
-
- static const uint8 dHeight[] = { 17, 10, 10 };
- static const uint8 dY[] = { 120, 137, 147 };
-
_compassShapes = new const uint8*[12];
- for (int y = 0; y < 3; y++) {
- for (int x = 0; x < 4; x++)
- _compassShapes[(y << 2) + x] = _screen->encodeShape(x * 3, dY[y], 3, dHeight[y], false, _cgaMappingDeco);
+ if (_flags.gameID == GI_EOB2)
+ _wallOfForceShapes = new const uint8*[6];
+
+ if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+ _lightningColumnShape = _staticres->loadRawData(kEoB2LightningColumnShapeData, size);
+ for (int i = 0; i < 6; i++)
+ _wallOfForceShapes[i] = _staticres->loadRawData(kEoB2WallOfForceShapeData00 + i, size);
+ for (int i = 0; i < 6; i++)
+ _teleporterShapes[i] = _staticres->loadRawData(kEoB2TeleporterShapeData00 + i, size);
+ for (int i = 0; i < 3; i++)
+ _sparkShapes[i] = _staticres->loadRawData(kEoB2SparkShapeData00 + i, size);
+ for (int i = 0; i < 12; i++)
+ _compassShapes[i] = _staticres->loadRawData(kEoB2CompassShapeData00 + i, size);
+
+ _deadCharShape = _staticres->loadRawData(kEoB2DeadCharShapeData, size);
+ _disabledCharGrid = _staticres->loadRawData(kEoB2DisabledCharGridShapeData, size);
+ _blackBoxSmallGrid = _staticres->loadRawData(kEoB2SmallGridShapeData, size);
+ _weaponSlotGrid = _staticres->loadRawData(kEoB2WeaponSlotGridShapeData, size);
+ _blackBoxWideGrid = _staticres->loadRawData(kEoB2WideGridShapeData, size);
+
+ } else {
+ _screen->loadShapeSetBitmap("DECORATE", 5, 3);
+ if (_flags.gameID == GI_EOB2) {
+ _lightningColumnShape = _screen->encodeShape(18, 88, 4, 64);
+ for (int i = 0; i < 6; i++)
+ _wallOfForceShapes[i] = _screen->encodeShape(_wallOfForceShapeDefs[(i << 2)], _wallOfForceShapeDefs[(i << 2) + 1], _wallOfForceShapeDefs[(i << 2) + 2], _wallOfForceShapeDefs[(i << 2) + 3]);
+ }
+
+ for (int i = 0; i < 6; i++)
+ _teleporterShapes[i] = _screen->encodeShape(_teleporterShapeDefs[(i << 2)], _teleporterShapeDefs[(i << 2) + 1], _teleporterShapeDefs[(i << 2) + 2], _teleporterShapeDefs[(i << 2) + 3], false, _cgaMappingDefault);
+
+ _sparkShapes[0] = _screen->encodeShape(29, 0, 2, 16, false, _cgaMappingDeco);
+ _sparkShapes[1] = _screen->encodeShape(31, 0, 2, 16, false, _cgaMappingDeco);
+ _sparkShapes[2] = _screen->encodeShape(33, 0, 2, 16, false, _cgaMappingDeco);
+ _deadCharShape = _screen->encodeShape(0, 88, 4, 32, false, _cgaMappingDeco);
+ _disabledCharGrid = _screen->encodeShape(4, 88, 4, 32, false, _cgaMappingDeco);
+ _blackBoxSmallGrid = _screen->encodeShape(9, 88, 2, 8, false, _cgaMappingDeco);
+ _weaponSlotGrid = _screen->encodeShape(8, 88, 4, 16, false, _cgaMappingDeco);
+ _blackBoxWideGrid = _screen->encodeShape(8, 104, 4, 8, false, _cgaMappingDeco);
+
+ static const uint8 dHeight[] = { 17, 10, 10 };
+ static const uint8 dY[] = { 120, 137, 147 };
+
+ for (int y = 0; y < 3; y++) {
+ for (int x = 0; x < 4; x++)
+ _compassShapes[(y << 2) + x] = _screen->encodeShape(x * 3, dY[y], 3, dHeight[y], false, _cgaMappingDeco);
+ }
}
}
void EoBCoreEngine::releaseItemsAndDecorationsShapes() {
- if (_largeItemShapes) {
- for (int i = 0; i < _numLargeItemShapes; i++) {
- if (_largeItemShapes[i])
- delete[] _largeItemShapes[i];
+ if (_flags.platform != Common::kPlatformFMTowns || _flags.gameID != GI_EOB2) {
+ if (_largeItemShapes) {
+ for (int i = 0; i < _numLargeItemShapes; i++) {
+ if (_largeItemShapes[i])
+ delete[] _largeItemShapes[i];
+ }
}
- delete[] _largeItemShapes;
- }
- if (_smallItemShapes) {
- for (int i = 0; i < _numSmallItemShapes; i++) {
- if (_smallItemShapes[i])
- delete[] _smallItemShapes[i];
+ if (_smallItemShapes) {
+ for (int i = 0; i < _numSmallItemShapes; i++) {
+ if (_smallItemShapes[i])
+ delete[] _smallItemShapes[i];
+ }
}
- delete[] _smallItemShapes;
- }
- if (_thrownItemShapes) {
- for (int i = 0; i < _numThrownItemShapes; i++) {
- if (_thrownItemShapes[i])
- delete[] _thrownItemShapes[i];
+ if (_thrownItemShapes) {
+ for (int i = 0; i < _numThrownItemShapes; i++) {
+ if (_thrownItemShapes[i])
+ delete[] _thrownItemShapes[i];
+ }
}
- delete[] _thrownItemShapes;
- }
- if (_spellShapes) {
- for (int i = 0; i < 4; i++) {
- if (_spellShapes[i])
- delete[] _spellShapes[i];
+ if (_spellShapes) {
+ for (int i = 0; i < 4; i++) {
+ if (_spellShapes[i])
+ delete[] _spellShapes[i];
+ }
}
- delete[] _spellShapes;
- }
- if (_itemIconShapes) {
- for (int i = 0; i < _numItemIconShapes; i++) {
- if (_itemIconShapes[i])
- delete[] _itemIconShapes[i];
+ if (_itemIconShapes) {
+ for (int i = 0; i < _numItemIconShapes; i++) {
+ if (_itemIconShapes[i])
+ delete[] _itemIconShapes[i];
+ }
}
- delete[] _itemIconShapes;
- }
- if (_sparkShapes) {
- for (int i = 0; i < 3; i++) {
- if (_sparkShapes[i])
- delete[] _sparkShapes[i];
+ if (_sparkShapes) {
+ for (int i = 0; i < 3; i++) {
+ if (_sparkShapes[i])
+ delete[] _sparkShapes[i];
+ }
}
- delete[] _sparkShapes;
- }
- if (_wallOfForceShapes) {
- for (int i = 0; i < 6; i++) {
- if (_wallOfForceShapes[i])
- delete[] _wallOfForceShapes[i];
+ if (_wallOfForceShapes) {
+ for (int i = 0; i < 6; i++) {
+ if (_wallOfForceShapes[i])
+ delete[] _wallOfForceShapes[i];
+ }
}
- delete[] _wallOfForceShapes;
- }
- if (_teleporterShapes) {
- for (int i = 0; i < 6; i++) {
- if (_teleporterShapes[i])
- delete[] _teleporterShapes[i];
+ if (_teleporterShapes) {
+ for (int i = 0; i < 6; i++) {
+ if (_teleporterShapes[i])
+ delete[] _teleporterShapes[i];
+ }
}
- delete[] _teleporterShapes;
- }
- if (_compassShapes) {
- for (int i = 0; i < 12; i++) {
- if (_compassShapes[i])
- delete[] _compassShapes[i];
+ if (_compassShapes) {
+ for (int i = 0; i < 12; i++) {
+ if (_compassShapes[i])
+ delete[] _compassShapes[i];
+ }
}
- delete[] _compassShapes;
- }
- if (_firebeamShapes) {
- for (int i = 0; i < 3; i++) {
- if (_firebeamShapes[i])
- delete[] _firebeamShapes[i];
+ if (_firebeamShapes) {
+ for (int i = 0; i < 3; i++) {
+ if (_firebeamShapes[i])
+ delete[] _firebeamShapes[i];
+ }
}
- delete[] _firebeamShapes;
+
+ delete[] _redSplatShape;
+ delete[] _greenSplatShape;
+ delete[] _deadCharShape;
+ delete[] _disabledCharGrid;
+ delete[] _blackBoxSmallGrid;
+ delete[] _weaponSlotGrid;
+ delete[] _blackBoxWideGrid;
+ delete[] _lightningColumnShape;
}
- delete[] _redSplatShape;
- delete[] _greenSplatShape;
- delete[] _deadCharShape;
- delete[] _disabledCharGrid;
- delete[] _blackBoxSmallGrid;
- delete[] _weaponSlotGrid;
- delete[] _blackBoxWideGrid;
- delete[] _lightningColumnShape;
+ delete[] _largeItemShapes;
+ delete[] _smallItemShapes;
+ delete[] _thrownItemShapes;
+ delete[] _spellShapes;
+ delete[] _itemIconShapes;
+ delete[] _sparkShapes;
+ delete[] _wallOfForceShapes;
+ delete[] _teleporterShapes;
+ delete[] _compassShapes;
+ delete[] _firebeamShapes;
}
void EoBCoreEngine::setHandItem(Item itemIndex) {
- if (itemIndex == -1)
+ if (itemIndex == -1) {
+ if (_flags.platform == Common::kPlatformFMTowns)
+ _screen->setMouseCursor(8, 8, _itemIconShapes[37], 0);
return;
+ }
if (_screen->curDimIndex() == 7 && itemIndex) {
printFullItemName(itemIndex);
@@ -860,6 +924,11 @@ void EoBCoreEngine::setHandItem(Item itemIndex) {
int mouseOffs = itemIndex ? 8 : 0;
_screen->setMouseCursor(mouseOffs, mouseOffs, shp, ovl);
+
+ if (_flags.useHiColorMode) {
+ _screen->setFadeTable(_greyFadingTable);
+ _screen->setShapeFadingLevel(0);
+ }
}
int EoBCoreEngine::getDexterityArmorClassModifier(int dexterity) {
@@ -1247,7 +1316,9 @@ int EoBCoreEngine::prepareForNewPartyMember(int16 itemType, int16 itemValue) {
deletePartyItems(itemType, itemValue);
} else {
gui_drawDialogueBox();
+ _screen->set16bitShadingLevel(4);
_txt->printDialogueText(_npcMaxStrings[0]);
+ _screen->set16bitShadingLevel(0);
int r = runDialogue(-1, 7, _characters[0].name, _characters[1].name, _characters[2].name, _characters[3].name,
_characters[4].name, _characters[5].name, _abortStrings[0]) - 1;
@@ -1376,6 +1447,8 @@ void EoBCoreEngine::setupDialogueButtons(int presetfirst, int numStr, va_list &a
_dialogueNumButtons = numStr;
_dialogueHighlightedButton = 0;
+ Screen::FontId of = _screen->setFont((_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns) ? Screen::FID_8_FNT : _screen->_currentFont);
+
for (int i = 0; i < numStr; i++) {
const char *s = va_arg(args, const char *);
if (s)
@@ -1396,6 +1469,8 @@ void EoBCoreEngine::setupDialogueButtons(int presetfirst, int numStr, va_list &a
drawDialogueButtons();
+ _screen->setFont(of);
+
if (!shouldQuit())
removeInputTop();
}
@@ -1448,6 +1523,7 @@ void EoBCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i
int page = ((flags & 2) || destRect) ? 0 : 6;
if (scumm_stricmp(_dialogueLastBitmap, file)) {
+ _screen->clearPage(2);
if (!destRect) {
if (!(flags & 1)) {
_screen->loadEoBBitmap("BORDER", 0, 3, 3, 2);
@@ -1622,7 +1698,9 @@ void EoBCoreEngine::displayParchment(int id) {
// display text
Common::SeekableReadStream *s = _res->createReadStream("TEXT.DAT");
_screen->loadFileDataToPage(s, 5, 32000);
+ _screen->set16bitShadingLevel(4);
gui_drawBox(0, 0, 176, 175, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
_txt->setupField(12, 1);
if (_flags.gameID == GI_EOB2)
id++;
@@ -1792,6 +1870,30 @@ bool EoBCoreEngine::checkPassword() {
return true;
}
+Common::String EoBCoreEngine::convertAsciiToSjis(Common::String str) {
+ if (_flags.platform != Common::kPlatformFMTowns)
+ return str;
+
+ Common::String n;
+ const char *src = str.c_str();
+ int pos = 0;
+ for (uint32 i = 0; i < str.size(); ++i) {
+ if (src[i] & 0x80) {
+ n.insertChar(src[i++], pos++);
+ n.insertChar(src[i], pos++);
+ } else if (src[i] >= 32 && src[i] <= 64) {
+ n.insertChar(_ascii2SjisTables[1][(src[i] - 32) * 2], pos++);
+ n.insertChar(_ascii2SjisTables[1][(src[i] - 32) * 2 + 1], pos++);
+ } else if ((src[i] >= 97 && src[i] <= 122) || (src[i] >= 65 && src[i] <= 90)) {
+ char c = (src[i] >= 97) ? src[i] - 97 : src[i] - 65;
+ n.insertChar(_ascii2SjisTables2[0][c * 2], pos++);
+ n.insertChar(_ascii2SjisTables2[0][c * 2 + 1], pos++);
+ }
+ }
+
+ return n;
+}
+
void EoBCoreEngine::useSlotWeapon(int charIndex, int slotIndex, Item item) {
EoBCharacter *c = &_characters[charIndex];
int tp = item ? _items[item].type : 0;
diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h
index 8d740f1f4d..e7b0f0d028 100644
--- a/engines/kyra/eobcommon.h
+++ b/engines/kyra/eobcommon.h
@@ -77,7 +77,7 @@ struct EoBGuiButtonDef {
struct EoBCharacter {
uint8 id;
uint8 flags;
- char name[11];
+ char name[21];
int8 strengthCur;
int8 strengthMax;
int8 strengthExtCur;
@@ -476,11 +476,15 @@ protected:
const uint8 *_expObjectAnimTbl3;
int _expObjectAnimTbl3Size;
+ const char *const *_ascii2SjisTables;
+ const char *const *_ascii2SjisTables2;
+
// Monsters
void loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex);
void releaseMonsterShapes(int first, int num);
+ uint8 *loadTownsShape(Common::SeekableReadStream *stream);
virtual void generateMonsterPalettes(const char *file, int16 monsterIndex) {}
- virtual void loadMonsterDecoration(const char *file, int16 monsterIndex) {}
+ virtual void loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex) {}
const uint8 *loadMonsterProperties(const uint8 *data);
const uint8 *loadActiveMonsterData(const uint8 *data, int level);
void initMonster(int index, int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int i, int randItem, int fixedItem);
@@ -632,7 +636,6 @@ protected:
const uint8 *_dscItemTileIndex;
const uint8 *_dscItemShapeMap;
- const uint8 *_dscDoorScaleOffs;
const uint8 *_dscDoorScaleMult1;
const uint8 *_dscDoorScaleMult2;
const uint8 *_dscDoorScaleMult3;
@@ -745,7 +748,7 @@ protected:
static const uint8 _buttonList8[];
int _buttonList8Size;
- const EoBGuiButtonDef *_buttonDefs;
+ EoBGuiButtonDef *_buttonDefs;
const char *const *_characterGuiStringsHp;
const char *const *_characterGuiStringsWp;
@@ -832,6 +835,8 @@ protected:
void seq_portal();
bool checkPassword();
+ Common::String convertAsciiToSjis(Common::String str);
+
virtual int resurrectionSelectDialogue() = 0;
virtual void useHorn(int charIndex, int weaponSlot) {}
virtual bool checkPartyStatusExtra() = 0;
@@ -1120,6 +1125,7 @@ protected:
const EoBMenuButtonDef *_menuButtonDefs;
bool _configMouse;
+ bool _config2431;
const char *const *_menuStringsMain;
const char *const *_menuStringsSaveLoad;
@@ -1142,12 +1148,15 @@ protected:
const char *_errorSlotEmptyString;
const char *_errorSlotNoNameString;
const char *_menuOkString;
-
+ const char *const *_2431Strings;
+ const char *const *_katakanaLines;
+ const char *const *_katakanaSelectStrings;
const char *const *_menuStringsTransfer;
const char *const *_transferStringsScummVM;
const char *const *_menuStringsSpec;
const char *const *_menuStringsSpellNo;
const char *const *_menuYesNoStrings;
+ const char *const *_saveNamePatterns;
const uint8 *_spellLevelsMage;
int _spellLevelsMageSize;
diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp
index eaefa50c1e..1e4fc4388e 100644
--- a/engines/kyra/gui_eob.cpp
+++ b/engines/kyra/gui_eob.cpp
@@ -103,7 +103,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
if (index == _exchangeCharacterId)
_screen->printText(_characterGuiStringsSt[0], x2 + 2, y2 + 2, 8, guiSettings()->colors.fill);
else
- _screen->printText(c->name, x2 + 2, y2 + 2, txtCol1, guiSettings()->colors.fill);
+ _screen->printText(c->name, x2 + 2, y2 + (_flags.platform == Common::kPlatformFMTowns ? 1 : 2), txtCol1, guiSettings()->colors.fill);
gui_drawFaceShape(index);
gui_drawWeaponSlot(index, 0);
@@ -256,8 +256,10 @@ void EoBCoreEngine::gui_drawFaceShape(int index) {
if (c->hitPointsCur < 1)
_screen->drawShape(_screen->_curPage, _disabledCharGrid, x, y, 0);
- _screen->setFadeTable(_greyFadingTable);
- _screen->setShapeFadingLevel(0);
+ if (c->flags & 8 || c->flags & 2 || c->effectFlags & 0x140) {
+ _screen->setFadeTable(_greyFadingTable);
+ _screen->setShapeFadingLevel(0);
+ }
}
void EoBCoreEngine::gui_drawWeaponSlot(int charIndex, int slot) {
@@ -527,8 +529,10 @@ void EoBCoreEngine::gui_drawCompass(bool force) {
}
void EoBCoreEngine::gui_drawDialogueBox() {
+ _screen->set16bitShadingLevel(4);
gui_drawBox(0, 121, 320, 79, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
txt()->clearCurDim();
+ _screen->set16bitShadingLevel(0);
}
void EoBCoreEngine::gui_drawSpellbook() {
@@ -563,7 +567,9 @@ void EoBCoreEngine::gui_drawSpellbook() {
gui_drawBox(i * 21 + 71, 122, 21, 9, col1, col2, col3);
_screen->printText(_magicStrings7[i], i * 21 + 73, 123, 12, 0);
} else {
+ _screen->set16bitShadingLevel(4);
gui_drawBox(i * 18 + 68, 121, 18, 9, col1, col2, col3);
+ _screen->set16bitShadingLevel(0);
_screen->printText(Common::String::format("%d", i + 1).c_str(), i * 18 + 75, 123, 12, 0);
}
}
@@ -571,7 +577,9 @@ void EoBCoreEngine::gui_drawSpellbook() {
if (_flags.gameID == GI_EOB1)
gui_drawBox(71, 131, 105, 44, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
else {
+ _screen->set16bitShadingLevel(4);
gui_drawBox(68, 130, 108, 47, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
gui_drawBox(68, 168, 78, 9, guiSettings()->colors.extraFrame1, guiSettings()->colors.extraFrame2, guiSettings()->colors.extraFill);
gui_drawBox(146, 168, 14, 9, guiSettings()->colors.extraFrame1, guiSettings()->colors.extraFrame2, guiSettings()->colors.extraFill);
gui_drawBox(160, 168, 16, 9, guiSettings()->colors.extraFrame1, guiSettings()->colors.extraFrame2, guiSettings()->colors.extraFill);
@@ -600,6 +608,7 @@ void EoBCoreEngine::gui_drawSpellbook() {
int d = _openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + i];
if (_openBookSpellSelectedItem == i) {
if (d >= 0 && i < 6 && (i + _openBookSpellListOffset) < 9) {
+ _screen->fillRect(textXs, 132 + 6 * i, textXs + _screen->getTextWidth(_openBookSpellList[d]) - 1, 137 + 6 * i, textCol2);
_screen->printText(_openBookSpellList[d], textXs, 132 + 6 * i, textCol1, textCol2);
} else if (i == 6) {
if (_flags.gameID == GI_EOB2)
@@ -1073,6 +1082,7 @@ int EoBCoreEngine::clickedInventoryNextPage(Button *button) {
int EoBCoreEngine::clickedPortraitRestore(Button *button) {
_currentControlMode = 0;
_screen->_curPage = 2;
+ _screen->fillRect(0, 0, 143, 167, 0);
_screen->copyRegion(0, 0, 0, 0, 144, 168, 5, _screen->_curPage, Screen::CR_NO_P_CHECK);
gui_drawAllCharPortraitsWithStats();
_screen->_curPage = 0;
@@ -1178,6 +1188,8 @@ int EoBCoreEngine::clickedSceneSpecial(Button *button) {
int EoBCoreEngine::clickedSpellbookAbort(Button *button) {
_updateFlags = 0;
+ _screen->fillRect(64, 121, 175, 176, 0, 0);
+ _screen->fillRect(64, 121, 175, 176, 0, 2);
_screen->copyRegion(0, 0, 64, 121, 112, 56, 10, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
gui_drawCompass(true);
@@ -1372,8 +1384,8 @@ GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
_saveSlotStringsTemp = new char*[6];
for (int i = 0; i < 6; i++) {
- _saveSlotStringsTemp[i] = new char[20];
- memset(_saveSlotStringsTemp[i], 0, 20);
+ _saveSlotStringsTemp[i] = new char[26];
+ memset(_saveSlotStringsTemp[i], 0, 26);
}
_saveSlotIdTemp = new int16[6];
_savegameOffset = 0;
@@ -2030,6 +2042,7 @@ void GUI_EoB::runCampMenu() {
int newMenu = 0;
int lastMenu = -1;
bool redrawPortraits = false;
+ bool keepButtons = false;
_charSelectRedraw = false;
_needRest = false;
@@ -2040,23 +2053,26 @@ void GUI_EoB::runCampMenu() {
updateOptionsStrings();
if (newMenu != -1) {
- releaseButtons(buttonList);
+ if (!keepButtons) {
+ releaseButtons(buttonList);
- _vm->_menuDefs[0].titleStrId = newMenu ? 1 : 56;
- if (newMenu == 2)
- _vm->_menuDefs[2].titleStrId = 57;
- else if (newMenu == 1)
- _vm->_menuDefs[1].titleStrId = 58;
+ _vm->_menuDefs[0].titleStrId = newMenu ? 1 : 56;
+ if (newMenu == 2)
+ _vm->_menuDefs[2].titleStrId = 57;
+ else if (newMenu == 1)
+ _vm->_menuDefs[1].titleStrId = 58;
- buttonList = initMenu(newMenu);
+ buttonList = initMenu(newMenu);
- if (newMenu != lastMenu) {
- highlightButton = buttonList;
- prevHighlightButton = 0;
+ if (newMenu != lastMenu) {
+ highlightButton = buttonList;
+ prevHighlightButton = 0;
+ }
}
lastMenu = newMenu;
newMenu = -1;
+ keepButtons = false;
}
int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80FF;
@@ -2089,6 +2105,8 @@ void GUI_EoB::runCampMenu() {
if (prevHighlightButton) {
int dir = (inputFlag == _vm->_keyMap[Common::KEYCODE_UP]) ? -1 : 1;
int s = prevHighlightButton->index + dir;
+ if (lastMenu == 2 && _vm->gameFlags().platform == Common::kPlatformFMTowns)
+ s += 32;
int a = _vm->_menuDefs[lastMenu].firstButtonStrId + 1;
int b = a + _vm->_menuDefs[lastMenu].numButtons - 1;
@@ -2102,10 +2120,12 @@ void GUI_EoB::runCampMenu() {
s += dir;
} while (!_vm->shouldQuit());
+ if (lastMenu == 2 && _vm->gameFlags().platform == Common::kPlatformFMTowns)
+ s -= 32;
highlightButton = _vm->gui_getButton(buttonList, s);
}
- } else if (inputFlag > 0x8000 && inputFlag < 0x8010) {
+ } else if (inputFlag > 0x8000 && inputFlag < 0x8011) {
int i = 0;
int cnt = 0;
@@ -2148,7 +2168,7 @@ void GUI_EoB::runCampMenu() {
// fall through
case 0x800C:
- case 0x800F:
+ case 0x8010:
if (lastMenu == 1 || lastMenu == 2)
newMenu = 0;
else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE])
@@ -2199,13 +2219,24 @@ void GUI_EoB::runCampMenu() {
case 0x800D:
_vm->_configSounds ^= true;
_vm->_configMusic = _vm->_configSounds ? 1 : 0;
+ keepButtons = true;
newMenu = 2;
break;
case 0x800E:
_vm->_configHpBarGraphs ^= true;
newMenu = 2;
- redrawPortraits = true;
+ redrawPortraits = keepButtons = true;
+ break;
+
+ case 0x800F:
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ _vm->_config2431 ^= true;
+ newMenu = 2;
+ redrawPortraits = keepButtons = true;
+ } else {
+ newMenu = 0;
+ }
break;
default:
@@ -2233,7 +2264,7 @@ void GUI_EoB::runCampMenu() {
if (prevHighlightButton != highlightButton && newMenu == -1 && runLoop) {
drawMenuButton(prevHighlightButton, false, false, true);
- drawMenuButton(highlightButton, false, true, true);
+ drawMenuButton(highlightButton, false, true, false);
_screen->updateScreen();
prevHighlightButton = highlightButton;
}
@@ -2322,7 +2353,7 @@ bool GUI_EoB::confirmDialogue2(int dim, int id, int deflt) {
if (newHighlight != lastHighlight) {
for (int i = 0; i < 2; i++)
- _screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (strlen(_vm->_menuYesNoStrings[i]) << 2) + 1, y + 3, i == newHighlight ? 6 : 15, 0);
+ _screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (_screen->getTextWidth(_vm->_menuYesNoStrings[i]) / 2) + 1, y + 3, i == newHighlight ? 6 : 15, 0);
_screen->updateScreen();
lastHighlight = newHighlight;
}
@@ -2349,9 +2380,9 @@ void GUI_EoB::messageDialogue(int dim, int id, int buttonTextCol) {
drawTextBox(dim, id);
const ScreenDim *dm = _screen->getScreenDim(dim);
- int bx = ((dm->sx + dm->w) << 3) - ((strlen(_vm->_menuOkString) << 3) + 16);
+ int bx = ((dm->sx + dm->w) << 3) - (_screen->getTextWidth(_vm->_menuOkString) + 16);
int by = dm->sy + dm->h - 19;
- int bw = (strlen(_vm->_menuOkString) << 3) + 7;
+ int bw = _screen->getTextWidth(_vm->_menuOkString) + 7;
drawMenuButtonBox(bx, by, bw, 14, false, false);
_screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0);
@@ -2382,8 +2413,6 @@ void GUI_EoB::messageDialogue(int dim, int id, int buttonTextCol) {
}
void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
- drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
-
_screen->_curPage = 2;
_screen->setClearScreenDim(dim);
drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
@@ -2391,9 +2420,9 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
_screen->_curPage = 0;
_screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK);
- int x = (_screen->_curDim->sx << 3) + (_screen->_curDim->w << 2) - (strlen(_vm->_menuOkString) << 2);
+ int x = (_screen->_curDim->sx << 3) + (_screen->_curDim->w << 2) - (_screen->getTextWidth(_vm->_menuOkString) / 2);
int y = _screen->_curDim->sy + _screen->_curDim->h - 21;
- int w = (strlen(_vm->_menuOkString) << 3) + 8;
+ int w = _screen->getTextWidth(_vm->_menuOkString) + 8;
drawMenuButtonBox(x, y, w, 14, false, false);
_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0);
_screen->updateScreen();
@@ -2410,7 +2439,9 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
}
}
+ _screen->set16bitShadingLevel(4);
_vm->gui_drawBox(x, y, w, 14, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill, -1);
+ _screen->set16bitShadingLevel(0);
_screen->updateScreen();
_vm->_system->delayMillis(80);
drawMenuButtonBox(x, y, w, 14, false, false);
@@ -2456,7 +2487,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
#endif
uint8 cursorState = 1;
- char sufx[] = " ";
+ char sufx[3] = " \0";
int len = strlen(dest);
if (len > destMaxLen) {
@@ -2469,12 +2500,17 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
pos--;
_screen->copyRegion((x - 1) << 3, y, 0, 191, (destMaxLen + 2) << 3, 9, 0, 2, Screen::CR_NO_P_CHECK);
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ _screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
_screen->printShadedText(dest, x << 3, y, textColor1, textColor2);
uint32 next = _vm->_system->getMillis() + 2 * _vm->_tickLength;
sufx[0] = (pos < len) ? dest[pos] : 32;
_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
+ _menuCur = -1;
+ printKatakanaOptions(0);
+
int in = 0;
do {
@@ -2487,33 +2523,58 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
_screen->copyRegion((pos + 1) << 3, 191, (x + pos) << 3, y, 8, 9, 2, 0, Screen::CR_NO_P_CHECK);
_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2);
} else {
+ _screen->fillRect((x + pos) << 3, y, ((x + pos) << 3) + 7, y + 7, cursorColor);
_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
}
_screen->updateScreen();
cursorState ^= 1;
- next = _vm->_system->getMillis() + 2 * _vm->_tickLength;
+ next = _vm->_system->getMillis() + 4 * _vm->_tickLength;
}
_vm->updateInput();
+ in = checkKatakanaSelection();
+
for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); ++evt) {
if (evt->event.type == Common::EVENT_KEYDOWN) {
_keyPressed = evt->event.kbd;
in = _keyPressed.ascii;
+
+ if (_vm->_flags.platform == Common::kPlatformFMTowns && _keyPressed.ascii > 31 && _keyPressed.ascii < 123) {
+ Common::String s;
+ s.insertChar(in & 0xff, 0);
+ s = _vm->convertAsciiToSjis(s);
+ if (s.empty()) {
+ in = 0;
+ } else {
+ _csjis[0] = s[0];
+ _csjis[1] = s[1];
+ _csjis[2] = 0;
+ in = 0x89;
+ }
+ }
}
}
_vm->removeInputTop();
}
if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE) {
- if (pos >= len && len > 0) {
- dest[--len] = 0;
- pos--;
+ if (pos > 0 && pos < len ) {
+ for (int i = pos; i < len; i++) {
+ if (dest[i * 2] & 0x80) {
+ dest[(i - 1) * 2] = dest[i * 2];
+ dest[(i - 1) * 2 + 1] = dest[i * 2 + 1];
+ } else {
+ dest[i - 1] = dest[i];
+ }
+ }
+ }
- } else if (pos > 0) {
- for (int i = pos; i < destMaxLen; i++)
- dest[i - 1] = dest[i];
- dest[--len] = 0;
+ if (pos > 0) {
+ if (dest[(len - 1) * 2] & 0x80)
+ dest[--len * 2] = 0;
+ else
+ dest[--len] = 0;
pos--;
}
@@ -2525,28 +2586,45 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
if (pos < len && pos < (destMaxLen - 1))
pos++;
- } else if (in > 31 && in < 126) {
+ } else if ((in > 31 && in < 126) || (in == 0x89)) {
if (!(in == 32 && pos == 0)) {
if (in >= 97 && in <= 122)
in -= 32;
if (pos < len) {
- for (int i = destMaxLen - 1; i >= pos; i--)
- dest[i + 1] = dest[i];
-
- dest[pos++] = in;
-
- if (len == destMaxLen)
- dest[len] = 0;
+ for (int i = destMaxLen - 2; i >= pos; i--) {
+ if (in == 0x89) {
+ dest[(i + 1) * 2] = dest[i * 2];
+ dest[(i + 1) * 2 + 1] = dest[i * 2 + 1];
+ } else {
+ dest[i + 1] = dest[i];
+ }
+ }
+ if (in == 0x89) {
+ dest[pos * 2] = _csjis[0];
+ dest[pos++ * 2 + 1] = _csjis[1];
+ if (len == destMaxLen)
+ dest[len * 2] = 0;
+ } else {
+ dest[pos++] = in;
+ if (len == destMaxLen)
+ dest[len] = 0;
+ }
} else {
if (pos == destMaxLen) {
pos--;
len--;
}
- dest[pos++] = in;
- dest[pos] = 0;
+ if (in == 0x89) {
+ dest[pos * 2] = _csjis[0];
+ dest[pos * 2 + 1] = _csjis[1];
+ dest[++pos * 2] = 0;
+ } else {
+ dest[pos++] = in;
+ dest[pos] = 0;
+ }
}
if (++len > destMaxLen)
@@ -2559,7 +2637,18 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
_screen->copyRegion(0, 191, (x - 1) << 3, y, (destMaxLen + 2) << 3, 9, 2, 0, Screen::CR_NO_P_CHECK);
_screen->printShadedText(dest, x << 3, y, textColor1, textColor2);
- sufx[0] = (pos < len) ? dest[pos] : 32;
+
+ if (_vm->_flags.platform == Common::kPlatformFMTowns) {
+ if (pos < len) {
+ sufx[0] = dest[pos * 2];
+ sufx[1] = dest[pos * 2 + 1];
+ } else {
+ sufx[0] = 32;
+ sufx[1] = 0;
+ }
+ } else {
+ sufx[0] = (pos < len) ? dest[pos] : 32;
+ }
if (cursorState)
_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
@@ -2576,6 +2665,108 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
return _keyPressed.keycode == Common::KEYCODE_ESCAPE ? -1 : len;
}
+int GUI_EoB::checkKatakanaSelection() {
+ if (_vm->_flags.platform != Common::kPlatformFMTowns)
+ return 0;
+
+ static uint16 kanaSelXCrds[] = { 224, 272, 186 };
+ Common::Point mousePos = _vm->getMousePos();
+ int highlight = -1;
+ _csjis[0] = _csjis[2] = 0;
+
+ for (int y = 112; y < 168; y += 16) {
+ for (int x = 152; x < 288; x += 8) {
+ if (!_vm->posWithinRect(mousePos.x, mousePos.y, x, y, x + 9, y + 9))
+ continue;
+
+ int lineOffs = (y - 112) >> 4;
+ int column = (x - 152) >> 2;
+
+ _csjis[0] = _vm->_katakanaLines[_currentKanaPage * 4 + lineOffs][column];
+ _csjis[1] = _vm->_katakanaLines[_currentKanaPage * 4 + lineOffs][column + 1];
+
+ if (_csjis[0] != '\x81' || _csjis[1] != '\x40') {
+ highlight = lineOffs << 8 | column;
+ _screen->printShadedText(_csjis, x & ~7, y & ~15, 6, 0);
+ }
+
+ x = 288; y = 168;
+ }
+ }
+
+ if (highlight == -1) {
+ for (int i = 0; i < 3; i++) {
+ if (!_vm->posWithinRect(mousePos.x, mousePos.y, kanaSelXCrds[i], 176, kanaSelXCrds[i] + _screen->getTextWidth(_vm->_katakanaSelectStrings[i]), 184))
+ continue;
+
+ highlight = 0x400 | i;
+ _screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelXCrds[i], 176, 6, 0);
+ i = 3;
+ }
+ }
+
+ 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 ((highlight == -1 || highlight == _menuCur) && !in)
+ return 0;
+
+ if (_menuCur != -1) {
+ if (_menuCur & 0x400) {
+ _screen->printShadedText(_vm->_katakanaSelectStrings[_menuCur & 3], kanaSelXCrds[_menuCur & 3], 176, 15, 0);
+ } else {
+ char osjis[3];
+ osjis[0] = _vm->_katakanaLines[_currentKanaPage * 4 + (_menuCur >> 8)][_menuCur & 0xFF];
+ osjis[1] = _vm->_katakanaLines[_currentKanaPage * 4 + (_menuCur >> 8)][(_menuCur & 0xFF) + 1];
+ osjis[2] = 0;
+ _screen->printShadedText(osjis, 152 + ((_menuCur & 0xFF) << 2), 112 + ((_menuCur >> 4) & ~0x0F), 15, 0);
+ }
+ }
+
+ _menuCur = highlight;
+
+ if (in && highlight != -1) {
+ if (highlight & 0x400) {
+ switch (highlight & 3) {
+ case 0:
+ printKatakanaOptions((_currentKanaPage + 1) % 3);
+ break;
+ case 1:
+ _keyPressed.keycode = Common::KEYCODE_RETURN;
+ break;
+ case 2:
+ _keyPressed.keycode = Common::KEYCODE_BACKSPACE;
+ break;
+ default:
+ break;
+ }
+ } else if (_csjis[0]) {
+ if (_csjis[0] == '\x81' && _csjis[1] == '\x51')
+ _csjis[1] = '\x40';
+ return 0x89;
+ }
+ }
+
+ return in;
+}
+
+void GUI_EoB::printKatakanaOptions(int page) {
+ if (_vm->_flags.platform != Common::kPlatformFMTowns)
+ return;
+
+ _currentKanaPage = page;
+ _screen->copyRegion(160, 44, 144, 108, 160, 84, 2, 0, Screen::CR_NO_P_CHECK);
+ for (int i = 0; i < 4; i++)
+ _screen->printShadedText(_vm->_katakanaLines[page * 4 + i], 152, (i << 4) + 112, 15, 0);
+
+ static uint16 kanaSelCrds[] = { 224, 272, 186 };
+ for (int i = 0; i < 3; i++)
+ _screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelCrds[i], 176, 15, 0);
+}
+
void GUI_EoB::transferWaitBox() {
const ScreenDim *dm = _screen->getScreenDim(11);
int xo = dm->sx;
@@ -2698,10 +2889,21 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
int fx = (x + 1) << 3;
int fy = y + slot * 17 + 23;
+ Screen::FontId of = _screen->_currentFont;
+ _screen->set16bitShadingLevel(4);
for (int in = -1; in == -1 && !_vm->shouldQuit();) {
_screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill);
- in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, 2, 0, 8);
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ TimeDate td;
+ _vm->_system->getTimeAndDate(td);
+ Common::strlcpy(_saveSlotStringsTemp[slot], Common::String::format(_vm->_saveNamePatterns[_vm->_currentLevel * 2 + _vm->_currentSub], td.tm_mon + 1, td.tm_mday, td.tm_hour, td.tm_min).c_str(), 25);
+ in = strlen(_saveSlotStringsTemp[slot]);
+ of = _vm->screen()->setFont(Screen::FID_6_FNT);
+ y++;
+ } else {
+ in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, 2, 0, 8);
+ }
if (in == -1) {
useSlot = false;
break;
@@ -2719,6 +2921,9 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
_screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill);
_screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, 15, 0);
+ _screen->set16bitShadingLevel(0);
+ _screen->setFont(of);
+ _screen->updateScreen();
Graphics::Surface thumb;
createScreenThumbnail(thumb);
@@ -2831,7 +3036,9 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
// Display highlighted slot index in the bottom left corner to avoid people getting lost with the 990 save slots
_screen->setFont(Screen::FID_6_FNT);
int sli = (newHighlight == 6) ? _savegameOffset : (_savegameOffset + newHighlight);
+ _screen->set16bitShadingLevel(4);
_screen->printText(Common::String::format("%03d/989", sli).c_str(), _saveSlotX + 5, _saveSlotY + 135, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
_screen->setFont(Screen::FID_8_FNT);
_screen->updateScreen();
@@ -2990,7 +3197,9 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) {
if (updateDesc) {
updateDesc = false;
+ _screen->set16bitShadingLevel(4);
_screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
}
if (newHighLightText < 0)
@@ -3664,6 +3873,13 @@ int GUI_EoB::selectCharacterDialogue(int id) {
result = -2;
int hlCur = -1;
+ for (int i = 0; i < 6; ++i) {
+ if (found[i] != -1) {
+ hlCur = i;
+ break;
+ }
+ }
+
Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
while (result == -2 && !_vm->shouldQuit()) {
@@ -3788,6 +4004,8 @@ Button *GUI_EoB::initMenu(int id) {
b->index = m->firstButtonStrId + i + 1;
if (id == 4 && _vm->game() == GI_EOB1)
b->index -= 14;
+ else if (id == 2 && _vm->gameFlags().platform == Common::kPlatformFMTowns)
+ b->index -= 32;
b->data0Val2 = 12;
b->data1Val2 = b->data2Val2 = 15;
@@ -3830,7 +4048,7 @@ void GUI_EoB::drawMenuButton(Button *b, bool clicked, bool highlight, bool noFil
int yOffs = 3;
if (d->flags & 4) {
- xOffs = ((b->width - (strlen(s) << 3)) >> 1) + 1;
+ xOffs = ((b->width - _screen->getTextWidth(s)) >> 1) + 1;
yOffs = (b->height - 7) >> 1;
}
@@ -3850,8 +4068,10 @@ void GUI_EoB::drawMenuButtonBox(int x, int y, int w, int h, bool clicked, bool n
if (clicked)
col1 = col2 = _vm->guiSettings()->colors.fill;
+ _screen->set16bitShadingLevel(4);
_vm->gui_drawBox(x, y, w, h, col1, col2, -1);
_vm->gui_drawBox(x + 1, y + 1, w - 2, h - 2, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, noFill ? -1 : _vm->guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
}
void GUI_EoB::drawTextBox(int dim, int id) {
@@ -3893,7 +4113,14 @@ void GUI_EoB::drawSaveSlotButton(int slot, int redrawBox, int textCol) {
if (redrawBox)
drawMenuButtonBox(x, y, w, 14, (redrawBox - 1) ? true : false, false);
+ Screen::FontId fnt = _screen->_currentFont;
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ fnt = _vm->screen()->setFont(Screen::FID_6_FNT);
+ y++;
+ }
+
_screen->printShadedText(s, x + 4, y + 3, textCol, 0);
+ _vm->screen()->setFont(fnt);
}
void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int spellType, bool noFill, bool highLight) {
@@ -3902,17 +4129,28 @@ void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int sp
int y = bookPageIndex * 9 + 50;
int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+ _screen->set16bitShadingLevel(4);
if (spellId) {
- Common::String s(Common::String::format(_vm->_menuStringsMgc[0], spellType ? _vm->_clericSpellList[spellId] : _vm->_mageSpellList[spellId], _numAssignedSpellsOfType[spellId * 2 - 2]));
+ Common::String s;
+ if (_vm->_flags.platform == Common::kPlatformFMTowns) {
+ s = spellType ? _vm->_clericSpellList[spellId] : _vm->_mageSpellList[spellId];
+ for (int i = s.size() >> 1; i < 17; ++i)
+ s.insertChar(' ', s.size());
+ s.insertChar((char)(_numAssignedSpellsOfType[spellId * 2 - 2] + 48), s.size());
+ } else {
+ s = Common::String::format(_vm->_menuStringsMgc[0], spellType ? _vm->_clericSpellList[spellId] : _vm->_mageSpellList[spellId], _numAssignedSpellsOfType[spellId * 2 - 2]);
+ }
+
if (noFill)
_screen->printText(s.c_str(), 8, y, highLight ? 6 : col1, 0);
else
_screen->printShadedText(s.c_str(), 8, y, highLight ? 6 : col1, _vm->guiSettings()->colors.fill);
-
} else {
_screen->fillRect(6, y, 168, y + 8, _vm->guiSettings()->colors.fill);
}
+
+ _screen->set16bitShadingLevel(0);
}
void GUI_EoB::updateOptionsStrings() {
@@ -3924,7 +4162,7 @@ void GUI_EoB::updateOptionsStrings() {
Common::strlcpy(_menuStringsPrefsTemp[0], Common::String::format(_vm->_menuStringsPrefs[0], _vm->_menuStringsOnOff[_vm->_configMusic ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[0]) + 8);
Common::strlcpy(_menuStringsPrefsTemp[1], Common::String::format(_vm->_menuStringsPrefs[1], _vm->_menuStringsOnOff[_vm->_configSounds ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[1]) + 8);
Common::strlcpy(_menuStringsPrefsTemp[2], Common::String::format(_vm->_menuStringsPrefs[2], _vm->_menuStringsOnOff[_vm->_configHpBarGraphs ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[2]) + 8);
- Common::strlcpy(_menuStringsPrefsTemp[3], Common::String::format(_vm->_menuStringsPrefs[3], _vm->_menuStringsOnOff[_vm->_configMouse ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[3]) + 8);
+ Common::strlcpy(_menuStringsPrefsTemp[3], Common::String::format(_vm->_menuStringsPrefs[3], _vm->gameFlags().platform == Common::kPlatformFMTowns ? _vm->_2431Strings[_vm->_config2431 ? 0 : 1] : _vm->_menuStringsOnOff[_vm->_configMouse ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[3]) + 8);
}
const char *GUI_EoB::getMenuString(int id) {
@@ -4010,12 +4248,12 @@ void GUI_EoB::setupSaveMenuSlots() {
for (int i = 0; i < 6; ++i) {
if (_savegameOffset + i < _savegameListSize) {
if (_savegameList[i + _savegameOffset]) {
- Common::strlcpy(_saveSlotStringsTemp[i], _savegameList[i + _savegameOffset], 20);
+ Common::strlcpy(_saveSlotStringsTemp[i], _savegameList[i + _savegameOffset], 25);
_saveSlotIdTemp[i] = i + _savegameOffset;
continue;
}
}
- Common::strlcpy(_saveSlotStringsTemp[i], _vm->_saveLoadStrings[1], 20);
+ Common::strlcpy(_saveSlotStringsTemp[i], _vm->_saveLoadStrings[1], 25);
_saveSlotIdTemp[i] = -1;
}
}
@@ -4055,14 +4293,13 @@ void GUI_EoB::restParty_updateRestTime(int hours, bool init) {
_screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0);
}
- _screen->setCurPage(2);
- _screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, 15, _vm->guiSettings()->colors.fill);
_screen->setCurPage(0);
- _screen->copyRegion(((_screen->_curDim->sx + 1) << 3) - 1, _screen->_curDim->sy + 20, ((_screen->_curDim->sx + 1) << 3) - 1, _screen->_curDim->sy + 20, 144, 8, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->set16bitShadingLevel(4);
+ _screen->fillRect((_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, ((_screen->_curDim->sx + 19) << 3) + 1, _screen->_curDim->sy + 29, _vm->guiSettings()->colors.fill);
+ _screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, 15, _vm->guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
_screen->updateScreen();
-
_vm->delay(160);
-
_screen->setScreenDim(od);
_screen->setFont(of);
}
diff --git a/engines/kyra/gui_eob.h b/engines/kyra/gui_eob.h
index e4daff6ada..5d2fed4dbc 100644
--- a/engines/kyra/gui_eob.h
+++ b/engines/kyra/gui_eob.h
@@ -154,6 +154,13 @@ private:
static const EoBRect16 _highlightFrames[];
static const uint8 _highlightColorTableVGA[];
static const uint8 _highlightColorTableEGA[];
+
+ // FM-Towns specific
+ int checkKatakanaSelection();
+ void printKatakanaOptions(int page);
+
+ int _currentKanaPage;
+ char _csjis[3];
};
} // End of namespace Kyra
diff --git a/engines/kyra/items_eob.cpp b/engines/kyra/items_eob.cpp
index 6ec9b331a3..036ee818f8 100644
--- a/engines/kyra/items_eob.cpp
+++ b/engines/kyra/items_eob.cpp
@@ -444,7 +444,7 @@ void EoBCoreEngine::printFullItemName(Item item) {
tmpString = (itm->flags & 0x40) ? nameId : nameUnid;
}
- _txt->printMessage(tmpString.c_str());
+ _txt->printMessage(convertAsciiToSjis(tmpString).c_str());
}
void EoBCoreEngine::identifyQueuedItems(Item itemQueue) {
diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp
index 635559dcfd..75cb6f5945 100644
--- a/engines/kyra/kyra_rpg.cpp
+++ b/engines/kyra/kyra_rpg.cpp
@@ -46,6 +46,7 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi
_vcnTransitionMask = 0;
_vcnShift = 0;
_vcnColTable = 0;
+ _vcnBpp = flags.useHiColorMode ? 2 : 1;
_vmpPtr = 0;
_blockBrightness = _wllVcnOffset = 0;
_blockDrawingBuffer = 0;
@@ -84,7 +85,7 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi
_dscShapeX = 0;
_dscTileIndex = 0;
- _dscUnk2 = 0;
+ _dscDoorScaleOffs = 0;
_dscDim1 = 0;
_dscDim2 = 0;
_dscBlockMap = 0;
@@ -168,8 +169,9 @@ Common::Error KyraRpgEngine::init() {
_blockDrawingBuffer = new uint16[1320];
memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16));
- _sceneWindowBuffer = new uint8[21120];
- memset(_sceneWindowBuffer, 0, 21120);
+ int windowBufferSize = _flags.useHiColorMode ? 42240 : 21120;
+ _sceneWindowBuffer = new uint8[windowBufferSize];
+ memset(_sceneWindowBuffer, 0, windowBufferSize);
_lvlShapeTop = new int16[18];
memset(_lvlShapeTop, 0, 18 * sizeof(int16));
@@ -187,7 +189,7 @@ Common::Error KyraRpgEngine::init() {
initStaticResource();
- _envSfxDistThreshold = (_sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : 3;
+ _envSfxDistThreshold = (_flags.gameID == GI_EOB2 || _sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : 3;
_dialogueButtonLabelColor1 = guiSettings()->buttons.labelColor1;
_dialogueButtonLabelColor2 = guiSettings()->buttons.labelColor2;
@@ -204,7 +206,7 @@ bool KyraRpgEngine::posWithinRect(int posX, int posY, int x1, int y1, int x2, in
void KyraRpgEngine::drawDialogueButtons() {
int cp = screen()->setCurPage(0);
- Screen::FontId of = screen()->setFont(_flags.lang == Common::JA_JPN && _flags.use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
+ Screen::FontId of = screen()->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : ((_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns) ? Screen::FID_8_FNT : Screen::FID_6_FNT));
for (int i = 0; i < _dialogueNumButtons; i++) {
int x = _dialogueButtonPosX[i];
@@ -213,8 +215,10 @@ void KyraRpgEngine::drawDialogueButtons() {
screen()->printText(_dialogueButtonString[i], (x + 37 - (screen()->getTextWidth(_dialogueButtonString[i])) / 2) & ~3,
((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xC1 : 0xE1, 0);
} else {
- int sjisYOffset = (_flags.lang == Common::JA_JPN && (_dialogueButtonString[i][0] & 0x80)) ? 2 : 0;
+ int sjisYOffset = (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns) ? 1 : ((_flags.lang == Common::JA_JPN && (_dialogueButtonString[i][0] & 0x80)) ? 2 : 0);
+ screen()->set16bitShadingLevel(4);
gui_drawBox(x, (_dialogueButtonYoffs + _dialogueButtonPosY[i]), _dialogueButtonWidth, guiSettings()->buttons.height, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ screen()->set16bitShadingLevel(0);
screen()->printText(_dialogueButtonString[i], x + (_dialogueButtonWidth >> 1) - (screen()->getTextWidth(_dialogueButtonString[i])) / 2,
(_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2 - sjisYOffset, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0);
}
@@ -348,7 +352,7 @@ bool KyraRpgEngine::snd_processEnvironmentalSoundEffect(int soundId, int block)
}
_environmentSfx = soundId;
- _environmentSfxVol = (15 - ((block || (_flags.gameID == GI_LOL && dist < 2)) ? dist : 0)) << 4;
+ _environmentSfxVol = (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns) ? (dist ? (16 - dist) * 8 - 1 : 127) : ((15 - ((block || (_flags.gameID == GI_LOL && dist < 2)) ? dist : 0)) << 4);
return true;
}
diff --git a/engines/kyra/kyra_rpg.h b/engines/kyra/kyra_rpg.h
index 69fc705ff2..3d673824f9 100644
--- a/engines/kyra/kyra_rpg.h
+++ b/engines/kyra/kyra_rpg.h
@@ -227,6 +227,7 @@ protected:
uint8 *_vcnTransitionMask;
uint8 *_vcnShift;
uint8 *_vcnColTable;
+ uint8 _vcnBpp;
uint16 *_blockDrawingBuffer;
uint8 *_sceneWindowBuffer;
uint8 _blockBrightness;
@@ -263,7 +264,7 @@ protected:
const int8 *_dscDim1;
const int8 *_dscDim2;
const int16 *_dscShapeX;
- const uint8 *_dscUnk2;
+ const uint8 *_dscDoorScaleOffs;
const uint8 *_dscBlockMap;
const int8 *_dscBlockIndex;
const uint8 *_dscTileIndex;
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index c8993fea47..83fe5192aa 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -378,21 +378,21 @@ void KyraEngine_v1::setupKeyMap() {
{ KC(KP1), 93, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
{ KC(PAGEDOWN), 103, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
{ KC(KP3), 103, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(F1), 112, 99, UNKNOWN_KEYCODE },
- { KC(F2), 113, 100, UNKNOWN_KEYCODE },
- { KC(F3), 114, 101, UNKNOWN_KEYCODE },
- { KC(F4), 115, 102, UNKNOWN_KEYCODE },
- { KC(F5), 116, 103, UNKNOWN_KEYCODE },
- { KC(F6), 117, 104, UNKNOWN_KEYCODE },
+ { KC(F1), 112, 99, 93 },
+ { KC(F2), 113, 100, 94 },
+ { KC(F3), 114, 101, 95 },
+ { KC(F4), 115, 102, 96 },
+ { KC(F5), 116, 103, 97 },
+ { KC(F6), 117, 104, 98 },
{ KC(a), 31, 31, UNKNOWN_KEYCODE },
- { KC(b), 50, 50, UNKNOWN_KEYCODE },
+ { KC(b), 50, 50, 66 },
{ KC(c), 48, 48, 67 },
- { KC(d), 33, 33, UNKNOWN_KEYCODE },
+ { KC(d), 33, 33, 68 },
{ KC(e), 19, 19, UNKNOWN_KEYCODE },
- { KC(f), 34, 34, UNKNOWN_KEYCODE },
- { KC(i), 24, 24, UNKNOWN_KEYCODE },
- { KC(k), 38, 38, UNKNOWN_KEYCODE },
- { KC(m), 52, 52, UNKNOWN_KEYCODE },
+ { KC(f), 34, 34, 70 },
+ { KC(i), 24, 24, 24 },
+ { KC(k), 38, 38, 75 },
+ { KC(m), 52, 52, 77 },
{ KC(n), 51, 51, UNKNOWN_KEYCODE },
{ KC(o), 25, 25, 79 },
{ KC(p), 26, 26, 80 },
@@ -411,22 +411,22 @@ void KyraEngine_v1::setupKeyMap() {
{ KC(7), 8, UNKNOWN_KEYCODE, 55 },
{ KC(SLASH), 55, 55, 47 },
{ KC(ESCAPE), 110, 1, 27 },
- { KC(MINUS), 12, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(KP_MINUS), 105, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(PLUS), 13, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(KP_PLUS), 106, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
+ { KC(MINUS), 12, UNKNOWN_KEYCODE, 45 },
+ { KC(KP_MINUS), 105, UNKNOWN_KEYCODE, 45 },
+ { KC(PLUS), 13, UNKNOWN_KEYCODE, 43 },
+ { KC(KP_PLUS), 106, UNKNOWN_KEYCODE, 43 },
// Multiple mappings for the keys to the right of the 'M' key,
// since these are different for QWERTZ, QWERTY and AZERTY keyboards.
// QWERTZ
- { KC(COMMA), 53, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(PERIOD), 54, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
+ { KC(COMMA), 53, UNKNOWN_KEYCODE, 60 },
+ { KC(PERIOD), 54, UNKNOWN_KEYCODE, 62 },
// AZERTY
- { KC(SEMICOLON), 53, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(COLON), 54, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
+ { KC(SEMICOLON), 53, UNKNOWN_KEYCODE, 60 },
+ { KC(COLON), 54, UNKNOWN_KEYCODE, 62 },
// QWERTY
- { KC(LESS), 53, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE },
- { KC(GREATER), 54, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }
+ { KC(LESS), 53, UNKNOWN_KEYCODE, 60 },
+ { KC(GREATER), 54, UNKNOWN_KEYCODE, 62 }
};
#undef KC
#undef UNKNOWN_KEYCODE
diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp
index 52bca46a24..91d50c6279 100644
--- a/engines/kyra/magic_eob.cpp
+++ b/engines/kyra/magic_eob.cpp
@@ -420,14 +420,14 @@ void EoBCoreEngine::sparkEffectDefensive(int charIndex) {
void EoBCoreEngine::sparkEffectOffensive() {
disableSysTimer(2);
_screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 2, Screen::CR_NO_P_CHECK);
+ int sh = _flags.useHiColorMode ? 9 : 8;
for (int i = 0; i < 16; i++)
- _screen->copyRegionToBuffer(0, _sparkEffectOfX[i], _sparkEffectOfY[i], 16, 16, &_spellAnimBuffer[i << 8]);
- _screen->updateScreen();
+ _screen->copyRegionToBuffer(0, _sparkEffectOfX[i], _sparkEffectOfY[i], 16, 16, &_spellAnimBuffer[i << sh]);
for (int i = 0; i < 11; i++) {
for (int ii = 0; ii < 16; ii++)
- _screen->copyBlockToPage(2, _sparkEffectOfX[ii], _sparkEffectOfY[ii], 16, 16, &_spellAnimBuffer[ii << 8]);
+ _screen->copyBlockToPage(2, _sparkEffectOfX[ii], _sparkEffectOfY[ii], 16, 16, &_spellAnimBuffer[ii << sh]);
for (int ii = 0; ii < 16; ii++) {
int shpIndex = (_sparkEffectOfFlags1[i] & _sparkEffectOfFlags2[ii]) >> _sparkEffectOfShift[ii];
@@ -440,7 +440,7 @@ void EoBCoreEngine::sparkEffectOffensive() {
}
for (int i = 0; i < 16; i++)
- _screen->copyBlockToPage(0, _sparkEffectOfX[i], _sparkEffectOfY[i], 16, 16, &_spellAnimBuffer[i << 8]);
+ _screen->copyBlockToPage(0, _sparkEffectOfX[i], _sparkEffectOfY[i], 16, 16, &_spellAnimBuffer[i << sh]);
_screen->updateScreen();
enableSysTimer(2);
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index 21e3ba3dff..098c6da248 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -120,6 +120,7 @@ MODULE_OBJS += \
script_eob.o \
sequences_eob.o \
sequences_darkmoon.o \
+ sound_towns_darkmoon.o \
sprites_eob.o \
staticres_eob.o \
timer_eob.o
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index c3ebf6e5fe..9d496baac5 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -255,7 +255,6 @@ enum KyraResources {
kRpgCommonDscShapeIndex,
kRpgCommonDscX,
kRpgCommonDscTileIndex,
- kRpgCommonDscUnk2,
kRpgCommonDscDoorShapeIndex,
kRpgCommonDscDimData1,
kRpgCommonDscDimData2,
@@ -266,6 +265,7 @@ enum KyraResources {
kRpgCommonDscDoorFrameY2,
kRpgCommonDscDoorFrameIndex1,
kRpgCommonDscDoorFrameIndex2,
+ kRpgCommonDscDoorScaleOffs,
kRpgCommonDscBlockIndex,
kEoBBaseChargenStrings1,
@@ -400,7 +400,6 @@ enum KyraResources {
kEoBBaseWllFlagPreset,
kEoBBaseDscShapeCoords,
- kEoBBaseDscDoorScaleOffs,
kEoBBaseDscDoorScaleMult1,
kEoBBaseDscDoorScaleMult2,
kEoBBaseDscDoorScaleMult3,
@@ -554,6 +553,7 @@ enum KyraResources {
kEoB1Npc7Strings,
kEoB2MainMenuStrings,
+ kEoB2MainMenuUtilStrings,
kEoB2TransferPortraitFrames,
kEoB2TransferConvertTable,
@@ -609,6 +609,7 @@ enum KyraResources {
kEoB2IntroAnimData41,
kEoB2IntroAnimData42,
kEoB2IntroAnimData43,
+
kEoB2IntroShapes00,
kEoB2IntroShapes01,
kEoB2IntroShapes04,
@@ -660,6 +661,257 @@ enum KyraResources {
kEoB2WallOfForceNumH,
kEoB2WallOfForceShpId,
+ kEoB2IntroCpsDataStreet1,
+ kEoB2IntroCpsDataStreet2,
+ kEoB2IntroCpsDataDoorway1,
+ kEoB2IntroCpsDataDoorway2,
+ kEoB2IntroCpsDataWestwood,
+ kEoB2IntroCpsDataWinding,
+ kEoB2IntroCpsDataKhelban2,
+ kEoB2IntroCpsDataKhelban1,
+ kEoB2IntroCpsDataKhelban3,
+ kEoB2IntroCpsDataKhelban4,
+ kEoB2IntroCpsDataCoin,
+ kEoB2IntroCpsDataKhelban5,
+ kEoB2IntroCpsDataKhelban6,
+
+ kEoB2FinaleCpsDataDragon1,
+ kEoB2FinaleCpsDataDragon2,
+ kEoB2FinaleCpsDataHurry1,
+ kEoB2FinaleCpsDataHurry2,
+ kEoB2FinaleCpsDataDestroy0,
+ kEoB2FinaleCpsDataDestroy1,
+ kEoB2FinaleCpsDataDestroy2,
+ kEoB2FinaleCpsDataMagic,
+ kEoB2FinaleCpsDataDestroy3,
+ kEoB2FinaleCpsDataCredits2,
+ kEoB2FinaleCpsDataCredits3,
+ kEoB2FinaleCpsDataHeroes,
+ kEoB2FinaleCpsDataThanks,
+
+ kEoB2ItemIconShapeData00,
+ kEoB2ItemIconShapeData01,
+ kEoB2ItemIconShapeData02,
+ kEoB2ItemIconShapeData03,
+ kEoB2ItemIconShapeData04,
+ kEoB2ItemIconShapeData05,
+ kEoB2ItemIconShapeData06,
+ kEoB2ItemIconShapeData07,
+ kEoB2ItemIconShapeData08,
+ kEoB2ItemIconShapeData09,
+ kEoB2ItemIconShapeData10,
+ kEoB2ItemIconShapeData11,
+ kEoB2ItemIconShapeData12,
+ kEoB2ItemIconShapeData13,
+ kEoB2ItemIconShapeData14,
+ kEoB2ItemIconShapeData15,
+ kEoB2ItemIconShapeData16,
+ kEoB2ItemIconShapeData17,
+ kEoB2ItemIconShapeData18,
+ kEoB2ItemIconShapeData19,
+ kEoB2ItemIconShapeData20,
+ kEoB2ItemIconShapeData21,
+ kEoB2ItemIconShapeData22,
+ kEoB2ItemIconShapeData23,
+ kEoB2ItemIconShapeData24,
+ kEoB2ItemIconShapeData25,
+ kEoB2ItemIconShapeData26,
+ kEoB2ItemIconShapeData27,
+ kEoB2ItemIconShapeData28,
+ kEoB2ItemIconShapeData29,
+ kEoB2ItemIconShapeData30,
+ kEoB2ItemIconShapeData31,
+ kEoB2ItemIconShapeData32,
+ kEoB2ItemIconShapeData33,
+ kEoB2ItemIconShapeData34,
+ kEoB2ItemIconShapeData35,
+ kEoB2ItemIconShapeData36,
+ kEoB2ItemIconShapeData37,
+ kEoB2ItemIconShapeData38,
+ kEoB2ItemIconShapeData39,
+ kEoB2ItemIconShapeData40,
+ kEoB2ItemIconShapeData41,
+ kEoB2ItemIconShapeData42,
+ kEoB2ItemIconShapeData43,
+ kEoB2ItemIconShapeData44,
+ kEoB2ItemIconShapeData45,
+ kEoB2ItemIconShapeData46,
+ kEoB2ItemIconShapeData47,
+ kEoB2ItemIconShapeData48,
+ kEoB2ItemIconShapeData49,
+ kEoB2ItemIconShapeData50,
+ kEoB2ItemIconShapeData51,
+ kEoB2ItemIconShapeData52,
+ kEoB2ItemIconShapeData53,
+ kEoB2ItemIconShapeData54,
+ kEoB2ItemIconShapeData55,
+ kEoB2ItemIconShapeData56,
+ kEoB2ItemIconShapeData57,
+ kEoB2ItemIconShapeData58,
+ kEoB2ItemIconShapeData59,
+ kEoB2ItemIconShapeData60,
+ kEoB2ItemIconShapeData61,
+ kEoB2ItemIconShapeData62,
+ kEoB2ItemIconShapeData63,
+ kEoB2ItemIconShapeData64,
+ kEoB2ItemIconShapeData65,
+ kEoB2ItemIconShapeData66,
+ kEoB2ItemIconShapeData67,
+ kEoB2ItemIconShapeData68,
+ kEoB2ItemIconShapeData69,
+ kEoB2ItemIconShapeData70,
+ kEoB2ItemIconShapeData71,
+ kEoB2ItemIconShapeData72,
+ kEoB2ItemIconShapeData73,
+ kEoB2ItemIconShapeData74,
+ kEoB2ItemIconShapeData75,
+ kEoB2ItemIconShapeData76,
+ kEoB2ItemIconShapeData77,
+ kEoB2ItemIconShapeData78,
+ kEoB2ItemIconShapeData79,
+ kEoB2ItemIconShapeData80,
+ kEoB2ItemIconShapeData81,
+ kEoB2ItemIconShapeData82,
+ kEoB2ItemIconShapeData83,
+ kEoB2ItemIconShapeData84,
+ kEoB2ItemIconShapeData85,
+ kEoB2ItemIconShapeData86,
+ kEoB2ItemIconShapeData87,
+ kEoB2ItemIconShapeData88,
+ kEoB2ItemIconShapeData89,
+ kEoB2ItemIconShapeData90,
+ kEoB2ItemIconShapeData91,
+ kEoB2ItemIconShapeData92,
+ kEoB2ItemIconShapeData93,
+ kEoB2ItemIconShapeData94,
+ kEoB2ItemIconShapeData95,
+ kEoB2ItemIconShapeData96,
+ kEoB2ItemIconShapeData97,
+ kEoB2ItemIconShapeData98,
+ kEoB2ItemIconShapeData99,
+ kEoB2ItemIconShapeData100,
+ kEoB2ItemIconShapeData101,
+ kEoB2ItemIconShapeData102,
+ kEoB2ItemIconShapeData103,
+ kEoB2ItemIconShapeData104,
+ kEoB2ItemIconShapeData105,
+ kEoB2ItemIconShapeData106,
+ kEoB2ItemIconShapeData107,
+ kEoB2ItemIconShapeData108,
+ kEoB2ItemIconShapeData109,
+ kEoB2ItemIconShapeData110,
+ kEoB2ItemIconShapeData111,
+
+ kEoB2LargeItemsShapeData00,
+ kEoB2LargeItemsShapeData01,
+ kEoB2LargeItemsShapeData02,
+ kEoB2LargeItemsShapeData03,
+ kEoB2LargeItemsShapeData04,
+ kEoB2LargeItemsShapeData05,
+ kEoB2LargeItemsShapeData06,
+ kEoB2LargeItemsShapeData07,
+ kEoB2LargeItemsShapeData08,
+ kEoB2LargeItemsShapeData09,
+ kEoB2LargeItemsShapeData10,
+
+ kEoB2SmallItemsShapeData00,
+ kEoB2SmallItemsShapeData01,
+ kEoB2SmallItemsShapeData02,
+ kEoB2SmallItemsShapeData03,
+ kEoB2SmallItemsShapeData04,
+ kEoB2SmallItemsShapeData05,
+ kEoB2SmallItemsShapeData06,
+ kEoB2SmallItemsShapeData07,
+ kEoB2SmallItemsShapeData08,
+ kEoB2SmallItemsShapeData09,
+ kEoB2SmallItemsShapeData10,
+ kEoB2SmallItemsShapeData11,
+ kEoB2SmallItemsShapeData12,
+ kEoB2SmallItemsShapeData13,
+ kEoB2SmallItemsShapeData14,
+ kEoB2SmallItemsShapeData15,
+ kEoB2SmallItemsShapeData16,
+ kEoB2SmallItemsShapeData17,
+ kEoB2SmallItemsShapeData18,
+ kEoB2SmallItemsShapeData19,
+ kEoB2SmallItemsShapeData20,
+ kEoB2SmallItemsShapeData21,
+ kEoB2SmallItemsShapeData22,
+ kEoB2SmallItemsShapeData23,
+ kEoB2SmallItemsShapeData24,
+ kEoB2SmallItemsShapeData25,
+
+ kEoB2ThrownShapeData00,
+ kEoB2ThrownShapeData01,
+ kEoB2ThrownShapeData02,
+ kEoB2ThrownShapeData03,
+ kEoB2ThrownShapeData04,
+ kEoB2ThrownShapeData05,
+ kEoB2ThrownShapeData06,
+ kEoB2ThrownShapeData07,
+ kEoB2ThrownShapeData08,
+
+ kEoB2SpellShapeData00,
+ kEoB2SpellShapeData01,
+ kEoB2SpellShapeData02,
+ kEoB2SpellShapeData03,
+
+ kEoB2TeleporterShapeData00,
+ kEoB2TeleporterShapeData01,
+ kEoB2TeleporterShapeData02,
+ kEoB2TeleporterShapeData03,
+ kEoB2TeleporterShapeData04,
+ kEoB2TeleporterShapeData05,
+
+ kEoB2LightningColumnShapeData,
+ kEoB2DeadCharShapeData,
+ kEoB2DisabledCharGridShapeData,
+ kEoB2WeaponSlotGridShapeData,
+ kEoB2SmallGridShapeData,
+ kEoB2WideGridShapeData,
+ kEoB2RedSplatShapeData,
+ kEoB2GreenSplatShapeData,
+
+ kEoB2FirebeamShapeData00,
+ kEoB2FirebeamShapeData01,
+ kEoB2FirebeamShapeData02,
+
+ kEoB2SparkShapeData00,
+ kEoB2SparkShapeData01,
+ kEoB2SparkShapeData02,
+
+ kEoB2CompassShapeData00,
+ kEoB2CompassShapeData01,
+ kEoB2CompassShapeData02,
+ kEoB2CompassShapeData03,
+ kEoB2CompassShapeData04,
+ kEoB2CompassShapeData05,
+ kEoB2CompassShapeData06,
+ kEoB2CompassShapeData07,
+ kEoB2CompassShapeData08,
+ kEoB2CompassShapeData09,
+ kEoB2CompassShapeData10,
+ kEoB2CompassShapeData11,
+
+ kEoB2WallOfForceShapeData00,
+ kEoB2WallOfForceShapeData01,
+ kEoB2WallOfForceShapeData02,
+ kEoB2WallOfForceShapeData03,
+ kEoB2WallOfForceShapeData04,
+ kEoB2WallOfForceShapeData05,
+
+ kEoB2UtilMenuStrings,
+ kEoB2Config2431Strings,
+ kEoB2KatakanaLines,
+ kEoB2KanaSelectStrings,
+ kEoB2FontDmpSearchTbl,
+ kEoB2Ascii2SjisTables,
+ kEoB2Ascii2SjisTables2,
+ kEoB2SaveNamePatterns,
+ kEoB2PcmSoundEffectsIngame,
+ kEoB2PcmSoundEffectsIntro,
+ kEoB2PcmSoundEffectsFinale,
+
kLoLIngamePakFiles,
kLoLCharacterDefs,
kLoLIngameSfxFiles,
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index 365941b1c8..e59eb5d77b 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -29,7 +29,7 @@
#include "graphics/thumbnail.h"
#include "graphics/surface.h"
-#define CURRENT_SAVE_VERSION 17
+#define CURRENT_SAVE_VERSION 18
#define GF_FLOPPY (1 << 0)
#define GF_TALKIE (1 << 1)
diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp
index dca4aaa0f1..0b24ba552d 100644
--- a/engines/kyra/saveload_eob.cpp
+++ b/engines/kyra/saveload_eob.cpp
@@ -38,6 +38,7 @@ namespace Kyra {
Common::Error EoBCoreEngine::loadGameState(int slot) {
// Special slot id -1 for EOB1 party transfer
const char *fileName = (slot == -1) ? _savegameFilename.c_str() : getSavegameFilename(slot);
+ setHandItem(-1);
SaveHeader header;
Common::InSaveFile *saveFile = openSaveForReading(fileName, header, (slot != -1));
@@ -54,7 +55,7 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
EoBCharacter *c = &_characters[i];
c->id = in.readByte();
c->flags = in.readByte();
- in.read(c->name, 11);
+ in.read(c->name, (header.version < 18) ? 11 : 21);
c->strengthCur = in.readSByte();
c->strengthMax = in.readSByte();
c->strengthExtCur = in.readSByte();
@@ -273,6 +274,9 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
}
loadLevel(_currentLevel, _currentSub);
+ if (_flags.platform == Common::kPlatformFMTowns && _gameToLoad != -1)
+ _screen->setScreenPalette(_screen->getPalette(0));
+
_sceneUpdateRequired = true;
_screen->setFont(Screen::FID_6_FNT);
@@ -283,6 +287,9 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
}
}
+ if (!_updateFlags)
+ _screen->fillRect(64, 121, 175, 176, 0, 2);
+
_screen->setCurPage(0);
gui_drawPlayField(false);
@@ -316,6 +323,7 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) {
Common::String saveNameTmp;
const char *fileName = 0;
+ setHandItem(-1);
// Special slot id -1 to create final save for party transfer
if (slot == -1) {
@@ -345,7 +353,7 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName,
out->writeByte(c->id);
out->writeByte(c->flags);
- out->write(c->name, 11);
+ out->write(c->name, 21);
out->writeSByte(c->strengthCur);
out->writeSByte(c->strengthMax);
out->writeSByte(c->strengthExtCur);
@@ -525,6 +533,8 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName,
_gui->notifyUpdateSaveSlotsList();
+ setHandItem(_itemInHand);
+
return Common::kNoError;
}
@@ -636,13 +646,27 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
Common::SeekableSubReadStreamEndian in(fs, 0, fs->size(), _flags.platform == Common::kPlatformAmiga, DisposeAfterUse::YES);
+ // detect source platform
+ Common::Platform sourcePlatform = Common::kPlatformDOS;
+ in.seek(32);
+ uint16 testSJIS = in.readByte();
+ in.seek(53);
+ int8 testStr = in.readSByte();
+ in.seek(66);
+ int8 testChr = in.readSByte();
+ in.seek(0);
+ if (testStr >= 0 && testStr <= 25 && testChr >= 0 && testChr <= 25) {
+ if (testSJIS >= 0xE0 || (testSJIS > 0x80 && testSJIS < 0xA0))
+ sourcePlatform = Common::kPlatformFMTowns;
+ }
+
if (_flags.gameID == GI_EOB1) {
// Nothing to read here for EOB 1. Original EOB 1 has
// only one save slot without save file description.
desc = "<IMPORTED GAME>";
} else {
- char tempStr[20];
- in.read(tempStr, 20);
+ char tempStr[30];
+ in.read(tempStr, sourcePlatform == Common::kPlatformFMTowns ? 30 : 20);
desc = tempStr;
}
@@ -650,7 +674,9 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
EoBCharacter *c = &_characters[i];
c->id = in.readByte();
c->flags = in.readByte();
- in.read(c->name, 11);
+ in.read(c->name, sourcePlatform == Common::kPlatformFMTowns ? 21 : 11);
+ if (_flags.platform != sourcePlatform)
+ c->name[10] = '\0';
c->strengthCur = in.readSByte();
c->strengthMax = in.readSByte();
c->strengthExtCur = in.readSByte();
@@ -696,7 +722,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
c->effectFlags = in.readUint32();
if (c->effectFlags && _flags.gameID == GI_EOB1) {
// Spell effect flags are completely different in EOB I. We only use EOB II style flags in ScummVM.
- // Doesn't matter much, since these are the temporary spell effects only anyway.
+ // Doesn't matter much, since these are only temporary spell effects.
warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled character effect flags encountered in original EOB1 save file '%s' ('%s')", file.c_str(), desc.c_str());
c->effectFlags = 0;
}
@@ -716,13 +742,13 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
_partyEffectFlags = (_flags.gameID == GI_EOB1) ? in.readUint16() : in.readUint32();
if (_partyEffectFlags && _flags.gameID == GI_EOB1) {
// Spell effect flags are completely different in EOB I. We only use EOB II style flags in ScummVM.
- // Doesn't matter much, since these are the temporary spell effects only anyway.
+ // Doesn't matter much, since these are only temporary spell effects.
warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled party effect flags encountered in original EOB1 save file '%s' ('%s')", file.c_str(), desc.c_str());
_partyEffectFlags = 0;
}
if (_flags.gameID == GI_EOB2)
in.skip(1);
-
+
_inf->loadState(in, true);
int numItems = (_flags.gameID == GI_EOB1) ? 500 : 600;
@@ -742,7 +768,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
}
int numParts = (_flags.gameID == GI_EOB1) ? 12 : 17;
- int partSize = (_flags.gameID == GI_EOB1) ? 2040 : 2130;
+ int partSize = (sourcePlatform == Common::kPlatformFMTowns) ? 5030 : (_flags.gameID == GI_EOB1 ? 2040 : 2130);
uint32 nextPart = in.pos();
uint8 *cmpData = new uint8[1200];
@@ -777,8 +803,12 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
memset(lw, 0, 5 * sizeof(WallOfForce));
l->wallsOfForce = lw;
- in.read(cmpData, 1200);
- _screen->decodeFrame4(cmpData, l->wallsXorData, 4096);
+ if (sourcePlatform == Common::kPlatformFMTowns) {
+ in.read(l->wallsXorData, 4096);
+ } else {
+ in.read(cmpData, 1200);
+ _screen->decodeFrame4(cmpData, l->wallsXorData, 4096);
+ }
_curBlockFile = getBlockFileName(i + 1, 0);
const uint8 *p = getBlockFileData();
uint16 len = READ_LE_UINT16(p + 4);
@@ -790,6 +820,9 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
*d++ ^= p[ii * len + iii];
}
+ if (sourcePlatform == Common::kPlatformFMTowns)
+ in.skip(4);
+
for (int ii = 0; ii < 30; ii++) {
EoBMonsterInPlay *m = &lm[ii];
m->type = in.readByte();
@@ -998,8 +1031,8 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
Common::OutSaveFile *out = new Common::OutSaveFile(nf.createWriteStream());
if (_flags.gameID == GI_EOB2) {
- static const char tempStr[20] = "SCUMMVM EXPORT ";
- out->write(tempStr, 20);
+ static const char tempStr[31] = "SCUMMVM EXPORT ";
+ out->write(tempStr, (_flags.platform == Common::kPlatformFMTowns) ? 30 : 20);
}
completeDoorOperations();
@@ -1014,7 +1047,7 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
EoBCharacter *c = &_characters[i];
out->writeByte(c->id);
out->writeByte(c->flags);
- out->write(c->name, 11);
+ out->write(c->name, (_flags.platform == Common::kPlatformFMTowns) ? 21 : 11);
out->writeSByte(c->strengthCur);
out->writeSByte(c->strengthMax);
out->writeSByte(c->strengthExtCur);
@@ -1110,13 +1143,14 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
}
int numParts = (_flags.gameID == GI_EOB1) ? 12 : 17;
- int partSize = (_flags.gameID == GI_EOB1) ? 2040 : 2130;
- uint8 *tempData = new uint8[4096];
+ int partSize = (_flags.platform == Common::kPlatformFMTowns) ? 5030 :(_flags.gameID == GI_EOB1) ? 2040 : 2130;
+
+ uint8 *tempData = new uint8[5030];
uint8 *cmpData = new uint8[1200];
for (int i = 0; i < numParts; i++) {
LevelTempData *l = _lvlTempData[i];
- memset(tempData, 0, 4096);
+ memset(tempData, 0, 5030);
memset(cmpData, 0, 1200);
if (!l || !(_hasTempDataFlags & (1 << i))) {
@@ -1135,11 +1169,18 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
*d++ = l->wallsXorData[ii * len + iii] ^ p[ii * len + iii];
}
- uint32 outsize = encodeFrame4(tempData, cmpData, 4096);
- if (outsize > 1200)
- error("Map compression failure: size of map = %d", outsize);
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ out->write(tempData, 4096);
+ } else {
+ uint32 outsize = encodeFrame4(tempData, cmpData, 4096);
+ if (outsize > 1200)
+ error("Map compression failure: size of map = %d", outsize);
+
+ out->write(cmpData, 1200);
+ }
- out->write(cmpData, 1200);
+ if (_flags.platform == Common::kPlatformFMTowns)
+ out->writeUint32BE(0);
for (int ii = 0; ii < 30; ii++) {
EoBMonsterInPlay *m = &((EoBMonsterInPlay*)l->monsters)[ii];
diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp
index 6fac56f12c..c19f102e03 100644
--- a/engines/kyra/scene_eob.cpp
+++ b/engines/kyra/scene_eob.cpp
@@ -36,6 +36,8 @@ namespace Kyra {
void EoBCoreEngine::loadLevel(int level, int sub) {
_currentLevel = level;
_currentSub = sub;
+ if (!_loading)
+ setHandItem(-1);
uint32 end = _system->getMillis() + 500;
readLevelFileData(level);
@@ -99,12 +101,13 @@ void EoBCoreEngine::loadLevel(int level, int sub) {
_sceneDrawPage1 = 2;
_sceneDrawPage2 = 1;
_screen->setCurPage(0);
+ setHandItem(_itemInHand);
}
void EoBCoreEngine::readLevelFileData(int level) {
Common::String file;
Common::SeekableReadStream *s = 0;
- static const char *const suffix[] = { "INF", "DRO", "ELO", 0 };
+ static const char *const suffix[] = { "INF", "DRO", "ELO", "JOT", 0 };
for (const char *const *sf = suffix; *sf && !s; sf++) {
file = Common::String::format("LEVEL%d.%s", level, *sf);
@@ -112,7 +115,7 @@ void EoBCoreEngine::readLevelFileData(int level) {
}
if (!s)
- error("Failed to load level file LEVEL%d.INF/DRO/ELO", level);
+ error("Failed to load level file LEVEL%d.INF/DRO/ELO/JOT", level);
if (s->readUint16LE() + 2 == s->size()) {
if (s->readUint16LE() == 4) {
@@ -148,7 +151,7 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
const char *vmpPattern = (_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.EMP" : "%s.VMP";
Common::SeekableReadStream *s = _res->createReadStream(Common::String::format(vmpPattern, (const char *)pos));
- uint16 size = s->readUint16LE();
+ uint16 size = (_flags.platform == Common::kPlatformFMTowns) ? 2916 : s->readUint16LE();
delete[] _vmpPtr;
_vmpPtr = new uint16[size];
for (int i = 0; i < size; i++)
@@ -175,7 +178,15 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
if (_flags.gameID == GI_EOB2 || _configRenderMode != Common::kRenderEGA)
_screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0));
- if (_configRenderMode != Common::kRenderCGA) {
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ uint16 *src = (uint16*)_screen->getPalette(0).getData();
+ _screen->createFadeTable16bit(src, (uint16*)_greenFadingTable, 4, 75);
+ _screen->createFadeTable16bit(src, (uint16*)_blackFadingTable, 12, 200);
+ _screen->createFadeTable16bit(src, (uint16*)_blueFadingTable, 10, 85);
+ _screen->createFadeTable16bit(src, (uint16*)_lightBlueFadingTable, 11, 125);
+ _screen->createFadeTable16bit(src, (uint16*)_greyFadingTable, 0, 85);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ } else if (_configRenderMode != Common::kRenderCGA) {
Palette backupPal(256);
backupPal.copy(_screen->getPalette(0), 224, 32, 224);
_screen->getPalette(0).fill(224, 32, 0x3F);
@@ -283,7 +294,14 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
if (file)
strcpy(_lastBlockDataFile, file);
- const char *filePattern = (_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.ECN" : "%s.VCN";
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ uint32 size;
+ delete[] _vcnBlocks;
+ _vcnBlocks = _res->fileData(Common::String::format("%s.VCC", _lastBlockDataFile).c_str(), &size);
+ return;
+ }
+
+ const char *filePattern = ((_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.ECN" : "%s.VCN");
_screen->loadBitmap(Common::String::format(filePattern, _lastBlockDataFile).c_str(), 3, 3, 0);
const uint8 *pos = _screen->getCPagePtr(3);
diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp
index a746080190..c1579c3501 100644
--- a/engines/kyra/scene_lol.cpp
+++ b/engines/kyra/scene_lol.cpp
@@ -1425,7 +1425,7 @@ void LoLEngine::drawSceneShapes(int) {
if (!(w & 8))
continue;
- uint16 v = 20 * (s - (s < 23 ? _dscUnk2[s] : 0));
+ uint16 v = 20 * (s - (s < 23 ? _dscDoorScaleOffs[s] : 0));
if (v > 80)
v = 80;
diff --git a/engines/kyra/scene_rpg.cpp b/engines/kyra/scene_rpg.cpp
index dabc368a27..756f694a36 100644
--- a/engines/kyra/scene_rpg.cpp
+++ b/engines/kyra/scene_rpg.cpp
@@ -348,6 +348,7 @@ bool KyraRpgEngine::checkSceneUpdateNeed(int block) {
void KyraRpgEngine::drawVcnBlocks() {
uint8 *d = _sceneWindowBuffer;
uint16 *bdb = _blockDrawingBuffer;
+ uint16 *hiColorPal = screen()->get16bitPalette();
for (int y = 0; y < 15; y++) {
for (int x = 0; x < 22; x++) {
@@ -369,9 +370,9 @@ void KyraRpgEngine::drawVcnBlocks() {
vcnOffset &= 0x3FFF;
}
- uint8 *src = 0;
+ const uint8 *src = 0;
if (vcnOffset) {
- src = &_vcnBlocks[vcnOffset << 5];
+ src = &_vcnBlocks[vcnOffset << (4 + _vcnBpp)];
wllVcnOffset = _wllVcnOffset;
} else {
// floor/ceiling blocks
@@ -381,36 +382,46 @@ void KyraRpgEngine::drawVcnBlocks() {
vcnOffset &= 0x3FFF;
}
- src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset << 5);
+ src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset << (4 + _vcnBpp));
}
uint8 shift = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness;
if (horizontalFlip) {
for (int blockY = 0; blockY < 8; blockY++) {
- src += 3;
- for (int blockX = 0; blockX < 4; blockX++) {
- uint8 bl = *src--;
- *d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift];
- *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];
+ src += ((_vcnBpp << 2) - 1);
+ for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+ if (_vcnBpp == 2) {
+ *(uint16*)d = hiColorPal[*src--];
+ d += 2;
+ } else {
+ uint8 bl = *src--;
+ *d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift];
+ *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];
+ }
}
- src += 5;
- d += 168;
+ src += ((_vcnBpp << 2) + 1);
+ d += 168 * _vcnBpp;
}
} else {
for (int blockY = 0; blockY < 8; blockY++) {
- for (int blockX = 0; blockX < 4; blockX++) {
- uint8 bl = *src++;
- *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];
- *d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift];
+ for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+ if (_vcnBpp == 2) {
+ *(uint16*)d = hiColorPal[*src++];
+ d += 2;
+ } else {
+ uint8 bl = *src++;
+ *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];
+ *d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift];
+ }
}
- d += 168;
+ d += 168 * _vcnBpp;
}
}
- d -= 1400;
+ d -= 1400 * _vcnBpp;
if (vcnExtraOffsetWll) {
- d -= 8;
+ d -= 8 * _vcnBpp;
horizontalFlip = false;
if (vcnExtraOffsetWll & 0x4000) {
@@ -419,62 +430,76 @@ void KyraRpgEngine::drawVcnBlocks() {
}
shift = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness;
- src = &_vcnBlocks[vcnExtraOffsetWll << 5];
+ src = &_vcnBlocks[vcnExtraOffsetWll << (4 + _vcnBpp)];
uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll << 5] : 0;
if (horizontalFlip) {
for (int blockY = 0; blockY < 8; blockY++) {
- src += 3;
+ src += ((_vcnBpp << 2) - 1);
maskTable += 3;
- for (int blockX = 0; blockX < 4; blockX++) {
- uint8 bl = *src--;
- uint8 mask = _vcnTransitionMask ? *maskTable-- : 0;
- uint8 h = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift];
- uint8 l = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];
-
- if (_vcnTransitionMask)
- *d = (*d & (mask & 0x0F)) | h;
- else if (h)
- *d = h;
- d++;
-
- if (_vcnTransitionMask)
- *d = (*d & (mask >> 4)) | l;
- else if (l)
- *d = l;
- d++;
+ for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+ if (_vcnBpp == 2) {
+ uint8 bl = *src--;
+ if (bl)
+ *(uint16*)d = hiColorPal[bl];
+ d += 2;
+ } else {
+ uint8 bl = *src--;
+ uint8 mask = _vcnTransitionMask ? *maskTable-- : 0;
+ uint8 h = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift];
+ uint8 l = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];
+
+ if (_vcnTransitionMask)
+ *d = (*d & (mask & 0x0F)) | h;
+ else if (h)
+ *d = h;
+ d++;
+
+ if (_vcnTransitionMask)
+ *d = (*d & (mask >> 4)) | l;
+ else if (l)
+ *d = l;
+ d++;
+ }
}
- src += 5;
+ src += ((_vcnBpp << 2) + 1);
maskTable += 5;
- d += 168;
+ d += 168 * _vcnBpp;
}
} else {
for (int blockY = 0; blockY < 8; blockY++) {
- for (int blockX = 0; blockX < 4; blockX++) {
- uint8 bl = *src++;
- uint8 mask = _vcnTransitionMask ? *maskTable++ : 0;
- uint8 h = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];
- uint8 l = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift];
-
- if (_vcnTransitionMask)
- *d = (*d & (mask >> 4)) | h;
- else if (h)
- *d = h;
- d++;
-
- if (_vcnTransitionMask)
- *d = (*d & (mask & 0x0F)) | l;
- else if (l)
- *d = l;
- d++;
+ for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+ if (_vcnBpp == 2) {
+ uint8 bl = *src++;
+ if (bl)
+ *(uint16*)d = hiColorPal[bl];
+ d += 2;
+ } else {
+ uint8 bl = *src++;
+ uint8 mask = _vcnTransitionMask ? *maskTable++ : 0;
+ uint8 h = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];
+ uint8 l = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift];
+
+ if (_vcnTransitionMask)
+ *d = (*d & (mask >> 4)) | h;
+ else if (h)
+ *d = h;
+ d++;
+
+ if (_vcnTransitionMask)
+ *d = (*d & (mask & 0x0F)) | l;
+ else if (l)
+ *d = l;
+ d++;
+ }
}
- d += 168;
+ d += 168 * _vcnBpp;
}
}
- d -= 1400;
+ d -= 1400 * _vcnBpp;
}
}
- d += 1232;
+ d += 1232 * _vcnBpp;
}
screen()->copyBlockToPage(_sceneDrawPage1, _sceneXoffset, 0, 176, 120, _sceneWindowBuffer);
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index a0cab913b9..eb9ba016bd 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -739,10 +739,13 @@ void Screen::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc,
}
}
-uint8 Screen::getPagePixel(int pageNum, int x, int y) {
+int Screen::getPagePixel(int pageNum, int x, int y) {
assert(pageNum < SCREEN_PAGE_NUM);
assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H);
- return _pagePtrs[pageNum][y * SCREEN_W + x];
+ if (_bytesPerPixel == 1)
+ return _pagePtrs[pageNum][y * SCREEN_W + x];
+ else
+ return ((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x];
}
void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {
@@ -762,7 +765,7 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {
}
if (_bytesPerPixel == 2) {
- *(uint16*)(&_pagePtrs[pageNum][y * SCREEN_W * 2 + x * 2]) = _16bitPalette[color];
+ ((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x] = _16bitPalette[color];
} else {
_pagePtrs[pageNum][y * SCREEN_W + x] = color;
}
@@ -781,12 +784,12 @@ void Screen::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
}
void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) {
- if (_renderMode == Common::kRenderEGA)
+ if (_renderMode == Common::kRenderEGA || _bytesPerPixel == 2)
setScreenPalette(pal);
updateScreen();
- if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA)
+ if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA || _bytesPerPixel == 2)
return;
int diff = 0, delayInc = 0;
@@ -1056,7 +1059,7 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *dest) {
if (y < 0) {
- dest += (-y) * w;
+ dest += (-y) * w * _bytesPerPixel;
h += y;
y = 0;
} else if (y + h > SCREEN_H) {
@@ -1064,7 +1067,7 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *
}
if (x < 0) {
- dest += -x;
+ dest += -x * _bytesPerPixel;
w += x;
x = 0;
} else if (x + w > SCREEN_W) {
@@ -1093,7 +1096,7 @@ void Screen::copyPage(uint8 srcPage, uint8 dstPage) {
void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint8 *src) {
if (y < 0) {
- src += (-y) * w;
+ src += (-y) * w * _bytesPerPixel;
h += y;
y = 0;
} else if (y + h > SCREEN_H) {
@@ -1101,7 +1104,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
}
if (x < 0) {
- src += -x;
+ src += -x * _bytesPerPixel;
w += x;
x = 0;
} else if (x + w > SCREEN_W) {
@@ -1398,7 +1401,7 @@ int Screen::getFontWidth() const {
int Screen::getCharWidth(uint16 c) const {
const int width = _fonts[_currentFont]->getCharWidth(c);
- return width + ((_currentFont != FID_SJIS_FNT) ? _charWidth : 0);
+ return width + ((_currentFont != FID_SJIS_FNT && _currentFont != FID_SJIS_LARGE_FNT && _currentFont != FID_SJIS_SMALL_FNT) ? _charWidth : 0);
}
int Screen::getTextWidth(const char *str) {
@@ -1408,8 +1411,8 @@ int Screen::getTextWidth(const char *str) {
FontId curFont = _currentFont;
while (1) {
- if (_sjisMixedFontMode)
- setFont((*str & 0x80) ? FID_SJIS_FNT : curFont);
+ if (_sjisMixedFontMode && curFont != FID_SJIS_FNT && curFont != FID_SJIS_LARGE_FNT && curFont != FID_SJIS_SMALL_FNT)
+ setFont((*str & 0x80) ? ((_vm->game() == GI_EOB2 && curFont == FID_6_FNT) ? FID_SJIS_SMALL_FNT : FID_SJIS_FNT) : curFont);
uint c = fetchChar(str);
@@ -1455,8 +1458,8 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
return;
while (1) {
- if (_sjisMixedFontMode)
- setFont((*str & 0x80) ? FID_SJIS_FNT : curFont);
+ if (_sjisMixedFontMode && curFont != FID_SJIS_FNT && curFont != FID_SJIS_LARGE_FNT && curFont != FID_SJIS_SMALL_FNT)
+ setFont((*str & 0x80) ? ((_vm->game() == GI_EOB2 && curFont == FID_6_FNT) ? FID_SJIS_SMALL_FNT : FID_SJIS_FNT) : curFont);
uint8 charHeightFnt = getFontHeight();
@@ -1483,7 +1486,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
}
uint16 Screen::fetchChar(const char *&s) const {
- if (_currentFont != FID_SJIS_FNT)
+ if (_currentFont != FID_SJIS_FNT && _currentFont != FID_SJIS_LARGE_FNT && _currentFont != FID_SJIS_SMALL_FNT)
return (uint8)*s++;
uint16 ch = (uint8)*s++;
@@ -1515,7 +1518,7 @@ void Screen::drawChar(uint16 c, int x, int y) {
return;
}
- int bpp = (_currentFont == Screen::FID_SJIS_FNT) ? 1 : 2;
+ int bpp = (_currentFont == Screen::FID_SJIS_FNT || _currentFont == Screen::FID_SJIS_SMALL_FNT) ? 1 : 2;
destPage += (y * 2) * 640 * bpp + (x * 2 * bpp);
fnt->drawChar(c, destPage, 640, bpp);
@@ -3472,7 +3475,7 @@ void Screen::copyOverlayRegion(int x, int y, int x2, int y2, int w, int h, int s
while (h--) {
for (x = 0; x < w; ++x)
- memcpy(dst, src, w);
+ memmove(dst, src, w);
dst += 640;
src += 640;
}
@@ -3486,7 +3489,7 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s
hideMouse();
uint16 *wB = (uint16 *)_pagePtrs[14];
- uint8 *hB = _pagePtrs[14] + 640;
+ uint8 *hB = _pagePtrs[14] + 640 * _bytesPerPixel;
for (int i = 0; i < w; i++)
wB[i] = i;
@@ -3515,7 +3518,10 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s
if (++iH >= h)
iH = 0;
- d[dY * 320 + dX] = s[sY * 320 + sX];
+ if (_bytesPerPixel == 2)
+ ((uint16*)d)[dY * 320 + dX] = ((uint16*)s)[sY * 320 + sX];
+ else
+ d[dY * 320 + dX] = s[sY * 320 + sX];
addDirtyRect(dX, dY, 1, 1);
}
@@ -3815,16 +3821,6 @@ void SJISFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
_font->drawChar(dst, c, 640, 1, color1, color2, 640, 400);
}
-SJISFontLarge::SJISFontLarge(Graphics::FontSJIS *font) : SJISFont(font, 0, false, false, false, 0) {
- _sjisWidth = _font->getMaxFontWidth();
- _fontHeight = _font->getFontHeight();
- _asciiWidth = _font->getCharWidth('a');
-}
-
-void SJISFontLarge::drawChar(uint16 c, byte *dst, int pitch) const {
- _font->drawChar(dst, c, 320, 1, _colorMap[1], _colorMap[0], 320, 200);
-}
-
#pragma mark -
Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) {
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index bac93ae49c..44113e4372 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -145,10 +145,10 @@ private:
#ifdef ENABLE_EOB
/**
- * Implementation of the Font interface for old DOS fonts used
- * in EOB and EOB II.
- *
- */
+* Implementation of the Font interface for old DOS fonts used
+* in EOB and EOB II.
+*
+*/
class OldDOSFont : public Font {
public:
OldDOSFont(Common::RenderMode mode);
@@ -250,18 +250,6 @@ private:
};
/**
-* SJISFont variant used in the intro and outro of EOB II FM-Towns. It appears twice as large, since it is not rendered on the hires overlay pages
-*/
-class SJISFontLarge : public SJISFont {
-public:
- SJISFontLarge(Graphics::FontSJIS *font);
- virtual ~SJISFontLarge() { unload(); }
-
- virtual bool usesOverlay() const { return false; }
- virtual void drawChar(uint16 c, byte *dst, int pitch) const;
-};
-
-/**
* A class that manages KYRA palettes.
*
* This class stores the palette data as VGA RGB internally.
@@ -426,6 +414,7 @@ public:
FID_INTRO_FNT,
FID_SJIS_FNT,
FID_SJIS_LARGE_FNT,
+ FID_SJIS_SMALL_FNT,
FID_NUM
};
@@ -466,7 +455,7 @@ public:
void clearPage(int pageNum);
- uint8 getPagePixel(int pageNum, int x, int y);
+ int getPagePixel(int pageNum, int x, int y);
void setPagePixel(int pageNum, int x, int y, uint8 color);
const uint8 *getCPagePtr(int pageNum) const;
@@ -499,7 +488,7 @@ public:
void drawBox(int x1, int y1, int x2, int y2, int color);
// font/text handling
- bool loadFont(FontId fontId, const char *filename);
+ virtual bool loadFont(FontId fontId, const char *filename);
FontId setFont(FontId fontId);
int getFontHeight() const;
@@ -584,6 +573,7 @@ public:
// RPG specific, this does not belong here
void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
+ uint16 *get16bitPalette() { return _16bitPalette; }
void set16bitShadingLevel(int lvl) { _16bitShadingLevel = lvl; }
protected:
diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp
index 88c53fdb7b..e24f6219a9 100644
--- a/engines/kyra/screen_eob.cpp
+++ b/engines/kyra/screen_eob.cpp
@@ -34,6 +34,7 @@
#include "graphics/cursorman.h"
#include "graphics/palette.h"
+#include "graphics/sjis.h"
namespace Kyra {
@@ -46,7 +47,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,
_gfxX = _gfxY = 0;
_gfxCol = 0;
_dsTempPage = 0;
- _convertHiColorBuffer = 0;
+ _shpBuffer = _convertHiColorBuffer = 0;
_dsDiv = 0;
_dsRem = 0;
_dsScaleTrans = 0;
@@ -61,6 +62,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,
Screen_EoB::~Screen_EoB() {
delete[] _dsTempPage;
+ delete[] _shpBuffer;
delete[] _convertHiColorBuffer;
delete[] _cgaScaleTable;
delete[] _egaDitheringTable;
@@ -73,12 +75,21 @@ bool Screen_EoB::init() {
if (Screen::init()) {
int temp;
_gfxMaxY = _vm->staticres()->loadRawData(kEoBBaseExpObjectY, temp);
-
_dsTempPage = new uint8[12000];
if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ _shpBuffer = new uint8[SCREEN_H * SCREEN_W];
_convertHiColorBuffer = new uint8[SCREEN_H * SCREEN_W];
+ enableHiColorMode(true);
+
+ Graphics::FontSJIS *font = Graphics::FontSJIS::createFont(Common::kPlatformFMTowns);
+ if (!font)
+ error("Could not load any SJIS font, neither the original nor ScummVM's 'SJIS.FNT'");
+ _fonts[FID_SJIS_LARGE_FNT] = new SJISFontLarge(font);
+
+ loadFont(FID_SJIS_SMALL_FNT, "FONT.DMP");
}
+
if (_vm->gameFlags().useHiRes && _renderMode == Common::kRenderEGA) {
_useHiResEGADithering = true;
_egaDitheringTable = new uint8[256];
@@ -124,19 +135,28 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
int mouseH = (shape[3]);
int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : _cursorColorKey;
- int scaleFactor = _useHiResEGADithering ? 2 : 1;
+ int scaleFactor = _vm->gameFlags().useHiRes ? 2 : 1;
int bpp = _useHiColorScreen ? 2 : 1;
uint8 *cursor = new uint8[mouseW * scaleFactor * bpp * mouseH * scaleFactor];
- // We use memset and copyBlockToPage instead of fillRect to make sure that the
- // color key 0xFF doesn't get converted into EGA color
- memset(cursor, colorKey, mouseW * scaleFactor * bpp * mouseH * scaleFactor);
+
+ if (_bytesPerPixel == 2) {
+ colorKey = _16bitPalette[colorKey];
+ for (int s = mouseW * scaleFactor * bpp * mouseH * scaleFactor; s; s -= 2)
+ *(uint16*)(cursor + s - 2) = colorKey;
+ } else {
+ // We don't use fillRect here to make sure that the color key 0xFF doesn't get converted into EGA color
+ memset(cursor, colorKey, mouseW * scaleFactor * bpp * mouseH * scaleFactor);
+ }
+
copyBlockToPage(6, 0, 0, mouseW * scaleFactor, mouseH * scaleFactor, cursor);
drawShape(6, shape, 0, 0, 0, 2, ovl);
CursorMan.showMouse(false);
if (_useHiResEGADithering)
ditherRect(getCPagePtr(6), cursor, mouseW * scaleFactor, mouseW, mouseH, colorKey);
+ else if (_vm->gameFlags().useHiRes)
+ scale2x(cursor, mouseW * scaleFactor, getCPagePtr(6), SCREEN_W, mouseW, mouseH);
else
copyRegionToBuffer(6, 0, 0, mouseW, mouseH, cursor);
@@ -185,9 +205,13 @@ void Screen_EoB::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum,
}
void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int col2) {
- printText(string, x - 1, y, 12, col2);
- printText(string, x, y + 1, 12, 0);
- printText(string, x - 1, y + 1, 12, 0);
+ if (_vm->gameFlags().platform != Common::kPlatformFMTowns) {
+ printText(string, x - 1, y, 12, col2);
+ printText(string, x, y + 1, 12, 0);
+ printText(string, x - 1, y + 1, 12, 0);
+ } else if (col2) {
+ fillRect(x, y, x + getTextWidth(string) - 1, y + getFontHeight() - 1, col2);
+ }
printText(string, x, y, col1, 0);
}
@@ -197,22 +221,28 @@ void Screen_EoB::loadShapeSetBitmap(const char *file, int tempPage, int destPage
}
void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage) {
- const char *filePattern = (_vm->game() == GI_EOB1 && (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA)) ? "%s.EGA" : "%s.CPS";
+ const char *filePattern = _vm->gameFlags().platform == Common::kPlatformFMTowns ? "%s.SHP" : ((_vm->game() == GI_EOB1 && (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA)) ? "%s.EGA" : "%s.CPS");
Common::String tmp = Common::String::format(filePattern, file);
Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp);
bool loadAlternative = false;
- if (s) {
+
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ if (!s)
+ error("Screen_EoB::loadEoBBitmap(): Failed to load file '%s'", file);
+ s->read(_shpBuffer, s->size());
+ decodeSHP(_shpBuffer, destPage);
+ } else if (s) {
// This additional check is necessary since some localized versions of EOB II seem to contain invalid (size zero) cps files
if (s->size())
loadBitmap(tmp.c_str(), tempPage, destPage, 0);
else
loadAlternative = true;
-
- delete s;
} else {
loadAlternative = true;
}
+ delete s;
+
if (loadAlternative) {
if (_vm->game() == GI_EOB1) {
tmp.insertChar('1', tmp.size() - 4);
@@ -279,7 +309,7 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping)
void Screen_EoB::setScreenPalette(const Palette &pal) {
if (_bytesPerPixel == 2) {
for (int i = 0; i < 4; i++)
- createFadeTable16bit((const uint16*)(pal.getData()), &_16bitPalette[i * 256], 0, i * 53);
+ createFadeTable16bit((const uint16*)(pal.getData()), &_16bitPalette[i * 256], 0, i * 85);
}else if (_useHiResEGADithering && pal.getNumColors() != 16) {
generateEGADitheringTable(pal);
} else if (_renderMode == Common::kRenderEGA && pal.getNumColors() == 16) {
@@ -315,7 +345,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco
if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)
encode8bit = false;
- if (_bytesPerPixel == 2) {
+ if (_bytesPerPixel == 2 && encode8bit) {
shapesize = h * (w << 3) + 4;
shp = new uint8[shapesize];
memset(shp, 0, shapesize);
@@ -890,6 +920,12 @@ const uint8 *Screen_EoB::generateShapeOverlay(const uint8 *shp, const uint8 *fad
if (*shp != 2)
return 0;
+ if (_bytesPerPixel == 2) {
+ setFadeTable(fadingTable);
+ setShapeFadingLevel(1);
+ return 0;
+ }
+
shp += 4;
for (int i = 0; i < 16; i++)
_shapeOverlay[i] = fadingTable[shp[i]];
@@ -963,8 +999,12 @@ void Screen_EoB::drawExplosion(int scale, int radius, int numElements, int stepS
int16 py = ((ptr3[i] >> 6) >> scale) + gy2;
if (py > ymax)
py = ymax;
- if (posWithinRect(px, py, rX1, rY1, rX2, rY2))
- setPagePixel(0, px, py, ptr6[i]);
+ if (posWithinRect(px, py, rX1, rY1, rX2, rY2)) {
+ if (_bytesPerPixel == 2)
+ setPagePixel16bit(0, px, py, ptr6[i]);
+ else
+ setPagePixel(0, px, py, ptr6[i]);
+ }
}
}
@@ -1094,7 +1134,10 @@ void Screen_EoB::drawVortex(int numElements, int radius, int stepSize, int, int
for (int ii = numElements - 1; ii >= 0; ii--) {
int16 px = CLIP((xCoords[ii] >> 6) + cx, 0, SCREEN_W - 1);
int16 py = CLIP((yCoords[ii] >> 6) + cy, 0, SCREEN_H - 1);
- setPagePixel(0, px, py, pixBackup[ii]);
+ if (_bytesPerPixel == 2)
+ setPagePixel16bit(0, px, py, pixBackup[ii]);
+ else
+ setPagePixel(0, px, py, pixBackup[ii]);
}
}
@@ -1219,6 +1262,8 @@ int Screen_EoB::getRectSize(int w, int h) {
void Screen_EoB::setFadeTable(const uint8 *table) {
_dsShapeFadingTable = table;
+ if (_bytesPerPixel == 2)
+ memcpy(&_16bitPalette[0x100], table, 512);
}
void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
@@ -1265,6 +1310,7 @@ void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootCol
}
void Screen_EoB::createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight) {
+ rootColor = palData[rootColor];
uint8 r8 = (rootColor & 0x1f);
uint8 g8 = (rootColor & 0x3E0) >> 5;
uint8 b8 = (rootColor & 0x7C00) >> 10;
@@ -1320,7 +1366,6 @@ void Screen_EoB::createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16
*dst++ = (b8 << 10) | (g8 << 5) | r8;
}
-
}
const uint16 *Screen_EoB::getCGADitheringTable(int index) {
@@ -1331,10 +1376,69 @@ const uint8 *Screen_EoB::getEGADitheringTable() {
return _egaDitheringTable;
}
+bool Screen_EoB::loadFont(FontId fontId, const char *filename) {
+ if (scumm_stricmp(filename, "FONT.DMP"))
+ return Screen::loadFont(fontId, filename);
+
+ Font *&fnt = _fonts[fontId];
+ int temp;
+
+ const uint16 *tbl = _vm->staticres()->loadRawDataBe16(kEoB2FontDmpSearchTbl, temp);
+ assert(tbl);
+
+ if (!fnt) {
+ fnt = new SJISFont12x12(tbl);
+ assert(fnt);
+ }
+
+ Common::SeekableReadStream *file = _vm->resource()->createReadStream(filename);
+ if (!file)
+ error("Font file '%s' is missing", filename);
+
+ bool ret = fnt->load(*file);
+ fnt->setColorMap(_textColorsMap);
+ delete file;
+ return ret;
+}
+
+void Screen_EoB::decodeSHP(const uint8 *data, int dstPage) {
+ int32 bytesLeft = READ_LE_UINT32(data);
+ const uint8 *src = data + 4;
+ uint8 *dst = getPagePtr(dstPage);
+
+ if (bytesLeft < 0) {
+ memcpy(dst, data, 64000);
+ return;
+ }
+
+ while (bytesLeft > 0) {
+ uint8 code = *src++;
+ bytesLeft--;
+
+ for (int i = 8; i; i--) {
+ if (code & 0x80) {
+ uint16 copyOffs = (src[0] << 4) | (src[1] >> 4);
+ uint8 count = (src[1] & 0x0F) + 3;
+ src += 2;
+ bytesLeft -= 2;
+ const uint8 *copySrc = dst - 1 - copyOffs;
+ while (count--)
+ *dst++ = *copySrc++;
+ } else if (bytesLeft) {
+ *dst++ = *src++;
+ bytesLeft--;
+ } else {
+ break;
+ }
+ code <<= 1;
+ }
+ }
+}
+
void Screen_EoB::convertToHiColor(int page) {
if (!_16bitPalette)
return;
- uint16 *dst = (uint16 *)getCPagePtr(page);
+ uint16 *dst = (uint16 *)getPagePtr(page);
memcpy(_convertHiColorBuffer, dst, SCREEN_H * SCREEN_W);
uint8 *src = _convertHiColorBuffer;
for (int s = SCREEN_H * SCREEN_W; s; --s)
@@ -1483,6 +1587,17 @@ bool Screen_EoB::posWithinRect(int posX, int posY, int x1, int y1, int x2, int y
return true;
}
+void Screen_EoB::setPagePixel16bit(int pageNum, int x, int y, uint16 color) {
+ assert(pageNum < SCREEN_PAGE_NUM);
+ assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H);
+ assert(_bytesPerPixel == 2);
+
+ if (pageNum == 0 || pageNum == 1)
+ addDirtyRect(x, y, 1, 1);
+
+ ((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x] = color;
+}
+
void Screen_EoB::generateEGADitheringTable(const Palette &pal) {
assert(_egaDitheringTable);
const uint8 *src = pal.getData();
@@ -1795,6 +1910,66 @@ void OldDOSFont::unload() {
_bitmapOffsets = 0;
}
+SJISFontLarge::SJISFontLarge(Graphics::FontSJIS *font) : SJISFont(font, 0, false, false, false, 0) {
+ _sjisWidth = _font->getMaxFontWidth();
+ _fontHeight = _font->getFontHeight();
+ _asciiWidth = _font->getCharWidth('a');
+}
+
+void SJISFontLarge::drawChar(uint16 c, byte *dst, int pitch, int) const {
+ _font->drawChar(dst, c, 320, 1, _colorMap[1], _colorMap[0], 320, 200);
+}
+
+SJISFont12x12::SJISFont12x12(const uint16 *searchTable) : _height(6), _width(6), _data(0) {
+ assert(searchTable);
+ for (int i = 0; i < 148; i++)
+ _searchTable[searchTable[i]] = i + 1;
+}
+
+bool SJISFont12x12::load(Common::SeekableReadStream &file) {
+ delete[] _data;
+ int size = 148 * 24;
+ if (file.size() < size)
+ return false;
+
+ _data = new uint8[size];
+ file.read(_data, size);
+
+ return true;
+}
+
+void SJISFont12x12::unload() {
+ delete[] _data;
+ _data = 0;
+ _searchTable.clear();
+}
+
+void SJISFont12x12::drawChar(uint16 c, byte *dst, int pitch, int) const {
+ int offs = _searchTable[c];
+ if (!offs)
+ return;
+
+ const uint8 *src = _data + (offs - 1) * 24;
+ uint8 color1 = _colorMap[1];
+
+ int bt = 0;
+ uint16 chr = 0;
+
+ for (int i = 0; i < 192; ++i) {
+ if (!bt) {
+ chr = *src++;
+ bt = 8;
+ }
+ if (chr & 0x80)
+ *dst = color1;
+ dst++;
+ if (--bt)
+ chr <<= 1;
+ else if (i & 8)
+ dst += (pitch - 16);
+ }
+}
+
} // End of namespace Kyra
#endif // ENABLE_EOB
diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h
index 7c2a31e9d3..f213fc985e 100644
--- a/engines/kyra/screen_eob.h
+++ b/engines/kyra/screen_eob.h
@@ -82,8 +82,13 @@ public:
const uint16 *getCGADitheringTable(int index);
const uint8 *getEGADitheringTable();
+ bool loadFont(FontId fontId, const char *filename);
+
+ // FM-Towns specific
+ void decodeSHP(const uint8 *data, int dstPage);
void convertToHiColor(int page);
void shadeRect(int x1, int y1, int x2, int y2, int shadingLevel);
+
private:
void updateDirtyRects();
void ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW, int srcH, int colorKey = -1);
@@ -93,13 +98,15 @@ private:
void scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src);
bool posWithinRect(int posX, int posY, int x1, int y1, int x2, int y2);
+ void setPagePixel16bit(int pageNum, int x, int y, uint16 color);
+
void generateEGADitheringTable(const Palette &pal);
void generateCGADitheringTables(const uint8 *mappingData);
int _dsDiv, _dsRem, _dsScaleTrans;
uint8 *_cgaScaleTable;
int16 _gfxX, _gfxY;
- uint8 _gfxCol;
+ uint16 _gfxCol;
const uint8 *_gfxMaxY;
int16 _dsX1, _dsX2, _dsY1, _dsY2;
@@ -109,6 +116,7 @@ private:
uint8 _shapeOverlay[16];
uint8 *_dsTempPage;
+ uint8 *_shpBuffer;
uint8 *_convertHiColorBuffer;
uint16 *_cgaDitheringTables[2];
@@ -122,6 +130,44 @@ private:
static const int _screenDimTableCount;
};
+/**
+* SJIS Font variant used in the intro and outro of EOB II FM-Towns. It appears twice as large, since it is not rendered on the hires overlay pages
+*/
+class SJISFontLarge : public SJISFont {
+public:
+ SJISFontLarge(Graphics::FontSJIS *font);
+ virtual ~SJISFontLarge() { unload(); }
+
+ virtual bool usesOverlay() const { return false; }
+ virtual void drawChar(uint16 c, byte *dst, int pitch, int) const;
+};
+
+/**
+* 12 x 12 SJIS font for EOB II FM-Towns. The data for this font comes from a file, not from the font rom.
+*/
+class SJISFont12x12 : public Font {
+public:
+ SJISFont12x12(const uint16 *searchTable);
+ virtual ~SJISFont12x12() { unload(); }
+
+ virtual bool load(Common::SeekableReadStream &file);
+ virtual bool usesOverlay() const { return true; }
+ virtual int getHeight() const { return _height; }
+ virtual int getWidth() const { return _width; }
+ virtual int getCharWidth(uint16 c) const { return _width; }
+ virtual void setColorMap(const uint8 *src) { _colorMap = src; }
+ virtual void drawChar(uint16 c, byte *dst, int pitch, int) const;
+
+private:
+ void unload();
+
+ uint8 *_data;
+ Common::HashMap<uint16, uint8> _searchTable;
+
+ const uint8 *_colorMap;
+ const int _height, _width;
+};
+
} // End of namespace Kyra
#endif // ENABLE_EOB
diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp
index 455180b5e1..eb1eb7d39c 100644
--- a/engines/kyra/script_eob.cpp
+++ b/engines/kyra/script_eob.cpp
@@ -1495,7 +1495,8 @@ int EoBInfProcessor::oeob_sequence(int8 *data) {
break;
case -1:
- _vm->_runFlag = _vm->checkPassword();
+ if (_vm->gameFlags().platform == Common::kPlatformDOS)
+ _vm->_runFlag = _vm->checkPassword();
break;
default:
diff --git a/engines/kyra/sequences_darkmoon.cpp b/engines/kyra/sequences_darkmoon.cpp
index befa8aa6a6..2f99ffe41d 100644
--- a/engines/kyra/sequences_darkmoon.cpp
+++ b/engines/kyra/sequences_darkmoon.cpp
@@ -41,18 +41,7 @@ public:
kFinale
};
- struct Config {
- Config(Mode m, const char *const *str, const char *const *cps, const char *const *pal, const DarkMoonShapeDef **shp, const DarkMoonAnimCommand **anim, bool paletteFading) : mode(m), strings(str), cpsFiles(cps), palFiles(pal), shapeDefs(shp), animData(anim), palFading(paletteFading) {}
- Mode mode;
- const char *const *strings;
- const char *const *cpsFiles;
- const char *const *palFiles;
- const DarkMoonShapeDef **shapeDefs;
- const DarkMoonAnimCommand **animData;
- bool palFading;
- };
-
- DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *vm, Screen_EoB *screen, const Config *config);
+ DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *vm, Screen_EoB *screen, Mode mode);
~DarkmoonSequenceHelper();
void loadScene(int index, int pageNum);
@@ -79,9 +68,28 @@ private:
OSystem *_system;
DarkMoonEngine *_vm;
Screen_EoB *_screen;
+
+ struct Config {
+ Config(const char *const *str, const char *const *cpsfiles, const uint8 **cpsdata, const char *const *pal, const DarkMoonShapeDef **shp, const DarkMoonAnimCommand **anim, bool loadScenePalette, bool paletteFading, bool animCmdRestorePalette, bool shapeBackgroundFading, int animPalOffset, int animType1ShapeDim, bool animCmd5SetPalette, int animCmd5ExtraPage) : strings(str), cpsFiles(cpsfiles), cpsData(cpsdata), palFiles(pal), shapeDefs(shp), animData(anim), loadScenePal(loadScenePalette), palFading(paletteFading), animCmdRestorePal(animCmdRestorePalette), shpBackgroundFading(shapeBackgroundFading), animPalOffs(animPalOffset), animCmd1ShapeFrame(animType1ShapeDim), animCmd5SetPal(animCmd5SetPalette), animCmd5AltPage(animCmd5ExtraPage) {}
+ const char *const *strings;
+ const char *const *cpsFiles;
+ const uint8 **cpsData;
+ const char *const *palFiles;
+ const DarkMoonShapeDef **shapeDefs;
+ const DarkMoonAnimCommand **animData;
+ bool loadScenePal;
+ bool palFading;
+ bool animCmdRestorePal;
+ bool shpBackgroundFading;
+ int animPalOffs;
+ int animCmd1ShapeFrame;
+ bool animCmd5SetPal;
+ int animCmd5AltPage;
+ };
+
const Config *_config;
- Palette *_palettes[12];
+ Palette *_palettes[13];
uint8 *_fadingTables[7];
const uint8 **_shapes;
@@ -89,13 +97,22 @@ private:
uint32 _fadePalTimer;
int _fadePalRate;
int _fadePalIndex;
+
+ Screen::FontId _prevFont;
+
+ static const char *const _palFilesIntroVGA[];
+ static const char *const _palFilesIntroEGA[];
+ static const char *const _palFilesFinaleVGA[];
+ static const char *const _palFilesFinaleEGA[];
};
int DarkMoonEngine::mainMenu() {
int menuChoice = _menuChoiceInit;
_menuChoiceInit = 0;
+ _sound->selectAudioResourceSet(kMusicIntro);
_sound->loadSoundFile("INTRO");
+
Screen::FontId of = _screen->_currentFont;
int op = 0;
Common::SeekableReadStream *s = 0;
@@ -103,17 +120,23 @@ int DarkMoonEngine::mainMenu() {
while (menuChoice >= 0 && !shouldQuit()) {
switch (menuChoice) {
case 0: {
- s = _res->createReadStream("XENU.CPS");
- if (s) {
- s->read(_screen->getPalette(0).getData(), 768);
- _screen->loadFileDataToPage(s, 3, 64000);
- delete s;
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ _screen->loadPalette("MENU.PAL", _screen->getPalette(0));
+ _screen->setScreenPalette(_screen->getPalette(0));
+ _screen->loadEoBBitmap("MENU", 0, 3, 3, 2);
} else {
- _screen->loadBitmap("MENU.CPS", 3, 3, &_screen->getPalette(0));
- }
+ s = _res->createReadStream("XENU.CPS");
+ if (s) {
+ s->read(_screen->getPalette(0).getData(), 768);
+ _screen->loadFileDataToPage(s, 3, 64000);
+ delete s;
+ } else {
+ _screen->loadBitmap("MENU.CPS", 3, 3, &_screen->getPalette(0));
+ }
- if (_configRenderMode == Common::kRenderEGA)
- _screen->loadPalette("MENU.EGA", _screen->getPalette(0));
+ if (_configRenderMode == Common::kRenderEGA)
+ _screen->loadPalette("MENU.EGA", _screen->getPalette(0));
+ }
_screen->setScreenPalette(_screen->getPalette(0));
_screen->convertPage(3, 2, 0);
@@ -121,10 +144,11 @@ int DarkMoonEngine::mainMenu() {
of = _screen->setFont(Screen::FID_6_FNT);
op = _screen->setCurPage(2);
Common::String versionString(Common::String::format("ScummVM %s", gScummVMVersion));
- _screen->printText(versionString.c_str(), 267 - versionString.size() * 6, 160, 13, 0);
+ _screen->printText(versionString.c_str(), 267 - versionString.size() * 6, _flags.platform == Common::kPlatformFMTowns ? 152 : 160, 13, 0);
_screen->setFont(of);
_screen->_curPage = op;
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->shadeRect(78, 99, 249, 141, 4);
_screen->updateScreen();
_allowImport = true;
menuChoice = mainMenuLoop();
@@ -172,12 +196,30 @@ int DarkMoonEngine::mainMenuLoop() {
sel = _gui->simpleMenu_process(6, _mainMenuStrings, 0, -1, 0);
} while ((sel < 0 || sel > 5) && !shouldQuit());
+ if (_flags.platform == Common::kPlatformFMTowns && sel == 2) {
+ townsUtilitiesMenu();
+ sel = -1;
+ }
+
return sel + 1;
}
+void DarkMoonEngine::townsUtilitiesMenu() {
+ _screen->copyRegion(78, 99, 78, 99, 172, 43, 2, 0, Screen::CR_NO_P_CHECK);
+ int sel = -1;
+ do {
+ _gui->simpleMenu_setup(8, 0, _utilMenuStrings, -1, 0, 0);
+ while (sel == -1 && !shouldQuit())
+ sel = _gui->simpleMenu_process(8, _utilMenuStrings, 0, -1, 0);
+ if (sel == 0) {
+ _config2431 ^= true;
+ sel = -1;
+ }
+ } while ((sel < 0 || sel > 1) && !shouldQuit());
+}
+
void DarkMoonEngine::seq_playIntro() {
- DarkmoonSequenceHelper::Config config(DarkmoonSequenceHelper::kIntro, _introStrings, _cpsFilesIntro, _configRenderMode == Common::kRenderEGA ? _palFilesIntroEGA : _palFilesIntroVGA, _shapesIntro, _animIntro, false);
- DarkmoonSequenceHelper sq(_system, this, _screen, &config);
+ DarkmoonSequenceHelper sq(_system, this, _screen, DarkmoonSequenceHelper::kIntro);
_screen->setCurPage(0);
_screen->clearCurPage();
@@ -206,13 +248,13 @@ void DarkMoonEngine::seq_playIntro() {
sq.animCommand(6, 18);
sq.animCommand(0);
- sq.waitForSongNotifier(1);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 229 : 1);
sq.animCommand(_configRenderMode == Common::kRenderEGA ? 12 : 11);
sq.animCommand(7, 6);
sq.animCommand(2, 6);
- sq.waitForSongNotifier(2);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 447 : 2);
sq.animCommand(_configRenderMode == Common::kRenderEGA ? 39 : 38);
sq.animCommand(3);
@@ -221,7 +263,7 @@ void DarkMoonEngine::seq_playIntro() {
sq.animCommand(0, 6);
sq.animCommand(2);
- sq.waitForSongNotifier(3);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 670 : 3);
_screen->setClearScreenDim(17);
_screen->setCurPage(2);
@@ -249,7 +291,7 @@ void DarkMoonEngine::seq_playIntro() {
sq.printText(3, 16); // The message was urgent.
sq.loadScene(1, 2);
- sq.waitForSongNotifier(4);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 1380 : 4);
// intro scroll
if (!skipFlag() && !shouldQuit()) {
@@ -310,7 +352,7 @@ void DarkMoonEngine::seq_playIntro() {
sq.animCommand(14);
sq.loadScene(5, 2);
- sq.waitForSongNotifier(5);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 2037 : 5);
sq.fadeText();
_screen->clearCurPage();
@@ -365,7 +407,7 @@ void DarkMoonEngine::seq_playIntro() {
sq.loadScene(9, 2);
sq.fadeText();
- sq.waitForSongNotifier(6);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 3000 : 6);
sq.update(2);
sq.animCommand(34);
@@ -470,12 +512,12 @@ void DarkMoonEngine::seq_playIntro() {
sq.fadeText();
sq.animCommand(29);
- sq.waitForSongNotifier(7);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 4475 : 7);
sq.animCommand(30);
sq.animCommand(31);
- sq.waitForSongNotifier(8, true);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 4825 : 8, true);
if (skipFlag() || shouldQuit()) {
snd_fadeOut();
@@ -496,17 +538,16 @@ void DarkMoonEngine::seq_playIntro() {
}
void DarkMoonEngine::seq_playFinale() {
- DarkmoonSequenceHelper::Config config(DarkmoonSequenceHelper::kFinale, _finaleStrings, _cpsFilesFinale, _configRenderMode == Common::kRenderEGA ? _palFilesFinaleEGA : _palFilesFinaleVGA, _shapesFinale, _animFinale, true);
- DarkmoonSequenceHelper sq(_system, this, _screen, &config);
+ DarkmoonSequenceHelper sq(_system, this, _screen, DarkmoonSequenceHelper::kFinale);
_screen->setCurPage(0);
- _screen->setFont(Screen::FID_8_FNT);
- _sound->loadSoundFile("FINALE1");
+ _sound->loadSoundFile(_flags.platform == Common::kPlatformFMTowns ? "FINALE" : "FINALE1");
snd_stopSound();
sq.delay(3);
_screen->clearCurPage();
+ _screen->clearPage(2);
_screen->updateScreen();
sq.loadScene(0, 2);
@@ -532,7 +573,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.fadeText();
sq.animCommand(2);
- sq.waitForSongNotifier(1);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 475 : 1);
sq.printText(1, 10); // Suddenly, your friend Khelben appears
sq.animCommand(4);
@@ -624,7 +665,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.loadScene(4, 2);
- sq.waitForSongNotifier(2);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 2030 : 2);
_screen->clearCurPage();
sq.update(2);
@@ -637,7 +678,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.delay(90);
sq.fadeText();
- sq.waitForSongNotifier(3);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 2200 : 3);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(7);
@@ -669,7 +710,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.delay(72);
sq.fadeText();
- sq.waitForSongNotifier(4);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 2752 : 4);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(7);
@@ -703,7 +744,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.fadeText();
sq.loadScene(12, 2);
- sq.waitForSongNotifier(5);
+ sq.waitForSongNotifier(_flags.platform == Common::kPlatformFMTowns ? 3475 : 5);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(6);
@@ -782,16 +823,24 @@ void DarkMoonEngine::seq_playFinale() {
sq.loadScene(10, 2);
sq.loadScene(9, 2);
+
snd_stopSound();
sq.delay(3);
- _sound->loadSoundFile("FINALE2");
+ if (_flags.platform != Common::kPlatformFMTowns)
+ _sound->loadSoundFile("FINALE2");
sq.delay(18);
if (!skipFlag() && !shouldQuit())
- snd_playSong(1);
+ snd_playSong(_flags.platform == Common::kPlatformFMTowns ? 16 : 1);
- seq_playCredits(&sq, _creditsData, 18, 2, 6, 2);
+ int temp = 0;
+ const uint8 *creditsData = (_flags.platform == Common::kPlatformFMTowns) ? _res->fileData("CREDITS.TXT", 0) : _staticres->loadRawData(kEoB2CreditsData, temp);
+
+ seq_playCredits(&sq, creditsData, 18, 2, 6, 2);
+
+ if (_flags.platform == Common::kPlatformFMTowns)
+ delete[] creditsData;
sq.delay(90);
@@ -817,6 +866,9 @@ void DarkMoonEngine::seq_playFinale() {
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
+ if (_flags.platform == Common::kPlatformFMTowns)
+ sq.copyPalette(12, 0);
+
sq.setPalette(9);
sq.fadePalette(0, 18);
@@ -831,7 +883,9 @@ void DarkMoonEngine::seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *da
if (!data)
return;
+ _screen->setFont(Screen::FID_8_FNT);
_screen->setScreenDim(sd);
+
const ScreenDim *dm = _screen->_curDim;
_screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 0, backupPage, Screen::CR_NO_P_CHECK);
@@ -955,8 +1009,74 @@ void DarkMoonEngine::seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *da
delete[] items[i].str;
}
-DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *vm, Screen_EoB *screen, const Config *config) :
- _system(system), _vm(vm), _screen(screen), _config(config) {
+DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *vm, Screen_EoB *screen, Mode mode) :
+ _system(system), _vm(vm), _screen(screen) {
+
+ int size = 0;
+
+ if (mode == kIntro) {
+ _config = new Config(
+ _vm->staticres()->loadStrings(kEoB2IntroStrings, size),
+ _vm->staticres()->loadStrings(kEoB2IntroCPSFiles, size),
+ new const uint8*[13],
+ _vm->_configRenderMode == Common::kRenderEGA ? _palFilesIntroEGA : _palFilesIntroVGA,
+ new const DarkMoonShapeDef*[13],
+ new const DarkMoonAnimCommand *[44],
+ false,
+ false,
+ true,
+ true,
+ 0,
+ 0,
+ false,
+ 2
+ );
+
+ for (int i = 0; i < 44; i++)
+ _config->animData[i] = _vm->staticres()->loadEoB2SeqData(kEoB2IntroAnimData00 + i, size);
+
+ for (int i = 0; i < 13; i++)
+ _config->cpsData[i] = _vm->staticres()->loadRawData(kEoB2IntroCpsDataStreet1 + i, size);
+
+ memset(_config->shapeDefs, 0, 13 * sizeof(DarkMoonShapeDef*));
+ _config->shapeDefs[0] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes00, size);
+ _config->shapeDefs[1] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes01, size);
+ _config->shapeDefs[4] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes04, size);
+ _config->shapeDefs[7] = _vm->staticres()->loadEoB2ShapeData(kEoB2IntroShapes07, size);
+
+ } else {
+ _config = new Config(
+ _vm->staticres()->loadStrings(kEoB2FinaleStrings, size),
+ _vm->staticres()->loadStrings(kEoB2FinaleCPSFiles, size),
+ new const uint8*[13],
+ _vm->_configRenderMode == Common::kRenderEGA ? _palFilesFinaleEGA : _palFilesFinaleVGA,
+ new const DarkMoonShapeDef*[13],
+ new const DarkMoonAnimCommand *[21],
+ true,
+ true,
+ false,
+ false,
+ 1,
+ 18,
+ true,
+ 6
+ );
+
+ for (int i = 0; i < 21; i++)
+ _config->animData[i] = _vm->staticres()->loadEoB2SeqData(kEoB2FinaleAnimData00 + i, size);
+
+ for (int i = 0; i < 13; i++)
+ _config->cpsData[i] = _vm->staticres()->loadRawData(kEoB2FinaleCpsDataDragon1 + i, size);
+
+ memset(_config->shapeDefs, 0, 13 * sizeof(DarkMoonShapeDef*));
+ _config->shapeDefs[0] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes00, size);
+ _config->shapeDefs[3] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes03, size);
+ _config->shapeDefs[7] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes07, size);
+ _config->shapeDefs[9] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes09, size);
+ _config->shapeDefs[10] = _vm->staticres()->loadEoB2ShapeData(kEoB2FinaleShapes10, size);
+ }
+
+ _screen->enableHiColorMode(false);
for (int i = 0; _config->palFiles[i]; i++) {
if (i < 4)
@@ -966,13 +1086,16 @@ DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *
_screen->loadPalette(_config->palFiles[i], *_palettes[i]);
}
- _palettes[9] = new Palette(256);
+ for (int i = 9; i < 13; ++i)
+ _palettes[i] = new Palette(256);
+
_palettes[9]->fill(0, 256, 0);
- _palettes[10] = new Palette(256);
_palettes[10]->fill(0, 256, 63);
- _palettes[11] = new Palette(256);
_palettes[11]->fill(0, 256, 0);
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ _screen->loadPalette("PALETTE.COL", *_palettes[12]);
+
for (int i = 0; i < 7; i++)
_fadingTables[i] = 0;
@@ -1001,7 +1124,7 @@ DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *
_fadePalRate = 0;
_screen->setScreenPalette(*_palettes[0]);
- _screen->setFont(Screen::FID_8_FNT);
+ _prevFont = _screen->setFont(_vm->gameFlags().platform == Common::kPlatformFMTowns ? Screen::FID_SJIS_LARGE_FNT : Screen::FID_8_FNT);
_screen->hideMouse();
_vm->delay(150);
@@ -1012,9 +1135,8 @@ DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *
DarkmoonSequenceHelper::~DarkmoonSequenceHelper() {
for (int i = 4; _config->palFiles[i]; i++)
delete _palettes[i];
- delete _palettes[9];
- delete _palettes[10];
- delete _palettes[11];
+ for (int i = 9; i < 13; ++i)
+ delete _palettes[i];
for (int i = 0; i < 7; i++)
delete[] _fadingTables[i];
@@ -1023,7 +1145,14 @@ DarkmoonSequenceHelper::~DarkmoonSequenceHelper() {
delete[] _shapes[i];
delete[] _shapes;
+ delete[] _config->animData;
+ delete[] _config->shapeDefs;
+ delete[] _config->cpsData;
+ delete _config;
+
+ _screen->enableHiColorMode(true);
_screen->clearCurPage();
+ _screen->setFont(_prevFont);
_screen->showMouse();
_screen->updateScreen();
@@ -1033,17 +1162,23 @@ DarkmoonSequenceHelper::~DarkmoonSequenceHelper() {
}
void DarkmoonSequenceHelper::loadScene(int index, int pageNum) {
- char file[13];
- strcpy(file, _config->cpsFiles[index]);
-
- Common::SeekableReadStream *s = _vm->resource()->createReadStream(file);
+ char file[13] = "";
+ Common::SeekableReadStream *s = 0;
uint32 chunkID = 0;
+
+ if (_config->cpsFiles) {
+ strcpy(file, _config->cpsFiles[index]);
+ s = _vm->resource()->createReadStream(file);
+ }
+
if (s) {
chunkID = s->readUint32LE();
s->seek(0);
}
- if (s && chunkID == MKTAG('F', 'O', 'R', 'M')) {
+ if (_config->cpsData[index]) {
+ _screen->decodeSHP(_config->cpsData[index], pageNum);
+ } else if (s && chunkID == MKTAG('F', 'O', 'R', 'M')) {
// The original code also handles files with FORM chunks and ILBM and PBM sub chunks. This will probably be necessary for Amiga versions.
// The DOS versions do not need this, but still have the code for it. We error out for now.
error("DarkmoonSequenceHelper::loadScene(): CPS file loading failure in scene %d - unhandled FORM chunk encountered", index);
@@ -1059,7 +1194,7 @@ void DarkmoonSequenceHelper::loadScene(int index, int pageNum) {
if (!s)
error("DarkmoonSequenceHelper::loadScene(): CPS file loading failure in scene %d", index);
- if (_config->mode == kFinale)
+ if (_config->loadScenePal)
s->read(_palettes[0]->getData(), 768);
else
s->seek(768);
@@ -1096,8 +1231,10 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
uint32 end = 0;
for (const DarkMoonAnimCommand *s = _config->animData[index]; s->command != 0xFF && !_vm->skipFlag() && !_vm->shouldQuit(); s++) {
- int palIndex = _config->mode == kFinale ? (s->pal + 1) : s->pal;
+ int palIndex = s->pal + _config->animPalOffs;
int x = s->x1;
+ if (x >= Screen::SCREEN_W)
+ x >>= 1;
int y = s->y1;
int x2 = 0;
uint16 shapeW = 0;
@@ -1109,7 +1246,7 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
setPaletteWithoutTextColor(palIndex);
delay(s->delay);
- if (_vm->_configRenderMode != Common::kRenderEGA && _config->mode == kIntro && s->pal)
+ if (_vm->_configRenderMode != Common::kRenderEGA && _config->animCmdRestorePal && s->pal)
setPaletteWithoutTextColor(0);
break;
@@ -1118,7 +1255,7 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
shapeW = _shapes[s->obj][2];
shapeH = _shapes[s->obj][3];
- if (_config->mode == kFinale) {
+ if (_config->animCmd1ShapeFrame == 18) {
_screen->setScreenDim(18);
x -= (_screen->_curDim->sx << 3);
y -= _screen->_curDim->sy;
@@ -1128,7 +1265,7 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
x2 = x;
}
- _screen->drawShape(0, _shapes[s->obj], x, y, _config->mode == kIntro ? 0 : 18);
+ _screen->drawShape(0, _shapes[s->obj], x, y, _config->animCmd1ShapeFrame);
if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
setPaletteWithoutTextColor(palIndex);
@@ -1137,7 +1274,7 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
delay(s->delay);
- if (_config->mode == kIntro) {
+ if (_config->animCmd1ShapeFrame == 0) {
if (_vm->_configRenderMode != Common::kRenderEGA && s->pal)
setPaletteWithoutTextColor(0);
_screen->copyRegion(x - 8, y - 8, x, y, (shapeW + 1) << 3, shapeH, 2, 0, Screen::CR_NO_P_CHECK);
@@ -1159,14 +1296,14 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
delay(s->delay);
- if (_vm->_configRenderMode != Common::kRenderEGA && _config->mode == kIntro && s->pal)
+ if (_vm->_configRenderMode != Common::kRenderEGA && _config->animCmdRestorePal && s->pal)
setPaletteWithoutTextColor(0);
break;
case 3:
case 4:
// fade shape in or out or restore background
- if (_config->mode == kFinale)
+ if (!_config->shpBackgroundFading)
break;
if (_vm->_configRenderMode == Common::kRenderEGA) {
@@ -1201,10 +1338,10 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) {
case 5:
// copy region
- if (_config->mode == kFinale && s->pal)
+ if (_config->animCmd5SetPal && s->pal)
setPaletteWithoutTextColor(palIndex);
- _screen->copyRegion(s->x2 << 3, s->y2, s->x1, s->y1, s->w << 3, s->h, (s->obj && _config->mode == kFinale) ? 6 : 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(s->x2 << 3, s->y2, s->x1, s->y1, s->w << 3, s->h, s->obj ? _config->animCmd5AltPage : 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delay(s->delay);
break;
@@ -1250,8 +1387,9 @@ void DarkmoonSequenceHelper::printText(int index, int color) {
strcpy(str, _config->strings[index]);
const ScreenDim *dm = _screen->_curDim;
+ int fontHeight = _screen->getFontHeight() + 1;
- for (int yOffs = 0; *str; yOffs += 9) {
+ for (int yOffs = 0; *str; yOffs += fontHeight) {
char *cr = strchr(str, 13);
if (cr)
@@ -1383,8 +1521,52 @@ void DarkmoonSequenceHelper::waitForSongNotifier(int index, bool introUpdateAnim
}
}
+const char *const DarkmoonSequenceHelper::_palFilesIntroVGA[] = {
+ "PALETTE1.PAL",
+ "PALETTE3.PAL",
+ "PALETTE2.PAL",
+ "PALETTE4.PAL",
+ 0
+};
+
+const char *const DarkmoonSequenceHelper::_palFilesIntroEGA[] = {
+ "PALETTE0.PAL",
+ "PALETTE3.PAL",
+ "PALETTE2.PAL",
+ "PALETTE4.PAL",
+ 0
+};
+
+const char *const DarkmoonSequenceHelper::_palFilesFinaleVGA[] = {
+ "FINALE_0.PAL",
+ "FINALE_0.PAL",
+ "FINALE_1.PAL",
+ "FINALE_2.PAL",
+ "FINALE_3.PAL",
+ "FINALE_4.PAL",
+ "FINALE_5.PAL",
+ "FINALE_6.PAL",
+ "FINALE_7.PAL",
+ 0
+};
+
+const char *const DarkmoonSequenceHelper::_palFilesFinaleEGA[] = {
+ "FINALE_0.PAL",
+ "FINALE_0.PAL",
+ "FINALE_1.PAL",
+ "FINALE_2.PAL",
+ "FINALE_3.PAL",
+ "FINALE_4.PAL",
+ "FINALE_5.PAL",
+ "FINALE_0.PAL",
+ "FINALE_0.PAL",
+ 0
+};
+
void DarkMoonEngine::seq_nightmare() {
Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
+ if (_flags.lang == Common::JA_JPN)
+ _screen->clearCurDim();
_screen->copyRegion(0, 0, 0, 120, 176, 24, 12, 2, Screen::CR_NO_P_CHECK);
initDialogueSequence();
@@ -1416,6 +1598,7 @@ void DarkMoonEngine::seq_kheldran() {
gui_drawDialogueBox();
static const char file[] = "KHELDRAN";
+ _screen->set16bitShadingLevel(4);
_txt->printDialogueText(_kheldranStrings[0]);
drawSequenceBitmap(file, 0, 0, 0, 0);
_txt->printDialogueText(20, _moreStrings[0]);
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index 2f5a0b6121..3f4216c5fb 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -66,6 +66,13 @@ struct SoundResourceInfo_TownsPC98V2 {
uint cdaTableSize;
};
+struct SoundResourceInfo_TownsEoB {
+ SoundResourceInfo_TownsEoB(const uint8 *pcmdata, uint dataSize, int pcmvolume) : pcmData(pcmdata), pcmDataSize(dataSize), pcmVolume(pcmvolume) {}
+ const uint8 *pcmData;
+ uint pcmDataSize;
+ int pcmVolume;
+};
+
/**
* Analog audio output device API for Kyrandia games.
* It contains functionality to play music tracks,
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index 3559133cb1..dd043790a2 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -349,6 +349,59 @@ protected:
int _tableSfxGame_Size;
};
+class SoundTowns_Darkmoon : public Sound, public TownsAudioInterfacePluginDriver {
+public:
+ SoundTowns_Darkmoon(KyraEngine_v1 *vm, Audio::Mixer *mixer);
+ virtual ~SoundTowns_Darkmoon();
+
+ virtual kType getMusicType() const { return kTowns; }
+
+ virtual bool init();
+
+ void timerCallback(int timerId);
+
+ virtual void initAudioResourceInfo(int set, void *info);
+ virtual void selectAudioResourceSet(int set);
+ virtual bool hasSoundFile(uint file) const;
+ virtual void loadSoundFile(uint file) {}
+ virtual void loadSoundFile(Common::String name);
+
+ virtual void playTrack(uint8 track);
+ virtual void haltTrack();
+ virtual bool isPlaying() const;
+
+ virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
+ virtual void stopAllSoundEffects();
+
+ virtual void beginFadeOut();
+
+ virtual void updateVolumeSettings();
+
+ virtual int checkTrigger();
+
+ virtual void resetTrigger();
+
+private:
+ struct SoundTableEntry {
+ int8 type;
+ int32 para1;
+ int16 para2;
+ } _soundTable[120];
+
+ uint8 _lastSfxChan;
+ uint8 _lastEnvChan;
+ uint8 *_pcmData;
+ uint32 _pcmDataSize;
+ uint8 _pcmVol;
+
+ int _timer;
+ int _timerSwitch;
+
+ SoundResourceInfo_TownsEoB *_pcmResource[3];
+
+ TownsAudioInterface *_intf;
+};
+
} // End of namespace Kyra
#endif
diff --git a/engines/kyra/sound_towns_darkmoon.cpp b/engines/kyra/sound_towns_darkmoon.cpp
new file mode 100644
index 0000000000..b1fcb57e30
--- /dev/null
+++ b/engines/kyra/sound_towns_darkmoon.cpp
@@ -0,0 +1,276 @@
+/* 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 "kyra/sound_intern.h"
+#include "kyra/resource.h"
+
+#include "common/config-manager.h"
+#include "common/system.h"
+
+#include "backends/audiocd/audiocd.h"
+
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+
+namespace Kyra {
+
+SoundTowns_Darkmoon::SoundTowns_Darkmoon(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer) {
+ _intf = new TownsAudioInterface(mixer, this, false);
+ _pcmData = 0;
+ _pcmVol = 0;
+ _timer = 0;
+ _timerSwitch = 0;
+ memset(_pcmResource, 0, sizeof(_pcmResource));
+}
+
+SoundTowns_Darkmoon::~SoundTowns_Darkmoon() {
+ for (int i = 0; i < 3; i++)
+ initAudioResourceInfo(i, 0);
+ delete _intf;
+ delete[] _pcmData;
+}
+
+bool SoundTowns_Darkmoon::init() {
+ if (!_intf->init())
+ return false;
+
+ _intf->callback(21, 255, 1);
+ _intf->callback(21, 0, 1);
+ _intf->callback(22, 255, 221);
+
+ _intf->callback(70, 0x31);
+ _intf->callback(33, 1);
+ _intf->callback(8, 0x47, 127);
+ _intf->callback(67, 1, 127, 127);
+
+ _lastSfxChan = 0x46;
+ _lastEnvChan = 0x40;
+
+ updateVolumeSettings();
+
+ return true;
+}
+
+void SoundTowns_Darkmoon::timerCallback(int timerId) {
+ switch (timerId) {
+ case 1:
+ _timerSwitch = (_timerSwitch + 1) % 4;
+ if (!_timerSwitch)
+ _timer++;
+ break;
+ default:
+ break;
+ }
+}
+
+void SoundTowns_Darkmoon::initAudioResourceInfo(int set, void *info) {
+ delete _pcmResource[set];
+ _pcmResource[set] = info ? new SoundResourceInfo_TownsEoB(*(SoundResourceInfo_TownsEoB*)info) : 0;
+}
+
+void SoundTowns_Darkmoon::selectAudioResourceSet(int set) {
+ delete[] _pcmData;
+
+ if (!_pcmResource[set] || !_pcmResource[kMusicIngame])
+ return;
+
+ _pcmDataSize = _pcmResource[kMusicIngame]->pcmDataSize;
+ _pcmData = new uint8[_pcmDataSize];
+ _pcmVol = _pcmResource[set]->pcmVolume;
+ memcpy(_pcmData, _pcmResource[kMusicIngame]->pcmData, _pcmDataSize);
+
+ if (set == kMusicIngame)
+ return;
+
+ memcpy(_pcmData, _pcmResource[set]->pcmData, _pcmResource[set]->pcmDataSize);
+}
+
+bool SoundTowns_Darkmoon::hasSoundFile(uint file) const {
+ return true;
+}
+
+void SoundTowns_Darkmoon::loadSoundFile(Common::String name) {
+ Common::SeekableReadStream *s = _vm->resource()->createReadStream(Common::String::format("%s.SDT", name.c_str()));
+ if (!s)
+ error("Failed to load sound file '%s.SDT'", name.c_str());
+
+ for (int i = 0; i < 120; i++) {
+ _soundTable[i].type = s->readSByte();
+ _soundTable[i].para1 = s->readSint32LE();
+ _soundTable[i].para2 = s->readSint16LE();
+ }
+
+ delete s;
+
+ uint32 bytesLeft;
+ uint8 *pmb = _vm->resource()->fileData(Common::String::format("%s.PMB", name.c_str()).c_str(), &bytesLeft);
+
+ _vm->delay(300);
+
+ if (pmb) {
+ uint8 *src = pmb + 8;
+ for (int i = 0; i < 32; i++)
+ _intf->callback(5, 0x40, i, &src[i << 7]);
+
+ _intf->callback(35, -1);
+ src += 0x1000;
+ bytesLeft -= 0x1008;
+
+ while (bytesLeft) {
+ _intf->callback(34, src);
+ uint32 len = READ_LE_UINT16(&src[12]) + 32;
+ src = src + len;
+ bytesLeft -= len;
+ }
+
+ delete[] pmb;
+ } else {
+ warning("Sound file '%s.PMB' not found.", name.c_str());
+ // TODO
+ }
+}
+
+void SoundTowns_Darkmoon::playTrack(uint8 track) {
+ if (track >= 120 || !_sfxEnabled)
+ return;
+
+ uint8 *pcm = 0;
+
+ switch (_soundTable[track].type) {
+ case -1:
+ if (track == 0)
+ haltTrack();
+ else if (track == 2)
+ beginFadeOut();
+ break;
+
+ case 0:
+ if (_soundTable[track].para1 == -1 || (uint32)_soundTable[track].para1 > _pcmDataSize)
+ return;
+
+ pcm = _pcmData + _soundTable[track].para1;
+ WRITE_LE_UINT16(&pcm[24], _soundTable[track].para2 * 98 / 1000);
+
+ _intf->callback(39, 0x47);
+ _intf->callback(37, 0x47, 60, track == 11 ? 127 : _pcmVol, pcm);
+ break;
+
+ case 2:
+ resetTrigger();
+ g_system->getAudioCDManager()->play(_soundTable[track].para1 - 1, 1, 0, 0);
+ break;
+
+ case 3:
+ _lastSfxChan ^= 3;
+ _intf->callback(39, _lastSfxChan);
+ _intf->callback(4, _lastSfxChan, _soundTable[track].para1);
+ _intf->callback(1, _lastSfxChan, _soundTable[track].para2, 127);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void SoundTowns_Darkmoon::haltTrack() {
+ _intf->callback(39, 0x47);
+ _intf->callback(39, 0x46);
+ _intf->callback(39, 0x45);
+
+ g_system->getAudioCDManager()->stop();
+}
+
+bool SoundTowns_Darkmoon::isPlaying() const {
+ return g_system->getAudioCDManager()->isPlaying();
+}
+
+void SoundTowns_Darkmoon::playSoundEffect(uint8 track, uint8 volume) {
+ if (!_sfxEnabled)
+ return;
+
+ if (volume == 255)
+ return playTrack(track);
+
+ uint8 *pcm = 0;
+
+ switch (_soundTable[track].type) {
+ case 0:
+ if (_soundTable[track].para1 == -1 || (uint32)_soundTable[track].para1 > _pcmDataSize)
+ return;
+
+ pcm = _pcmData + _soundTable[track].para1;
+ WRITE_LE_UINT16(&pcm[24], _soundTable[track].para2 * 98 / 1000);
+
+ _intf->callback(39, 0x47);
+ _intf->callback(37, 0x47, 60, volume, pcm);
+ break;
+
+ case 3:
+ _intf->callback(2, _lastEnvChan);
+ _intf->callback(4, _lastEnvChan, _soundTable[track].para1);
+ _intf->callback(1, _lastEnvChan, _soundTable[track].para2, volume);
+ break;
+
+ default:
+ break;
+ }
+
+ if (++_lastEnvChan == 0x43)
+ _lastEnvChan = 0x40;
+}
+
+void SoundTowns_Darkmoon::stopAllSoundEffects() {
+ _intf->callback(39, 0x42);
+ _intf->callback(39, 0x41);
+ _intf->callback(39, 0x40);
+}
+
+void SoundTowns_Darkmoon::beginFadeOut() {
+ for (int vol = 127; vol >= 0; vol -= 2) {
+ _intf->callback(67, 1, vol, vol);
+ _vm->delay(16);
+ }
+
+ _intf->callback(67, 1, 0, 0);
+ _intf->callback(70, 1);
+
+ g_system->getAudioCDManager()->stop();
+
+ _intf->callback(70, 0x31);
+ _intf->callback(67, 1, 127, 127);
+}
+
+void SoundTowns_Darkmoon::updateVolumeSettings() {
+ bool mute = (ConfMan.hasKey("mute")) ? ConfMan.getBool("mute") : false;
+ _intf->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
+}
+
+int SoundTowns_Darkmoon::checkTrigger() {
+ return _timer;
+}
+
+void SoundTowns_Darkmoon::resetTrigger() {
+ _timer = 0;
+ _timerSwitch = 0;
+}
+
+} // End of namespace Kyra
diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp
index c93bf0edb7..077eafa97b 100644
--- a/engines/kyra/sprites_eob.cpp
+++ b/engines/kyra/sprites_eob.cpp
@@ -33,17 +33,40 @@
namespace Kyra {
void EoBCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) {
- _screen->loadShapeSetBitmap(filename, 3, 3);
- const uint16 *enc = &_encodeMonsterShpTable[encodeTableIndex << 2];
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ Common::String tmp = Common::String::format("%s.MNT", filename);
+ Common::SeekableReadStream *s = _res->createReadStream(tmp);
+ if (!s)
+ error("Screen_EoB::loadMonsterShapes(): Failed to load file '%s'", tmp.c_str());
+
+ for (int i = 0; i < 6; i++)
+ _monsterShapes[monsterIndex + i] = loadTownsShape(s);
+
+ for (int i = 0; i < 6; i++) {
+ for (int ii = 0; ii < 2; ii++)
+ s->read(_monsterPalettes[(monsterIndex >= 18 ? i + 6 : i) * 2 + ii], 16);
+ }
+
+ if (hasDecorations)
+ loadMonsterDecoration(s, monsterIndex);
- for (int i = 0; i < 6; i++, enc += 4)
- _monsterShapes[monsterIndex + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, _cgaMappingDefault);
+ delete s;
+ } else {
+ _screen->loadShapeSetBitmap(filename, 3, 3);
+ const uint16 *enc = &_encodeMonsterShpTable[encodeTableIndex << 2];
- generateMonsterPalettes(filename, monsterIndex);
+ for (int i = 0; i < 6; i++, enc += 4)
+ _monsterShapes[monsterIndex + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, _cgaMappingDefault);
- if (hasDecorations)
- loadMonsterDecoration(filename, monsterIndex);
+ generateMonsterPalettes(filename, monsterIndex);
+ if (hasDecorations) {
+ Common::SeekableReadStream *s = _res->createReadStream(Common::String::format("%s.DCR", filename));
+ if (s)
+ loadMonsterDecoration(s, monsterIndex);
+ delete s;
+ }
+ }
_screen->_curPage = 0;
}
@@ -56,6 +79,15 @@ void EoBCoreEngine::releaseMonsterShapes(int first, int num) {
}
}
+uint8 *EoBCoreEngine::loadTownsShape(Common::SeekableReadStream *stream) {
+ uint32 size = stream->readUint32LE();
+ uint8 *shape= new uint8[size];
+ stream->read(shape, size);
+ if (shape[0] == 1)
+ shape[0]++;
+ return shape;
+}
+
const uint8 *EoBCoreEngine::loadMonsterProperties(const uint8 *data) {
uint8 cmd = *data++;
while (cmd != 0xFF) {
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 7cb102b0c4..3a83bd193d 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -39,7 +39,7 @@
namespace Kyra {
-#define RESFILE_VERSION 90
+#define RESFILE_VERSION 91
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp
index f4897b5256..933b120370 100644
--- a/engines/kyra/staticres_eob.cpp
+++ b/engines/kyra/staticres_eob.cpp
@@ -22,6 +22,7 @@
#include "kyra/eob.h"
#include "kyra/resource.h"
+#include "kyra/sound_intern.h"
namespace Kyra {
@@ -164,7 +165,7 @@ const ScreenDim Screen_EoB::_screenDimTable[] = {
{ 0x01, 0x14, 0x14, 0x58, 0x0F, 0x02, 0x00, 0x00 },
{ 0x02, 0x06, 0x23, 0x78, 0x0F, 0x02, 0x00, 0x00 },
{ 0x09, 0x14, 0x16, 0x38, 0x0F, 0x02, 0x00, 0x00 },
- { 0x01, 0x96, 0x26, 0x31, 0x0F, 0x00, 0x00, 0x00 },
+ { 0x01, 0x96, 0x26, 0x32, 0x0F, 0x00, 0x00, 0x00 },
{ 0x01, 0x08, 0x26, 0x80, 0x0C, 0x0F, 0x00, 0x00 },
{ 0x01, 0x10, 0x26, 0x14, 0x00, 0x0F, 0x06, 0x00 },
{ 0x00, 0x10, 0x10, 0x0C, 0x00, 0x0F, 0x06, 0x00 },
@@ -407,7 +408,6 @@ void EoBCoreEngine::initStaticResource() {
_wllFlagPreset = _staticres->loadRawData(kEoBBaseWllFlagPreset, _wllFlagPresetSize);
_dscShapeCoords = (const int16 *)_staticres->loadRawDataBe16(kEoBBaseDscShapeCoords, temp);
- _dscDoorScaleOffs = _staticres->loadRawData(kEoBBaseDscDoorScaleOffs, temp);
_dscDoorScaleMult1 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult1, temp);
_dscDoorScaleMult2 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult2, temp);
_dscDoorScaleMult3 = _staticres->loadRawData(kEoBBaseDscDoorScaleMult3, temp);
@@ -471,10 +471,11 @@ void EoBCoreEngine::initStaticResource() {
{ 0, 0, 0, 0 }
};
- static const char *const errorSlotEmptyString[4] = {
+ static const char *const errorSlotEmptyString[5] = {
"There is no game\rsaved in that slot!",
"Hier ist noch kein\rSpiel gespeichert!",
"Non c'\x0E alcun gioco\rsalvato in quella\rposizione!",
+ "\r ""\x82\xBB\x82\xCC\x83""X""\x83\x8D\x83""b""\x83""g""\x82\xC9\x82\xCD\x83""Q""\x81""[""\x83\x80\x82\xAA\x83""Z""\x81""[""\x83""u\r ""\x82\xB3\x82\xEA\x82\xC4\x82\xA2\x82\xDC\x82\xB9\x82\xF1\x81""B",
0
};
@@ -487,10 +488,15 @@ void EoBCoreEngine::initStaticResource() {
} else if (_flags.lang == Common::IT_ITA) {
_saveLoadStrings = saveLoadStrings[2];
_errorSlotEmptyString = errorSlotEmptyString[2];
- } else {
- _saveLoadStrings = saveLoadStrings[3];
+ } else if (_flags.lang == Common::JA_JPN) {
+ // EOB II FM-Towns uses English here.
+ // Only the empty slot warning is in Japanese.
+ _saveLoadStrings = saveLoadStrings[0];
_errorSlotEmptyString = errorSlotEmptyString[3];
- }
+ } else {
+ _saveLoadStrings = saveLoadStrings[4];
+ _errorSlotEmptyString = errorSlotEmptyString[4];
+ }
_menuOkString = "OK";
}
@@ -602,7 +608,24 @@ void EoBCoreEngine::initButtonData() {
{ 110, 0, 0x1100, 75, 168, 97, 6, 0 }
};
- _buttonDefs = buttonDefs;
+ _buttonDefs = new EoBGuiButtonDef[ARRAYSIZE(buttonDefs)];
+ memcpy(_buttonDefs, buttonDefs, sizeof(buttonDefs));
+
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ static const uint16 keyCodesFMTowns[] = {
+ 93, 94, 95, 96, 67, 27, 24, 349, 350, 351, 352, 80, 27, 24, 30, 0, 31, 0, 29, 0, 28, 0, 127, 18, 27, 93, 94, 95, 96,
+ 49, 50, 51, 52, 53, 93, 94, 95, 96, 60, 62, 32, 353, 354, 97, 98, 27, 27, 97, 98, 97, 98, 54, 49, 50, 51, 52, 53, 27
+ };
+
+ const uint16 *c = keyCodesFMTowns;
+ for (int i = 0; i < ARRAYSIZE(buttonDefs); ++i) {
+ if (_buttonDefs[i].keyCode)
+ _buttonDefs[i].keyCode = *c++;
+ if (_buttonDefs[i].keyCode2)
+ _buttonDefs[i].keyCode2 = *c++;
+ }
+ }
+
_buttonCallbacks.clear();
_buttonCallbacks.reserve(ARRAYSIZE(buttonDefs));
@@ -696,7 +719,12 @@ void EoBCoreEngine::initMenus() {
{ 32, 40, 16, 24, 20, 3, 5 },
{ 33, 72, 16, 24, 20, 4, 5 },
{ 34, 104, 16, 24, 20, 5, 5 },
- { 35, 136, 16, 24, 20, 6, 5 }
+ { 35, 136, 16, 24, 20, 6, 5 },
+ // FM-Towns options menu
+ { 18, 12, 20, 158, 14, 32, 3 },
+ { 19, 12, 37, 158, 14, 50, 3 },
+ { 20, 12, 54, 158, 14, 21, 3 },
+ { 8, 128, 122, 40, 14, 19, 7 }
};
_menuButtonDefs = buttonDefs;
@@ -720,6 +748,12 @@ void EoBCoreEngine::initMenus() {
_menuDefs[4].numButtons = 8;
_menuDefs[4].firstButtonStrId = 36;
}
+
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ // assign FM-Towns style options menu
+ _menuDefs[2].numButtons = 4;
+ _menuDefs[2].firstButtonStrId = 44;
+ }
}
@@ -1226,35 +1260,6 @@ const uint8 EoBEngine::_monsterAcHitChanceTbl2[] = {
void DarkMoonEngine::initStaticResource() {
int temp;
_mainMenuStrings = _staticres->loadStrings(kEoB2MainMenuStrings, temp);
- _introStrings = _staticres->loadStrings(kEoB2IntroStrings, temp);
- _cpsFilesIntro = _staticres->loadStrings(kEoB2IntroCPSFiles, temp);
-
- _animIntro = new const DarkMoonAnimCommand*[44];
- for (int i = 0; i < 44; i++)
- _animIntro[i] = _staticres->loadEoB2SeqData(kEoB2IntroAnimData00 + i, temp);
-
- _shapesIntro = new const DarkMoonShapeDef*[13];
- memset(_shapesIntro, 0, sizeof(DarkMoonShapeDef *) * 13);
- _shapesIntro[0] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes00, temp);
- _shapesIntro[1] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes01, temp);
- _shapesIntro[4] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes04, temp);
- _shapesIntro[7] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes07, temp);
-
- _finaleStrings = _staticres->loadStrings(kEoB2FinaleStrings, temp);
- _creditsData = _staticres->loadRawData(kEoB2CreditsData, temp);
- _cpsFilesFinale = _staticres->loadStrings(kEoB2FinaleCPSFiles, temp);
-
- _animFinale = new const DarkMoonAnimCommand*[21];
- for (int i = 0; i < 21; i++)
- _animFinale[i] = _staticres->loadEoB2SeqData(kEoB2FinaleAnimData00 + i, temp);
-
- _shapesFinale = new const DarkMoonShapeDef*[13];
- memset(_shapesFinale, 0, sizeof(DarkMoonShapeDef *) * 13);
- _shapesFinale[0] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes00, temp);
- _shapesFinale[3] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes03, temp);
- _shapesFinale[7] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes07, temp);
- _shapesFinale[9] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes09, temp);
- _shapesFinale[10] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes10, temp);
_dscDoorType5Offs = _staticres->loadRawData(kEoBBaseDscDoorType5Offs, temp);
@@ -1273,6 +1278,26 @@ void DarkMoonEngine::initStaticResource() {
_wallOfForceDsNumH = _staticres->loadRawData(kEoB2WallOfForceNumH, temp);
_wallOfForceShpId = _staticres->loadRawData(kEoB2WallOfForceShpId, temp);
+ _utilMenuStrings = _staticres->loadStrings(kEoB2UtilMenuStrings, temp);
+ _2431Strings = _staticres->loadStrings(kEoB2Config2431Strings, temp);
+ _katakanaLines = _staticres->loadStrings(kEoB2KatakanaLines, temp);
+ _katakanaSelectStrings = _staticres->loadStrings(kEoB2KanaSelectStrings, temp);
+
+ _ascii2SjisTables = _staticres->loadStrings(kEoB2Ascii2SjisTables, temp);
+ _ascii2SjisTables2 = _staticres->loadStrings(kEoB2Ascii2SjisTables2, temp);
+ _saveNamePatterns = _staticres->loadStrings(kEoB2SaveNamePatterns, temp);
+
+ const uint8 *data = _staticres->loadRawData(kEoB2PcmSoundEffectsIngame, temp);
+ SoundResourceInfo_TownsEoB ingame(data, temp, 127);
+ data = _staticres->loadRawData(kEoB2PcmSoundEffectsIntro, temp);
+ SoundResourceInfo_TownsEoB intro(data, temp, 40);
+ data = _staticres->loadRawData(kEoB2PcmSoundEffectsFinale, temp);
+ SoundResourceInfo_TownsEoB finale(data, temp, 40);
+
+ _sound->initAudioResourceInfo(kMusicIngame, &ingame);
+ _sound->initAudioResourceInfo(kMusicIntro, &intro);
+ _sound->initAudioResourceInfo(kMusicFinale, &finale);
+
_monsterAcHitChanceTable1 = _monsterAcHitChanceTbl1;
_monsterAcHitChanceTable2 = _monsterAcHitChanceTbl2;
@@ -1327,49 +1352,12 @@ void DarkMoonEngine::initSpells() {
}
}
-const char *const DarkMoonEngine::_palFilesIntroVGA[] = {
- "PALETTE1.PAL",
- "PALETTE3.PAL",
- "PALETTE2.PAL",
- "PALETTE4.PAL",
- 0
-};
-
-const char *const DarkMoonEngine::_palFilesIntroEGA[] = {
- "PALETTE0.PAL",
- "PALETTE3.PAL",
- "PALETTE2.PAL",
- "PALETTE4.PAL",
- 0
-};
-
-const char *const DarkMoonEngine::_palFilesFinaleVGA[] = {
- "FINALE_0.PAL",
- "FINALE_0.PAL",
- "FINALE_1.PAL",
- "FINALE_2.PAL",
- "FINALE_3.PAL",
- "FINALE_4.PAL",
- "FINALE_5.PAL",
- "FINALE_6.PAL",
- "FINALE_7.PAL",
- 0
-};
-
-const char *const DarkMoonEngine::_palFilesFinaleEGA[] = {
- "FINALE_0.PAL",
- "FINALE_0.PAL",
- "FINALE_1.PAL",
- "FINALE_2.PAL",
- "FINALE_3.PAL",
- "FINALE_4.PAL",
- "FINALE_5.PAL",
- "FINALE_0.PAL",
- "FINALE_0.PAL",
- 0
+const KyraRpgGUISettings DarkMoonEngine::_guiSettingsFMTowns = {
+ { 9, 15, 95, 11, 7, { 221, 76 }, { 187, 162 }, { 95, 95 } },
+ { 186, 181, 183, 133, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180 }
};
-const KyraRpgGUISettings DarkMoonEngine::_guiSettings = {
+const KyraRpgGUISettings DarkMoonEngine::_guiSettingsDOS = {
{ 9, 15, 95, 9, 7, { 221, 76 }, { 189, 162 }, { 95, 95 } },
{ 186, 181, 183, 133, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180 }
};
diff --git a/engines/kyra/staticres_rpg.cpp b/engines/kyra/staticres_rpg.cpp
index 671d3dfd1d..55d14698fd 100644
--- a/engines/kyra/staticres_rpg.cpp
+++ b/engines/kyra/staticres_rpg.cpp
@@ -81,7 +81,7 @@ void KyraRpgEngine::initStaticResource() {
_dscTileIndex = _staticres->loadRawData(kRpgCommonDscTileIndex, temp);
_dscDim1 = (const int8 *)_staticres->loadRawData(kRpgCommonDscDimData1, temp);
_dscDim2 = (const int8 *)_staticres->loadRawData(kRpgCommonDscDimData2, temp);
- _dscUnk2 = _staticres->loadRawData(kRpgCommonDscUnk2, temp);
+ _dscDoorScaleOffs = _staticres->loadRawData(kRpgCommonDscDoorScaleOffs, temp);
_dscBlockMap = _staticres->loadRawData(kRpgCommonDscBlockMap, temp);
_dscBlockIndex = (const int8 *)_staticres->loadRawData(kRpgCommonDscBlockIndex, temp);
_dscDimMap = _staticres->loadRawData(kRpgCommonDscDimMap, temp);
diff --git a/engines/kyra/text_rpg.cpp b/engines/kyra/text_rpg.cpp
index 6dea66c14d..cc7ab068a7 100644
--- a/engines/kyra/text_rpg.cpp
+++ b/engines/kyra/text_rpg.cpp
@@ -75,10 +75,13 @@ void TextDisplayer_rpg::setupField(int dim, bool mode) {
_textDimData[dim].color2 = _vm->guiSettings()->colors.fill;
_screen->setScreenDim(dim);
- if (mode)
+ if (mode) {
+ _screen->set16bitShadingLevel(4);
clearCurDim();
- else
+ _screen->set16bitShadingLevel(0);
+ } else {
resetDimTextPositions(dim);
+ }
}
void TextDisplayer_rpg::resetDimTextPositions(int dim) {
@@ -123,7 +126,8 @@ void TextDisplayer_rpg::displayText(char *str, ...) {
int sdx = _screen->curDimIndex();
bool sjisTextMode = (_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
- int sjisOffs = sjisTextMode ? 8 : 9;
+ int sjisOffs = (sjisTextMode || _vm->game() == GI_EOB2) ? 8 : 9;
+ Screen::FontId of = (_vm->game() == GI_EOB2 && _vm->gameFlags().platform == Common::kPlatformFMTowns) ? _screen->setFont(Screen::FID_8_FNT) : _screen->_currentFont;
uint16 charsPerLine = (sd->w << 3) / (_screen->getFontWidth() + _screen->_charWidth);
@@ -225,6 +229,8 @@ void TextDisplayer_rpg::displayText(char *str, ...) {
if (_numCharsLeft)
printLine(_currentLine);
+
+ _screen->setFont(of);
}
char TextDisplayer_rpg::parseCommand() {
@@ -283,7 +289,7 @@ void TextDisplayer_rpg::readNextPara() {
void TextDisplayer_rpg::printLine(char *str) {
const ScreenDim *sd = _screen->_curDim;
int sdx = _screen->curDimIndex();
- bool sjisTextMode = (_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
+ bool sjisTextMode = _vm->gameFlags().lang == Common::JA_JPN && (_vm->gameFlags().use16ColorMode && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
int fh = (_screen->_currentFont == Screen::FID_SJIS_FNT) ? 9 : (_screen->getFontHeight() + _screen->_charOffset);
int lines = (sd->h - _screen->_charOffset) / fh;
@@ -301,7 +307,10 @@ void TextDisplayer_rpg::printLine(char *str) {
if (h2)
_screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK);
+ _screen->set16bitShadingLevel(4);
_screen->fillRect(sd->sx << 3, sd->sy + h1, ((sd->sx + sd->w) << 3) - 1, sd->sy + sd->h - 1, _textDimData[sdx].color2);
+ _screen->set16bitShadingLevel(0);
+
if (_textDimData[sdx].line)
_textDimData[sdx].line--;
}
@@ -482,7 +491,7 @@ void TextDisplayer_rpg::printLine(char *str) {
str[len] = 0;
_numCharsLeft = strlen(str);
- _lineWidth = sjisTextMode ? (_numCharsLeft << 2) : (_screen->_currentFont == Screen::FID_SJIS_FNT ? _numCharsLeft * 9: _screen->getTextWidth(str));
+ _lineWidth = sjisTextMode ? (_numCharsLeft << 2) : (_screen->_currentFont == Screen::FID_SJIS_FNT ? _numCharsLeft * 9 : _screen->getTextWidth(str));
if (!_numCharsLeft && (_textDimData[sdx].column + twoByteCharOffs) <= (sd->w << 3))
return;
@@ -499,7 +508,9 @@ void TextDisplayer_rpg::printDialogueText(int stringId, const char *pageBreakStr
assert(strlen(str) < kEoBTextBufferSize);
Common::strlcpy(_dialogueBuffer, str, kEoBTextBufferSize);
+ _screen->set16bitShadingLevel(4);
displayText(_dialogueBuffer);
+ _screen->set16bitShadingLevel(0);
if (pageBreakString) {
if (pageBreakString[0]) {
@@ -566,7 +577,7 @@ void TextDisplayer_rpg::textPageBreak() {
SWAP(_vm->_dialogueButtonLabelColor1, _vm->_dialogueButtonLabelColor2);
int cp = _screen->setCurPage(0);
- Screen::FontId cf = _screen->setFont((_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
+ Screen::FontId cf = _screen->setFont((_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode) ? Screen::FID_SJIS_FNT : ((_vm->game() == GI_EOB2 && _vm->gameFlags().platform == Common::kPlatformFMTowns) ? Screen::FID_8_FNT : Screen::FID_6_FNT));
if (_vm->game() == GI_LOL)
_vm->_timer->pauseSingleTimer(11, true);
@@ -614,8 +625,11 @@ void TextDisplayer_rpg::textPageBreak() {
_vm->gui_drawBox(x + 8, (y & ~7) - 1, 66, 10, 0xEE, 0xCC, -1);
_screen->printText(_pageBreakString, (x + 37 - (strlen(_pageBreakString) << 1) + 4) & ~3, (y + 2) & ~7, 0xC1, 0);
} else {
+ int yOffs = (_vm->game() == GI_EOB2 && _vm->gameFlags().platform == Common::kPlatformFMTowns) ? 1 : 2;
+ _screen->set16bitShadingLevel(4);
_vm->gui_drawBox(x, y, w, _vm->guiSettings()->buttons.height, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
- _screen->printText(_pageBreakString, x + (w >> 1) - (_vm->screen()->getTextWidth(_pageBreakString) >> 1), y + 2, _vm->_dialogueButtonLabelColor1, 0);
+ _screen->set16bitShadingLevel(0);
+ _screen->printText(_pageBreakString, x + (w >> 1) - (_vm->screen()->getTextWidth(_pageBreakString) >> 1), y + yOffs, _vm->_dialogueButtonLabelColor1, 0);
}
_vm->removeInputTop();
@@ -659,12 +673,14 @@ void TextDisplayer_rpg::textPageBreak() {
}
} while (loop && !_vm->shouldQuit());
+ _screen->set16bitShadingLevel(4);
if (_vm->gameFlags().use16ColorMode)
_screen->fillRect(x + 8, y, x + 57, y + 9, _textDimData[_screen->curDimIndex()].color2);
else
- _screen->fillRect(x, y, x + w - 1, y + 8, _textDimData[_screen->curDimIndex()].color2);
+ _screen->fillRect(x, y, x + w - 1, y + _vm->guiSettings()->buttons.height - 1, _textDimData[_screen->curDimIndex()].color2);
clearCurDim();
+ _screen->set16bitShadingLevel(0);
_screen->updateScreen();
if (_vm->game() == GI_LOL)
@@ -709,7 +725,9 @@ void TextDisplayer_rpg::displayWaitButton() {
while (!_vm->processDialogue() && !_vm->shouldQuit()) {}
+ _screen->set16bitShadingLevel(4);
_screen->fillRect(_vm->_dialogueButtonPosX[0], _vm->_dialogueButtonPosY[0], _vm->_dialogueButtonPosX[0] + _vm->_dialogueButtonWidth - 1, _vm->_dialogueButtonPosY[0] + _vm->guiSettings()->buttons.height - 1, _vm->guiSettings()->colors.fill);
+ _screen->set16bitShadingLevel(0);
_screen->updateScreen();
_vm->_dialogueButtonWidth = 95;
SWAP(_vm->_dialogueButtonLabelColor1, _vm->_dialogueButtonLabelColor2);