From c35de374dfe545ffc5044a00a247c5814e3b250e Mon Sep 17 00:00:00 2001 From: athrxx Date: Sat, 20 Aug 2011 13:24:36 +0200 Subject: KYRA: (EOB) - lots of bug fixes, mostly for EOB II --- devtools/create_kyradat/create_kyradat.cpp | 9 ++++-- devtools/create_kyradat/create_kyradat.h | 3 +- devtools/create_kyradat/games.cpp | 3 +- devtools/create_kyradat/tables.cpp | 10 ++++-- dists/engine-data/kyra.dat | Bin 465202 -> 465243 bytes engines/kyra/detection.cpp | 10 +++--- engines/kyra/eob2.cpp | 10 ++++-- engines/kyra/eob2.h | 5 +-- engines/kyra/eobcommon.cpp | 20 ++++++------ engines/kyra/magic_eob.cpp | 17 ++++++---- engines/kyra/resource.h | 3 +- engines/kyra/saveload_eob.cpp | 7 +++++ engines/kyra/scene_eob.cpp | 10 ++++-- engines/kyra/screen_eob.cpp | 17 +--------- engines/kyra/script_eob.cpp | 48 +++++++++++++++-------------- engines/kyra/script_eob.h | 9 +++--- engines/kyra/sequences_eob2.cpp | 7 ++--- engines/kyra/staticres_eob.cpp | 3 +- engines/kyra/text_eob.cpp | 37 +++++++++++++--------- engines/kyra/timer_eob.cpp | 7 +++++ 20 files changed, 137 insertions(+), 98 deletions(-) diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp index ad56fb44c2..11e868f3ed 100644 --- a/devtools/create_kyradat/create_kyradat.cpp +++ b/devtools/create_kyradat/create_kyradat.cpp @@ -570,7 +570,8 @@ const ExtractFilename extractFilenames[] = { { kEob2Npc1Strings, kTypeStringList, true }, { kEob2Npc2Strings, kTypeStringList, true }, { kEob2MonsterDustStrings, kTypeStringList, true }, - { kEob2DranFoolsStrings, kTypeStringList, true }, + { kEob2DreamSteps, kTypeRawData, false }, + { kEob2KheldranStrings, kTypeStringList, true }, { kEob2HornStrings, kTypeStringList, true }, { kEob2HornSounds, kTypeRawData, false }, { kEob2WallOfForceDsX, kLolTypeRaw16, false }, @@ -1991,8 +1992,10 @@ const char *getIdString(const int id) { return "kEob2Npc2Strings"; case kEob2MonsterDustStrings: return "kEob2MonsterDustStrings"; - case kEob2DranFoolsStrings: - return "kEob2DranFoolsStrings"; + case kEob2DreamSteps: + return "kEob2DreamSteps"; + case kEob2KheldranStrings: + return "kEob2KheldranStrings"; case kEob2HornStrings: return "kEob2HornStrings"; case kEob2HornSounds: diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h index d7bcc4d986..4ac94755e7 100644 --- a/devtools/create_kyradat/create_kyradat.h +++ b/devtools/create_kyradat/create_kyradat.h @@ -552,7 +552,8 @@ enum kExtractID { kEob2Npc2Strings, kEob2MonsterDustStrings, - kEob2DranFoolsStrings, + kEob2DreamSteps, + kEob2KheldranStrings, kEob2HornStrings, kEob2HornSounds, diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp index 78baeb6b39..cc81abaa39 100644 --- a/devtools/create_kyradat/games.cpp +++ b/devtools/create_kyradat/games.cpp @@ -1594,7 +1594,8 @@ const int eob2FloppyNeed[] = { kEob2Npc1Strings, kEob2Npc2Strings, kEob2MonsterDustStrings, - kEob2DranFoolsStrings, + kEob2DreamSteps, + kEob2KheldranStrings, kEob2HornStrings, kEob2HornSounds, kEob2WallOfForceDsX, diff --git a/devtools/create_kyradat/tables.cpp b/devtools/create_kyradat/tables.cpp index 239ee6e1bd..064b3c80ae 100644 --- a/devtools/create_kyradat/tables.cpp +++ b/devtools/create_kyradat/tables.cpp @@ -3187,7 +3187,12 @@ const ExtractEntrySearchData kEob2MonsterDustStringsProvider[] = { EXTRACT_END_ENTRY }; -const ExtractEntrySearchData kEob2DranFoolsStringsProvider[] = { +const ExtractEntrySearchData kEob2DreamStepsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000E, 0x00000114, { { 0x27, 0x32, 0xCB, 0x89, 0x27, 0xC5, 0xDD, 0x91, 0xBE, 0x97, 0x62, 0xF5, 0x76, 0xF7, 0xCD, 0x25 } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob2KheldranStringsProvider[] = { { EN_ANY, kPlatformUnknown, { 0x0000001A, 0x00000887, { { 0xA6, 0xB4, 0x45, 0x1B, 0x33, 0x54, 0x36, 0xAD, 0x1D, 0xB1, 0xDA, 0xC3, 0x12, 0x85, 0x3C, 0x58 } } } }, { DE_DEU, kPlatformUnknown, { 0x00000012, 0x00000511, { { 0xEE, 0x21, 0xA8, 0x6E, 0xF7, 0xEC, 0x9A, 0x8D, 0xBA, 0x8D, 0xE3, 0x4A, 0x17, 0x15, 0xCA, 0x8C } } } }, EXTRACT_END_ENTRY @@ -4198,7 +4203,8 @@ const ExtractEntry extractProviders[] = { { kEob2Npc1Strings, kEob2Npc1StringsProvider }, { kEob2Npc2Strings, kEob2Npc2StringsProvider }, { kEob2MonsterDustStrings, kEob2MonsterDustStringsProvider }, - { kEob2DranFoolsStrings, kEob2DranFoolsStringsProvider }, + { kEob2DreamSteps, kEob2DreamStepsProvider }, + { kEob2KheldranStrings, kEob2KheldranStringsProvider }, { kEob2HornStrings, kEob2HornStringsProvider }, { kEob2HornSounds, kEob2HornSoundsProvider }, { kEob2WallOfForceDsX, kEob2WallOfForceDsXProvider }, diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat index 8d45a5f0d6..704c8adc3c 100644 Binary files a/dists/engine-data/kyra.dat and b/dists/engine-data/kyra.dat differ diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 44fbc0fe68..adfb1c612a 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -188,7 +188,7 @@ void KyraMetaEngine::removeSaveState(const char *target, int slot) const { // In Kyra games slot 0 can't be deleted, it's for restarting the game(s). // An exception makes Lands of Lore here, it does not have any way to restart the // game except via its main menu. - if (slot == 0 && !ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("lol")) + if (slot == 0 && !ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("lol") && !ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("eob") && !ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("eob2")) return; Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot); @@ -198,7 +198,7 @@ void KyraMetaEngine::removeSaveState(const char *target, int slot) const { SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename); - const bool lolGame = ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("lol"); + bool nonKyraGame = ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("lol") || ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("eob") || ConfMan.getDomain(target)->getVal("gameid").equalsIgnoreCase("eob2"); if (in) { Kyra::KyraEngine_v1::SaveHeader header; @@ -212,12 +212,12 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s // Slot 0 is used for the 'restart game' save in all three Kyrandia games, thus // we prevent it from being deleted. - desc.setDeletableFlag(slot != 0 || lolGame); + desc.setDeletableFlag(slot != 0 || nonKyraGame); // We don't allow quick saves (slot 990 till 998) to be overwritten. // The same goes for the 'Autosave', which is slot 999. Slot 0 will also // be protected in Kyra 1-3, since it's the 'restart game' save. - desc.setWriteProtectedFlag((slot == 0 && !lolGame) || slot >= 990); + desc.setWriteProtectedFlag((slot == 0 && !nonKyraGame) || slot >= 990); desc.setThumbnail(header.thumbnail); return desc; @@ -229,7 +229,7 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s // We don't allow quick saves (slot 990 till 998) to be overwritten. // The same goes for the 'Autosave', which is slot 999. Slot 0 will also // be protected in Kyra 1-3, since it's the 'restart game' save. - desc.setWriteProtectedFlag((slot == 0 && !lolGame) || slot >= 990); + desc.setWriteProtectedFlag((slot == 0 && !nonKyraGame) || slot >= 990); return desc; } diff --git a/engines/kyra/eob2.cpp b/engines/kyra/eob2.cpp index 0ecdba0fd3..0ffca10093 100644 --- a/engines/kyra/eob2.cpp +++ b/engines/kyra/eob2.cpp @@ -77,6 +77,10 @@ Common::Error DarkMoonEngine::init() { _color13 = 177; _color14 = 182; + // Necessary wall hacks (where the original code makes out of bounds accesses) + _wllWallFlags[183] = 0x50; + _wllVmpMap[183] = 1; + return Common::kNoError; } @@ -312,6 +316,8 @@ const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16) { int shapeIndex = type * 3 + 2 - mDim; uint8 *shp = _doorShapes[shapeIndex]; + if (!shp) + return; if ((_doorType[type] == 0) || (_doorType[type] == 1)) { y = _dscDoorY1[mDim] - shp[1]; @@ -392,7 +398,7 @@ void DarkMoonEngine::useHorn(int charIndex, int weaponSlot) { bool DarkMoonEngine::checkPartyStatusExtra() { if (checkScriptFlags(0x100000)) - seq_dranFools(); + seq_kheldran(); return _gui->confirmDialogue2(14, 67, 1); } @@ -462,7 +468,7 @@ void DarkMoonEngine::characterLevelGain(int charIndex) { if (er == 0xffffffff) continue; - increaseCharacterExperience(charIndex, er - c->experience[i]); + increaseCharacterExperience(charIndex, er - c->experience[i] + 1); } } diff --git a/engines/kyra/eob2.h b/engines/kyra/eob2.h index f24db79e62..6da09010b4 100644 --- a/engines/kyra/eob2.h +++ b/engines/kyra/eob2.h @@ -88,10 +88,11 @@ private: // Ingame sequence void seq_nightmare(); - void seq_dranFools(); + void seq_kheldran(); void seq_dranDragonTransformation(); - const char *const *_dranFoolsStrings; + const int8 *_dreamSteps; + const char *const *_kheldranStrings; // characters void drawNpcScene(int npcIndex); diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index 3a298d84ad..67609520fa 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -302,13 +302,6 @@ Common::Error EobCoreEngine::init() { memset(&_wllShapeMap[3], -1, 5); memset(&_wllShapeMap[13], -1, 5); - /*int clen = _flags.gameID == GI_EOB2 ? 80 : 70; - memcpy(&_wllShapeMap[256 - clen], _wllVmpMap, clen); - memcpy(&_specialWallTypes[256 - 2 * clen], _wllVmpMap, clen); - memcpy(&_specialWallTypes[256 - clen], _wllShapeMap, clen); - memcpy(&_wllWallFlags[256 - 2 * clen], _wllShapeMap, clen); - memcpy(&_wllWallFlags[256 - clen], _specialWallTypes, clen);*/ - _wllVcnOffset = 16; _monsters = new EobMonsterInPlay[30]; @@ -1248,6 +1241,7 @@ void EobCoreEngine::initDialogueSequence() { _txt->resetPageBreakString(); gui_updateControls(); + //_allowSkip = true; _sound->playTrack(0); Common::SeekableReadStream *s = _res->createReadStream("TEXT.DAT"); @@ -1263,6 +1257,7 @@ void EobCoreEngine::restoreAfterDialogueSequence() { _dialogueLastBitmap[0] = 0; gui_restorePlayField(); + //_allowSkip = false; _screen->setScreenDim(7); if (_flags.gameID == GI_EOB2) @@ -1603,14 +1598,18 @@ bool EobCoreEngine::checkPassword() { for (int i = 0; i < 3; i++) { _screen->fillRect(_screen->_curDim->sx << 3, _screen->_curDim->sy, ((_screen->_curDim->sx + _screen->_curDim->w) << 3) - 1, (_screen->_curDim->sy + _screen->_curDim->h) - 1, _bkgColor_1); int c = rollDice(1, _mnNumWord - 1, -1); - _screen->drawShape(0, _largeItemShapes[_mnDef[c << 2]], 100, 2, 13); + const uint8 *shp = (_mnDef[c << 2] < _numLargeItemShapes) ? _largeItemShapes[_mnDef[c << 2]] : (_mnDef[c << 2] < 15 ? 0 : _smallItemShapes[_mnDef[c << 2] - 15]); + assert(shp); + _screen->drawShape(0, shp, 100, 2, 13); _screen->printShadedText(Common::String::format(_mnPrompt[0], _mnDef[(c << 2) + 1], _mnDef[(c << 2) + 2]).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy, _screen->_curDim->unk8, _bkgColor_1); memset(answ, 0, 20); gui_drawBox(76, 100, 133, 14, _color2_1, _color1_1, -1); gui_drawBox(77, 101, 131, 12, _color2_1, _color1_1, -1); if (_gui->getTextInput(answ, 10, 103, 15, _screen->_curDim->unk8, _bkgColor_1, 8) < 0) i = 3; - if (scumm_stricmp(_mnWord[c], answ) && i == 2) + if (!scumm_stricmp(_mnWord[c], answ)) + break; + else if (i == 2) return false; } @@ -1806,7 +1805,7 @@ int EobCoreEngine::calcCharacterDamage(int charIndex, int times, int itemOrPips, EobCharacter *c = &_characters[charIndex]; if (savingThrowType != 5) { - if (trySavingThrow(c, _charClassModUnk[c->cClass], c->level[0], savingThrowType, c->raceSex)) + if (trySavingThrow(c, _charClassModUnk[c->cClass], c->level[0], savingThrowType, c->raceSex >> 1 /*fix bug in original code by adding a right shift*/)) s = savingThrowReduceDamage(savingThrowEffect, s); } @@ -2006,6 +2005,7 @@ void EobCoreEngine::monsterCloseAttack(EobMonsterInPlay *m) { _txt->printMessage(_ripItemStrings[(_characters[c].raceSex & 1) ^ 1], -1, _characters[c].name); printFullItemName(itm); _txt->printMessage(_ripItemStrings[2]); + break; } gui_drawCharPortraitWithStats(c); } diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index 646d389706..0424558b04 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -360,7 +360,7 @@ void EobCoreEngine::startSpell(int spell) { if (_castScrollSlot) { gui_updateSlotAfterScrollUse(); } else { - c->disabledSlots |= 4; + _characters[_openBookChar].disabledSlots |= 4; setCharEventTimer(_openBookChar, 72, 11, 1); gui_toggleButtons(); gui_drawSpellbook(); @@ -405,7 +405,6 @@ void EobCoreEngine::sparkEffectDefensive(int charIndex) { _screen->updateScreen(); } } - resetSkipFlag(); delay(2 * _tickLength); } @@ -430,7 +429,6 @@ void EobCoreEngine::sparkEffectOffensive() { if (shpIndex) _screen->drawShape(2, _sparkShapes[shpIndex - 1], _sparkEffectOfX[ii], _sparkEffectOfY[ii], 0); } - resetSkipFlag(); delay(2 * _tickLength); _screen->copyRegion(0, 0, 0, 0, 176, 120, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); @@ -444,6 +442,7 @@ void EobCoreEngine::sparkEffectOffensive() { } void EobCoreEngine::setSpellEventTimer(int spell, int timerBaseFactor, int timerLength, int timerLevelFactor, int updateExistingTimer) { + assert (spell >= 0); int l = _openBookType == 1 ? getClericPaladinLevel(_openBookChar) : getMageLevel(_openBookChar); uint32 countdown = timerLength * timerBaseFactor + timerLength * l * timerLevelFactor; setCharEventTimer(_activeSpellCharId, countdown, -spell, updateExistingTimer); @@ -753,7 +752,7 @@ int EobCoreEngine::findFirstCharacterSpellTarget() { } int EobCoreEngine::findNextCharacterSpellTarget(int curCharIndex) { - for (; _characterSpellTarget < 6; _characterSpellTarget++) { + for (_characterSpellTarget++; _characterSpellTarget < 6; ) { if (++curCharIndex == 6) curCharIndex = 0; if (testCharacter(curCharIndex, 3)) @@ -763,8 +762,14 @@ int EobCoreEngine::findNextCharacterSpellTarget(int curCharIndex) { } int EobCoreEngine::charDeathSavingThrow(int charIndex, int div) { - if (specialAttackSavingThrow(charIndex, 4)) + bool _beholderOrgBhv = true; + // Due to a bug in the original code the saving throw result is completely ignored + // here. The Beholders' disintegrate spell will alway succeed while their flesh to + // stone spell will always fail. + if (_beholderOrgBhv) div >>= 1; + else + div = specialAttackSavingThrow(charIndex, 4) ? 1 : 0; return div; } @@ -1226,7 +1231,7 @@ bool EobCoreEngine::spellCallback_end_flameStrike(void *obj) { } void EobCoreEngine::spellCallback_start_raiseDead() { - if (_characters[_activeSpellCharId].hitPointsCur == -10 || ((_characters[_activeSpellCharId].raceSex >> 1) == 1)) { + if (_characters[_activeSpellCharId].hitPointsCur == -10 && ((_characters[_activeSpellCharId].raceSex >> 1) != 1)) { _characters[_activeSpellCharId].hitPointsCur = 1; gui_drawCharPortraitWithStats(_activeSpellCharId); } else { diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index cd3865736f..a7060cdf6d 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -626,7 +626,8 @@ enum KyraResources { kEob2Npc2Strings, kEob2MonsterDustStrings, - kEob2DranFoolsStrings, + kEob2DreamSteps, + kEob2KheldranStrings, kEob2HornStrings, kEob2HornSounds, diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp index 847f304288..01fbd75cfe 100644 --- a/engines/kyra/saveload_eob.cpp +++ b/engines/kyra/saveload_eob.cpp @@ -366,6 +366,13 @@ Common::Error EobCoreEngine::loadGameState(int slot) { _sceneUpdateRequired = true; _screen->setFont(Screen::FID_6_FNT); + for (int i = 0; i < 6; i++) { + for (int ii = 0; ii < 10; ii++) { + if (_characters[i].events[ii] == -57) + spellCallback_start_trueSeeing(); + } + } + _screen->setCurPage(0); gui_drawPlayField(false); diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp index 1bd7fca04a..98cd60dcd9 100644 --- a/engines/kyra/scene_eob.cpp +++ b/engines/kyra/scene_eob.cpp @@ -647,8 +647,12 @@ void EobCoreEngine::loadLevel(int level, int sub) { delete s; } - Common::String gfxFile = initLevelData(sub); - + Common::String gfxFile; + // Work around for issue with corrupt (incomplete) monster property data + // when loading a savegame saved in a sub level + for (int i = 0; i <= sub; i++) + gfxFile = initLevelData(i); + const uint8 *data = _screen->getCPagePtr(5); const uint8 *pos = data + READ_LE_UINT16(data); uint16 len = READ_LE_UINT16(pos); @@ -1142,7 +1146,7 @@ int EobCoreEngine::calcNewBlockPositionAndTestPassability(uint16 curBlock, uint1 int f = _wllWallFlags[w]; //if (!f) - assert((_flags.gameID == GI_EOB1 && w < 70) || (_flags.gameID == GI_EOB2 && w < 80)); + assert((_flags.gameID == GI_EOB1 && w < 70) || (_flags.gameID == GI_EOB2 && w < 80)); if (_flags.gameID == GI_EOB2 && w == 74 && _currentBlock == curBlock) { for (int i = 0; i < 5; i++) { diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp index d29af69f0a..9c67750ba8 100644 --- a/engines/kyra/screen_eob.cpp +++ b/engines/kyra/screen_eob.cpp @@ -774,15 +774,8 @@ 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)) { + if (posWithinRect(px, py, rX1, rY1, rX2, rY2)) setPagePixel(0, px, py, ptr6[i]); - if (i % 5 == 0) { - updateScreen(); - uint32 cur = _system->getMillis(); - if (end > cur) - _system->delayMillis(end - cur); - } - } } } @@ -914,14 +907,6 @@ void Screen_Eob::drawVortex(int numElements, int radius, int stepSize, int, int 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 (ii % 15 == 0) { - updateScreen(); - uint32 cur = _system->getMillis(); - if (nextDelay > cur) - _system->delayMillis(nextDelay - cur); - nextDelay += 1; - } } } diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp index 6feac6bd77..1dbb02414f 100644 --- a/engines/kyra/script_eob.cpp +++ b/engines/kyra/script_eob.cpp @@ -106,8 +106,8 @@ EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _v Opcode(oeob_calcAndInflictCharacterDamage); Opcode(oeob_jump); Opcode(oeob_end); - Opcode(oeob_popPosAndReturn); - Opcode(oeob_pushPosAndJump); + Opcode(oeob_returnFromSubroutine); + Opcode(oeob_callSubroutine); OpcodeAlt(oeob_eval); Opcode(oeob_deleteItem); Opcode(oeob_loadNewLevelOrMonsters); @@ -125,6 +125,7 @@ EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _v #undef OpcodeAlt _scriptData = 0; + _scriptSize = 0; _abortScript = 0; _abortAfterSubroutine = 0; @@ -134,9 +135,9 @@ EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _v _lastScriptFunc = 0; _lastScriptSub = 0; - _scriptPosStack = new int8*[10]; - memset(_scriptPosStack, 0, 10 * sizeof(int8*)); - _scriptPosStackIndex = 0; + _subroutineStack = new int8*[10]; + memset(_subroutineStack, 0, 10 * sizeof(int8*)); + _subroutineStackPos = 0; _flagTable = new uint32[18]; memset(_flagTable, 0, 18 * sizeof(uint32)); @@ -145,14 +146,14 @@ EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _v memset(_stack, 0, 30 * sizeof(int16)); _stackIndex = 0; - memset(_scriptPosStack, 0, sizeof(_scriptPosStack)); - _scriptPosStackIndex = 0; + memset(_subroutineStack, 0, sizeof(_subroutineStack)); + _subroutineStackPos = 0; _activeCharacter = -1; } EobInfProcessor::~EobInfProcessor() { - delete[] _scriptPosStack; + delete[] _subroutineStack; delete[] _flagTable; delete[] _stack; delete[] _scriptData; @@ -163,8 +164,9 @@ EobInfProcessor::~EobInfProcessor() { void EobInfProcessor::loadData(const uint8 *data, uint32 dataSize) { delete[] _scriptData; - _scriptData = new int8[dataSize]; - memcpy(_scriptData, data, dataSize); + _scriptSize = dataSize; + _scriptData = new int8[_scriptSize]; + memcpy(_scriptData, data, _scriptSize); } void EobInfProcessor::run(int func, int sub) { @@ -382,7 +384,7 @@ int EobInfProcessor::oeob_movePartyOrObject(int8 *data) { int bc = _lastScriptSub; int bd = _abortScript; int be = _activeCharacter; - int bf = _scriptPosStackIndex; + int bf = _subroutineStackPos; _vm->moveParty(d); @@ -392,7 +394,7 @@ int EobInfProcessor::oeob_movePartyOrObject(int8 *data) { _abortScript = bd; _activeCharacter = be; if (!_abortAfterSubroutine) - _scriptPosStackIndex = bf; + _subroutineStackPos = bf; _vm->_sceneDefaultUpdate = 0; } else if ((a == -31 && _vm->game() == GI_EOB2) || a == -11) { @@ -589,7 +591,6 @@ int EobInfProcessor::oeob_playSoundEffect(int8 *data) { int EobInfProcessor::oeob_removeFlags(int8 *data) { int8 *pos = data; int8 a = *pos++; - int8 b = *pos++; switch (a) { case -47: @@ -601,11 +602,11 @@ int EobInfProcessor::oeob_removeFlags(int8 *data) { break; case -17: - _flagTable[_vm->_currentLevel] &= ~(1 << b); + _flagTable[_vm->_currentLevel] &= ~(1 << (*pos++)); break; case -16: - _flagTable[17] &= ~(1 << b); + _flagTable[17] &= ~(1 << (*pos++)); break; default: @@ -667,28 +668,29 @@ int EobInfProcessor::oeob_jump(int8 *data) { int EobInfProcessor::oeob_end(int8 *data) { _abortScript = 1; - _scriptPosStackIndex = 0; + _subroutineStackPos = 0; return 0; } -int EobInfProcessor::oeob_popPosAndReturn(int8 *data) { +int EobInfProcessor::oeob_returnFromSubroutine(int8 *data) { int8 *pos = data; - if (_scriptPosStackIndex) - pos = _scriptPosStack[--_scriptPosStackIndex]; + if (_subroutineStackPos) + pos = _subroutineStack[--_subroutineStackPos]; else _abortScript = 1; return pos - data; } -int EobInfProcessor::oeob_pushPosAndJump(int8 *data) { +int EobInfProcessor::oeob_callSubroutine(int8 *data) { int8 *pos = data; uint16 offs = READ_LE_UINT16(pos); + assert(offs < _scriptSize); pos += 2; - if (_scriptPosStackIndex < 10) { - _scriptPosStack[_scriptPosStackIndex++] = pos; + if (_subroutineStackPos < 10) { + _subroutineStack[_subroutineStackPos++] = pos; pos = _scriptData + offs; } @@ -1245,7 +1247,7 @@ int EobInfProcessor::oeob_loadNewLevelOrMonsters(int8 *data) { _vm->_sceneUpdateRequired = true; _vm->gui_drawAllCharPortraitsWithStats(); - _scriptPosStackIndex = 0; + _subroutineStackPos = 0; } else { cmd = *pos++; diff --git a/engines/kyra/script_eob.h b/engines/kyra/script_eob.h index 648d214017..8f44c7f6f9 100644 --- a/engines/kyra/script_eob.h +++ b/engines/kyra/script_eob.h @@ -69,8 +69,8 @@ private: int oeob_calcAndInflictCharacterDamage(int8 *data); int oeob_jump(int8 *data); int oeob_end(int8 *data); - int oeob_popPosAndReturn(int8 *data); - int oeob_pushPosAndJump(int8 *data); + int oeob_returnFromSubroutine(int8 *data); + int oeob_callSubroutine(int8 *data); int oeob_eval_v1(int8 *data); int oeob_eval_v2(int8 *data); int oeob_deleteItem(int8 *data); @@ -94,6 +94,7 @@ private: Common::Array _opcodes; int8 *_scriptData; + uint16 _scriptSize; uint8 _abortScript; uint16 _abortAfterSubroutine; @@ -103,8 +104,8 @@ private: uint16 _lastScriptFunc; uint16 _lastScriptSub; - int8 **_scriptPosStack; - int _scriptPosStackIndex; + int8 **_subroutineStack; + int _subroutineStackPos; uint32 *_flagTable; diff --git a/engines/kyra/sequences_eob2.cpp b/engines/kyra/sequences_eob2.cpp index ea96779bb1..dcf293bd52 100644 --- a/engines/kyra/sequences_eob2.cpp +++ b/engines/kyra/sequences_eob2.cpp @@ -1282,12 +1282,11 @@ void DarkMoonEngine::seq_nightmare() { _txt->printDialogueText(99, 0); snd_playSoundEffect(54); - static const int8 dreamSteps[] = { 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 3, 2, 1, 0, -1 }; static const uint8 seqX[] = { 0, 20, 0, 20 }; static const uint8 seqY[] = { 0, 0, 96, 96 }; static const uint8 seqDelay[] = { 12, 7, 7, 12 }; - for (const int8 *i = dreamSteps; *i != -1; ++i) { + for (const int8 *i = _dreamSteps; *i != -1; ++i) { drawSequenceBitmap("DREAM", 0, seqX[*i], seqY[*i], 0); delay(seqDelay[*i] * _tickLength); } @@ -1299,14 +1298,14 @@ void DarkMoonEngine::seq_nightmare() { _screen->setFont(of); } -void DarkMoonEngine::seq_dranFools() { +void DarkMoonEngine::seq_kheldran() { Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); initDialogueSequence(); gui_drawDialogueBox(); static const char file[] = "KHELDRAN"; - _txt->printDialogueText(_dranFoolsStrings[0]); + _txt->printDialogueText(_kheldranStrings[0]); drawSequenceBitmap(file, 0, 0, 0, 0); _txt->printDialogueText(20, _moreStrings[0]); snd_playSoundEffect(56); diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index 57ee737ba0..274feba4fa 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -1280,7 +1280,8 @@ void DarkMoonEngine::initStaticResource() { _npc1Strings = _staticres->loadStrings(kEob2Npc1Strings, temp); _npc2Strings = _staticres->loadStrings(kEob2Npc2Strings, temp); _monsterDustStrings = _staticres->loadStrings(kEob2MonsterDustStrings, temp); - _dranFoolsStrings = _staticres->loadStrings(kEob2DranFoolsStrings, temp); + _dreamSteps = (const int8*)_staticres->loadRawData(kEob2DreamSteps, temp); + _kheldranStrings = _staticres->loadStrings(kEob2KheldranStrings, temp); _hornStrings = _staticres->loadStrings(kEob2HornStrings, temp); _hornSounds = _staticres->loadRawData(kEob2HornSounds, temp); diff --git a/engines/kyra/text_eob.cpp b/engines/kyra/text_eob.cpp index 318147c679..a2cc5c6e00 100644 --- a/engines/kyra/text_eob.cpp +++ b/engines/kyra/text_eob.cpp @@ -29,16 +29,18 @@ #include "common/system.h" -#define EOBTEXTBUFFERSIZE 2048 - namespace Kyra { +enum { + kEobTextBufferSize = 2048 +}; + TextDisplayer_Eob::TextDisplayer_Eob(LolEobBaseEngine *engine, Screen *sScreen) : _vm(engine), _screen(sScreen), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), _allowPageBreak(true), _numCharsLeft(0), _numCharsPrinted(0), _sjisLineBreakFlag(false), _waitButtonMode(1) { - _dialogueBuffer = new char[EOBTEXTBUFFERSIZE]; - memset(_dialogueBuffer, 0, EOBTEXTBUFFERSIZE); + _dialogueBuffer = new char[kEobTextBufferSize]; + memset(_dialogueBuffer, 0, kEobTextBufferSize); _currentLine = new char[85]; memset(_currentLine, 0, 85); @@ -221,12 +223,14 @@ void TextDisplayer_Eob::displayText(char *str, ...) { break; default: - _lineWidth += (pc98PrintFlag ? 4 : _screen->getCharWidth((uint8)c)); - _currentLine[_numCharsLeft++] = c; - _currentLine[_numCharsLeft] = 0; + if (_vm->game() == GI_LOL || c > 30) { + _lineWidth += (pc98PrintFlag ? 4 : _screen->getCharWidth((uint8)c)); + _currentLine[_numCharsLeft++] = c; + _currentLine[_numCharsLeft] = 0; - if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3)) - printLine(_currentLine); + if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3)) + printLine(_currentLine); + } } c = parseCommand(); @@ -271,6 +275,10 @@ void TextDisplayer_Eob::readNextPara() { _tempString1 = 0; } + if (d & 0x80) { + warning("TextDisplayer_Eob::readNextPara():"); + } + _ctrl[1] = d; _ctrl[2] = 0; } @@ -442,8 +450,8 @@ void TextDisplayer_Eob::printLine(char *str) { void TextDisplayer_Eob::printDialogueText(int stringId, const char *pageBreakString) { const char * str = (const char *)(screen()->getCPagePtr(5) + READ_LE_UINT16(&screen()->getCPagePtr(5)[(stringId - 1) << 1])); - assert (strlen(str) < EOBTEXTBUFFERSIZE); - Common::strlcpy(_dialogueBuffer, str, EOBTEXTBUFFERSIZE); + assert (strlen(str) < kEobTextBufferSize); + Common::strlcpy(_dialogueBuffer, str, kEobTextBufferSize); displayText(_dialogueBuffer); @@ -457,8 +465,8 @@ void TextDisplayer_Eob::printDialogueText(int stringId, const char *pageBreakStr } void TextDisplayer_Eob::printDialogueText(const char *str, bool wait) { - assert (strlen(str) < EOBTEXTBUFFERSIZE); - Common::strlcpy(_dialogueBuffer, str, EOBTEXTBUFFERSIZE); + assert (strlen(str) < kEobTextBufferSize); + Common::strlcpy(_dialogueBuffer, str, kEobTextBufferSize); strcpy(_dialogueBuffer, str); displayText(_dialogueBuffer); @@ -474,7 +482,7 @@ void TextDisplayer_Eob::printMessage(const char *str, int textColor, ...) { va_list args; va_start(args, textColor); - vsnprintf(_dialogueBuffer, 240, str, args); + vsnprintf(_dialogueBuffer, kEobTextBufferSize - 1, str, args); va_end(args); displayText(_dialogueBuffer); @@ -655,6 +663,7 @@ void TextDisplayer_Eob::displayWaitButton() { while (!vm()->processDialogue() && !vm()->shouldQuit()) {} _screen->fillRect(vm()->_dialogueButtonPosX[0], vm()->_dialogueButtonPosY[0], vm()->_dialogueButtonPosX[0] + vm()->_dialogueButtonW - 1, vm()->_dialogueButtonPosY[0] + vm()->_dialogueButtonH - 1, vm()->_bkgColor_1); + _screen->updateScreen(); vm()->_dialogueButtonW = 95; SWAP(vm()->_dialogueButtonLabelCol1, vm()->_dialogueButtonLabelCol2); clearCurDim(); diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp index caeae8cb29..f36688df39 100644 --- a/engines/kyra/timer_eob.cpp +++ b/engines/kyra/timer_eob.cpp @@ -221,6 +221,13 @@ void EobCoreEngine::advanceTimers(uint32 millis) { } } } + + for (int i = 0; i < 5; i++) { + if (_wallsOfForce[i].duration > ct) { + uint32 chrt = _wallsOfForce[i].duration - ct; + _wallsOfForce[i].duration = chrt > millis ? ct + chrt - millis : ct; + } + } } void EobCoreEngine::timerProcessCharacterExchange(int timerNum) { -- cgit v1.2.3