diff options
| author | athrxx | 2016-01-09 22:00:51 +0100 | 
|---|---|---|
| committer | athrxx | 2018-11-14 17:22:22 +0100 | 
| commit | f49eaa5654b2ee2e41b1794a4576d24967e2f7d7 (patch) | |
| tree | 9366d630ba3fc4d5f7579bc2602075e6dfe35c6b /engines | |
| parent | 61bd730bcf4ee311e79ab2fc49e3eca21018cdfe (diff) | |
| download | scummvm-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')
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);  | 
