From 6e3474896cec0e42c2f5ac7ccb5783981d746fcc Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Wed, 25 Jun 2008 00:55:18 +0000 Subject: Kyra and Lure are now using the new _quit flag svn-id: r32772 --- engines/kyra/gui_hof.cpp | 2 +- engines/kyra/gui_lok.cpp | 12 ++++++------ engines/kyra/gui_mr.cpp | 2 +- engines/kyra/gui_v2.cpp | 4 ++-- engines/kyra/kyra_hof.cpp | 10 +++++----- engines/kyra/kyra_lok.cpp | 18 +++++++++--------- engines/kyra/kyra_mr.cpp | 10 +++++----- engines/kyra/kyra_v1.cpp | 6 ++---- engines/kyra/kyra_v1.h | 5 +---- engines/kyra/kyra_v2.cpp | 6 +++--- engines/kyra/saveload.cpp | 2 +- engines/kyra/saveload_lok.cpp | 2 +- engines/kyra/scene_hof.cpp | 2 +- engines/kyra/scene_mr.cpp | 2 +- engines/kyra/script_mr.cpp | 2 +- engines/kyra/sequences_hof.cpp | 22 +++++++++++----------- engines/kyra/sequences_lok.cpp | 14 +++++++------- engines/kyra/text_hof.cpp | 12 ++++++------ engines/kyra/text_mr.cpp | 10 +++++----- 19 files changed, 69 insertions(+), 74 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 555934cb7f..5281919a0d 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -500,7 +500,7 @@ void KyraEngine_HoF::bookLoop() { showBookPage(); _bookShown = true; - while (_bookShown && !_quitFlag) { + while (_bookShown && !_quit) { checkInput(buttonList); removeInputTop(); diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 6fa30c9e9a..f3f1f50d93 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -459,7 +459,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { updateAllMenuButtons(); } - while (_displayMenu && !_vm->_quitFlag) { + while (_displayMenu && !_vm->_quit) { Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[_toplevelMenu], mouse.x, mouse.y); processButtonList(_menuButtonList, 0, 0); @@ -582,7 +582,7 @@ int GUI_LoK::saveGameMenu(Button *button) { _displaySubMenu = true; _cancelSubMenu = false; - while (_displaySubMenu && !_vm->_quitFlag) { + while (_displaySubMenu && !_vm->_quit) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); @@ -631,7 +631,7 @@ int GUI_LoK::loadGameMenu(Button *button) { _vm->_gameToLoad = -1; - while (_displaySubMenu && !_vm->_quitFlag) { + while (_displaySubMenu && !_vm->_quit) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); @@ -719,7 +719,7 @@ int GUI_LoK::saveGame(Button *button) { } redrawTextfield(); - while (_displaySubMenu && !_vm->_quitFlag) { + while (_displaySubMenu && !_vm->_quit) { getInput(); updateSavegameString(); Common::Point mouse = _vm->getMousePos(); @@ -795,7 +795,7 @@ bool GUI_LoK::quitConfirm(const char *str) { _displaySubMenu = true; _cancelSubMenu = true; - while (_displaySubMenu && !_vm->_quitFlag) { + while (_displaySubMenu && !_vm->_quit) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[1], mouse.x, mouse.y); @@ -861,7 +861,7 @@ int GUI_LoK::gameControlsMenu(Button *button) { _displaySubMenu = true; _cancelSubMenu = false; - while (_displaySubMenu && !_vm->_quitFlag) { + while (_displaySubMenu && !_vm->_quit) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[5], mouse.x, mouse.y); diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 6822b303c3..46834bb335 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -868,7 +868,7 @@ void KyraEngine_MR::processAlbum() { albumNewPage(); _album.running = true; - while (_album.running && !_quitFlag) { + while (_album.running && !_quit) { updateInput(); checkInput(buttonList); removeInputTop(); diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index 2819c4f077..c056b1561d 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -822,12 +822,12 @@ void GUI_v2::checkTextfieldInput() { while (_vm->_eventMan->pollEvent(event) && running) { switch (event.type) { case Common::EVENT_QUIT: - _vm->_quitFlag = true; + _vm->_quit = true; break; case Common::EVENT_KEYDOWN: if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) - _vm->_quitFlag = true; + _vm->_quit = true; else _keyPressed = event.kbd; running = false; diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 57f0dcc24a..040ee0526f 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -311,7 +311,7 @@ int KyraEngine_HoF::go() { seq_playSequences(kSequenceFunters, kSequenceFrash); } - return 0; + return _rtl; } void KyraEngine_HoF::startup() { @@ -440,9 +440,9 @@ void KyraEngine_HoF::startup() { void KyraEngine_HoF::runLoop() { _screen->updateScreen(); - _quitFlag = false; + _quit = false; _runFlag = true; - while (!_quitFlag && _runFlag) { + while (!_quit && _runFlag) { if (_deathHandler >= 0) { removeHandItem(); delay(5); @@ -1603,7 +1603,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run, int delayTime, in _invWsa.timer = _system->getMillis(); if (run) { - while (_invWsa.running && !skipFlag() && !_quitFlag) { + while (_invWsa.running && !skipFlag() && !_quit) { update(); _system->delayMillis(10); } @@ -1977,7 +1977,7 @@ void KyraEngine_HoF::playTim(const char *filename) { return; _tim->resetFinishedFlag(); - while (!_quitFlag && !_tim->finished()) { + while (!_quit && !_tim->finished()) { _tim->exec(tim, 0); if (_chatText) updateWithText(); diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index c852f6e3ee..7790fa38a1 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -300,8 +300,8 @@ int KyraEngine_LoK::go() { if (_gameToLoad == -1) { setGameFlag(0xEF); seq_intro(); - if (_quitFlag) - return 0; + if (_quit) + return _rtl; if (_skipIntroFlag && _abortIntroFlag) resetGameFlag(0xEF); } @@ -309,7 +309,7 @@ int KyraEngine_LoK::go() { resetGameFlag(0xEF); mainLoop(); } - return 0; + return _rtl; } @@ -399,7 +399,7 @@ void KyraEngine_LoK::startup() { void KyraEngine_LoK::mainLoop() { debugC(9, kDebugLevelMain, "KyraEngine_LoK::mainLoop()"); - while (!_quitFlag) { + while (!_quit) { int32 frameTime = (int32)_system->getMillis(); _skipFlag = false; @@ -444,7 +444,7 @@ void KyraEngine_LoK::mainLoop() { } void KyraEngine_LoK::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quitFlag) { + while (_system->getMillis() < timestamp && !_quit) { if (updateTimers) _timer->update(); @@ -476,7 +476,7 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { if (event.kbd.keycode == 'd') _debugger->attach(); else if (event.kbd.keycode == 'q') - _quitFlag = true; + _quit = true; } else if (event.kbd.keycode == '.') { _skipFlag = true; } else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) { @@ -529,19 +529,19 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) _skipFlag = false; - if (amount > 0 && !_skipFlag && !_quitFlag) + if (amount > 0 && !_skipFlag && !_quit) _system->delayMillis(10); if (_skipFlag) _sound->voiceStop(); - } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag); + } while (!_skipFlag && _system->getMillis() < start + amount && !_quit); } void KyraEngine_LoK::waitForEvent() { bool finished = false; Common::Event event; - while (!finished && !_quitFlag) { + while (!finished && !_quit) { while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 8a49b8e155..643cb9521f 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -263,7 +263,7 @@ int KyraEngine_MR::go() { running = false; } - while (running && !_quitFlag) { + while (running && !_quit) { _screen->_curPage = 0; _screen->clearPage(0); @@ -272,14 +272,14 @@ int KyraEngine_MR::go() { // XXX playMenuAudioFile(); - for (int i = 0; i < 64 && !_quitFlag; ++i) { + for (int i = 0; i < 64 && !_quit; ++i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; _menuAnim->displayFrame(i, 0); _screen->updateScreen(); delayUntil(nextRun); } - for (int i = 64; i > 29 && !_quitFlag; --i) { + for (int i = 64; i > 29 && !_quit; --i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; _menuAnim->displayFrame(i, 0); _screen->updateScreen(); @@ -324,7 +324,7 @@ int KyraEngine_MR::go() { if (_showOutro) playVQA("CREDITS"); - return 0; + return _rtl; } void KyraEngine_MR::initMainMenu() { @@ -987,7 +987,7 @@ void KyraEngine_MR::runLoop() { _eventList.clear(); _runFlag = true; - while (_runFlag && !_quitFlag) { + while (_runFlag && !_quit) { if (_deathHandler >= 0) { removeHandItem(); delay(5); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 1cc1d728bf..c87f8bc46a 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -52,8 +52,6 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags) _gameSpeed = 60; _tickLength = (uint8)(1000.0 / _gameSpeed); - _quitFlag = false; - _speechFile = ""; _trackMap = 0; _trackMapSize = 0; @@ -220,7 +218,7 @@ KyraEngine_v1::~KyraEngine_v1() { void KyraEngine_v1::quitGame() { debugC(9, kDebugLevelMain, "KyraEngine_v1::quitGame()"); - _quitFlag = true; + _quit = true; // Nothing to do here } @@ -258,7 +256,7 @@ int KyraEngine_v1::resetGameFlag(int flag) { } void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quitFlag) { + while (_system->getMillis() < timestamp && !_quit) { if (timestamp - _system->getMillis() >= 10) delay(10, update, isMainLoop); } diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 4f38ceca98..be947080b2 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -112,7 +112,7 @@ public: virtual void pauseEngineIntern(bool pause); - bool quit() const { return _quitFlag; } + bool quit() const { return _quit; } uint8 game() const { return _flags.gameID; } const GameFlags &gameFlags() const { return _flags; } @@ -172,9 +172,6 @@ protected: virtual int go() = 0; virtual int init(); - // quit Handling - bool _quitFlag; - // intern Resource *_res; Sound *_sound; diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 12da338843..daf85c9cfa 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -127,7 +127,7 @@ void KyraEngine_v2::delay(uint32 amount, bool updateGame, bool isMainLoop) { if (amount > 0) _system->delayMillis(amount > 10 ? 10 : amount); - } while (!skipFlag() && _system->getMillis() < start + amount && !_quitFlag); + } while (!skipFlag() && _system->getMillis() < start + amount && !_quit); } int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { @@ -207,14 +207,14 @@ void KyraEngine_v2::updateInput() { while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_QUIT: - _quitFlag = true; + _quit = true; break; case Common::EVENT_KEYDOWN: if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE) _eventList.push_back(Event(event, true)); else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) - _quitFlag = true; + _quit = true; else _eventList.push_back(event); break; diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 22f934ba69..e149018c45 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -161,7 +161,7 @@ Common::InSaveFile *KyraEngine_v1::openSaveForReading(const char *filename, Save Common::OutSaveFile *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName) const { debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s')", filename, saveName); - if (_quitFlag) + if (_quit) return 0; Common::OutSaveFile *out = 0; diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 8af73acc61..999a990c5b 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -221,7 +221,7 @@ void KyraEngine_LoK::loadGame(const char *fileName) { void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) { debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s')", fileName, saveName); - if (_quitFlag) + if (_quit) return; Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index 1882386b03..db9966d144 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -277,7 +277,7 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { int changedScene = 0; const int *moveTableStart = moveTable; _unk4 = 0; - while (running && !_quitFlag) { + while (running && !_quit) { if (*moveTable >= 0 && *moveTable <= 7) { _mainCharacter.facing = getOppositeFacingDirection(*moveTable); unkFlag = true; diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index e4a3a5c54e..699da1420b 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -653,7 +653,7 @@ int KyraEngine_MR::trySceneChange(int *moveTable, int unk1, int updateChar) { const int *moveTableStart = moveTable; _unk4 = 0; - while (running && !_quitFlag) { + while (running && !_quit) { if (*moveTable >= 0 && *moveTable <= 7) { _mainCharacter.facing = getOppositeFacingDirection(*moveTable); unkFlag = true; diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 9a059ead2a..6f093ee83c 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -786,7 +786,7 @@ int KyraEngine_MR::o3_daggerWarning(EMCState *script) { _screen->_curPage = curPageBackUp; _screen->showMouse(); - while (!_quitFlag) { + while (!_quit) { int keys = checkInput(0); removeInputTop(); diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 169c319347..bce21365cf 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -75,7 +75,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqEndTime = 0; _menuChoice = 0; - for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { + for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { _screen->clearPage(0); _screen->clearPage(8); memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); @@ -131,7 +131,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_sequenceCommand(cseq.startupCommand); - if (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } @@ -165,7 +165,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqWsaCurrentFrame = cseq.startFrame; bool loop = true; - while (loop && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (loop && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; if (_seqWsa || !cb) @@ -189,16 +189,16 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_processWSAs(); seq_processText(); - if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } bool loop2 = true; - while (loop2 && !((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (loop2 && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { if (_seqWsa) { seq_processText(); - if (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } @@ -230,7 +230,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { } else { _seqFrameDelay = cseq.frameDelay; _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - while (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); if (cb) @@ -262,7 +262,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { dl = ct; _seqEndTime = _system->getMillis() + dl; - while (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); @@ -2093,7 +2093,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { int xa = 0, ya = 0; command--; - if (!_activeWSA[wsaNum].movie || skipFlag() || _quitFlag || _abortIntroFlag) + if (!_activeWSA[wsaNum].movie || skipFlag() || _quit || _abortIntroFlag) return; switch (command) { @@ -2293,7 +2293,7 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) { uint8 colormap[16]; - if (skipFlag() || _quitFlag || _abortIntroFlag || _menuChoice) + if (skipFlag() || _quit || _abortIntroFlag || _menuChoice) return; memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6); @@ -2774,7 +2774,7 @@ void KyraEngine_HoF::seq_makeBookAppear() { ++_invWsa.curFrame; - if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag) + if (_invWsa.curFrame >= _invWsa.lastFrame && !_quit) break; switch (_invWsa.curFrame) { diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index b30568c7e2..4fa7acfb1b 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -164,7 +164,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->updateScreen(); _screen->fadeFromBlack(); - if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || _quitFlag) { + if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || _quit) { _screen->fadeToBlack(); _screen->clearPage(0); return; @@ -176,14 +176,14 @@ void KyraEngine_LoK::seq_introLogos() { _screen->setScreenPalette(_screen->_currentPalette); } - if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _quitFlag) { + if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _quit) { _screen->fadeToBlack(); _screen->clearPage(0); return; } _screen->fillRect(0, 179, 319, 199, 0); - if (_quitFlag) + if (_quit) return; if (_flags.platform == Common::kPlatformAmiga) { @@ -223,10 +223,10 @@ void KyraEngine_LoK::seq_introLogos() { oldDistance = distance; delay(10); - } while (!doneFlag && !_quitFlag && !_abortIntroFlag); + } while (!doneFlag && !_quit && !_abortIntroFlag); } - if (_quitFlag) + if (_quit) return; _seq->playSequence(_seq_Forest, true); @@ -1030,7 +1030,7 @@ void KyraEngine_LoK::seq_brandonToStone() { void KyraEngine_LoK::seq_playEnding() { debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playEnding()"); - if (_quitFlag) + if (_quit) return; _screen->hideMouse(); _screen->_curPage = 0; @@ -1211,7 +1211,7 @@ void KyraEngine_LoK::seq_playCredits() { bool KyraEngine_LoK::seq_skipSequence() const { debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_skipSequence()"); - return _quitFlag || _abortIntroFlag; + return _quit || _abortIntroFlag; } int KyraEngine_LoK::handleMalcolmFlag() { diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index dd587c5112..69d211a219 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -335,7 +335,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() { const uint32 endTime = _chatEndTime; resetSkipFlag(); - while (running && !_quitFlag) { + while (running && !_quit) { if (!_emc->isValid(&_chatScriptState)) _emc->start(&_chatScriptState, 1); @@ -353,7 +353,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; - while (_system->getMillis() < nextFrame && !_quitFlag) { + while (_system->getMillis() < nextFrame && !_quit) { updateWithText(); const uint32 curTime = _system->getMillis(); @@ -593,7 +593,7 @@ void KyraEngine_HoF::initTalkObject(int index) { if (_currentTalkSections.STATim) { _tim->resetFinishedFlag(); - while (!_quitFlag && !_tim->finished()) { + while (!_quit && !_tim->finished()) { _tim->exec(_currentTalkSections.STATim, false); if (_chatText) updateWithText(); @@ -609,7 +609,7 @@ void KyraEngine_HoF::deinitTalkObject(int index) { if (_currentTalkSections.ENDTim) { _tim->resetFinishedFlag(); - while (!_quitFlag && !_tim->finished()) { + while (!_quit && !_tim->finished()) { _tim->exec(_currentTalkSections.ENDTim, false); if (_chatText) updateWithText(); @@ -647,10 +647,10 @@ void KyraEngine_HoF::npcChatSequence(const char *str, int objectId, int vocHigh, _chatVocHigh = _chatVocLow = -1; } - while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || skipFlag())) { + while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quit || skipFlag())) { if ((!speechEnabled() && chatAnimEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) { _tim->resetFinishedFlag(); - while (!_tim->finished() && !skipFlag() && !_quitFlag) { + while (!_tim->finished() && !skipFlag() && !_quit) { if (_currentTalkSections.TLKTim) _tim->exec(_currentTalkSections.TLKTim, false); else diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index 16c56da099..6c6aaffe68 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -349,7 +349,7 @@ void KyraEngine_MR::objectChatWaitToFinish() { const uint32 endTime = _chatEndTime; resetSkipFlag(); - while (running && !_quitFlag) { + while (running && !_quit) { if (!_emc->isValid(&_chatScriptState)) _emc->start(&_chatScriptState, 1); @@ -367,7 +367,7 @@ void KyraEngine_MR::objectChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; - while (_system->getMillis() < nextFrame && !_quitFlag) { + while (_system->getMillis() < nextFrame && !_quit) { updateWithText(); const uint32 curTime = _system->getMillis(); @@ -419,7 +419,7 @@ void KyraEngine_MR::badConscienceChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; int frame = _badConscienceFrameTable[_badConscienceAnim+24]; - while (running && !_quitFlag) { + while (running && !_quit) { if (nextFrame < _system->getMillis()) { ++frame; if (_badConscienceFrameTable[_badConscienceAnim+32] < frame) @@ -477,7 +477,7 @@ void KyraEngine_MR::goodConscienceChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(3, 6) * _tickLength; int frame = _goodConscienceFrameTable[_goodConscienceAnim+15]; - while (running && !_quitFlag) { + while (running && !_quit) { if (nextFrame < _system->getMillis()) { ++frame; if (_goodConscienceFrameTable[_goodConscienceAnim+20] < frame) @@ -597,7 +597,7 @@ void KyraEngine_MR::albumChatWaitToFinish() { uint32 nextFrame = 0; int frame = 12; - while (running && !_quitFlag) { + while (running && !_quit) { if (nextFrame < _system->getMillis()) { ++frame; if (frame > 22) -- cgit v1.2.3 From b97f39019cff74f7211152c78e4777ca0e31826e Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Tue, 8 Jul 2008 05:02:45 +0000 Subject: KYRA works with the new GMM implementation svn-id: r32957 --- engines/kyra/gui.cpp | 3 --- engines/kyra/gui_hof.cpp | 2 +- engines/kyra/gui_lok.cpp | 17 +++++++---------- engines/kyra/gui_mr.cpp | 2 +- engines/kyra/gui_v2.cpp | 6 +----- engines/kyra/kyra_hof.cpp | 9 ++++----- engines/kyra/kyra_lok.cpp | 24 +++++++++--------------- engines/kyra/kyra_mr.cpp | 10 +++++----- engines/kyra/kyra_v1.cpp | 4 ++-- engines/kyra/kyra_v1.h | 2 +- engines/kyra/kyra_v2.cpp | 8 ++------ engines/kyra/saveload.cpp | 2 +- engines/kyra/saveload_lok.cpp | 2 +- engines/kyra/scene_hof.cpp | 2 +- engines/kyra/scene_mr.cpp | 2 +- engines/kyra/script_mr.cpp | 2 +- engines/kyra/sequences_hof.cpp | 22 +++++++++++----------- engines/kyra/sequences_lok.cpp | 15 +++++++-------- engines/kyra/text_hof.cpp | 12 ++++++------ engines/kyra/text_lok.cpp | 1 - engines/kyra/text_mr.cpp | 10 +++++----- engines/kyra/vqa.cpp | 1 - 22 files changed, 67 insertions(+), 91 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index 96ea233025..8a5a4dfc91 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -378,9 +378,6 @@ bool MainMenu::getInput() { while (_system->getEventManager()->pollEvent(event)) { switch (event.type) { - case Common::EVENT_QUIT: - _vm->quitGame(); - break; case Common::EVENT_LBUTTONUP: return true; default: diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 5281919a0d..ca68413cb8 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -500,7 +500,7 @@ void KyraEngine_HoF::bookLoop() { showBookPage(); _bookShown = true; - while (_bookShown && !_quit) { + while (_bookShown && !_eventMan->shouldQuit()) { checkInput(buttonList); removeInputTop(); diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index f3f1f50d93..055b5366ca 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -459,7 +459,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { updateAllMenuButtons(); } - while (_displayMenu && !_vm->_quit) { + while (_displayMenu && !_vm->_eventMan->shouldQuit()) { Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[_toplevelMenu], mouse.x, mouse.y); processButtonList(_menuButtonList, 0, 0); @@ -485,9 +485,6 @@ void GUI_LoK::getInput() { _mouseWheel = 0; while (_vm->_eventMan->pollEvent(event)) { switch (event.type) { - case Common::EVENT_QUIT: - _vm->quitGame(); - break; case Common::EVENT_LBUTTONDOWN: _vm->_mousePressFlag = true; break; @@ -582,7 +579,7 @@ int GUI_LoK::saveGameMenu(Button *button) { _displaySubMenu = true; _cancelSubMenu = false; - while (_displaySubMenu && !_vm->_quit) { + while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); @@ -631,7 +628,7 @@ int GUI_LoK::loadGameMenu(Button *button) { _vm->_gameToLoad = -1; - while (_displaySubMenu && !_vm->_quit) { + while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); @@ -719,7 +716,7 @@ int GUI_LoK::saveGame(Button *button) { } redrawTextfield(); - while (_displaySubMenu && !_vm->_quit) { + while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { getInput(); updateSavegameString(); Common::Point mouse = _vm->getMousePos(); @@ -773,7 +770,7 @@ int GUI_LoK::quitPlaying(Button *button) { updateMenuButton(button); if (quitConfirm(_vm->_guiStrings[14])) { // Are you sure you want to quit playing? - _vm->quitGame(); + _vm->_eventMan->pushEvent(Common::EVENT_QUIT); } else { initMenu(_menu[_toplevelMenu]); updateAllMenuButtons(); @@ -795,7 +792,7 @@ bool GUI_LoK::quitConfirm(const char *str) { _displaySubMenu = true; _cancelSubMenu = true; - while (_displaySubMenu && !_vm->_quit) { + while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[1], mouse.x, mouse.y); @@ -861,7 +858,7 @@ int GUI_LoK::gameControlsMenu(Button *button) { _displaySubMenu = true; _cancelSubMenu = false; - while (_displaySubMenu && !_vm->_quit) { + while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[5], mouse.x, mouse.y); diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 46834bb335..5262d2819e 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -868,7 +868,7 @@ void KyraEngine_MR::processAlbum() { albumNewPage(); _album.running = true; - while (_album.running && !_quit) { + while (_album.running && !_eventMan->shouldQuit()) { updateInput(); checkInput(buttonList); removeInputTop(); diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index c056b1561d..37dc254acd 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -821,13 +821,9 @@ void GUI_v2::checkTextfieldInput() { int keys = 0; while (_vm->_eventMan->pollEvent(event) && running) { switch (event.type) { - case Common::EVENT_QUIT: - _vm->_quit = true; - break; - case Common::EVENT_KEYDOWN: if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) - _vm->_quit = true; + _vm->_eventMan->pushEvent(Common::EVENT_QUIT); else _keyPressed = event.kbd; running = false; diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 040ee0526f..74332ecc8f 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -311,7 +311,7 @@ int KyraEngine_HoF::go() { seq_playSequences(kSequenceFunters, kSequenceFrash); } - return _rtl; + return _eventMan->shouldRTL(); } void KyraEngine_HoF::startup() { @@ -440,9 +440,8 @@ void KyraEngine_HoF::startup() { void KyraEngine_HoF::runLoop() { _screen->updateScreen(); - _quit = false; _runFlag = true; - while (!_quit && _runFlag) { + while (!_eventMan->shouldQuit() && _runFlag) { if (_deathHandler >= 0) { removeHandItem(); delay(5); @@ -1603,7 +1602,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run, int delayTime, in _invWsa.timer = _system->getMillis(); if (run) { - while (_invWsa.running && !skipFlag() && !_quit) { + while (_invWsa.running && !skipFlag() && !_eventMan->shouldQuit()) { update(); _system->delayMillis(10); } @@ -1977,7 +1976,7 @@ void KyraEngine_HoF::playTim(const char *filename) { return; _tim->resetFinishedFlag(); - while (!_quit && !_tim->finished()) { + while (!_eventMan->shouldQuit() && !_tim->finished()) { _tim->exec(tim, 0); if (_chatText) updateWithText(); diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 7790fa38a1..6525d3cfbe 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -300,8 +300,8 @@ int KyraEngine_LoK::go() { if (_gameToLoad == -1) { setGameFlag(0xEF); seq_intro(); - if (_quit) - return _rtl; + if (_eventMan->shouldQuit()) + return _eventMan->shouldRTL(); if (_skipIntroFlag && _abortIntroFlag) resetGameFlag(0xEF); } @@ -309,7 +309,7 @@ int KyraEngine_LoK::go() { resetGameFlag(0xEF); mainLoop(); } - return _rtl; + return _eventMan->shouldRTL(); } @@ -399,7 +399,7 @@ void KyraEngine_LoK::startup() { void KyraEngine_LoK::mainLoop() { debugC(9, kDebugLevelMain, "KyraEngine_LoK::mainLoop()"); - while (!_quit) { + while (!_eventMan->shouldQuit()) { int32 frameTime = (int32)_system->getMillis(); _skipFlag = false; @@ -444,7 +444,7 @@ void KyraEngine_LoK::mainLoop() { } void KyraEngine_LoK::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quit) { + while (_system->getMillis() < timestamp && !_eventMan->shouldQuit()) { if (updateTimers) _timer->update(); @@ -476,7 +476,7 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { if (event.kbd.keycode == 'd') _debugger->attach(); else if (event.kbd.keycode == 'q') - _quit = true; + quitGame(); } else if (event.kbd.keycode == '.') { _skipFlag = true; } else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) { @@ -488,9 +488,6 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { case Common::EVENT_MOUSEMOVE: _animator->_updateScreen = true; break; - case Common::EVENT_QUIT: - quitGame(); - break; case Common::EVENT_LBUTTONDOWN: _mousePressFlag = true; break; @@ -529,27 +526,24 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) _skipFlag = false; - if (amount > 0 && !_skipFlag && !_quit) + if (amount > 0 && !_skipFlag && !_eventMan->shouldQuit()) _system->delayMillis(10); if (_skipFlag) _sound->voiceStop(); - } while (!_skipFlag && _system->getMillis() < start + amount && !_quit); + } while (!_skipFlag && _system->getMillis() < start + amount && !_eventMan->shouldQuit()); } void KyraEngine_LoK::waitForEvent() { bool finished = false; Common::Event event; - while (!finished && !_quit) { + while (!finished && !_eventMan->shouldQuit()) { while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: finished = true; break; - case Common::EVENT_QUIT: - quitGame(); - break; case Common::EVENT_LBUTTONDOWN: finished = true; _skipFlag = true; diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 643cb9521f..431bdf4109 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -263,7 +263,7 @@ int KyraEngine_MR::go() { running = false; } - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { _screen->_curPage = 0; _screen->clearPage(0); @@ -272,14 +272,14 @@ int KyraEngine_MR::go() { // XXX playMenuAudioFile(); - for (int i = 0; i < 64 && !_quit; ++i) { + for (int i = 0; i < 64 && !_eventMan->shouldQuit(); ++i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; _menuAnim->displayFrame(i, 0); _screen->updateScreen(); delayUntil(nextRun); } - for (int i = 64; i > 29 && !_quit; --i) { + for (int i = 64; i > 29 && !_eventMan->shouldQuit(); --i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; _menuAnim->displayFrame(i, 0); _screen->updateScreen(); @@ -324,7 +324,7 @@ int KyraEngine_MR::go() { if (_showOutro) playVQA("CREDITS"); - return _rtl; + return _eventMan->shouldRTL(); } void KyraEngine_MR::initMainMenu() { @@ -987,7 +987,7 @@ void KyraEngine_MR::runLoop() { _eventList.clear(); _runFlag = true; - while (_runFlag && !_quit) { + while (_runFlag && !_eventMan->shouldQuit()) { if (_deathHandler >= 0) { removeHandItem(); delay(5); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index c87f8bc46a..068e2f681b 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -218,7 +218,7 @@ KyraEngine_v1::~KyraEngine_v1() { void KyraEngine_v1::quitGame() { debugC(9, kDebugLevelMain, "KyraEngine_v1::quitGame()"); - _quit = true; + _eventMan->pushEvent(Common::EVENT_QUIT); // Nothing to do here } @@ -256,7 +256,7 @@ int KyraEngine_v1::resetGameFlag(int flag) { } void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quit) { + while (_system->getMillis() < timestamp && !_eventMan->shouldQuit()) { if (timestamp - _system->getMillis() >= 10) delay(10, update, isMainLoop); } diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index be947080b2..8021abd1ef 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -112,7 +112,7 @@ public: virtual void pauseEngineIntern(bool pause); - bool quit() const { return _quit; } + bool quit() const { return _eventMan->shouldQuit(); } uint8 game() const { return _flags.gameID; } const GameFlags &gameFlags() const { return _flags; } diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index daf85c9cfa..d55c50dd7b 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -127,7 +127,7 @@ void KyraEngine_v2::delay(uint32 amount, bool updateGame, bool isMainLoop) { if (amount > 0) _system->delayMillis(amount > 10 ? 10 : amount); - } while (!skipFlag() && _system->getMillis() < start + amount && !_quit); + } while (!skipFlag() && _system->getMillis() < start + amount && !_eventMan->shouldQuit()); } int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { @@ -206,15 +206,11 @@ void KyraEngine_v2::updateInput() { while (_eventMan->pollEvent(event)) { switch (event.type) { - case Common::EVENT_QUIT: - _quit = true; - break; - case Common::EVENT_KEYDOWN: if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE) _eventList.push_back(Event(event, true)); else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) - _quit = true; + quitGame(); else _eventList.push_back(event); break; diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index e149018c45..e91c4cdaf7 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -161,7 +161,7 @@ Common::InSaveFile *KyraEngine_v1::openSaveForReading(const char *filename, Save Common::OutSaveFile *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName) const { debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s')", filename, saveName); - if (_quit) + if (_eventMan->shouldQuit()) return 0; Common::OutSaveFile *out = 0; diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 999a990c5b..8dbe85485f 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -221,7 +221,7 @@ void KyraEngine_LoK::loadGame(const char *fileName) { void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) { debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s')", fileName, saveName); - if (_quit) + if (_eventMan->shouldQuit()) return; Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index db9966d144..feb73abbc5 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -277,7 +277,7 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { int changedScene = 0; const int *moveTableStart = moveTable; _unk4 = 0; - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (*moveTable >= 0 && *moveTable <= 7) { _mainCharacter.facing = getOppositeFacingDirection(*moveTable); unkFlag = true; diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index 699da1420b..6c12f9a62d 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -653,7 +653,7 @@ int KyraEngine_MR::trySceneChange(int *moveTable, int unk1, int updateChar) { const int *moveTableStart = moveTable; _unk4 = 0; - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (*moveTable >= 0 && *moveTable <= 7) { _mainCharacter.facing = getOppositeFacingDirection(*moveTable); unkFlag = true; diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 6f093ee83c..2dba9b550f 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -786,7 +786,7 @@ int KyraEngine_MR::o3_daggerWarning(EMCState *script) { _screen->_curPage = curPageBackUp; _screen->showMouse(); - while (!_quit) { + while (!_eventMan->shouldQuit()) { int keys = checkInput(0); removeInputTop(); diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index bce21365cf..520a5e063b 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -75,7 +75,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqEndTime = 0; _menuChoice = 0; - for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { + for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { _screen->clearPage(0); _screen->clearPage(8); memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); @@ -131,7 +131,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_sequenceCommand(cseq.startupCommand); - if (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } @@ -165,7 +165,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqWsaCurrentFrame = cseq.startFrame; bool loop = true; - while (loop && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (loop && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; if (_seqWsa || !cb) @@ -189,16 +189,16 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_processWSAs(); seq_processText(); - if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } bool loop2 = true; - while (loop2 && !((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (loop2 && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { if (_seqWsa) { seq_processText(); - if (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } @@ -230,7 +230,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { } else { _seqFrameDelay = cseq.frameDelay; _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - while (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); if (cb) @@ -262,7 +262,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { dl = ct; _seqEndTime = _system->getMillis() + dl; - while (!((skipFlag() && allowSkip) || _quit || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); @@ -2093,7 +2093,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { int xa = 0, ya = 0; command--; - if (!_activeWSA[wsaNum].movie || skipFlag() || _quit || _abortIntroFlag) + if (!_activeWSA[wsaNum].movie || skipFlag() || _eventMan->shouldQuit() || _abortIntroFlag) return; switch (command) { @@ -2293,7 +2293,7 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) { uint8 colormap[16]; - if (skipFlag() || _quit || _abortIntroFlag || _menuChoice) + if (skipFlag() || _eventMan->shouldQuit() || _abortIntroFlag || _menuChoice) return; memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6); @@ -2774,7 +2774,7 @@ void KyraEngine_HoF::seq_makeBookAppear() { ++_invWsa.curFrame; - if (_invWsa.curFrame >= _invWsa.lastFrame && !_quit) + if (_invWsa.curFrame >= _invWsa.lastFrame && !_eventMan->shouldQuit()) break; switch (_invWsa.curFrame) { diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 4fa7acfb1b..73cf634826 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -164,7 +164,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->updateScreen(); _screen->fadeFromBlack(); - if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || _quit) { + if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || _eventMan->shouldQuit()) { _screen->fadeToBlack(); _screen->clearPage(0); return; @@ -176,14 +176,14 @@ void KyraEngine_LoK::seq_introLogos() { _screen->setScreenPalette(_screen->_currentPalette); } - if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _quit) { + if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _eventMan->shouldQuit()) { _screen->fadeToBlack(); _screen->clearPage(0); return; } _screen->fillRect(0, 179, 319, 199, 0); - if (_quit) + if (_eventMan->shouldQuit()) return; if (_flags.platform == Common::kPlatformAmiga) { @@ -223,10 +223,10 @@ void KyraEngine_LoK::seq_introLogos() { oldDistance = distance; delay(10); - } while (!doneFlag && !_quit && !_abortIntroFlag); + } while (!doneFlag && !_eventMan->shouldQuit() && !_abortIntroFlag); } - if (_quit) + if (_eventMan->shouldQuit()) return; _seq->playSequence(_seq_Forest, true); @@ -1030,7 +1030,7 @@ void KyraEngine_LoK::seq_brandonToStone() { void KyraEngine_LoK::seq_playEnding() { debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playEnding()"); - if (_quit) + if (_eventMan->shouldQuit()) return; _screen->hideMouse(); _screen->_curPage = 0; @@ -1187,7 +1187,6 @@ void KyraEngine_LoK::seq_playCredits() { finished = true; break; case Common::EVENT_QUIT: - quitGame(); finished = true; break; default: @@ -1211,7 +1210,7 @@ void KyraEngine_LoK::seq_playCredits() { bool KyraEngine_LoK::seq_skipSequence() const { debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_skipSequence()"); - return _quit || _abortIntroFlag; + return _eventMan->shouldQuit() || _abortIntroFlag; } int KyraEngine_LoK::handleMalcolmFlag() { diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index 69d211a219..4a109966b0 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -335,7 +335,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() { const uint32 endTime = _chatEndTime; resetSkipFlag(); - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (!_emc->isValid(&_chatScriptState)) _emc->start(&_chatScriptState, 1); @@ -353,7 +353,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; - while (_system->getMillis() < nextFrame && !_quit) { + while (_system->getMillis() < nextFrame && !_eventMan->shouldQuit()) { updateWithText(); const uint32 curTime = _system->getMillis(); @@ -593,7 +593,7 @@ void KyraEngine_HoF::initTalkObject(int index) { if (_currentTalkSections.STATim) { _tim->resetFinishedFlag(); - while (!_quit && !_tim->finished()) { + while (!_eventMan->shouldQuit() && !_tim->finished()) { _tim->exec(_currentTalkSections.STATim, false); if (_chatText) updateWithText(); @@ -609,7 +609,7 @@ void KyraEngine_HoF::deinitTalkObject(int index) { if (_currentTalkSections.ENDTim) { _tim->resetFinishedFlag(); - while (!_quit && !_tim->finished()) { + while (!_eventMan->shouldQuit() && !_tim->finished()) { _tim->exec(_currentTalkSections.ENDTim, false); if (_chatText) updateWithText(); @@ -647,10 +647,10 @@ void KyraEngine_HoF::npcChatSequence(const char *str, int objectId, int vocHigh, _chatVocHigh = _chatVocLow = -1; } - while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quit || skipFlag())) { + while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_eventMan->shouldQuit() || skipFlag())) { if ((!speechEnabled() && chatAnimEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) { _tim->resetFinishedFlag(); - while (!_tim->finished() && !skipFlag() && !_quit) { + while (!_tim->finished() && !skipFlag() && !_eventMan->shouldQuit()) { if (_currentTalkSections.TLKTim) _tim->exec(_currentTalkSections.TLKTim, false); else diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp index f6b0407a75..d452109f91 100644 --- a/engines/kyra/text_lok.cpp +++ b/engines/kyra/text_lok.cpp @@ -121,7 +121,6 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const _skipFlag = true; break; case Common::EVENT_QUIT: - quitGame(); runLoop = false; break; case Common::EVENT_LBUTTONDOWN: diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index 6c6aaffe68..d9ef59e226 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -349,7 +349,7 @@ void KyraEngine_MR::objectChatWaitToFinish() { const uint32 endTime = _chatEndTime; resetSkipFlag(); - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (!_emc->isValid(&_chatScriptState)) _emc->start(&_chatScriptState, 1); @@ -367,7 +367,7 @@ void KyraEngine_MR::objectChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; - while (_system->getMillis() < nextFrame && !_quit) { + while (_system->getMillis() < nextFrame && !_eventMan->shouldQuit()) { updateWithText(); const uint32 curTime = _system->getMillis(); @@ -419,7 +419,7 @@ void KyraEngine_MR::badConscienceChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; int frame = _badConscienceFrameTable[_badConscienceAnim+24]; - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (nextFrame < _system->getMillis()) { ++frame; if (_badConscienceFrameTable[_badConscienceAnim+32] < frame) @@ -477,7 +477,7 @@ void KyraEngine_MR::goodConscienceChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(3, 6) * _tickLength; int frame = _goodConscienceFrameTable[_goodConscienceAnim+15]; - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (nextFrame < _system->getMillis()) { ++frame; if (_goodConscienceFrameTable[_goodConscienceAnim+20] < frame) @@ -597,7 +597,7 @@ void KyraEngine_MR::albumChatWaitToFinish() { uint32 nextFrame = 0; int frame = 12; - while (running && !_quit) { + while (running && !_eventMan->shouldQuit()) { if (nextFrame < _system->getMillis()) { ++frame; if (frame > 22) diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 3d18f27c7e..e66dfaf193 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -672,7 +672,6 @@ void VQAMovie::play() { return; break; case Common::EVENT_QUIT: - _vm->quitGame(); return; default: break; -- cgit v1.2.3 From b8fe71e7a12e60f0c19fa86da83f270dc09e14fd Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Tue, 8 Jul 2008 06:00:39 +0000 Subject: Updated KYRA to work with the new GMM implementation svn-id: r32959 --- engines/kyra/gui_hof.cpp | 2 +- engines/kyra/gui_lok.cpp | 14 +++++++------- engines/kyra/gui_mr.cpp | 2 +- engines/kyra/gui_v2.cpp | 2 +- engines/kyra/kyra_hof.cpp | 6 +++--- engines/kyra/kyra_lok.cpp | 12 ++++++------ engines/kyra/kyra_mr.cpp | 8 ++++---- engines/kyra/kyra_v1.cpp | 2 +- engines/kyra/kyra_v1.h | 2 -- engines/kyra/kyra_v2.cpp | 2 +- engines/kyra/saveload.cpp | 2 +- engines/kyra/saveload_lok.cpp | 2 +- engines/kyra/scene_hof.cpp | 2 +- engines/kyra/scene_mr.cpp | 2 +- engines/kyra/script_mr.cpp | 2 +- engines/kyra/sequences_hof.cpp | 22 +++++++++++----------- engines/kyra/sequences_lok.cpp | 14 +++++++------- engines/kyra/text_hof.cpp | 12 ++++++------ engines/kyra/text_mr.cpp | 10 +++++----- 19 files changed, 59 insertions(+), 61 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index ca68413cb8..032c28d44d 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -500,7 +500,7 @@ void KyraEngine_HoF::bookLoop() { showBookPage(); _bookShown = true; - while (_bookShown && !_eventMan->shouldQuit()) { + while (_bookShown && !quit()) { checkInput(buttonList); removeInputTop(); diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 055b5366ca..c725659089 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -459,7 +459,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { updateAllMenuButtons(); } - while (_displayMenu && !_vm->_eventMan->shouldQuit()) { + while (_displayMenu && !_vm->quit()) { Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[_toplevelMenu], mouse.x, mouse.y); processButtonList(_menuButtonList, 0, 0); @@ -579,7 +579,7 @@ int GUI_LoK::saveGameMenu(Button *button) { _displaySubMenu = true; _cancelSubMenu = false; - while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { + while (_displaySubMenu && !_vm->quit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); @@ -628,7 +628,7 @@ int GUI_LoK::loadGameMenu(Button *button) { _vm->_gameToLoad = -1; - while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { + while (_displaySubMenu && !_vm->quit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); @@ -716,7 +716,7 @@ int GUI_LoK::saveGame(Button *button) { } redrawTextfield(); - while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { + while (_displaySubMenu && !_vm->quit()) { getInput(); updateSavegameString(); Common::Point mouse = _vm->getMousePos(); @@ -770,7 +770,7 @@ int GUI_LoK::quitPlaying(Button *button) { updateMenuButton(button); if (quitConfirm(_vm->_guiStrings[14])) { // Are you sure you want to quit playing? - _vm->_eventMan->pushEvent(Common::EVENT_QUIT); + _vm->quitGame(); } else { initMenu(_menu[_toplevelMenu]); updateAllMenuButtons(); @@ -792,7 +792,7 @@ bool GUI_LoK::quitConfirm(const char *str) { _displaySubMenu = true; _cancelSubMenu = true; - while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { + while (_displaySubMenu && !_vm->quit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[1], mouse.x, mouse.y); @@ -858,7 +858,7 @@ int GUI_LoK::gameControlsMenu(Button *button) { _displaySubMenu = true; _cancelSubMenu = false; - while (_displaySubMenu && !_vm->_eventMan->shouldQuit()) { + while (_displaySubMenu && !_vm->quit()) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[5], mouse.x, mouse.y); diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 5262d2819e..40fe78c439 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -868,7 +868,7 @@ void KyraEngine_MR::processAlbum() { albumNewPage(); _album.running = true; - while (_album.running && !_eventMan->shouldQuit()) { + while (_album.running && !quit()) { updateInput(); checkInput(buttonList); removeInputTop(); diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index 37dc254acd..11f430040c 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -823,7 +823,7 @@ void GUI_v2::checkTextfieldInput() { switch (event.type) { case Common::EVENT_KEYDOWN: if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) - _vm->_eventMan->pushEvent(Common::EVENT_QUIT); + _vm->quitGame(); else _keyPressed = event.kbd; running = false; diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 74332ecc8f..470e5f0343 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -441,7 +441,7 @@ void KyraEngine_HoF::runLoop() { _screen->updateScreen(); _runFlag = true; - while (!_eventMan->shouldQuit() && _runFlag) { + while (!quit() && _runFlag) { if (_deathHandler >= 0) { removeHandItem(); delay(5); @@ -1602,7 +1602,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run, int delayTime, in _invWsa.timer = _system->getMillis(); if (run) { - while (_invWsa.running && !skipFlag() && !_eventMan->shouldQuit()) { + while (_invWsa.running && !skipFlag() && !quit()) { update(); _system->delayMillis(10); } @@ -1976,7 +1976,7 @@ void KyraEngine_HoF::playTim(const char *filename) { return; _tim->resetFinishedFlag(); - while (!_eventMan->shouldQuit() && !_tim->finished()) { + while (!quit() && !_tim->finished()) { _tim->exec(tim, 0); if (_chatText) updateWithText(); diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 6525d3cfbe..747513cc52 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -300,7 +300,7 @@ int KyraEngine_LoK::go() { if (_gameToLoad == -1) { setGameFlag(0xEF); seq_intro(); - if (_eventMan->shouldQuit()) + if (quit()) return _eventMan->shouldRTL(); if (_skipIntroFlag && _abortIntroFlag) resetGameFlag(0xEF); @@ -399,7 +399,7 @@ void KyraEngine_LoK::startup() { void KyraEngine_LoK::mainLoop() { debugC(9, kDebugLevelMain, "KyraEngine_LoK::mainLoop()"); - while (!_eventMan->shouldQuit()) { + while (!quit()) { int32 frameTime = (int32)_system->getMillis(); _skipFlag = false; @@ -444,7 +444,7 @@ void KyraEngine_LoK::mainLoop() { } void KyraEngine_LoK::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_eventMan->shouldQuit()) { + while (_system->getMillis() < timestamp && !quit()) { if (updateTimers) _timer->update(); @@ -526,19 +526,19 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) _skipFlag = false; - if (amount > 0 && !_skipFlag && !_eventMan->shouldQuit()) + if (amount > 0 && !_skipFlag && !quit()) _system->delayMillis(10); if (_skipFlag) _sound->voiceStop(); - } while (!_skipFlag && _system->getMillis() < start + amount && !_eventMan->shouldQuit()); + } while (!_skipFlag && _system->getMillis() < start + amount && !quit()); } void KyraEngine_LoK::waitForEvent() { bool finished = false; Common::Event event; - while (!finished && !_eventMan->shouldQuit()) { + while (!finished && !quit()) { while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 431bdf4109..700bec10b7 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -263,7 +263,7 @@ int KyraEngine_MR::go() { running = false; } - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { _screen->_curPage = 0; _screen->clearPage(0); @@ -272,14 +272,14 @@ int KyraEngine_MR::go() { // XXX playMenuAudioFile(); - for (int i = 0; i < 64 && !_eventMan->shouldQuit(); ++i) { + for (int i = 0; i < 64 && !quit(); ++i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; _menuAnim->displayFrame(i, 0); _screen->updateScreen(); delayUntil(nextRun); } - for (int i = 64; i > 29 && !_eventMan->shouldQuit(); --i) { + for (int i = 64; i > 29 && !quit(); --i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; _menuAnim->displayFrame(i, 0); _screen->updateScreen(); @@ -987,7 +987,7 @@ void KyraEngine_MR::runLoop() { _eventList.clear(); _runFlag = true; - while (_runFlag && !_eventMan->shouldQuit()) { + while (_runFlag && !quit()) { if (_deathHandler >= 0) { removeHandItem(); delay(5); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 068e2f681b..c7b39aa257 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -256,7 +256,7 @@ int KyraEngine_v1::resetGameFlag(int flag) { } void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_eventMan->shouldQuit()) { + while (_system->getMillis() < timestamp && !quit()) { if (timestamp - _system->getMillis() >= 10) delay(10, update, isMainLoop); } diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 8021abd1ef..921d5ba033 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -112,8 +112,6 @@ public: virtual void pauseEngineIntern(bool pause); - bool quit() const { return _eventMan->shouldQuit(); } - uint8 game() const { return _flags.gameID; } const GameFlags &gameFlags() const { return _flags; } diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index d55c50dd7b..20875202e5 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -127,7 +127,7 @@ void KyraEngine_v2::delay(uint32 amount, bool updateGame, bool isMainLoop) { if (amount > 0) _system->delayMillis(amount > 10 ? 10 : amount); - } while (!skipFlag() && _system->getMillis() < start + amount && !_eventMan->shouldQuit()); + } while (!skipFlag() && _system->getMillis() < start + amount && !quit()); } int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index e91c4cdaf7..147c774a52 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -161,7 +161,7 @@ Common::InSaveFile *KyraEngine_v1::openSaveForReading(const char *filename, Save Common::OutSaveFile *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName) const { debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s')", filename, saveName); - if (_eventMan->shouldQuit()) + if (quit()) return 0; Common::OutSaveFile *out = 0; diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 8dbe85485f..74cf26646c 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -221,7 +221,7 @@ void KyraEngine_LoK::loadGame(const char *fileName) { void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) { debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s')", fileName, saveName); - if (_eventMan->shouldQuit()) + if (quit()) return; Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index feb73abbc5..dbf54e1fcd 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -277,7 +277,7 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { int changedScene = 0; const int *moveTableStart = moveTable; _unk4 = 0; - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (*moveTable >= 0 && *moveTable <= 7) { _mainCharacter.facing = getOppositeFacingDirection(*moveTable); unkFlag = true; diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index 6c12f9a62d..716c139129 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -653,7 +653,7 @@ int KyraEngine_MR::trySceneChange(int *moveTable, int unk1, int updateChar) { const int *moveTableStart = moveTable; _unk4 = 0; - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (*moveTable >= 0 && *moveTable <= 7) { _mainCharacter.facing = getOppositeFacingDirection(*moveTable); unkFlag = true; diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 2dba9b550f..6dda6c8bd7 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -786,7 +786,7 @@ int KyraEngine_MR::o3_daggerWarning(EMCState *script) { _screen->_curPage = curPageBackUp; _screen->showMouse(); - while (!_eventMan->shouldQuit()) { + while (!quit()) { int keys = checkInput(0); removeInputTop(); diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 520a5e063b..7e0220af8a 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -75,7 +75,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqEndTime = 0; _menuChoice = 0; - for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { + for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { _screen->clearPage(0); _screen->clearPage(8); memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); @@ -131,7 +131,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_sequenceCommand(cseq.startupCommand); - if (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } @@ -165,7 +165,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqWsaCurrentFrame = cseq.startFrame; bool loop = true; - while (loop && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (loop && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; if (_seqWsa || !cb) @@ -189,16 +189,16 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_processWSAs(); seq_processText(); - if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } bool loop2 = true; - while (loop2 && !((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (loop2 && !((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { if (_seqWsa) { seq_processText(); - if (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _screen->copyPage(2, 0); _screen->updateScreen(); } @@ -230,7 +230,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { } else { _seqFrameDelay = cseq.frameDelay; _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - while (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); if (cb) @@ -262,7 +262,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { dl = ct; _seqEndTime = _system->getMillis() + dl; - while (!((skipFlag() && allowSkip) || _eventMan->shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + while (!((skipFlag() && allowSkip) || quit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); @@ -2093,7 +2093,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { int xa = 0, ya = 0; command--; - if (!_activeWSA[wsaNum].movie || skipFlag() || _eventMan->shouldQuit() || _abortIntroFlag) + if (!_activeWSA[wsaNum].movie || skipFlag() || quit() || _abortIntroFlag) return; switch (command) { @@ -2293,7 +2293,7 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) { uint8 colormap[16]; - if (skipFlag() || _eventMan->shouldQuit() || _abortIntroFlag || _menuChoice) + if (skipFlag() || quit() || _abortIntroFlag || _menuChoice) return; memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6); @@ -2774,7 +2774,7 @@ void KyraEngine_HoF::seq_makeBookAppear() { ++_invWsa.curFrame; - if (_invWsa.curFrame >= _invWsa.lastFrame && !_eventMan->shouldQuit()) + if (_invWsa.curFrame >= _invWsa.lastFrame && !quit()) break; switch (_invWsa.curFrame) { diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 73cf634826..8005167d7d 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -164,7 +164,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->updateScreen(); _screen->fadeFromBlack(); - if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || _eventMan->shouldQuit()) { + if (_seq->playSequence(_seq_WestwoodLogo, _skipFlag) || quit()) { _screen->fadeToBlack(); _screen->clearPage(0); return; @@ -176,14 +176,14 @@ void KyraEngine_LoK::seq_introLogos() { _screen->setScreenPalette(_screen->_currentPalette); } - if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _eventMan->shouldQuit()) { + if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || quit()) { _screen->fadeToBlack(); _screen->clearPage(0); return; } _screen->fillRect(0, 179, 319, 199, 0); - if (_eventMan->shouldQuit()) + if (quit()) return; if (_flags.platform == Common::kPlatformAmiga) { @@ -223,10 +223,10 @@ void KyraEngine_LoK::seq_introLogos() { oldDistance = distance; delay(10); - } while (!doneFlag && !_eventMan->shouldQuit() && !_abortIntroFlag); + } while (!doneFlag && !quit() && !_abortIntroFlag); } - if (_eventMan->shouldQuit()) + if (quit()) return; _seq->playSequence(_seq_Forest, true); @@ -1030,7 +1030,7 @@ void KyraEngine_LoK::seq_brandonToStone() { void KyraEngine_LoK::seq_playEnding() { debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playEnding()"); - if (_eventMan->shouldQuit()) + if (quit()) return; _screen->hideMouse(); _screen->_curPage = 0; @@ -1210,7 +1210,7 @@ void KyraEngine_LoK::seq_playCredits() { bool KyraEngine_LoK::seq_skipSequence() const { debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_skipSequence()"); - return _eventMan->shouldQuit() || _abortIntroFlag; + return quit() || _abortIntroFlag; } int KyraEngine_LoK::handleMalcolmFlag() { diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index 4a109966b0..b94b8a6258 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -335,7 +335,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() { const uint32 endTime = _chatEndTime; resetSkipFlag(); - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (!_emc->isValid(&_chatScriptState)) _emc->start(&_chatScriptState, 1); @@ -353,7 +353,7 @@ void KyraEngine_HoF::objectChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; - while (_system->getMillis() < nextFrame && !_eventMan->shouldQuit()) { + while (_system->getMillis() < nextFrame && !quit()) { updateWithText(); const uint32 curTime = _system->getMillis(); @@ -593,7 +593,7 @@ void KyraEngine_HoF::initTalkObject(int index) { if (_currentTalkSections.STATim) { _tim->resetFinishedFlag(); - while (!_eventMan->shouldQuit() && !_tim->finished()) { + while (!quit() && !_tim->finished()) { _tim->exec(_currentTalkSections.STATim, false); if (_chatText) updateWithText(); @@ -609,7 +609,7 @@ void KyraEngine_HoF::deinitTalkObject(int index) { if (_currentTalkSections.ENDTim) { _tim->resetFinishedFlag(); - while (!_eventMan->shouldQuit() && !_tim->finished()) { + while (!quit() && !_tim->finished()) { _tim->exec(_currentTalkSections.ENDTim, false); if (_chatText) updateWithText(); @@ -647,10 +647,10 @@ void KyraEngine_HoF::npcChatSequence(const char *str, int objectId, int vocHigh, _chatVocHigh = _chatVocLow = -1; } - while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_eventMan->shouldQuit() || skipFlag())) { + while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(quit() || skipFlag())) { if ((!speechEnabled() && chatAnimEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) { _tim->resetFinishedFlag(); - while (!_tim->finished() && !skipFlag() && !_eventMan->shouldQuit()) { + while (!_tim->finished() && !skipFlag() && !quit()) { if (_currentTalkSections.TLKTim) _tim->exec(_currentTalkSections.TLKTim, false); else diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index d9ef59e226..be306ceec1 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -349,7 +349,7 @@ void KyraEngine_MR::objectChatWaitToFinish() { const uint32 endTime = _chatEndTime; resetSkipFlag(); - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (!_emc->isValid(&_chatScriptState)) _emc->start(&_chatScriptState, 1); @@ -367,7 +367,7 @@ void KyraEngine_MR::objectChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + delayTime * _tickLength; - while (_system->getMillis() < nextFrame && !_eventMan->shouldQuit()) { + while (_system->getMillis() < nextFrame && !quit()) { updateWithText(); const uint32 curTime = _system->getMillis(); @@ -419,7 +419,7 @@ void KyraEngine_MR::badConscienceChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; int frame = _badConscienceFrameTable[_badConscienceAnim+24]; - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (nextFrame < _system->getMillis()) { ++frame; if (_badConscienceFrameTable[_badConscienceAnim+32] < frame) @@ -477,7 +477,7 @@ void KyraEngine_MR::goodConscienceChatWaitToFinish() { uint32 nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(3, 6) * _tickLength; int frame = _goodConscienceFrameTable[_goodConscienceAnim+15]; - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (nextFrame < _system->getMillis()) { ++frame; if (_goodConscienceFrameTable[_goodConscienceAnim+20] < frame) @@ -597,7 +597,7 @@ void KyraEngine_MR::albumChatWaitToFinish() { uint32 nextFrame = 0; int frame = 12; - while (running && !_eventMan->shouldQuit()) { + while (running && !quit()) { if (nextFrame < _system->getMillis()) { ++frame; if (frame > 22) -- cgit v1.2.3 From e808cdf7a08d641389ecc81063b3b1016c7bc8cf Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Wed, 9 Jul 2008 02:27:05 +0000 Subject: Reimplemented pushEvent() and artificialEventQueue to work with Events instead of EventTypes. Reimplemented Queue as a List instead of Array. Updated AGOS, AGI, CINE, GOB, and KYRA to work with the current implementation of the GMM svn-id: r32971 --- engines/kyra/kyra_v1.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index c7b39aa257..2f63e2831b 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -24,6 +24,7 @@ */ #include "common/config-manager.h" +#include "common/events.h" #include "sound/mididrv.h" #include "sound/mixer.h" @@ -218,7 +219,10 @@ KyraEngine_v1::~KyraEngine_v1() { void KyraEngine_v1::quitGame() { debugC(9, kDebugLevelMain, "KyraEngine_v1::quitGame()"); - _eventMan->pushEvent(Common::EVENT_QUIT); + Common::Event event; + + event.type = Common::EVENT_QUIT; + _eventMan->pushEvent(event); // Nothing to do here } -- cgit v1.2.3 From 30b1a62e810cfbe3246ebb9b94aa341ea3be5f7c Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Thu, 10 Jul 2008 05:15:19 +0000 Subject: Removed unnecessary #inlcudes svn-id: r32984 --- engines/kyra/gui_lok.cpp | 1 - engines/kyra/kyra_lok.cpp | 1 - engines/kyra/kyra_v1.cpp | 1 - engines/kyra/sequences_lok.cpp | 1 - engines/kyra/sprites.cpp | 1 - engines/kyra/text.cpp | 1 - engines/kyra/vqa.cpp | 1 - 7 files changed, 7 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index c725659089..db9d61ce5e 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -34,7 +34,6 @@ #include "common/config-manager.h" #include "common/savefile.h" -#include "common/events.h" #include "common/system.h" namespace Kyra { diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 747513cc52..afd164958c 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -26,7 +26,6 @@ #include "kyra/kyra_lok.h" #include "common/file.h" -#include "common/events.h" #include "common/system.h" #include "common/savefile.h" diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 2f63e2831b..accf5ab57e 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -24,7 +24,6 @@ */ #include "common/config-manager.h" -#include "common/events.h" #include "sound/mididrv.h" #include "sound/mixer.h" diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 8005167d7d..1940acbf7f 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -34,7 +34,6 @@ #include "kyra/text.h" #include "kyra/timer.h" -#include "common/events.h" #include "common/system.h" #include "common/savefile.h" diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp index 34c2986f25..05074d20b1 100644 --- a/engines/kyra/sprites.cpp +++ b/engines/kyra/sprites.cpp @@ -28,7 +28,6 @@ #include "common/stream.h" #include "common/util.h" #include "common/system.h" -#include "common/events.h" #include "kyra/screen.h" #include "kyra/kyra_lok.h" #include "kyra/sprites.h" diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp index f8eb10a85e..eecb617942 100644 --- a/engines/kyra/text.cpp +++ b/engines/kyra/text.cpp @@ -29,7 +29,6 @@ #include "kyra/screen.h" #include "kyra/text.h" -#include "common/events.h" #include "common/system.h" #include "common/endian.h" diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index e66dfaf193..9e2adfa71f 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -32,7 +32,6 @@ // The jung2.vqa movie does work, but only thanks to a grotesque hack. -#include "common/events.h" #include "common/system.h" #include "sound/audiostream.h" #include "sound/mixer.h" -- cgit v1.2.3 From 7f480ac571f978802a3ecd5cf6169d0271d1f561 Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Wed, 16 Jul 2008 04:22:56 +0000 Subject: Quit and RTL code is more modular now. EVENT_RTL no longer sets _shouldQuit, shouldQuit is only set if there's an EVENT_QUIT. EVENT_RTL and EVENT_QUIT are completely separate from each other. Engine::quit() method now checks both _shouldQuit and _shouldRTL to determine if the engine should exit. There is no longer a need for resetQuit(), so it's removed svn-id: r33082 --- engines/kyra/sequences_lok.cpp | 1 + engines/kyra/text_lok.cpp | 1 + engines/kyra/vqa.cpp | 1 + 3 files changed, 3 insertions(+) (limited to 'engines/kyra') diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 577dcd827b..77cfbed2d0 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -1185,6 +1185,7 @@ void KyraEngine_LoK::seq_playCredits() { case Common::EVENT_KEYDOWN: finished = true; break; + case Common::EVENT_RTL: case Common::EVENT_QUIT: finished = true; break; diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp index d452109f91..150ec59a23 100644 --- a/engines/kyra/text_lok.cpp +++ b/engines/kyra/text_lok.cpp @@ -120,6 +120,7 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const if (event.kbd.keycode == '.') _skipFlag = true; break; + case Common::EVENT_RTL: case Common::EVENT_QUIT: runLoop = false; break; diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 9e2adfa71f..c55c573ea3 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -670,6 +670,7 @@ void VQAMovie::play() { if (event.kbd.ascii == 27) return; break; + case Common::EVENT_RTL: case Common::EVENT_QUIT: return; default: -- cgit v1.2.3 From 0725f7ec932311987a936d11cefd4ce50f5fc49e Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Tue, 5 Aug 2008 02:11:00 +0000 Subject: Made changes to keep KYRA and PARA compatible with RTL/GMM svn-id: r33628 --- engines/kyra/lol.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index ef1121baa0..148b7daf4d 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -180,15 +180,11 @@ void LoLEngine::updateInput() { while (_eventMan->pollEvent(event)) { switch (event.type) { - case Common::EVENT_QUIT: - _quitFlag = true; - break; - case Common::EVENT_KEYDOWN: if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE) _eventList.push_back(Event(event, true)); else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) - _quitFlag = true; + quitGame(); else _eventList.push_back(event); break; @@ -301,7 +297,7 @@ void LoLEngine::showIntro() { _screen->hideMouse(); uint32 palNextFadeStep = 0; - while (!_tim->finished() && !_quitFlag && !skipFlag()) { + while (!_tim->finished() && !quit() && !skipFlag()) { updateInput(); _tim->exec(intro, false); _screen->checkedPageUpdate(8, 4); @@ -379,14 +375,14 @@ int LoLEngine::chooseCharacter() { _screen->fadePalette(_screen->getPalette(0), 30, 0); bool kingIntro = true; - while (!_quitFlag) { + while (!quit()) { if (kingIntro) kingSelectionIntro(); if (_charSelection < 0) processCharacterSelection(); - if (_quitFlag) + if (quit()) break; if (_charSelection == 100) { @@ -407,11 +403,11 @@ int LoLEngine::chooseCharacter() { } } - if (_quitFlag) + if (quit()) return -1; uint32 waitTime = _system->getMillis() + 420 * _tickLength; - while (waitTime > _system->getMillis() && !skipFlag() && !_quitFlag) { + while (waitTime > _system->getMillis() && !skipFlag() && !quit()) { updateInput(); _system->delayMillis(10); } @@ -443,7 +439,7 @@ void LoLEngine::kingSelectionIntro() { _chargenWSA->setDrawPage(0); int index = 4; - while (_sound->voiceIsPlaying("KING01") && _charSelection == -1 && !_quitFlag && !skipFlag()) { + while (_sound->voiceIsPlaying("KING01") && _charSelection == -1 && !quit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0); @@ -454,7 +450,7 @@ void LoLEngine::kingSelectionIntro() { _screen->updateScreen(); uint32 waitEnd = _system->getMillis() + 7 * _tickLength; - while (waitEnd > _system->getMillis() && _charSelection == -1 && !_quitFlag && !skipFlag()) { + while (waitEnd > _system->getMillis() && _charSelection == -1 && !quit() && !skipFlag()) { _charSelection = getCharSelection(); _system->delayMillis(10); } @@ -485,7 +481,7 @@ void LoLEngine::kingSelectionReminder() { _chargenWSA->setDrawPage(0); int index = 0; - while (_sound->voiceIsPlaying("KING02") && _charSelection == -1 && !_quitFlag && index < 15) { + while (_sound->voiceIsPlaying("KING02") && _charSelection == -1 && !quit() && index < 15) { _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 0, 0); _screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0); @@ -494,7 +490,7 @@ void LoLEngine::kingSelectionReminder() { _screen->updateScreen(); uint32 waitEnd = _system->getMillis() + 8 * _tickLength; - while (waitEnd > _system->getMillis() && !_quitFlag) { + while (waitEnd > _system->getMillis() && !quit()) { _charSelection = getCharSelection(); _system->delayMillis(10); } @@ -515,14 +511,14 @@ void LoLEngine::kingSelectionOutro() { _chargenWSA->setDrawPage(0); int index = 0; - while (_sound->voiceIsPlaying("KING03") && !_quitFlag && !skipFlag()) { + while (_sound->voiceIsPlaying("KING03") && !quit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 0, 0); _screen->updateScreen(); uint32 waitEnd = _system->getMillis() + 8 * _tickLength; - while (waitEnd > _system->getMillis() && !_quitFlag && !skipFlag()) { + while (waitEnd > _system->getMillis() && !quit() && !skipFlag()) { updateInput(); _system->delayMillis(10); } @@ -541,10 +537,10 @@ void LoLEngine::processCharacterSelection() { debugC(9, kDebugLevelMain, "LoLEngine::processCharacterSelection()"); _charSelection = -1; - while (!_quitFlag && _charSelection == -1) { + while (!quit() && _charSelection == -1) { uint32 nextKingMessage = _system->getMillis() + 900 * _tickLength; - while (nextKingMessage > _system->getMillis() && _charSelection == -1 && !_quitFlag) { + while (nextKingMessage > _system->getMillis() && _charSelection == -1 && !quit()) { updateSelectionAnims(); _charSelection = getCharSelection(); _system->delayMillis(10); @@ -663,12 +659,12 @@ void LoLEngine::selectionCharInfoIntro(char *file) { int index = 0; file[4] = '0'; - while (_charSelectionInfoResult == -1 && !_quitFlag) { + while (_charSelectionInfoResult == -1 && !quit()) { if (!_sound->voicePlay(file)) break; int i = 0; - while (_sound->voiceIsPlaying(file) && _charSelectionInfoResult == -1 && !_quitFlag) { + while (_sound->voiceIsPlaying(file) && _charSelectionInfoResult == -1 && !quit()) { _screen->drawShape(0, _screen->getPtrToShape(_screen->getCPagePtr(9), _charInfoFrameTable[i]), 11, 130, 0, 0); _screen->updateScreen(); -- cgit v1.2.3 From 2d31207a8169491647d8fa3baab7eadbfdfa1da9 Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Wed, 13 Aug 2008 20:27:39 +0000 Subject: Fixed some memory leaks svn-id: r33846 --- engines/kyra/kyra_lok.cpp | 4 ++++ engines/kyra/staticres.cpp | 1 + 2 files changed, 5 insertions(+) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index afd164958c..2ce8af4a81 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -118,8 +118,12 @@ KyraEngine_LoK::~KyraEngine_LoK() { delete[] _characterList; + delete[] _roomTable; + delete[] _movFacingTable; + delete[] _defaultShapeTable; + delete[] _gui->_scrollUpButton.data0ShapePtr; delete[] _gui->_scrollUpButton.data1ShapePtr; delete[] _gui->_scrollUpButton.data2ShapePtr; diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index bb63c24c36..5c0e05f23d 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -920,6 +920,7 @@ void StaticResource::freePaletteTable(void *&ptr, int &size) { uint8 **data = (uint8**)ptr; while (size--) delete[] data[size]; + delete[] data; ptr = 0; size = 0; } -- cgit v1.2.3 From 9d3cdcb2da64ae3afdcd19f1ea18a917f9318190 Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Fri, 15 Aug 2008 18:15:14 +0000 Subject: Defined some MetaEngineFeatures for the engines, the launcher uses these features to allow/disallow loading and deleting saves svn-id: r33909 --- engines/kyra/detection.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index f8aa44be63..5ed556cc27 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -931,11 +931,18 @@ public: return "The Legend of Kyrandia (C) Westwood Studios"; } - bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; - - SaveStateList listSaves(const char *target) const; + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; }; +bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsDirectLoad) || + (f == kSupportsDeleteSave); +} + bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const { const KYRAGameDescription *gd = (const KYRAGameDescription *)desc; bool res = true; -- cgit v1.2.3 From ec8dac5540d87925525523eb1715abc1ec271261 Mon Sep 17 00:00:00 2001 From: Christopher Page Date: Sat, 16 Aug 2008 02:53:16 +0000 Subject: Added a MetaEngineFeature for RTL support, the RTL button is disabled in the GMM if the engine doesn't support it svn-id: r33921 --- engines/kyra/detection.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 5ed556cc27..78b0863ac5 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -938,6 +938,7 @@ public: bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { return + (f == kSupportsRTL) || (f == kSupportsListSaves) || (f == kSupportsDirectLoad) || (f == kSupportsDeleteSave); -- cgit v1.2.3 From 807bfe50796edd683d0aa026adc2cfbca7c490dd Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 16 Aug 2008 12:38:37 +0000 Subject: - KYRA: FM-Towns/PC-98 Audio: fixed several bugs and got rid of some floating point arithmetic (or at least replaced some doubles with floats) - Improved support for PC-98 music: HOF tracks seem to be fine, KYRA should be okay, too (I can't compare with an emulator since I am missing the floppy boot disk with the executable) - There are still tempo issues. Some tracks play way too slow, others way too fast - PC-98 sound effects in Kyra 1 don't work (I would need the floppy disk with the executable for that) svn-id: r33938 --- engines/kyra/kyra_hof.cpp | 12 +- engines/kyra/sequences_hof.cpp | 3 + engines/kyra/sound.h | 5 +- engines/kyra/sound_towns.cpp | 1320 ++++++++++++++++++++++++++++++---------- 4 files changed, 1021 insertions(+), 319 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 33a8af91f1..0271f5ea0d 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -306,8 +306,10 @@ int KyraEngine_HoF::go() { _res->loadFileList(_ingamePakList, _ingamePakListSize); } - if (_flags.platform == Common::kPlatformPC98) + if (_flags.platform == Common::kPlatformPC98) { _res->loadPakFile("AUDIO.PAK"); + _sound->loadSoundFile("sound.dat"); + } } _menuDirectlyToLoad = (_menuChoice == 3) ? true : false; @@ -1578,10 +1580,14 @@ void KyraEngine_HoF::snd_playSoundEffect(int track, int volume) { int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); if (vocIndex != -1) _sound->voicePlay(_ingameSoundList[vocIndex], true); - else if (_flags.platform != Common::kPlatformFMTowns) + else if (_flags.platform == Common::kPlatformPC) + KyraEngine_v1::snd_playSoundEffect(track); + // TODO ?? Maybe there is a way to let users select whether they want // voc, midi or adl sfx (even though it makes no sense to choose anything but voc). - KyraEngine_v1::snd_playSoundEffect(track); + // The PC-98 version has support for non-pcm sound effects, but only for tracks + // which also have voc files. The syntax would be: + // KyraEngine_v1::snd_playSoundEffect(vocIndex); } #pragma mark - diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 635db3629c..3cd319fe77 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -2830,6 +2830,9 @@ void KyraEngine_HoF::seq_init() { _res->unloadAllPakFiles(); _res->loadPakFile(StaticResource::staticDataFilename()); _res->loadFileList(_sequencePakList, _sequencePakListSize); + + if (_flags.platform == Common::kPlatformPC98) + _sound->loadSoundFile("sound.dat"); int numShp = -1; diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index e5294eb15d..2f7ac27ac5 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -429,7 +429,7 @@ public: MidiChannel *allocateChannel() { return 0; } MidiChannel *getPercussionChannel() { return 0; } - static float semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey, + static float calculatePhaseStep(int8 semiTone, int8 semiToneRootkey, uint32 sampleRate, uint32 outputRate, int32 pitchWheel); private: @@ -492,7 +492,7 @@ public: void process(); void loadSoundFile(uint file) {} - void loadSoundFile(Common::String) {} + void loadSoundFile(Common::String file); void playTrack(uint8 track); void haltTrack(); @@ -507,6 +507,7 @@ protected: bool _useFmSfx; uint8 *_musicTrackData; + uint8 *_sfxTrackData; TownsPC98_OpnDriver *_driver; }; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index ec1962a58f..d4c6afa4f6 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -427,7 +427,7 @@ void Towns_EuphonyPcmChannel::nextTick(int32 *outbuf, int buflen) { return; } - float phaseStep = SoundTowns::semitoneAndSampleRate_to_sampleStep(_note, _voice->_snd[_current]->keyNote - + float phaseStep = SoundTowns::calculatePhaseStep(_note, _voice->_snd[_current]->keyNote - _voice->_env[_current]->rootKeyOffset, _voice->_snd[_current]->samplingRate, _rate, _frequencyOffs); int32 looplength = _voice->_snd[_current]->loopLength; @@ -1085,7 +1085,7 @@ void Towns_EuphonyTrackQueue::initDriver() { class TownsPC98_OpnOperator { public: - TownsPC98_OpnOperator(double rate, const uint8 *rateTable, + TownsPC98_OpnOperator(float rate, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable); ~TownsPC98_OpnOperator() {} @@ -1095,7 +1095,7 @@ public: void frequency(int freq); void updatePhaseIncrement(); void recalculateRates(); - void generateOutput(int phasebuf, int *_feedbuf, int &out); + void generateOutput(int phasebuf, int *feedbuf, int &out); void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; } void detune(int value) { _detn = &_detnTbl[value << 5]; } @@ -1137,8 +1137,8 @@ protected: const int32 *_tLvlTbl; const int32 *_detnTbl; - const double _tickLength; - double _tick; + const int _tickLength; + int _tick; int32 _currentLevel; struct EvpState { @@ -1147,11 +1147,11 @@ protected: } fs_a, fs_d, fs_s, fs_r; }; -TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, const uint8 *rateTable, +TownsPC98_OpnOperator::TownsPC98_OpnOperator(float rate, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) : _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), - _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(rate * 65536.0), + _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength((int)(rate * 65536.0f)), _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), _phase(0), _state(s_ready) { @@ -1172,6 +1172,7 @@ void TownsPC98_OpnOperator::frequency(int freq) { uint8 block = (freq >> 11); uint16 pos = (freq & 0x7ff); uint8 c = pos >> 7; + _kcode = (block << 2) | ((c < 7) ? 0 : ((c > 8) ? 3 : c - 6 )); _frequency = _fTbl[pos << 1] >> (7 - block); } @@ -1204,7 +1205,7 @@ void TownsPC98_OpnOperator::recalculateRates() { fs_r.shift = _rshiftTbl[r + k]; } -void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out) { +void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feed, int &out) { if (_state == s_ready) return; @@ -1216,32 +1217,32 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out int32 levelIncrement = 0; uint32 targetTime = 0; int32 targetLevel = 0; - EnvelopeState next_state = s_ready; + EnvelopeState nextState = s_ready; switch (_state) { case s_ready: return; case s_attacking: - next_state = s_decaying; + nextState = s_decaying; targetTime = (1 << fs_a.shift) - 1; targetLevel = 0; levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4; break; case s_decaying: targetTime = (1 << fs_d.shift) - 1; - next_state = s_sustaining; + nextState = s_sustaining; targetLevel = _sustainLevel; levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)]; break; case s_sustaining: targetTime = (1 << fs_s.shift) - 1; - next_state = s_ready; + nextState = s_sustaining; targetLevel = 1023; levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)]; break; case s_releasing: targetTime = (1 << fs_r.shift) - 1; - next_state = s_ready; + nextState = s_ready; targetLevel = 1023; levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)]; break; @@ -1249,11 +1250,10 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out if (!(_tickCount & targetTime)) { _currentLevel += levelIncrement; - if ((!targetLevel && _currentLevel <= targetLevel) || (targetLevel && _currentLevel >= targetLevel)) { + if ((_state == s_attacking && _currentLevel <= targetLevel) || (_state != s_attacking && _currentLevel >= targetLevel)) { if (_state != s_decaying) _currentLevel = targetLevel; - if (_state != s_sustaining) - _state = next_state; + _state = nextState; } } } @@ -1264,10 +1264,10 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out int *i = &outp, *o = &outp; int phaseShift = 0; - if (_feedbuf) { - o = &_feedbuf[0]; - i = &_feedbuf[1]; - phaseShift = _feedbackLevel ? ((_feedbuf[0] + _feedbuf[1]) << _feedbackLevel) : 0; + if (feed) { + o = &feed[0]; + i = &feed[1]; + phaseShift = _feedbackLevel ? ((*o + *i) << _feedbackLevel) : 0; if (phasebuf == -1) *i = 0; *o = *i; @@ -1332,25 +1332,24 @@ public: virtual ~TownsPC98_OpnChannel(); virtual void init(); - typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para); - typedef enum channelState { CHS_RECALCFREQ = 0x01, CHS_KEYOFF = 0x02, - CHS_SSG = 0x04, + CHS_SSGOFF = 0x04, CHS_PITCHWHEELOFF = 0x08, CHS_ALL_BUT_EOT = 0x0f, + CHS_PROTECT = 0x40, CHS_EOT = 0x80 } ChannelState; virtual void loadData(uint8 *data); virtual void processEvents(); virtual void processFrequency(); - bool processControlEvent(uint8 cmd); + virtual bool processControlEvent(uint8 cmd); void writeReg(uint8 regAdress, uint8 value); virtual void keyOn(); - virtual void keyOff(); + void keyOff(); void setOutputLevel(); void fadeStep(); @@ -1361,11 +1360,14 @@ public: bool _enableLeft; bool _enableRight; - bool _updateEnvelopes; + bool _updateEnvelopeParameters; const uint8 _idFlag; int _feedbuf[3]; protected: + void setupPitchWheel(); + bool processPitchWheel(); + bool control_dummy(uint8 para); bool control_f0_setPatch(uint8 para); bool control_f1_presetOutputLevel(uint8 para); @@ -1377,40 +1379,36 @@ protected: bool control_f7_setupPitchWheel(uint8 para); bool control_f8_togglePitchWheel(uint8 para); bool control_fa_writeReg(uint8 para); - bool control_fb_incOutLevel(uint8 para); - bool control_fc_decOutLevel(uint8 para); + virtual bool control_fb_incOutLevel(uint8 para); + virtual bool control_fc_decOutLevel(uint8 para); bool control_fd_jump(uint8 para); - bool control_ff_endOfTrack(uint8 para); - - bool control_f0_setPatchSSG(uint8 para); - bool control_f1_setTotalLevel(uint8 para); - bool control_f4_setAlgorithm(uint8 para); - bool control_f9_unkSSG(uint8 para); - bool control_fb_incOutLevelSSG(uint8 para); - bool control_fc_decOutLevelSSG(uint8 para); - bool control_ff_endOfTrackSSG(uint8 para); + virtual bool control_ff_endOfTrack(uint8 para); uint8 _ticksLeft; uint8 _algorithm; - uint8 _instrID; + uint8 _instr; uint8 _totalLevel; uint8 _frqBlockMSB; int8 _frqLSB; uint8 _keyOffTime; - bool _protect; + bool _hold; uint8 *_dataPtr; - uint8 _ptchWhlInitDelayLo; uint8 _ptchWhlInitDelayHi; + uint8 _ptchWhlInitDelayLo; int16 _ptchWhlModInitVal; uint8 _ptchWhlDuration; uint8 _ptchWhlCurDelay; int16 _ptchWhlModCurVal; uint8 _ptchWhlDurLeft; - uint16 frequency; + uint16 _frequency; + uint8 _block; uint8 _regOffset; uint8 _flags; - uint8 _ssg1; - uint8 _ssg2; + uint8 _ssgTl; + uint8 _ssgStep; + uint8 _ssgTicksLeft; + uint8 _ssgTargetLvl; + uint8 _ssgStartLvl; const uint8 _chanNum; const uint8 _keyNum; @@ -1420,6 +1418,7 @@ protected: TownsPC98_OpnOperator **_opr; uint16 _frqTemp; + typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para); const ControlEventFunc *controlEvents; }; @@ -1427,24 +1426,129 @@ class TownsPC98_OpnChannelSSG : public TownsPC98_OpnChannel { public: TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id); - ~TownsPC98_OpnChannelSSG() {} + virtual ~TownsPC98_OpnChannelSSG() {} void init(); + virtual void loadData(uint8 *data); void processEvents(); void processFrequency(); + bool processControlEvent(uint8 cmd); void keyOn(); - void keyOff(); + void nextShape(); + + void protect(); + void restore(); + + void fadeStep(); + +protected: + void setOutputLevel(uint8 lvl); + + bool control_f0_setInstr(uint8 para); + bool control_f1_setTotalLevel(uint8 para); + bool control_f4_setAlgorithm(uint8 para); + bool control_f9_loadCustomPatch(uint8 para); + bool control_fb_incOutLevel(uint8 para); + bool control_fc_decOutLevel(uint8 para); + bool control_ff_endOfTrack(uint8 para); + + typedef bool (TownsPC98_OpnChannelSSG::*ControlEventFunc)(uint8 para); + const ControlEventFunc *controlEvents; +}; + +class TownsPC98_OpnSfxChannel : public TownsPC98_OpnChannelSSG { +public: + TownsPC98_OpnSfxChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, + uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : + TownsPC98_OpnChannelSSG(driver, regOffs, flgs, num, key, prt, id) {} + ~TownsPC98_OpnSfxChannel() {} + void loadData(uint8 *data); +}; + +class TownsPC98_OpnChannelPCM : public TownsPC98_OpnChannel { +public: + TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, + uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id); + ~TownsPC98_OpnChannelPCM() {} + void init(); + + void loadData(uint8 *data); + void processEvents(); + bool processControlEvent(uint8 cmd); + + void fadeStep(); private: - void opn_SSG_UNK(uint8 a); + bool control_f1_pcmStart(uint8 para); + bool control_ff_endOfTrack(uint8 para); + + typedef bool (TownsPC98_OpnChannelPCM::*ControlEventFunc)(uint8 para); + const ControlEventFunc *controlEvents; }; +class TownsPC98_SSG : public Audio::AudioStream { +public: + TownsPC98_SSG(TownsPC98_OpnDriver *driver, Audio::Mixer *mixer, float rate); + ~TownsPC98_SSG(); + + void init(const int *rsTable, const int *rseTable); + void reset(); + uint8 readReg(uint8 address); + void writeReg(uint8 address, uint8 value, bool force = false); + + // AudioStream interface + int inline readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return true; } + bool endOfData() const { return false; } + int getRate() const { return _mixer->getOutputRate(); } + +private: + void updatesRegs(); + void nextTick(int16 *buffer, uint32 bufferSize); + + uint8 _reg[16]; + uint8 _updateRequestBuf[32]; + int _updateRequest; + uint8 *_regIndex; + int _rand; + + int8 _evpTimer; + uint32 _pReslt; + uint8 _attack; + + bool _evpUpdate, _cont; + + int _evpUpdateCnt; + uint8 _outN; + int _nTick; + + int32 *_tlTable; + int32 *_tleTable; + + const float _rate; + const int _tickLength; + int _timer; + + struct Channel { + int tick; + uint8 smp; + uint8 out; + } _channels[3]; + + TownsPC98_OpnDriver *_drv; + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + + bool _ready; +}; class TownsPC98_OpnDriver : public Audio::AudioStream { friend class TownsPC98_OpnChannel; friend class TownsPC98_OpnChannelSSG; +friend class TownsPC98_OpnSfxChannel; +friend class TownsPC98_OpnChannelPCM; public: enum OpnType { OD_TOWNS, @@ -1456,12 +1560,13 @@ public: ~TownsPC98_OpnDriver(); bool init(); - void loadData(uint8 *data, bool loadPaused = false); + void loadMusicData(uint8 *data, bool loadPaused = false); + void loadSoundEffectData(uint8 *data, uint8 trackNum); void reset(); void fadeOut(); - void pause() { _playing = false; } - void cont() { _playing = true; } + void pause() { _musicPlaying = false; } + void cont() { _musicPlaying = true; } void callback(); void nextTick(int16 *buffer, uint32 bufferSize); @@ -1479,8 +1584,11 @@ protected: TownsPC98_OpnChannel **_channels; TownsPC98_OpnChannelSSG **_ssgChannels; - //TownsPC98_OpnChannel *_adpcmChannel; + TownsPC98_OpnSfxChannel **_sfxChannels; + TownsPC98_OpnChannelPCM *_pcmChannel; + TownsPC98_SSG *_ssg; + void startSoundEffect(); void setTempo(uint8 tempo); void lock() { _mutex.lock(); } @@ -1492,6 +1600,7 @@ protected: const uint8 *_opnCarrier; const uint8 *_opnFreqTable; + const uint8 *_opnFreqTableSSG; const uint8 *_opnFxCmdLen; const uint8 *_opnLvlPresets; @@ -1503,20 +1612,33 @@ protected: int32 *_oprLevelOut; int32 *_oprDetune; - uint8 *_trackData; + uint8 *_musicBuffer; + uint8 *_sfxBuffer; + uint8 *_trackPtr; uint8 *_patches; + uint8 *_ssgPatches; uint8 _cbCounter; uint8 _updateChannelsFlag; + uint8 _updateSSGFlag; + uint8 _updatePCMFlag; uint8 _finishedChannelsFlag; + uint8 _finishedSSGFlag; + uint8 _finishedPCMFlag; + uint16 _tempo; - bool _playing; + bool _musicPlaying; + bool _sfxPlaying; bool _fading; uint8 _looping; uint32 _tickCounter; - bool _updateEnvelopes; - int _ssgFlag; + bool _updateEnvelopeParameters; + + bool _regProtectionFlag; + int _sfxOffs; + uint8 *_sfxData; + uint16 _sfxOffsets[2]; int32 _samplesTillCallback; int32 _samplesTillCallbackRemainder; @@ -1525,12 +1647,14 @@ protected: const int _numChan; const int _numSSG; - const bool _hasADPCM; + const bool _hasPCM; const bool _hasStereo; - double _baserate; static const uint8 _drvTables[]; static const uint32 _adtStat[]; + static const int _ssgTables[]; + + const float _baserate; bool _ready; }; @@ -1538,14 +1662,15 @@ TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 re uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key), _part(prt), _idFlag(id) { - _ticksLeft = _algorithm = _instrID = _totalLevel = _frqBlockMSB = _keyOffTime = _ssg1 = _ssg2 = 0; - _ptchWhlInitDelayLo = _ptchWhlInitDelayHi = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = 0; + _ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0; + _ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0; + _ptchWhlInitDelayHi = _ptchWhlInitDelayLo = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = 0; _frqLSB = 0; - _protect = _updateEnvelopes = false; + _hold = _updateEnvelopeParameters = false; _enableLeft = _enableRight = true; _dataPtr = 0; _ptchWhlModInitVal = _ptchWhlModCurVal = 0; - frequency = _frqTemp = 0; + _frequency = _frqTemp = 0; memset(&_feedbuf, 0, sizeof(int) * 3); _opr = 0; } @@ -1558,8 +1683,7 @@ TownsPC98_OpnChannel::~TownsPC98_OpnChannel() { } } -void TownsPC98_OpnChannel::init() { - +void TownsPC98_OpnChannel::init() { _opr = new TownsPC98_OpnOperator*[4]; for (int i = 0; i < 4; i++) _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift, @@ -1645,13 +1769,13 @@ void TownsPC98_OpnChannel::processEvents() { if (_flags & CHS_EOT) return; - if (_protect == false && _ticksLeft == _keyOffTime) + if (_hold == false && _ticksLeft == _keyOffTime) keyOff(); if (--_ticksLeft) return; - if (_protect == false) + if (_hold == false) keyOff(); uint8 cmd = 0; @@ -1669,14 +1793,14 @@ void TownsPC98_OpnChannel::processEvents() { if (cmd == 0x80) { keyOff(); - _protect = false; + _hold = false; } else { keyOn(); - if (_protect == false || cmd != _frqBlockMSB) + if (_hold == false || cmd != _frqBlockMSB) _flags |= CHS_RECALCFREQ; - _protect = (para & 0x80) ? true : false; + _hold = (para & 0x80) ? true : false; _frqBlockMSB = cmd; } @@ -1687,35 +1811,46 @@ void TownsPC98_OpnChannel::processFrequency() { if (_flags & CHS_RECALCFREQ) { uint8 block = (_frqBlockMSB & 0x70) >> 1; uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f]; - frequency = (bfreq + _frqLSB) | (block << 8); - - writeReg(_regOffset + 0xa4, (frequency >> 8)); - writeReg(_regOffset + 0xa0, (frequency & 0xff)); - _ptchWhlCurDelay = _ptchWhlInitDelayHi; - if (_flags & CHS_KEYOFF) { - _ptchWhlModCurVal = _ptchWhlModInitVal; - _ptchWhlCurDelay += _ptchWhlInitDelayLo; - } + _frequency = (bfreq + _frqLSB) | (block << 8); + writeReg(_regOffset + 0xa4, (_frequency >> 8)); + writeReg(_regOffset + 0xa0, (_frequency & 0xff)); - _ptchWhlDurLeft = (_ptchWhlDuration >> 1); - _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); + setupPitchWheel(); } if (!(_flags & CHS_PITCHWHEELOFF)) { - if (--_ptchWhlCurDelay) + if (!processPitchWheel()) return; - _ptchWhlCurDelay = _ptchWhlInitDelayHi; - frequency += _ptchWhlModCurVal; - writeReg(_regOffset + 0xa4, (frequency >> 8)); - writeReg(_regOffset + 0xa0, (frequency & 0xff)); + writeReg(_regOffset + 0xa4, (_frequency >> 8)); + writeReg(_regOffset + 0xa0, (_frequency & 0xff)); + } +} - if(!--_ptchWhlDurLeft) { - _ptchWhlDurLeft = _ptchWhlDuration; - _ptchWhlModCurVal = -_ptchWhlModCurVal; - } +void TownsPC98_OpnChannel::setupPitchWheel() { + _ptchWhlCurDelay = _ptchWhlInitDelayHi; + if (_flags & CHS_KEYOFF) { + _ptchWhlModCurVal = _ptchWhlModInitVal; + _ptchWhlCurDelay += _ptchWhlInitDelayLo; } + _ptchWhlDurLeft = (_ptchWhlDuration >> 1); + _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); +} + +bool TownsPC98_OpnChannel::processPitchWheel() { + if (--_ptchWhlCurDelay) + return false; + + _ptchWhlCurDelay = _ptchWhlInitDelayHi; + _frequency += _ptchWhlModCurVal; + + if(!--_ptchWhlDurLeft) { + _ptchWhlDurLeft = _ptchWhlDuration; + _ptchWhlModCurVal = -_ptchWhlModCurVal; + } + + return true; } bool TownsPC98_OpnChannel::processControlEvent(uint8 cmd) { @@ -1743,10 +1878,23 @@ void TownsPC98_OpnChannel::fadeStep() { } void TownsPC98_OpnChannel::reset() { - for (int i = 0; i < 4; i++) - _opr[i]->reset(); + if (_opr) { + for (int i = 0; i < 4; i++) + _opr[i]->reset(); + } + + _block = 0; + _frequency = 0; + _hold = false; + _frqTemp = 0; + _ssgTl = 0; + _ssgStartLvl = 0; + _ssgTargetLvl = 0; + _ssgStep = 0; + _ssgTicksLeft = 0; + _totalLevel = 0; - _updateEnvelopes = false; + _updateEnvelopeParameters = false; _enableLeft = _enableRight = true; memset(&_feedbuf, 0, sizeof(int) * 3); } @@ -1820,7 +1968,7 @@ void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, }; if (_enableLeft) { - int l = output + leftSample; + int l = output + (int) leftSample; if (l > 32767) l = 32767; if (l < -32767) @@ -1829,7 +1977,7 @@ void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, } if (_enableRight) { - int r = output + rightSample; + int r = output + (int) rightSample; if (r > 32767) r = 32767; if (r < -32767) @@ -1839,19 +1987,29 @@ void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, } void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { + if (_drv->_regProtectionFlag) + return; + uint8 h = regAdress & 0xf0; uint8 l = (regAdress & 0x0f); static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; uint8 o = oprOrdr[(l - _regOffset) >> 2]; - + switch (h) { case 0x00: // ssg - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + if (_drv->_ssg) + _drv->_ssg->writeReg(regAdress, value); break; case 0x10: - // adpcm - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + // pcm rhythm channel + if (!(regAdress -= 0x10) && !(value & 0x80)) { + static const char *names[] = { "bass drum", "snare drum", "top cymbal", "high hat", "tom tom", "rim shot" }; + for (int i = 0; i < 6; i++) + if ((value >> i) & 1) + debugC(9, kDebugLevelMain | kDebugLevelSound, "TownsPC98_OpnDriver: TRYING TO USE UNSUPPORTED PCM INSTRUMENT: '%s'", names[i]); + } + break; case 0x20: if (l == 8) { @@ -1884,7 +2042,7 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { // detune, multiple _opr[o]->detune((value >> 4) & 7); _opr[o]->multiple(value & 0x0f); - _updateEnvelopes = true; + _updateEnvelopeParameters = true; break; case 0x40: @@ -1896,7 +2054,7 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { // rate scaling, attack rate _opr[o]->attackRate(value & 0x1f); if (_opr[o]->scaleRate(value >> 6)) - _updateEnvelopes = true; + _updateEnvelopeParameters = true; break; case 0x60: @@ -1904,7 +2062,6 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { _opr[o]->decayRate(value & 0x1f); if (value & 0x80) warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)"); - break; case 0x70: @@ -1919,7 +2076,6 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { break; case 0x90: - // ssg warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); break; @@ -1928,7 +2084,7 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { l -= _regOffset; if (l == 0) { _frqTemp = (_frqTemp & 0xff00) | value; - _updateEnvelopes = true; + _updateEnvelopeParameters = true; for (int i = 0; i < 4; i++) _opr[i]->frequency(_frqTemp); } else if (l == 4) { @@ -1970,7 +2126,7 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { } bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { - _instrID = para; + _instr = para; uint8 reg = _regOffset + 0x80; for (int i = 0; i < 4; i++) { @@ -1979,7 +2135,7 @@ bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { reg += 4; } - const uint8 *tptr = _drv->_patches + ((uint32)_instrID << 5); + const uint8 *tptr = _drv->_patches + ((uint32)_instr << 5); reg = _regOffset + 0x30; // write registers 0x30 to 0x8f @@ -2043,7 +2199,7 @@ bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) { if (*_dataPtr) { // repeat section until counter has reached zero - _dataPtr = _drv->_trackData + READ_LE_UINT16(_dataPtr + 2); + _dataPtr = _drv->_trackPtr + READ_LE_UINT16(_dataPtr + 2); } else { // reset counter, advance to next section _dataPtr[0] = _dataPtr[1]; @@ -2053,8 +2209,8 @@ bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) { } bool TownsPC98_OpnChannel::control_f7_setupPitchWheel(uint8 para) { - _ptchWhlInitDelayLo = _dataPtr[0]; - _ptchWhlInitDelayHi = para; + _ptchWhlInitDelayHi = _dataPtr[0]; + _ptchWhlInitDelayLo = para; _ptchWhlModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1); _ptchWhlDuration = _dataPtr[3]; _dataPtr += 4; @@ -2113,7 +2269,7 @@ bool TownsPC98_OpnChannel::control_fc_decOutLevel(uint8 para) { } bool TownsPC98_OpnChannel::control_fd_jump(uint8 para) { - uint8 *tmp = _drv->_trackData + READ_LE_UINT16(_dataPtr - 1); + uint8 *tmp = _drv->_trackPtr + READ_LE_UINT16(_dataPtr - 1); _dataPtr = (tmp[1] == 1) ? tmp : ++_dataPtr; return true; } @@ -2127,7 +2283,7 @@ bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) { uint16 val = READ_LE_UINT16(--_dataPtr); if (val) { // loop - _dataPtr = _drv->_trackData + val; + _dataPtr = _drv->_trackPtr + val; return true; } else { // quit parsing for active channel @@ -2139,31 +2295,250 @@ bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) { } } -bool TownsPC98_OpnChannel::control_f0_setPatchSSG(uint8 para) { - _instrID = para << 4; +TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, + uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : + TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) { +} + +void TownsPC98_OpnChannelSSG::init() { + _algorithm = 0x80; + + #define Control(x) &TownsPC98_OpnChannelSSG::control_##x + static const ControlEventFunc ctrlEventsSSG[] = { + Control(f0_setInstr), + Control(f1_setTotalLevel), + Control(f2_setKeyOffTime), + Control(f3_setFreqLSB), + Control(f4_setAlgorithm), + Control(f5_setTempo), + Control(f6_repeatSection), + Control(f7_setupPitchWheel), + Control(f8_togglePitchWheel), + Control(f9_loadCustomPatch), + Control(fa_writeReg), + Control(fb_incOutLevel), + Control(fc_decOutLevel), + Control(fd_jump), + Control(dummy), + Control(ff_endOfTrack) + }; + #undef Control + + controlEvents = ctrlEventsSSG; +} + +void TownsPC98_OpnChannelSSG::processEvents() { + if (_flags & CHS_EOT) + return; + + _drv->_regProtectionFlag = (_flags & CHS_PROTECT) ? true : false; + + if (!_hold && _ticksLeft == _keyOffTime) + nextShape(); + + if (!--_ticksLeft) { + + uint8 cmd = 0; + bool loop = true; + + while (loop) { + cmd = *_dataPtr++; + if (cmd < 0xf0) + loop = false; + else if (!processControlEvent(cmd)) + return; + } + + uint8 para = *_dataPtr++; + + if (cmd == 0x80) { + nextShape(); + _hold = false; + } else { + if (!_hold) { + _instr &= 0xf0; + _ssgStep = _drv->_ssgPatches[_instr]; + _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f; + _ssgTargetLvl = _drv->_ssgPatches[_instr + 2]; + _ssgStartLvl = _drv->_ssgPatches[_instr + 3]; + _flags = (_flags & ~CHS_SSGOFF) | CHS_KEYOFF; + } + + keyOn(); + + if (_hold == false || cmd != _frqBlockMSB) + _flags |= CHS_RECALCFREQ; + + _hold = (para & 0x80) ? true : false; + _frqBlockMSB = cmd; + } + + _ticksLeft = para & 0x7f; + } + + if (!(_flags & CHS_SSGOFF)) { + if (--_ssgTicksLeft) { + if (!_drv->_fading) + setOutputLevel(_ssgStartLvl); + return; + } + + _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f; + + if (_drv->_ssgPatches[_instr + 1] & 0x80) { + uint8 t = _ssgStartLvl - _ssgStep; + + if (_ssgStep <= _ssgStartLvl && _ssgTargetLvl < t) { + if (!_drv->_fading) + setOutputLevel(t); + return; + } + } else { + int t = _ssgStartLvl + _ssgStep; + uint8 p = (uint8) (t & 0xff); + + if (t < 256 && _ssgTargetLvl > p) { + if (!_drv->_fading) + setOutputLevel(p); + return; + } + } + + setOutputLevel(_ssgTargetLvl); + if (_ssgStartLvl && !(_instr & 8)){ + _instr += 4; + _ssgStep = _drv->_ssgPatches[_instr]; + _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f; + _ssgTargetLvl = _drv->_ssgPatches[_instr + 2]; + } else { + _flags |= CHS_SSGOFF; + setOutputLevel(0); + } + } +} + +void TownsPC98_OpnChannelSSG::processFrequency() { + if (_algorithm & 0x40) + return; + + if (_flags & CHS_RECALCFREQ) { + _block = _frqBlockMSB >> 4; + _frequency = ((const uint16*)_drv->_opnFreqTableSSG)[_frqBlockMSB & 0x0f] + _frqLSB; + + uint16 f = _frequency >> _block; + writeReg(_regOffset << 1, f & 0xff); + writeReg((_regOffset << 1) + 1, f >> 8); + + setupPitchWheel(); + } + + if (!(_flags & (CHS_EOT | CHS_PITCHWHEELOFF | CHS_SSGOFF))) { + if (!processPitchWheel()) + return; + + processPitchWheel(); + + uint16 f = _frequency >> _block; + writeReg(_regOffset << 1, f & 0xff); + writeReg((_regOffset << 1) + 1, f >> 8); + } +} + +bool TownsPC98_OpnChannelSSG::processControlEvent(uint8 cmd) { + uint8 para = *_dataPtr++; + return (this->*controlEvents[cmd & 0x0f])(para); +} + +void TownsPC98_OpnChannelSSG::nextShape() { + _instr = (_instr & 0xf0) + 0x0c; + _ssgStep = _drv->_ssgPatches[_instr]; + _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f; + _ssgTargetLvl = _drv->_ssgPatches[_instr + 2]; +} + +void TownsPC98_OpnChannelSSG::keyOn() { + uint8 c = 0x7b; + uint8 t = (_algorithm & 0xC0) << 1; + if (_algorithm & 0x80) + t |= 4; + + c = (c << (_regOffset + 1)) | (c >> (7 - _regOffset)); + t = (t << (_regOffset + 1)) | (t >> (7 - _regOffset)); + + if (!(_algorithm & 0x80)) + writeReg(6, _algorithm & 0x7f); + + uint8 e = (_drv->_ssg->readReg(7) & c) | t; + writeReg(7, e); +} + +void TownsPC98_OpnChannelSSG::protect() { + _flags |= CHS_PROTECT; +} + +void TownsPC98_OpnChannelSSG::restore() { + _flags &= ~CHS_PROTECT; + keyOn(); + writeReg(8 + _regOffset, _ssgTl); + uint16 f = _frequency >> _block; + writeReg(_regOffset << 1, f & 0xff); + writeReg((_regOffset << 1) + 1, f >> 8); +} + +void TownsPC98_OpnChannelSSG::loadData(uint8 *data) { + _drv->_regProtectionFlag = (_flags & CHS_PROTECT) ? true : false; + TownsPC98_OpnChannel::loadData(data); + setOutputLevel(0); + _algorithm = 0x80; +} + +void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) { + _ssgStartLvl = lvl; + uint16 newTl = (((uint16)_totalLevel + 1) * (uint16)lvl) >> 8; + if (newTl == _ssgTl) + return; + _ssgTl = newTl; + writeReg(8 + _regOffset, _ssgTl); +} + +void TownsPC98_OpnChannelSSG::fadeStep() { + _totalLevel--; + if ((int8)_totalLevel < 0) + _totalLevel = 0; + setOutputLevel(_ssgStartLvl); +} + +bool TownsPC98_OpnChannelSSG::control_f0_setInstr(uint8 para) { + _instr = para << 4; para = (para >> 3) & 0x1e; if (para) return control_f4_setAlgorithm(para | 0x40); return true; } -bool TownsPC98_OpnChannel::control_f1_setTotalLevel(uint8 para) { +bool TownsPC98_OpnChannelSSG::control_f1_setTotalLevel(uint8 para) { if (!_drv->_fading) _totalLevel = para; return true; } -bool TownsPC98_OpnChannel::control_f4_setAlgorithm(uint8 para) { +bool TownsPC98_OpnChannelSSG::control_f4_setAlgorithm(uint8 para) { _algorithm = para; return true; } -bool TownsPC98_OpnChannel::control_f9_unkSSG(uint8 para) { - _dataPtr += 5; +bool TownsPC98_OpnChannelSSG::control_f9_loadCustomPatch(uint8 para) { + _instr = (_drv->_sfxOffs + 10 + _regOffset) << 4; + _drv->_ssgPatches[_instr] = *_dataPtr++; + _drv->_ssgPatches[_instr + 3] = para; + _drv->_ssgPatches[_instr + 4] = *_dataPtr++; + _drv->_ssgPatches[_instr + 6] = *_dataPtr++; + _drv->_ssgPatches[_instr + 8] = *_dataPtr++; + _drv->_ssgPatches[_instr + 12] = *_dataPtr++; return true; } -bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) { +bool TownsPC98_OpnChannelSSG::control_fb_incOutLevel(uint8 para) { _dataPtr--; if (_drv->_fading) return true; @@ -2175,7 +2550,7 @@ bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) { return true; } -bool TownsPC98_OpnChannel::control_fc_decOutLevelSSG(uint8 para) { +bool TownsPC98_OpnChannelSSG::control_fc_decOutLevel(uint8 para) { _dataPtr--; if (_drv->_fading) return true; @@ -2186,184 +2561,331 @@ bool TownsPC98_OpnChannel::control_fc_decOutLevelSSG(uint8 para) { return true; } -bool TownsPC98_OpnChannel::control_ff_endOfTrackSSG(uint8 para) { - uint16 val = READ_LE_UINT16(--_dataPtr); - if (val) { - // loop - _dataPtr = _drv->_trackData + val; - return true; +bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) { + if (!_drv->_sfxOffs) { + uint16 val = READ_LE_UINT16(--_dataPtr); + if (val) { + // loop + _dataPtr = _drv->_trackPtr + val; + return true; + } else { + // stop parsing + if (!_drv->_fading) + setOutputLevel(0); + --_dataPtr; + _flags |= CHS_EOT; + _drv->_finishedSSGFlag |= _idFlag; + } } else { - // quit parsing for active channel - --_dataPtr; + // end of sfx track - restore ssg music channel _flags |= CHS_EOT; - //_finishedChannelsFlag |= _idFlag; - keyOff(); - return false; + _drv->_ssgChannels[_chanNum]->restore(); } + + return false; } -TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, +void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { + _flags = CHS_ALL_BUT_EOT; + _ticksLeft = 1; + _dataPtr = data; + _ssgTl = 0xff; + _algorithm = 0x80; +} + +TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) { } -void TownsPC98_OpnChannelSSG::init() { +void TownsPC98_OpnChannelPCM::init() { _algorithm = 0x80; - - _opr = new TownsPC98_OpnOperator*[4]; - for (int i = 0; i < 4; i++) - _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift, - _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune); - #define Control(x) &TownsPC98_OpnChannelSSG::control_##x - static const ControlEventFunc ctrlEventsSSG[] = { - Control(f0_setPatchSSG), - Control(f1_setTotalLevel), - Control(f2_setKeyOffTime), - Control(f3_setFreqLSB), - Control(f4_setOutputLevel), - Control(f5_setTempo), + #define Control(x) &TownsPC98_OpnChannelPCM::control_##x + static const ControlEventFunc ctrlEventsPCM[] = { + Control(dummy), + Control(f1_pcmStart), + Control(dummy), + Control(dummy), + Control(dummy), + Control(dummy), Control(f6_repeatSection), - Control(f7_setupPitchWheel), - Control(f8_togglePitchWheel), - Control(f9_unkSSG), + Control(dummy), + Control(dummy), + Control(dummy), Control(fa_writeReg), - Control(fb_incOutLevelSSG), - Control(fc_decOutLevelSSG), - Control(fd_jump), Control(dummy), - Control(ff_endOfTrackSSG) + Control(dummy), + Control(dummy), + Control(dummy), + Control(ff_endOfTrack) }; #undef Control - controlEvents = ctrlEventsSSG; + controlEvents = ctrlEventsPCM; } -void TownsPC98_OpnChannelSSG::processEvents() { +void TownsPC98_OpnChannelPCM::loadData(uint8 *data) { + _flags = (_flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; + _ticksLeft = 1; + _dataPtr = data; + _totalLevel = 0x7F; +} + +void TownsPC98_OpnChannelPCM::processEvents() { if (_flags & CHS_EOT) return; - _drv->_ssgFlag = (_flags & CHS_SSG) ? -1 : 0; - - if (_protect == false && _ticksLeft == _keyOffTime) - keyOff(); - if (--_ticksLeft) return; - if (_protect == false) - keyOff(); - uint8 cmd = 0; bool loop = true; while (loop) { cmd = *_dataPtr++; - if (cmd < 0xf0) + if (cmd == 0x80) { loop = false; - else if (!processControlEvent(cmd)) + } else if (cmd < 0xf0) { + writeReg(0x10, cmd); + } else if (!processControlEvent(cmd)) { return; + } } + _ticksLeft = *_dataPtr++; +} + +bool TownsPC98_OpnChannelPCM::processControlEvent(uint8 cmd) { uint8 para = *_dataPtr++; + return (this->*controlEvents[cmd & 0x0f])(para); +} - if (cmd == 0x80) { - keyOff(); - _protect = false; - } else { - keyOn(); +void TownsPC98_OpnChannelPCM::fadeStep() { - if (_protect == false || cmd != _frqBlockMSB) - _flags |= CHS_RECALCFREQ; - - _protect = (para & 0x80) ? true : false; - _frqBlockMSB = cmd; +} + +bool TownsPC98_OpnChannelPCM::control_f1_pcmStart(uint8 para) { + _totalLevel = para; + writeReg(0x11, para); + return true; +} + +bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { + uint16 val = READ_LE_UINT16(--_dataPtr); + if (val) { + // loop + _dataPtr = _drv->_trackPtr + val; + return true; + } else { + // quit parsing for active channel + --_dataPtr; + _flags |= CHS_EOT; + _drv->_finishedPCMFlag |= _idFlag; + return false; } +} - _ticksLeft = para & 0x7f; +TownsPC98_SSG::TownsPC98_SSG(TownsPC98_OpnDriver *driver, Audio::Mixer *mixer, float rate) : _drv(driver), _mixer(mixer), _rate(rate), + _tlTable(0), _tleTable(0), _regIndex(_reg), _updateRequest(-1), _tickLength((int)(rate * 32768.0f * 27.0f)), _ready(0) { + memset(_reg, 0, 16); + memset(_channels, 0, sizeof(Channel) * 3); + reset(); +} - if (!(_flags & CHS_SSG)) { +TownsPC98_SSG::~TownsPC98_SSG() { + _mixer->stopHandle(_soundHandle); - } + delete [] _tlTable; + delete [] _tleTable; } -void TownsPC98_OpnChannelSSG::processFrequency() { - if (_flags & CHS_RECALCFREQ) { - uint8 block = (_frqBlockMSB & 0x70) >> 1; - uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f]; - frequency = (bfreq + _frqLSB) | (block << 8); +void TownsPC98_SSG::init(const int *rsTable, const int *rseTable) { + if (_ready) { + reset(); + return; + } - writeReg(_regOffset + 0xa4, (frequency >> 8)); - writeReg(_regOffset + 0xa0, (frequency & 0xff)); + delete [] _tlTable; + delete [] _tleTable; + _tlTable = new int32[16]; + _tleTable = new int32[32]; + float a, b, d; + d = 801.0f; - _ptchWhlCurDelay = _ptchWhlInitDelayHi; - if (_flags & CHS_KEYOFF) { - _ptchWhlModCurVal = _ptchWhlModInitVal; - _ptchWhlCurDelay += _ptchWhlInitDelayLo; - } + for (int i = 0; i < 16; i++) { + b = 1.0f / rsTable[i]; + a = 1.0f / d + b + 1.0f / 1000.0f; + float v = (b / a) * 32767.0f; + _tlTable[i] = (int32) v; - _ptchWhlDurLeft = (_ptchWhlDuration >> 1); - _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); + b = 1.0f / rseTable[i]; + a = 1.0f / d + b + 1.0f / 1000.0f; + v = (b / a) * 32767.0f; + _tleTable[i] = (int32) v; } - if (!(_flags & CHS_PITCHWHEELOFF)) { - if (--_ptchWhlCurDelay) - return; - _ptchWhlCurDelay = _ptchWhlInitDelayHi; - frequency += _ptchWhlModCurVal; + for (int i = 16; i < 32; i++) { + b = 1.0f / rseTable[i]; + a = 1.0f / d + b + 1.0f / 1000.0f; + float v = (b / a) * 32767.0f; + _tleTable[i] = (int32) v; + } - writeReg(_regOffset + 0xa4, (frequency >> 8)); - writeReg(_regOffset + 0xa0, (frequency & 0xff)); + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, + &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); - if(!--_ptchWhlDurLeft) { - _ptchWhlDurLeft = _ptchWhlDuration; - _ptchWhlModCurVal = -_ptchWhlModCurVal; - } + _ready = true; +} + +void TownsPC98_SSG::reset() { + _rand = 1; + _outN = 1; + _updateRequest = -1; + _nTick = _evpUpdateCnt = 0; + _regIndex = _reg; + _evpTimer = 0x1f; + _pReslt = 0x1f; + _attack = 0; + _cont = false; + _evpUpdate = true; + _timer = 0; + + for (int i = 0; i < 3; i++) { + _channels[i].tick = 0; + _channels[i].smp = _channels[i].out = 0; } + + for (int i = 0; i < 14; i++) + writeReg(i, 0, true); + + writeReg(7, 0xbf, true); } -void TownsPC98_OpnChannelSSG::keyOff() { - // all operators off - uint8 value = _keyNum & 0x0f; - uint8 regAdress = 0x28; - writeReg(regAdress, value); - _flags |= CHS_KEYOFF; +uint8 TownsPC98_SSG::readReg(uint8 address) { + return _reg[address]; } -void TownsPC98_OpnChannelSSG::keyOn() { - // all operators on - uint8 value = _keyNum | 0xf0; - uint8 regAdress = 0x28; - writeReg(regAdress, value); +void TownsPC98_SSG::writeReg(uint8 address, uint8 value, bool force) { + _regIndex = &_reg[address]; + int o = _regIndex - _reg; + if (!force && (o == 13 || *_regIndex != value)) { + if (_updateRequest == 31) { + warning("TownsPC98_SSG: event buffer overflow"); + _updateRequest = -1; + } + _updateRequestBuf[++_updateRequest] = value; + _updateRequestBuf[++_updateRequest] = o; + return; + } + + *_regIndex = value; } -void TownsPC98_OpnChannelSSG::loadData(uint8 *data) { - _drv->_ssgFlag = (_flags & CHS_SSG) ? -1 : 0; - opn_SSG_UNK(0); - TownsPC98_OpnChannel::loadData(data); - _algorithm = 0x80; +void TownsPC98_SSG::updatesRegs() { + for (int i = 0; i < _updateRequest;) { + uint8 b = _updateRequestBuf[i++]; + uint8 a = _updateRequestBuf[i++]; + writeReg(a, b, true); + } + _updateRequest = -1; } -void TownsPC98_OpnChannelSSG::opn_SSG_UNK(uint8 a) { - _ssg1 = a; - uint16 h = (_totalLevel + 1) * a; - if ((h >> 8) == _ssg2) +void TownsPC98_SSG::nextTick(int16 *buffer, uint32 bufferSize) { + if (!_ready) return; - _ssg2 = (h >> 8); - writeReg(8 + _regOffset, _ssg2); + + for (uint32 i = 0; i < bufferSize; i++) { + _timer += _tickLength; + while (_timer > 0x30000) { + _timer -= 0x30000; + + if (++_nTick >= (_reg[6] & 0x1f)) { + if ((_rand + 1) & 2) + _outN ^= 1; + + _rand = (((_rand & 1) ^ ((_rand >> 3) & 1)) << 16) | (_rand >> 1); + _nTick = 0; + } + + for (int ii = 0; ii < 3; ii++) { + if (++_channels[ii].tick >= (((_reg[ii * 2 + 1] & 0x0f) << 8) | _reg[ii * 2])) { + _channels[ii].tick = 0; + _channels[ii].smp ^= 1; + } + _channels[ii].out = (_channels[ii].smp | ((_reg[7] >> ii) & 1)) & (_outN | ((_reg[7] >> (ii + 3)) & 1)); + } + + if (_evpUpdate) { + if (++_evpUpdateCnt >= ((_reg[12] << 8) | _reg[11])) { + _evpUpdateCnt = 0; + + if (--_evpTimer < 0) { + if (_cont) { + _evpTimer &= 0x1f; + } else { + _evpUpdate = false; + _evpTimer = 0; + } + } + } + } + _pReslt = _evpTimer ^ _attack; + updatesRegs(); + } + + int16 t[3]; + for (int ii = 0; ii < 3; ii++) { + if ((_reg[ii + 8] >> 4) & 1) + t[ii] = _tleTable[_channels[ii].out ? _pReslt : 0]; + else + t[ii] = _tlTable[_channels[ii].out ? (_reg[ii + 8] & 0x0f) : 0]; + } + + int l = (int) buffer[i << 1]; + int r = (int) buffer[(i << 1) + 1]; + + for (int ii = 0; ii < 3; ii++) { + l += t[ii]; + r += t[ii]; + } + + l /= 2; + r /= 2; + + if (l > 32767) + l = 32767; + if (l < -32767) + l = -32767; + buffer[i << 1] = (int16)l; + + if (r > 32767) + r = 32767; + if (r < -32767) + r = -32767; + buffer[(i << 1) + 1] = (int16)r; + } } +int TownsPC98_SSG::readBuffer(int16 *buffer, const int numSamples) { + memset(buffer, 0, sizeof(int16) * numSamples); + nextTick(buffer, numSamples >> 1); + return numSamples; +} + TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : - _mixer(mixer), _trackData(0), _playing(false), _fading(false), _channels(0), _ssgChannels(0), - _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), - _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) , - _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), - _oprDetune(0), _cbCounter(4), _tickCounter(0), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), - _finishedChannelsFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), _ready(false), - _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false), - _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) { + _mixer(mixer), _trackPtr(0), _musicPlaying(false), _sfxPlaying(false), _fading(false), _channels(0), + _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _looping(0), _opnCarrier(_drvTables + 76), + _opnFreqTable(_drvTables + 84), _opnFreqTableSSG(_drvTables + 252), _opnFxCmdLen(_drvTables + 36), + _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 228)), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), + _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _cbCounter(4), _tickCounter(0), + _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _updateSSGFlag(type == OD_TOWNS ? 0 : 7), + _updatePCMFlag(type == OD_TYPE86 ? 1 : 0), _finishedChannelsFlag(0), _finishedSSGFlag(0), + _finishedPCMFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), + _sfxData(0), _ready(false), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPCM(type == OD_TYPE86 ? true : false), + _sfxOffs(0), _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true), + _ssgPatches(0), _ssg(0), _baserate(55125.0f / (float)getRate()) { setTempo(84); - _baserate = (486202500.0 / (double)getRate()) / 10368.0; } TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { @@ -2381,13 +2903,24 @@ TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { delete [] _ssgChannels; } + if (_sfxChannels) { + for (int i = 0; i < 2; i++) + delete _sfxChannels[i]; + delete [] _sfxChannels; + } + + if (_pcmChannel) + delete _pcmChannel; + + delete _ssg; delete [] _oprRates; delete [] _oprRateshift; delete [] _oprFrq; delete [] _oprAttackDecay; delete [] _oprSinTbl; delete [] _oprLevelOut; - delete [] _oprDetune; + delete [] _oprDetune; + delete [] _ssgPatches; } bool TownsPC98_OpnDriver::init() { @@ -2420,7 +2953,21 @@ bool TownsPC98_OpnDriver::init() { } delete [] _ssgChannels; } + + if (_sfxChannels) { + for (int i = 0; i < 2; i++) { + if (_sfxChannels[i]) + delete _sfxChannels[i]; + } + delete [] _sfxChannels; + } + if (_numSSG) { + _ssg = new TownsPC98_SSG(this, _mixer, _baserate); + _ssg->init(&_ssgTables[0], &_ssgTables[16]); + _ssgPatches = new uint8[256]; + memcpy(_ssgPatches, _drvTables + 244, 256); + _ssgChannels = new TownsPC98_OpnChannelSSG*[_numSSG]; for (int i = 0; i < _numSSG; i++) { int ii = i * 6; @@ -2428,6 +2975,20 @@ bool TownsPC98_OpnDriver::init() { _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]); _ssgChannels[i]->init(); } + + _sfxChannels = new TownsPC98_OpnSfxChannel*[2]; + for (int i = 0; i < 2; i++) { + int ii = (i + 1) * 6; + _sfxChannels[i] = new TownsPC98_OpnSfxChannel(this, _drvTables[ii], _drvTables[ii + 1], + _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]); + _sfxChannels[i]->init(); + } + } + + if (_hasPCM) { + delete _pcmChannel; + _pcmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1); + _pcmChannel->init(); } _mixer->playInputStream(Audio::Mixer::kMusicSoundType, @@ -2440,9 +3001,11 @@ bool TownsPC98_OpnDriver::init() { int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) { memset(buffer, 0, sizeof(int16) * numSamples); int32 samplesLeft = numSamples >> 1; + while (samplesLeft) { if (!_samplesTillCallback) { callback(); + _samplesTillCallback = _samplesPerCallback; _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; if (_samplesTillCallbackRemainder >= _tempo) { @@ -2458,8 +3021,19 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) nextTick(buffer, render); for (int i = 0; i < render; ++i) { - buffer[i << 1] <<= 2; - buffer[(i << 1) + 1] <<= 2; + int l = (int) (buffer[i << 1] * 7) / 2; + if (l > 32767) + l = 32767; + if (l < -32767) + l = -32767; + buffer[i << 1] = (int16) l; + + int r = (int) (buffer[(i << 1) + 1] * 7) / 2; + if (r > 32767) + r = 32767; + if (r < -32767) + r = -32767; + buffer[(i << 1) + 1] = (int16) r; } buffer += (render << 1); @@ -2468,7 +3042,7 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) return numSamples; } -void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) { +void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) { if (!_ready) { warning("TownsPC98_OpnDriver: Driver must be initialized before loading data"); return; @@ -2479,12 +3053,11 @@ void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) { return; } - lock(); - _trackData = data; - reset(); + + lock(); - uint8 *src_a = data; + uint8 *src_a = _trackPtr = _musicBuffer = data; for (uint8 i = 0; i < 3; i++) { _channels[i]->loadData(data + READ_LE_UINT16(src_a)); @@ -2501,117 +3074,167 @@ void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) { src_a += 2; } - if (_hasADPCM) { - //_adpcmChannel->loadData(data + READ_LE_UINT16(src_a)); + if (_hasPCM) { + _pcmChannel->loadData(data + READ_LE_UINT16(src_a)); src_a += 2; } - _ssgFlag = 0; + _regProtectionFlag = false; _patches = src_a + 4; _cbCounter = 4; - _finishedChannelsFlag = 0; + _finishedChannelsFlag = _finishedSSGFlag = 0; + + _musicPlaying = (loadPaused ? false : true); + + unlock(); +} + +void TownsPC98_OpnDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { + if (!_ready) { + warning("TownsPC98_OpnDriver: Driver must be initialized before loading data"); + return; + } + + if (!_sfxChannels) { + warning("TownsPC98_OpnDriver: sound effects not supported by this configuration"); + return; + } - // AH 0x17 + if (!data) { + warning("TownsPC98_OpnDriver: Invalid sound effect file data"); + return; + } + + lock(); + _sfxData = _sfxBuffer = data; + _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]); + _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]); + _sfxPlaying = true; unlock(); - _playing = (loadPaused ? false : true); } void TownsPC98_OpnDriver::reset() { - for (int i = 0; i < (_numChan); i++) + lock(); + + for (int i = 0; i < _numChan; i++) _channels[i]->reset(); - for (int i = 0; i < (_numSSG); i++) + for (int i = 0; i < _numSSG; i++) _ssgChannels[i]->reset(); + + if (_ssg) { + for (int i = 0; i < 2; i++) + _sfxChannels[i]->reset(); + + memcpy(_ssgPatches, _drvTables + 276, 256); + _ssg->reset(); + } - _playing = _fading = false; + _musicPlaying = _sfxPlaying = _fading = false; _looping = 0; _tickCounter = 0; + _sfxData = 0; + + unlock(); } void TownsPC98_OpnDriver::fadeOut() { - if (!_playing) + if (!_musicPlaying) return; - _fading = true; - for (int i = 0; i < 20; i++) { lock(); + + _fading = true; + uint32 dTime = _tickCounter + 2; for (int j = 0; j < _numChan; j++) { if (_updateChannelsFlag & _channels[j]->_idFlag) _channels[j]->fadeStep(); } - for (int j = 0; j < _numSSG; j++) - _ssgChannels[j]->fadeStep(); + for (int j = 0; j < _numSSG; j++) { + if (_updateSSGFlag & _channels[j]->_idFlag) + _ssgChannels[j]->fadeStep(); + } unlock(); - while (_playing) { + while (_musicPlaying) { if (_tickCounter >= dTime) break; } } - _fading = false; - reset(); } void TownsPC98_OpnDriver::callback() { - if (!_playing || --_cbCounter) - return; + lock(); - _cbCounter = 4; _tickCounter++; - lock(); + if (_sfxChannels && _sfxPlaying) { + if (_sfxData) + startSoundEffect(); - for (int i = 0; i < _numChan; i++) { - if (_updateChannelsFlag & _channels[i]->_idFlag) { - _channels[i]->processEvents(); - _channels[i]->processFrequency(); + _sfxOffs = 3; + _trackPtr = _sfxBuffer; + + for (int i = 0; i < 2; i++) { + _sfxChannels[i]->processEvents(); + _sfxChannels[i]->processFrequency(); } + + _trackPtr = _musicBuffer; } - if (_numSSG) { - for (int i = 0; i < _numSSG; i++) { - _ssgChannels[i]->processEvents(); - _ssgChannels[i]->processFrequency(); + _sfxOffs = 0; + + if (!--_cbCounter && _musicPlaying) { + _cbCounter = 4; + + for (int i = 0; i < _numChan; i++) { + if (_updateChannelsFlag & _channels[i]->_idFlag) { + _channels[i]->processEvents(); + _channels[i]->processFrequency(); + } } + + if (_numSSG) { + for (int i = 0; i < _numSSG; i++) { + if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { + _ssgChannels[i]->processEvents(); + _ssgChannels[i]->processFrequency(); + } + } + } + + if (_hasPCM) + if (_updatePCMFlag & _pcmChannel->_idFlag) + _pcmChannel->processEvents(); } - - _ssgFlag = 0; - unlock(); + _regProtectionFlag = false; - if (_finishedChannelsFlag == _updateChannelsFlag) - reset(); + if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedPCMFlag == _updatePCMFlag) + _musicPlaying = false; + + unlock(); } void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { - if (!_playing) + if (!_ready) return; - for (int i = 0; i < _numChan ; i++) { - if (_channels[i]->_updateEnvelopes) { - _channels[i]->_updateEnvelopes = false; + for (int i = 0; i < _numChan; i++) { + if (_channels[i]->_updateEnvelopeParameters) { + _channels[i]->_updateEnvelopeParameters = false; _channels[i]->updateEnv(); } for (uint32 ii = 0; ii < bufferSize ; ii++) _channels[i]->generateOutput(buffer[ii * 2], - buffer[ii * 2 + 1], &_channels[i]->_feedbuf[2], _channels[i]->_feedbuf); - } - - for (int i = 0; i < _numSSG ; i++) { - if (_ssgChannels[i]->_updateEnvelopes) { - _ssgChannels[i]->_updateEnvelopes = false; - _ssgChannels[i]->updateEnv(); - } - - for (uint32 ii = 0; ii < bufferSize ; ii++) - _ssgChannels[i]->generateOutput(buffer[ii * 2], - buffer[ii * 2 + 1], &_ssgChannels[i]->_feedbuf[2], _ssgChannels[i]->_feedbuf); + buffer[ii * 2 + 1], &_channels[i]->_feedbuf[2], _channels[i]->_feedbuf); } } @@ -2641,7 +3264,7 @@ void TownsPC98_OpnDriver::generateTables() { delete [] _oprFrq; _oprFrq = new uint32[0x1000]; for (uint32 i = 0; i < 0x1000; i++) - _oprFrq[i] = (uint32)(_baserate * (double)(i << 11)); + _oprFrq[i] = (uint32)(_baserate * (float)(i << 11)); delete [] _oprAttackDecay; _oprAttackDecay = new uint8[152]; @@ -2680,17 +3303,29 @@ void TownsPC98_OpnDriver::generateTables() { delete [] _oprDetune; _oprDetune = new int32[256]; for (int i = 0; i < 128; i++) { - _oprDetune[i] = (int32) ((double)dtt[i] * _baserate * 64.0); + _oprDetune[i] = (int32) ((float)dtt[i] * _baserate * 64.0); _oprDetune[i + 128] = -_oprDetune[i]; } delete [] dtt; } +void TownsPC98_OpnDriver::startSoundEffect() { + for (int i = 0; i < 2; i++) { + if (_sfxOffsets[i]) { + _ssgChannels[i + 1]->protect(); + _sfxChannels[i]->reset(); + _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]); + } + } + + _sfxData = 0; +} + void TownsPC98_OpnDriver::setTempo(uint8 tempo) { - _tempo = tempo; - _samplesPerCallback = getRate() / _tempo; - _samplesPerCallbackRemainder = getRate() % _tempo; + _tempo = tempo - 0x10; + _samplesPerCallback = _tempo ? (getRate() / _tempo) : 0; + _samplesPerCallbackRemainder = _tempo ? (getRate() % _tempo) : 0; } const uint8 TownsPC98_OpnDriver::_drvTables[] = { @@ -2742,7 +3377,47 @@ const uint8 TownsPC98_OpnDriver::_drvTables[] = { // pc98 level presets 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, - 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90 + 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90, + + // ssg frequencies + 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C, + 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09, + 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07, + + // ssg patch data + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00, + 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + + 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00, + 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00 }; const uint32 TownsPC98_OpnDriver::_adtStat[] = { @@ -2757,6 +3432,15 @@ const uint32 TownsPC98_OpnDriver::_adtStat[] = { 0x08080808, 0x08080808, 0x10101010, 0x10101010 }; +const int TownsPC98_OpnDriver::_ssgTables[] = { + 0x01202A, 0x0092D2, 0x006B42, 0x0053CB, 0x003DF8, 0x003053, 0x0022DA, 0x001A8C, + 0x00129B, 0x000DC1, 0x000963, 0x0006C9, 0x000463, 0x0002FA, 0x0001B6, 0x0000FB, + 0x0193B6, 0x01202A, 0x00CDB1, 0x0092D2, 0x007D7D, 0x006B42, 0x005ECD, 0x0053CB, + 0x00480F, 0x003DF8, 0x0036B9, 0x003053, 0x00290A, 0x0022DA, 0x001E6B, 0x001A8C, + 0x001639, 0x00129B, 0x000FFF, 0x000DC1, 0x000B5D, 0x000963, 0x0007FB, 0x0006C9, + 0x000575, 0x000463, 0x00039D, 0x0002FA, 0x000242, 0x0001B6, 0x00014C, 0x0000FB +}; + SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _sfxBTTable(0), _parser(0) { @@ -2916,7 +3600,8 @@ void SoundTowns::playSoundEffect(uint8 track) { } playbackBufferSize -= 0x20; - uint32 outputRate = uint32(11025 * semitoneAndSampleRate_to_sampleStep(note, sfxRootNoteOffs, sfxRate, 11025, 0x2000)); + + uint32 outputRate = uint32(11025 * calculatePhaseStep(note, sfxRootNoteOffs, sfxRate, 11025, 0x2000)); _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize, outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0); @@ -2995,7 +3680,7 @@ void SoundTowns::onTimer(void *data) { music->_parser->onTimer(); } -float SoundTowns::semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey, +float SoundTowns::calculatePhaseStep(int8 semiTone, int8 semiToneRootkey, uint32 sampleRate, uint32 outputRate, int32 pitchWheel) { if (semiTone < 0) semiTone = 0; @@ -3054,14 +3739,14 @@ void SoundPC98::playTrack(uint8 track) { if (track == _lastTrack && _musicEnabled) return; - haltTrack(); + beginFadeOut(); char musicfile[13]; sprintf(musicfile, fileListEntry(0), track); delete[] _musicTrackData; _musicTrackData = _vm->resource()->fileData(musicfile, 0); if (_musicEnabled) - _driver->loadData(_musicTrackData); + _driver->loadMusicData(_musicTrackData); _lastTrack = track; } @@ -3078,25 +3763,32 @@ void SoundPC98::beginFadeOut() { haltTrack(); } -void SoundPC98::playSoundEffect(uint8) { - /// TODO /// +void SoundPC98::playSoundEffect(uint8 track) { + if (!_sfxTrackData) + return; + + // This has been disabled for now since I don't know + // how to make up the correct track number. It probably + // needs a map. + //_driver->loadSoundEffectData(_sfxTrackData, track); } // KYRA 2 SoundTownsPC98_v2::SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) : - Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false) { + Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false) { } SoundTownsPC98_v2::~SoundTownsPC98_v2() { delete[] _musicTrackData; + delete[] _sfxTrackData; delete _driver; } bool SoundTownsPC98_v2::init() { - _driver = new TownsPC98_OpnDriver(_mixer, /*_vm->gameFlags().platform == Common::kPlatformPC98 ? - TownsPC98_OpnDriver::OD_TYPE86 :*/ TownsPC98_OpnDriver::OD_TOWNS); + _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ? + TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS); _useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false; _vm->checkCD(); // FIXME: While checking for 'track1.XXX(X)' looks like @@ -3110,9 +3802,15 @@ bool SoundTownsPC98_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; + return _driver->init(); } +void SoundTownsPC98_v2::loadSoundFile(Common::String file) { + delete [] _sfxTrackData; + _sfxTrackData = _vm->resource()->fileData(file.c_str(), 0); +} + void SoundTownsPC98_v2::process() { AudioCD.updateCD(); } @@ -3140,7 +3838,7 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { delete[] _musicTrackData; _musicTrackData = _vm->resource()->fileData(musicfile, 0); - _driver->loadData(_musicTrackData, true); + _driver->loadMusicData(_musicTrackData, true); if (_musicEnabled == 2 && trackNum != -1) { AudioCD.play(trackNum+1, _driver->looping() ? -1 : 1, 0, 0); @@ -3221,7 +3919,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) { sfx[i] = cmd; } - uint32 outputRate = uint32(11025 * SoundTowns::semitoneAndSampleRate_to_sampleStep(0x3c, 0x3c, sfxRate, 11025, 0x2000)); + uint32 outputRate = uint32(11025 * SoundTowns::calculatePhaseStep(0x3c, 0x3c, sfxRate, 11025, 0x2000)); _currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0); @@ -3233,18 +3931,12 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) { } void SoundTownsPC98_v2::playSoundEffect(uint8 track) { - if (!_useFmSfx) + if (!_useFmSfx || !_sfxTrackData) return; - - uint8 *sd = _vm->resource()->fileData("sound.dat", 0); - - - //TODO - - delete [] sd; + + _driver->loadSoundEffectData(_sfxTrackData, track); } } // end of namespace Kyra #undef EUPHONY_FADEOUT_TICKS - -- cgit v1.2.3 From 193f52906c617f7b0305e18f34e632bb256e4c8f Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 16 Aug 2008 14:25:03 +0000 Subject: KYRA: Fm-Towns Audio: fixed music fading svn-id: r33942 --- engines/kyra/sound_towns.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index d4c6afa4f6..9ae012b9c4 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1631,7 +1631,7 @@ protected: bool _sfxPlaying; bool _fading; uint8 _looping; - uint32 _tickCounter; + uint32 _musicTickCounter; bool _updateEnvelopeParameters; @@ -2662,7 +2662,7 @@ bool TownsPC98_OpnChannelPCM::processControlEvent(uint8 cmd) { } void TownsPC98_OpnChannelPCM::fadeStep() { - + // TODO (emulation not implemented anyway) } bool TownsPC98_OpnChannelPCM::control_f1_pcmStart(uint8 para) { @@ -2878,7 +2878,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), _opnFreqTableSSG(_drvTables + 252), _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 228)), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), - _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _cbCounter(4), _tickCounter(0), + _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _cbCounter(4), _musicTickCounter(0), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _updateSSGFlag(type == OD_TOWNS ? 0 : 7), _updatePCMFlag(type == OD_TYPE86 ? 1 : 0), _finishedChannelsFlag(0), _finishedSSGFlag(0), _finishedPCMFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), @@ -3132,7 +3132,7 @@ void TownsPC98_OpnDriver::reset() { _musicPlaying = _sfxPlaying = _fading = false; _looping = 0; - _tickCounter = 0; + _musicTickCounter = 0; _sfxData = 0; unlock(); @@ -3147,20 +3147,22 @@ void TownsPC98_OpnDriver::fadeOut() { _fading = true; - uint32 dTime = _tickCounter + 2; + uint32 dTime = _musicTickCounter + 2; for (int j = 0; j < _numChan; j++) { if (_updateChannelsFlag & _channels[j]->_idFlag) _channels[j]->fadeStep(); } for (int j = 0; j < _numSSG; j++) { - if (_updateSSGFlag & _channels[j]->_idFlag) + if (_updateSSGFlag & _ssgChannels[j]->_idFlag) _ssgChannels[j]->fadeStep(); } + if (_updatePCMFlag & _pcmChannel->_idFlag) + _pcmChannel->fadeStep(); unlock(); while (_musicPlaying) { - if (_tickCounter >= dTime) + if (_musicTickCounter >= dTime) break; } } @@ -3171,8 +3173,6 @@ void TownsPC98_OpnDriver::fadeOut() { void TownsPC98_OpnDriver::callback() { lock(); - _tickCounter++; - if (_sfxChannels && _sfxPlaying) { if (_sfxData) startSoundEffect(); @@ -3192,6 +3192,7 @@ void TownsPC98_OpnDriver::callback() { if (!--_cbCounter && _musicPlaying) { _cbCounter = 4; + _musicTickCounter++; for (int i = 0; i < _numChan; i++) { if (_updateChannelsFlag & _channels[i]->_idFlag) { -- cgit v1.2.3 From cc80af14485304b97f0b329438fcf89c427d8bfb Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 16 Aug 2008 15:24:52 +0000 Subject: KYRA: Fm-Towns Audio: fixed crash svn-id: r33943 --- engines/kyra/sound_towns.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 9ae012b9c4..df7dab714a 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -3156,8 +3156,10 @@ void TownsPC98_OpnDriver::fadeOut() { if (_updateSSGFlag & _ssgChannels[j]->_idFlag) _ssgChannels[j]->fadeStep(); } - if (_updatePCMFlag & _pcmChannel->_idFlag) - _pcmChannel->fadeStep(); + if (_hasPCM) { + if (_updatePCMFlag & _pcmChannel->_idFlag) + _pcmChannel->fadeStep(); + } unlock(); -- cgit v1.2.3 From 08b4cf127bf2b810fbe284ea4f424ca342b27c6b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 16 Aug 2008 21:51:56 +0000 Subject: Cleanup. svn-id: r33948 --- engines/kyra/screen.cpp | 9 +++------ engines/kyra/screen.h | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 0cde066cc0..68faaf6177 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -554,19 +554,16 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag copyOverlayRegion(x1, y1, x2, y2, w, h, srcPage, dstPage); - if (flags & CR_X_FLIPPED) { + if (flags & CR_NO_P_CHECK) { while (h--) { - for (int i = 0; i < w; ++i) { - if (src[i] || (flags & CR_NO_P_CHECK)) - dst[w-i] = src[i]; - } + memcpy(dst, src, w); src += SCREEN_W; dst += SCREEN_W; } } else { while (h--) { for (int i = 0; i < w; ++i) { - if (src[i] || (flags & CR_NO_P_CHECK)) + if (src[i]) dst[i] = src[i]; } src += SCREEN_W; diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 99ba2d7c5f..8623856878 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -74,8 +74,7 @@ public: }; enum CopyRegionFlags { - CR_X_FLIPPED = 0x01, - CR_NO_P_CHECK = 0x02 + CR_NO_P_CHECK = 0x01 }; enum DrawShapeFlags { -- cgit v1.2.3 From 87164b6c059ca4bb3ddd4d2257a9e53685b0f364 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 17 Aug 2008 22:49:34 +0000 Subject: KYRA: FM-Towns/PC-98 Audio: - improved accuracy - complete percussion channel support (does not work atm though, since the instrument data is missing) - some cleanup svn-id: r33980 --- engines/kyra/sound_towns.cpp | 488 ++++++++++++++++++++++++++++--------------- 1 file changed, 319 insertions(+), 169 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index df7dab714a..dd65fa644f 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -23,7 +23,6 @@ * */ - #include "common/system.h" #include "kyra/resource.h" #include "kyra/sound.h" @@ -1085,7 +1084,7 @@ void Towns_EuphonyTrackQueue::initDriver() { class TownsPC98_OpnOperator { public: - TownsPC98_OpnOperator(float rate, const uint8 *rateTable, + TownsPC98_OpnOperator(const float rate, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable); ~TownsPC98_OpnOperator() {} @@ -1095,7 +1094,7 @@ public: void frequency(int freq); void updatePhaseIncrement(); void recalculateRates(); - void generateOutput(int phasebuf, int *feedbuf, int &out); + void generateOutput(int32 phasebuf, int32 *feedbuf, int32 &out); void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; } void detune(int value) { _detn = &_detnTbl[value << 5]; } @@ -1147,14 +1146,14 @@ protected: } fs_a, fs_d, fs_s, fs_r; }; -TownsPC98_OpnOperator::TownsPC98_OpnOperator(float rate, const uint8 *rateTable, +TownsPC98_OpnOperator::TownsPC98_OpnOperator(const float rate, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) : _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength((int)(rate * 65536.0f)), _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), _phase(0), _state(s_ready) { - + reset(); } @@ -1205,7 +1204,7 @@ void TownsPC98_OpnOperator::recalculateRates() { fs_r.shift = _rshiftTbl[r + k]; } -void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feed, int &out) { +void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &out) { if (_state == s_ready) return; @@ -1273,7 +1272,7 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feed, int &out) { *o = *i; } else { phaseShift = phasebuf << 15; - } + } if (lvlout < 832) { uint32 index = (lvlout << 3) + _sinTbl[(((int32)((_phase & 0xffff0000) @@ -1285,10 +1284,6 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feed, int &out) { _phase += _phaseIncrement; out += *o; - if (out > 32767) - out = 32767; - if (out < -32767) - out = -32767; } void TownsPC98_OpnOperator::reset(){ @@ -1306,7 +1301,7 @@ void TownsPC98_OpnOperator::reset(){ decayRate(0); releaseRate(0); sustainRate(0); - feedbackLevel(0); + feedbackLevel(0); totalLevel(127); } @@ -1346,17 +1341,17 @@ public: virtual void processEvents(); virtual void processFrequency(); virtual bool processControlEvent(uint8 cmd); - void writeReg(uint8 regAdress, uint8 value); + void writeReg(uint8 regAddress, uint8 value); virtual void keyOn(); - void keyOff(); - + void keyOff(); + void setOutputLevel(); - void fadeStep(); - void reset(); + virtual void fadeStep(); + virtual void reset(); void updateEnv(); - void generateOutput(int16 &leftSample, int16 &rightSample, int *del, int *feed); + void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed); bool _enableLeft; bool _enableRight; @@ -1460,7 +1455,7 @@ protected: class TownsPC98_OpnSfxChannel : public TownsPC98_OpnChannelSSG { public: TownsPC98_OpnSfxChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, - uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : + uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : TownsPC98_OpnChannelSSG(driver, regOffs, flgs, num, key, prt, id) {} ~TownsPC98_OpnSfxChannel() {} @@ -1478,7 +1473,7 @@ public: void processEvents(); bool processControlEvent(uint8 cmd); - void fadeStep(); + void reset(); private: bool control_f1_pcmStart(uint8 para); @@ -1488,25 +1483,20 @@ private: const ControlEventFunc *controlEvents; }; -class TownsPC98_SSG : public Audio::AudioStream { +class TownsPC98_OpnSquareSineSource { public: - TownsPC98_SSG(TownsPC98_OpnDriver *driver, Audio::Mixer *mixer, float rate); - ~TownsPC98_SSG(); + TownsPC98_OpnSquareSineSource(const float rate); + ~TownsPC98_OpnSquareSineSource(); - void init(const int *rsTable, const int *rseTable); + void init(const int *rsTable, const int *rseTable); void reset(); uint8 readReg(uint8 address); void writeReg(uint8 address, uint8 value, bool force = false); - // AudioStream interface - int inline readBuffer(int16 *buffer, const int numSamples); - bool isStereo() const { return true; } - bool endOfData() const { return false; } - int getRate() const { return _mixer->getOutputRate(); } + void nextTick(int32 *buffer, uint32 bufferSize); private: void updatesRegs(); - void nextTick(int16 *buffer, uint32 bufferSize); uint8 _reg[16]; uint8 _updateRequestBuf[32]; @@ -1517,12 +1507,12 @@ private: int8 _evpTimer; uint32 _pReslt; uint8 _attack; - + bool _evpUpdate, _cont; int _evpUpdateCnt; - uint8 _outN; - int _nTick; + uint8 _outN; + int _nTick; int32 *_tlTable; int32 *_tleTable; @@ -1537,10 +1527,44 @@ private: uint8 out; } _channels[3]; - TownsPC98_OpnDriver *_drv; - Audio::Mixer *_mixer; - Audio::SoundHandle _soundHandle; + bool _ready; +}; + +class TownsPC98_OpnPercussionSource { +public: + TownsPC98_OpnPercussionSource(const float rate); + ~TownsPC98_OpnPercussionSource(); + + void init(uint8 *pcmData); + void reset(); + void writeReg(uint8 address, uint8 value); + + void nextTick(int32 *buffer, uint32 bufferSize); + +private: + void recalcLevel(int instrument); + + struct Pcm_Instrument { + const int16 *data; + + const int16 *start; + const int16 *end; + const int16 *pos; + uint32 size; + bool active; + uint8 level; + int out; + }; + + Pcm_Instrument _pcmInstr[6]; + uint8 _regs[48]; + uint8 *_rsamples; + + uint8 _totalLevel; + + const int _tickLength; + int _timer; bool _ready; }; @@ -1559,17 +1583,18 @@ public: TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type); ~TownsPC98_OpnDriver(); - bool init(); + bool init(uint8 *pcmData = 0); + void loadMusicData(uint8 *data, bool loadPaused = false); void loadSoundEffectData(uint8 *data, uint8 trackNum); void reset(); void fadeOut(); - + void pause() { _musicPlaying = false; } void cont() { _musicPlaying = true; } void callback(); - void nextTick(int16 *buffer, uint32 bufferSize); + void nextTick(int32 *buffer, uint32 bufferSize); bool looping() { return _looping == _updateChannelsFlag ? true : false; } @@ -1586,9 +1611,11 @@ protected: TownsPC98_OpnChannelSSG **_ssgChannels; TownsPC98_OpnSfxChannel **_sfxChannels; TownsPC98_OpnChannelPCM *_pcmChannel; - TownsPC98_SSG *_ssg; - void startSoundEffect(); + TownsPC98_OpnSquareSineSource *_ssg; + TownsPC98_OpnPercussionSource *_pcm; + + void startSoundEffect(); void setTempo(uint8 tempo); void lock() { _mutex.lock(); } @@ -1613,7 +1640,7 @@ protected: int32 *_oprDetune; uint8 *_musicBuffer; - uint8 *_sfxBuffer; + uint8 *_sfxBuffer; uint8 *_trackPtr; uint8 *_patches; uint8 *_ssgPatches; @@ -1668,7 +1695,7 @@ TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 re _frqLSB = 0; _hold = _updateEnvelopeParameters = false; _enableLeft = _enableRight = true; - _dataPtr = 0; + _dataPtr = 0; _ptchWhlModInitVal = _ptchWhlModCurVal = 0; _frequency = _frqTemp = 0; memset(&_feedbuf, 0, sizeof(int) * 3); @@ -1683,7 +1710,7 @@ TownsPC98_OpnChannel::~TownsPC98_OpnChannel() { } } -void TownsPC98_OpnChannel::init() { +void TownsPC98_OpnChannel::init() { _opr = new TownsPC98_OpnOperator*[4]; for (int i = 0; i < 4; i++) _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift, @@ -1716,16 +1743,16 @@ void TownsPC98_OpnChannel::init() { void TownsPC98_OpnChannel::keyOff() { // all operators off uint8 value = _keyNum & 0x0f; - uint8 regAdress = 0x28; - writeReg(regAdress, value); + uint8 regAddress = 0x28; + writeReg(regAddress, value); _flags |= CHS_KEYOFF; } void TownsPC98_OpnChannel::keyOn() { // all operators on uint8 value = _keyNum | 0xf0; - uint8 regAdress = 0x28; - writeReg(regAdress, value); + uint8 regAddress = 0x28; + writeReg(regAddress, value); } void TownsPC98_OpnChannel::loadData(uint8 *data) { @@ -1799,7 +1826,7 @@ void TownsPC98_OpnChannel::processEvents() { if (_hold == false || cmd != _frqBlockMSB) _flags |= CHS_RECALCFREQ; - + _hold = (para & 0x80) ? true : false; _frqBlockMSB = cmd; } @@ -1849,7 +1876,7 @@ bool TownsPC98_OpnChannel::processPitchWheel() { _ptchWhlDurLeft = _ptchWhlDuration; _ptchWhlModCurVal = -_ptchWhlModCurVal; } - + return true; } @@ -1893,6 +1920,7 @@ void TownsPC98_OpnChannel::reset() { _ssgStep = 0; _ssgTicksLeft = 0; _totalLevel = 0; + _flags |= CHS_EOT; _updateEnvelopeParameters = false; _enableLeft = _enableRight = true; @@ -1904,10 +1932,10 @@ void TownsPC98_OpnChannel::updateEnv() { _opr[i]->updatePhaseIncrement(); } -void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, int *del, int *feed) { +void TownsPC98_OpnChannel::generateOutput(int32 &leftSample, int32 &rightSample, int *del, int *feed) { int phbuf1, phbuf2, output; phbuf1 = phbuf2 = output = 0; - + switch (_algorithm) { case 0: _opr[0]->generateOutput(0, feed, phbuf1); @@ -1919,7 +1947,7 @@ void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, case 1: _opr[0]->generateOutput(0, feed, phbuf1); _opr[2]->generateOutput(*del, 0, phbuf2); - _opr[1]->generateOutput(0, 0, phbuf1); + _opr[1]->generateOutput(0, 0, phbuf1); _opr[3]->generateOutput(phbuf2, 0, output); *del = phbuf1; break; @@ -1940,7 +1968,7 @@ void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, case 4: _opr[0]->generateOutput(0, feed, phbuf1); _opr[2]->generateOutput(0, 0, phbuf2); - _opr[1]->generateOutput(phbuf1, 0, output); + _opr[1]->generateOutput(phbuf1, 0, output); _opr[3]->generateOutput(phbuf2, 0, output); *del = 0; break; @@ -1967,31 +1995,21 @@ void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, break; }; - if (_enableLeft) { - int l = output + (int) leftSample; - if (l > 32767) - l = 32767; - if (l < -32767) - l = -32767; - leftSample = (int16) l; - } + int32 finOut = ((output * 7) / 2); - if (_enableRight) { - int r = output + (int) rightSample; - if (r > 32767) - r = 32767; - if (r < -32767) - r = -32767; - rightSample = (int16) r; - } + if (_enableLeft) + leftSample += finOut; + + if (_enableRight) + rightSample += finOut; } -void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { +void TownsPC98_OpnChannel::writeReg(uint8 regAddress, uint8 value) { if (_drv->_regProtectionFlag) return; - uint8 h = regAdress & 0xf0; - uint8 l = (regAdress & 0x0f); + uint8 h = regAddress & 0xf0; + uint8 l = (regAddress & 0x0f); static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; uint8 o = oprOrdr[(l - _regOffset) >> 2]; @@ -1999,17 +2017,12 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { case 0x00: // ssg if (_drv->_ssg) - _drv->_ssg->writeReg(regAdress, value); + _drv->_ssg->writeReg(regAddress, value); break; case 0x10: // pcm rhythm channel - if (!(regAdress -= 0x10) && !(value & 0x80)) { - static const char *names[] = { "bass drum", "snare drum", "top cymbal", "high hat", "tom tom", "rim shot" }; - for (int i = 0; i < 6; i++) - if ((value >> i) & 1) - debugC(9, kDebugLevelMain | kDebugLevelSound, "TownsPC98_OpnDriver: TRYING TO USE UNSUPPORTED PCM INSTRUMENT: '%s'", names[i]); - } - + if (_drv->_pcm) + _drv->_pcm->writeReg(regAddress - 0x10, value); break; case 0x20: if (l == 8) { @@ -2076,7 +2089,7 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { break; case 0x90: - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress); break; case 0xa0: @@ -2120,7 +2133,7 @@ void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { break; default: - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress); break; } } @@ -2295,7 +2308,7 @@ bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) { } } -TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, +TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) { } @@ -2337,7 +2350,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { nextShape(); if (!--_ticksLeft) { - + uint8 cmd = 0; bool loop = true; @@ -2368,7 +2381,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { if (_hold == false || cmd != _frqBlockMSB) _flags |= CHS_RECALCFREQ; - + _hold = (para & 0x80) ? true : false; _frqBlockMSB = cmd; } @@ -2379,7 +2392,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { if (!(_flags & CHS_SSGOFF)) { if (--_ssgTicksLeft) { if (!_drv->_fading) - setOutputLevel(_ssgStartLvl); + setOutputLevel(_ssgStartLvl); return; } @@ -2390,7 +2403,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { if (_ssgStep <= _ssgStartLvl && _ssgTargetLvl < t) { if (!_drv->_fading) - setOutputLevel(t); + setOutputLevel(t); return; } } else { @@ -2435,7 +2448,7 @@ void TownsPC98_OpnChannelSSG::processFrequency() { if (!(_flags & (CHS_EOT | CHS_PITCHWHEELOFF | CHS_SSGOFF))) { if (!processPitchWheel()) return; - + processPitchWheel(); uint16 f = _frequency >> _block; @@ -2486,7 +2499,7 @@ void TownsPC98_OpnChannelSSG::restore() { } void TownsPC98_OpnChannelSSG::loadData(uint8 *data) { - _drv->_regProtectionFlag = (_flags & CHS_PROTECT) ? true : false; + _drv->_regProtectionFlag = (_flags & CHS_PROTECT) ? true : false; TownsPC98_OpnChannel::loadData(data); setOutputLevel(0); _algorithm = 0x80; @@ -2571,7 +2584,7 @@ bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) { } else { // stop parsing if (!_drv->_fading) - setOutputLevel(0); + setOutputLevel(0); --_dataPtr; _flags |= CHS_EOT; _drv->_finishedSSGFlag |= _idFlag; @@ -2581,7 +2594,7 @@ bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) { _flags |= CHS_EOT; _drv->_ssgChannels[_chanNum]->restore(); } - + return false; } @@ -2593,7 +2606,7 @@ void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { _algorithm = 0x80; } -TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, +TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) { } @@ -2661,8 +2674,11 @@ bool TownsPC98_OpnChannelPCM::processControlEvent(uint8 cmd) { return (this->*controlEvents[cmd & 0x0f])(para); } -void TownsPC98_OpnChannelPCM::fadeStep() { - // TODO (emulation not implemented anyway) +void TownsPC98_OpnChannelPCM::reset() { + TownsPC98_OpnChannel::reset(); + + if (_drv->_pcm) + _drv->_pcm->reset(); } bool TownsPC98_OpnChannelPCM::control_f1_pcmStart(uint8 para) { @@ -2686,21 +2702,19 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { } } -TownsPC98_SSG::TownsPC98_SSG(TownsPC98_OpnDriver *driver, Audio::Mixer *mixer, float rate) : _drv(driver), _mixer(mixer), _rate(rate), - _tlTable(0), _tleTable(0), _regIndex(_reg), _updateRequest(-1), _tickLength((int)(rate * 32768.0f * 27.0f)), _ready(0) { +TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const float rate) : _rate(rate), _tlTable(0), + _tleTable(0), _regIndex(_reg), _updateRequest(-1), _tickLength((int)(rate * 32768.0f * 27.0f)), _ready(0) { memset(_reg, 0, 16); memset(_channels, 0, sizeof(Channel) * 3); reset(); } -TownsPC98_SSG::~TownsPC98_SSG() { - _mixer->stopHandle(_soundHandle); - +TownsPC98_OpnSquareSineSource::~TownsPC98_OpnSquareSineSource() { delete [] _tlTable; delete [] _tleTable; } -void TownsPC98_SSG::init(const int *rsTable, const int *rseTable) { +void TownsPC98_OpnSquareSineSource::init(const int *rsTable, const int *rseTable) { if (_ready) { reset(); return; @@ -2732,13 +2746,13 @@ void TownsPC98_SSG::init(const int *rsTable, const int *rseTable) { _tleTable[i] = (int32) v; } - _mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); + //_mixer->playInputStream(Audio::Mixer::kMusicSoundType, + // &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); _ready = true; } -void TownsPC98_SSG::reset() { +void TownsPC98_OpnSquareSineSource::reset() { _rand = 1; _outN = 1; _updateRequest = -1; @@ -2762,16 +2776,16 @@ void TownsPC98_SSG::reset() { writeReg(7, 0xbf, true); } -uint8 TownsPC98_SSG::readReg(uint8 address) { +uint8 TownsPC98_OpnSquareSineSource::readReg(uint8 address) { return _reg[address]; } -void TownsPC98_SSG::writeReg(uint8 address, uint8 value, bool force) { +void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool force) { _regIndex = &_reg[address]; int o = _regIndex - _reg; if (!force && (o == 13 || *_regIndex != value)) { if (_updateRequest == 31) { - warning("TownsPC98_SSG: event buffer overflow"); + warning("TownsPC98_OpnSquareSineSource: event buffer overflow"); _updateRequest = -1; } _updateRequestBuf[++_updateRequest] = value; @@ -2782,16 +2796,153 @@ void TownsPC98_SSG::writeReg(uint8 address, uint8 value, bool force) { *_regIndex = value; } -void TownsPC98_SSG::updatesRegs() { +void TownsPC98_OpnSquareSineSource::updatesRegs() { for (int i = 0; i < _updateRequest;) { uint8 b = _updateRequestBuf[i++]; uint8 a = _updateRequestBuf[i++]; writeReg(a, b, true); } - _updateRequest = -1; + _updateRequest = -1; +} + +TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const float rate) : + _tickLength((int)(rate * 65536.0)), _rsamples(0), _timer(0), _ready(false) { + memset(_pcmInstr, 0, sizeof(Pcm_Instrument) * 6); } -void TownsPC98_SSG::nextTick(int16 *buffer, uint32 bufferSize) { +TownsPC98_OpnPercussionSource::~TownsPC98_OpnPercussionSource() { + delete [] _rsamples; +} + +void TownsPC98_OpnPercussionSource::init(uint8 *pcmData) { + if (_ready) { + reset(); + return; + } + + _rsamples = pcmData; + if (_rsamples) { + for (int i = 0; i < 6; i++) { + _pcmInstr[i].data = (const int16*) (_rsamples + READ_BE_UINT16(pcmData)); + pcmData += 2; + _pcmInstr[i].size = READ_BE_UINT16(pcmData) >> 1; + pcmData += 2; + } + + reset(); + + _ready = true; + } else { + memset(_pcmInstr, 0, sizeof(Pcm_Instrument) * 6); + _ready = false; + } +} + +void TownsPC98_OpnPercussionSource::reset() { + _timer = 0; + _totalLevel = 63; + + memset(_regs, 0, 48); + + for (int i = 0; i < 6; i++) { + Pcm_Instrument *s = &_pcmInstr[i]; + s->pos = s->start = s->data; + s->end = s->data + s->size; + s->active = false; + s->level = 0; + s->out = 0; + } +} + +void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) { + if (!_ready) + return; + + uint8 h = address >> 4; + uint8 l = address & 15; + + _regs[address] = value; + + if (address == 0) { + if (value & 0x80) { + //key off + for (int i = 0; i < 6; i++) { + if ((value >> i) & 1) + _pcmInstr[i].active = false; + } + } else { + //key on + for (int i = 0; i < 6; i++) { + if ((value >> i) & 1) { + _pcmInstr[i].pos = (const int16*) _pcmInstr[i].start; + _pcmInstr[i].active = true; + _pcmInstr[i].out = 0; + } + } + } + } else if (address == 1) { + // total level + _totalLevel = (value & 63) ^ 63; + for (int i = 0; i < 6; i++) + recalcLevel(i); + } else if (!h && l & 8) { + // instrument level + l &= 7; + _pcmInstr[l].level = (value & 0x1f) ^ 0x1f; + recalcLevel(l); + } else if (h & 3) { + l &= 7; + if (h == 1) { + // set start offset + _pcmInstr[l].start = _pcmInstr[l].data + ((_regs[24 + l] * 256 + _regs[16 + l]) << 8); + } else if (h == 2) { + // set end offset + _pcmInstr[l].end = _pcmInstr[l].data + ((_regs[40 + l] * 256 + _regs[32 + l]) << 8) + 255; + } + } +} + +void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { + if (!_ready) + return; + + for (uint32 i = 0; i < bufferSize; i++) { + _timer += _tickLength; + while (_timer > 0x30000) { + _timer -= 0x30000; + + for (int ii = 0; ii < 6; ii++) { + if (_pcmInstr[ii].active) { + recalcLevel(ii); + if (++_pcmInstr[ii].pos == _pcmInstr[ii].end) + _pcmInstr[ii].active = false; + } + } + } + + int32 finOut = 0; + + for (int ii = 0; ii < 6; ii++) { + if (_pcmInstr[ii].active) + finOut += _pcmInstr[ii].out; + } + + finOut = (finOut * 7); + + buffer[i << 1] += finOut; + buffer[(i << 1) + 1] += finOut; + } +} + +void TownsPC98_OpnPercussionSource::recalcLevel(int instrument) { + Pcm_Instrument *i = &_pcmInstr[instrument]; + uint32 s = _totalLevel + i->level; + uint32 x = s > 62 ? 0 : (1 + (s >> 3)); + int32 y = s > 62 ? 0 : (15 - (s & 7)); + i->out = (((int16)READ_LE_UINT16(i->pos) * y) >> x) & ~3; +} + +void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { if (!_ready) return; @@ -2834,45 +2985,20 @@ void TownsPC98_SSG::nextTick(int16 *buffer, uint32 bufferSize) { updatesRegs(); } - int16 t[3]; + int32 finOut = 0; for (int ii = 0; ii < 3; ii++) { if ((_reg[ii + 8] >> 4) & 1) - t[ii] = _tleTable[_channels[ii].out ? _pReslt : 0]; + finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; else - t[ii] = _tlTable[_channels[ii].out ? (_reg[ii + 8] & 0x0f) : 0]; + finOut += _tlTable[_channels[ii].out ? (_reg[ii + 8] & 0x0f) : 0]; } - int l = (int) buffer[i << 1]; - int r = (int) buffer[(i << 1) + 1]; - - for (int ii = 0; ii < 3; ii++) { - l += t[ii]; - r += t[ii]; - } - - l /= 2; - r /= 2; - - if (l > 32767) - l = 32767; - if (l < -32767) - l = -32767; - buffer[i << 1] = (int16)l; - - if (r > 32767) - r = 32767; - if (r < -32767) - r = -32767; - buffer[(i << 1) + 1] = (int16)r; + finOut /= 2; + buffer[i << 1] += finOut; + buffer[(i << 1) + 1] += finOut; } } -int TownsPC98_SSG::readBuffer(int16 *buffer, const int numSamples) { - memset(buffer, 0, sizeof(int16) * numSamples); - nextTick(buffer, numSamples >> 1); - return numSamples; -} - TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _mixer(mixer), _trackPtr(0), _musicPlaying(false), _sfxPlaying(false), _fading(false), _channels(0), _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _looping(0), _opnCarrier(_drvTables + 76), @@ -2884,7 +3010,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _finishedPCMFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), _sfxData(0), _ready(false), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPCM(type == OD_TYPE86 ? true : false), _sfxOffs(0), _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true), - _ssgPatches(0), _ssg(0), _baserate(55125.0f / (float)getRate()) { + _ssgPatches(0), _ssg(0), _pcm(0), _baserate(55125.0f / (float)getRate()) { setTempo(84); } @@ -2913,6 +3039,8 @@ TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { delete _pcmChannel; delete _ssg; + delete _pcm; + delete [] _oprRates; delete [] _oprRateshift; delete [] _oprFrq; @@ -2923,7 +3051,7 @@ TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { delete [] _ssgPatches; } -bool TownsPC98_OpnDriver::init() { +bool TownsPC98_OpnDriver::init(uint8 *pcmData) { if (_ready) { reset(); return true; @@ -2963,7 +3091,7 @@ bool TownsPC98_OpnDriver::init() { } if (_numSSG) { - _ssg = new TownsPC98_SSG(this, _mixer, _baserate); + _ssg = new TownsPC98_OpnSquareSineSource(_baserate); _ssg->init(&_ssgTables[0], &_ssgTables[16]); _ssgPatches = new uint8[256]; memcpy(_ssgPatches, _drvTables + 244, 256); @@ -2986,6 +3114,11 @@ bool TownsPC98_OpnDriver::init() { } if (_hasPCM) { + if (pcmData) { + _pcm = new TownsPC98_OpnPercussionSource(_baserate); + _pcm->init(pcmData); + } + delete _pcmChannel; _pcmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1); _pcmChannel->init(); @@ -3000,6 +3133,9 @@ bool TownsPC98_OpnDriver::init() { int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) { memset(buffer, 0, sizeof(int16) * numSamples); + int32 *tmp = new int32[numSamples]; + int32 *tmpStart = tmp; + memset(tmp, 0, sizeof(int32) * numSamples); int32 samplesLeft = numSamples >> 1; while (samplesLeft) { @@ -3018,17 +3154,22 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) samplesLeft -= render; _samplesTillCallback -= render; - nextTick(buffer, render); + nextTick(tmp, render); + + if (_ssg) + _ssg->nextTick(tmp, render); + if (_pcm) + _pcm->nextTick(tmp, render); for (int i = 0; i < render; ++i) { - int l = (int) (buffer[i << 1] * 7) / 2; + int32 l = tmp[i << 1]; if (l > 32767) l = 32767; if (l < -32767) l = -32767; buffer[i << 1] = (int16) l; - int r = (int) (buffer[(i << 1) + 1] * 7) / 2; + int32 r = tmp[(i << 1) + 1]; if (r > 32767) r = 32767; if (r < -32767) @@ -3037,8 +3178,10 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) } buffer += (render << 1); + tmp += (render << 1); } + delete [] tmpStart; return numSamples; } @@ -3056,7 +3199,7 @@ void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) { reset(); lock(); - + uint8 *src_a = _trackPtr = _musicBuffer = data; for (uint8 i = 0; i < 3; i++) { @@ -3121,7 +3264,7 @@ void TownsPC98_OpnDriver::reset() { _channels[i]->reset(); for (int i = 0; i < _numSSG; i++) _ssgChannels[i]->reset(); - + if (_ssg) { for (int i = 0; i < 2; i++) _sfxChannels[i]->reset(); @@ -3130,6 +3273,9 @@ void TownsPC98_OpnDriver::reset() { _ssg->reset(); } + if (_pcmChannel) + _pcmChannel->reset(); + _musicPlaying = _sfxPlaying = _fading = false; _looping = 0; _musicTickCounter = 0; @@ -3142,7 +3288,14 @@ void TownsPC98_OpnDriver::fadeOut() { if (!_musicPlaying) return; - for (int i = 0; i < 20; i++) { + if (_hasPCM) { + lock(); + if (_updatePCMFlag & _pcmChannel->_idFlag) + _pcmChannel->reset(); + unlock(); + } + + for (int i = 0; i < 20; i++) { lock(); _fading = true; @@ -3156,10 +3309,6 @@ void TownsPC98_OpnDriver::fadeOut() { if (_updateSSGFlag & _ssgChannels[j]->_idFlag) _ssgChannels[j]->fadeStep(); } - if (_hasPCM) { - if (_updatePCMFlag & _pcmChannel->_idFlag) - _pcmChannel->fadeStep(); - } unlock(); @@ -3225,16 +3374,16 @@ void TownsPC98_OpnDriver::callback() { unlock(); } -void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { +void TownsPC98_OpnDriver::nextTick(int32 *buffer, uint32 bufferSize) { if (!_ready) - return; + return; for (int i = 0; i < _numChan; i++) { if (_channels[i]->_updateEnvelopeParameters) { _channels[i]->_updateEnvelopeParameters = false; _channels[i]->updateEnv(); } - + for (uint32 ii = 0; ii < bufferSize ; ii++) _channels[i]->generateOutput(buffer[ii * 2], buffer[ii * 2 + 1], &_channels[i]->_feedbuf[2], _channels[i]->_feedbuf); @@ -3344,11 +3493,11 @@ const uint8 TownsPC98_OpnDriver::_drvTables[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, - // fmt level presets + // fmt level presets 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38, 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18, 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90, - + // carriers 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F, @@ -3377,7 +3526,7 @@ const uint8 TownsPC98_OpnDriver::_drvTables[] = { 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, 0x16, 0x16, 0x16, 0x16, - // pc98 level presets + // pc98 level presets 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90, @@ -3406,17 +3555,17 @@ const uint8 TownsPC98_OpnDriver::_drvTables[] = { 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00, 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - + 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00, 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, @@ -3738,7 +3887,7 @@ bool SoundPC98::init() { void SoundPC98::playTrack(uint8 track) { if (--track >= 56) track -= 55; - + if (track == _lastTrack && _musicEnabled) return; @@ -3773,7 +3922,7 @@ void SoundPC98::playSoundEffect(uint8 track) { // This has been disabled for now since I don't know // how to make up the correct track number. It probably // needs a map. - //_driver->loadSoundEffectData(_sfxTrackData, track); + // _driver->loadSoundEffectData(_sfxTrackData, track); } @@ -3839,7 +3988,7 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { char musicfile[13]; sprintf(musicfile, fileListEntry(0), track); delete[] _musicTrackData; - + _musicTrackData = _vm->resource()->fileData(musicfile, 0); _driver->loadMusicData(_musicTrackData, true); @@ -3936,10 +4085,11 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) { void SoundTownsPC98_v2::playSoundEffect(uint8 track) { if (!_useFmSfx || !_sfxTrackData) return; - + _driver->loadSoundEffectData(_sfxTrackData, track); } } // end of namespace Kyra #undef EUPHONY_FADEOUT_TICKS + -- cgit v1.2.3 From 92f545ba6624331f5d4a37ef9413097cb1d6ec30 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Mon, 18 Aug 2008 17:42:32 +0000 Subject: KYRA: FM-Towns/PC-98 Audio: - adpcm decoding for rhythm channel - cleanup svn-id: r33993 --- engines/kyra/sound_towns.cpp | 367 ++++++++++++++++++++++++------------------- 1 file changed, 201 insertions(+), 166 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index dd65fa644f..8678498855 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1535,31 +1535,35 @@ public: TownsPC98_OpnPercussionSource(const float rate); ~TownsPC98_OpnPercussionSource(); - void init(uint8 *pcmData); + void init(const void *pcmData = 0); void reset(); void writeReg(uint8 address, uint8 value); void nextTick(int32 *buffer, uint32 bufferSize); private: - void recalcLevel(int instrument); + struct PcmInstrument { + const uint8 *data; - struct Pcm_Instrument { - const int16 *data; - - const int16 *start; - const int16 *end; - const int16 *pos; + const uint8 *start; + const uint8 *end; + const uint8 *pos; uint32 size; - bool active; uint8 level; + + int8 decState; + uint8 decStep; + + int16 samples[2]; int out; }; - Pcm_Instrument _pcmInstr[6]; + void recalcOuput(PcmInstrument *ins); + void advanceInput(PcmInstrument *ins); + + PcmInstrument _pcmInstr[6]; uint8 _regs[48]; - uint8 *_rsamples; uint8 _totalLevel; @@ -1583,7 +1587,7 @@ public: TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type); ~TownsPC98_OpnDriver(); - bool init(uint8 *pcmData = 0); + bool init(); void loadMusicData(uint8 *data, bool loadPaused = false); void loadSoundEffectData(uint8 *data, uint8 trackNum); @@ -2239,11 +2243,12 @@ bool TownsPC98_OpnChannel::control_f8_togglePitchWheel(uint8 para) { _flags |= CHS_PITCHWHEELOFF; } } else { - //uint8 skipChannels = para / 36; - //uint8 entry = para % 36; - //TownsPC98_OpnDriver::TownsPC98_OpnChannel *t = &chan[skipChannels]; - ////// NOT IMPLEMENTED - //t->unnamedEntries[entry] = *_dataPtr++; + /* NOT IMPLEMENTED + uint8 skipChannels = para / 36; + uint8 entry = para % 36; + TownsPC98_OpnDriver::TownsPC98_OpnChannel *t = &chan[skipChannels]; + + t->unnamedEntries[entry] = *_dataPtr++;*/ } return true; } @@ -2746,9 +2751,6 @@ void TownsPC98_OpnSquareSineSource::init(const int *rsTable, const int *rseTable _tleTable[i] = (int32) v; } - //_mixer->playInputStream(Audio::Mixer::kMusicSoundType, - // &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); - _ready = true; } @@ -2806,34 +2808,33 @@ void TownsPC98_OpnSquareSineSource::updatesRegs() { } TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const float rate) : - _tickLength((int)(rate * 65536.0)), _rsamples(0), _timer(0), _ready(false) { - memset(_pcmInstr, 0, sizeof(Pcm_Instrument) * 6); + _tickLength((int)(rate * 65536.0)), _timer(0), _ready(false) { + memset(_pcmInstr, 0, sizeof(PcmInstrument) * 6); } TownsPC98_OpnPercussionSource::~TownsPC98_OpnPercussionSource() { - delete [] _rsamples; } -void TownsPC98_OpnPercussionSource::init(uint8 *pcmData) { +void TownsPC98_OpnPercussionSource::init(const void *pcmData) { if (_ready) { reset(); return; } - _rsamples = pcmData; - if (_rsamples) { + const uint8 *start = (const uint8*) pcmData; + const uint8 *pos = start; + + if (pcmData) { for (int i = 0; i < 6; i++) { - _pcmInstr[i].data = (const int16*) (_rsamples + READ_BE_UINT16(pcmData)); - pcmData += 2; - _pcmInstr[i].size = READ_BE_UINT16(pcmData) >> 1; - pcmData += 2; + _pcmInstr[i].data = start + READ_BE_UINT16(pos); + pos += 2; + _pcmInstr[i].size = READ_BE_UINT16(pos); + pos += 2; } - reset(); - _ready = true; } else { - memset(_pcmInstr, 0, sizeof(Pcm_Instrument) * 6); + memset(_pcmInstr, 0, sizeof(PcmInstrument) * 6); _ready = false; } } @@ -2845,12 +2846,15 @@ void TownsPC98_OpnPercussionSource::reset() { memset(_regs, 0, 48); for (int i = 0; i < 6; i++) { - Pcm_Instrument *s = &_pcmInstr[i]; + PcmInstrument *s = &_pcmInstr[i]; s->pos = s->start = s->data; s->end = s->data + s->size; s->active = false; s->level = 0; s->out = 0; + s->decStep = 1; + s->decState = 0; + s->samples[0] = s->samples[1] = 0; } } @@ -2874,9 +2878,13 @@ void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) { //key on for (int i = 0; i < 6; i++) { if ((value >> i) & 1) { - _pcmInstr[i].pos = (const int16*) _pcmInstr[i].start; - _pcmInstr[i].active = true; - _pcmInstr[i].out = 0; + PcmInstrument *s = &_pcmInstr[i]; + s->pos = s->start; + s->active = true; + s->out = 0; + s->samples[0] = s->samples[1] = 0; + s->decStep = 1; + s->decState = 0; } } } @@ -2884,12 +2892,12 @@ void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) { // total level _totalLevel = (value & 63) ^ 63; for (int i = 0; i < 6; i++) - recalcLevel(i); + recalcOuput(&_pcmInstr[i]); } else if (!h && l & 8) { // instrument level l &= 7; _pcmInstr[l].level = (value & 0x1f) ^ 0x1f; - recalcLevel(l); + recalcOuput(&_pcmInstr[l]); } else if (h & 3) { l &= 7; if (h == 1) { @@ -2912,10 +2920,15 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { _timer -= 0x30000; for (int ii = 0; ii < 6; ii++) { - if (_pcmInstr[ii].active) { - recalcLevel(ii); - if (++_pcmInstr[ii].pos == _pcmInstr[ii].end) - _pcmInstr[ii].active = false; + PcmInstrument *s = &_pcmInstr[ii]; + if (s->active) { + recalcOuput(s); + if (s->decStep) { + advanceInput(s); + if (s->pos == s->end) + s->active = false; + } + s->decStep ^= 1; } } } @@ -2934,12 +2947,34 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { } } -void TownsPC98_OpnPercussionSource::recalcLevel(int instrument) { - Pcm_Instrument *i = &_pcmInstr[instrument]; - uint32 s = _totalLevel + i->level; +void TownsPC98_OpnPercussionSource::recalcOuput(PcmInstrument *ins) { + uint32 s = _totalLevel + ins->level; uint32 x = s > 62 ? 0 : (1 + (s >> 3)); int32 y = s > 62 ? 0 : (15 - (s & 7)); - i->out = (((int16)READ_LE_UINT16(i->pos) * y) >> x) & ~3; + ins->out = ((ins->samples[ins->decStep] * y) >> x) & ~3; +} + +void TownsPC98_OpnPercussionSource::advanceInput(PcmInstrument *ins) { + static const int8 adjustIndex[] = {-1, -1, -1, -1, 2, 5, 7, 9 }; + + static const int16 stepTable[] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, + 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, + 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 + }; + + int d = ins->samples[1]; + uint8 cur = (int8) *ins->pos++; + + for (int i = 0; i < 2; i++) { + int b = (2 * (cur & 7) + 1) * stepTable[ins->decState] / 8; + if (cur & 8) + b = -b; + d += b; + d = CLIP(d, -2048, 2047); + ins->samples[i] = d; + ins->decState = CLIP(ins->decState + adjustIndex[cur & 7], 0, 48); + cur >>= 4; + } } void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { @@ -3051,7 +3086,7 @@ TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { delete [] _ssgPatches; } -bool TownsPC98_OpnDriver::init(uint8 *pcmData) { +bool TownsPC98_OpnDriver::init() { if (_ready) { reset(); return true; @@ -3114,10 +3149,8 @@ bool TownsPC98_OpnDriver::init(uint8 *pcmData) { } if (_hasPCM) { - if (pcmData) { - _pcm = new TownsPC98_OpnPercussionSource(_baserate); - _pcm->init(pcmData); - } + _pcm = new TownsPC98_OpnPercussionSource(_baserate); + _pcm->init(); delete _pcmChannel; _pcmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1); @@ -3480,119 +3513,6 @@ void TownsPC98_OpnDriver::setTempo(uint8 tempo) { _samplesPerCallbackRemainder = _tempo ? (getRate() % _tempo) : 0; } -const uint8 TownsPC98_OpnDriver::_drvTables[] = { - // channel presets - 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, - 0x01, 0x80, 0x01, 0x01, 0x00, 0x02, - 0x02, 0x80, 0x02, 0x02, 0x00, 0x04, - 0x00, 0x80, 0x03, 0x04, 0x01, 0x08, - 0x01, 0x80, 0x04, 0x05, 0x01, 0x10, - 0x02, 0x80, 0x05, 0x06, 0x01, 0x20, - - // control event size - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, - 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, - - // fmt level presets - 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38, - 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18, - 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90, - - // carriers - 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F, - - // frequencies - 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02, - 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03, - 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04, - 0x00, 0x00, 0x00, 0x00, - - // unused - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - - // detune - 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, - 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x10, 0x10, 0x10, 0x10, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, - 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, - 0x16, 0x16, 0x16, 0x16, - - // pc98 level presets - 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, - 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, - 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90, - - // ssg frequencies - 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C, - 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09, - 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07, - - // ssg patch data - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00, - 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - - 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00, - 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00 -}; - -const uint32 TownsPC98_OpnDriver::_adtStat[] = { - 0x00010001, 0x00010001, 0x00010001, 0x01010001, - 0x00010101, 0x00010101, 0x00010101, 0x01010101, - 0x01010101, 0x01010101, 0x01010102, 0x01010102, - 0x01020102, 0x01020102, 0x01020202, 0x01020202, - 0x02020202, 0x02020202, 0x02020204, 0x02020204, - 0x02040204, 0x02040204, 0x02040404, 0x02040404, - 0x04040404, 0x04040404, 0x04040408, 0x04040408, - 0x04080408, 0x04080408, 0x04080808, 0x04080808, - 0x08080808, 0x08080808, 0x10101010, 0x10101010 -}; - -const int TownsPC98_OpnDriver::_ssgTables[] = { - 0x01202A, 0x0092D2, 0x006B42, 0x0053CB, 0x003DF8, 0x003053, 0x0022DA, 0x001A8C, - 0x00129B, 0x000DC1, 0x000963, 0x0006C9, 0x000463, 0x0002FA, 0x0001B6, 0x0000FB, - 0x0193B6, 0x01202A, 0x00CDB1, 0x0092D2, 0x007D7D, 0x006B42, 0x005ECD, 0x0053CB, - 0x00480F, 0x003DF8, 0x0036B9, 0x003053, 0x00290A, 0x0022DA, 0x001E6B, 0x001A8C, - 0x001639, 0x00129B, 0x000FFF, 0x000DC1, 0x000B5D, 0x000963, 0x0007FB, 0x0006C9, - 0x000575, 0x000463, 0x00039D, 0x0002FA, 0x000242, 0x0001B6, 0x00014C, 0x0000FB -}; - SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _sfxBTTable(0), _parser(0) { @@ -3954,7 +3874,7 @@ bool SoundTownsPC98_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; - + return _driver->init(); } @@ -4089,6 +4009,121 @@ void SoundTownsPC98_v2::playSoundEffect(uint8 track) { _driver->loadSoundEffectData(_sfxTrackData, track); } +// static resources + +const uint8 TownsPC98_OpnDriver::_drvTables[] = { + // channel presets + 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x80, 0x01, 0x01, 0x00, 0x02, + 0x02, 0x80, 0x02, 0x02, 0x00, 0x04, + 0x00, 0x80, 0x03, 0x04, 0x01, 0x08, + 0x01, 0x80, 0x04, 0x05, 0x01, 0x10, + 0x02, 0x80, 0x05, 0x06, 0x01, 0x20, + + // control event size + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, + 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, + + // fmt level presets + 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38, + 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18, + 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90, + + // carriers + 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F, + + // frequencies + 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02, + 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03, + 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04, + 0x00, 0x00, 0x00, 0x00, + + // unused + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + + // detune + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, + 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x10, 0x10, 0x10, 0x10, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, + 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, + 0x16, 0x16, 0x16, 0x16, + + // pc98 level presets + 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, + 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, + 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90, + + // ssg frequencies + 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C, + 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09, + 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07, + + // ssg patch data + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00, + 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + + 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00, + 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00 +}; + +const uint32 TownsPC98_OpnDriver::_adtStat[] = { + 0x00010001, 0x00010001, 0x00010001, 0x01010001, + 0x00010101, 0x00010101, 0x00010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010102, 0x01010102, + 0x01020102, 0x01020102, 0x01020202, 0x01020202, + 0x02020202, 0x02020202, 0x02020204, 0x02020204, + 0x02040204, 0x02040204, 0x02040404, 0x02040404, + 0x04040404, 0x04040404, 0x04040408, 0x04040408, + 0x04080408, 0x04080408, 0x04080808, 0x04080808, + 0x08080808, 0x08080808, 0x10101010, 0x10101010 +}; + +const int TownsPC98_OpnDriver::_ssgTables[] = { + 0x01202A, 0x0092D2, 0x006B42, 0x0053CB, 0x003DF8, 0x003053, 0x0022DA, 0x001A8C, + 0x00129B, 0x000DC1, 0x000963, 0x0006C9, 0x000463, 0x0002FA, 0x0001B6, 0x0000FB, + 0x0193B6, 0x01202A, 0x00CDB1, 0x0092D2, 0x007D7D, 0x006B42, 0x005ECD, 0x0053CB, + 0x00480F, 0x003DF8, 0x0036B9, 0x003053, 0x00290A, 0x0022DA, 0x001E6B, 0x001A8C, + 0x001639, 0x00129B, 0x000FFF, 0x000DC1, 0x000B5D, 0x000963, 0x0007FB, 0x0006C9, + 0x000575, 0x000463, 0x00039D, 0x0002FA, 0x000242, 0x0001B6, 0x00014C, 0x0000FB +}; + } // end of namespace Kyra #undef EUPHONY_FADEOUT_TICKS -- cgit v1.2.3 From 95745179f5a37fe664a5ca76dc7cb40afc68e457 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Tue, 19 Aug 2008 01:00:15 +0000 Subject: fixed bug that caused a lockup in certain configurations when the music was fading svn-id: r34015 --- engines/kyra/sound_towns.cpp | 183 ++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 88 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 8678498855..5fce99f495 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1592,7 +1592,7 @@ public: void loadMusicData(uint8 *data, bool loadPaused = false); void loadSoundEffectData(uint8 *data, uint8 trackNum); void reset(); - void fadeOut(); + void fadeStep(); void pause() { _musicPlaying = false; } void cont() { _musicPlaying = true; } @@ -1601,6 +1601,7 @@ public: void nextTick(int32 *buffer, uint32 bufferSize); bool looping() { return _looping == _updateChannelsFlag ? true : false; } + bool musicPlaying() { return _musicPlaying; } // AudioStream interface int inline readBuffer(int16 *buffer, const int numSamples); @@ -1660,7 +1661,7 @@ protected: uint16 _tempo; bool _musicPlaying; bool _sfxPlaying; - bool _fading; + uint8 _fading; uint8 _looping; uint32 _musicTickCounter; @@ -2798,6 +2799,63 @@ void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool fo *_regIndex = value; } +void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { + if (!_ready) + return; + + for (uint32 i = 0; i < bufferSize; i++) { + _timer += _tickLength; + while (_timer > 0x30000) { + _timer -= 0x30000; + + if (++_nTick >= (_reg[6] & 0x1f)) { + if ((_rand + 1) & 2) + _outN ^= 1; + + _rand = (((_rand & 1) ^ ((_rand >> 3) & 1)) << 16) | (_rand >> 1); + _nTick = 0; + } + + for (int ii = 0; ii < 3; ii++) { + if (++_channels[ii].tick >= (((_reg[ii * 2 + 1] & 0x0f) << 8) | _reg[ii * 2])) { + _channels[ii].tick = 0; + _channels[ii].smp ^= 1; + } + _channels[ii].out = (_channels[ii].smp | ((_reg[7] >> ii) & 1)) & (_outN | ((_reg[7] >> (ii + 3)) & 1)); + } + + if (_evpUpdate) { + if (++_evpUpdateCnt >= ((_reg[12] << 8) | _reg[11])) { + _evpUpdateCnt = 0; + + if (--_evpTimer < 0) { + if (_cont) { + _evpTimer &= 0x1f; + } else { + _evpUpdate = false; + _evpTimer = 0; + } + } + } + } + _pReslt = _evpTimer ^ _attack; + updatesRegs(); + } + + int32 finOut = 0; + for (int ii = 0; ii < 3; ii++) { + if ((_reg[ii + 8] >> 4) & 1) + finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; + else + finOut += _tlTable[_channels[ii].out ? (_reg[ii + 8] & 0x0f) : 0]; + } + + finOut /= 2; + buffer[i << 1] += finOut; + buffer[(i << 1) + 1] += finOut; + } +} + void TownsPC98_OpnSquareSineSource::updatesRegs() { for (int i = 0; i < _updateRequest;) { uint8 b = _updateRequestBuf[i++]; @@ -2977,63 +3035,6 @@ void TownsPC98_OpnPercussionSource::advanceInput(PcmInstrument *ins) { } } -void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { - if (!_ready) - return; - - for (uint32 i = 0; i < bufferSize; i++) { - _timer += _tickLength; - while (_timer > 0x30000) { - _timer -= 0x30000; - - if (++_nTick >= (_reg[6] & 0x1f)) { - if ((_rand + 1) & 2) - _outN ^= 1; - - _rand = (((_rand & 1) ^ ((_rand >> 3) & 1)) << 16) | (_rand >> 1); - _nTick = 0; - } - - for (int ii = 0; ii < 3; ii++) { - if (++_channels[ii].tick >= (((_reg[ii * 2 + 1] & 0x0f) << 8) | _reg[ii * 2])) { - _channels[ii].tick = 0; - _channels[ii].smp ^= 1; - } - _channels[ii].out = (_channels[ii].smp | ((_reg[7] >> ii) & 1)) & (_outN | ((_reg[7] >> (ii + 3)) & 1)); - } - - if (_evpUpdate) { - if (++_evpUpdateCnt >= ((_reg[12] << 8) | _reg[11])) { - _evpUpdateCnt = 0; - - if (--_evpTimer < 0) { - if (_cont) { - _evpTimer &= 0x1f; - } else { - _evpUpdate = false; - _evpTimer = 0; - } - } - } - } - _pReslt = _evpTimer ^ _attack; - updatesRegs(); - } - - int32 finOut = 0; - for (int ii = 0; ii < 3; ii++) { - if ((_reg[ii + 8] >> 4) & 1) - finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; - else - finOut += _tlTable[_channels[ii].out ? (_reg[ii + 8] & 0x0f) : 0]; - } - - finOut /= 2; - buffer[i << 1] += finOut; - buffer[(i << 1) + 1] += finOut; - } -} - TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _mixer(mixer), _trackPtr(0), _musicPlaying(false), _sfxPlaying(false), _fading(false), _channels(0), _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _looping(0), _opnCarrier(_drvTables + 76), @@ -3317,41 +3318,34 @@ void TownsPC98_OpnDriver::reset() { unlock(); } -void TownsPC98_OpnDriver::fadeOut() { +void TownsPC98_OpnDriver::fadeStep() { if (!_musicPlaying) return; - if (_hasPCM) { - lock(); - if (_updatePCMFlag & _pcmChannel->_idFlag) - _pcmChannel->reset(); - unlock(); - } - - for (int i = 0; i < 20; i++) { - lock(); - - _fading = true; - - uint32 dTime = _musicTickCounter + 2; - for (int j = 0; j < _numChan; j++) { - if (_updateChannelsFlag & _channels[j]->_idFlag) - _channels[j]->fadeStep(); - } - for (int j = 0; j < _numSSG; j++) { - if (_updateSSGFlag & _ssgChannels[j]->_idFlag) - _ssgChannels[j]->fadeStep(); - } + lock(); - unlock(); + for (int j = 0; j < _numChan; j++) { + if (_updateChannelsFlag & _channels[j]->_idFlag) + _channels[j]->fadeStep(); + } + + for (int j = 0; j < _numSSG; j++) { + if (_updateSSGFlag & _ssgChannels[j]->_idFlag) + _ssgChannels[j]->fadeStep(); + } - while (_musicPlaying) { - if (_musicTickCounter >= dTime) - break; + if (!_fading) { + _fading = 19; + if (_hasPCM) { + if (_updatePCMFlag & _pcmChannel->_idFlag) + _pcmChannel->reset(); } + } else { + if (!--_fading) + reset(); } - reset(); + unlock(); } void TownsPC98_OpnDriver::callback() { @@ -3831,7 +3825,13 @@ void SoundPC98::haltTrack() { } void SoundPC98::beginFadeOut() { - _driver->fadeOut(); + if (!_driver->musicPlaying()) + return; + + for (int i = 0; i < 20; i++) { + _driver->fadeStep(); + _vm->delay(32); + } haltTrack(); } @@ -3930,7 +3930,14 @@ void SoundTownsPC98_v2::haltTrack() { } void SoundTownsPC98_v2::beginFadeOut() { - _driver->fadeOut(); + if (!_driver->musicPlaying()) + return; + + for (int i = 0; i < 20; i++) { + _driver->fadeStep(); + _vm->delay(32); + } + haltTrack(); } -- cgit v1.2.3 From cb5162fad687de4ebe76885652026dd017bd8300 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Tue, 19 Aug 2008 06:31:57 +0000 Subject: fixed warnings svn-id: r34019 --- engines/kyra/sound_towns.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 5fce99f495..bc5a3329c7 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -63,13 +63,13 @@ public: MidiDriver *device() { return 0; } byte getNumber() { return 0; } void release() { } - void send(uint32 b) { } + void send(uint32) { } void noteOff(byte note); void noteOn(byte note, byte onVelo); - void programChange(byte program) {} + void programChange(byte) {} void pitchBend(int16 value); void controlChange(byte control, byte value); - void pitchBendFactor(byte value) { } + void pitchBendFactor(byte) { } void sysEx_customInstrument(uint32 unused, const byte *instr); protected: @@ -818,7 +818,8 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { } } - while (true) { + bool loop = true; + while (loop) { byte cmd = *pos; byte evt = (cmd & 0xF0); @@ -852,7 +853,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { info.basic.param2 = onVelo; pos += 12; - break; + loop = false; } else { pos += 6; } @@ -869,7 +870,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { info.basic.param1 = pos[4]; info.basic.param2 = pos[5]; pos += 6; - break; + loop = false; } else { pos += 6; } @@ -888,7 +889,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { _tempo[2] = tempo & 0xff; info.ext.data = (byte*) _tempo; pos += 6; - break; + loop = false; } else if (cmd == 0xFD || cmd == 0xFE) { // End of track. if (_autoLoop) { @@ -905,12 +906,12 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { info.event = 0xFF; info.ext.type = 0x2F; info.ext.data = pos; - break; + loop = false; } else { error("Unknown Euphony music event 0x%02X", (int)cmd); memset(&info, 0, sizeof(info)); pos = 0; - break; + loop = false; } } _position._play_pos = pos; @@ -1259,8 +1260,8 @@ void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &o uint32 lvlout = _totalLevel + (uint32) _currentLevel; - int outp = 0; - int *i = &outp, *o = &outp; + int32 outp = 0; + int32 *i = &outp, *o = &outp; int phaseShift = 0; if (feed) { @@ -1937,8 +1938,8 @@ void TownsPC98_OpnChannel::updateEnv() { _opr[i]->updatePhaseIncrement(); } -void TownsPC98_OpnChannel::generateOutput(int32 &leftSample, int32 &rightSample, int *del, int *feed) { - int phbuf1, phbuf2, output; +void TownsPC98_OpnChannel::generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed) { + int32 phbuf1, phbuf2, output; phbuf1 = phbuf2 = output = 0; switch (_algorithm) { -- cgit v1.2.3 From 983e07ff6e452d1fcf83fa8f099d36a86d8d3f30 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Tue, 19 Aug 2008 09:26:41 +0000 Subject: Use the correct and specified datatype int32 instead of only int. svn-id: r34027 --- engines/kyra/sound_towns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index bc5a3329c7..355dfc724a 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1358,7 +1358,7 @@ public: bool _enableRight; bool _updateEnvelopeParameters; const uint8 _idFlag; - int _feedbuf[3]; + int32 _feedbuf[3]; protected: void setupPitchWheel(); -- cgit v1.2.3 From 05bac1e74e009bf6622394320dbf0da5321ba88b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 19 Aug 2008 10:52:39 +0000 Subject: Fixed GCC warning svn-id: r34032 --- engines/kyra/sound_towns.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 355dfc724a..dbe0469809 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -3311,7 +3311,9 @@ void TownsPC98_OpnDriver::reset() { if (_pcmChannel) _pcmChannel->reset(); - _musicPlaying = _sfxPlaying = _fading = false; + _musicPlaying = false; + _sfxPlaying = false; + _fading = false; _looping = 0; _musicTickCounter = 0; _sfxData = 0; -- cgit v1.2.3 From f4fc8c3e4c1621e8c40392881a6c647f9915fa38 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 20 Aug 2008 14:03:34 +0000 Subject: Committed patch #2050337 "KYRA/SCUMM: Thumbnail support/improvement". (Without Max' compressed backward seeking support for now) svn-id: r34053 --- engines/kyra/detection.cpp | 2 +- engines/kyra/gui.h | 4 ++++ engines/kyra/gui_hof.cpp | 8 +++++++- engines/kyra/gui_hof.h | 2 ++ engines/kyra/gui_lok.cpp | 19 +++++++++++++++++-- engines/kyra/gui_lok.h | 2 ++ engines/kyra/gui_mr.cpp | 8 +++++++- engines/kyra/gui_mr.h | 2 ++ engines/kyra/gui_v2.cpp | 7 ++++++- engines/kyra/kyra_hof.cpp | 2 +- engines/kyra/kyra_hof.h | 2 +- engines/kyra/kyra_lok.cpp | 4 ++-- engines/kyra/kyra_lok.h | 2 +- engines/kyra/kyra_mr.cpp | 2 +- engines/kyra/kyra_mr.h | 2 +- engines/kyra/kyra_v1.h | 6 ++++-- engines/kyra/kyra_v2.cpp | 2 +- engines/kyra/kyra_v2.h | 2 +- engines/kyra/saveload.cpp | 26 +++++++++++++++++++++----- engines/kyra/saveload_hof.cpp | 6 +++--- engines/kyra/saveload_lok.cpp | 6 +++--- engines/kyra/saveload_mr.cpp | 6 +++--- engines/kyra/screen_lok.cpp | 18 +++++++++++++++++- engines/kyra/screen_lok.h | 1 + engines/kyra/script_mr.cpp | 2 +- engines/kyra/timer_mr.cpp | 2 +- 26 files changed, 111 insertions(+), 34 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 0c6eb29665..d41ecb5e9b 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1117,7 +1117,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { - if (Kyra::KyraEngine_v1::readSaveHeader(in, header) == Kyra::KyraEngine_v1::kRSHENoError) + if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) saveList.push_back(SaveStateDescriptor(slotNum, header.description, *file)); delete in; } diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h index 1361bdb399..7db8f52f16 100644 --- a/engines/kyra/gui.h +++ b/engines/kyra/gui.h @@ -32,6 +32,8 @@ #include "common/array.h" #include "common/func.h" +#include "graphics/surface.h" + namespace Kyra { #define BUTTON_FUNCTOR(type, x, y) Button::Callback(new Common::Functor1Mem(x, y)) @@ -153,6 +155,8 @@ public: void processHighlights(Menu &menu, int mouseX, int mouseY); + // utilities for thumbnail creation + virtual void createScreenThumbnail(Graphics::Surface &dst) = 0; protected: KyraEngine_v1 *_vm; Screen *_screen; diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 7d56743af5..fb2aa24e1e 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -33,6 +33,8 @@ #include "common/savefile.h" +#include "graphics/scaler.h" + namespace Kyra { void KyraEngine_HoF::loadButtonShapes() { @@ -793,6 +795,10 @@ int GUI_HoF::optionsButton(Button *button) { #pragma mark - +void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) { + ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(1)); +} + void GUI_HoF::setupPalette() { memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); @@ -996,7 +1002,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) { if (_vm->_lang != lang) { _reloadTemporarySave = true; - _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 2 Savegame"); + _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 2 Savegame", 0); _vm->loadCCodeBuffer("C_CODE.XXX"); if (_vm->_flags.isTalkie) _vm->loadOptionsBuffer("OPTIONS.XXX"); diff --git a/engines/kyra/gui_hof.h b/engines/kyra/gui_hof.h index f64336a8f6..a9c0426a2b 100644 --- a/engines/kyra/gui_hof.h +++ b/engines/kyra/gui_hof.h @@ -41,6 +41,8 @@ public: void initStaticData(); int optionsButton(Button *button); + + void createScreenThumbnail(Graphics::Surface &dst); private: const char *getMenuTitle(const Menu &menu); const char *getMenuItemTitle(const MenuItem &menuItem); diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 47ce698e50..ca1c94e215 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -37,6 +37,8 @@ #include "common/events.h" #include "common/system.h" +#include "graphics/scaler.h" + namespace Kyra { void KyraEngine_LoK::initMainButtonList() { @@ -199,6 +201,15 @@ GUI_LoK::~GUI_LoK() { delete[] _menu; } +void GUI_LoK::createScreenThumbnail(Graphics::Surface &dst) { + uint8 *screen = new uint8[Screen::SCREEN_W*Screen::SCREEN_H]; + if (screen) { + _screen->queryPageFromDisk("SEENPAGE.TMP", 0, screen); + ::createThumbnail(&dst, screen, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(2)); + } + delete[] screen; +} + int GUI_LoK::processButtonList(Button *list, uint16 inputFlag, int8 mouseWheel) { while (list) { if (list->flags & 8) { @@ -736,8 +747,12 @@ int GUI_LoK::saveGame(Button *button) { } else { if (_savegameOffset == 0 && _vm->_gameToLoad == 0) _vm->_gameToLoad = getNextSavegameSlot(); - if (_vm->_gameToLoad > 0) - _vm->saveGame(_vm->getSavegameFilename(_vm->_gameToLoad), _savegameName); + if (_vm->_gameToLoad > 0) { + Graphics::Surface thumb; + createScreenThumbnail(thumb); + _vm->saveGame(_vm->getSavegameFilename(_vm->_gameToLoad), _savegameName, &thumb); + thumb.free(); + } } return 0; diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h index 16b7ef9183..0ce718d7a7 100644 --- a/engines/kyra/gui_lok.h +++ b/engines/kyra/gui_lok.h @@ -103,6 +103,8 @@ public: int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel); int buttonMenuCallback(Button *caller); + + void createScreenThumbnail(Graphics::Surface &dst); private: void initStaticResource(); diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 6822b303c3..7a84d7093a 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -33,6 +33,8 @@ #include "common/savefile.h" +#include "graphics/scaler.h" + namespace Kyra { void KyraEngine_MR::loadButtonShapes() { @@ -1138,6 +1140,10 @@ int KyraEngine_MR::albumClose(Button *caller) { GUI_MR::GUI_MR(KyraEngine_MR *vm) : GUI_v2(vm), _vm(vm), _screen(vm->_screen) { } +void GUI_MR::createScreenThumbnail(Graphics::Surface &dst) { + ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(0)); +} + void GUI_MR::flagButtonEnable(Button *button) { if (!button) return; @@ -1450,7 +1456,7 @@ int GUI_MR::gameOptions(Button *caller) { if (_vm->_lang != lang) { _reloadTemporarySave = true; - _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 3 Savegame"); + _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 3 Savegame", 0); if (!_vm->loadLanguageFile("ITEMS.", _vm->_itemFile)) error("Couldn't load ITEMS"); if (!_vm->loadLanguageFile("SCORE.", _vm->_scoreFile)) diff --git a/engines/kyra/gui_mr.h b/engines/kyra/gui_mr.h index 5bd3569031..a78d0559a6 100644 --- a/engines/kyra/gui_mr.h +++ b/engines/kyra/gui_mr.h @@ -47,6 +47,8 @@ public: int redrawButtonCallback(Button *button); int optionsButton(Button *button); + + void createScreenThumbnail(Graphics::Surface &dst); private: void getInput(); diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index e4cec760fa..e9d81f3b8a 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -618,7 +618,12 @@ int GUI_v2::saveMenu(Button *caller) { restorePage1(_vm->_screenBuffer); restorePalette(); - _vm->saveGame(_vm->getSavegameFilename(_saveSlot), _saveDescription); + + Graphics::Surface thumb; + createScreenThumbnail(thumb); + _vm->saveGame(_vm->getSavegameFilename(_saveSlot), _saveDescription, &thumb); + thumb.free(); + _displayMenu = false; _madeSave = true; diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 0271f5ea0d..2f8f2674e4 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -436,7 +436,7 @@ void KyraEngine_HoF::startup() { if (_gameToLoad == -1) { snd_playWanderScoreViaMap(52, 1); enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); - saveGame(getSavegameFilename(0), "New Game"); + saveGame(getSavegameFilename(0), "New Game", 0); } else { loadGame(getSavegameFilename(_gameToLoad)); } diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index f6e887c648..dc4161f0c1 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -907,7 +907,7 @@ protected: int _dbgPass; // save/load specific - void saveGame(const char *fileName, const char *saveName); + void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail); void loadGame(const char *fileName); }; diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index c852f6e3ee..3d228210b9 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -388,7 +388,7 @@ void KyraEngine_LoK::startup() { _gui->buttonMenuCallback(0); _menuDirectlyToLoad = false; } else - saveGame(getSavegameFilename(0), "New game"); + saveGame(getSavegameFilename(0), "New game", 0); } else { _screen->setFont(Screen::FID_8_FNT); loadGame(getSavegameFilename(_gameToLoad)); @@ -470,7 +470,7 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { else { char savegameName[14]; sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); - saveGame(saveLoadSlot, savegameName); + saveGame(saveLoadSlot, savegameName, 0); } } else if (event.kbd.flags == Common::KBD_CTRL) { if (event.kbd.keycode == 'd') diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index 1def95ddbf..e6fc0dc774 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -214,7 +214,7 @@ public: protected: int32 _speechPlayTime; - void saveGame(const char *fileName, const char *saveName); + void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail); void loadGame(const char *fileName); protected: diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index a61253199b..9b9549b778 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -684,7 +684,7 @@ void KyraEngine_MR::startup() { assert(_invWsa); _invWsa->open("MOODOMTR.WSA", 1, 0); _invWsaFrame = 6; - saveGame(getSavegameFilename(0), (const char*)getTableEntry(_optionsFile, 33)); + saveGame(getSavegameFilename(0), (const char*)getTableEntry(_optionsFile, 33), 0); _soundDigital->beginFadeOut(_musicSoundChannel, 60); delayWithTicks(60); if (_gameToLoad == -1) diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 5f9f6f91a3..a6fb9af20c 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -583,7 +583,7 @@ private: int albumClose(Button *caller); // save/load - void saveGame(const char *fileName, const char *saveName); + void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail); void loadGame(const char *fileName); // opcodes diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 738a3fc8ec..438d625503 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -290,6 +290,8 @@ protected: bool originalSave; // savegame from original interpreter bool oldHeader; // old scummvm save header + + Graphics::Surface *thumbnail; }; enum kReadSaveHeaderError { @@ -299,10 +301,10 @@ protected: kRSHEIoError = 3 }; - static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, SaveHeader &header); + static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header); Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header); - Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName) const; + Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const; }; } // End of namespace Kyra diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 2e704f2aa2..4e1bf38991 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -186,7 +186,7 @@ int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { } else { char savegameName[14]; sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); - saveGame(saveLoadSlot, savegameName); + saveGame(saveLoadSlot, savegameName, 0); } } else if (event.kbd.flags == Common::KBD_CTRL) { if (event.kbd.keycode == 'd') diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index 6fdf30fff8..e7f9634fc6 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -419,7 +419,7 @@ protected: int o2_getVocHigh(EMCState *script); // save/load specific - virtual void saveGame(const char *fileName, const char *saveName) = 0; + virtual void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) = 0; virtual void loadGame(const char *fileName) = 0; }; diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 31c5e15fa6..c08967c85c 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -26,10 +26,11 @@ #include "common/endian.h" #include "common/savefile.h" #include "common/system.h" +#include "graphics/thumbnail.h" #include "kyra/kyra_v1.h" -#define CURRENT_SAVE_VERSION 13 +#define CURRENT_SAVE_VERSION 14 #define GF_FLOPPY (1 << 0) #define GF_TALKIE (1 << 1) @@ -37,7 +38,7 @@ namespace Kyra { -KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header) { +KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) { uint32 type = in->readUint32BE(); header.originalSave = false; header.oldHeader = false; @@ -108,6 +109,16 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab if (header.version >= 2) header.flags = in->readUint32BE(); + if (header.version >= 14) { + if (loadThumbnail) { + header.thumbnail = new Graphics::Surface(); + assert(header.thumbnail); + Graphics::loadThumbnail(*in, *header.thumbnail); + } else { + Graphics::skipThumbnailHeader(*in); + } + } + return (in->ioFailed() ? kRSHEIoError : kRSHENoError); } @@ -118,7 +129,7 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena if (!(in = _saveFileMan->openForLoading(filename))) return 0; - kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, header); + kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header); if (errorCode != kRSHENoError) { if (errorCode == kRSHEInvalidType) warning("No ScummVM Kyra engine savefile header."); @@ -162,8 +173,8 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena return in; } -Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName) const { - debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s')", filename, saveName); +Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const { + debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s', %p)", filename, saveName, (const void *)thumbnail); if (_quitFlag) return 0; @@ -191,6 +202,11 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con return 0; } + if (thumbnail) + Graphics::saveThumbnail(*out, *thumbnail); + else + Graphics::saveThumbnail(*out); + return out; } diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp index 954cbccfa9..2b245f6167 100644 --- a/engines/kyra/saveload_hof.cpp +++ b/engines/kyra/saveload_hof.cpp @@ -35,10 +35,10 @@ namespace Kyra { -void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName) { - debugC(9, kDebugLevelMain, "KyraEngine_HoF::saveGame('%s', '%s')", fileName, saveName); +void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb); - Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); + Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); if (!out) { warning("Can't open file '%s', game not loadable", fileName); return; diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 8af73acc61..f734ffd5d9 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -218,13 +218,13 @@ void KyraEngine_LoK::loadGame(const char *fileName) { delete in; } -void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) { - debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s')", fileName, saveName); +void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb); if (_quitFlag) return; - Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); + Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); if (!out) return; diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp index 51efc33723..8849f99523 100644 --- a/engines/kyra/saveload_mr.cpp +++ b/engines/kyra/saveload_mr.cpp @@ -32,10 +32,10 @@ namespace Kyra { -void KyraEngine_MR::saveGame(const char *fileName, const char *saveName) { - debugC(9, kDebugLevelMain, "KyraEngine_MR::saveGame('%s', '%s')", fileName, saveName); +void KyraEngine_MR::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb); - Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); + Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); if (!out) { warning("Can't open file '%s', game not loadable", fileName); return; diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp index 011c90dde9..da88abc61f 100644 --- a/engines/kyra/screen_lok.cpp +++ b/engines/kyra/screen_lok.cpp @@ -147,8 +147,14 @@ void Screen_LoK::savePageToDisk(const char *file, int page) { void Screen_LoK::loadPageFromDisk(const char *file, int page) { debugC(9, kDebugLevelScreen, "Screen_LoK::loadPageFromDisk('%s', %d)", file, page); + if (!_saveLoadPage[page/2]) { + warning("trying to restore page %d, but no backup found", page); + return; + } + copyBlockToPage(page, 0, 0, SCREEN_W, SCREEN_H, _saveLoadPage[page/2]); delete[] _saveLoadPage[page/2]; + _saveLoadPage[page/2] = 0; if (_saveLoadPageOvl[page/2]) { uint8 *dstPage = getOverlayPtr(page); @@ -160,7 +166,17 @@ void Screen_LoK::loadPageFromDisk(const char *file, int page) { memcpy(dstPage, _saveLoadPageOvl[page/2], SCREEN_OVL_SJIS_SIZE); delete[] _saveLoadPageOvl[page/2]; _saveLoadPageOvl[page/2] = 0; - } _saveLoadPage[page/2] = 0; + } +} + +void Screen_LoK::queryPageFromDisk(const char *file, int page, uint8 *buffer) { + debugC(9, kDebugLevelScreen, "Screen_LoK::queryPageFromDisk('%s', %d, %p)", file, page, (const void *)buffer); + if (!_saveLoadPage[page/2]) { + warning("trying to query page %d, but no backup found", page); + return; + } + + memcpy(buffer, _saveLoadPage[page/2], SCREEN_W*SCREEN_H); } void Screen_LoK::deletePageFromDisk(int page) { diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h index 74df23a543..5b4b8a9266 100644 --- a/engines/kyra/screen_lok.h +++ b/engines/kyra/screen_lok.h @@ -50,6 +50,7 @@ public: void savePageToDisk(const char *file, int page); void loadPageFromDisk(const char *file, int page); + void queryPageFromDisk(const char *file, int page, uint8 *buffer); void deletePageFromDisk(int page); void copyBackgroundBlock(int x, int page, int flag); diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 9a059ead2a..cf2d2aceb1 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -293,7 +293,7 @@ int KyraEngine_MR::o3_updateScore(EMCState *script) { int KyraEngine_MR::o3_makeSecondChanceSave(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_makeSecondChanceSave(%p) ()", (const void *)script); - saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME"); + saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME", 0); return 0; } diff --git a/engines/kyra/timer_mr.cpp b/engines/kyra/timer_mr.cpp index 37a910ccf2..ea7f64fed1 100644 --- a/engines/kyra/timer_mr.cpp +++ b/engines/kyra/timer_mr.cpp @@ -65,7 +65,7 @@ void KyraEngine_MR::timerRunSceneScript7(int arg) { void KyraEngine_MR::timerFleaDeath(int arg) { debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_MR::timerFleaDeath(%d)", arg); _timer->setCountdown(4, 5400); - saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME"); + saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME", 0); _screen->hideMouse(); _timer->disable(4); runAnimationScript("FLEADTH1.EMC", 0, 0, 1, 1); -- cgit v1.2.3 From 9138128f5cee660184ce57b645644d341241918a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 20 Aug 2008 14:24:16 +0000 Subject: - Committed Max' compressed save backseeking support from patch #2050337 "KYRA/SCUMM: Thumbnail support/improvement" - Extended SCUMM engine to support savegames without thumbnail header. (Increased savegame version to prevent saves to be loaded from older ScummVM versions) - Fixed KYRA to properly support savegames without thumbnail header. svn-id: r34054 --- engines/kyra/saveload.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index c08967c85c..debf0623ac 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -113,7 +113,10 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab if (loadThumbnail) { header.thumbnail = new Graphics::Surface(); assert(header.thumbnail); - Graphics::loadThumbnail(*in, *header.thumbnail); + if (!Graphics::loadThumbnail(*in, *header.thumbnail)) { + delete header.thumbnail; + header.thumbnail = 0; + } } else { Graphics::skipThumbnailHeader(*in); } -- cgit v1.2.3 From 430977e438794b85808d3df8f2876b6faf46fc25 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 20 Aug 2008 14:30:40 +0000 Subject: Committed patch #2055831 "KYRA: ResFileEntry parent cache optimization". svn-id: r34055 --- engines/kyra/resource.cpp | 159 ++++++++++++++++++++++++++++++---------------- engines/kyra/resource.h | 10 ++- 2 files changed, 112 insertions(+), 57 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 5da6bb3873..5845fa80a5 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -150,7 +150,7 @@ bool Resource::reset() { } bool Resource::loadPakFile(const Common::String &filename) { - if (!isAccessable(filename)) + if (!isAccessible(filename)) return false; ResFileMap::iterator iter = _map.find(filename); @@ -201,18 +201,18 @@ bool Resource::loadPakFile(const Common::String &filename) { // If the old parent is not protected we mark it as not preload anymore, // since now no longer all of its embedded files are in the filemap. oldParent->_value.preload = false; - _map[i->filename] = i->entry; + iter->_value = i->entry; } } else { // Old parent not found? That's strange... But we just overwrite the old // entry. - _map[i->filename] = i->entry; + iter->_value = i->entry; } } else { // The old parent has the same filenames as the new archive, we are sure and overwrite the // old file entry, could be afterall that the preload flag of the new archive was // just unflagged. - _map[i->filename] = i->entry; + iter->_value = i->entry; } } // 'else' case would mean here overwriting an existing file entry in the map without parent. @@ -244,7 +244,7 @@ bool Resource::loadFileList(const Common::String &filedata) { filename.toUppercase(); if (filename.hasSuffix(".PAK")) { - if (!isAccessable(filename) && _vm->gameFlags().isDemo) { + if (!isAccessible(filename) && _vm->gameFlags().isDemo) { // the demo version supplied with Kyra3 does not // contain all pak files listed in filedata.fdt // so we don't do anything here if they are non @@ -289,7 +289,7 @@ void Resource::clearCompFileList() { } bool Resource::isInPakList(const Common::String &filename) { - if (!isAccessable(filename)) + if (!isAccessible(filename)) return false; ResFileMap::iterator iter = _map.find(filename); if (iter == _map.end()) @@ -320,7 +320,7 @@ uint8 *Resource::fileData(const char *file, uint32 *size) { bool Resource::exists(const char *file, bool errorOutOnFail) { if (Common::File::exists(file)) return true; - else if (isAccessable(file)) + else if (isAccessible(file)) return true; else if (errorOutOnFail) error("File '%s' can't be found", file); @@ -335,7 +335,7 @@ uint32 Resource::getFileSize(const char *file) { if (f.open(file)) return f.size(); } else { - if (!isAccessable(file)) + if (!isAccessible(file)) return 0; ResFileMap::const_iterator iter = _map.find(file); @@ -362,7 +362,7 @@ Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) if ((compEntry = _compFiles.find(file)) != _compFiles.end()) return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false); - if (!isAccessable(file)) + if (!isAccessible(file)) return 0; ResFileMap::const_iterator iter = _map.find(file); @@ -381,8 +381,8 @@ Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) Common::SeekableReadStream *parent = getFileStream(iter->_value.parent); assert(parent); - ResFileMap::const_iterator parentIter = _map.find(iter->_value.parent); - const ResArchiveLoader *loader = getLoader(parentIter->_value.type); + ResFileEntry* parentEntry = getParentEntry(&iter->_value); + const ResArchiveLoader *loader = getLoader(parentEntry->type); assert(loader); return loader->loadFileFromArchive(file, parent, iter->_value); @@ -391,26 +391,65 @@ Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) return 0; } -bool Resource::isAccessable(const Common::String &file) { +bool Resource::isAccessible(const Common::String &file) { checkFile(file); ResFileMap::const_iterator iter = _map.find(file); - while (iter != _map.end()) { - if (!iter->_value.parent.empty()) { - iter = _map.find(iter->_value.parent); - if (iter != _map.end()) { - // parent can never be a non archive file - if (iter->_value.type == ResFileEntry::kRaw) - return false; - // not mounted parent means not accessable - else if (!iter->_value.mounted) - return false; - } + if (iter == _map.end()) + return false; + + return isAccessible(&iter->_value); +} + +bool Resource::isAccessible(const ResFileEntry *fileEntry) { + assert(fileEntry); + + const ResFileEntry* currentEntry = fileEntry; + while (not currentEntry->parent.empty()) { + if (currentEntry->parentEntry) { + currentEntry = currentEntry->parentEntry; } else { - return true; + ResFileMap::iterator it = _map.find(currentEntry->parent); + if (it == _map.end()) + return false; + else + currentEntry->parentEntry = &it->_value; } + // parent can never be a non archive file + if (currentEntry->type == ResFileEntry::kRaw) + return false; + // not mounted parent means not accessable + else if (!currentEntry->mounted) + return false; } - return false; + + return true; +} + +ResFileEntry *Resource::getParentEntry(const ResFileEntry *entry) const { + assert(entry); + if (entry->parent.empty()) { + return 0; + } else if (entry->parentEntry) { + assert(_map.find(entry->parent) != _map.end()); // If some day the hash map implementations changes and moves nodes around, + // this assumption would fail and the whole system would need a refactoring + assert(entry->parentEntry == &_map.find(entry->parent)->_value); + return entry->parentEntry; + } else { + ResFileMap::iterator it = _map.find(entry->parent); + if (it == _map.end()) + return 0; // If it happens often, the structure maybe deserves a flag to avoid rechecking the map + else { + entry->parentEntry = &it->_value; + return entry->parentEntry; + } + } +} + +ResFileEntry *Resource::getParentEntry(const Common::String &filename) const { + ResFileMap::iterator it = _map.find(filename); + assert(it != _map.end()); + return getParentEntry(&it->_value); } void Resource::checkFile(const Common::String &file) { @@ -418,67 +457,72 @@ void Resource::checkFile(const Common::String &file) { CompFileMap::const_iterator iter; if ((iter = _compFiles.find(file)) != _compFiles.end()) { - ResFileEntry entry; + ResFileEntry& entry = _map[file]; entry.parent = ""; + entry.parentEntry = 0; entry.size = iter->_value.size; entry.mounted = false; entry.preload = false; entry.prot = false; entry.type = ResFileEntry::kAutoDetect; entry.offset = 0; - _map[file] = entry; - - detectFileTypes(); + + detectFileType(file, &entry); } else if (Common::File::exists(file)) { Common::File temp; if (temp.open(file)) { - ResFileEntry entry; + ResFileEntry& entry = _map[file]; entry.parent = ""; + entry.parentEntry = 0; entry.size = temp.size(); entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; entry.preload = false; entry.prot = false; entry.type = ResFileEntry::kAutoDetect; entry.offset = 0; - _map[file] = entry; temp.close(); - detectFileTypes(); + detectFileType(file, &entry); } } } } -void Resource::detectFileTypes() { - for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) { - if (!isAccessable(i->_key)) - continue; +void Resource::detectFileType(const Common::String &filename, ResFileEntry *fileEntry) { + assert(fileEntry); + + if (!isAccessible(fileEntry)) + return; - if (i->_value.type == ResFileEntry::kAutoDetect) { - Common::SeekableReadStream *stream = 0; - for (LoaderIterator l = _loaders.begin(); l != _loaders.end(); ++l) { - if (!(*l)->checkFilename(i->_key)) - continue; - - if (!stream) - stream = getFileStream(i->_key); - - if ((*l)->isLoadable(i->_key, *stream)) { - i->_value.type = (*l)->getType(); - i->_value.mounted = false; - i->_value.preload = false; - break; - } - } - delete stream; - stream = 0; + if (fileEntry->type == ResFileEntry::kAutoDetect) { + Common::SeekableReadStream *stream = 0; + for (LoaderIterator l = _loaders.begin(); l != _loaders.end(); ++l) { + if (!(*l)->checkFilename(filename)) + continue; + + if (!stream) + stream = getFileStream(filename); - if (i->_value.type == ResFileEntry::kAutoDetect) - i->_value.type = ResFileEntry::kRaw; + if ((*l)->isLoadable(filename, *stream)) { + fileEntry->type = (*l)->getType(); + fileEntry->mounted = false; + fileEntry->preload = false; + break; + } } + delete stream; + stream = 0; + + if (fileEntry->type == ResFileEntry::kAutoDetect) + fileEntry->type = ResFileEntry::kRaw; } } +void Resource::detectFileTypes() { + for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) + detectFileType(i->_key, &i->_value); +} + void Resource::tryLoadCompFiles() { for (CCompLoaderIterator i = _compLoaders.begin(); i != _compLoaders.end(); ++i) { if ((*i)->checkForFiles()) @@ -620,6 +664,7 @@ bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableRead entry.size = endoffset - startoffset; entry.offset = startoffset; entry.parent = filename; + entry.parentEntry = 0; entry.type = ResFileEntry::kAutoDetect; entry.mounted = false; entry.prot = false; @@ -738,6 +783,7 @@ bool ResLoaderInsMalcolm::loadFile(const Common::String &filename, Common::Seeka for (Common::List::iterator file = filenames.begin(); file != filenames.end(); ++file) { ResFileEntry entry; entry.parent = filename; + entry.parentEntry = 0; entry.type = ResFileEntry::kAutoDetect; entry.mounted = false; entry.preload = false; @@ -807,6 +853,7 @@ bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableRead for (uint i = 0; i < entries; ++i) { ResFileEntry entry; entry.parent = filename; + entry.parentEntry = 0; entry.type = ResFileEntry::kAutoDetect; entry.mounted = false; entry.preload = false; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index d43f730e6b..5ecbd145fe 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -43,6 +43,9 @@ namespace Kyra { struct ResFileEntry { Common::String parent; + mutable ResFileEntry *parentEntry; // Cache to avoid lookup by string in the map + // No smart invalidation is needed because the map is cleared globally + // or expanded but no element is ever removed uint32 size; bool preload; @@ -128,9 +131,11 @@ public: bool loadFileToBuf(const char *file, void *buf, uint32 maxSize); protected: void checkFile(const Common::String &file); - bool isAccessable(const Common::String &file); + bool isAccessible(const Common::String &file); + bool isAccessible(const ResFileEntry *fileEntry); void detectFileTypes(); + void detectFileType(const Common::String &filename, ResFileEntry *fileEntry); void initializeLoaders(); const ResArchiveLoader *getLoader(ResFileEntry::kType type) const; @@ -140,6 +145,9 @@ protected: LoaderList _loaders; ResFileMap _map; + ResFileEntry *getParentEntry(const ResFileEntry *entry) const; + ResFileEntry *getParentEntry(const Common::String &filename) const; + typedef Common::List > CompLoaderList; typedef CompLoaderList::iterator CompLoaderIterator; typedef CompLoaderList::const_iterator CCompLoaderIterator; -- cgit v1.2.3 From f28b93e7c70fe68d4362c84201ed7b584654e5a0 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 20 Aug 2008 14:56:46 +0000 Subject: Fix compilation: Changed 'not' to '!'. svn-id: r34057 --- engines/kyra/resource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 5845fa80a5..946169ddd4 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -405,7 +405,7 @@ bool Resource::isAccessible(const ResFileEntry *fileEntry) { assert(fileEntry); const ResFileEntry* currentEntry = fileEntry; - while (not currentEntry->parent.empty()) { + while (!currentEntry->parent.empty()) { if (currentEntry->parentEntry) { currentEntry = currentEntry->parentEntry; } else { -- cgit v1.2.3 From 023189d6f1d270ca30331ec05c5f93ba40707670 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Wed, 20 Aug 2008 16:14:10 +0000 Subject: tempo fix svn-id: r34064 --- engines/kyra/sound_towns.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index dbe0469809..c103b51bc0 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1534,9 +1534,9 @@ private: class TownsPC98_OpnPercussionSource { public: TownsPC98_OpnPercussionSource(const float rate); - ~TownsPC98_OpnPercussionSource(); + ~TownsPC98_OpnPercussionSource() {} - void init(const void *pcmData = 0); + void init(const uint8 *pcmData = 0); void reset(); void writeReg(uint8 address, uint8 value); @@ -2871,16 +2871,13 @@ TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const float rate) : memset(_pcmInstr, 0, sizeof(PcmInstrument) * 6); } -TownsPC98_OpnPercussionSource::~TownsPC98_OpnPercussionSource() { -} - -void TownsPC98_OpnPercussionSource::init(const void *pcmData) { +void TownsPC98_OpnPercussionSource::init(const uint8 *pcmData) { if (_ready) { reset(); return; } - const uint8 *start = (const uint8*) pcmData; + const uint8 *start = pcmData; const uint8 *pos = start; if (pcmData) { @@ -3505,9 +3502,12 @@ void TownsPC98_OpnDriver::startSoundEffect() { } void TownsPC98_OpnDriver::setTempo(uint8 tempo) { - _tempo = tempo - 0x10; - _samplesPerCallback = _tempo ? (getRate() / _tempo) : 0; - _samplesPerCallbackRemainder = _tempo ? (getRate() % _tempo) : 0; + _tempo = tempo; + + float spc = (float)(0x100 - _tempo) * 2.5 * _baserate; + _samplesPerCallback = (int32) spc; + spc -= _samplesPerCallback; + _samplesPerCallbackRemainder = (spc > 0.5) ? 1 : 0; } SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) -- cgit v1.2.3 From bfd172399817fdaf7ef681363dfae6ea25d99715 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Wed, 20 Aug 2008 19:57:57 +0000 Subject: - add support for Italian floppy version - more work on fm-towns music tempo svn-id: r34067 --- engines/kyra/detection.cpp | 12 +++++ engines/kyra/sound_towns.cpp | 116 ++++++++++++++++++++++++------------------- engines/kyra/staticres.cpp | 2 +- 3 files changed, 79 insertions(+), 51 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index d41ecb5e9b..47bdbbb559 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -397,6 +397,18 @@ const KYRAGameDescription adGameDescs[] = { KYRA2_FLOPPY_FLAGS }, + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"), + Common::IT_ITA, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA2_FLOPPY_FLAGS + }, + { // CD version { "kyra2", diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index c103b51bc0..cec238862f 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1598,7 +1598,8 @@ public: void pause() { _musicPlaying = false; } void cont() { _musicPlaying = true; } - void callback(); + void musicCallback(); + void sfxCallback(); void nextTick(int32 *buffer, uint32 bufferSize); bool looping() { return _looping == _updateChannelsFlag ? true : false; } @@ -1622,7 +1623,9 @@ protected: TownsPC98_OpnPercussionSource *_pcm; void startSoundEffect(); - void setTempo(uint8 tempo); + + void setMusicTempo(uint8 tempo); + void setSfxTempo(uint16 tempo); void lock() { _mutex.lock(); } void unlock() { _mutex.unlock(); } @@ -1651,15 +1654,15 @@ protected: uint8 *_patches; uint8 *_ssgPatches; - uint8 _cbCounter; uint8 _updateChannelsFlag; uint8 _updateSSGFlag; uint8 _updatePCMFlag; + uint8 _updateSfxFlag; uint8 _finishedChannelsFlag; uint8 _finishedSSGFlag; uint8 _finishedPCMFlag; + uint8 _finishedSfxFlag; - uint16 _tempo; bool _musicPlaying; bool _sfxPlaying; uint8 _fading; @@ -1673,10 +1676,10 @@ protected: uint8 *_sfxData; uint16 _sfxOffsets[2]; - int32 _samplesTillCallback; - int32 _samplesTillCallbackRemainder; - int32 _samplesPerCallback; - int32 _samplesPerCallbackRemainder; + int32 _samplesTillMusicCallback; + int32 _samplesPerMusicCallback; + int32 _samplesTillSfxCallback; + int32 _samplesPerSfxCallback; const int _numChan; const int _numSSG; @@ -2208,7 +2211,7 @@ bool TownsPC98_OpnChannel::control_f4_setOutputLevel(uint8 para) { } bool TownsPC98_OpnChannel::control_f5_setTempo(uint8 para) { - _drv->setTempo(para); + _drv->setMusicTempo(para); return true; } @@ -2599,6 +2602,7 @@ bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) { } else { // end of sfx track - restore ssg music channel _flags |= CHS_EOT; + _drv->_finishedSfxFlag |= _idFlag; _drv->_ssgChannels[_chanNum]->restore(); } @@ -3038,14 +3042,15 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), _opnFreqTableSSG(_drvTables + 252), _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 228)), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), - _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _cbCounter(4), _musicTickCounter(0), + _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _musicTickCounter(0), _updateSfxFlag(type == OD_TOWNS ? 0 : 6), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _updateSSGFlag(type == OD_TOWNS ? 0 : 7), _updatePCMFlag(type == OD_TYPE86 ? 1 : 0), _finishedChannelsFlag(0), _finishedSSGFlag(0), - _finishedPCMFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), + _finishedPCMFlag(0), _samplesTillMusicCallback(0), _samplesTillSfxCallback (0), _finishedSfxFlag(0), _sfxData(0), _ready(false), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPCM(type == OD_TYPE86 ? true : false), _sfxOffs(0), _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true), _ssgPatches(0), _ssg(0), _pcm(0), _baserate(55125.0f / (float)getRate()) { - setTempo(84); + setMusicTempo(84); + setSfxTempo(654); } TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { @@ -3171,20 +3176,22 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) int32 samplesLeft = numSamples >> 1; while (samplesLeft) { - if (!_samplesTillCallback) { - callback(); - - _samplesTillCallback = _samplesPerCallback; - _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; - if (_samplesTillCallbackRemainder >= _tempo) { - _samplesTillCallback++; - _samplesTillCallbackRemainder -= _tempo; - } + if (!_samplesTillMusicCallback) { + musicCallback(); + _samplesTillMusicCallback = _samplesPerMusicCallback; + } + + if (!_samplesTillSfxCallback) { + sfxCallback(); + _samplesTillSfxCallback = _samplesPerSfxCallback; } - int32 render = MIN(samplesLeft, _samplesTillCallback); + int32 render = MIN(_samplesTillSfxCallback, _samplesTillMusicCallback); + render = MIN(samplesLeft, render); samplesLeft -= render; - _samplesTillCallback -= render; + + _samplesTillMusicCallback -= render; + _samplesTillSfxCallback -= render; nextTick(tmp, render); @@ -3257,8 +3264,7 @@ void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) { _regProtectionFlag = false; _patches = src_a + 4; - _cbCounter = 4; - _finishedChannelsFlag = _finishedSSGFlag = 0; + _finishedChannelsFlag = _finishedSSGFlag = _finishedPCMFlag = 0; _musicPlaying = (loadPaused ? false : true); @@ -3286,6 +3292,7 @@ void TownsPC98_OpnDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]); _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]); _sfxPlaying = true; + _finishedSfxFlag = 0; unlock(); } @@ -3348,28 +3355,12 @@ void TownsPC98_OpnDriver::fadeStep() { unlock(); } -void TownsPC98_OpnDriver::callback() { +void TownsPC98_OpnDriver::musicCallback() { lock(); - if (_sfxChannels && _sfxPlaying) { - if (_sfxData) - startSoundEffect(); - - _sfxOffs = 3; - _trackPtr = _sfxBuffer; - - for (int i = 0; i < 2; i++) { - _sfxChannels[i]->processEvents(); - _sfxChannels[i]->processFrequency(); - } - - _trackPtr = _musicBuffer; - } - _sfxOffs = 0; - if (!--_cbCounter && _musicPlaying) { - _cbCounter = 4; + if (_musicPlaying) { _musicTickCounter++; for (int i = 0; i < _numChan; i++) { @@ -3401,6 +3392,30 @@ void TownsPC98_OpnDriver::callback() { unlock(); } +void TownsPC98_OpnDriver::sfxCallback() { + lock(); + + if (_sfxChannels && _sfxPlaying) { + if (_sfxData) + startSoundEffect(); + + _sfxOffs = 3; + _trackPtr = _sfxBuffer; + + for (int i = 0; i < 2; i++) { + _sfxChannels[i]->processEvents(); + _sfxChannels[i]->processFrequency(); + } + + _trackPtr = _musicBuffer; + } + + if (_finishedSfxFlag == _updateSfxFlag) + _sfxPlaying = false; + + unlock(); +} + void TownsPC98_OpnDriver::nextTick(int32 *buffer, uint32 bufferSize) { if (!_ready) return; @@ -3501,13 +3516,14 @@ void TownsPC98_OpnDriver::startSoundEffect() { _sfxData = 0; } -void TownsPC98_OpnDriver::setTempo(uint8 tempo) { - _tempo = tempo; +void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { + float spc = (float)(0x100 - tempo) * 10.0 * _baserate; + _samplesPerMusicCallback = (int32) spc; +} - float spc = (float)(0x100 - _tempo) * 2.5 * _baserate; - _samplesPerCallback = (int32) spc; - spc -= _samplesPerCallback; - _samplesPerCallbackRemainder = (spc > 0.5) ? 1 : 0; +void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { + float spc = (float)(0x400 - tempo) * _baserate; + _samplesPerSfxCallback = (int32) spc; } SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) @@ -3845,7 +3861,7 @@ void SoundPC98::playSoundEffect(uint8 track) { // This has been disabled for now since I don't know // how to make up the correct track number. It probably // needs a map. - // _driver->loadSoundEffectData(_sfxTrackData, track); + //_driver->loadSoundEffectData(_sfxTrackData, track); } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index bb63c24c36..7464df049a 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -43,7 +43,7 @@ namespace Kyra { -#define RESFILE_VERSION 31 +#define RESFILE_VERSION 32 bool StaticResource::checkKyraDat() { Common::File kyraDat; -- cgit v1.2.3 From 1a7d3ef5eefd372d93a1298883120b9a835fd271 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Wed, 20 Aug 2008 22:38:36 +0000 Subject: KYRA: Towns/PC-98-Audio: fix bug where pitch wheel is processed twice instead of once svn-id: r34076 --- engines/kyra/sound_towns.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index cec238862f..6f06fa9b5e 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -2459,8 +2459,6 @@ void TownsPC98_OpnChannelSSG::processFrequency() { if (!processPitchWheel()) return; - processPitchWheel(); - uint16 f = _frequency >> _block; writeReg(_regOffset << 1, f & 0xff); writeReg((_regOffset << 1) + 1, f >> 8); @@ -3517,12 +3515,12 @@ void TownsPC98_OpnDriver::startSoundEffect() { } void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { - float spc = (float)(0x100 - tempo) * 10.0 * _baserate; + float spc = (float)(0x100 - tempo) * 10.0f * _baserate; _samplesPerMusicCallback = (int32) spc; } void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { - float spc = (float)(0x400 - tempo) * _baserate; + float spc = (float)(0x400 - tempo) * 0.625f * _baserate; _samplesPerSfxCallback = (int32) spc; } -- cgit v1.2.3 From 99790e79151207988305d2a5344365994ad306ad Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 21 Aug 2008 02:17:52 +0000 Subject: KYRA: Towns/PC-98-Audio: tempo fix for output rates other than 44100 Hz svn-id: r34078 --- engines/kyra/sound_towns.cpp | 60 ++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 25 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 6f06fa9b5e..17b3c4a626 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1684,7 +1684,6 @@ protected: const int _numChan; const int _numSSG; const bool _hasPCM; - const bool _hasStereo; static const uint8 _drvTables[]; static const uint32 _adtStat[]; @@ -3036,17 +3035,28 @@ void TownsPC98_OpnPercussionSource::advanceInput(PcmInstrument *ins) { } TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : - _mixer(mixer), _trackPtr(0), _musicPlaying(false), _sfxPlaying(false), _fading(false), _channels(0), - _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _looping(0), _opnCarrier(_drvTables + 76), - _opnFreqTable(_drvTables + 84), _opnFreqTableSSG(_drvTables + 252), _opnFxCmdLen(_drvTables + 36), - _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 228)), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), - _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _musicTickCounter(0), _updateSfxFlag(type == OD_TOWNS ? 0 : 6), - _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _updateSSGFlag(type == OD_TOWNS ? 0 : 7), - _updatePCMFlag(type == OD_TYPE86 ? 1 : 0), _finishedChannelsFlag(0), _finishedSSGFlag(0), - _finishedPCMFlag(0), _samplesTillMusicCallback(0), _samplesTillSfxCallback (0), _finishedSfxFlag(0), - _sfxData(0), _ready(false), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPCM(type == OD_TYPE86 ? true : false), - _sfxOffs(0), _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true), - _ssgPatches(0), _ssg(0), _pcm(0), _baserate(55125.0f / (float)getRate()) { + _mixer(mixer), + + _channels(0), _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _ssg(0), _pcm(0), + + _trackPtr(0), _sfxData(0), _sfxOffs(0), _ssgPatches(0), + + _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), _opnFreqTableSSG(_drvTables + 252), + _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 228)), + _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), + + _numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPCM(type == OD_TYPE86 ? true : false), + _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0), + _updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0), + _updatePCMFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedPCMFlag(0), + _updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0), + + _baserate(55125.0f / (float)getRate()), + _samplesTillMusicCallback(0), _samplesTillSfxCallback (0), + _musicTickCounter(0), + + _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) { + setMusicTempo(84); setSfxTempo(654); } @@ -3276,12 +3286,12 @@ void TownsPC98_OpnDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { } if (!_sfxChannels) { - warning("TownsPC98_OpnDriver: sound effects not supported by this configuration"); + warning("TownsPC98_OpnDriver: Sound effects not supported by this configuration"); return; } if (!data) { - warning("TownsPC98_OpnDriver: Invalid sound effect file data"); + warning("TownsPC98_OpnDriver: Invalid sound effects file data"); return; } @@ -3368,15 +3378,13 @@ void TownsPC98_OpnDriver::musicCallback() { } } - if (_numSSG) { - for (int i = 0; i < _numSSG; i++) { - if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { - _ssgChannels[i]->processEvents(); - _ssgChannels[i]->processFrequency(); - } + for (int i = 0; i < _numSSG; i++) { + if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { + _ssgChannels[i]->processEvents(); + _ssgChannels[i]->processFrequency(); } } - + if (_hasPCM) if (_updatePCMFlag & _pcmChannel->_idFlag) _pcmChannel->processEvents(); @@ -3401,8 +3409,10 @@ void TownsPC98_OpnDriver::sfxCallback() { _trackPtr = _sfxBuffer; for (int i = 0; i < 2; i++) { - _sfxChannels[i]->processEvents(); - _sfxChannels[i]->processFrequency(); + if (_updateSfxFlag & _sfxChannels[i]->_idFlag) { + _sfxChannels[i]->processEvents(); + _sfxChannels[i]->processFrequency(); + } } _trackPtr = _musicBuffer; @@ -3515,12 +3525,12 @@ void TownsPC98_OpnDriver::startSoundEffect() { } void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { - float spc = (float)(0x100 - tempo) * 10.0f * _baserate; + float spc = (float)(0x100 - tempo) * 16.0f / _baserate; _samplesPerMusicCallback = (int32) spc; } void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { - float spc = (float)(0x400 - tempo) * 0.625f * _baserate; + float spc = (float)(0x400 - tempo) / _baserate; _samplesPerSfxCallback = (int32) spc; } -- cgit v1.2.3 From 513f5ae150ad60bd899bae7ecae2435363e1d84d Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 21 Aug 2008 12:04:55 +0000 Subject: KYRA: Towns/PC-98-Audio: increased precision for envelope generator timing and tempo when using "odd" output rates like 48 kHz or 8 kHz svn-id: r34079 --- engines/kyra/sound_towns.cpp | 89 +++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 34 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 17b3c4a626..99b23824c7 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1085,7 +1085,7 @@ void Towns_EuphonyTrackQueue::initDriver() { class TownsPC98_OpnOperator { public: - TownsPC98_OpnOperator(const float rate, const uint8 *rateTable, + TownsPC98_OpnOperator(const uint32 timerbase, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable); ~TownsPC98_OpnOperator() {} @@ -1137,8 +1137,8 @@ protected: const int32 *_tLvlTbl; const int32 *_detnTbl; - const int _tickLength; - int _tick; + const uint32 _tickLength; + uint32 _timer; int32 _currentLevel; struct EvpState { @@ -1147,11 +1147,11 @@ protected: } fs_a, fs_d, fs_s, fs_r; }; -TownsPC98_OpnOperator::TownsPC98_OpnOperator(const float rate, const uint8 *rateTable, +TownsPC98_OpnOperator::TownsPC98_OpnOperator(const uint32 timerbase, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) : _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), - _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength((int)(rate * 65536.0f)), + _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2), _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), _phase(0), _state(s_ready) { @@ -1209,9 +1209,9 @@ void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &o if (_state == s_ready) return; - _tick += _tickLength; - while (_tick > 0x30000) { - _tick -= 0x30000; + _timer += _tickLength; + while (_timer > 0x5B8D80) { + _timer -= 0x5B8D80; ++_tickCount; int32 levelIncrement = 0; @@ -1289,7 +1289,7 @@ void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &o void TownsPC98_OpnOperator::reset(){ keyOff(); - _tick = 0; + _timer = 0; _keyScale2 = 0; _currentLevel = 1023; @@ -1486,7 +1486,7 @@ private: class TownsPC98_OpnSquareSineSource { public: - TownsPC98_OpnSquareSineSource(const float rate); + TownsPC98_OpnSquareSineSource(const uint32 timerbase); ~TownsPC98_OpnSquareSineSource(); void init(const int *rsTable, const int *rseTable); @@ -1518,9 +1518,8 @@ private: int32 *_tlTable; int32 *_tleTable; - const float _rate; - const int _tickLength; - int _timer; + const uint32 _tickLength; + uint32 _timer; struct Channel { int tick; @@ -1533,7 +1532,7 @@ private: class TownsPC98_OpnPercussionSource { public: - TownsPC98_OpnPercussionSource(const float rate); + TownsPC98_OpnPercussionSource(const uint32 timerbase); ~TownsPC98_OpnPercussionSource() {} void init(const uint8 *pcmData = 0); @@ -1568,8 +1567,8 @@ private: uint8 _totalLevel; - const int _tickLength; - int _timer; + const uint32 _tickLength; + uint32 _timer; bool _ready; }; @@ -1676,10 +1675,14 @@ protected: uint8 *_sfxData; uint16 _sfxOffsets[2]; - int32 _samplesTillMusicCallback; - int32 _samplesPerMusicCallback; - int32 _samplesTillSfxCallback; - int32 _samplesPerSfxCallback; + uint32 _samplesTillMusicCallback; + uint32 _samplesTillMusicCallbackRemainder; + uint32 _samplesPerMusicCallback; + uint32 _samplesPerMusicCallbackRemainder; + uint32 _samplesTillSfxCallback; + uint32 _samplesTillSfxCallbackRemainder; + uint32 _samplesPerSfxCallback; + uint32 _samplesPerSfxCallbackRemainder; const int _numChan; const int _numSSG; @@ -1690,6 +1693,8 @@ protected: static const int _ssgTables[]; const float _baserate; + uint32 _timerbase; + bool _ready; }; @@ -1721,7 +1726,7 @@ TownsPC98_OpnChannel::~TownsPC98_OpnChannel() { void TownsPC98_OpnChannel::init() { _opr = new TownsPC98_OpnOperator*[4]; for (int i = 0; i < 4; i++) - _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift, + _opr[i] = new TownsPC98_OpnOperator(_drv->_timerbase, _drv->_oprRates, _drv->_oprRateshift, _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune); #define Control(x) &TownsPC98_OpnChannel::control_##x @@ -2710,8 +2715,8 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { } } -TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const float rate) : _rate(rate), _tlTable(0), - _tleTable(0), _regIndex(_reg), _updateRequest(-1), _tickLength((int)(rate * 32768.0f * 27.0f)), _ready(0) { +TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0), + _tleTable(0), _regIndex(_reg), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0) { memset(_reg, 0, 16); memset(_channels, 0, sizeof(Channel) * 3); reset(); @@ -2807,8 +2812,8 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { for (uint32 i = 0; i < bufferSize; i++) { _timer += _tickLength; - while (_timer > 0x30000) { - _timer -= 0x30000; + while (_timer > 0x5B8D80) { + _timer -= 0x5B8D80; if (++_nTick >= (_reg[6] & 0x1f)) { if ((_rand + 1) & 2) @@ -2867,8 +2872,8 @@ void TownsPC98_OpnSquareSineSource::updatesRegs() { _updateRequest = -1; } -TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const float rate) : - _tickLength((int)(rate * 65536.0)), _timer(0), _ready(false) { +TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) : + _tickLength(timerbase * 2), _timer(0), _ready(false) { memset(_pcmInstr, 0, sizeof(PcmInstrument) * 6); } @@ -2973,8 +2978,8 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { for (uint32 i = 0; i < bufferSize; i++) { _timer += _tickLength; - while (_timer > 0x30000) { - _timer -= 0x30000; + while (_timer > 0x5B8D80) { + _timer -= 0x5B8D80; for (int ii = 0; ii < 6; ii++) { PcmInstrument *s = &_pcmInstr[ii]; @@ -3052,11 +3057,13 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0), _baserate(55125.0f / (float)getRate()), - _samplesTillMusicCallback(0), _samplesTillSfxCallback (0), + _samplesTillMusicCallback(0), _samplesTillSfxCallback(0), + _samplesTillMusicCallbackRemainder(0), _samplesTillSfxCallbackRemainder(0), _musicTickCounter(0), _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) { + _timerbase = (uint32)(_baserate * 1000000.0f); setMusicTempo(84); setSfxTempo(654); } @@ -3138,7 +3145,7 @@ bool TownsPC98_OpnDriver::init() { } if (_numSSG) { - _ssg = new TownsPC98_OpnSquareSineSource(_baserate); + _ssg = new TownsPC98_OpnSquareSineSource(_timerbase); _ssg->init(&_ssgTables[0], &_ssgTables[16]); _ssgPatches = new uint8[256]; memcpy(_ssgPatches, _drvTables + 244, 256); @@ -3161,7 +3168,7 @@ bool TownsPC98_OpnDriver::init() { } if (_hasPCM) { - _pcm = new TownsPC98_OpnPercussionSource(_baserate); + _pcm = new TownsPC98_OpnPercussionSource(_timerbase); _pcm->init(); delete _pcmChannel; @@ -3187,11 +3194,23 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) if (!_samplesTillMusicCallback) { musicCallback(); _samplesTillMusicCallback = _samplesPerMusicCallback; + + _samplesTillMusicCallbackRemainder += _samplesPerMusicCallbackRemainder; + if (_samplesTillMusicCallbackRemainder >= _timerbase) { + _samplesTillMusicCallback++; + _samplesTillMusicCallbackRemainder -= _timerbase; + } } if (!_samplesTillSfxCallback) { sfxCallback(); _samplesTillSfxCallback = _samplesPerSfxCallback; + + _samplesTillSfxCallbackRemainder += _samplesPerSfxCallbackRemainder; + if (_samplesTillSfxCallbackRemainder >= _timerbase) { + _samplesTillSfxCallback++; + _samplesTillSfxCallbackRemainder -= _timerbase; + } } int32 render = MIN(_samplesTillSfxCallback, _samplesTillMusicCallback); @@ -3526,12 +3545,14 @@ void TownsPC98_OpnDriver::startSoundEffect() { void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { float spc = (float)(0x100 - tempo) * 16.0f / _baserate; - _samplesPerMusicCallback = (int32) spc; + _samplesPerMusicCallback = (uint32) spc; + _samplesPerMusicCallbackRemainder = (uint32) ((spc - (float)_samplesPerMusicCallback) * 1000000.0f); } void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { float spc = (float)(0x400 - tempo) / _baserate; - _samplesPerSfxCallback = (int32) spc; + _samplesPerSfxCallback = (uint32) spc; + _samplesPerSfxCallbackRemainder = (uint32) ((spc - (float)_samplesPerSfxCallback) * 1000000.0f); } SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) -- cgit v1.2.3 From f0ea072df689d2eb4ee22e224c0a395e57443cb7 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 21 Aug 2008 18:24:52 +0000 Subject: KYRA: Towns/PC-98-Audio: fixed bug where notes for which the hold flag was set were turned off nonetheless svn-id: r34087 --- engines/kyra/sound_towns.cpp | 49 ++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 27 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 99b23824c7..abda839ab4 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1111,6 +1111,7 @@ public: protected: EnvelopeState _state; + bool _playing; uint32 _feedbackLevel; uint32 _multiple; uint32 _totalLevel; @@ -1159,11 +1160,19 @@ TownsPC98_OpnOperator::TownsPC98_OpnOperator(const uint32 timerbase, const uint8 } void TownsPC98_OpnOperator::keyOn() { + if (_playing) + return; + + _playing = true; _state = s_attacking; _phase = 0; } void TownsPC98_OpnOperator::keyOff() { + if (!_playing) + return; + + _playing = false; if (_state != s_ready) _state = s_releasing; } @@ -1260,6 +1269,7 @@ void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &o uint32 lvlout = _totalLevel + (uint32) _currentLevel; + int32 outp = 0; int32 *i = &outp, *o = &outp; int phaseShift = 0; @@ -1675,13 +1685,13 @@ protected: uint8 *_sfxData; uint16 _sfxOffsets[2]; - uint32 _samplesTillMusicCallback; + int32 _samplesTillMusicCallback; uint32 _samplesTillMusicCallbackRemainder; - uint32 _samplesPerMusicCallback; + int32 _samplesPerMusicCallback; uint32 _samplesPerMusicCallbackRemainder; - uint32 _samplesTillSfxCallback; + int32 _samplesTillSfxCallback; uint32 _samplesTillSfxCallbackRemainder; - uint32 _samplesPerSfxCallback; + int32 _samplesPerSfxCallback; uint32 _samplesPerSfxCallbackRemainder; const int _numChan; @@ -1809,13 +1819,13 @@ void TownsPC98_OpnChannel::processEvents() { if (_flags & CHS_EOT) return; - if (_hold == false && _ticksLeft == _keyOffTime) + if (!_hold && _ticksLeft == _keyOffTime) keyOff(); if (--_ticksLeft) return; - if (_hold == false) + if (!_hold) keyOff(); uint8 cmd = 0; @@ -3024,16 +3034,11 @@ void TownsPC98_OpnPercussionSource::advanceInput(PcmInstrument *ins) { 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 }; - int d = ins->samples[1]; uint8 cur = (int8) *ins->pos++; for (int i = 0; i < 2; i++) { int b = (2 * (cur & 7) + 1) * stepTable[ins->decState] / 8; - if (cur & 8) - b = -b; - d += b; - d = CLIP(d, -2048, 2047); - ins->samples[i] = d; + ins->samples[i] = CLIP(ins->samples[i ^ 1] + (cur & 8 ? b : -b), -2048, 2047); ins->decState = CLIP(ins->decState + adjustIndex[cur & 7], 0, 48); cur >>= 4; } @@ -3213,8 +3218,7 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) } } - int32 render = MIN(_samplesTillSfxCallback, _samplesTillMusicCallback); - render = MIN(samplesLeft, render); + int32 render = MIN(samplesLeft, MIN(_samplesTillSfxCallback, _samplesTillMusicCallback)); samplesLeft -= render; _samplesTillMusicCallback -= render; @@ -3228,18 +3232,9 @@ int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) _pcm->nextTick(tmp, render); for (int i = 0; i < render; ++i) { - int32 l = tmp[i << 1]; - if (l > 32767) - l = 32767; - if (l < -32767) - l = -32767; + int32 l = CLIP(tmp[i << 1], -32767, 32767); buffer[i << 1] = (int16) l; - - int32 r = tmp[(i << 1) + 1]; - if (r > 32767) - r = 32767; - if (r < -32767) - r = -32767; + int32 r = CLIP(tmp[(i << 1) + 1], -32767, 32767); buffer[(i << 1) + 1] = (int16) r; } @@ -3545,13 +3540,13 @@ void TownsPC98_OpnDriver::startSoundEffect() { void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { float spc = (float)(0x100 - tempo) * 16.0f / _baserate; - _samplesPerMusicCallback = (uint32) spc; + _samplesPerMusicCallback = (int32) spc; _samplesPerMusicCallbackRemainder = (uint32) ((spc - (float)_samplesPerMusicCallback) * 1000000.0f); } void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { float spc = (float)(0x400 - tempo) / _baserate; - _samplesPerSfxCallback = (uint32) spc; + _samplesPerSfxCallback = (int32) spc; _samplesPerSfxCallbackRemainder = (uint32) ((spc - (float)_samplesPerSfxCallback) * 1000000.0f); } -- cgit v1.2.3 From 3b90f69a6e30b4e815d450d4165911a78a1357b9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 25 Aug 2008 13:52:10 +0000 Subject: Added short delay(Millis) call while waiting for text input, should reduce CPU usage a little bit. svn-id: r34149 --- engines/kyra/gui_v2.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/kyra') diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index e9d81f3b8a..f3013e0cb0 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -780,6 +780,7 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 } _keyPressed.reset(); + _vm->delay(10); } return buffer; -- cgit v1.2.3 From a6c931459be0b9fd9122bf67d1ac2296512496ac Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 25 Aug 2008 15:14:29 +0000 Subject: Implemented continous screen updating while waiting for text input in v2 GUI. (based on LoK implementation) svn-id: r34157 --- engines/kyra/gui_v2.cpp | 13 ++++++++++++- engines/kyra/gui_v2.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index f3013e0cb0..2ef1109183 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -35,6 +35,7 @@ namespace Kyra { GUI_v2::GUI_v2(KyraEngine_v2 *vm) : GUI(vm), _vm(vm), _screen(vm->screen_v2()) { _backUpButtonList = _unknownButtonList = 0; _buttonListChanged = false; + _lastScreenUpdate = 0; _currentMenu = 0; _isDeathMenu = false; @@ -767,6 +768,7 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 x2 -= getCharWidth(buffer[curPos]); drawTextfieldBlock(x2, y2, c3); _screen->updateScreen(); + _lastScreenUpdate = _vm->_system->getMillis(); } else if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127 && curPos < bufferSize) { if (x2 + getCharWidth(_keyPressed.ascii) + 7 < 0x11F) { buffer[curPos] = _keyPressed.ascii; @@ -776,11 +778,11 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 drawTextfieldBlock(x2, y2, c3); ++curPos; _screen->updateScreen(); + _lastScreenUpdate = _vm->_system->getMillis(); } } _keyPressed.reset(); - _vm->delay(10); } return buffer; @@ -824,6 +826,8 @@ int GUI_v2::getCharWidth(uint8 c) { void GUI_v2::checkTextfieldInput() { Common::Event event; + uint32 now = _vm->_system->getMillis(); + bool running = true; int keys = 0; while (_vm->_eventMan->pollEvent(event) && running) { @@ -854,6 +858,7 @@ void GUI_v2::checkTextfieldInput() { _vm->_mouseX = pos.x; _vm->_mouseY = pos.y; _screen->updateScreen(); + _lastScreenUpdate = now; } break; default: @@ -861,7 +866,13 @@ void GUI_v2::checkTextfieldInput() { } } + if (now - _lastScreenUpdate > 50) { + _vm->_system->updateScreen(); + _lastScreenUpdate = now; + } + processButtonList(_menuButtonList, keys | 0x8000, 0); + _vm->_system->delayMillis(3); } void GUI_v2::drawTextfieldBlock(int x, int y, uint8 c) { diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h index 60b7f0ab86..88861ff905 100644 --- a/engines/kyra/gui_v2.h +++ b/engines/kyra/gui_v2.h @@ -213,6 +213,7 @@ protected: // savename menu bool _finishNameInput, _cancelNameInput; Common::KeyState _keyPressed; + uint32 _lastScreenUpdate; const char *nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 c2, uint8 c3, int bufferSize); int finishSavename(Button *caller); -- cgit v1.2.3 From 8c58e27ab1618afa8f0e057442ad9a86243c4ed2 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 1 Sep 2008 18:14:55 +0000 Subject: Cleanup. svn-id: r34248 --- engines/kyra/detection.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index e3006f3180..c19db16d36 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1064,9 +1064,9 @@ public: return "The Legend of Kyrandia (C) Westwood Studios"; } - virtual bool hasFeature(MetaEngineFeature f) const; - virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; - virtual SaveStateList listSaves(const char *target) const; + bool hasFeature(MetaEngineFeature f) const; + bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; + SaveStateList listSaves(const char *target) const; }; bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -1152,3 +1152,4 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { #else REGISTER_PLUGIN_STATIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine); #endif + -- cgit v1.2.3 From 2f884b4f259dde121bf367bea9261f0ac6930ebc Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Mon, 1 Sep 2008 20:23:25 +0000 Subject: - kyra: fm-towns/pc-98 audio: restructured driver, added rhythm channel data svn-id: r34259 --- engines/kyra/sound_towns.cpp | 1807 ++++++++++++++++++++++++------------------ 1 file changed, 1018 insertions(+), 789 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index abda839ab4..cbf8efa99c 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1342,8 +1342,8 @@ public: CHS_RECALCFREQ = 0x01, CHS_KEYOFF = 0x02, CHS_SSGOFF = 0x04, - CHS_PITCHWHEELOFF = 0x08, - CHS_ALL_BUT_EOT = 0x0f, + CHS_VBROFF = 0x08, + CHS_ALLOFF = 0x0f, CHS_PROTECT = 0x40, CHS_EOT = 0x80 } ChannelState; @@ -1352,27 +1352,19 @@ public: virtual void processEvents(); virtual void processFrequency(); virtual bool processControlEvent(uint8 cmd); - void writeReg(uint8 regAddress, uint8 value); virtual void keyOn(); void keyOff(); void setOutputLevel(); virtual void fadeStep(); - virtual void reset(); - - void updateEnv(); - void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed); + void reset(); - bool _enableLeft; - bool _enableRight; - bool _updateEnvelopeParameters; - const uint8 _idFlag; - int32 _feedbuf[3]; + const uint8 _idFlag; protected: - void setupPitchWheel(); - bool processPitchWheel(); + void setupVibrato(); + bool processVibrato(); bool control_dummy(uint8 para); bool control_f0_setPatch(uint8 para); @@ -1382,8 +1374,8 @@ protected: bool control_f4_setOutputLevel(uint8 para); bool control_f5_setTempo(uint8 para); bool control_f6_repeatSection(uint8 para); - bool control_f7_setupPitchWheel(uint8 para); - bool control_f8_togglePitchWheel(uint8 para); + bool control_f7_setupVibrato(uint8 para); + bool control_f8_toggleVibrato(uint8 para); bool control_fa_writeReg(uint8 para); virtual bool control_fb_incOutLevel(uint8 para); virtual bool control_fc_decOutLevel(uint8 para); @@ -1399,13 +1391,13 @@ protected: uint8 _keyOffTime; bool _hold; uint8 *_dataPtr; - uint8 _ptchWhlInitDelayHi; - uint8 _ptchWhlInitDelayLo; - int16 _ptchWhlModInitVal; - uint8 _ptchWhlDuration; - uint8 _ptchWhlCurDelay; - int16 _ptchWhlModCurVal; - uint8 _ptchWhlDurLeft; + uint8 _vbrInitDelayHi; + uint8 _vbrInitDelayLo; + int16 _vbrModInitVal; + uint8 _vbrDuration; + uint8 _vbrCurDelay; + int16 _vbrModCurVal; + uint8 _vbrDurLeft; uint16 _frequency; uint8 _block; uint8 _regOffset; @@ -1421,8 +1413,6 @@ protected: const uint8 _part; TownsPC98_OpnDriver *_drv; - TownsPC98_OpnOperator **_opr; - uint16 _frqTemp; typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para); const ControlEventFunc *controlEvents; @@ -1484,10 +1474,8 @@ public: void processEvents(); bool processControlEvent(uint8 cmd); - void reset(); - private: - bool control_f1_pcmStart(uint8 para); + bool control_f1_prcStart(uint8 para); bool control_ff_endOfTrack(uint8 para); typedef bool (TownsPC98_OpnChannelPCM::*ControlEventFunc)(uint8 para); @@ -1501,18 +1489,16 @@ public: void init(const int *rsTable, const int *rseTable); void reset(); - uint8 readReg(uint8 address); void writeReg(uint8 address, uint8 value, bool force = false); void nextTick(int32 *buffer, uint32 bufferSize); + uint8 chanEnable() { return _chanEnable; } private: void updatesRegs(); - uint8 _reg[16]; uint8 _updateRequestBuf[32]; int _updateRequest; - uint8 *_regIndex; int _rand; int8 _evpTimer; @@ -1535,8 +1521,17 @@ private: int tick; uint8 smp; uint8 out; + + uint8 frqL; + uint8 frqH; + uint8 vol; } _channels[3]; + uint8 _noiseGenerator; + uint8 _chanEnable; + + uint8 *const *_reg; + bool _ready; }; @@ -1545,14 +1540,14 @@ public: TownsPC98_OpnPercussionSource(const uint32 timerbase); ~TownsPC98_OpnPercussionSource() {} - void init(const uint8 *pcmData = 0); + void init(const uint8 *instrData = 0); void reset(); void writeReg(uint8 address, uint8 value); void nextTick(int32 *buffer, uint32 bufferSize); private: - struct PcmInstrument { + struct RhtChannel { const uint8 *data; const uint8 *start; @@ -1567,26 +1562,29 @@ private: int16 samples[2]; int out; + + uint8 startPosH; + uint8 startPosL; + uint8 endPosH; + uint8 endPosL; }; - void recalcOuput(PcmInstrument *ins); - void advanceInput(PcmInstrument *ins); + void recalcOuput(RhtChannel *ins); + void advanceInput(RhtChannel *ins); - PcmInstrument _pcmInstr[6]; - uint8 _regs[48]; + RhtChannel _rhChan[6]; uint8 _totalLevel; const uint32 _tickLength; uint32 _timer; + + uint8 *const *_reg; + bool _ready; }; -class TownsPC98_OpnDriver : public Audio::AudioStream { -friend class TownsPC98_OpnChannel; -friend class TownsPC98_OpnChannelSSG; -friend class TownsPC98_OpnSfxChannel; -friend class TownsPC98_OpnChannelPCM; +class TownsPC98_OpnCore : public Audio::AudioStream { public: enum OpnType { OD_TOWNS, @@ -1594,25 +1592,13 @@ public: OD_TYPE86 }; - TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type); - ~TownsPC98_OpnDriver(); - - bool init(); - - void loadMusicData(uint8 *data, bool loadPaused = false); - void loadSoundEffectData(uint8 *data, uint8 trackNum); - void reset(); - void fadeStep(); - - void pause() { _musicPlaying = false; } - void cont() { _musicPlaying = true; } + TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type); + virtual ~TownsPC98_OpnCore(); - void musicCallback(); - void sfxCallback(); - void nextTick(int32 *buffer, uint32 bufferSize); + virtual bool init(); + virtual void reset(); - bool looping() { return _looping == _updateChannelsFlag ? true : false; } - bool musicPlaying() { return _musicPlaying; } + void writeReg(uint8 part, uint8 regAddress, uint8 value); // AudioStream interface int inline readBuffer(int16 *buffer, const int numSamples); @@ -1623,25 +1609,114 @@ public: protected: void generateTables(); - TownsPC98_OpnChannel **_channels; - TownsPC98_OpnChannelSSG **_ssgChannels; - TownsPC98_OpnSfxChannel **_sfxChannels; - TownsPC98_OpnChannelPCM *_pcmChannel; + void toggleRegProtection(bool prot) { _regProtectionFlag = prot; } + uint8 readSSGStatus() { return _ssg->chanEnable(); } + + virtual void timerCallbackA() = 0; + virtual void timerCallbackB() = 0; + + const int _numChan; + const int _numSSG; + const bool _hasPercussion; + +private: + void nextTick(int32 *buffer, uint32 bufferSize); + void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed); + + struct ChanInternal { + uint16 frqTemp; + bool enableLeft; + bool enableRight; + bool updateEnvelopeParameters; + int32 feedbuf[3]; + uint8 algorithm; + TownsPC98_OpnOperator **opr; + }; TownsPC98_OpnSquareSineSource *_ssg; - TownsPC98_OpnPercussionSource *_pcm; + TownsPC98_OpnPercussionSource *_prc; + ChanInternal *_chanInternal; + + uint8 *_oprRates; + uint8 *_oprRateshift; + uint8 *_oprAttackDecay; + uint32 *_oprFrq; + uint32 *_oprSinTbl; + int32 *_oprLevelOut; + int32 *_oprDetune; - void startSoundEffect(); + bool _regProtectionFlag; + + typedef void (TownsPC98_OpnCore::*OpnTimerProc)(); + + struct OpnTimer { + bool enabled; + uint16 value; + + int32 smpTillCb; + uint32 smpTillCbRem; + int32 smpPerCb; + uint32 smpPerCbRem; + + OpnTimerProc cb; + }; + + OpnTimer _timers[2]; + + const float _baserate; + uint32 _timerbase; + + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + + static const uint8 _percussionData[]; + static const uint32 _adtStat[]; + static const uint8 _detSrc[]; + static const int _ssgTables[]; + + bool _ready; +}; + +class TownsPC98_OpnDriver : public TownsPC98_OpnCore { +friend class TownsPC98_OpnChannel; +friend class TownsPC98_OpnChannelSSG; +friend class TownsPC98_OpnSfxChannel; +friend class TownsPC98_OpnChannelPCM; +public: + TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type); + ~TownsPC98_OpnDriver(); + + void loadMusicData(uint8 *data, bool loadPaused = false); + void loadSoundEffectData(uint8 *data, uint8 trackNum); + bool init(); + void reset(); + + void fadeStep(); + + void pause() { _musicPlaying = false; } + void cont() { _musicPlaying = true; } + + void timerCallbackB(); + void timerCallbackA(); + bool looping() { return _looping == _updateChannelsFlag ? true : false; } + bool musicPlaying() { return _musicPlaying; } + +protected: + void startSoundEffect(); + void setMusicTempo(uint8 tempo); void setSfxTempo(uint16 tempo); void lock() { _mutex.lock(); } void unlock() { _mutex.unlock(); } - Audio::Mixer *_mixer; + TownsPC98_OpnChannel **_channels; + TownsPC98_OpnChannelSSG **_ssgChannels; + TownsPC98_OpnSfxChannel **_sfxChannels; + TownsPC98_OpnChannelPCM *_rhythmChannel; + Common::Mutex _mutex; - Audio::SoundHandle _soundHandle; const uint8 *_opnCarrier; const uint8 *_opnFreqTable; @@ -1649,14 +1724,6 @@ protected: const uint8 *_opnFxCmdLen; const uint8 *_opnLvlPresets; - uint8 *_oprRates; - uint8 *_oprRateshift; - uint8 *_oprAttackDecay; - uint32 *_oprFrq; - uint32 *_oprSinTbl; - int32 *_oprLevelOut; - int32 *_oprDetune; - uint8 *_musicBuffer; uint8 *_sfxBuffer; uint8 *_trackPtr; @@ -1665,11 +1732,11 @@ protected: uint8 _updateChannelsFlag; uint8 _updateSSGFlag; - uint8 _updatePCMFlag; + uint8 _updateRhythmFlag; uint8 _updateSfxFlag; uint8 _finishedChannelsFlag; uint8 _finishedSSGFlag; - uint8 _finishedPCMFlag; + uint8 _finishedRhythmFlag; uint8 _finishedSfxFlag; bool _musicPlaying; @@ -1678,33 +1745,12 @@ protected: uint8 _looping; uint32 _musicTickCounter; - bool _updateEnvelopeParameters; - - bool _regProtectionFlag; int _sfxOffs; uint8 *_sfxData; uint16 _sfxOffsets[2]; - int32 _samplesTillMusicCallback; - uint32 _samplesTillMusicCallbackRemainder; - int32 _samplesPerMusicCallback; - uint32 _samplesPerMusicCallbackRemainder; - int32 _samplesTillSfxCallback; - uint32 _samplesTillSfxCallbackRemainder; - int32 _samplesPerSfxCallback; - uint32 _samplesPerSfxCallbackRemainder; - - const int _numChan; - const int _numSSG; - const bool _hasPCM; - static const uint8 _drvTables[]; - static const uint32 _adtStat[]; - static const int _ssgTables[]; - - const float _baserate; - uint32 _timerbase; - + bool _ready; }; @@ -1714,31 +1760,18 @@ TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 re _ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0; _ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0; - _ptchWhlInitDelayHi = _ptchWhlInitDelayLo = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = 0; + _vbrInitDelayHi = _vbrInitDelayLo = _vbrDuration = _vbrCurDelay = _vbrDurLeft = 0; _frqLSB = 0; - _hold = _updateEnvelopeParameters = false; - _enableLeft = _enableRight = true; + _hold = false; _dataPtr = 0; - _ptchWhlModInitVal = _ptchWhlModCurVal = 0; - _frequency = _frqTemp = 0; - memset(&_feedbuf, 0, sizeof(int) * 3); - _opr = 0; + _vbrModInitVal = _vbrModCurVal = 0; + _frequency = 0; } TownsPC98_OpnChannel::~TownsPC98_OpnChannel() { - if (_opr) { - for (int i = 0; i < 4; i++) - delete _opr[i]; - delete [] _opr; - } } void TownsPC98_OpnChannel::init() { - _opr = new TownsPC98_OpnOperator*[4]; - for (int i = 0; i < 4; i++) - _opr[i] = new TownsPC98_OpnOperator(_drv->_timerbase, _drv->_oprRates, _drv->_oprRateshift, - _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune); - #define Control(x) &TownsPC98_OpnChannel::control_##x static const ControlEventFunc ctrlEvents[] = { Control(f0_setPatch), @@ -1748,8 +1781,8 @@ void TownsPC98_OpnChannel::init() { Control(f4_setOutputLevel), Control(f5_setTempo), Control(f6_repeatSection), - Control(f7_setupPitchWheel), - Control(f8_togglePitchWheel), + Control(f7_setupVibrato), + Control(f8_toggleVibrato), Control(dummy), Control(fa_writeReg), Control(fb_incOutLevel), @@ -1766,20 +1799,24 @@ void TownsPC98_OpnChannel::init() { void TownsPC98_OpnChannel::keyOff() { // all operators off uint8 value = _keyNum & 0x0f; + if (_part) + value |= 4; uint8 regAddress = 0x28; - writeReg(regAddress, value); + _drv->writeReg(0, regAddress, value); _flags |= CHS_KEYOFF; } void TownsPC98_OpnChannel::keyOn() { // all operators on uint8 value = _keyNum | 0xf0; + if (_part) + value |= 4; uint8 regAddress = 0x28; - writeReg(regAddress, value); + _drv->writeReg(0, regAddress, value); } void TownsPC98_OpnChannel::loadData(uint8 *data) { - _flags = (_flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; + _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF; _ticksLeft = 1; _dataPtr = data; _totalLevel = 0x7F; @@ -1859,45 +1896,44 @@ void TownsPC98_OpnChannel::processEvents() { void TownsPC98_OpnChannel::processFrequency() { if (_flags & CHS_RECALCFREQ) { - uint8 block = (_frqBlockMSB & 0x70) >> 1; - uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f]; + + _frequency = (((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f] + _frqLSB) | (((_frqBlockMSB & 0x70) >> 1) << 8); - _frequency = (bfreq + _frqLSB) | (block << 8); - writeReg(_regOffset + 0xa4, (_frequency >> 8)); - writeReg(_regOffset + 0xa0, (_frequency & 0xff)); + _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8)); + _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff)); - setupPitchWheel(); + setupVibrato(); } - if (!(_flags & CHS_PITCHWHEELOFF)) { - if (!processPitchWheel()) + if (!(_flags & CHS_VBROFF)) { + if (!processVibrato()) return; - writeReg(_regOffset + 0xa4, (_frequency >> 8)); - writeReg(_regOffset + 0xa0, (_frequency & 0xff)); + _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8)); + _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff)); } } -void TownsPC98_OpnChannel::setupPitchWheel() { - _ptchWhlCurDelay = _ptchWhlInitDelayHi; +void TownsPC98_OpnChannel::setupVibrato() { + _vbrCurDelay = _vbrInitDelayHi; if (_flags & CHS_KEYOFF) { - _ptchWhlModCurVal = _ptchWhlModInitVal; - _ptchWhlCurDelay += _ptchWhlInitDelayLo; + _vbrModCurVal = _vbrModInitVal; + _vbrCurDelay += _vbrInitDelayLo; } - _ptchWhlDurLeft = (_ptchWhlDuration >> 1); + _vbrDurLeft = (_vbrDuration >> 1); _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); } -bool TownsPC98_OpnChannel::processPitchWheel() { - if (--_ptchWhlCurDelay) +bool TownsPC98_OpnChannel::processVibrato() { + if (--_vbrCurDelay) return false; - _ptchWhlCurDelay = _ptchWhlInitDelayHi; - _frequency += _ptchWhlModCurVal; + _vbrCurDelay = _vbrInitDelayHi; + _frequency += _vbrModCurVal; - if(!--_ptchWhlDurLeft) { - _ptchWhlDurLeft = _ptchWhlDuration; - _ptchWhlModCurVal = -_ptchWhlModCurVal; + if(!--_vbrDurLeft) { + _vbrDurLeft = _vbrDuration; + _vbrModCurVal = -_vbrModCurVal; } return true; @@ -1914,7 +1950,7 @@ void TownsPC98_OpnChannel::setOutputLevel() { for (int i = 0; i < 4; i++) { if (outopr & 1) - writeReg(reg, _totalLevel); + _drv->writeReg(_part, reg, _totalLevel); outopr >>= 1; reg += 4; } @@ -1928,15 +1964,9 @@ void TownsPC98_OpnChannel::fadeStep() { } void TownsPC98_OpnChannel::reset() { - if (_opr) { - for (int i = 0; i < 4; i++) - _opr[i]->reset(); - } - _block = 0; _frequency = 0; _hold = false; - _frqTemp = 0; _ssgTl = 0; _ssgStartLvl = 0; _ssgTargetLvl = 0; @@ -1944,221 +1974,6 @@ void TownsPC98_OpnChannel::reset() { _ssgTicksLeft = 0; _totalLevel = 0; _flags |= CHS_EOT; - - _updateEnvelopeParameters = false; - _enableLeft = _enableRight = true; - memset(&_feedbuf, 0, sizeof(int) * 3); -} - -void TownsPC98_OpnChannel::updateEnv() { - for (int i = 0; i < 4 ; i++) - _opr[i]->updatePhaseIncrement(); -} - -void TownsPC98_OpnChannel::generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed) { - int32 phbuf1, phbuf2, output; - phbuf1 = phbuf2 = output = 0; - - switch (_algorithm) { - case 0: - _opr[0]->generateOutput(0, feed, phbuf1); - _opr[2]->generateOutput(*del, 0, phbuf2); - *del = 0; - _opr[1]->generateOutput(phbuf1, 0, *del); - _opr[3]->generateOutput(phbuf2, 0, output); - break; - case 1: - _opr[0]->generateOutput(0, feed, phbuf1); - _opr[2]->generateOutput(*del, 0, phbuf2); - _opr[1]->generateOutput(0, 0, phbuf1); - _opr[3]->generateOutput(phbuf2, 0, output); - *del = phbuf1; - break; - case 2: - _opr[0]->generateOutput(0, feed, phbuf2); - _opr[2]->generateOutput(*del, 0, phbuf2); - _opr[1]->generateOutput(0, 0, phbuf1); - _opr[3]->generateOutput(phbuf2, 0, output); - *del = phbuf1; - break; - case 3: - _opr[0]->generateOutput(0, feed, phbuf2); - _opr[2]->generateOutput(0, 0, *del); - _opr[1]->generateOutput(phbuf2, 0, phbuf1); - _opr[3]->generateOutput(*del, 0, output); - *del = phbuf1; - break; - case 4: - _opr[0]->generateOutput(0, feed, phbuf1); - _opr[2]->generateOutput(0, 0, phbuf2); - _opr[1]->generateOutput(phbuf1, 0, output); - _opr[3]->generateOutput(phbuf2, 0, output); - *del = 0; - break; - case 5: - *del = feed[1]; - _opr[0]->generateOutput(-1, feed, phbuf1); - _opr[2]->generateOutput(*del, 0, output); - _opr[1]->generateOutput(*del, 0, output); - _opr[3]->generateOutput(*del, 0, output); - break; - case 6: - _opr[0]->generateOutput(0, feed, phbuf1); - _opr[2]->generateOutput(0, 0, output); - _opr[1]->generateOutput(phbuf1, 0, output); - _opr[3]->generateOutput(0, 0, output); - *del = 0; - break; - case 7: - _opr[0]->generateOutput(0, feed, output); - _opr[2]->generateOutput(0, 0, output); - _opr[1]->generateOutput(0, 0, output); - _opr[3]->generateOutput(0, 0, output); - *del = 0; - break; - }; - - int32 finOut = ((output * 7) / 2); - - if (_enableLeft) - leftSample += finOut; - - if (_enableRight) - rightSample += finOut; -} - -void TownsPC98_OpnChannel::writeReg(uint8 regAddress, uint8 value) { - if (_drv->_regProtectionFlag) - return; - - uint8 h = regAddress & 0xf0; - uint8 l = (regAddress & 0x0f); - static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; - uint8 o = oprOrdr[(l - _regOffset) >> 2]; - - switch (h) { - case 0x00: - // ssg - if (_drv->_ssg) - _drv->_ssg->writeReg(regAddress, value); - break; - case 0x10: - // pcm rhythm channel - if (_drv->_pcm) - _drv->_pcm->writeReg(regAddress - 0x10, value); - break; - case 0x20: - if (l == 8) { - // Key on/off - for (int i = 0; i < 4; i++) { - if ((value >> (4 + i)) & 1) - _opr[i]->keyOn(); - else - _opr[i]->keyOff(); - } - } else if (l == 2) { - // LFO - warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)"); - } else if (l == 7) { - // Timers; Ch 3/6 special mode - warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE (NOT SUPPORTED)"); - } else if (l == 4 || l == 5) { - // Timer A - warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_A (NOT SUPPORTED)"); - } else if (l == 6) { - // Timer B - warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_B (NOT SUPPORTED)"); - } else if (l == 10 || l == 11) { - // DAC - warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)"); - } - break; - - case 0x30: - // detune, multiple - _opr[o]->detune((value >> 4) & 7); - _opr[o]->multiple(value & 0x0f); - _updateEnvelopeParameters = true; - break; - - case 0x40: - // total level - _opr[o]->totalLevel(value & 0x7f); - break; - - case 0x50: - // rate scaling, attack rate - _opr[o]->attackRate(value & 0x1f); - if (_opr[o]->scaleRate(value >> 6)) - _updateEnvelopeParameters = true; - break; - - case 0x60: - // first decay rate, amplitude modulation - _opr[o]->decayRate(value & 0x1f); - if (value & 0x80) - warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)"); - break; - - case 0x70: - // secondary decay rate - _opr[o]->sustainRate(value & 0x1f); - break; - - case 0x80: - // secondary amplitude, release rate; - _opr[o]->sustainLevel(value >> 4); - _opr[o]->releaseRate(value & 0x0f); - break; - - case 0x90: - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress); - break; - - case 0xa0: - // frequency - l -= _regOffset; - if (l == 0) { - _frqTemp = (_frqTemp & 0xff00) | value; - _updateEnvelopeParameters = true; - for (int i = 0; i < 4; i++) - _opr[i]->frequency(_frqTemp); - } else if (l == 4) { - _frqTemp = (_frqTemp & 0xff) | (value << 8); - } else if (l == 8) { - // Ch 3/6 special mode frq - warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); - } else if (l == 12) { - // Ch 3/6 special mode frq - warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); - } - break; - - case 0xb0: - l -= _regOffset; - if (l == 0) { - // feedback, _algorithm - _opr[0]->feedbackLevel((value >> 3) & 7); - _opr[1]->feedbackLevel(0); - _opr[2]->feedbackLevel(0); - _opr[3]->feedbackLevel(0); - } else if (l == 4) { - // stereo, LFO sensitivity - _enableLeft = value & 0x80 ? true : false; - _enableRight = value & 0x40 ? true : false; - uint8 ams = (value & 0x3F) >> 3; - if (ams) - warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)"); - uint8 fms = value & 3; - if (fms) - warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)"); - } - break; - - default: - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress); - break; - } } bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { @@ -2167,7 +1982,7 @@ bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { for (int i = 0; i < 4; i++) { // set release rate for each operator - writeReg(reg, 0x0f); + _drv->writeReg(_part, reg, 0x0f); reg += 4; } @@ -2176,13 +1991,13 @@ bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { // write registers 0x30 to 0x8f for (int i = 0; i < 6; i++) { - writeReg(reg, tptr[0]); + _drv->writeReg(_part, reg, tptr[0]); reg += 4; - writeReg(reg, tptr[2]); + _drv->writeReg(_part, reg, tptr[2]); reg += 4; - writeReg(reg, tptr[1]); + _drv->writeReg(_part, reg, tptr[1]); reg += 4; - writeReg(reg, tptr[3]); + _drv->writeReg(_part, reg, tptr[3]); reg += 4; tptr += 4; } @@ -2190,7 +2005,7 @@ bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { reg = _regOffset + 0xB0; _algorithm = tptr[0] & 7; // set feedback and algorithm - writeReg(reg, tptr[0]); + _drv->writeReg(_part, reg, tptr[0]); setOutputLevel(); return true; @@ -2244,22 +2059,22 @@ bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) { return true; } -bool TownsPC98_OpnChannel::control_f7_setupPitchWheel(uint8 para) { - _ptchWhlInitDelayHi = _dataPtr[0]; - _ptchWhlInitDelayLo = para; - _ptchWhlModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1); - _ptchWhlDuration = _dataPtr[3]; +bool TownsPC98_OpnChannel::control_f7_setupVibrato(uint8 para) { + _vbrInitDelayHi = _dataPtr[0]; + _vbrInitDelayLo = para; + _vbrModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1); + _vbrDuration = _dataPtr[3]; _dataPtr += 4; - _flags = (_flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF | CHS_RECALCFREQ; + _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF | CHS_RECALCFREQ; return true; } -bool TownsPC98_OpnChannel::control_f8_togglePitchWheel(uint8 para) { +bool TownsPC98_OpnChannel::control_f8_toggleVibrato(uint8 para) { if (para == 0x10) { if (*_dataPtr++) { - _flags = (_flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF; + _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF; } else { - _flags |= CHS_PITCHWHEELOFF; + _flags |= CHS_VBROFF; } } else { /* NOT IMPLEMENTED @@ -2273,7 +2088,7 @@ bool TownsPC98_OpnChannel::control_f8_togglePitchWheel(uint8 para) { } bool TownsPC98_OpnChannel::control_fa_writeReg(uint8 para) { - writeReg(para, *_dataPtr++); + _drv->writeReg(_part, para, *_dataPtr++); return true; } @@ -2349,8 +2164,8 @@ void TownsPC98_OpnChannelSSG::init() { Control(f4_setAlgorithm), Control(f5_setTempo), Control(f6_repeatSection), - Control(f7_setupPitchWheel), - Control(f8_togglePitchWheel), + Control(f7_setupVibrato), + Control(f8_toggleVibrato), Control(f9_loadCustomPatch), Control(fa_writeReg), Control(fb_incOutLevel), @@ -2368,7 +2183,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { if (_flags & CHS_EOT) return; - _drv->_regProtectionFlag = (_flags & CHS_PROTECT) ? true : false; + _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false); if (!_hold && _ticksLeft == _keyOffTime) nextShape(); @@ -2463,19 +2278,19 @@ void TownsPC98_OpnChannelSSG::processFrequency() { _frequency = ((const uint16*)_drv->_opnFreqTableSSG)[_frqBlockMSB & 0x0f] + _frqLSB; uint16 f = _frequency >> _block; - writeReg(_regOffset << 1, f & 0xff); - writeReg((_regOffset << 1) + 1, f >> 8); + _drv->writeReg(_part, _regOffset << 1, f & 0xff); + _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8); - setupPitchWheel(); + setupVibrato(); } - if (!(_flags & (CHS_EOT | CHS_PITCHWHEELOFF | CHS_SSGOFF))) { - if (!processPitchWheel()) + if (!(_flags & (CHS_EOT | CHS_VBROFF | CHS_SSGOFF))) { + if (!processVibrato()) return; uint16 f = _frequency >> _block; - writeReg(_regOffset << 1, f & 0xff); - writeReg((_regOffset << 1) + 1, f >> 8); + _drv->writeReg(_part, _regOffset << 1, f & 0xff); + _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8); } } @@ -2501,10 +2316,10 @@ void TownsPC98_OpnChannelSSG::keyOn() { t = (t << (_regOffset + 1)) | (t >> (7 - _regOffset)); if (!(_algorithm & 0x80)) - writeReg(6, _algorithm & 0x7f); + _drv->writeReg(_part, 6, _algorithm & 0x7f); - uint8 e = (_drv->_ssg->readReg(7) & c) | t; - writeReg(7, e); + uint8 e = (_drv->readSSGStatus() & c) | t; + _drv->writeReg(_part, 7, e); } void TownsPC98_OpnChannelSSG::protect() { @@ -2514,14 +2329,14 @@ void TownsPC98_OpnChannelSSG::protect() { void TownsPC98_OpnChannelSSG::restore() { _flags &= ~CHS_PROTECT; keyOn(); - writeReg(8 + _regOffset, _ssgTl); + _drv->writeReg(_part, 8 + _regOffset, _ssgTl); uint16 f = _frequency >> _block; - writeReg(_regOffset << 1, f & 0xff); - writeReg((_regOffset << 1) + 1, f >> 8); + _drv->writeReg(_part, _regOffset << 1, f & 0xff); + _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8); } void TownsPC98_OpnChannelSSG::loadData(uint8 *data) { - _drv->_regProtectionFlag = (_flags & CHS_PROTECT) ? true : false; + _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false); TownsPC98_OpnChannel::loadData(data); setOutputLevel(0); _algorithm = 0x80; @@ -2533,7 +2348,7 @@ void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) { if (newTl == _ssgTl) return; _ssgTl = newTl; - writeReg(8 + _regOffset, _ssgTl); + _drv->writeReg(_part, 8 + _regOffset, _ssgTl); } void TownsPC98_OpnChannelSSG::fadeStep() { @@ -2622,7 +2437,7 @@ bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) { } void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { - _flags = CHS_ALL_BUT_EOT; + _flags = CHS_ALLOFF; _ticksLeft = 1; _dataPtr = data; _ssgTl = 0xff; @@ -2640,7 +2455,7 @@ void TownsPC98_OpnChannelPCM::init() { #define Control(x) &TownsPC98_OpnChannelPCM::control_##x static const ControlEventFunc ctrlEventsPCM[] = { Control(dummy), - Control(f1_pcmStart), + Control(f1_prcStart), Control(dummy), Control(dummy), Control(dummy), @@ -2662,7 +2477,7 @@ void TownsPC98_OpnChannelPCM::init() { } void TownsPC98_OpnChannelPCM::loadData(uint8 *data) { - _flags = (_flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; + _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF; _ticksLeft = 1; _dataPtr = data; _totalLevel = 0x7F; @@ -2683,7 +2498,7 @@ void TownsPC98_OpnChannelPCM::processEvents() { if (cmd == 0x80) { loop = false; } else if (cmd < 0xf0) { - writeReg(0x10, cmd); + _drv->writeReg(_part, 0x10, cmd); } else if (!processControlEvent(cmd)) { return; } @@ -2697,16 +2512,9 @@ bool TownsPC98_OpnChannelPCM::processControlEvent(uint8 cmd) { return (this->*controlEvents[cmd & 0x0f])(para); } -void TownsPC98_OpnChannelPCM::reset() { - TownsPC98_OpnChannel::reset(); - - if (_drv->_pcm) - _drv->_pcm->reset(); -} - -bool TownsPC98_OpnChannelPCM::control_f1_pcmStart(uint8 para) { +bool TownsPC98_OpnChannelPCM::control_f1_prcStart(uint8 para) { _totalLevel = para; - writeReg(0x11, para); + _drv->writeReg(_part, 0x11, para); return true; } @@ -2720,15 +2528,31 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { // quit parsing for active channel --_dataPtr; _flags |= CHS_EOT; - _drv->_finishedPCMFlag |= _idFlag; + _drv->_finishedRhythmFlag |= _idFlag; return false; } } TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0), - _tleTable(0), _regIndex(_reg), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0) { - memset(_reg, 0, 16); + _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0) { memset(_channels, 0, sizeof(Channel) * 3); + + static uint8 *const reg [] = { + &_channels[0].frqL, + &_channels[0].frqH, + &_channels[1].frqL, + &_channels[1].frqH, + &_channels[2].frqL, + &_channels[2].frqH, + &_noiseGenerator, + &_chanEnable, + &_channels[0].vol, + &_channels[1].vol, + &_channels[2].vol, + }; + + _reg = reg; + reset(); } @@ -2777,7 +2601,6 @@ void TownsPC98_OpnSquareSineSource::reset() { _outN = 1; _updateRequest = -1; _nTick = _evpUpdateCnt = 0; - _regIndex = _reg; _evpTimer = 0x1f; _pReslt = 0x1f; _attack = 0; @@ -2796,24 +2619,24 @@ void TownsPC98_OpnSquareSineSource::reset() { writeReg(7, 0xbf, true); } -uint8 TownsPC98_OpnSquareSineSource::readReg(uint8 address) { - return _reg[address]; -} - void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool force) { - _regIndex = &_reg[address]; - int o = _regIndex - _reg; - if (!force && (o == 13 || *_regIndex != value)) { - if (_updateRequest == 31) { + if (address > 10 || *_reg[address] == value) { + if ((address == 11 || address == 12 || address == 13) && value) + warning("TownsPC98_OpnSquareSineSource: unsupported reg address: %d", address); + return; + } + + if (!force) { + if (_updateRequest == 31) { warning("TownsPC98_OpnSquareSineSource: event buffer overflow"); _updateRequest = -1; } _updateRequestBuf[++_updateRequest] = value; - _updateRequestBuf[++_updateRequest] = o; + _updateRequestBuf[++_updateRequest] = address; return; } - *_regIndex = value; + *_reg[address] = value; } void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { @@ -2825,7 +2648,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { while (_timer > 0x5B8D80) { _timer -= 0x5B8D80; - if (++_nTick >= (_reg[6] & 0x1f)) { + if (++_nTick >= (_noiseGenerator & 0x1f)) { if ((_rand + 1) & 2) _outN ^= 1; @@ -2834,15 +2657,15 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { } for (int ii = 0; ii < 3; ii++) { - if (++_channels[ii].tick >= (((_reg[ii * 2 + 1] & 0x0f) << 8) | _reg[ii * 2])) { + if (++_channels[ii].tick >= (((_channels[ii].frqH & 0x0f) << 8) | _channels[ii].frqL)) { _channels[ii].tick = 0; _channels[ii].smp ^= 1; } - _channels[ii].out = (_channels[ii].smp | ((_reg[7] >> ii) & 1)) & (_outN | ((_reg[7] >> (ii + 3)) & 1)); + _channels[ii].out = (_channels[ii].smp | ((_chanEnable >> ii) & 1)) & (_outN | ((_chanEnable >> (ii + 3)) & 1)); } if (_evpUpdate) { - if (++_evpUpdateCnt >= ((_reg[12] << 8) | _reg[11])) { + if (++_evpUpdateCnt >= 0) { _evpUpdateCnt = 0; if (--_evpTimer < 0) { @@ -2861,10 +2684,10 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { int32 finOut = 0; for (int ii = 0; ii < 3; ii++) { - if ((_reg[ii + 8] >> 4) & 1) + if ((_channels[ii].vol >> 4) & 1) finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; else - finOut += _tlTable[_channels[ii].out ? (_reg[ii + 8] & 0x0f) : 0]; + finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; } finOut /= 2; @@ -2884,29 +2707,60 @@ void TownsPC98_OpnSquareSineSource::updatesRegs() { TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) : _tickLength(timerbase * 2), _timer(0), _ready(false) { - memset(_pcmInstr, 0, sizeof(PcmInstrument) * 6); + + memset(_rhChan, 0, sizeof(RhtChannel) * 6); + static uint8 *const reg [] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + &_rhChan[0].startPosL, + &_rhChan[1].startPosL, + &_rhChan[2].startPosL, + &_rhChan[3].startPosL, + &_rhChan[4].startPosL, + &_rhChan[5].startPosL, + &_rhChan[0].startPosH, + &_rhChan[1].startPosH, + &_rhChan[2].startPosH, + &_rhChan[3].startPosH, + &_rhChan[4].startPosH, + &_rhChan[5].startPosH, + &_rhChan[0].endPosL, + &_rhChan[1].endPosL, + &_rhChan[2].endPosL, + &_rhChan[3].endPosL, + &_rhChan[4].endPosL, + &_rhChan[5].endPosL, + &_rhChan[0].endPosH, + &_rhChan[1].endPosH, + &_rhChan[2].endPosH, + &_rhChan[3].endPosH, + &_rhChan[4].endPosH, + &_rhChan[5].endPosH, + }; + + _reg = reg; } -void TownsPC98_OpnPercussionSource::init(const uint8 *pcmData) { +void TownsPC98_OpnPercussionSource::init(const uint8 *instrData) { if (_ready) { reset(); return; } - const uint8 *start = pcmData; + const uint8 *start = instrData; const uint8 *pos = start; - if (pcmData) { + if (instrData) { for (int i = 0; i < 6; i++) { - _pcmInstr[i].data = start + READ_BE_UINT16(pos); + _rhChan[i].data = start + READ_BE_UINT16(pos); pos += 2; - _pcmInstr[i].size = READ_BE_UINT16(pos); + _rhChan[i].size = READ_BE_UINT16(pos); pos += 2; } reset(); _ready = true; } else { - memset(_pcmInstr, 0, sizeof(PcmInstrument) * 6); + memset(_rhChan, 0, sizeof(RhtChannel) * 6); _ready = false; } } @@ -2915,10 +2769,8 @@ void TownsPC98_OpnPercussionSource::reset() { _timer = 0; _totalLevel = 63; - memset(_regs, 0, 48); - for (int i = 0; i < 6; i++) { - PcmInstrument *s = &_pcmInstr[i]; + RhtChannel *s = &_rhChan[i]; s->pos = s->start = s->data; s->end = s->data + s->size; s->active = false; @@ -2927,6 +2779,7 @@ void TownsPC98_OpnPercussionSource::reset() { s->decStep = 1; s->decState = 0; s->samples[0] = s->samples[1] = 0; + s->startPosH = s->startPosL = s->endPosH = s->endPosL = 0; } } @@ -2937,20 +2790,21 @@ void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) { uint8 h = address >> 4; uint8 l = address & 15; - _regs[address] = value; + if (address > 15) + *_reg[address] = value; if (address == 0) { if (value & 0x80) { //key off for (int i = 0; i < 6; i++) { if ((value >> i) & 1) - _pcmInstr[i].active = false; + _rhChan[i].active = false; } } else { //key on for (int i = 0; i < 6; i++) { if ((value >> i) & 1) { - PcmInstrument *s = &_pcmInstr[i]; + RhtChannel *s = &_rhChan[i]; s->pos = s->start; s->active = true; s->out = 0; @@ -2964,20 +2818,20 @@ void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) { // total level _totalLevel = (value & 63) ^ 63; for (int i = 0; i < 6; i++) - recalcOuput(&_pcmInstr[i]); + recalcOuput(&_rhChan[i]); } else if (!h && l & 8) { // instrument level l &= 7; - _pcmInstr[l].level = (value & 0x1f) ^ 0x1f; - recalcOuput(&_pcmInstr[l]); + _rhChan[l].level = (value & 0x1f) ^ 0x1f; + recalcOuput(&_rhChan[l]); } else if (h & 3) { l &= 7; if (h == 1) { // set start offset - _pcmInstr[l].start = _pcmInstr[l].data + ((_regs[24 + l] * 256 + _regs[16 + l]) << 8); + _rhChan[l].start = _rhChan[l].data + ((_rhChan[l].startPosH << 8 | _rhChan[l].startPosL) << 8); } else if (h == 2) { // set end offset - _pcmInstr[l].end = _pcmInstr[l].data + ((_regs[40 + l] * 256 + _regs[32 + l]) << 8) + 255; + _rhChan[l].end = _rhChan[l].data + ((_rhChan[l].endPosH << 8 | _rhChan[l].endPosL) << 8) + 255; } } } @@ -2992,7 +2846,7 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { _timer -= 0x5B8D80; for (int ii = 0; ii < 6; ii++) { - PcmInstrument *s = &_pcmInstr[ii]; + RhtChannel *s = &_rhChan[ii]; if (s->active) { recalcOuput(s); if (s->decStep) { @@ -3008,25 +2862,25 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { int32 finOut = 0; for (int ii = 0; ii < 6; ii++) { - if (_pcmInstr[ii].active) - finOut += _pcmInstr[ii].out; + if (_rhChan[ii].active) + finOut += _rhChan[ii].out; } - finOut = (finOut * 7); + finOut *= 7; buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } } -void TownsPC98_OpnPercussionSource::recalcOuput(PcmInstrument *ins) { +void TownsPC98_OpnPercussionSource::recalcOuput(RhtChannel *ins) { uint32 s = _totalLevel + ins->level; uint32 x = s > 62 ? 0 : (1 + (s >> 3)); int32 y = s > 62 ? 0 : (15 - (s & 7)); ins->out = ((ins->samples[ins->decStep] * y) >> x) & ~3; } -void TownsPC98_OpnPercussionSource::advanceInput(PcmInstrument *ins) { +void TownsPC98_OpnPercussionSource::advanceInput(RhtChannel *ins) { static const int8 adjustIndex[] = {-1, -1, -1, -1, 2, 5, 7, 9 }; static const int16 stepTable[] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, @@ -3044,38 +2898,488 @@ void TownsPC98_OpnPercussionSource::advanceInput(PcmInstrument *ins) { } } -TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : +TownsPC98_OpnCore::TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type) : _mixer(mixer), + _chanInternal(0), _ssg(0), _prc(0), + _numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPercussion(type == OD_TYPE86 ? true : false), + _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), + _baserate(55125.0f / (float)mixer->getOutputRate()), + _regProtectionFlag(false), _ready(false) { + + memset(&_timers[0], 0, sizeof(OpnTimer)); + memset(&_timers[1], 0, sizeof(OpnTimer)); + _timers[0].cb = &TownsPC98_OpnCore::timerCallbackA; + _timers[1].cb = &TownsPC98_OpnCore::timerCallbackB; + _timerbase = (uint32)(_baserate * 1000000.0f); +} + +TownsPC98_OpnCore::~TownsPC98_OpnCore() { + _mixer->stopHandle(_soundHandle); + delete _ssg; + delete _prc; + delete [] _chanInternal; + + delete [] _oprRates; + delete [] _oprRateshift; + delete [] _oprFrq; + delete [] _oprAttackDecay; + delete [] _oprSinTbl; + delete [] _oprLevelOut; + delete [] _oprDetune; +} + +bool TownsPC98_OpnCore::init() { + if (_ready) { + reset(); + return true; + } - _channels(0), _ssgChannels(0), _sfxChannels(0), _pcmChannel(0), _ssg(0), _pcm(0), + generateTables(); + TownsPC98_OpnOperator **opr = new TownsPC98_OpnOperator*[_numChan << 2]; + for (int i = 0; i < (_numChan << 2); i++) + opr[i] = new TownsPC98_OpnOperator(_timerbase, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune); + + _chanInternal = new ChanInternal[_numChan]; + for (int i = 0; i < _numChan; i++) { + memset(&_chanInternal[i], 0, sizeof(ChanInternal)); + _chanInternal[i].opr = &opr[i << 2]; + } + + if (_numSSG) { + _ssg = new TownsPC98_OpnSquareSineSource(_timerbase); + _ssg->init(&_ssgTables[0], &_ssgTables[16]); + } + + if (_hasPercussion) { + _prc = new TownsPC98_OpnPercussionSource(_timerbase); + _prc->init(_percussionData); + } + + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, + &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); + + _ready = true; + + return true; +} + +void TownsPC98_OpnCore::reset() { + for (int i = 0; i < _numChan; i++) { + for (int ii = 0; ii < 4; ii++) + _chanInternal[i].opr[ii]->reset(); + memset(&_chanInternal[i].feedbuf, 0, 3); + _chanInternal[i].algorithm = 0; + _chanInternal[i].frqTemp = 0; + _chanInternal[i].enableLeft = _chanInternal[i].enableRight = true; + _chanInternal[i].updateEnvelopeParameters = false; + } + + writeReg(0, 27, 0x33); + + if (_ssg) + _ssg->reset(); + + if (_prc) + _prc->reset(); +} + +void TownsPC98_OpnCore::writeReg(uint8 part, uint8 regAddress, uint8 value) { + if (_regProtectionFlag || !_ready) + return; + + static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; + + uint8 h = regAddress & 0xf0; + uint8 l = (regAddress & 0x0f); + + ChanInternal *c = &_chanInternal[(h < 0x30) ? ((value & 3) + ((value & 4) ? 3 : 0)) : ((l & 3) + 3 * part)]; + TownsPC98_OpnOperator **co = c->opr; + TownsPC98_OpnOperator *o = (h < 0x30) ? 0 : c->opr[oprOrdr[(l - (l & 3)) >> 2]]; + + switch (h) { + case 0x00: + // ssg + if (_ssg) + _ssg->writeReg(regAddress, value); + break; + case 0x10: + // pcm rhythm channel + if (_prc) + _prc->writeReg(regAddress - 0x10, value); + break; + case 0x20: + if (l == 8) { + // Key on/off + for (int i = 0; i < 4; i++) { + if ((value >> (4 + i)) & 1) + co[i]->keyOn(); + else + co[i]->keyOff(); + } + } else if (l == 4) { + // Timer A + _timers[0].value = (_timers[0].value & 0xff00) | value; + } else if (l == 5) { + // Timer A + _timers[0].value = (_timers[0].value & 0xff) | (value << 8); + } else if (l == 6) { + // Timer B + _timers[1].value = value & 0xff; + } else if (l == 7) { + _timers[0].enabled = (value & 1) ? 1 : 0; + _timers[1].enabled = (value & 2) ? 1 : 0; + + float spc = (float)(0x400 - _timers[0].value) / _baserate; + _timers[0].smpPerCb = (int32) spc; + _timers[0].smpPerCbRem = (uint32) ((spc - (float)_timers[0].smpPerCb) * 1000000.0f); + + spc = (float)(0x100 - _timers[1].value) * 16.0f / _baserate; + _timers[1].smpPerCb = (int32) spc; + _timers[1].smpPerCbRem = (uint32) ((spc - (float)_timers[1].smpPerCb) * 1000000.0f); + + if (value & 10) { + _timers[0].smpTillCb = _timers[0].smpPerCb; + _timers[0].smpTillCbRem = _timers[0].smpTillCbRem; + } + + if (value & 20) { + _timers[1].smpTillCb = _timers[1].smpPerCb; + _timers[1].smpTillCbRem = _timers[1].smpTillCbRem; + } + } else if (l == 2) { + // LFO + warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)"); + } else if (l == 10 || l == 11) { + // DAC + warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)"); + } + break; + + case 0x30: + // detune, multiple + o->detune((value >> 4) & 7); + o->multiple(value & 0x0f); + c->updateEnvelopeParameters = true; + break; + + case 0x40: + // total level + o->totalLevel(value & 0x7f); + break; + + case 0x50: + // rate scaling, attack rate + o->attackRate(value & 0x1f); + if (o->scaleRate(value >> 6)) + c->updateEnvelopeParameters = true; + break; + + case 0x60: + // first decay rate, amplitude modulation + o->decayRate(value & 0x1f); + if (value & 0x80) + warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)"); + break; + + case 0x70: + // secondary decay rate + o->sustainRate(value & 0x1f); + break; + + case 0x80: + // secondary amplitude, release rate; + o->sustainLevel(value >> 4); + o->releaseRate(value & 0x0f); + break; + + case 0x90: + warning("TownsPC98_OpnDriver: TRYING TO SSG ENVELOPE SHAPES (NOT SUPPORTED)"); + break; + + case 0xa0: + // frequency + l &= ~3; + if (l == 0) { + c->frqTemp = (c->frqTemp & 0xff00) | value; + c->updateEnvelopeParameters = true; + for (int i = 0; i < 4; i++) + co[i]->frequency(c->frqTemp); + } else if (l == 4) { + c->frqTemp = (c->frqTemp & 0xff) | (value << 8); + } else if (l == 8) { + // Ch 3/6 special mode frq + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); + } else if (l == 12) { + // Ch 3/6 special mode frq + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); + } + break; + + case 0xb0: + l &= ~3; + if (l == 0) { + // feedback, _algorithm + co[0]->feedbackLevel((value >> 3) & 7); + c->algorithm = value & 7; + } else if (l == 4) { + // stereo, LFO sensitivity + c->enableLeft = value & 0x80 ? true : false; + c->enableRight = value & 0x40 ? true : false; + uint8 ams = (value & 0x3F) >> 3; + if (ams) + warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)"); + uint8 fms = value & 3; + if (fms) + warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)"); + } + break; + + default: + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress); + break; + } +} + +int inline TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) { + memset(buffer, 0, sizeof(int16) * numSamples); + int32 *tmp = new int32[numSamples]; + int32 *tmpStart = tmp; + memset(tmp, 0, sizeof(int32) * numSamples); + int32 samplesLeft = numSamples >> 1; + + while (samplesLeft) { + + int32 render = samplesLeft; + + for (int i = 0; i < 2; i++) { + if (_timers[i].enabled && _timers[i].cb) { + if (!_timers[i].smpTillCb) { + (this->*_timers[i].cb)(); + _timers[i].smpTillCb = _timers[i].smpPerCb; + + _timers[i].smpTillCbRem += _timers[i].smpPerCbRem; + if (_timers[i].smpTillCbRem >= _timerbase) { + _timers[i].smpTillCb++; + _timers[i].smpTillCbRem -= _timerbase; + } + } + render = MIN(render, _timers[i].smpTillCb); + } + } + + samplesLeft -= render; + + for (int i = 0; i < 2; i++) { + if (_timers[i].enabled && _timers[i].cb) { + _timers[i].smpTillCb -= render; + } + } + + nextTick(tmp, render); + + if (_ssg) + _ssg->nextTick(tmp, render); + if (_prc) + _prc->nextTick(tmp, render); + + for (int i = 0; i < render; ++i) { + int32 l = CLIP(tmp[i << 1], -32767, 32767); + buffer[i << 1] = (int16) l; + int32 r = CLIP(tmp[(i << 1) + 1], -32767, 32767); + buffer[(i << 1) + 1] = (int16) r; + } + + buffer += (render << 1); + tmp += (render << 1); + } + + delete [] tmpStart; + return numSamples; +} + +void TownsPC98_OpnCore::generateTables() { + delete [] _oprRates; + _oprRates = new uint8[128]; + memset(_oprRates, 0x90, 32); + uint8 *dst = (uint8*) _oprRates + 32; + for (int i = 0; i < 48; i += 4) + WRITE_BE_UINT32(dst + i, 0x00081018); + dst += 48; + for (uint8 i = 0; i < 16; i ++) { + uint8 v = (i < 12) ? i : 12; + *dst++ = ((4 + v) << 3); + } + memset(dst, 0x80, 32); + + delete [] _oprRateshift; + _oprRateshift = new uint8[128]; + memset(_oprRateshift, 0, 128); + dst = (uint8*) _oprRateshift + 32; + for (int i = 11; i; i--) { + memset(dst, i, 4); + dst += 4; + } + + delete [] _oprFrq; + _oprFrq = new uint32[0x1000]; + for (uint32 i = 0; i < 0x1000; i++) + _oprFrq[i] = (uint32)(_baserate * (float)(i << 11)); + + delete [] _oprAttackDecay; + _oprAttackDecay = new uint8[152]; + memset(_oprAttackDecay, 0, 152); + for (int i = 0; i < 36; i++) + WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]); + + delete [] _oprSinTbl; + _oprSinTbl = new uint32[1024]; + for (int i = 0; i < 1024; i++) { + double val = sin((double) (((i << 1) + 1) * PI / 1024.0)); + double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0; + int32 i_dcb = (int32)(2.0 * d_dcb); + i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1); + _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1); + } + + delete [] _oprLevelOut; + _oprLevelOut = new int32[0x1a00]; + for (int i = 0; i < 256; i++) { + double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i))); + int32 val_int = ((int32) val) >> 4; + _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2; + _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1]; + for (int ii = 1; ii < 13; ii++) { + _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii; + _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)]; + } + } + + uint8 *dtt = new uint8[128]; + memset(dtt, 0, 36); + memset(dtt + 36, 1, 8); + memcpy(dtt + 44, _detSrc, 84); + + delete [] _oprDetune; + _oprDetune = new int32[256]; + for (int i = 0; i < 128; i++) { + _oprDetune[i] = (int32) ((float)dtt[i] * _baserate * 64.0); + _oprDetune[i + 128] = -_oprDetune[i]; + } + + delete [] dtt; +} + +void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) { + if (!_ready) + return; + + for (int i = 0; i < _numChan; i++) { + TownsPC98_OpnOperator **o = _chanInternal[i].opr; + + if (_chanInternal[i].updateEnvelopeParameters) { + _chanInternal[i].updateEnvelopeParameters = false; + for (int ii = 0; ii < 4 ; ii++) + o[ii]->updatePhaseIncrement(); + } + + for (uint32 ii = 0; ii < bufferSize ; ii++) { + int32 phbuf1, phbuf2, output; + phbuf1 = phbuf2 = output = 0; + + int32 *leftSample = &buffer[ii * 2]; + int32 *rightSample = &buffer[ii * 2 + 1]; + int32 *del = &_chanInternal[i].feedbuf[2]; + int32 *feed = _chanInternal[i].feedbuf; + + switch (_chanInternal[i].algorithm) { + case 0: + o[0]->generateOutput(0, feed, phbuf1); + o[2]->generateOutput(*del, 0, phbuf2); + *del = 0; + o[1]->generateOutput(phbuf1, 0, *del); + o[3]->generateOutput(phbuf2, 0, output); + break; + case 1: + o[0]->generateOutput(0, feed, phbuf1); + o[2]->generateOutput(*del, 0, phbuf2); + o[1]->generateOutput(0, 0, phbuf1); + o[3]->generateOutput(phbuf2, 0, output); + *del = phbuf1; + break; + case 2: + o[0]->generateOutput(0, feed, phbuf2); + o[2]->generateOutput(*del, 0, phbuf2); + o[1]->generateOutput(0, 0, phbuf1); + o[3]->generateOutput(phbuf2, 0, output); + *del = phbuf1; + break; + case 3: + o[0]->generateOutput(0, feed, phbuf2); + o[2]->generateOutput(0, 0, *del); + o[1]->generateOutput(phbuf2, 0, phbuf1); + o[3]->generateOutput(*del, 0, output); + *del = phbuf1; + break; + case 4: + o[0]->generateOutput(0, feed, phbuf1); + o[2]->generateOutput(0, 0, phbuf2); + o[1]->generateOutput(phbuf1, 0, output); + o[3]->generateOutput(phbuf2, 0, output); + *del = 0; + break; + case 5: + *del = feed[1]; + o[0]->generateOutput(-1, feed, phbuf1); + o[2]->generateOutput(*del, 0, output); + o[1]->generateOutput(*del, 0, output); + o[3]->generateOutput(*del, 0, output); + break; + case 6: + o[0]->generateOutput(0, feed, phbuf1); + o[2]->generateOutput(0, 0, output); + o[1]->generateOutput(phbuf1, 0, output); + o[3]->generateOutput(0, 0, output); + *del = 0; + break; + case 7: + o[0]->generateOutput(0, feed, output); + o[2]->generateOutput(0, 0, output); + o[1]->generateOutput(0, 0, output); + o[3]->generateOutput(0, 0, output); + *del = 0; + break; + }; + + int32 finOut = ((output * 7) / 2); + + if (_chanInternal[i].enableLeft) + *leftSample += finOut; + + if (_chanInternal[i].enableRight) + *rightSample += finOut; + } + } +} + +TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : TownsPC98_OpnCore(mixer, type), + _channels(0), _ssgChannels(0), _sfxChannels(0), _rhythmChannel(0), _trackPtr(0), _sfxData(0), _sfxOffs(0), _ssgPatches(0), - _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), _opnFreqTableSSG(_drvTables + 252), - _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 228)), - _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), + _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 108), _opnFreqTableSSG(_drvTables + 132), + _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 84)), - _numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPCM(type == OD_TYPE86 ? true : false), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0), _updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0), - _updatePCMFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedPCMFlag(0), + _updateRhythmFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedRhythmFlag(0), _updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0), - _baserate(55125.0f / (float)getRate()), - _samplesTillMusicCallback(0), _samplesTillSfxCallback(0), - _samplesTillMusicCallbackRemainder(0), _samplesTillSfxCallbackRemainder(0), _musicTickCounter(0), _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) { - - _timerbase = (uint32)(_baserate * 1000000.0f); - setMusicTempo(84); - setSfxTempo(654); } TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { - _mixer->stopHandle(_soundHandle); - if (_channels) { for (int i = 0; i < _numChan; i++) delete _channels[i]; @@ -3094,19 +3398,9 @@ TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { delete [] _sfxChannels; } - if (_pcmChannel) - delete _pcmChannel; - - delete _ssg; - delete _pcm; + if (_rhythmChannel) + delete _rhythmChannel; - delete [] _oprRates; - delete [] _oprRateshift; - delete [] _oprFrq; - delete [] _oprAttackDecay; - delete [] _oprSinTbl; - delete [] _oprLevelOut; - delete [] _oprDetune; delete [] _ssgPatches; } @@ -3116,15 +3410,8 @@ bool TownsPC98_OpnDriver::init() { return true; } - generateTables(); + TownsPC98_OpnCore::init(); - if (_channels) { - for (int i = 0; i < _numChan; i++) { - if (_channels[i]) - delete _channels[i]; - } - delete [] _channels; - } _channels = new TownsPC98_OpnChannel*[_numChan]; for (int i = 0; i < _numChan; i++) { int ii = i * 6; @@ -3133,27 +3420,9 @@ bool TownsPC98_OpnDriver::init() { _channels[i]->init(); } - if (_ssgChannels) { - for (int i = 0; i < _numSSG; i++) { - if (_ssgChannels[i]) - delete _ssgChannels[i]; - } - delete [] _ssgChannels; - } - - if (_sfxChannels) { - for (int i = 0; i < 2; i++) { - if (_sfxChannels[i]) - delete _sfxChannels[i]; - } - delete [] _sfxChannels; - } - if (_numSSG) { - _ssg = new TownsPC98_OpnSquareSineSource(_timerbase); - _ssg->init(&_ssgTables[0], &_ssgTables[16]); _ssgPatches = new uint8[256]; - memcpy(_ssgPatches, _drvTables + 244, 256); + memcpy(_ssgPatches, _drvTables + 156, 256); _ssgChannels = new TownsPC98_OpnChannelSSG*[_numSSG]; for (int i = 0; i < _numSSG; i++) { @@ -3168,82 +3437,21 @@ bool TownsPC98_OpnDriver::init() { int ii = (i + 1) * 6; _sfxChannels[i] = new TownsPC98_OpnSfxChannel(this, _drvTables[ii], _drvTables[ii + 1], _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]); - _sfxChannels[i]->init(); - } - } - - if (_hasPCM) { - _pcm = new TownsPC98_OpnPercussionSource(_timerbase); - _pcm->init(); - - delete _pcmChannel; - _pcmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1); - _pcmChannel->init(); - } - - _mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); - - _ready = true; - return true; -} - -int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) { - memset(buffer, 0, sizeof(int16) * numSamples); - int32 *tmp = new int32[numSamples]; - int32 *tmpStart = tmp; - memset(tmp, 0, sizeof(int32) * numSamples); - int32 samplesLeft = numSamples >> 1; - - while (samplesLeft) { - if (!_samplesTillMusicCallback) { - musicCallback(); - _samplesTillMusicCallback = _samplesPerMusicCallback; - - _samplesTillMusicCallbackRemainder += _samplesPerMusicCallbackRemainder; - if (_samplesTillMusicCallbackRemainder >= _timerbase) { - _samplesTillMusicCallback++; - _samplesTillMusicCallbackRemainder -= _timerbase; - } - } - - if (!_samplesTillSfxCallback) { - sfxCallback(); - _samplesTillSfxCallback = _samplesPerSfxCallback; - - _samplesTillSfxCallbackRemainder += _samplesPerSfxCallbackRemainder; - if (_samplesTillSfxCallbackRemainder >= _timerbase) { - _samplesTillSfxCallback++; - _samplesTillSfxCallbackRemainder -= _timerbase; - } - } - - int32 render = MIN(samplesLeft, MIN(_samplesTillSfxCallback, _samplesTillMusicCallback)); - samplesLeft -= render; - - _samplesTillMusicCallback -= render; - _samplesTillSfxCallback -= render; - - nextTick(tmp, render); - - if (_ssg) - _ssg->nextTick(tmp, render); - if (_pcm) - _pcm->nextTick(tmp, render); - - for (int i = 0; i < render; ++i) { - int32 l = CLIP(tmp[i << 1], -32767, 32767); - buffer[i << 1] = (int16) l; - int32 r = CLIP(tmp[(i << 1) + 1], -32767, 32767); - buffer[(i << 1) + 1] = (int16) r; + _sfxChannels[i]->init(); } + } - buffer += (render << 1); - tmp += (render << 1); + if (_hasPercussion) { + _rhythmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1); + _rhythmChannel->init(); } - delete [] tmpStart; - return numSamples; + setMusicTempo(84); + setSfxTempo(654); + + _ready = true; + + return true; } void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) { @@ -3278,17 +3486,17 @@ void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) { src_a += 2; } - if (_hasPCM) { - _pcmChannel->loadData(data + READ_LE_UINT16(src_a)); + if (_hasPercussion) { + _rhythmChannel->loadData(data + READ_LE_UINT16(src_a)); src_a += 2; } - _regProtectionFlag = false; + toggleRegProtection(false); _patches = src_a + 4; - _finishedChannelsFlag = _finishedSSGFlag = _finishedPCMFlag = 0; + _finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0; - _musicPlaying = (loadPaused ? false : true); + _musicPlaying = (loadPaused ? false : true); unlock(); } @@ -3321,21 +3529,22 @@ void TownsPC98_OpnDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { void TownsPC98_OpnDriver::reset() { lock(); + TownsPC98_OpnCore::reset(); + for (int i = 0; i < _numChan; i++) _channels[i]->reset(); for (int i = 0; i < _numSSG; i++) _ssgChannels[i]->reset(); - if (_ssg) { + if (_numSSG) { for (int i = 0; i < 2; i++) _sfxChannels[i]->reset(); - memcpy(_ssgPatches, _drvTables + 276, 256); - _ssg->reset(); + memcpy(_ssgPatches, _drvTables + 156, 256); } - if (_pcmChannel) - _pcmChannel->reset(); + if (_rhythmChannel) + _rhythmChannel->reset(); _musicPlaying = false; _sfxPlaying = false; @@ -3365,9 +3574,9 @@ void TownsPC98_OpnDriver::fadeStep() { if (!_fading) { _fading = 19; - if (_hasPCM) { - if (_updatePCMFlag & _pcmChannel->_idFlag) - _pcmChannel->reset(); + if (_hasPercussion) { + if (_updateRhythmFlag & _rhythmChannel->_idFlag) + _rhythmChannel->reset(); } } else { if (!--_fading) @@ -3377,7 +3586,7 @@ void TownsPC98_OpnDriver::fadeStep() { unlock(); } -void TownsPC98_OpnDriver::musicCallback() { +void TownsPC98_OpnDriver::timerCallbackB() { lock(); _sfxOffs = 0; @@ -3399,20 +3608,20 @@ void TownsPC98_OpnDriver::musicCallback() { } } - if (_hasPCM) - if (_updatePCMFlag & _pcmChannel->_idFlag) - _pcmChannel->processEvents(); + if (_hasPercussion) + if (_updateRhythmFlag & _rhythmChannel->_idFlag) + _rhythmChannel->processEvents(); } - _regProtectionFlag = false; + toggleRegProtection(false); - if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedPCMFlag == _updatePCMFlag) + if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag) _musicPlaying = false; unlock(); } -void TownsPC98_OpnDriver::sfxCallback() { +void TownsPC98_OpnDriver::timerCallbackA() { lock(); if (_sfxChannels && _sfxPlaying) { @@ -3438,92 +3647,15 @@ void TownsPC98_OpnDriver::sfxCallback() { unlock(); } -void TownsPC98_OpnDriver::nextTick(int32 *buffer, uint32 bufferSize) { - if (!_ready) - return; - - for (int i = 0; i < _numChan; i++) { - if (_channels[i]->_updateEnvelopeParameters) { - _channels[i]->_updateEnvelopeParameters = false; - _channels[i]->updateEnv(); - } - - for (uint32 ii = 0; ii < bufferSize ; ii++) - _channels[i]->generateOutput(buffer[ii * 2], - buffer[ii * 2 + 1], &_channels[i]->_feedbuf[2], _channels[i]->_feedbuf); - } +void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { + writeReg(0, 0x26, tempo); + writeReg(0, 0x27, 0x33); } -void TownsPC98_OpnDriver::generateTables() { - delete [] _oprRates; - _oprRates = new uint8[128]; - memset(_oprRates, 0x90, 32); - uint8 *dst = (uint8*) _oprRates + 32; - for (int i = 0; i < 48; i += 4) - WRITE_BE_UINT32(dst + i, 0x00081018); - dst += 48; - for (uint8 i = 0; i < 16; i ++) { - uint8 v = (i < 12) ? i : 12; - *dst++ = ((4 + v) << 3); - } - memset(dst, 0x80, 32); - - delete [] _oprRateshift; - _oprRateshift = new uint8[128]; - memset(_oprRateshift, 0, 128); - dst = (uint8*) _oprRateshift + 32; - for (int i = 11; i; i--) { - memset(dst, i, 4); - dst += 4; - } - - delete [] _oprFrq; - _oprFrq = new uint32[0x1000]; - for (uint32 i = 0; i < 0x1000; i++) - _oprFrq[i] = (uint32)(_baserate * (float)(i << 11)); - - delete [] _oprAttackDecay; - _oprAttackDecay = new uint8[152]; - memset(_oprAttackDecay, 0, 152); - for (int i = 0; i < 36; i++) - WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]); - - delete [] _oprSinTbl; - _oprSinTbl = new uint32[1024]; - for (int i = 0; i < 1024; i++) { - double val = sin((double) (((i << 1) + 1) * PI / 1024.0)); - double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0; - int32 i_dcb = (int32)(2.0 * d_dcb); - i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1); - _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1); - } - - delete [] _oprLevelOut; - _oprLevelOut = new int32[0x1a00]; - for (int i = 0; i < 256; i++) { - double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i))); - int32 val_int = ((int32) val) >> 4; - _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2; - _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1]; - for (int ii = 1; ii < 13; ii++) { - _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii; - _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)]; - } - } - - uint8 *dtt = new uint8[128]; - memset(dtt, 0, 36); - memset(dtt + 36, 1, 8); - memcpy(dtt + 44, _drvTables + 144, 84); - - delete [] _oprDetune; - _oprDetune = new int32[256]; - for (int i = 0; i < 128; i++) { - _oprDetune[i] = (int32) ((float)dtt[i] * _baserate * 64.0); - _oprDetune[i + 128] = -_oprDetune[i]; - } - - delete [] dtt; +void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { + writeReg(0, 0x24, tempo & 0xff); + writeReg(0, 0x25, tempo >> 8); + writeReg(0, 0x27, 0x33); } void TownsPC98_OpnDriver::startSoundEffect() { @@ -3538,17 +3670,77 @@ void TownsPC98_OpnDriver::startSoundEffect() { _sfxData = 0; } -void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { - float spc = (float)(0x100 - tempo) * 16.0f / _baserate; - _samplesPerMusicCallback = (int32) spc; - _samplesPerMusicCallbackRemainder = (uint32) ((spc - (float)_samplesPerMusicCallback) * 1000000.0f); -} +const uint8 TownsPC98_OpnDriver::_drvTables[] = { + // channel presets + 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x80, 0x01, 0x01, 0x00, 0x02, + 0x02, 0x80, 0x02, 0x02, 0x00, 0x04, + 0x00, 0x80, 0x03, 0x04, 0x01, 0x08, + 0x01, 0x80, 0x04, 0x05, 0x01, 0x10, + 0x02, 0x80, 0x05, 0x06, 0x01, 0x20, -void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { - float spc = (float)(0x400 - tempo) / _baserate; - _samplesPerSfxCallback = (int32) spc; - _samplesPerSfxCallbackRemainder = (uint32) ((spc - (float)_samplesPerSfxCallback) * 1000000.0f); -} + // control event size + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, + 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, + + // fmt level presets + 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38, + 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18, + 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90, + + // carriers + 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F, + + // pc98 level presets + 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, + 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, + 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90, + + // frequencies + 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02, + 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03, + 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04, + + // ssg frequencies + 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C, + 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09, + 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07, + + // ssg patch data + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, + 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00, + 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + + 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00, + 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00, + 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00, + 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00 +}; SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _sfxFileData(0), @@ -4061,40 +4253,19 @@ void SoundTownsPC98_v2::playSoundEffect(uint8 track) { // static resources -const uint8 TownsPC98_OpnDriver::_drvTables[] = { - // channel presets - 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, - 0x01, 0x80, 0x01, 0x01, 0x00, 0x02, - 0x02, 0x80, 0x02, 0x02, 0x00, 0x04, - 0x00, 0x80, 0x03, 0x04, 0x01, 0x08, - 0x01, 0x80, 0x04, 0x05, 0x01, 0x10, - 0x02, 0x80, 0x05, 0x06, 0x01, 0x20, - - // control event size - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, - 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, - - // fmt level presets - 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38, - 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18, - 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90, - - // carriers - 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F, - - // frequencies - 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02, - 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03, - 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04, - 0x00, 0x00, 0x00, 0x00, - - // unused - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +const uint32 TownsPC98_OpnCore::_adtStat[] = { + 0x00010001, 0x00010001, 0x00010001, 0x01010001, + 0x00010101, 0x00010101, 0x00010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010102, 0x01010102, + 0x01020102, 0x01020102, 0x01020202, 0x01020202, + 0x02020202, 0x02020202, 0x02020204, 0x02020204, + 0x02040204, 0x02040204, 0x02040404, 0x02040404, + 0x04040404, 0x04040404, 0x04040408, 0x04040408, + 0x04080408, 0x04080408, 0x04080808, 0x04080808, + 0x08080808, 0x08080808, 0x10101010, 0x10101010 +}; - // detune +const uint8 TownsPC98_OpnCore::_detSrc[] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, @@ -4105,67 +4276,10 @@ const uint8 TownsPC98_OpnDriver::_drvTables[] = { 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, - 0x16, 0x16, 0x16, 0x16, - - // pc98 level presets - 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, - 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, - 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90, - - // ssg frequencies - 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C, - 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09, - 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07, - - // ssg patch data - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00, - 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00, - 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - - 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00, - 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00, - 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00 -}; - -const uint32 TownsPC98_OpnDriver::_adtStat[] = { - 0x00010001, 0x00010001, 0x00010001, 0x01010001, - 0x00010101, 0x00010101, 0x00010101, 0x01010101, - 0x01010101, 0x01010101, 0x01010102, 0x01010102, - 0x01020102, 0x01020102, 0x01020202, 0x01020202, - 0x02020202, 0x02020202, 0x02020204, 0x02020204, - 0x02040204, 0x02040204, 0x02040404, 0x02040404, - 0x04040404, 0x04040404, 0x04040408, 0x04040408, - 0x04080408, 0x04080408, 0x04080808, 0x04080808, - 0x08080808, 0x08080808, 0x10101010, 0x10101010 + 0x16, 0x16, 0x16, 0x16 }; -const int TownsPC98_OpnDriver::_ssgTables[] = { +const int TownsPC98_OpnCore::_ssgTables[] = { 0x01202A, 0x0092D2, 0x006B42, 0x0053CB, 0x003DF8, 0x003053, 0x0022DA, 0x001A8C, 0x00129B, 0x000DC1, 0x000963, 0x0006C9, 0x000463, 0x0002FA, 0x0001B6, 0x0000FB, 0x0193B6, 0x01202A, 0x00CDB1, 0x0092D2, 0x007D7D, 0x006B42, 0x005ECD, 0x0053CB, @@ -4174,6 +4288,121 @@ const int TownsPC98_OpnDriver::_ssgTables[] = { 0x000575, 0x000463, 0x00039D, 0x0002FA, 0x000242, 0x0001B6, 0x00014C, 0x0000FB }; +const uint8 TownsPC98_OpnCore::_percussionData[] = { + 0,24,1,192,1,216,2,128,4,88,23,64,27,152,1,128,29,24,2,128,31,152,0,128,136,128,128,128,0,136,97,103,153,139,34,163,72,195,27,69,1,154,137,35,8,51,169,122,164,75,133,203,81,146,168,121,185,68,202,8,33,237,49,177,12,133,140,17,160,42,161,10,0,137,176, 57, + 233,41,160,136,235,65,177,137,128,26,164,28,3,157,51,137,1,152,113,161,40,146,115,192,56,5,169,66,161,56,1,50,145,59,39,168,97,1,160,57,7,153,50,153,32,2,25,129,32,20,186,66,129,24,153,164,142,130,169,153,26,242,138,217,9,128,204,58,209,172,40, 176, 141, + 128,155,144,203,139,0,235,9,177,172,0,185,168,138,25,240,59,211,139,19,176,90,160,17,26,132,41,1,5,25,3,50,144,115,147,42,39,152,41,3,56,193,105,130,155,66,200,26,19,218,154,49,201,171,138,176,251,139,185,172,136,189,139,145,207,41,160,171,152, 186, 139, + 186,141,128,218,171,51,217,170,56,163,12,4,155,81,147,42,37,152,32,54,136,49,50,48,37,32,69,0,17,50,50,83,2,16,68,20,8,66,4,154,84,145,24,33,24,32,17,18,145,32,22,168,49,163,1,33,50,184,115,129,25,66,1,24,67,2,80,35,40,53,2,65,51,19,67,37,0,52,35,49, 37, + 34,49,37,17,52,17,35,35,35,34,32,49,33,152,34,145,24,24,128,138,128,184,9,177,171,168,185,155,152,172,155,186,172,185,172,155,186,173,153,202,187,185,202,170,171,202,186,169,170,170,171,139,154,171,153,154,169,10,168,154,128,168,154,0,153, 152, 136, 137, + 128,153,0,152,8,128,137,0,136,136,8,9,8,9,8,24,153,128,136,153,144,0,161,138,1,169,136,128,160,168,152,153,138,137,154,153,153,154,153,170,168,170,185,168,169,154,169,171,153,169,170,153,152,154,153,137,169,137,136,144,152,144,128,128,144,129,129, 0, 33, + 0,17,17,17,33,33,18,18,34,34,34,34,34,34,35,19,35,19,35,35,18,19,18,35,18,33,0,8,8,8,8,8,8,8,160,205,65,176,171,203,16,240,95,242,120,145,156,66,177,26,19,153,9,35,35,239,56,132,138,154,50,145,203,25,32,20,237,24,130,138,160,27,39,173,50,203,64,145, 139, + 18,168,48,146,171,65,18,176,12,52,128,25,5,57,240,104,161,25,129,18,188,114,160,26,36,200,154,18,1,128,186,73,162,173,32,184,25,144,137,234,8,154,32,160,158,18,187,81,2,235,41,36,144,154,17,67,128,33,160,114,146,26,37,33,232,41,130,41,178,29,50, 251, 24, + 1,153,138,160,76,179,155,11,0,38,252,41,146,41,178,27,193,43,39,170,136,17,129,8,49,233,48,129,11,6,26,130,136,128,64,1,248,105,145,9,16,144,140,5,25,168,16,186,48,5,171,217,57,134,171,8,34,188,20,203,41,6,155,161,89,164,140,2,136,51,202,41,131, 56, 144, + 8,97,144,146,13,69,200,42,130,25,152,57,6,220,88,177,26,148,9,168,8,67,192,156,65,145,137,10,4,154,18,157,67,160,154,1,50,188,82,170,82,185,49,220,97,144,10,8,16,145,9,136,18,202,51,184,141,114,179,139,24,19,8,250,121,160,40,160,10,18,152,168,42,35, 216, + 187,120,145,18,156,203,84,144,9,144,26,66,161,13,1,128,17,154,18,142,6,154,65,192,29,35,186,64,192,24,9,146,56,185,16,248,121,176,40,129,136,171,96,147,140,50,203,64,144,41,128,161,187,71,200,24,129,24,217,56,20,220,24,4,169,9,1,33,201,26,134,141,51,201, + 25,16,33,235,32,144,33,153,169,99,160,11,3,136,58,210,33,203,48,163,17,219,128,140,38,8,184,141,50,131,159,33,128,153,25,18,153,88,242,43,3,9,136,157,53,202,40,145,25,2,204,105,146,156,66,152,8,153,33,128,129,136,153,50,186,55,188,51,249,64,178, 27, 128, + 48,177,156,18,35,175,51,189,32,51,234,155,69,184,26,2,152,9,17,136,144,137,50,235,115,216,24,2,170,67,187,49,129,155,4,27,129,56,232,43,39,203,40,3,154,169,66,184,114,224,25,2,9,128,11,35,155,18,11,202,84,169,26,5,154,8,160,98,185,17,187,50, 23, 188, 33, + 1,139,4,154,90,147,12,3,43,2,170,171,103,193,28,132,137,8,129,24,170,50,201,42,35,202,169,52,201,33,218,40,39,203,0,40,147,29,163,139,83,185,1,4,159,34,160,12,21,155,40,129,137,58,151,13,2,136,144,16,153,40,17,131,207,51,144,140,4,154,17,146,170,73, 163, + 44,164,12,152,37,203,17,128,144,139,23,154,128,138,38,216,41,1,0,233,73,131,171,49,136,9,164,46,3,171,32,0,145,157,38,187,64,176,58,134,155,18,136,217,64,1,200,140,38,153,170,66,161,8,169,65,185,98,200,41,3,155,144,58,23,187,1,145,40,147,189,32, 68, 249, + 1,112,255,199,195,19,108,76,187,247,247,183,40,168,212,245,199,227,68,45,59,10,145,177,198,24,130,76,26,193,180,129,0,162,42,160,199,162,0,16,152,137,132,168,195,130,162,181,227,163,161,179,211,180,179,164,128,162,161,194,164,179,40,153,195,213,146, 178, + 147,176,50,186,161,196,151,58,16,28,162,160,131,122,155,33,241,146,128,40,26,128,154,36,170,89,59,9,24,144,77,161,8,177,112,139,33,232,148,24,41,61,9,26,162,32,30,58,153,32,59,73,59,11,79,137,57,9,49,30,24,153,131,25,106,61,153,73,28,56,27, 41, 137, 148, + 76,43,74,58,13,161,3,171,149,32,77,10,74,42,168,16,0,123,138,129,162,178,225,50,140,161,0,147,10,129,41,244,210,165,1,152,24,162,184,166,32,144,59,216,132,177,8,145,67,143,146,160,183,162,130,24,192,32,225,146,144,33,44,73,30,129,137,32,76, 152, 25, 161, + 2,154,32,177,132,232,2,136,210,128,149,177,32,58,27,168,225,133,8,44,107,136,25,136,17,26,58,46,16,11,145,17,144,79,136,144,136,145,152,33,31,162,130,200,82,153,74,137,147,26,0,13,133,170,149,16,192,0,178,0,128,152,182,150,9,16,9,137,33,59,63,10,152, 32, + 179,192,5,154,228,182,145,130,144,42,128,242,2,136,41,168,17,76,57,31,129,136,17,47,8,41,138,32,138,123,59,58,10,136,161,4,46,25,145,136,129,25,56,28,91,41,154,108,9,16,44,24,137,48,15,0,194,162,41,194,56,241,163,146,0,139,7,186,150,129,152,1,208,33,176, + 136,164,163,185,7,138,130,242,162,163,177,88,136,184,166,146,0,25,25,177,199,146,16,136,9,145,178,178,0,147,138,229,18,152,25,144,163,246,162,129,129,184,5,152,178,145,148,136,146,95,152,128,144,33,170,81,11,40,202,131,0,243,24,1,11,148,42, 24, 163, 140, + 120,9,76,58,153,145,56,30,72,46,42,9,8,57,91,76,59,26,160,129,41,76,10,57,192,163,129,16,225,2,27,40,200,48,91,226,40,145,43,177,177,182,196,145,33,184,165,17,192,163,194,129,211,128,162,197,129,0,136,211,146,8,162,144,0,167,160,1,176,150,137,1, 24, 243, + 0,129,145,25,123,169,130,168,132,41,63,42,136,137,120,26,136,8,24,89,29,58,177,193,147,1,26,162,176,167,180,8,49,28,29,178,162,88,43,42,57,43,61,8,29,129,128,128,123,137,24,243,16,136,16,46,0,169,149,128,1,60,153,72,154,90,25,25,25,8,91,73,12,16,137,144, + 72,11,8,167,128,129,9,138,166,193,147,162,123,137,145,1,162,26,1,219,147,129,210,147,243,1,243,16,144,145,160,131,200,4,59,75,57,218,2,178,77,24,60,11,147,10,50,141,64,27,185,122,161,41,128,90,136,24,46,16,139,16,24,28,124,9,41,8,26,121,10,42,40,139,129, + 0,201,135,137,56,176,176,35,215,145,1,26,145,144,160,135,138,1,177,146,146,161,65,242,136,164,177,1,1,186,151,208,148,129,10,32,241,145,163,178,17,168,136,151,168,2,148,185,133,176,130,129,154,163,215,0,146,136,40,211,161,131,171,81,144,170, 21, 184, 56, + 195,168,133,177,91,16,187,5,145,153,66,172,18,177,42,120,138,27,134,26,106,42,138,146,184,66,75,46,41,168,0,145,57,91,75,27,24,27,48,169,40,122,9,109,10,8,177,146,16,74,30,129,160,162,146,41,124,138,24,145,152,3,1,14,3,139,1,192,161,151,177,122,8, 10, 0, + 176,130,129,27,88,225,0,2,154,129,129,193,49,203,81,153,226,33,0,30,0,176,179,18,9,96,156,162,148,160,129,2,29,195,128,0,56,156,20,232,129,128,32,10,144,74,183,9,145,162,1,162,138,23,171,1,164,224,34,43,43,177,200,135,161,91,57,154,177,148, 145, 146, 58, + 108,136,170,35,208,177,34,128,44,129,155,151,243,16,1,154,72,193,144,18,11,122,160,153,5,192,24,130,184,132,226,0,128,153,131,181,136,65,154,128,17,170,39,28,59,144,168,80,25,47,24,26,144,32,47,41,153,161,148,8,92,9,9,129,144,33,26,47,24,137,108, 25, 10, + 17,10,73,75,47,24,184,48,8,45,57,138,136,150,10,48,139,136,35,203,121,8,27,179,161,106,0,29,16,176,179,3,185,19,227,41,145,168,61,197,177,20,10,57,42,250,147,196,16,41,138,24,195,208,135,137,0,145,160,2,210,146,195,177,132,136,153,167,210,146,162, 40, 8, + 138,148,227,145,17,137,40,169,179,130,242,2,196,9,146,145,169,167,146,130,137,136,51,220,17,163,28,74,10,76,40,140,5,137,43,18,12,107,137,40,8,201,50,0,143,3,138,161,134,138,104,169,16,162,160,121,25,28,129,152,32,56,14,16,184,146,3,46,25, 176, 129, 179, + 193,17,130,202,135,8,57,25,154,148,184,120,9,153,211,165,24,128,26,17,242,161,18,185,81,42,11,17,12,25,181,137,66,42,47,41,184,166,129,24,91,27,136,196,0,0,74,28,178,161,149,160,32,8,225,32,128,59,8,169,50,139,47,72,186,16,132,9,122,9,160,146,144,89,153, + 10,149,178,0,121,11,146,152,162,48,13,123,177,24,0,106,27,9,144,132,12,17,0,168,0,181,56,169,129,242,195,129,17,154,64,161,244,16,137,24,144,144,164,129,75,42,176,149,9,179,148,203,4,166,136,163,128,227,163,8,57,11,30,165,0,74,59,62,9,208,131,144,40, 76, + 26,27,196,129,1,25,43,49,174,67,153,136,106,152,41,25,28,2,43,44,104,45,59,8,43,128,144,120,25,12,17,152,9,130,155,151,145,74,40,13,48,192,58,90,43,43,177,146,49,31,75,24,217,131,0,76,26,152,149,161,24,74,154,193,166,145,32,27,161,164,176,135,152,24,193, + 162,146,164,58,227,193,148,161,128,18,234,130,180,145,2,200,1,163,186,98,184,129,149,153,49,42,186,151,242,129,1,43,8,177,212,165,8,40,137,24,8,144,90,9,25,48,44,46,24,138,40,144,108,58,27,128,181,128,80,29,42,152,162,130,25,106,136,11,148,8,144,128,136, + 112,139,80,153,24,136,129,46,0,60,129,208,1,3,13,57,168,144,1,242,17,9,26,2,185,27,55,140,73,137,179,16,192,3,145,143,33,9,171,135,160,17,137,10,151,168,3,178,44,17,208,144,167,0,40,155,16,167,152,18,144,26,160,199,1,136,91,136,160,178,150,161,1,10, 181, + 145,161,1,145,161,198,2,9,90,137,177,160,150,40,29,129,144,145,162,57,77,169,16,148,42,42,40,141,34,170,121,154,210,131,162,107,8,9,160,195,40,73,139,18,224,162,34,139,0,244,178,163,24,26,146,194,166,49,29,42,137,130,192,16,93,128,154,19,59, 11, 122, 11, + 146,177,120,42,26,43,164,152,17,60,63,137,128,48,10,58,92,9,59,91,75,139,32,25,25,61,74,28,177,40,130,74,29,73,168,130,128,48,14,8,77,9,25,26,179,211,32,78,26,41,152,161,180,89,59,9,153,166,160,3,26,57,106,154,88,184,40,1,27,58,73,143,131,169,3,161, 184, + 122,152,16,181,145,129,17,15,129,193,147,145,192,33,193,162,183,163,136,178,129,178,197,2,41,216,131,168,163,181,226,163,178,1,33,187,166,212,129,1,27,24,162,184,151,8,16,160,144,181,210,72,168,128,32,42,25,40,142,5,185,88,58,11,58,177,32,129,63,42, 136, + 186,53,29,75,58,144,144,129,77,128,11,144,133,29,40,152,24,161,129,80,155,60,3,12,89,8,60,152,152,49,136,47,57,224,129,16,41,90,139,162,147,170,51,169,27,17,95,26,26,160,5,139,48,76,10,228,146,1,136,44,161,147,209,130,137,73,224,1,162,195,32,210,177,180, + 179,148,145,154,132,242,146,1,152,32,192,1,144,155,7,177,168,5,138,178,148,152,150,136,89,152,9,41,196,145,40,28,16,8,10,178,167,24,1,44,123,137,136,145,194,48,27,74,26,192,179,135,136,88,27,10,177,163,164,128,73,24,31,8,0,192,149,144,129,9,106, 41, 200, + 161,151,41,138,0,24,226,162,49,42,11,90,136,136,152,17,145,10,63,40,11,56,245,162,16,26,73,11,144,135,137,58,106,10,25,8,57,137,28,33,129,156,113,10,10,161,18,8,153,77,3,217,0,1,242,128,193,18,128,75,60,178,154,37,45,58,29,144,1,184,66,41,29, 8, 145, 10, + 194,33,148,170,107,89,139,128,163,178,16,63,59,176,144,151,129,42,74,10,129,192,2,128,154,97,192,0,177,128,178,183,16,16,155,149,145,184,84,138,8,192,161,20,225,0,130,138,165,0,28,148,153,18,209,128,88,153,89,152,9,17,9,29,130,43,122,153,24, 32, 202, 49, + 24,43,106,154,130,193,27,51,29,28,133,138,65,11,123,25,10,40,152,44,130,26,43,148,45,73,140,33,8,153,88,128,61,144,42,59,225,128,18,155,50,75,186,20,202,120,144,42,92,176,162,165,25,2,169,152,135,185,19,152,8,146,160,123,195,137,132,209,0,16, 11, 2, 242, + 146,164,152,73,193,136,130,178,1,136,169,23,169,128,164,242,129,178,129,32,138,180,167,153,132,8,138,2,209,4,138,1,128,138,92,136,44,129,136,162,33,63,40,141,2,160,144,106,137,64,155,17,129,60,30,146,26,17,28,48,46,169,51,154,91,137,41,26,32,143,18, 138, + 1,32,28,123,177,9,181,195,56,57,14,145,161,17,17,31,41,152,145,194,194,20,153,41,9,243,129,180,0,128,45,16,43,170,135,144,16,25,42,137,242,163,194,16,0,57,14,130,194,178,16,33,30,8,59,211,163,160,5,137,44,10,17,170,3,120,9,44,146,136,131,140, 91, 9, 171, + 7,161,32,73,13,8,161,40,106,11,25,129,59,0,49,31,42,28,40,11,0,81,176,61,32,138,25,178,241,148,136,106,8,136,128,177,90,8,155,96,176,9,18,217,132,129,10,81,156,40,178,161,36,169,76,147,203,150,0,10,146,200,147,149,128,144,148,154,182,24,0,137,11,134,211, + 24,136,129,145,209,33,8,43,163,243,88,41,13,0,160,145,33,31,32,185,145,4,155,17,32,47,161,128,73,160,44,56,176,75,74,12,35,141,104,137,9,89,152,58,56,44,41,30,41,40,157,48,128,154,88,41,42,8,14,3,184,59,120,152,9,56,10,128,41,57,227,186,52,152,62, 8, 56, + 242,0,58,8,156,34,243,128,24,176,51,169,58,183,192,146,164,177,18,170,7,177,208,132,161,24,136,27,147,243,128,133,10,24,161,161,178,214,17,160,25,16,161,137,165,192,48,27,72,58,218,133,162,26,72,27,10,197,178,49,138,89,56,142,1,24,11,0,44,105, 10, 25, 0, + 194,9,3,47,8,138,147,18,28,48,202,147,199,146,25,161,0,145,194,163,57,11,146,248,130,32,57,63,154,16,48,14,128,144,209,133,26,56,154,182,162,195,18,152,44,194,180,168,5,24,137,138,35,192,232,66,176,161,24,41,26,244,129,163,160,75,129,226,147,40, 145, 61, + 13,130,177,17,137,112,170,130,0,136,75,152,177,241,34,0,59,156,51,186,178,91,132,137,137,122,1,45,28,50,172,57,108,8,26,136,32,152,46,144,131,171,4,152,18,141,148,1,216,32,9,60,169,66,152,128,72,90,201,1,17,201,136,3,195,26,73,133,200,176, 150, 146, 169, + 24,33,178,184,151,73,11,28,72,44,153,82,153,17,42,57,78,153,8,160,0,1,123,11,19,171,195,18,59,31,129,10,162,2,58,96,142,130,26,75,128,176,17,180,123,9,90,137,211,145,32,26,76,43,145,130,12,90,41,27,58,160,160,128,178,7,76,59,0,203,180,147,33,62,10,0,243, + 129,146,73,29,145,144,0,26,56,153,185,83,8,76,27,166,161,193,146,131,224,145,165,161,40,168,149,162,226,2,136,138,163,131,211,0,59,146,218,148,1,192,16,16,58,248,88,144,177,136,1,58,45,9,195,197,147,48,29,10,0,162,176,64,122,9,10,17,9,153,56, 75, 27, 31, + 72,136,9,129,129,61,45,59,10,161,18,122,43,59,41,169,34,155,130,131,219,120,162,27,49,208,160,131,156,66,12,145,50,240,16,136,12,162,40,129,130,15,129,162,146,180,83,139,58,217,129,177,4,0,169,197,163,144,242,131,168,179,179,17,197,145,178,164, 128, 160, + 211,2,244,163,145,162,129,212,177,163,17,208,163,195,180,57,24,170,182,164,129,0,60,60,169,149,162,177,122,26,24,136,136,133,43,27,178,56,77,24,128,240,0,2,44,46,8,128,193,146,64,27,42,16,193,25,0,192,148,11,52,47,153,147,243,0,24,73,28,144, 161, 150, 9, + 8,73,170,2,162,25,27,147,167,131,29,1,168,200,165,16,91,137,8,162,176,35,41,31,24,169,50,168,58,123,144,48,128,13,73,169,144,16,57,123,44,200,163,56,153,80,10,176,146,57,94,8,152,131,9,168,125,26,145,177,132,137,41,60,26,144,243,32,192,34,60, 43, 26, 16, + 249,164,16,58,61,11,130,243,146,2,42,44,27,128,165,137,49,45,28,16,43,8,211,48,28,152,105,9,9,163,161,169,35,107,42,232,164,130,168,72,42,168,210,148,144,136,129,3,217,194,50,27,192,41,210,147,40,76,226,1,161,1,155,132,145,147,171,67,173,210,132,161,106, + 137,56,169,209,131,64,13,129,9,194,17,57,61,169,17,128,40,31,16,10,162,57,61,75,139,40,242,17,58,59,138,179,144,50,105,140,179,243,57,40,26,9,243,130,24,29,57,128,210,129,25,59,91,137,162,178,72,27,181,168,19,129,8,184,231,147,178,32,28,184,198,148, 144, + 1,26,128,16,192,2,26,144,244,129,0,16,10,197,177,181,1,41,9,178,165,211,129,25,145,137,210,147,152,210,163,132,194,17,91,169,145,181,130,9,89,137,152,178,4,128,9,63,160,128,106,8,25,43,10,32,47,26,123,152,24,40,25,27,18,186,35,158,64,42,216,33,25,58, 58, + 45,184,147,29,72,46,9,0,178,146,58,77,26,25,209,165,128,145,17,153,128,129,148,240,129,1,40,31,0,152,242,163,16,59,44,24,243,146,128,1,26,26,179,213,145,130,176,131,40,25,145,219,179,167,8,33,59,14,176,166,16,136,74,128,176,128,149,8,8,209,148,152,0, 72, + 153,161,178,35,62,75,154,163,153,19,62,170,133,179,136,89,12,129,164,144,3,47,58,193,177,148,0,61,43,10,129,17,41,61,43,25,8,126,26,25,137,145,34,44,45,129,216,179,1,90,25,137,32,227,8,16,9,170,49,31,32,29,128,145,148,75,25,75,153,162,192,35,12, 80, 136, + 176,8,194,24,1,176,21,154,145,80,251,130,2,30,9,8,130,145,128,98,27,26,129,136,162,15,33,168,59,65,177,77,141,1,128,168,113,10,137,178,163,146,132,74,153,224,164,33,184,19,184,228,161,17,91,152,25,146,152,44,121,9,160,145,17,25,28,93,128,152,2,25,27,161, + 210,129,146,45,179,227,163,162,9,40,193,148,179,57,107,140,196,32,25,57,47,136,210,130,24,40,28,152,210,182,145,40,8,129,184,147,147,140,163,166,160,34,45,144,194,161,134,41,46,152,162,162,3,44,58,75,209,162,144,57,129,47,152,130,59,16,248,129,17,26, 57, + 9,29,167,2,60,42,138,136,209,130,90,42,42,176,146,178,120,28,8,160,145,16,33,31,1,8,160,129,128,242,164,32,152,177,146,213,196,128,40,26,160,163,180,146,108,60,144,144,136,147,137,40,90,161,3,17,219,243,33,184,130,60,136,243,178,179,132,26,8,168,212,147, + 16,57,42,31,145,145,160,32,43,184,66,45,180,33,140,226,1,91,152,16,144,193,162,48,77,25,137,153,17,178,78,0,0,16,14,90,152,153,19,129,13,123,137,129,160,1,73,44,9,129,0,153,120,10,9,162,195,32,139,28,151,161,2,128,26,45,193,146,48,29,146,153, 194, 5, 59, + 29,128,144,195,1,64,43,208,178,149,8,9,16,240,163,129,16,42,185,181,211,24,48,45,137,149,9,24,41,75,184,177,4,43,91,128,180,16,144,29,25,184,167,1,59,60,153,148,161,146,91,42,186,4,24,145,123,11,2,178,77,136,26,25,195,40,115,61,27,168,177,3,59,79,26, 25, + 144,1,48,13,56,154,248,1,16,9,129,8,2,178,31,130,153,162,20,15,33,170,56,40,29,28,128,152,149,144,56,120,11,162,212,129,144,145,59,180,243,147,145,144,16,152,48,241,0,161,176,1,134,10,129,200,166,144,128,121,26,24,177,178,196,48,75,138,41,180,195,26, 24, + 89,138,24,33,187,41,84,155,57,79,136,160,210,130,0,58,58,168,243,132,27,41,75,138,3,8,61,8,29,145,179,76,24,28,146,208,2,49,140,75,196,144,0,40,44,179,208,3,176,33,15,177,2,160,106,8,160,164,164,8,73,27,226,179,161,1,57,1,196,211,128,40,156,145,166, 178, + 131,29,128,145,162,165,40,27,216,146,135,144,40,160,194,177,145,20,139,200,151,178,17,136,40,25,205,130,17,11,17,129,156,38,26,25,137,179,163,11,79,16,12,146,147,143,89,25,136,136,25,48,26,46,129,40,29,42,29,8,145,2,56,27,62,8,25,212,161,48,43, 144, 129, + 29,145,144,41,106,10,107,43,184,131,1,36,61,13,138,2,194,1,16,27,75,186,181,151,8,1,161,138,211,129,2,59,248,129,16,0,144,63,152,150,136,24,25,128,30,161,128,17,24,225,146,10,16,0,9,227,183,129,40,60,26,162,194,181,24,90,9,24,0,176,161,193,194,35,12, 63, + 8,210,162,1,32,78,28,152,164,144,16,48,45,137,162,147,168,152,98,27,43,33,12,160,165,129,137,63,41,153,153,151,16,91,26,8,8,9,56,10,46,24,146,57,168,160,166,241,129,32,140,16,145,179,164,137,113,138,208,131,26,25,1,42,178,196,106,24,171,18,196,8, 18, 29, + 41,194,128,3,249,57,162,152,48,184,120,160,208,33,137,74,57,187,149,129,26,35,158,72,128,168,32,26,25,180,75,2,136,15,163,161,136,120,27,41,160,128,182,56,60,25,12,178,151,128,168,72,10,152,4,177,26,147,137,113,44,42,33,220,2,152,41,82,11, 210, 163, 184, + 133,162,10,196,128,3,234,40,149,152,161,1,44,129,194,4,225,16,58,168,24,194,146,146,154,49,21,218,33,152,248,129,194,147,0,28,1,195,162,20,140,42,25,160,198,1,33,136,142,3,25,24,141,16,177,208,112,0,138,41,160,130,45,60,32,170,73,24,75,59,161,176,49,159, + 97,26,168,149,145,32,28,25,184,211,129,179,74,73,8,153,136,193,151,160,32,48,143,9,147,181,145,32,60,9,187,133,166,144,32,152,25,136,161,150,168,145,81,10,42,0,169,182,148,136,58,41,187,182,211,131,16,137,25,243,144,129,2,9,8,202,7,25,185,21,144,136,153, + 65,184,137,56,151,10,153,49,16,145,14,56,176,11,192,19,89,91,44,168,147,2,8,147,63,27,1,136,229,129,73,26,136,26,137,81,170,147,77,72,12,42,42,192,24,104,91,26,27,65,177,27,32,41,60,14,136,17,170,150,129,24,58,11,16,251,162,19,57,31,0,152,129,145,17, 61, + 14,1,129,27,129,66,169,178,74,12,11,19,198,145,75,33,138,174,133,1,184,57,40,136,169,20,1,60,174,20,154,201,67,26,162,151,42,16,138,59,130,204,20,169,59,180,59,114,184,56,178,242,128,130,43,8,194,3,229,144,33,185,144,34,181,145,168,17,149,153,74,35, 220, + 129,128,1,88,59,75,225,136,130,168,17,144,12,151,8,25,179,8,1,240,16,8,25,145,211,41,130,138,115,169,160,163,168,84,154,74,0,170,144,211,149,2,30,128,137,9,149,1,144,58,60,57,153,178,150,17,29,27,74,25,195,152,56,15,1,25,26,152,149,80,153,57,73,140, 128, + 160,144,113,27,56,28,25,4,42,44,137,60,171,130,50,240,8,5,139,145,1,105,137,200,80,137,145,146,178,179,160,46,16,240,195,131,128,144,24,164,198,128,0,136,137,131,194,165,177,2,161,147,11,144,188,181,148,144,23,0,28,224,128,131,192,32,1,224,1,168,132,145, + 9,41,208,58,137,179,151,145,16,1,30,8,145,178,1,47,32,186,72,169,146,75,8,41,48,136,89,13,48,9,10,124,26,11,42,32,129,91,77,16,12,128,42,57,138,10,60,2,63,9,0,93,128,152,90,8,10,24,40,44,144,29,49,188,48,72,25,30,177,33,128,186,120,129,186,133, 152, 130, + 24,156,51,154,8,226,2,56,155,2,179,233,167,128,24,129,176,136,151,8,184,0,33,224,152,21,177,24,10,163,16,250,17,130,171,83,137,136,37,12,56,242,154,17,160,145,82,13,3,201,128,18,137,24,162,63,162,8,107,178,128,57,158,32,24,200,18,0,106,154,73,16, 248, 8, + 73,137,57,75,0,128,12,65,137,59,75,28,144,129,122,0,58,140,160,195,145,105,56,28,153,145,164,88,8,28,25,153,9,162,113,89,153,136,33,234,147,128,41,72,11,138,151,144,145,16,43,58,248,130,178,42,4,40,10,196,154,147,216,24,7,136,10,161,148,210,161, 98, 138, + 137,128,146,176,33,105,27,43,163,49,185,6,10,136,43,67,174,161,162,151,137,1,64,200,193,24,64,200,56,145,242,24,57,137,1,128,3,162,175,80,128,162,152,25,58,175,17,17,0,200,64,168,162,91,1,154,44,211,177,35,64,160,161,144,4,241,41,209,162,25,1,3,242, 176, + 134,153,42,41,136,135,154,2,130,46,41,161,153,180,145,34,26,46,18,242,137,146,129,25,128,11,151,161,40,179,27,122,168,59,137,181,50,172,36,56,15,9,129,137,128,75,2,58,12,52,141,8,24,58,153,157,122,145,9,1,80,27,184,32,74,219,50,57,168,153,180,48,28, 143, + 131,144,178,65,13,48,168,162,147,155,121,9,170,5,16,153,21,29,144,161,91,0,184,57,128,137,17,159,88,178,128,105,152,9,162,33,164,141,88,178,224,1,0,16,27,185,150,161,9,4,139,16,128,160,194,144,65,180,46,40,136,27,135,160,16,44,57,145,236,2,195,40,75,177, + 2,200,179,146,186,104,50,141,24,169,165,148,11,97,10,11,130,177,49,57,78,42,154,128,165,59,33,28,30,1,136,16,192,41,128,152,123,136,24,1,169,113,10,11,49,153,14,147,19,45,43,8,176,210,148,8,16,11,96,144,192,163,150,10,128,43,26,150,178,165,24,41,171, 18, + 27,215,1,8,128,136,40,35,208,11,161,193,18,73,154,133,155,165,164,10,49,154,8,199,0,2,168,64,192,0,40,162,43,202,180,150,10,106,24,185,145,131,184,113,43,24,162,187,73,146,42,81,171,121,58,155,151,16,43,32,31,9,160,146,17,136,94,10,24,145,25, 9, 130, 59, + 65,13,91,25,169,146,176,112,42,59,16,217,130,20,13,25,9,40,161,138,68,169,154,18,62,154,180,145,135,152,56,58,155,165,211,8,40,42,10,198,1,2,184,57,184,224,51,154,27,134,168,19,202,73,75,184,35,176,75,24,25,209,51,157,19,30,184,179,3,33,148,45, 232, 146, + 129,168,41,32,170,149,193,35,136,16,50,191,56,146,173,149,16,24,41,30,129,168,209,3,57,31,0,16,176,147,41,152,10,17,181,14,40,144,49,170,75,97,141,25,162,146,72,177,92,137,137,19,137,153,113,154,2,41,60,129,217,2,211,152,73,42,193,197,146,147, 10, 59, 0, + 192,196,132,41,160,25,88,169,16,40,241,1,153,81,28,10,147,161,209,88,75,9,161,162,180,16,43,57,235,33,56,156,129,144,2,135,31,128,145,136,163,56,59,154,57,167,160,105,137,0,138,163,3,41,47,185,211,131,41,41,60,139,182,146,16,16,43,242,144,145,129,16,179, + 183,1,26,9,147,240,131,160,91,74,152,184,166,178,33,140,9,4,162,233,34,136,129,144,163,60,142,144,149,128,33,73,13,161,194,131,0,26,56,142,128,163,128,1,233,56,209,41,145,194,147,179,149,64,30,8,128,216,18,24,43,43,32,153,25,74,109,137,153,48,8,137, 122, + 25,144,26,43,59,30,33,41,27,24,96,153,160,50,76,27,47,152,145,163,73,40,14,152,131,176,74,90,8,8,200,67,155,154,50,49,155,28,124,177,152,1,2,17,62,138,180,176,4,25,9,177,245,162,129,40,25,176,164,130,172,4,8,181,194,49,11,168,154,165,133,152,40,136, 226, + 179,19,26,185,16,167,194,16,25,57,243,136,147,1,31,25,184,132,160,33,62,138,129,130,41,121,137,153,145,26,17,107,136,179,1,61,60,26,162,168,148,64,31,25,32,168,152,64,31,137,8,129,33,62,24,137,8,16,59,47,153,33,162,91,59,41,170,145,5,43,60,41,13,178,134, + 57,153,12,194,227,8,2,128,57,208,162,19,216,32,178,25,128,160,48,194,195,37,155,10,33,251,163,146,16,136,12,166,195,160,148,129,176,147,178,150,160,72,162,162,193,162,60,200,145,5,144,25,122,216,129,161,130,0,10,73,1,241,2,9,168,33,13,161,165,24,64, 203, + 50,1,14,9,9,129,161,106,33,27,13,164,128,40,41,107,169,160,33,136,60,92,168,152,2,91,57,176,129,0,144,47,136,162,164,128,80,43,154,179,213,130,74,27,0,145,145,167,58,59,160,9,26,76,8,171,5,49,28,44,169,162,183,130,72,28,144,179,228,2,25,26,129, 186, 151, + 1,75,128,169,17,178,15,57,170,16,166,16,57,8,139,162,181,1,8,152,164,181,41,81,43,10,242,145,57,139,89,8,193,18,154,32,176,10,165,129,137,147,177,134,0,25,25,201,147,227,129,72,59,185,167,128,129,160,91,25,176,130,147,145,9,160,5,202,17,16, 186, 136, 37, + 177,56,76,42,169,186,48,9,145,57,24,128,41,169,134,137,145,147,28,41,168,131,228,32,27,9,60,129,178,64,60,45,25,9,24,152,49,31,136,57,42,0,25,12,181,18,153,57,96,169,177,132,153,123,9,152,129,177,17,74,43,24,169,128,121,137,25,1,139,96,42,10,146,178, 18, + 44,29,1,161,164,146,31,137,146,177,19,1,10,26,209,165,146,43,40,138,240,130,18,144,25,40,212,1,58,11,152,196,147,10,74,26,152,225,130,146,58,60,210,145,16,148,16,185,192,18,44,42,57,199,162,1,9,87,47,186,215,231,197,179,180,195,212,164,32,59,92, 126, 62, + 41,59,76,59,60,168,179,213,197,163,72,44,25,74,126,127,127,79,26,177,148,90,27,225,247,165,0,152,147,123,138,211,164,72,126,127,46,210,196,163,228,215,64,11,210,180,1,8,58,153,1,224,149,57,76,27,24,76,42,43,136,128,243,179,130,106,60,42,42,92,28,243,231, + 147,24,57,44,58,94,45,8,57,139,214,148,40,77,26,9,16,10,144,64,62,43,25,123,59,138,162,48,63,26,41,92,60,43,176,3,59,232,214,164,16,75,75,76,60,153,179,33,62,26,136,40,75,169,197,163,129,57,60,59,75,138,145,64,63,138,179,1,42,136,90,43,176,214,180,1, 25, + 152,195,129,129,106,76,60,137,145,178,2,25,10,228,130,57,59,44,41,154,165,105,76,44,144,16,76,26,41,76,26,152,1,58,26,9,193,165,16,92,26,41,77,59,76,76,60,26,136,161,130,152,195,163,211,146,0,57,11,211,130,8,25,40,62,153,162,17,109,60,153,146,40, 76, 60, + 26,160,179,211,163,32,60,42,153,179,194,199,130,24,58,43,58,27,128,161,195,129,226,196,147,90,59,75,44,136,128,145,160,148,123,59,42,26,41,26,57,27,192,215,147,57,59,27,161,145,213,130,106,76,43,9,144,162,129,177,181,130,136,194,146,40,10,129,25,210,146, + 178,197,196,179,196,130,8,41,9,144,178,130,209,182,17,92,43,176,147,144,212,130,136,0,177,130,73,62,10,161,130,91,75,59,43,57,46,25,41,77,10,177,164,16,26,136,210,197,179,130,128,57,77,43,25,75,10,227,179,180,179,146,128,57,185,183,163,145,0,8,8,10, 119, + 114,120,16,210,244,60,28,41,25,152,149,56,161,35,44,89,27,24,136,24,164,211,17,233,176,136,192,129,179,17,17,25,0,10,46,160,132,49,66,24,132,177,147,193,56,72,26,29,232,168,176,12,137,41,139,147,9,1,41,15,91,136,35,148,21,18,48,40,1,168,167,144,0,42,172, + 177,204,193,155,232,152,152,26,152,41,146,17,6,4,65,34,35,135,4,16,32,9,24,186,176,0,250,153,204,186,173,154,153,177,3,65,41,34,145,134,35,65,98,49,50,50,2,33,169,138,155,175,170,172,204,192,138,234,136,155,136,10,32,18,5,52,48,24,162,17,67,54,66,51, 34, + 131,184,174,234,153,10,9,40,0,152,251,168,142,154,9,16,33,49,33,128,154,170,156,34,54,54,33,68,0,1,136,201,137,26,88,48,35,99,8,152,189,189,187,155,171,16,24,130,145,188,175,203,144,49,115,67,67,50,19,2,1,0,0,130,131,1,136,206,216,188,203, 204, 187, 187, + 156,153,0,0,51,17,34,24,112,20,69,67,67,34,19,0,136,169,185,137,186,232,185,219,201,203,187,173,170,154,153,129,131,6,2,19,49,49,21,65,19,53,51,83,34,16,168,201,154,172,156,138,0,1,24,201,233,186,204,186,171,137,3,37,48,24,128,201,202,202,129,17, 48, 21, + 22,20,19,19,32,16,2,66,52,68,4,3,1,203,235,188,189,186,171,153,137,153,170,219,170,140,9,17,53,115,50,52,67,51,51,51,17,130,0,145,154,169,188,236,187,190,203,187,172,171,138,136,17,33,18,2,34,98,98,50,50,52,66,34,35,2,19,24,169,203,203,188,219, 169, 154, + 9,137,171,204,188,203,184,136,34,83,50,33,153,184,170,170,152,40,57,19,36,50,50,18,35,17,2,49,49,66,66,66,34,17,168,233,202,202,170,171,170,186,219,203,188,188,154,138,25,33,68,52,68,67,67,36,51,36,18,17,17,136,8,170,176,202,188,206,202,171,172,186, 169, + 153,8,25,144,128,1,34,68,52,68,51,52,34,49,18,34,2,144,136,155,140,187,186,186,154,154,185,185,153,9,9,0,24,0,128,144,168,169,170,154,154,153,9,8,16,8,0,144,19,35,68,51,52,67,51,66,34,50,33,1,144,185,186,172,204,187,188,173,172,186,172,186, 154, 138, 41, + 33,52,53,83,50,51,52,52,37,34,34,18,16,144,152,154,187,219,203,188,173,186,186,186,170,154,153,138,144,16,17,67,82,50,51,21,34,19,33,2,18,33,1,8,153,169,153,153,136,128,0,136,154,153,153,8,8,1,16,0,169,170,187,171,171,154,153,153,152,153,153,0,16,51, 83, + 66,50,67,50,51,67,51,52,35,18,136,186,219,187,189,186,171,187,173,187,188,187,203,138,9,16,33,50,52,53,67,67,147,8,128,128,128,128,128,128,128,128,0,240,255,55,232,23,220,0,148,1,9,18,148,10,189,32,163,62,160,5,137,12,149,42,153,144,34,42,8, 1, 138, 181, + 45,136,18,144,105,138,1,160,14,128,132,145,186,37,138,41,192,48,145,46,160,33,44,24,225,16,13,132,136,137,16,148,25,170,194,82,152,136,91,24,42,169,33,233,131,179,24,185,149,16,57,172,164,18,10,211,160,147,211,33,138,243,129,16,41,193,0,43, 132, 155, 73, + 58,145,244,145,43,35,9,171,16,110,25,8,28,74,162,128,26,27,82,45,136,153,18,8,136,8 +}; + } // end of namespace Kyra #undef EUPHONY_FADEOUT_TICKS -- cgit v1.2.3 From ced14e186eaf41a78b5390645b1043b9fcea9cbe Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 2 Sep 2008 14:36:47 +0000 Subject: Cleanup: Remove now unneeded KyraEngine_v1::quitGame. Peres proposal for this commit log was: 'fixing .... as peres pointed out in his very interesting mail on -devel that everybody should read'. svn-id: r34282 --- engines/kyra/kyra_v1.cpp | 9 --------- engines/kyra/kyra_v1.h | 3 --- 2 files changed, 12 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index f3014911fc..95f775d78b 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -198,15 +198,6 @@ KyraEngine_v1::~KyraEngine_v1() { delete _debugger; } -void KyraEngine_v1::quitGame() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::quitGame()"); - Common::Event event; - - event.type = Common::EVENT_QUIT; - _eventMan->pushEvent(event); - // Nothing to do here -} - Common::Point KyraEngine_v1::getMousePos() const { Common::Point mouse = _eventMan->getMousePos(); diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 761724fa2f..81871615e8 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -151,9 +151,6 @@ public: void setVolume(kVolumeEntry vol, uint8 value); uint8 getVolume(kVolumeEntry vol); - // quit handling - virtual void quitGame(); - // game flag handling int setGameFlag(int flag); int queryGameFlag(int flag) const; -- cgit v1.2.3 From b7d260330b3278d8de1fdf035d99f7725704f21d Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Tue, 2 Sep 2008 21:31:53 +0000 Subject: some minor bug fixes svn-id: r34288 --- engines/kyra/sound_towns.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index cbf8efa99c..c57636a3fb 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1278,8 +1278,6 @@ void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &o o = &feed[0]; i = &feed[1]; phaseShift = _feedbackLevel ? ((*o + *i) << _feedbackLevel) : 0; - if (phasebuf == -1) - *i = 0; *o = *i; } else { phaseShift = phasebuf << 15; @@ -1964,16 +1962,35 @@ void TownsPC98_OpnChannel::fadeStep() { } void TownsPC98_OpnChannel::reset() { + _hold = false; + _keyOffTime = 0; + _ticksLeft = 1; + + _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF; + + _totalLevel = 0; + _algorithm = 0; + _flags = CHS_EOT; + _algorithm = 0; + _block = 0; _frequency = 0; - _hold = false; + _frqBlockMSB = 0; + _frqLSB = 0; + _ssgTl = 0; _ssgStartLvl = 0; _ssgTargetLvl = 0; _ssgStep = 0; _ssgTicksLeft = 0; - _totalLevel = 0; - _flags |= CHS_EOT; + + _vbrInitDelayHi = 0; + _vbrInitDelayLo = 0; + _vbrModInitVal = 0; + _vbrDuration = 0; + _vbrCurDelay = 0; + _vbrModCurVal = 0; + _vbrDurLeft = 0; } bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { @@ -3329,11 +3346,11 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) { *del = 0; break; case 5: - *del = feed[1]; - o[0]->generateOutput(-1, feed, phbuf1); + o[0]->generateOutput(0, feed, phbuf1); o[2]->generateOutput(*del, 0, output); - o[1]->generateOutput(*del, 0, output); - o[3]->generateOutput(*del, 0, output); + o[1]->generateOutput(phbuf1, 0, output); + o[3]->generateOutput(phbuf1, 0, output); + *del = phbuf1; break; case 6: o[0]->generateOutput(0, feed, phbuf1); -- cgit v1.2.3 From 531bcf847ceef2b9eca82e0b3ef8473612889632 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 3 Sep 2008 11:22:51 +0000 Subject: Moved FilesystemNode / FSList to namespace Common; also got rid of some 'typedef Common::String String;' name aliases svn-id: r34302 --- engines/kyra/resource.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 946169ddd4..bfd8b6a91c 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -50,7 +50,7 @@ bool Resource::reset() { clearCompFileList(); unloadAllPakFiles(); - FilesystemNode dir(ConfMan.get("path")); + Common::FilesystemNode dir(ConfMan.get("path")); if (!dir.exists() || !dir.isDirectory()) error("invalid game path '%s'", dir.getPath().c_str()); @@ -109,8 +109,8 @@ bool Resource::reset() { return true; } - FSList fslist; - if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) + Common::FSList fslist; + if (!dir.getChildren(fslist, Common::FilesystemNode::kListFilesOnly)) error("can't list files inside game path '%s'", dir.getPath().c_str()); if (_vm->game() == GI_KYRA1 && _vm->gameFlags().isTalkie) { @@ -128,7 +128,7 @@ bool Resource::reset() { iterator->_value.prot = true; } } else { - for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { + for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { Common::String filename = file->getName(); filename.toUppercase(); -- cgit v1.2.3 From d3642080def2d9ae5035724dab00565547a52a5e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 3 Sep 2008 16:56:40 +0000 Subject: Moved check for shouldRTL() from engines to scummvm_main svn-id: r34310 --- engines/kyra/kyra_hof.cpp | 2 +- engines/kyra/kyra_lok.cpp | 4 ++-- engines/kyra/kyra_mr.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 086d8d6913..2c418e43e3 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -325,7 +325,7 @@ int KyraEngine_HoF::go() { seq_playSequences(kSequenceFunters, kSequenceFrash); } - return _eventMan->shouldRTL(); + return 0; } void KyraEngine_HoF::startup() { diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index b6c874339c..59127d62ad 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -304,7 +304,7 @@ int KyraEngine_LoK::go() { setGameFlag(0xEF); seq_intro(); if (quit()) - return _eventMan->shouldRTL(); + return 0; if (_skipIntroFlag && _abortIntroFlag) resetGameFlag(0xEF); } @@ -312,7 +312,7 @@ int KyraEngine_LoK::go() { resetGameFlag(0xEF); mainLoop(); } - return _eventMan->shouldRTL(); + return 0; } diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 5bc843d8a8..9e26d5436b 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -324,7 +324,7 @@ int KyraEngine_MR::go() { if (_showOutro) playVQA("CREDITS"); - return _eventMan->shouldRTL(); + return 0; } void KyraEngine_MR::initMainMenu() { -- cgit v1.2.3 From 6bfa3e274a882dc0ac0b8362b225ae3234f4830b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Sep 2008 21:23:08 +0000 Subject: Got rid of File::eof() svn-id: r34396 --- engines/kyra/vqa.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index c55c573ea3..d5b63bdf6b 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -323,7 +323,7 @@ bool VQAMovie::open(const char *filename) { uint32 scanTag = readTag(); uint32 scanSize = _file.readUint32BE(); - if (_file.eof()) + if (_file.eos()) break; if (scanTag == MKID_BE('VQFR')) { @@ -396,7 +396,7 @@ void VQAMovie::displayFrame(uint frameNum) { uint32 tag = readTag(); uint32 size = _file.readUint32BE(); - if (_file.eof()) { + if (_file.eos()) { // This happens at the last frame. Apparently it has // no sound? break; @@ -596,7 +596,7 @@ void VQAMovie::play() { uint32 tag = readTag(); uint32 size = _file.readUint32BE(); - if (_file.eof()) { + if (_file.eos()) { warning("VQAMovie::play: Unexpected EOF"); break; } -- cgit v1.2.3 From f5462901b24f5a1191f3d68d866e4ee75a006347 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 7 Sep 2008 15:16:45 +0000 Subject: Temporary workaround for bug #2098279: ALL: Game path with no trailing backslash fails svn-id: r34408 --- engines/kyra/resource.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index bfd8b6a91c..340d9e0d1c 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -79,8 +79,8 @@ bool Resource::reset() { } else { if (_vm->gameFlags().isTalkie) { // Add default file directories - Common::File::addDefaultDirectory(ConfMan.get("path") + "hof_cd"); - Common::File::addDefaultDirectory(ConfMan.get("path") + "HOF_CD"); + Common::File::addDefaultDirectory(ConfMan.get("path") + "/hof_cd"); + Common::File::addDefaultDirectory(ConfMan.get("path") + "/HOF_CD"); } loadPakFile("INTROGEN.PAK"); @@ -95,8 +95,8 @@ bool Resource::reset() { } // Add default file directories - Common::File::addDefaultDirectory(ConfMan.get("path") + "malcolm"); - Common::File::addDefaultDirectory(ConfMan.get("path") + "MALCOLM"); + Common::File::addDefaultDirectory(ConfMan.get("path") + "/malcolm"); + Common::File::addDefaultDirectory(ConfMan.get("path") + "/MALCOLM"); if (!loadFileList("FILEDATA.FDT")) error("couldn't load file: 'FILEDATA.FDT'"); -- cgit v1.2.3 From 7aaf6139e25b55d4eca335553fe6da654ba1b341 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 7 Sep 2008 21:46:37 +0000 Subject: Moved Kyra resource code to a SearchSet/Archive based implementation, this removes dependencies on Common::File. svn-id: r34428 --- engines/kyra/module.mk | 1 + engines/kyra/resource.cpp | 1418 ++------------------------------------ engines/kyra/resource.h | 101 +-- engines/kyra/resource_intern.cpp | 1072 ++++++++++++++++++++++++++++ engines/kyra/resource_intern.h | 131 ++++ 5 files changed, 1291 insertions(+), 1432 deletions(-) create mode 100644 engines/kyra/resource_intern.cpp create mode 100644 engines/kyra/resource_intern.h (limited to 'engines/kyra') diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index e059a8ce4b..b38661ada5 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -23,6 +23,7 @@ MODULE_OBJS := \ kyra_mr.o \ lol.o \ resource.o \ + resource_intern.o \ saveload.o \ saveload_lok.o \ saveload_hof.o \ diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 340d9e0d1c..362c6a205d 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -23,31 +23,37 @@ * */ +#include "kyra/resource.h" +#include "kyra/resource_intern.h" #include "common/config-manager.h" #include "common/endian.h" #include "common/file.h" #include "common/fs.h" #include "common/func.h" - -#include "kyra/resource.h" +#include "common/system.h" namespace Kyra { -Resource::Resource(KyraEngine_v1 *vm) : _loaders(), _map(), _vm(vm) { +Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(new Common::SearchSet()), _protectedFiles(new Common::SearchSet()), _loaders(), _vm(vm) { initializeLoaders(); + + Common::SharedPtr path(new Common::FSDirectory(ConfMan.get("path"))); + Common::SharedPtr extrapath(new Common::FSDirectory(ConfMan.get("extrapath"))); + _vm->_system->addSysArchivesToSearchSet(_files); + _files.add("path", path, 3); + _files.add("extrapath", extrapath, 3); + // compressed installer archives are added at level '2', + // but that's done in Resource::reset not here + _files.add("protected", _protectedFiles, 1); + _files.add("archives", _archiveFiles, 0); } Resource::~Resource() { - _map.clear(); _loaders.clear(); - - clearCompFileList(); - _compLoaders.clear(); } bool Resource::reset() { - clearCompFileList(); unloadAllPakFiles(); Common::FilesystemNode dir(ConfMan.get("path")); @@ -71,18 +77,12 @@ bool Resource::reset() { loadPakFile("CHAPTER1.VRM"); } else if (_vm->game() == GI_KYRA2) { if (_vm->gameFlags().useInstallerPackage) - tryLoadCompFiles(); + _files.add("installer", loadInstallerArchive("WESTWOOD", "%03d", 6), 2); // mouse pointer, fonts, etc. required for initializing if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) { loadPakFile("GENERAL.PAK"); } else { - if (_vm->gameFlags().isTalkie) { - // Add default file directories - Common::File::addDefaultDirectory(ConfMan.get("path") + "/hof_cd"); - Common::File::addDefaultDirectory(ConfMan.get("path") + "/HOF_CD"); - } - loadPakFile("INTROGEN.PAK"); loadPakFile("OTHER.PAK"); } @@ -94,17 +94,13 @@ bool Resource::reset() { error("couldn't load file: 'WESTWOOD.001'"); } - // Add default file directories - Common::File::addDefaultDirectory(ConfMan.get("path") + "/malcolm"); - Common::File::addDefaultDirectory(ConfMan.get("path") + "/MALCOLM"); - if (!loadFileList("FILEDATA.FDT")) error("couldn't load file: 'FILEDATA.FDT'"); return true; } else if (_vm->game() == GI_LOL) { if (_vm->gameFlags().useInstallerPackage) - tryLoadCompFiles(); + _files.add("installer", loadInstallerArchive("WESTWOOD", "%d", 0), 2); return true; } @@ -120,12 +116,9 @@ bool Resource::reset() { "CAVE.APK", "DRAGON1.APK", "DRAGON2.APK", "LAGOON.APK" }; - Common::for_each(list, list + ARRAYSIZE(list), Common::bind1st(Common::mem_fun(&Resource::loadPakFile), this)); - - for (int i = 0; i < ARRAYSIZE(list); ++i) { - ResFileMap::iterator iterator = _map.find(list[i]); - if (iterator != _map.end()) - iterator->_value.prot = true; + for (uint i = 0; i < ARRAYSIZE(list); ++i) { + Common::ArchivePtr archive = loadArchive(list[i]); + _protectedFiles->add(list[i], archive, 0); } } else { for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { @@ -149,78 +142,18 @@ bool Resource::reset() { return true; } -bool Resource::loadPakFile(const Common::String &filename) { - if (!isAccessible(filename)) - return false; - - ResFileMap::iterator iter = _map.find(filename); - if (iter == _map.end()) - return false; +bool Resource::loadPakFile(Common::String filename) { + filename.toUppercase(); - if (iter->_value.preload) { - iter->_value.mounted = true; + if (_archiveFiles->hasArchive(filename) || _protectedFiles->hasArchive(filename)) return true; - } - const ResArchiveLoader *loader = getLoader(iter->_value.type); - if (!loader) { - error("no archive loader for file '%s' found which is of type %d", filename.c_str(), iter->_value.type); + Common::ArchivePtr archive = loadArchive(filename); + if (!archive) return false; - } - Common::SeekableReadStream *stream = getFileStream(filename); - if (!stream) { - error("archive file '%s' not found", filename.c_str()); - return false; - } + _archiveFiles->add(filename, archive, 0); - iter->_value.mounted = true; - iter->_value.preload = true; - ResArchiveLoader::FileList files; - loader->loadFile(filename, *stream, files); - delete stream; - stream = 0; - - for (ResArchiveLoader::FileList::iterator i = files.begin(); i != files.end(); ++i) { - iter = _map.find(i->filename); - if (iter == _map.end()) { - // We do an internal check for a file in gamepath with same filename to - // allow overwriting files inside archives with plain files inside the - // game directory - checkFile(i->filename); - - // A new file entry, so we just insert it into the file map. - if (_map.find(i->filename) == _map.end()) - _map[i->filename] = i->entry; - } else if (!iter->_value.parent.empty()) { - if (!iter->_value.parent.equalsIgnoreCase(filename)) { - ResFileMap::iterator oldParent = _map.find(iter->_value.parent); - if (oldParent != _map.end()) { - // Protected files and their embedded file entries do not get overwritten. - if (!oldParent->_value.prot) { - // If the old parent is not protected we mark it as not preload anymore, - // since now no longer all of its embedded files are in the filemap. - oldParent->_value.preload = false; - iter->_value = i->entry; - } - } else { - // Old parent not found? That's strange... But we just overwrite the old - // entry. - iter->_value = i->entry; - } - } else { - // The old parent has the same filenames as the new archive, we are sure and overwrite the - // old file entry, could be afterall that the preload flag of the new archive was - // just unflagged. - iter->_value = i->entry; - } - } - // 'else' case would mean here overwriting an existing file entry in the map without parent. - // We don't support that though, so one can overwrite files from archives by putting - // them in the gamepath. - } - - detectFileTypes(); return true; } @@ -240,11 +173,11 @@ bool Resource::loadFileList(const Common::String &filedata) { buffer[12] = 0; f.seek(offset + 16, SEEK_SET); - Common::String filename = Common::String((char*)buffer); + Common::String filename = Common::String((char *)buffer); filename.toUppercase(); if (filename.hasSuffix(".PAK")) { - if (!isAccessible(filename) && _vm->gameFlags().isDemo) { + if (!exists(filename.c_str()) && _vm->gameFlags().isDemo) { // the demo version supplied with Kyra3 does not // contain all pak files listed in filedata.fdt // so we don't do anything here if they are non @@ -273,33 +206,20 @@ bool Resource::loadFileList(const char * const *filelist, uint32 numFiles) { return true; } -void Resource::unloadPakFile(const Common::String &filename) { - ResFileMap::iterator iter = _map.find(filename); - if (iter != _map.end()) { - if (!iter->_value.prot) - iter->_value.mounted = false; - } -} - -void Resource::clearCompFileList() { - for (CompFileMap::iterator i = _compFiles.begin(); i != _compFiles.end(); ++i) - delete[] i->_value.data; - - _compFiles.clear(); +void Resource::unloadPakFile(Common::String filename) { + filename.toUppercase(); + _archiveFiles->remove(filename); + _protectedFiles->remove(filename); } -bool Resource::isInPakList(const Common::String &filename) { - if (!isAccessible(filename)) - return false; - ResFileMap::iterator iter = _map.find(filename); - if (iter == _map.end()) - return false; - return (iter->_value.type != ResFileEntry::kRaw); +bool Resource::isInPakList(Common::String filename) { + filename.toUppercase(); + return (_archiveFiles->hasArchive(filename) || _protectedFiles->hasArchive(filename)); } void Resource::unloadAllPakFiles() { - // remove all entries - _map.clear(); + _archiveFiles->clear(); + _protectedFiles->clear(); } uint8 *Resource::fileData(const char *file, uint32 *size) { @@ -318,9 +238,7 @@ uint8 *Resource::fileData(const char *file, uint32 *size) { } bool Resource::exists(const char *file, bool errorOutOnFail) { - if (Common::File::exists(file)) - return true; - else if (isAccessible(file)) + if (_files.hasFile(file)) return true; else if (errorOutOnFail) error("File '%s' can't be found", file); @@ -328,21 +246,13 @@ bool Resource::exists(const char *file, bool errorOutOnFail) { } uint32 Resource::getFileSize(const char *file) { - CompFileMap::iterator compEntry; - - if (Common::File::exists(file)) { - Common::File f; - if (f.open(file)) - return f.size(); - } else { - if (!isAccessible(file)) - return 0; + Common::SeekableReadStream *stream = getFileStream(file); + if (!stream) + return 0; - ResFileMap::const_iterator iter = _map.find(file); - if (iter != _map.end()) - return iter->_value.size; - } - return 0; + uint32 size = stream->size(); + delete stream; + return size; } bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) { @@ -357,1222 +267,51 @@ bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) { } Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) { - CompFileMap::iterator compEntry; - - if ((compEntry = _compFiles.find(file)) != _compFiles.end()) - return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false); - - if (!isAccessible(file)) - return 0; - - ResFileMap::const_iterator iter = _map.find(file); - if (iter == _map.end()) - return 0; - - if (iter->_value.parent.empty()) { - Common::File *stream = new Common::File(); - if (!stream->open(file)) { - delete stream; - stream = 0; - error("Couldn't open file '%s'", file.c_str()); - } - return stream; - } else { - Common::SeekableReadStream *parent = getFileStream(iter->_value.parent); - assert(parent); - - ResFileEntry* parentEntry = getParentEntry(&iter->_value); - const ResArchiveLoader *loader = getLoader(parentEntry->type); - assert(loader); - - return loader->loadFileFromArchive(file, parent, iter->_value); - } - - return 0; -} - -bool Resource::isAccessible(const Common::String &file) { - checkFile(file); - - ResFileMap::const_iterator iter = _map.find(file); - if (iter == _map.end()) - return false; - - return isAccessible(&iter->_value); -} - -bool Resource::isAccessible(const ResFileEntry *fileEntry) { - assert(fileEntry); - - const ResFileEntry* currentEntry = fileEntry; - while (!currentEntry->parent.empty()) { - if (currentEntry->parentEntry) { - currentEntry = currentEntry->parentEntry; - } else { - ResFileMap::iterator it = _map.find(currentEntry->parent); - if (it == _map.end()) - return false; - else - currentEntry->parentEntry = &it->_value; - } - // parent can never be a non archive file - if (currentEntry->type == ResFileEntry::kRaw) - return false; - // not mounted parent means not accessable - else if (!currentEntry->mounted) - return false; - } - - return true; -} - -ResFileEntry *Resource::getParentEntry(const ResFileEntry *entry) const { - assert(entry); - if (entry->parent.empty()) { - return 0; - } else if (entry->parentEntry) { - assert(_map.find(entry->parent) != _map.end()); // If some day the hash map implementations changes and moves nodes around, - // this assumption would fail and the whole system would need a refactoring - assert(entry->parentEntry == &_map.find(entry->parent)->_value); - return entry->parentEntry; - } else { - ResFileMap::iterator it = _map.find(entry->parent); - if (it == _map.end()) - return 0; // If it happens often, the structure maybe deserves a flag to avoid rechecking the map - else { - entry->parentEntry = &it->_value; - return entry->parentEntry; - } - } -} - -ResFileEntry *Resource::getParentEntry(const Common::String &filename) const { - ResFileMap::iterator it = _map.find(filename); - assert(it != _map.end()); - return getParentEntry(&it->_value); -} - -void Resource::checkFile(const Common::String &file) { - if (_map.find(file) == _map.end()) { - CompFileMap::const_iterator iter; - - if ((iter = _compFiles.find(file)) != _compFiles.end()) { - ResFileEntry& entry = _map[file]; - entry.parent = ""; - entry.parentEntry = 0; - entry.size = iter->_value.size; - entry.mounted = false; - entry.preload = false; - entry.prot = false; - entry.type = ResFileEntry::kAutoDetect; - entry.offset = 0; - - detectFileType(file, &entry); - } else if (Common::File::exists(file)) { - Common::File temp; - if (temp.open(file)) { - ResFileEntry& entry = _map[file]; - entry.parent = ""; - entry.parentEntry = 0; - entry.size = temp.size(); - entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; - entry.preload = false; - entry.prot = false; - entry.type = ResFileEntry::kAutoDetect; - entry.offset = 0; - temp.close(); - - detectFileType(file, &entry); - } - } - } -} - -void Resource::detectFileType(const Common::String &filename, ResFileEntry *fileEntry) { - assert(fileEntry); - - if (!isAccessible(fileEntry)) - return; - - if (fileEntry->type == ResFileEntry::kAutoDetect) { - Common::SeekableReadStream *stream = 0; - for (LoaderIterator l = _loaders.begin(); l != _loaders.end(); ++l) { - if (!(*l)->checkFilename(filename)) - continue; - - if (!stream) - stream = getFileStream(filename); - - if ((*l)->isLoadable(filename, *stream)) { - fileEntry->type = (*l)->getType(); - fileEntry->mounted = false; - fileEntry->preload = false; - break; - } - } - delete stream; - stream = 0; - - if (fileEntry->type == ResFileEntry::kAutoDetect) - fileEntry->type = ResFileEntry::kRaw; - } + return _files.openFile(file); } -void Resource::detectFileTypes() { - for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) - detectFileType(i->_key, &i->_value); -} - -void Resource::tryLoadCompFiles() { - for (CCompLoaderIterator i = _compLoaders.begin(); i != _compLoaders.end(); ++i) { - if ((*i)->checkForFiles()) - (*i)->loadFile(_compFiles); - } -} - -#pragma mark - -#pragma mark - ResFileLodaer -#pragma mark - - -class ResLoaderPak : public ResArchiveLoader { -public: - bool checkFilename(Common::String filename) const; - bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; - bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const; - Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const; - - ResFileEntry::kType getType() const { - return ResFileEntry::kPak; - } -}; - -bool ResLoaderPak::checkFilename(Common::String filename) const { - filename.toUppercase(); - return (filename.hasSuffix(".PAK") || filename.hasSuffix(".APK") || filename.hasSuffix(".VRM") || filename.hasSuffix(".TLK") || filename.equalsIgnoreCase(StaticResource::staticDataFilename())); -} - -bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { - uint32 filesize = stream.size(); - uint32 offset = 0; - bool switchEndian = false; - bool firstFile = true; - - offset = stream.readUint32LE(); - if (offset > filesize) { - switchEndian = true; - offset = SWAP_BYTES_32(offset); - } +Common::ArchivePtr Resource::loadArchive(const Common::String &file) { + ArchiveMap::iterator cachedArchive = _archiveCache.find(file); + if (cachedArchive != _archiveCache.end()) + return cachedArchive->_value; - Common::String file = ""; - while (!stream.eos()) { - // The start offset of a file should never be in the filelist - if (offset < stream.pos() || offset > filesize) - return false; - - byte c = 0; - - file = ""; - - while (!stream.eos() && (c = stream.readByte()) != 0) - file += c; - - if (stream.eos()) - return false; - - // Quit now if we encounter an empty string - if (file.empty()) { - if (firstFile) - return false; - else + Common::SeekableReadStream *stream = getFileStream(file); + if (!stream) + return Common::ArchivePtr(); + + Common::ArchivePtr archive; + for (LoaderList::const_iterator i = _loaders.begin(); i != _loaders.end(); ++i) { + if ((*i)->checkFilename(file)) { + if ((*i)->isLoadable(file, *stream)) { + stream->seek(0, SEEK_SET); + archive = Common::ArchivePtr((*i)->load(this, file, *stream)); break; - } - - firstFile = false; - offset = switchEndian ? stream.readUint32BE() : stream.readUint32LE(); - - if (!offset || offset == filesize) - break; - } - - return true; -} - -namespace { - -Common::String readString(Common::SeekableReadStream &stream) { - Common::String result; - char c = 0; - - while ((c = stream.readByte()) != 0) - result += c; - - return result; -} - -} // end of anonymous namespace - -bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { - uint32 filesize = stream.size(); - - uint32 startoffset = 0, endoffset = 0; - bool switchEndian = false; - bool firstFile = true; - - startoffset = stream.readUint32LE(); - if (startoffset > filesize) { - switchEndian = true; - startoffset = SWAP_BYTES_32(startoffset); - } - - Common::String file = ""; - while (!stream.eos()) { - // The start offset of a file should never be in the filelist - if (startoffset < stream.pos() || startoffset > filesize) { - warning("PAK file '%s' is corrupted", filename.c_str()); - return false; - } - - file = ""; - byte c = 0; - - while (!stream.eos() && (c = stream.readByte()) != 0) - file += c; - - if (stream.eos()) { - warning("PAK file '%s' is corrupted", filename.c_str()); - return false; - } - - // Quit now if we encounter an empty string - if (file.empty()) { - if (firstFile) { - warning("PAK file '%s' is corrupted", filename.c_str()); - return false; } else { - break; - } - } - - firstFile = false; - endoffset = switchEndian ? stream.readUint32BE() : stream.readUint32LE(); - - if (!endoffset) - endoffset = filesize; - - if (startoffset != endoffset) { - ResFileEntry entry; - entry.size = endoffset - startoffset; - entry.offset = startoffset; - entry.parent = filename; - entry.parentEntry = 0; - entry.type = ResFileEntry::kAutoDetect; - entry.mounted = false; - entry.prot = false; - entry.preload = false; - - files.push_back(File(file, entry)); - } - - if (endoffset == filesize) - break; - - startoffset = endoffset; - } - - FileList::const_iterator iter = Common::find(files.begin(), files.end(), Common::String("LINKLIST")); - if (iter != files.end()) { - stream.seek(iter->entry.offset, SEEK_SET); - - uint32 magic = stream.readUint32BE(); - - if (magic != MKID_BE('SCVM')) - error("LINKLIST file does not contain 'SCVM' header"); - - uint32 links = stream.readUint32BE(); - for (uint i = 0; i < links; ++i) { - Common::String linksTo = readString(stream); - uint32 sources = stream.readUint32BE(); - - iter = Common::find(files.begin(), files.end(), linksTo); - if (iter == files.end()) - error("PAK file link destination '%s' not found", linksTo.c_str()); - - for (uint j = 0; j < sources; ++j) { - Common::String dest = readString(stream); - files.push_back(File(dest, iter->entry)); - // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it - iter = Common::find(files.begin(), files.end(), linksTo); - } - } - } - - return true; -} - -Common::SeekableReadStream *ResLoaderPak::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const { - assert(archive); - - archive->seek(entry.offset, SEEK_SET); - Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true); - assert(stream); - return stream; -} - -class ResLoaderInsMalcolm : public ResArchiveLoader { -public: - bool checkFilename(Common::String filename) const; - bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; - bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const; - Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const; - - ResFileEntry::kType getType() const { - return ResFileEntry::kInsMal; - } -}; - -bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const { - filename.toUppercase(); - if (!filename.hasSuffix(".001")) - return false; - return true; -} - -bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { - stream.seek(3); - uint32 size = stream.readUint32LE(); - - if (size+7 > stream.size()) - return false; - - stream.seek(size+5, SEEK_SET); - uint8 buffer[2]; - stream.read(&buffer, 2); - - return (buffer[0] == 0x0D && buffer[1] == 0x0A); -} - -bool ResLoaderInsMalcolm::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { - Common::List filenames; - - // thanks to eriktorbjorn for this code (a bit modified though) - stream.seek(3, SEEK_SET); - - // first file is the index table - uint32 size = stream.readUint32LE(); - Common::String temp = ""; - - for (uint32 i = 0; i < size; ++i) { - byte c = stream.readByte(); - - if (c == '\\') { - temp = ""; - } else if (c == 0x0D) { - // line endings are CRLF - c = stream.readByte(); - assert(c == 0x0A); - ++i; - - filenames.push_back(temp); - } else { - temp += (char)c; - } - } - - stream.seek(3, SEEK_SET); - - for (Common::List::iterator file = filenames.begin(); file != filenames.end(); ++file) { - ResFileEntry entry; - entry.parent = filename; - entry.parentEntry = 0; - entry.type = ResFileEntry::kAutoDetect; - entry.mounted = false; - entry.preload = false; - entry.prot = false; - entry.size = stream.readUint32LE(); - entry.offset = stream.pos(); - stream.seek(entry.size, SEEK_CUR); - files.push_back(File(*file, entry)); - } - - return true; -} - -Common::SeekableReadStream *ResLoaderInsMalcolm::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const { - assert(archive); - - archive->seek(entry.offset, SEEK_SET); - Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true); - assert(stream); - return stream; -} - -class ResLoaderTlk : public ResArchiveLoader { -public: - bool checkFilename(Common::String filename) const; - bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; - bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const; - Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const; - - ResFileEntry::kType getType() const { - return ResFileEntry::kTlk; - } - -private: - static bool sortTlkFileList(const File &l, const File &r); - static FileList::const_iterator nextFile(const FileList &list, FileList::const_iterator iter); -}; - -bool ResLoaderTlk::checkFilename(Common::String filename) const { - filename.toUppercase(); - return (filename.hasSuffix(".TLK")); -} - -bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { - uint16 entries = stream.readUint16LE(); - uint32 entryTableSize = (entries * 8); - - if (entryTableSize + 2 > stream.size()) - return false; - - uint32 offset = 0; - - for (uint i = 0; i < entries; ++i) { - stream.readUint32LE(); - offset = stream.readUint32LE(); - - if (offset > stream.size()) - return false; - } - - return true; -} - -bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { - uint16 entries = stream.readUint16LE(); - - for (uint i = 0; i < entries; ++i) { - ResFileEntry entry; - entry.parent = filename; - entry.parentEntry = 0; - entry.type = ResFileEntry::kAutoDetect; - entry.mounted = false; - entry.preload = false; - entry.prot = false; - - uint32 resFilename = stream.readUint32LE(); - uint32 resOffset = stream.readUint32LE(); - - entry.offset = resOffset+4; - - char realFilename[20]; - snprintf(realFilename, 20, "%.08u.AUD", resFilename); - - uint32 curOffset = stream.pos(); - stream.seek(resOffset, SEEK_SET); - entry.size = stream.readUint32LE(); - stream.seek(curOffset, SEEK_SET); - - files.push_back(FileList::value_type(realFilename, entry)); - } - - return true; -} - -Common::SeekableReadStream *ResLoaderTlk::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const { - assert(archive); - - archive->seek(entry.offset, SEEK_SET); - Common::SeekableSubReadStream *stream = new Common::SeekableSubReadStream(archive, entry.offset, entry.offset + entry.size, true); - assert(stream); - return stream; -} - -#pragma mark - -#pragma mark - CompFileLoader -#pragma mark - - -class FileExpanderSource { -public: - FileExpanderSource(const uint8 *data, int dataSize) : _dataPtr(data), _endofBuffer(data + dataSize), _bitsLeft(8), _key(0), _index(0) {} - ~FileExpanderSource() {} - - void advSrcRefresh(); - void advSrcBitsBy1(); - void advSrcBitsByIndex(uint8 newIndex); - - uint8 getKeyLower() { return _key & 0xff; } - void setIndex(uint8 index) { _index = index; } - uint16 getKeyMasked(uint8 newIndex); - uint16 keyMaskedAlign(uint16 val); - - void copyBytes(uint8 *& dst); - -private: - const uint8 *_dataPtr; - const uint8 *_endofBuffer; - uint16 _key; - int8 _bitsLeft; - uint8 _index; -}; - -void FileExpanderSource::advSrcBitsBy1() { - _key >>= 1; - if (!--_bitsLeft) { - if (_dataPtr < _endofBuffer) - _key = ((*_dataPtr++) << 8 ) | (_key & 0xff); - _bitsLeft = 8; - } -} - -void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) { - _index = newIndex; - _bitsLeft -= _index; - if (_bitsLeft <= 0) { - _key >>= (_index + _bitsLeft); - _index = -_bitsLeft; - _bitsLeft = 8 - _index; - if (_dataPtr < _endofBuffer) - _key = (*_dataPtr++ << 8) | (_key & 0xff); - } - _key >>= _index; -} - -uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) { - static const uint8 mskTable[] = { 0x0F, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; - _index = newIndex; - uint16 res = 0; - - if (_index > 8) { - newIndex = _index - 8; - res = (_key & 0xff) & mskTable[8]; - advSrcBitsByIndex(8); - _index = newIndex; - res |= (((_key & 0xff) & mskTable[_index]) << 8); - advSrcBitsByIndex(_index); - } else { - res = (_key & 0xff) & mskTable[_index]; - advSrcBitsByIndex(_index); - } - - return res; -} - -void FileExpanderSource::copyBytes(uint8 *& dst) { - advSrcBitsByIndex(_bitsLeft); - uint16 r = (READ_LE_UINT16(_dataPtr) ^ _key) + 1; - _dataPtr += 2; - - if (r) - error("decompression failure"); - - memcpy(dst, _dataPtr, _key); - _dataPtr += _key; - dst += _key; -} - -uint16 FileExpanderSource::keyMaskedAlign(uint16 val) { - val -= 0x101; - _index = (val & 0xff) >> 2; - int16 b = ((_bitsLeft << 8) | _index) - 1; - _bitsLeft = b >> 8; - _index = b & 0xff; - uint16 res = (((val & 3) + 4) << _index) + 0x101; - return res + getKeyMasked(_index); -} - -void FileExpanderSource::advSrcRefresh() { - _key = READ_LE_UINT16(_dataPtr); - if (_dataPtr < _endofBuffer - 1) - _dataPtr += 2; - _bitsLeft = 8; -} - -class FileExpander { -public: - FileExpander(); - ~FileExpander(); - - bool process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 insize); - -private: - void generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt); - uint8 calcCmdAndIndex(const uint8 *tbl, int16 ¶); - - FileExpanderSource *_src; - uint8 *_tables[9]; - uint16 *_tables16[3]; -}; - -FileExpander::FileExpander() : _src(0) { - _tables[0] = new uint8[3914]; - assert(_tables[0]); - - _tables[1] = _tables[0] + 320; - _tables[2] = _tables[0] + 352; - _tables[3] = _tables[0] + 864; - _tables[4] = _tables[0] + 2016; - _tables[5] = _tables[0] + 2528; - _tables[6] = _tables[0] + 2656; - _tables[7] = _tables[0] + 2736; - _tables[8] = _tables[0] + 2756; - - _tables16[0] = (uint16 *)(_tables[0] + 3268); - _tables16[1] = (uint16 *)(_tables[0] + 3302); - _tables16[2] = (uint16 *)(_tables[0] + 3338); -} - -FileExpander::~FileExpander() { - delete _src; - delete[] _tables[0]; -} - -bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 compressedSize) { - static const uint8 indexTable[] = { - 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, 0x0A, - 0x05, 0x0B, 0x04, 0x0C, 0x03, 0x0D, 0x02, 0x0E, 0x01, 0x0F - }; - - memset(_tables[0], 0, 3914); - - uint8 *d = dst; - uint16 tableSize0 = 0; - uint16 tableSize1 = 0; - bool needrefresh = true; - bool postprocess = false; - - _src = new FileExpanderSource(src, compressedSize); - - while (d < dst + outsize) { - - if (needrefresh) { - needrefresh = false; - _src->advSrcRefresh(); - } - - _src->advSrcBitsBy1(); - - int mode = _src->getKeyMasked(2) - 1; - if (mode == 1) { - tableSize0 = _src->getKeyMasked(5) + 257; - tableSize1 = _src->getKeyMasked(5) + 1; - memset(_tables[7], 0, 19); - - const uint8 *itbl = indexTable; - int numbytes = _src->getKeyMasked(4) + 4; - - while (numbytes--) - _tables[7][*itbl++] = _src->getKeyMasked(3); - - generateTables(7, 8, 255, 19); - - int cnt = tableSize0 + tableSize1; - uint8 *tmp = _tables[0]; - - while (cnt) { - uint16 cmd = _src->getKeyLower(); - cmd = READ_LE_UINT16(&_tables[8][cmd << 1]); - _src->advSrcBitsByIndex(_tables[7][cmd]); - - if (cmd < 16) { - *tmp++ = cmd; - cnt--; - } else { - uint8 tmpI = 0; - if (cmd == 16) { - cmd = _src->getKeyMasked(2) + 3; - tmpI = *(tmp - 1); - } else if (cmd == 17) { - cmd = _src->getKeyMasked(3) + 3; - } else { - cmd = _src->getKeyMasked(7) + 11; - } - _src->setIndex(tmpI); - memset(tmp, tmpI, cmd); - tmp += cmd; - - cnt -= cmd; - if (cnt < 0) - error("decompression failure"); - } + stream->seek(0, SEEK_SET); } - - memcpy(_tables[1], _tables[0] + tableSize0, tableSize1); - generateTables(0, 2, 3, tableSize0); - generateTables(1, 4, 5, tableSize1); - postprocess = true; - } else if (mode < 0) { - _src->copyBytes(d); - postprocess = false; - needrefresh = true; - } else if (mode == 0){ - uint8 *d2 = _tables[0]; - memset(d2, 8, 144); - memset(d2 + 144, 9, 112); - memset(d2 + 256, 7, 24); - memset(d2 + 280, 8, 8); - d2 = _tables[1]; - memset(d2, 5, 32); - tableSize0 = 288; - tableSize1 = 32; - - generateTables(0, 2, 3, tableSize0); - generateTables(1, 4, 5, tableSize1); - postprocess = true; - } else { - error("decompression failure"); } - - if (!postprocess) - continue; - - int16 cmd = 0; - - do { - cmd = ((int16*) _tables[2])[_src->getKeyLower()]; - _src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]); - - if (cmd == 0x11d) { - cmd = 0x200; - } else if (cmd > 0x108) { - cmd = _src->keyMaskedAlign(cmd); - } - - if (!(cmd >> 8)) { - *d++ = cmd & 0xff; - } else if (cmd != 0x100) { - cmd -= 0xfe; - int16 offset = ((int16*) _tables[4])[_src->getKeyLower()]; - _src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]); - if ((offset & 0xff) >= 4) { - uint8 newIndex = ((offset & 0xff) >> 1) - 1; - offset = (((offset & 1) + 2) << newIndex); - offset += _src->getKeyMasked(newIndex); - } - - uint8 *s2 = d - 1 - offset; - if (s2 >= dst) { - while (cmd--) - *d++ = *s2++; - } else { - uint32 pos = dst - s2; - s2 += (d - dst); - - if (pos < (uint32) cmd) { - cmd -= pos; - while (pos--) - *d++ = *s2++; - s2 = dst; - } - while (cmd--) - *d++ = *s2++; - } - } - } while (cmd != 0x100); } - delete _src; - _src = 0; - - return true; -} - -void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) { - const uint8 *tbl1 = _tables[srcIndex]; - uint8 *tbl2 = _tables[dstIndex]; - const uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2]; - - if (!cnt) - return; - - const uint8 *s = tbl1; - memset(_tables16[0], 0, 32); - - for (int i = 0; i < cnt; i++) - _tables16[0][(*s++)]++; - - _tables16[1][1] = 0; - - for (uint16 i = 1, r = 0; i < 16; i++) { - r = (r + _tables16[0][i]) << 1; - _tables16[1][i + 1] = r; - } - - if (_tables16[1][16]) { - uint16 r = 0; - for (uint16 i = 1; i < 16; i++) - r += _tables16[0][i]; - if (r > 1) - error("decompression failure"); - } - - s = tbl1; - uint16 *d = _tables16[2]; - for (int i = 0; i < cnt; i++) { - uint16 t = *s++; - if (t) { - _tables16[1][t]++; - t = _tables16[1][t] - 1; - } - *d++ = t; - } - - s = tbl1; - d = _tables16[2]; - for (int i = 0; i < cnt; i++) { - int8 t = ((int8)(*s++)) - 1; - if (t > 0) { - uint16 v1 = *d; - uint16 v2 = 0; - - do { - v2 = (v2 << 1) | (v1 & 1); - v1 >>= 1; - } while (--t && v1); - - t++; - uint8 c1 = (v1 & 1); - while (t--) { - uint8 c2 = v2 >> 15; - v2 = (v2 << 1) | c1; - c1 = c2; - }; - - *d++ = v2; - } else { - d++; - } - } - - memset(tbl2, 0, 512); - - cnt--; - s = tbl1 + cnt; - d = &_tables16[2][cnt]; - uint16 * bt = (uint16*) tbl3; - uint16 inc = 0; - uint16 cnt2 = 0; - - do { - uint8 t = *s--; - uint16 *s2 = (uint16*) tbl2; - - if (t && t < 9) { - inc = 1 << t; - uint16 o = *d; - - do { - s2[o] = cnt; - o += inc; - } while (!(o & 0xf00)); - - } else if (t > 8) { - if (!bt) - error("decompression failure"); - - t -= 8; - uint8 shiftCnt = 1; - uint8 v = (*d) >> 8; - s2 = &((uint16*) tbl2)[*d & 0xff]; - - do { - if (!*s2) { - *s2 = (uint16)(~cnt2); - *(uint32*)&bt[cnt2] = 0; - cnt2 += 2; - } - - s2 = &bt[(uint16)(~*s2)]; - if (v & shiftCnt) - s2++; - - shiftCnt <<= 1; - } while (--t); - *s2 = cnt; - } - d--; - } while (--cnt >= 0); -} - -uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 ¶) { - const uint16 *t = (const uint16*)tbl; - _src->advSrcBitsByIndex(8); - uint8 newIndex = 0; - uint16 v = _src->getKeyLower(); - - do { - newIndex++; - para = t[((~para) & 0xfffe) | (v & 1)]; - v >>= 1; - } while (para < 0); - - return newIndex; -} - -class CompLoaderInsHof : public CompArchiveLoader { -public: - CompLoaderInsHof() { - _fileExtP = "%03d"; - _checkFile1 = "WESTWOOD.001"; - _checkFile2 = "WESTWOOD.002"; - _containerOffset = 6; - } + delete stream; - virtual bool checkForFiles() const; - virtual bool loadFile(CompFileMap &loadTo) const; - -protected: - struct Archive { - Common::String filename; - uint32 firstFile; - uint32 startOffset; - uint32 lastFile; - uint32 endOffset; - uint32 totalSize; - }; - - const char *_fileExtP; - const char *_checkFile1; - const char *_checkFile2; - uint8 _containerOffset; -}; - -class CompLoaderInsLol : public CompLoaderInsHof { -public: - CompLoaderInsLol() { - _fileExtP = "%d"; - _checkFile1 = "WESTWOOD.1"; - _checkFile2 = "WESTWOOD.2"; - _containerOffset = 0; - } -}; + if (!archive) + return Common::ArchivePtr(); -bool CompLoaderInsHof::checkForFiles() const { - return (Common::File::exists(_checkFile1) && Common::File::exists(_checkFile2)); + _archiveCache[file] = archive; + return archive; } -bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const { - Common::File tmpFile; - - uint32 pos = 0; - uint32 bytesleft = 0; - bool startFile = true; - - Common::String filenameBase = "WESTWOOD."; - Common::String filenameTemp; - char filenameExt[4]; - - while (filenameBase.lastChar() != '.') - filenameBase.deleteLastChar(); - - Archive newArchive; - - Common::List archives; - - for (int8 currentFile = 1; currentFile; currentFile++) { - sprintf(filenameExt, _fileExtP, currentFile); - filenameTemp = filenameBase + Common::String(filenameExt); - - if (!tmpFile.open(filenameTemp)) { - debug(3, "couldn't open file '%s'\n", filenameTemp.c_str()); - break; - } - - tmpFile.seek(pos); - uint8 fileId = tmpFile.readByte(); - pos++; - - uint32 size = tmpFile.size() - 1; - if (startFile) { - size -= 4; - if (fileId == currentFile) { - size -= _containerOffset; - pos += _containerOffset; - tmpFile.seek(_containerOffset, SEEK_CUR); - } else { - size = size + 1 - pos; - } - newArchive.filename = filenameBase; - bytesleft = newArchive.totalSize = tmpFile.readUint32LE(); - pos += 4; - newArchive.firstFile = currentFile; - newArchive.startOffset = pos; - startFile = false; - } - - uint32 cs = MIN(size, bytesleft); - bytesleft -= cs; - - tmpFile.close(); - - pos += cs; - if (cs == size) { - if (!bytesleft) { - newArchive.lastFile = currentFile; - newArchive.endOffset = --pos; - archives.push_back(newArchive); - currentFile = -1; - } else { - pos = 0; - } - } else { - startFile = true; - bytesleft = size - cs; - newArchive.lastFile = currentFile--; - newArchive.endOffset = --pos; - archives.push_back(newArchive); - } - } - - FileExpander exp; - CompFileEntry newEntry; - uint32 insize = 0; - uint32 outsize = 0; - uint8 *inbuffer = 0; - uint8 *outbuffer = 0; - uint32 inPart1 = 0; - uint32 inPart2 = 0; - uint8 compressionType = 0; - Common::String entryStr; - - pos = 0; - - const uint32 kExecSize = 0x0bba; - const uint32 kHeaderSize = 30; - const uint32 kHeaderSize2 = 46; - - for (Common::List::iterator a = archives.begin(); a != archives.end(); ++a) { - startFile = true; - for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) { - sprintf(filenameExt, _fileExtP, i); - filenameTemp = a->filename + Common::String(filenameExt); - - if (!tmpFile.open(filenameTemp)) { - debug(3, "couldn't open file '%s'\n", filenameTemp.c_str()); - break; - } - - uint32 size = (i == a->lastFile) ? a->endOffset : tmpFile.size(); - - if (startFile) { - startFile = false; - pos = a->startOffset + kExecSize; - if (pos > size) { - pos -= size; - tmpFile.close(); - continue; - } - } else { - if (inPart2) { - tmpFile.seek(1); - tmpFile.read(inbuffer + inPart1, inPart2); - inPart2 = 0; - - if (compressionType > 0) - exp.process(outbuffer, inbuffer, outsize, insize); - else - memcpy(outbuffer, inbuffer, outsize); - - delete[] inbuffer; - inbuffer = 0; - newEntry.data = outbuffer; - newEntry.size = outsize; - loadTo[entryStr] = newEntry; - } - pos++; - } +Common::ArchivePtr Resource::loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset) { + ArchiveMap::iterator cachedArchive = _archiveCache.find(file); + if (cachedArchive != _archiveCache.end()) + return cachedArchive->_value; - while (pos < size) { - uint8 hdr[43]; - uint32 m = 0; - tmpFile.seek(pos); - - if (pos + 42 > size) { - m = size - pos; - uint32 b = 42 - m; - - if (m >= 4) { - uint32 id = tmpFile.readUint32LE(); - if (id == 0x06054B50) { - startFile = true; - break; - } else { - tmpFile.seek(pos); - } - } - - sprintf(filenameExt, _fileExtP, i + 1); - filenameTemp = a->filename + Common::String(filenameExt); - - Common::File tmpFile2; - tmpFile2.open(filenameTemp); - tmpFile.read(hdr, m); - tmpFile2.read(hdr + m, b); - tmpFile2.close(); - - } else { - tmpFile.read(hdr, 42); - } - - uint32 id = READ_LE_UINT32(hdr); - - if (id == 0x04034B50) { - compressionType = hdr[8]; - insize = READ_LE_UINT32(hdr + 18); - outsize = READ_LE_UINT32(hdr + 22); - - uint16 filestrlen = READ_LE_UINT16(hdr + 26); - *(hdr + 30 + filestrlen) = 0; - entryStr = Common::String((const char *)(hdr + 30)); - pos += (kHeaderSize + filestrlen - m); - tmpFile.seek(pos); - - outbuffer = new uint8[outsize]; - if (!outbuffer) - error("Out of memory: Can't uncompress installer files"); - - if (!inbuffer) { - inbuffer = new uint8[insize]; - if (!inbuffer) - error("Out of memory: Can't uncompress installer files"); - } - - if ((pos + insize) > size) { - // this is for files that are split between two archive files - inPart1 = size - pos; - inPart2 = insize - inPart1; - tmpFile.read(inbuffer, inPart1); - } else { - tmpFile.read(inbuffer, insize); - inPart2 = 0; - - if (compressionType > 0) - exp.process(outbuffer, inbuffer, outsize, insize); - else - memcpy(outbuffer, inbuffer, outsize); - - delete[] inbuffer; - inbuffer = 0; - newEntry.data = outbuffer; - newEntry.size = outsize; - loadTo[entryStr] = newEntry; - } - - pos += insize; - if (pos > size) { - pos -= size; - break; - } - } else { - uint32 filestrlen = READ_LE_UINT32(hdr + 28); - pos += (kHeaderSize2 + filestrlen - m); - } - } - tmpFile.close(); - } - } + Common::ArchivePtr archive(InstallerLoader::load(this, file, ext, offset)); + if (!archive) + return Common::ArchivePtr(); - archives.clear(); - return true; + _archiveCache[file] = archive; + return archive; } #pragma mark - @@ -1581,17 +320,6 @@ void Resource::initializeLoaders() { _loaders.push_back(LoaderList::value_type(new ResLoaderPak())); _loaders.push_back(LoaderList::value_type(new ResLoaderInsMalcolm())); _loaders.push_back(LoaderList::value_type(new ResLoaderTlk())); - - _compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsHof())); - _compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsLol())); -} - -const ResArchiveLoader *Resource::getLoader(ResFileEntry::kType type) const { - for (CLoaderIterator i = _loaders.begin(); i != _loaders.end(); ++i) { - if ((*i)->getType() == type) - return (*i).get(); - } - return 0; } } // end of namespace Kyra diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 5ecbd145fe..cfefa6e3b0 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -35,77 +35,16 @@ #include "common/hashmap.h" #include "common/stream.h" #include "common/ptr.h" +#include "common/archive.h" #include "kyra/kyra_v1.h" #include "kyra/kyra_hof.h" namespace Kyra { -struct ResFileEntry { - Common::String parent; - mutable ResFileEntry *parentEntry; // Cache to avoid lookup by string in the map - // No smart invalidation is needed because the map is cleared globally - // or expanded but no element is ever removed - uint32 size; - - bool preload; - bool mounted; - bool prot; - - enum kType { - kRaw = 0, - kPak = 1, - kInsMal = 2, - kTlk = 3, - kAutoDetect - }; - kType type; - uint32 offset; -}; - -struct CompFileEntry { - uint32 size; - uint8 *data; -}; - -typedef Common::HashMap ResFileMap; -typedef Common::HashMap CompFileMap; class Resource; -class ResArchiveLoader { -public: - struct File { - File() : filename(), entry() {} - File(const Common::String &f, const ResFileEntry &e) : filename(f), entry(e) {} - - bool operator ==(const Common::String &r) const { - return filename.equalsIgnoreCase(r); - } - - Common::String filename; - ResFileEntry entry; - }; - typedef Common::List FileList; - - virtual ~ResArchiveLoader() {} - - virtual bool checkFilename(Common::String filename) const = 0; - virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0; - virtual bool loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const = 0; - // parameter 'archive' can be deleted by this method and it may not be deleted from the caller - virtual Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const = 0; - - virtual ResFileEntry::kType getType() const = 0; -protected: -}; - -class CompArchiveLoader { -public: - virtual ~CompArchiveLoader() {} - - virtual bool checkForFiles() const = 0; - virtual bool loadFile(CompFileMap &loadTo) const = 0; -}; +class ResArchiveLoader; class Resource { public: @@ -114,9 +53,9 @@ public: bool reset(); - bool loadPakFile(const Common::String &filename); - void unloadPakFile(const Common::String &filename); - bool isInPakList(const Common::String &filename); + bool loadPakFile(Common::String filename); + void unloadPakFile(Common::String filename); + bool isInPakList(Common::String filename); bool loadFileList(const Common::String &filedata); bool loadFileList(const char * const *filelist, uint32 numFiles); @@ -130,32 +69,20 @@ public: bool loadFileToBuf(const char *file, void *buf, uint32 maxSize); protected: - void checkFile(const Common::String &file); - bool isAccessible(const Common::String &file); - bool isAccessible(const ResFileEntry *fileEntry); + typedef Common::HashMap ArchiveMap; + ArchiveMap _archiveCache; - void detectFileTypes(); - void detectFileType(const Common::String &filename, ResFileEntry *fileEntry); + Common::SearchSet _files; + Common::SharedPtr _archiveFiles; + Common::SharedPtr _protectedFiles; + + Common::ArchivePtr loadArchive(const Common::String &file); + Common::ArchivePtr loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset); void initializeLoaders(); - const ResArchiveLoader *getLoader(ResFileEntry::kType type) const; + typedef Common::List > LoaderList; - typedef LoaderList::iterator LoaderIterator; - typedef LoaderList::const_iterator CLoaderIterator; LoaderList _loaders; - ResFileMap _map; - - ResFileEntry *getParentEntry(const ResFileEntry *entry) const; - ResFileEntry *getParentEntry(const Common::String &filename) const; - - typedef Common::List > CompLoaderList; - typedef CompLoaderList::iterator CompLoaderIterator; - typedef CompLoaderList::const_iterator CCompLoaderIterator; - CompLoaderList _compLoaders; - CompFileMap _compFiles; - - void tryLoadCompFiles(); - void clearCompFileList(); KyraEngine_v1 *_vm; }; diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp new file mode 100644 index 0000000000..e6b3b14c8a --- /dev/null +++ b/engines/kyra/resource_intern.cpp @@ -0,0 +1,1072 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/resource_intern.h" +#include "kyra/resource.h" + +#include "common/stream.h" +#include "common/endian.h" + +namespace Kyra { + +// Implementation of various Archive subclasses + +// -> PlainArchive implementation + +PlainArchive::PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files) + : _owner(owner), _filename(filename), _files() { + for (FileInputList::iterator i = files.begin(); i != files.end(); ++i) { + Entry entry; + + entry.offset = i->offset; + entry.size = i->size; + + _files[i->name] = entry; + } +} + +bool PlainArchive::hasFile(const Common::String &name) { + return (_files.find(name) != _files.end()); +} + +int PlainArchive::getAllNames(Common::StringList &list) { + int count = 0; + + for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) { + list.push_back(i->_key); + ++count; + } + + return count; +} + +Common::SeekableReadStream *PlainArchive::openFile(const Common::String &name) { + FileMap::const_iterator fDesc = _files.find(name); + if (fDesc == _files.end()) + return 0; + + Common::SeekableReadStream *parent = _owner->getFileStream(_filename); + if (!parent) + return 0; + + return new Common::SeekableSubReadStream(parent, fDesc->_value.offset, fDesc->_value.offset + fDesc->_value.size, true); +} + +// -> CachedArchive implementation + +CachedArchive::CachedArchive(const FileInputList &files) + : _files() { + for (FileInputList::iterator i = files.begin(); i != files.end(); ++i) { + Entry entry; + + entry.data = i->data; + entry.size = i->size; + + _files[i->name] = entry; + } +} + +CachedArchive::~CachedArchive() { + for (FileMap::iterator i = _files.begin(); i != _files.end(); ++i) + delete[] i->_value.data; + _files.clear(); +} + +bool CachedArchive::hasFile(const Common::String &name) { + return (_files.find(name) != _files.end()); +} + +int CachedArchive::getAllNames(Common::StringList &list) { + int count = 0; + + for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) { + list.push_back(i->_key); + ++count; + } + + return count; +} + +Common::SeekableReadStream *CachedArchive::openFile(const Common::String &name) { + FileMap::const_iterator fDesc = _files.find(name); + if (fDesc == _files.end()) + return 0; + + return new Common::MemoryReadStream(fDesc->_value.data, fDesc->_value.size, false); +} + +// ResFileLoader implementations + +// -> ResLoaderPak implementation + +bool ResLoaderPak::checkFilename(Common::String filename) const { + filename.toUppercase(); + return (filename.hasSuffix(".PAK") || filename.hasSuffix(".APK") || filename.hasSuffix(".VRM") || filename.hasSuffix(".TLK") || filename.equalsIgnoreCase(StaticResource::staticDataFilename())); +} + +bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { + uint32 filesize = stream.size(); + uint32 offset = 0; + bool switchEndian = false; + bool firstFile = true; + + offset = stream.readUint32LE(); + if (offset > filesize) { + switchEndian = true; + offset = SWAP_BYTES_32(offset); + } + + Common::String file = ""; + while (!stream.eos()) { + // The start offset of a file should never be in the filelist + if (offset < stream.pos() || offset > filesize) + return false; + + byte c = 0; + + file = ""; + + while (!stream.eos() && (c = stream.readByte()) != 0) + file += c; + + if (stream.eos()) + return false; + + // Quit now if we encounter an empty string + if (file.empty()) { + if (firstFile) + return false; + else + break; + } + + firstFile = false; + offset = switchEndian ? stream.readUint32BE() : stream.readUint32LE(); + + if (!offset || offset == filesize) + break; + } + + return true; +} + +namespace { + +Common::String readString(Common::SeekableReadStream &stream) { + Common::String result; + char c = 0; + + while ((c = stream.readByte()) != 0) + result += c; + + return result; +} + +struct PlainArchiveListSearch { + PlainArchiveListSearch(const Common::String &search) : _search(search) {} + + bool operator()(const PlainArchive::InputEntry &entry) { + return _search.equalsIgnoreCase(entry.name); + } + Common::String _search; +}; + +} // end of anonymous namespace + +Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { + uint32 filesize = stream.size(); + + uint32 startoffset = 0, endoffset = 0; + bool switchEndian = false; + bool firstFile = true; + + startoffset = stream.readUint32LE(); + if (startoffset > filesize) { + switchEndian = true; + startoffset = SWAP_BYTES_32(startoffset); + } + + PlainArchive::FileInputList files; + + Common::String file = ""; + while (!stream.eos()) { + // The start offset of a file should never be in the filelist + if (startoffset < stream.pos() || startoffset > filesize) { + warning("PAK file '%s' is corrupted", filename.c_str()); + return false; + } + + file = ""; + byte c = 0; + + while (!stream.eos() && (c = stream.readByte()) != 0) + file += c; + + if (stream.eos()) { + warning("PAK file '%s' is corrupted", filename.c_str()); + return false; + } + + // Quit now if we encounter an empty string + if (file.empty()) { + if (firstFile) { + warning("PAK file '%s' is corrupted", filename.c_str()); + return false; + } else { + break; + } + } + + firstFile = false; + endoffset = switchEndian ? stream.readUint32BE() : stream.readUint32LE(); + + if (!endoffset) + endoffset = filesize; + + if (startoffset != endoffset) { + PlainArchive::InputEntry entry; + entry.size = endoffset - startoffset; + entry.offset = startoffset; + entry.name = file; + + files.push_back(entry); + } + + if (endoffset == filesize) + break; + + startoffset = endoffset; + } + + PlainArchive::FileInputList::const_iterator iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch("LINKLIST")); + if (iter != files.end()) { + stream.seek(iter->offset, SEEK_SET); + + uint32 magic = stream.readUint32BE(); + + if (magic != MKID_BE('SCVM')) + error("LINKLIST file does not contain 'SCVM' header"); + + uint32 links = stream.readUint32BE(); + for (uint i = 0; i < links; ++i) { + Common::String linksTo = readString(stream); + uint32 sources = stream.readUint32BE(); + + iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch(linksTo)); + if (iter == files.end()) + error("PAK file link destination '%s' not found", linksTo.c_str()); + + for (uint j = 0; j < sources; ++j) { + Common::String dest = readString(stream); + files.push_back(*iter); + // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it + iter = Common::find_if(files.begin(), files.end(), PlainArchiveListSearch(linksTo)); + } + } + } + + return new PlainArchive(owner, filename, files); +} + +// -> ResLoaderInsMalcolm implementation + +bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const { + filename.toUppercase(); + if (!filename.hasSuffix(".001")) + return false; + return true; +} + +bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { + stream.seek(3, SEEK_SET); + uint32 size = stream.readUint32LE(); + + if (size+7 > stream.size()) + return false; + + stream.seek(size+5, SEEK_SET); + uint8 buffer[2]; + stream.read(&buffer, 2); + + return (buffer[0] == 0x0D && buffer[1] == 0x0A); +} + +Common::Archive *ResLoaderInsMalcolm::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { + Common::List filenames; + PlainArchive::FileInputList files; + + // thanks to eriktorbjorn for this code (a bit modified though) + stream.seek(3, SEEK_SET); + + // first file is the index table + uint32 size = stream.readUint32LE(); + Common::String temp = ""; + + for (uint32 i = 0; i < size; ++i) { + byte c = stream.readByte(); + + if (c == '\\') { + temp = ""; + } else if (c == 0x0D) { + // line endings are CRLF + c = stream.readByte(); + assert(c == 0x0A); + ++i; + + filenames.push_back(temp); + } else { + temp += (char)c; + } + } + + stream.seek(3, SEEK_SET); + + for (Common::List::iterator file = filenames.begin(); file != filenames.end(); ++file) { + PlainArchive::InputEntry entry; + entry.size = stream.readUint32LE(); + entry.offset = stream.pos(); + entry.name = *file; + stream.seek(entry.size, SEEK_CUR); + + files.push_back(entry); + } + + return new PlainArchive(owner, filename, files); +} + +bool ResLoaderTlk::checkFilename(Common::String filename) const { + filename.toUppercase(); + return (filename.hasSuffix(".TLK")); +} + +bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { + uint16 entries = stream.readUint16LE(); + uint32 entryTableSize = (entries * 8); + + if (entryTableSize + 2 > stream.size()) + return false; + + uint32 offset = 0; + + for (uint i = 0; i < entries; ++i) { + stream.readUint32LE(); + offset = stream.readUint32LE(); + + if (offset > stream.size()) + return false; + } + + return true; +} + +Common::Archive *ResLoaderTlk::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { + uint16 entries = stream.readUint16LE(); + PlainArchive::FileInputList files; + + for (uint i = 0; i < entries; ++i) { + PlainArchive::InputEntry entry; + + uint32 resFilename = stream.readUint32LE(); + uint32 resOffset = stream.readUint32LE(); + + entry.offset = resOffset+4; + + char realFilename[20]; + snprintf(realFilename, 20, "%.08u.AUD", resFilename); + entry.name = realFilename; + + uint32 curOffset = stream.pos(); + stream.seek(resOffset, SEEK_SET); + entry.size = stream.readUint32LE(); + stream.seek(curOffset, SEEK_SET); + + files.push_back(entry); + } + + return new PlainArchive(owner, filename, files); +} + +// InstallerLoader implementation + +class FileExpanderSource { +public: + FileExpanderSource(const uint8 *data, int dataSize) : _dataPtr(data), _endofBuffer(data + dataSize), _bitsLeft(8), _key(0), _index(0) {} + ~FileExpanderSource() {} + + void advSrcRefresh(); + void advSrcBitsBy1(); + void advSrcBitsByIndex(uint8 newIndex); + + uint8 getKeyLower() { return _key & 0xff; } + void setIndex(uint8 index) { _index = index; } + uint16 getKeyMasked(uint8 newIndex); + uint16 keyMaskedAlign(uint16 val); + + void copyBytes(uint8 *& dst); + +private: + const uint8 *_dataPtr; + const uint8 *_endofBuffer; + uint16 _key; + int8 _bitsLeft; + uint8 _index; +}; + +void FileExpanderSource::advSrcBitsBy1() { + _key >>= 1; + if (!--_bitsLeft) { + if (_dataPtr < _endofBuffer) + _key = ((*_dataPtr++) << 8 ) | (_key & 0xff); + _bitsLeft = 8; + } +} + +void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) { + _index = newIndex; + _bitsLeft -= _index; + if (_bitsLeft <= 0) { + _key >>= (_index + _bitsLeft); + _index = -_bitsLeft; + _bitsLeft = 8 - _index; + if (_dataPtr < _endofBuffer) + _key = (*_dataPtr++ << 8) | (_key & 0xff); + } + _key >>= _index; +} + +uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) { + static const uint8 mskTable[] = { 0x0F, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; + _index = newIndex; + uint16 res = 0; + + if (_index > 8) { + newIndex = _index - 8; + res = (_key & 0xff) & mskTable[8]; + advSrcBitsByIndex(8); + _index = newIndex; + res |= (((_key & 0xff) & mskTable[_index]) << 8); + advSrcBitsByIndex(_index); + } else { + res = (_key & 0xff) & mskTable[_index]; + advSrcBitsByIndex(_index); + } + + return res; +} + +void FileExpanderSource::copyBytes(uint8 *& dst) { + advSrcBitsByIndex(_bitsLeft); + uint16 r = (READ_LE_UINT16(_dataPtr) ^ _key) + 1; + _dataPtr += 2; + + if (r) + error("decompression failure"); + + memcpy(dst, _dataPtr, _key); + _dataPtr += _key; + dst += _key; +} + +uint16 FileExpanderSource::keyMaskedAlign(uint16 val) { + val -= 0x101; + _index = (val & 0xff) >> 2; + int16 b = ((_bitsLeft << 8) | _index) - 1; + _bitsLeft = b >> 8; + _index = b & 0xff; + uint16 res = (((val & 3) + 4) << _index) + 0x101; + return res + getKeyMasked(_index); +} + +void FileExpanderSource::advSrcRefresh() { + _key = READ_LE_UINT16(_dataPtr); + if (_dataPtr < _endofBuffer - 1) + _dataPtr += 2; + _bitsLeft = 8; +} + +class FileExpander { +public: + FileExpander(); + ~FileExpander(); + + bool process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 insize); + +private: + void generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt); + uint8 calcCmdAndIndex(const uint8 *tbl, int16 ¶); + + FileExpanderSource *_src; + uint8 *_tables[9]; + uint16 *_tables16[3]; +}; + +FileExpander::FileExpander() : _src(0) { + _tables[0] = new uint8[3914]; + assert(_tables[0]); + + _tables[1] = _tables[0] + 320; + _tables[2] = _tables[0] + 352; + _tables[3] = _tables[0] + 864; + _tables[4] = _tables[0] + 2016; + _tables[5] = _tables[0] + 2528; + _tables[6] = _tables[0] + 2656; + _tables[7] = _tables[0] + 2736; + _tables[8] = _tables[0] + 2756; + + _tables16[0] = (uint16 *)(_tables[0] + 3268); + _tables16[1] = (uint16 *)(_tables[0] + 3302); + _tables16[2] = (uint16 *)(_tables[0] + 3338); +} + +FileExpander::~FileExpander() { + delete _src; + delete[] _tables[0]; +} + +bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 compressedSize) { + static const uint8 indexTable[] = { + 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, 0x0A, + 0x05, 0x0B, 0x04, 0x0C, 0x03, 0x0D, 0x02, 0x0E, 0x01, 0x0F + }; + + memset(_tables[0], 0, 3914); + + uint8 *d = dst; + uint16 tableSize0 = 0; + uint16 tableSize1 = 0; + bool needrefresh = true; + bool postprocess = false; + + _src = new FileExpanderSource(src, compressedSize); + + while (d < dst + outsize) { + + if (needrefresh) { + needrefresh = false; + _src->advSrcRefresh(); + } + + _src->advSrcBitsBy1(); + + int mode = _src->getKeyMasked(2) - 1; + if (mode == 1) { + tableSize0 = _src->getKeyMasked(5) + 257; + tableSize1 = _src->getKeyMasked(5) + 1; + memset(_tables[7], 0, 19); + + const uint8 *itbl = indexTable; + int numbytes = _src->getKeyMasked(4) + 4; + + while (numbytes--) + _tables[7][*itbl++] = _src->getKeyMasked(3); + + generateTables(7, 8, 255, 19); + + int cnt = tableSize0 + tableSize1; + uint8 *tmp = _tables[0]; + + while (cnt) { + uint16 cmd = _src->getKeyLower(); + cmd = READ_LE_UINT16(&_tables[8][cmd << 1]); + _src->advSrcBitsByIndex(_tables[7][cmd]); + + if (cmd < 16) { + *tmp++ = cmd; + cnt--; + } else { + uint8 tmpI = 0; + if (cmd == 16) { + cmd = _src->getKeyMasked(2) + 3; + tmpI = *(tmp - 1); + } else if (cmd == 17) { + cmd = _src->getKeyMasked(3) + 3; + } else { + cmd = _src->getKeyMasked(7) + 11; + } + _src->setIndex(tmpI); + memset(tmp, tmpI, cmd); + tmp += cmd; + + cnt -= cmd; + if (cnt < 0) + error("decompression failure"); + } + } + + memcpy(_tables[1], _tables[0] + tableSize0, tableSize1); + generateTables(0, 2, 3, tableSize0); + generateTables(1, 4, 5, tableSize1); + postprocess = true; + } else if (mode < 0) { + _src->copyBytes(d); + postprocess = false; + needrefresh = true; + } else if (mode == 0){ + uint8 *d2 = _tables[0]; + memset(d2, 8, 144); + memset(d2 + 144, 9, 112); + memset(d2 + 256, 7, 24); + memset(d2 + 280, 8, 8); + d2 = _tables[1]; + memset(d2, 5, 32); + tableSize0 = 288; + tableSize1 = 32; + + generateTables(0, 2, 3, tableSize0); + generateTables(1, 4, 5, tableSize1); + postprocess = true; + } else { + error("decompression failure"); + } + + if (!postprocess) + continue; + + int16 cmd = 0; + + do { + cmd = ((int16*) _tables[2])[_src->getKeyLower()]; + _src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]); + + if (cmd == 0x11d) { + cmd = 0x200; + } else if (cmd > 0x108) { + cmd = _src->keyMaskedAlign(cmd); + } + + if (!(cmd >> 8)) { + *d++ = cmd & 0xff; + } else if (cmd != 0x100) { + cmd -= 0xfe; + int16 offset = ((int16*) _tables[4])[_src->getKeyLower()]; + _src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]); + if ((offset & 0xff) >= 4) { + uint8 newIndex = ((offset & 0xff) >> 1) - 1; + offset = (((offset & 1) + 2) << newIndex); + offset += _src->getKeyMasked(newIndex); + } + + uint8 *s2 = d - 1 - offset; + if (s2 >= dst) { + while (cmd--) + *d++ = *s2++; + } else { + uint32 pos = dst - s2; + s2 += (d - dst); + + if (pos < (uint32) cmd) { + cmd -= pos; + while (pos--) + *d++ = *s2++; + s2 = dst; + } + while (cmd--) + *d++ = *s2++; + } + } + } while (cmd != 0x100); + } + + delete _src; + _src = 0; + + return true; +} + +void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) { + const uint8 *tbl1 = _tables[srcIndex]; + uint8 *tbl2 = _tables[dstIndex]; + const uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2]; + + if (!cnt) + return; + + const uint8 *s = tbl1; + memset(_tables16[0], 0, 32); + + for (int i = 0; i < cnt; i++) + _tables16[0][(*s++)]++; + + _tables16[1][1] = 0; + + for (uint16 i = 1, r = 0; i < 16; i++) { + r = (r + _tables16[0][i]) << 1; + _tables16[1][i + 1] = r; + } + + if (_tables16[1][16]) { + uint16 r = 0; + for (uint16 i = 1; i < 16; i++) + r += _tables16[0][i]; + if (r > 1) + error("decompression failure"); + } + + s = tbl1; + uint16 *d = _tables16[2]; + for (int i = 0; i < cnt; i++) { + uint16 t = *s++; + if (t) { + _tables16[1][t]++; + t = _tables16[1][t] - 1; + } + *d++ = t; + } + + s = tbl1; + d = _tables16[2]; + for (int i = 0; i < cnt; i++) { + int8 t = ((int8)(*s++)) - 1; + if (t > 0) { + uint16 v1 = *d; + uint16 v2 = 0; + + do { + v2 = (v2 << 1) | (v1 & 1); + v1 >>= 1; + } while (--t && v1); + + t++; + uint8 c1 = (v1 & 1); + while (t--) { + uint8 c2 = v2 >> 15; + v2 = (v2 << 1) | c1; + c1 = c2; + }; + + *d++ = v2; + } else { + d++; + } + } + + memset(tbl2, 0, 512); + + cnt--; + s = tbl1 + cnt; + d = &_tables16[2][cnt]; + uint16 * bt = (uint16*) tbl3; + uint16 inc = 0; + uint16 cnt2 = 0; + + do { + uint8 t = *s--; + uint16 *s2 = (uint16*) tbl2; + + if (t && t < 9) { + inc = 1 << t; + uint16 o = *d; + + do { + s2[o] = cnt; + o += inc; + } while (!(o & 0xf00)); + + } else if (t > 8) { + if (!bt) + error("decompression failure"); + + t -= 8; + uint8 shiftCnt = 1; + uint8 v = (*d) >> 8; + s2 = &((uint16*) tbl2)[*d & 0xff]; + + do { + if (!*s2) { + *s2 = (uint16)(~cnt2); + *(uint32*)&bt[cnt2] = 0; + cnt2 += 2; + } + + s2 = &bt[(uint16)(~*s2)]; + if (v & shiftCnt) + s2++; + + shiftCnt <<= 1; + } while (--t); + *s2 = cnt; + } + d--; + } while (--cnt >= 0); +} + +uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 ¶) { + const uint16 *t = (const uint16*)tbl; + _src->advSrcBitsByIndex(8); + uint8 newIndex = 0; + uint16 v = _src->getKeyLower(); + + do { + newIndex++; + para = t[((~para) & 0xfffe) | (v & 1)]; + v >>= 1; + } while (para < 0); + + return newIndex; +} + +namespace { + +struct InsArchive { + Common::String filename; + uint32 firstFile; + uint32 startOffset; + uint32 lastFile; + uint32 endOffset; + uint32 totalSize; +}; + +} // end of anonymouse namespace + +Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &filename, const Common::String &extension, const uint8 containerOffset) { + uint32 pos = 0; + uint32 bytesleft = 0; + bool startFile = true; + + Common::String filenameBase =filename; + Common::String filenameTemp; + char filenameExt[4]; + + if (filenameBase.lastChar() != '.') + filenameBase += '.'; + + InsArchive newArchive; + Common::List archives; + + Common::SeekableReadStream *tmpFile = 0; + + for (int8 currentFile = 1; currentFile; currentFile++) { + sprintf(filenameExt, extension.c_str(), currentFile); + filenameTemp = filenameBase + Common::String(filenameExt); + + if (!(tmpFile = owner->getFileStream(filenameTemp))) { + debug(3, "couldn't open file '%s'\n", filenameTemp.c_str()); + break; + } + + tmpFile->seek(pos, SEEK_SET); + uint8 fileId = tmpFile->readByte(); + pos++; + + uint32 size = tmpFile->size() - 1; + if (startFile) { + size -= 4; + if (fileId == currentFile) { + size -= containerOffset; + pos += containerOffset; + tmpFile->seek(containerOffset, SEEK_CUR); + } else { + size = size + 1 - pos; + } + newArchive.filename = filenameBase; + bytesleft = newArchive.totalSize = tmpFile->readUint32LE(); + pos += 4; + newArchive.firstFile = currentFile; + newArchive.startOffset = pos; + startFile = false; + } + + uint32 cs = MIN(size, bytesleft); + bytesleft -= cs; + + delete tmpFile; + tmpFile = 0; + + pos += cs; + if (cs == size) { + if (!bytesleft) { + newArchive.lastFile = currentFile; + newArchive.endOffset = --pos; + archives.push_back(newArchive); + currentFile = -1; + } else { + pos = 0; + } + } else { + startFile = true; + bytesleft = size - cs; + newArchive.lastFile = currentFile--; + newArchive.endOffset = --pos; + archives.push_back(newArchive); + } + } + + FileExpander exp; + CachedArchive::InputEntry newEntry; + uint32 insize = 0; + uint32 outsize = 0; + uint8 *inbuffer = 0; + uint8 *outbuffer = 0; + uint32 inPart1 = 0; + uint32 inPart2 = 0; + uint8 compressionType = 0; + Common::String entryStr; + + CachedArchive::FileInputList fileList; + + pos = 0; + + const uint32 kExecSize = 0x0bba; + const uint32 kHeaderSize = 30; + const uint32 kHeaderSize2 = 46; + + for (Common::List::iterator a = archives.begin(); a != archives.end(); ++a) { + startFile = true; + for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) { + sprintf(filenameExt, extension.c_str(), i); + filenameTemp = a->filename + Common::String(filenameExt); + + if (!(tmpFile = owner->getFileStream(filenameTemp))) { + debug(3, "couldn't open file '%s'\n", filenameTemp.c_str()); + break; + } + + uint32 size = (i == a->lastFile) ? a->endOffset : tmpFile->size(); + + if (startFile) { + startFile = false; + pos = a->startOffset + kExecSize; + if (pos > size) { + pos -= size; + delete tmpFile; + tmpFile = 0; + continue; + } + } else { + if (inPart2) { + tmpFile->seek(1, SEEK_SET); + tmpFile->read(inbuffer + inPart1, inPart2); + inPart2 = 0; + + if (compressionType > 0) + exp.process(outbuffer, inbuffer, outsize, insize); + else + memcpy(outbuffer, inbuffer, outsize); + + delete[] inbuffer; + inbuffer = 0; + newEntry.data = outbuffer; + newEntry.size = outsize; + newEntry.name = entryStr; + fileList.push_back(newEntry); + } + pos++; + } + + while (pos < size) { + uint8 hdr[43]; + uint32 m = 0; + tmpFile->seek(pos, SEEK_SET); + + if (pos + 42 > size) { + m = size - pos; + uint32 b = 42 - m; + + if (m >= 4) { + uint32 id = tmpFile->readUint32LE(); + if (id == 0x06054B50) { + startFile = true; + break; + } else { + tmpFile->seek(pos, SEEK_SET); + } + } + + sprintf(filenameExt, extension.c_str(), i + 1); + filenameTemp = a->filename + Common::String(filenameExt); + + Common::SeekableReadStream *tmpFile2 = owner->getFileStream(filenameTemp); + tmpFile->read(hdr, m); + tmpFile2->read(hdr + m, b); + delete tmpFile2; + } else { + tmpFile->read(hdr, 42); + } + + uint32 id = READ_LE_UINT32(hdr); + + if (id == 0x04034B50) { + compressionType = hdr[8]; + insize = READ_LE_UINT32(hdr + 18); + outsize = READ_LE_UINT32(hdr + 22); + + uint16 filestrlen = READ_LE_UINT16(hdr + 26); + *(hdr + 30 + filestrlen) = 0; + entryStr = Common::String((const char *)(hdr + 30)); + pos += (kHeaderSize + filestrlen - m); + tmpFile->seek(pos, SEEK_SET); + + outbuffer = new uint8[outsize]; + if (!outbuffer) + error("Out of memory: Can't uncompress installer files"); + + if (!inbuffer) { + inbuffer = new uint8[insize]; + if (!inbuffer) + error("Out of memory: Can't uncompress installer files"); + } + + if ((pos + insize) > size) { + // this is for files that are split between two archive files + inPart1 = size - pos; + inPart2 = insize - inPart1; + tmpFile->read(inbuffer, inPart1); + } else { + tmpFile->read(inbuffer, insize); + inPart2 = 0; + + if (compressionType > 0) + exp.process(outbuffer, inbuffer, outsize, insize); + else + memcpy(outbuffer, inbuffer, outsize); + + delete[] inbuffer; + inbuffer = 0; + newEntry.data = outbuffer; + newEntry.size = outsize; + newEntry.name = entryStr; + fileList.push_back(newEntry); + } + + pos += insize; + if (pos > size) { + pos -= size; + break; + } + } else { + uint32 filestrlen = READ_LE_UINT32(hdr + 28); + pos += (kHeaderSize2 + filestrlen - m); + } + } + delete tmpFile; + tmpFile = 0; + } + } + + archives.clear(); + return new CachedArchive(fileList); +} + +} // end of namespace Kyra diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h new file mode 100644 index 0000000000..13546d7768 --- /dev/null +++ b/engines/kyra/resource_intern.h @@ -0,0 +1,131 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_RESOURCE_INTERN_H +#define KYRA_RESOURCE_INTERN_H + +#include "common/archive.h" +#include "common/hash-str.h" +#include "common/hashmap.h" +#include "common/str.h" +#include "common/list.h" + +namespace Kyra { + +class Resource; + +class PlainArchive : public Common::Archive { +public: + struct InputEntry { + Common::String name; + + uint32 offset; + uint32 size; + }; + + typedef Common::List FileInputList; + + PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files); + + bool hasFile(const Common::String &name); + int getAllNames(Common::StringList &list); + Common::SeekableReadStream *openFile(const Common::String &name); +private: + struct Entry { + uint32 offset; + uint32 size; + }; + + typedef Common::HashMap FileMap; + + Resource *_owner; + Common::String _filename; + FileMap _files; +}; + +class CachedArchive : public Common::Archive { +public: + struct InputEntry { + Common::String name; + + byte *data; + uint32 size; + }; + + typedef Common::List FileInputList; + + CachedArchive(const FileInputList &files); + ~CachedArchive(); + + bool hasFile(const Common::String &name); + int getAllNames(Common::StringList &list); + Common::SeekableReadStream *openFile(const Common::String &name); +private: + struct Entry { + byte *data; + uint32 size; + }; + + typedef Common::HashMap FileMap; + FileMap _files; +}; + + +class ResArchiveLoader { +public: + virtual bool checkFilename(Common::String filename) const = 0; + virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0; + virtual Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const = 0; +}; + +class ResLoaderPak : public ResArchiveLoader { +public: + bool checkFilename(Common::String filename) const; + bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; + Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const; +}; + +class ResLoaderInsMalcolm : public ResArchiveLoader { +public: + bool checkFilename(Common::String filename) const; + bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; + Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const; +}; + +class ResLoaderTlk : public ResArchiveLoader { +public: + bool checkFilename(Common::String filename) const; + bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; + Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const; +}; + +class InstallerLoader { +public: + static Common::Archive *load(Resource *owner, const Common::String &filename, const Common::String &extension, const uint8 offset); +}; + +} // end of namespace Kyra + +#endif -- cgit v1.2.3 From 3c48fb7eaec11a81ee90577ee2e94bfa209aee69 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 7 Sep 2008 22:00:04 +0000 Subject: Fix warning about missing virtual destructor svn-id: r34433 --- engines/kyra/resource_intern.h | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/kyra') diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h index 13546d7768..1335be5e4e 100644 --- a/engines/kyra/resource_intern.h +++ b/engines/kyra/resource_intern.h @@ -95,6 +95,7 @@ private: class ResArchiveLoader { public: + virtual ~ResArchiveLoader() {} virtual bool checkFilename(Common::String filename) const = 0; virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0; virtual Common::Archive *load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const = 0; -- cgit v1.2.3 From bd10e674a3c5e7b3ac87aaa405565a3f532de52c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 7 Sep 2008 22:30:34 +0000 Subject: Got rid of all Common::File usages in Kyra. svn-id: r34435 --- engines/kyra/resource.cpp | 25 ++++---- engines/kyra/resource.h | 2 +- engines/kyra/sound_towns.cpp | 4 +- engines/kyra/staticres.cpp | 16 ++--- engines/kyra/vqa.cpp | 138 ++++++++++++++++++++++--------------------- engines/kyra/vqa.h | 4 +- 6 files changed, 96 insertions(+), 93 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 362c6a205d..fe2b24e856 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -61,7 +61,7 @@ bool Resource::reset() { if (!dir.exists() || !dir.isDirectory()) error("invalid game path '%s'", dir.getPath().c_str()); - if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat()) { + if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat(this)) { Common::String errorMessage = "You're missing the '" + StaticResource::staticDataFilename() + "' file or it got corrupted, (re)get it from the ScummVM website"; _vm->GUIErrorMessage(errorMessage); error(errorMessage.c_str()); @@ -71,10 +71,6 @@ bool Resource::reset() { // We only need kyra.dat for the demo. if (_vm->gameFlags().isDemo) return true; - - // only VRM file we need in the *whole* game for kyra1 - if (_vm->gameFlags().isTalkie) - loadPakFile("CHAPTER1.VRM"); } else if (_vm->game() == GI_KYRA2) { if (_vm->gameFlags().useInstallerPackage) _files.add("installer", loadInstallerArchive("WESTWOOD", "%03d", 6), 2); @@ -118,7 +114,8 @@ bool Resource::reset() { for (uint i = 0; i < ARRAYSIZE(list); ++i) { Common::ArchivePtr archive = loadArchive(list[i]); - _protectedFiles->add(list[i], archive, 0); + if (archive) + _protectedFiles->add(list[i], archive, 0); } } else { for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { @@ -158,20 +155,20 @@ bool Resource::loadPakFile(Common::String filename) { } bool Resource::loadFileList(const Common::String &filedata) { - Common::File f; + Common::SeekableReadStream *f = getFileStream(filedata); - if (!f.open(filedata)) + if (!f) return false; uint32 filenameOffset = 0; - while ((filenameOffset = f.readUint32LE()) != 0) { - uint32 offset = f.pos(); - f.seek(filenameOffset, SEEK_SET); + while ((filenameOffset = f->readUint32LE()) != 0) { + uint32 offset = f->pos(); + f->seek(filenameOffset, SEEK_SET); uint8 buffer[13]; - f.read(buffer, sizeof(buffer)-1); + f->read(buffer, sizeof(buffer)-1); buffer[12] = 0; - f.seek(offset + 16, SEEK_SET); + f->seek(offset + 16, SEEK_SET); Common::String filename = Common::String((char *)buffer); filename.toUppercase(); @@ -183,12 +180,14 @@ bool Resource::loadFileList(const Common::String &filedata) { // so we don't do anything here if they are non // existant. } else if (!loadPakFile(filename)) { + delete f; error("couldn't load file '%s'", filename.c_str()); return false; } } } + delete f; return true; } diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index cfefa6e3b0..54b845c5c9 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -212,7 +212,7 @@ public: StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _builtIn(0), _filenameTable(0) {} ~StaticResource() { deinit(); } - static bool checkKyraDat(); + static bool checkKyraDat(Resource *res); bool init(); void deinit(); diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index c57636a3fb..5bb09e5dc9 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -4122,9 +4122,9 @@ bool SoundTownsPC98_v2::init() { // this misses the possibility that we play the tracks // right off CD. So we should find another way to // check if we have access to CD audio. + Resource *res = _vm->resource(); if (_musicEnabled && - (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || - Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) + (res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla"))) _musicEnabled = 2; return _driver->init(); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 9156fa7e9c..78d0961011 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -45,20 +45,20 @@ namespace Kyra { #define RESFILE_VERSION 32 -bool StaticResource::checkKyraDat() { - Common::File kyraDat; - if (!kyraDat.open(StaticResource::staticDataFilename())) +bool StaticResource::checkKyraDat(Resource *res) { + Common::SharedPtr kyraDat(res->getFileStream(StaticResource::staticDataFilename())); + if (!kyraDat) return false; - uint32 size = kyraDat.size() - 16; + uint32 size = kyraDat->size() - 16; uint8 digest[16]; - kyraDat.seek(size, SEEK_SET); - if (kyraDat.read(digest, 16) != 16) + kyraDat->seek(size, SEEK_SET); + if (kyraDat->read(digest, 16) != 16) return false; - kyraDat.close(); uint8 digestCalc[16]; - if (!Common::md5_file(StaticResource::staticDataFilename().c_str(), digestCalc, size)) + kyraDat->seek(0, SEEK_SET); + if (!Common::md5_file(*kyraDat, digestCalc, size)) return false; for (int i = 0; i < 16; ++i) diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index d5b63bdf6b..9a9941e20e 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -38,6 +38,7 @@ #include "kyra/sound.h" #include "kyra/screen.h" #include "kyra/vqa.h" +#include "kyra/resource.h" namespace Kyra { @@ -90,10 +91,10 @@ uint32 VQAMovie::readTag() { // Some tags have to be on an even offset, so they are padded with a // zero byte. Skip that. - uint32 tag = _file.readUint32BE(); + uint32 tag = _file->readUint32BE(); if (!(tag & 0xFF000000)) { - tag = (tag << 8) | _file.readByte(); + tag = (tag << 8) | _file->readByte(); } return tag; @@ -184,18 +185,19 @@ bool VQAMovie::open(const char *filename) { debugC(9, kDebugLevelMovie, "VQAMovie::open('%s')", filename); close(); - if (!_file.open(filename)) + _file = _vm->resource()->getFileStream(filename); + if (!_file) return false; - if (_file.readUint32BE() != MKID_BE('FORM')) { + if (_file->readUint32BE() != MKID_BE('FORM')) { warning("VQAMovie::open: Cannot find `FORM' tag"); return false; } // For now, we ignore the size of the FORM chunk. - _file.readUint32BE(); + _file->readUint32BE(); - if (_file.readUint32BE() != MKID_BE('WVQA')) { + if (_file->readUint32BE() != MKID_BE('WVQA')) { warning("WQAMovie::open: Cannot find `WVQA' tag"); return false; } @@ -208,30 +210,30 @@ bool VQAMovie::open(const char *filename) { while (!foundHeader || !foundFrameInfo) { uint32 tag = readTag(); - uint32 size = _file.readUint32BE(); + uint32 size = _file->readUint32BE(); switch (tag) { case MKID_BE('VQHD'): // VQA header - _header.version = _file.readUint16LE(); - _header.flags = _file.readUint16LE(); - _header.numFrames = _file.readUint16LE(); - _header.width = _file.readUint16LE(); - _header.height = _file.readUint16LE(); - _header.blockW = _file.readByte(); - _header.blockH = _file.readByte(); - _header.frameRate = _file.readByte(); - _header.cbParts = _file.readByte(); - _header.colors = _file.readUint16LE(); - _header.maxBlocks = _file.readUint16LE(); - _header.unk1 = _file.readUint32LE(); - _header.unk2 = _file.readUint16LE(); - _header.freq = _file.readUint16LE(); - _header.channels = _file.readByte(); - _header.bits = _file.readByte(); - _header.unk3 = _file.readUint32LE(); - _header.unk4 = _file.readUint16LE(); - _header.maxCBFZSize = _file.readUint32LE(); - _header.unk5 = _file.readUint32LE(); + _header.version = _file->readUint16LE(); + _header.flags = _file->readUint16LE(); + _header.numFrames = _file->readUint16LE(); + _header.width = _file->readUint16LE(); + _header.height = _file->readUint16LE(); + _header.blockW = _file->readByte(); + _header.blockH = _file->readByte(); + _header.frameRate = _file->readByte(); + _header.cbParts = _file->readByte(); + _header.colors = _file->readUint16LE(); + _header.maxBlocks = _file->readUint16LE(); + _header.unk1 = _file->readUint32LE(); + _header.unk2 = _file->readUint16LE(); + _header.freq = _file->readUint16LE(); + _header.channels = _file->readByte(); + _header.bits = _file->readByte(); + _header.unk3 = _file->readUint32LE(); + _header.unk4 = _file->readUint16LE(); + _header.maxCBFZSize = _file->readUint32LE(); + _header.unk5 = _file->readUint32LE(); // Kyrandia 3 uses version 1 VQA files, and is the only // known game to do so. This version of the format has @@ -301,7 +303,7 @@ bool VQAMovie::open(const char *filename) { foundFrameInfo = true; for (int i = 0; i < _header.numFrames; i++) { - _frameInfo[i] = 2 * _file.readUint32LE(); + _frameInfo[i] = 2 * _file->readUint32LE(); } // HACK: This flag is set in jung2.vqa, and its @@ -317,31 +319,31 @@ bool VQAMovie::open(const char *filename) { // to the first VQFR chunk. if (_frameInfo[0] & 0x01000000) { - uint32 oldPos = _file.pos(); + uint32 oldPos = _file->pos(); while (1) { uint32 scanTag = readTag(); - uint32 scanSize = _file.readUint32BE(); + uint32 scanSize = _file->readUint32BE(); - if (_file.eos()) + if (_file->eos()) break; if (scanTag == MKID_BE('VQFR')) { - _frameInfo[0] = (_file.pos() - 8) | 0x80000000; + _frameInfo[0] = (_file->pos() - 8) | 0x80000000; break; } - _file.seek(scanSize, SEEK_CUR); + _file->seek(scanSize, SEEK_CUR); } - _file.seek(oldPos); + _file->seek(oldPos); } break; default: warning("VQAMovie::open: Unknown tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF)); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; } } @@ -372,8 +374,8 @@ void VQAMovie::close() { _vectorPointers = NULL; _stream = NULL; - if (_file.isOpen()) - _file.close(); + delete _file; + _file = 0; freeBuffers(); @@ -390,13 +392,13 @@ void VQAMovie::displayFrame(uint frameNum) { bool foundFrame = false; uint i; - _file.seek(_frameInfo[frameNum] & 0x7FFFFFFF); + _file->seek(_frameInfo[frameNum] & 0x7FFFFFFF); while (!foundSound || !foundFrame) { uint32 tag = readTag(); - uint32 size = _file.readUint32BE(); + uint32 size = _file->readUint32BE(); - if (_file.eos()) { + if (_file->eos()) { // This happens at the last frame. Apparently it has // no sound? break; @@ -410,18 +412,18 @@ void VQAMovie::displayFrame(uint frameNum) { case MKID_BE('SND0'): // Uncompressed sound foundSound = true; inbuf = new byte[size]; - _file.read(inbuf, size); + _file->read(inbuf, size); assert(_stream); _stream->queueBuffer(inbuf, size); break; case MKID_BE('SND1'): // Compressed sound, almost like AUD foundSound = true; - outsize = _file.readUint16LE(); - insize = _file.readUint16LE(); + outsize = _file->readUint16LE(); + insize = _file->readUint16LE(); inbuf = new byte[insize]; - _file.read(inbuf, insize); + _file->read(inbuf, insize); if (insize == outsize) { assert(_stream); @@ -438,50 +440,50 @@ void VQAMovie::displayFrame(uint frameNum) { case MKID_BE('SND2'): // Compressed sound foundSound = true; warning("VQAMovie::displayFrame: `SND2' is not implemented"); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; case MKID_BE('VQFR'): foundFrame = true; - end = _file.pos() + size - 8; + end = _file->pos() + size - 8; - while (_file.pos() < end) { + while (_file->pos() < end) { tag = readTag(); - size = _file.readUint32BE(); + size = _file->readUint32BE(); switch (tag) { case MKID_BE('CBF0'): // Full codebook - _file.read(_codeBook, size); + _file->read(_codeBook, size); break; case MKID_BE('CBFZ'): // Full codebook inbuf = (byte *)allocBuffer(0, size); - _file.read(inbuf, size); + _file->read(inbuf, size); Screen::decodeFrame4(inbuf, _codeBook, _codeBookSize); break; case MKID_BE('CBP0'): // Partial codebook _compressedCodeBook = false; - _file.read(_partialCodeBook + _partialCodeBookSize, size); + _file->read(_partialCodeBook + _partialCodeBookSize, size); _partialCodeBookSize += size; _numPartialCodeBooks++; break; case MKID_BE('CBPZ'): // Partial codebook _compressedCodeBook = true; - _file.read(_partialCodeBook + _partialCodeBookSize, size); + _file->read(_partialCodeBook + _partialCodeBookSize, size); _partialCodeBookSize += size; _numPartialCodeBooks++; break; case MKID_BE('CPL0'): // Palette assert(size <= 3 * 256); - _file.read(_vm->screen()->_currentPalette, size); + _file->read(_vm->screen()->_currentPalette, size); break; case MKID_BE('CPLZ'): // Palette inbuf = (byte *)allocBuffer(0, size); - _file.read(inbuf, size); + _file->read(inbuf, size); Screen::decodeFrame4(inbuf, _vm->screen()->_currentPalette, 768); break; @@ -489,14 +491,14 @@ void VQAMovie::displayFrame(uint frameNum) { assert(size / 2 <= _numVectorPointers); for (i = 0; i < size / 2; i++) - _vectorPointers[i] = _file.readUint16LE(); + _vectorPointers[i] = _file->readUint16LE(); break; case MKID_BE('VPTZ'): // Frame data inbuf = (byte *)allocBuffer(0, size); outbuf = (byte *)allocBuffer(1, 2 * _numVectorPointers); - _file.read(inbuf, size); + _file->read(inbuf, size); size = Screen::decodeFrame4(inbuf, outbuf, 2 * _numVectorPointers); assert(size / 2 <= _numVectorPointers); @@ -507,7 +509,7 @@ void VQAMovie::displayFrame(uint frameNum) { default: warning("VQAMovie::displayFrame: Unknown `VQFR' sub-tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF)); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; } @@ -517,7 +519,7 @@ void VQAMovie::displayFrame(uint frameNum) { default: warning("VQAMovie::displayFrame: Unknown tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF)); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; } } @@ -592,11 +594,11 @@ void VQAMovie::play() { uint32 insize, outsize; if (_stream) { - while (_file.pos() < (_frameInfo[0] & 0x7FFFFFFF)) { + while (_file->pos() < (_frameInfo[0] & 0x7FFFFFFF)) { uint32 tag = readTag(); - uint32 size = _file.readUint32BE(); + uint32 size = _file->readUint32BE(); - if (_file.eos()) { + if (_file->eos()) { warning("VQAMovie::play: Unexpected EOF"); break; } @@ -604,16 +606,16 @@ void VQAMovie::play() { switch (tag) { case MKID_BE('SND0'): // Uncompressed sound inbuf = new byte[size]; - _file.read(inbuf, size); + _file->read(inbuf, size); _stream->queueBuffer(inbuf, size); break; case MKID_BE('SND1'): // Compressed sound - outsize = _file.readUint16LE(); - insize = _file.readUint16LE(); + outsize = _file->readUint16LE(); + insize = _file->readUint16LE(); inbuf = new byte[insize]; - _file.read(inbuf, insize); + _file->read(inbuf, insize); if (insize == outsize) { _stream->queueBuffer(inbuf, insize); @@ -627,17 +629,17 @@ void VQAMovie::play() { case MKID_BE('SND2'): // Compressed sound warning("VQAMovie::play: `SND2' is not implemented"); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; case MKID_BE('CMDS'): // Unused tag, always empty in kyra3 debugC(9, kDebugLevelMovie, "VQAMovie::play: skipping CMDS tag"); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; default: warning("VQAMovie::play: Unknown tag `%c%c%c%c'", char((tag >> 24) & 0xFF), char((tag >> 16) & 0xFF), char((tag >> 8) & 0xFF), char(tag & 0xFF)); - _file.seek(size, SEEK_CUR); + _file->seek(size, SEEK_CUR); break; } } diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h index f600f008b7..46d3bd48fb 100644 --- a/engines/kyra/vqa.h +++ b/engines/kyra/vqa.h @@ -26,6 +26,8 @@ #ifndef KYRA_VQA_H #define KYRA_VQA_H +#include "common/stream.h" + class OSystem; namespace Kyra { @@ -98,7 +100,7 @@ protected: void displayFrame(uint frameNum); - Common::File _file; + Common::SeekableReadStream *_file; VQAHeader _header; uint32 *_frameInfo; -- cgit v1.2.3 From 06d57a54f3b2ec623c085d0bcce76df4e3acd50d Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 7 Sep 2008 22:35:13 +0000 Subject: - Fixed regression in Resource::unloadPakFile - Changed priority value for OSystem::addSysArchivesToSearchSet call svn-id: r34436 --- engines/kyra/resource.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index fe2b24e856..51ef9f3e81 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -40,7 +40,8 @@ Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles Common::SharedPtr path(new Common::FSDirectory(ConfMan.get("path"))); Common::SharedPtr extrapath(new Common::FSDirectory(ConfMan.get("extrapath"))); - _vm->_system->addSysArchivesToSearchSet(_files); + + _vm->_system->addSysArchivesToSearchSet(_files, 3); _files.add("path", path, 3); _files.add("extrapath", extrapath, 3); // compressed installer archives are added at level '2', @@ -208,7 +209,8 @@ bool Resource::loadFileList(const char * const *filelist, uint32 numFiles) { void Resource::unloadPakFile(Common::String filename) { filename.toUppercase(); _archiveFiles->remove(filename); - _protectedFiles->remove(filename); + // We do not remove files from '_protectedFiles' here, since + // those are protected against unloading. } bool Resource::isInPakList(Common::String filename) { -- cgit v1.2.3 From a8c4ffa93ffa9062d02f93b327366b681050f5af Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 7 Sep 2008 22:41:57 +0000 Subject: Changed priorities for search paths. (Just in case system specific data paths contain an outdated kyra.dat version) svn-id: r34438 --- engines/kyra/resource.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 51ef9f3e81..bc83111d14 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -41,9 +41,9 @@ Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles Common::SharedPtr path(new Common::FSDirectory(ConfMan.get("path"))); Common::SharedPtr extrapath(new Common::FSDirectory(ConfMan.get("extrapath"))); + _files.add("path", path, 4); + _files.add("extrapath", extrapath, 4); _vm->_system->addSysArchivesToSearchSet(_files, 3); - _files.add("path", path, 3); - _files.add("extrapath", extrapath, 3); // compressed installer archives are added at level '2', // but that's done in Resource::reset not here _files.add("protected", _protectedFiles, 1); -- cgit v1.2.3 From c6b6a99f2ae4f946bd07443f3364ab7ddc0ae3ae Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 8 Sep 2008 18:48:39 +0000 Subject: Fixed LoL file loading regression. svn-id: r34451 --- engines/kyra/lol.cpp | 30 ++++++++++++------------------ engines/kyra/resource.cpp | 2 +- 2 files changed, 13 insertions(+), 19 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index b9cb7bcc0b..baa527b574 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -241,27 +241,21 @@ void LoLEngine::resetSkipFlag(bool removeEvent) { void LoLEngine::setupPrologueData(bool load) { static const char * const fileList[] = { - "xxx/general.pak", - "xxx/introvoc.pak", - "xxx/startup.pak", - "xxx/intro1.pak", - "xxx/intro2.pak", - "xxx/intro3.pak", - "xxx/intro4.pak", - "xxx/intro5.pak", - "xxx/intro6.pak", - "xxx/intro7.pak", - "xxx/intro8.pak", - "xxx/intro9.pak" + "general.pak", "introvoc.pak", "startup.pak", "intro1.pak", + "intro2.pak", "intro3.pak", "intro4.pak", "intro5.pak", + "intro6.pak", "intro7.pak", "intro8.pak", "intro9.pak" }; - char filepath[32]; - char *filename = filepath; + char filename[32]; for (uint i = 0; i < ARRAYSIZE(fileList); ++i) { - strcpy(filename, fileList[i]); - memcpy(filename, _languageExt[_lang], 3); - if (!_flags.isTalkie) - filename += 4; + filename[0] = '\0'; + + if (_flags.isTalkie) { + strcpy(filename, _languageExt[_lang]); + strcat(filename, "/"); + } + + strcat(filename, fileList[i]); if (load) { if (!_res->loadPakFile(filename)) diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index bc83111d14..531f875cc3 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -38,7 +38,7 @@ namespace Kyra { Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(new Common::SearchSet()), _protectedFiles(new Common::SearchSet()), _loaders(), _vm(vm) { initializeLoaders(); - Common::SharedPtr path(new Common::FSDirectory(ConfMan.get("path"))); + Common::SharedPtr path(new Common::FSDirectory(ConfMan.get("path"), 2)); Common::SharedPtr extrapath(new Common::FSDirectory(ConfMan.get("extrapath"))); _files.add("path", path, 4); -- cgit v1.2.3 From c5e049bce80a6c683a4d2c9c1b584f96f6ec782e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 8 Sep 2008 18:55:29 +0000 Subject: Made some filenames uppercase for consistency. svn-id: r34452 --- engines/kyra/lol.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index baa527b574..053d8a4de9 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -241,9 +241,9 @@ void LoLEngine::resetSkipFlag(bool removeEvent) { void LoLEngine::setupPrologueData(bool load) { static const char * const fileList[] = { - "general.pak", "introvoc.pak", "startup.pak", "intro1.pak", - "intro2.pak", "intro3.pak", "intro4.pak", "intro5.pak", - "intro6.pak", "intro7.pak", "intro8.pak", "intro9.pak" + "GENERAL.PAK", "INTROVOC.PAK", "STARTUP.PAK", "INTRO1.PAK", + "INTRO2.PAK", "INTRO3.PAK", "INTRO4.PAK", "INTRO5.PAK", + "INTRO6.PAK", "INTRO7.PAK", "INTRO8.PAK", "INTRO9.PAK" }; char filename[32]; @@ -585,22 +585,22 @@ int LoLEngine::selectionCharInfo(int character) { switch (character) { case 0: - strcpy(filename, "face09.shp"); + strcpy(filename, "FACE09.SHP"); vocFilename[3] = 'A'; break; case 1: - strcpy(filename, "face01.shp"); + strcpy(filename, "FACE01.SHP"); vocFilename[3] = 'M'; break; case 2: - strcpy(filename, "face08.shp"); + strcpy(filename, "FACE08.SHP"); vocFilename[3] = 'K'; break; case 3: - strcpy(filename, "face05.shp"); + strcpy(filename, "FACE05.SHP"); vocFilename[3] = 'C'; break; -- cgit v1.2.3 From 2c0c67c08a7d2d760657d4c1c96b3ace1c7e5439 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Mon, 8 Sep 2008 21:57:38 +0000 Subject: HOF: msvc8 compile fix (ARRAYSIZE used with run-time allocated array) svn-id: r34454 --- engines/kyra/scene_hof.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index 08df7b064e..df9fccaab9 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -517,7 +517,7 @@ void KyraEngine_HoF::runSceneScript7() { void KyraEngine_HoF::initSceneAnims(int unk1) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::initSceneAnims(%d)", unk1); - for (int i = 0; i < ARRAYSIZE(_animObjects); ++i) + for (int i = 0; i < 41; ++i) _animObjects[i].enabled = 0; bool animInit = false; -- cgit v1.2.3 From 6fad6711d96a256c0c75343981f3e2c04ff68986 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 9 Sep 2008 18:09:46 +0000 Subject: Changed static resource code to use Streams instead of operating on buffers. svn-id: r34467 --- engines/kyra/resource.h | 2 +- engines/kyra/staticres.cpp | 269 +++++++++++++++++++++------------------------ 2 files changed, 124 insertions(+), 147 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 54b845c5c9..799068d158 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -267,7 +267,7 @@ private: void freeHofShapeAnimDataV2(void *&ptr, int &size); const char *getFilename(const char *name); - uint8 *getFile(const char *name, int &size); + Common::SeekableReadStream *getFile(const char *name); enum kResTypes { kLanguageList, diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 78d0961011..bfffefb70a 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -308,28 +308,27 @@ bool StaticResource::init() { } char errorBuffer[100]; - int tempSize = 0; - uint8 *temp = getFile("INDEX", tempSize); - if (!temp) { + Common::SeekableReadStream *index = getFile("INDEX"); + if (!index) { snprintf(errorBuffer, sizeof(errorBuffer), "is missing an '%s' entry", getFilename("INDEX")); outputError(errorBuffer); return false; } - if (tempSize != 3*4) { - delete[] temp; + if (index->size() != 3*4) { + delete index; snprintf(errorBuffer, sizeof(errorBuffer), "has incorrect header size for entry '%s'", getFilename("INDEX")); outputError(errorBuffer); return false; } - uint32 version = READ_BE_UINT32(temp); - uint32 gameID = READ_BE_UINT32((temp+4)); - uint32 featuresValue = READ_BE_UINT32((temp+8)); + uint32 version = index->readUint32BE(); + uint32 gameID = index->readUint32BE(); + uint32 featuresValue = index->readUint32BE(); - delete[] temp; - temp = 0; + delete index; + index = 0; if (version != RESFILE_VERSION) { snprintf(errorBuffer, sizeof(errorBuffer), "has invalid version %d required, you got %d", RESFILE_VERSION, version); @@ -553,82 +552,86 @@ bool StaticResource::loadLanguageTable(const char *filename, void *&ptr, int &si } bool StaticResource::loadStringTable(const char *filename, void *&ptr, int &size) { - uint8 *filePtr = getFile(filename, size); - if (!filePtr) + Common::SeekableReadStream *file = getFile(filename); + if (!file) return false; - uint8 *src = filePtr; - uint32 count = READ_BE_UINT32(src); src += 4; + uint32 count = file->readUint32BE(); size = count; char **output = new char*[count]; assert(output); - const char *curPos = (const char*)src; for (uint32 i = 0; i < count; ++i) { - int strLen = strlen(curPos); - output[i] = new char[strLen+1]; - assert(output[i]); - memcpy(output[i], curPos, strLen+1); - curPos += strLen+1; + Common::String string; + char c = 0; + while ((c = (char)file->readByte()) != 0) + string += c; + + output[i] = new char[string.size()+1]; + strcpy(output[i], string.c_str()); } - delete[] filePtr; + delete file; ptr = output; return true; } bool StaticResource::loadRawData(const char *filename, void *&ptr, int &size) { - ptr = getFile(filename, size); - if (!ptr) + Common::SeekableReadStream *file = getFile(filename); + if (!file) return false; + + ptr = new uint8[file->size()]; + file->read(ptr, file->size()); + size = file->size(); + delete file; + return true; } bool StaticResource::loadShapeTable(const char *filename, void *&ptr, int &size) { - uint8 *filePtr = getFile(filename, size); - if (!filePtr) + Common::SeekableReadStream *file = getFile(filename); + if (!file) return false; - uint8 *src = filePtr; - uint32 count = READ_BE_UINT32(src); src += 4; + uint32 count = file->readUint32BE(); size = count; Shape *loadTo = new Shape[count]; assert(loadTo); for (uint32 i = 0; i < count; ++i) { - loadTo[i].imageIndex = *src++; - loadTo[i].x = *src++; - loadTo[i].y = *src++; - loadTo[i].w = *src++; - loadTo[i].h = *src++; - loadTo[i].xOffset = *src++; - loadTo[i].yOffset = *src++; + loadTo[i].imageIndex = file->readByte(); + loadTo[i].x = file->readByte(); + loadTo[i].y = file->readByte(); + loadTo[i].w = file->readByte(); + loadTo[i].h = file->readByte(); + loadTo[i].xOffset = file->readSByte(); + loadTo[i].yOffset = file->readSByte(); } - delete[] filePtr; + delete file; ptr = loadTo; return true; } bool StaticResource::loadRoomTable(const char *filename, void *&ptr, int &size) { - uint8 *filePtr = getFile(filename, size); - if (!filePtr) + Common::SeekableReadStream *file = getFile(filename); + if (!file) return false; - uint8 *src = filePtr; - uint32 count = READ_BE_UINT32(src); src += 4; + uint32 count = file->readUint32BE(); size = count; Room *loadTo = new Room[count]; assert(loadTo); for (uint32 i = 0; i < count; ++i) { - loadTo[i].nameIndex = *src++; - loadTo[i].northExit = READ_BE_UINT16(src); src += 2; - loadTo[i].eastExit = READ_BE_UINT16(src); src += 2; - loadTo[i].southExit = READ_BE_UINT16(src); src += 2; - loadTo[i].westExit = READ_BE_UINT16(src); src += 2; + loadTo[i].nameIndex = file->readByte(); + loadTo[i].northExit = file->readUint16BE(); + loadTo[i].eastExit = file->readUint16BE(); + loadTo[i].southExit = file->readUint16BE(); + loadTo[i].westExit = file->readUint16BE(); memset(&loadTo[i].itemsTable[0], 0xFF, sizeof(byte)*6); memset(&loadTo[i].itemsTable[6], 0, sizeof(byte)*6); memset(loadTo[i].itemsXPos, 0, sizeof(uint16)*12); @@ -636,7 +639,7 @@ bool StaticResource::loadRoomTable(const char *filename, void *&ptr, int &size) memset(loadTo[i].needInit, 0, sizeof(loadTo[i].needInit)); } - delete[] filePtr; + delete file; ptr = loadTo; return true; @@ -651,10 +654,10 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz ++temp; int end = atoi(temp); - char **table = new char*[end-start+1]; + uint8 **table = new uint8*[end-start+1]; assert(table); - char file[64]; + char baseFilename[64]; temp = filename; temp = strstr(temp, " "); ++temp; @@ -662,16 +665,24 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz if (temp == NULL) return false; ++temp; - strncpy(file, temp, 64); + strncpy(baseFilename, temp, 64); char name[64]; for (int i = start; i <= end; ++i) { - snprintf(name, 64, "%s%d.PAL", file, i); - table[(start != 0) ? (i-start) : i] = (char*)getFile(name, size); - if (!table[(start != 0) ? (i-start) : i]) { + snprintf(name, 64, "%s%d.PAL", baseFilename, i); + + Common::SeekableReadStream *file = getFile(name); + if (!file) { + for (int j = start; j < i; ++i) + delete[] table[j-start]; delete[] table; + return false; } + + table[i-start] = new uint8[file->size()]; + file->read(table[i-start], file->size()); + delete file; } ptr = table; @@ -680,86 +691,67 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz } bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int &size) { - int filesize; - uint8 *filePtr = getFile(filename, filesize); + Common::SeekableReadStream *file = getFile(filename); - if (!filePtr) + if (!file) return false; - uint16 *hdr = (uint16 *) filePtr; - int numSeq = READ_BE_UINT16(hdr++); + int numSeq = file->readUint16BE(); + uint32 offset = 2; Sequence *tmp_s = new Sequence[numSeq]; - char *tmp_c = 0; size = sizeof(HofSeqData) + numSeq * (sizeof(Sequence) + 28); for (int i = 0; i < numSeq; i++) { - const uint8 *offset = (const uint8 *)(filePtr + READ_BE_UINT16(hdr++)); - tmp_s[i].flags = READ_BE_UINT16(offset); - offset += 2; - tmp_c = new char[14]; - memcpy(tmp_c, offset, 14); - tmp_s[i].wsaFile = tmp_c; - offset += 14; - tmp_c = new char[14]; - memcpy(tmp_c, offset, 14); - tmp_s[i].cpsFile = tmp_c; - offset += 14; - tmp_s[i].startupCommand = *offset++; - tmp_s[i].finalCommand = *offset++; - tmp_s[i].stringIndex1 = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].stringIndex2 = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].startFrame = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].numFrames = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].frameDelay = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].xPos = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].yPos = READ_BE_UINT16(offset); - offset += 2; - tmp_s[i].duration = READ_BE_UINT16(offset); + file->seek(offset, SEEK_SET); offset += 2; + file->seek(file->readUint16BE(), SEEK_SET); + + tmp_s[i].flags = file->readUint16BE(); + tmp_s[i].wsaFile = new char[14]; + file->read(const_cast(tmp_s[i].wsaFile), 14); + tmp_s[i].cpsFile = new char[14]; + file->read(const_cast(tmp_s[i].cpsFile), 14); + tmp_s[i].startupCommand = file->readByte(); + tmp_s[i].finalCommand = file->readByte(); + tmp_s[i].stringIndex1 = file->readUint16BE(); + tmp_s[i].stringIndex2 = file->readUint16BE(); + tmp_s[i].startFrame = file->readUint16BE(); + tmp_s[i].numFrames = file->readUint16BE(); + tmp_s[i].frameDelay = file->readUint16BE(); + tmp_s[i].xPos = file->readUint16BE(); + tmp_s[i].yPos = file->readUint16BE(); + tmp_s[i].duration = file->readUint16BE(); } - int numSeqN = READ_BE_UINT16(hdr++); + file->seek(offset, SEEK_SET); offset += 2; + int numSeqN = file->readUint16BE(); NestedSequence *tmp_n = new NestedSequence[numSeqN]; size += (numSeqN * (sizeof(NestedSequence) + 14)); for (int i = 0; i < numSeqN; i++) { - const uint8 *offset = (const uint8 *)(filePtr + READ_BE_UINT16(hdr++)); - tmp_n[i].flags = READ_BE_UINT16(offset); - offset += 2; - tmp_c = new char[14]; - memcpy(tmp_c, offset, 14); - tmp_n[i].wsaFile = tmp_c; - offset += 14; - tmp_n[i].startframe = READ_BE_UINT16(offset); - offset += 2; - tmp_n[i].endFrame = READ_BE_UINT16(offset); - offset += 2; - tmp_n[i].frameDelay = READ_BE_UINT16(offset); - offset += 2; - tmp_n[i].x = READ_BE_UINT16(offset); - offset += 2; - tmp_n[i].y = READ_BE_UINT16(offset); - offset += 2; - uint16 ctrlOffs = READ_BE_UINT16(offset); - offset += 2; - tmp_n[i].startupCommand = READ_BE_UINT16(offset); - offset += 2; - tmp_n[i].finalCommand = READ_BE_UINT16(offset); + file->seek(offset, SEEK_SET); offset += 2; + file->seek(file->readUint16BE(), SEEK_SET); + + tmp_n[i].flags = file->readUint16BE(); + tmp_n[i].wsaFile = new char[14]; + file->read(const_cast(tmp_n[i].wsaFile), 14); + tmp_n[i].startframe = file->readUint16BE(); + tmp_n[i].endFrame = file->readUint16BE(); + tmp_n[i].frameDelay = file->readUint16BE(); + tmp_n[i].x = file->readUint16BE(); + tmp_n[i].y = file->readUint16BE(); + uint16 ctrlOffs = file->readUint16BE(); + tmp_n[i].startupCommand = file->readUint16BE(); + tmp_n[i].finalCommand = file->readUint16BE(); if (ctrlOffs) { - int num_c = *(filePtr + ctrlOffs); - const uint16 *in_c = (uint16*) (filePtr + ctrlOffs + 1); + file->seek(ctrlOffs, SEEK_SET); + int num_c = file->readByte(); FrameControl *tmp_f = new FrameControl[num_c]; for (int ii = 0; ii < num_c; ii++) { - tmp_f[ii].index = READ_BE_UINT16(in_c++); - tmp_f[ii].delay = READ_BE_UINT16(in_c++); + tmp_f[ii].index = file->readUint16BE(); + tmp_f[ii].delay = file->readUint16BE(); } tmp_n[i].wsaControl = (const FrameControl*) tmp_f; @@ -770,7 +762,7 @@ bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int & } } - delete[] filePtr; + delete file; HofSeqData *loadTo = new HofSeqData; assert(loadTo); @@ -786,65 +778,53 @@ bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int & } bool StaticResource::loadShapeAnimData_v1(const char *filename, void *&ptr, int &size) { - int filesize; - uint8 *filePtr = getFile(filename, filesize); - uint8 *src = filePtr; + Common::SeekableReadStream *file = getFile(filename); - if (!filePtr) + if (!file) return false; - size = *src++; + size = file->readByte(); ItemAnimData_v1 *loadTo = new ItemAnimData_v1[size]; assert(loadTo); for (int i = 0; i < size; i++) { - loadTo[i].itemIndex = (int16) READ_BE_UINT16(src); - src += 2; - loadTo[i].y = READ_BE_UINT16(src); - src += 2; + loadTo[i].itemIndex = file->readSint16BE(); + loadTo[i].y = file->readUint16BE(); uint16 *tmp_f = new uint16[20]; - for (int ii = 0; ii < 20; ii++) { - tmp_f[ii] = READ_BE_UINT16(src); - src += 2; - } + for (int ii = 0; ii < 20; ii++) + tmp_f[ii] = file->readUint16BE(); loadTo[i].frames = tmp_f; } - delete[] filePtr; + delete file; ptr = loadTo; return true; } bool StaticResource::loadShapeAnimData_v2(const char *filename, void *&ptr, int &size) { - int filesize; - uint8 *filePtr = getFile(filename, filesize); - uint8 *src = filePtr; + Common::SeekableReadStream *file = getFile(filename); - if (!filePtr) + if (!file) return false; - size = *src++; + size = file->readByte(); ItemAnimData_v2 *loadTo = new ItemAnimData_v2[size]; assert(loadTo); for (int i = 0; i < size; i++) { - loadTo[i].itemIndex = (int16) READ_BE_UINT16(src); - src += 2; - loadTo[i].numFrames = *src++; + loadTo[i].itemIndex = file->readSint16BE(); + loadTo[i].numFrames = file->readByte(); FrameControl *tmp_f = new FrameControl[loadTo[i].numFrames]; for (int ii = 0; ii < loadTo[i].numFrames; ii++) { - tmp_f[ii].index = READ_BE_UINT16(src); - src += 2; - tmp_f[ii].delay = READ_BE_UINT16(src); - src += 2; + tmp_f[ii].index = file->readUint16BE(); + tmp_f[ii].delay = file->readUint16BE(); } loadTo[i].frames = tmp_f; } - delete[] filePtr; + delete file; ptr = loadTo; - return true; } @@ -949,11 +929,8 @@ const char *StaticResource::getFilename(const char *name) { return filename.c_str(); } -uint8 *StaticResource::getFile(const char *name, int &size) { - uint32 tempSize = 0; - uint8 *data = _vm->resource()->fileData(getFilename(name), &tempSize); - size = tempSize; - return data; +Common::SeekableReadStream *StaticResource::getFile(const char *name) { + return _vm->resource()->getFileStream(getFilename(name)); } #pragma mark - -- cgit v1.2.3 From a54d1dbde66884afc1402809af1e57d1c214d9c7 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 10 Sep 2008 18:01:02 +0000 Subject: Cleanup. svn-id: r34481 --- engines/kyra/script.cpp | 40 ++++++++-------------------------------- engines/kyra/script.h | 2 +- 2 files changed, 9 insertions(+), 33 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index b10a4b32bf..df933c3ed8 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -435,59 +435,35 @@ void EMCInterpreter::cmd_eval(EMCState* script) { switch (_parameter) { case 0: - if (!val2 || !val1) - ret = 0; - else - ret = 1; + ret = (val2 && val1) ? 1 : 0; break; case 1: - if (val2 || val1) - ret = 1; - else - ret = 0; + ret = (val2 || val1) ? 1 : 0; break; case 2: - if (val1 == val2) - ret = 1; - else - ret = 0; + ret = (val1 == val2) ? 1 : 0; break; case 3: - if (val1 != val2) - ret = 1; - else - ret = 0; + ret = (val1 != val2) ? 1 : 0; break; case 4: - if (val1 > val2) - ret = 1; - else - ret = 0; + ret = (val1 > val2) ? 1 : 0; break; case 5: - if (val1 >= val2) - ret = 1; - else - ret = 0; + ret = (val1 >= val2) ? 1 : 0; break; case 6: - if (val1 < val2) - ret = 1; - else - ret = 0; + ret = (val1 < val2) ? 1 : 0; break; case 7: - if (val1 <= val2) - ret = 1; - else - ret = 0; + ret = (val1 <= val2) ? 1 : 0; break; case 8: diff --git a/engines/kyra/script.h b/engines/kyra/script.h index 2b97a83289..6e08017974 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -47,7 +47,7 @@ struct EMCData { }; struct EMCState { - uint16 *ip; + const uint16 *ip; const EMCData *dataPtr; int16 retValue; uint16 bp; -- cgit v1.2.3 From 25d79f8918810b66748bfc4cebb85a66ea758f15 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 10 Sep 2008 20:47:58 +0000 Subject: Cleanup. svn-id: r34484 --- engines/kyra/screen.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 68faaf6177..32fef01083 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -2736,21 +2736,7 @@ bool Screen::loadPalette(const char *filename, uint8 *palData) { if (palData && fileSize) { debugC(9, kDebugLevelScreen,"Loading a palette of size %u from '%s'", fileSize, filename); - if (_vm->gameFlags().platform == Common::kPlatformAmiga) { - assert(fileSize % 2 == 0); - assert(fileSize / 2 <= 256); - fileSize >>= 1; - const uint16 *src = (const uint16 *)srcData; - for (uint i = 0; i < fileSize; ++i) { - uint16 col = READ_BE_UINT16(src); ++src; - palData[2] = (col & 0xF) << 2; col >>= 4; - palData[1] = (col & 0xF) << 2; col >>= 4; - palData[0] = (col & 0xF) << 2; col >>= 4; - palData += 3; - } - } else { - memcpy(palData, srcData, fileSize); - } + loadPalette(srcData, palData, fileSize); } delete[] srcData; return true; -- cgit v1.2.3 From 0a35842954b9f1e79a84316deb496a4f4ecacf55 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 11 Sep 2008 19:47:45 +0000 Subject: Committed my patch #2105593 "Launcher/MetaEngine: Finnished removeSaveState". svn-id: r34495 --- engines/kyra/detection.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index c19db16d36..ccddbeb64c 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1067,6 +1067,7 @@ public: bool hasFeature(MetaEngineFeature f) const; bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; SaveStateList listSaves(const char *target) const; + void removeSaveState(const char *target, int slot) const; }; bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -1147,6 +1148,16 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { return saveList; } +void KyraMetaEngine::removeSaveState(const char *target, int slot) const { + char extension[6]; + snprintf(extension, sizeof(extension), ".%03d", slot); + + Common::String filename = target; + filename += extension; + + g_system->getSavefileManager()->removeSavefile(filename.c_str()); +} + #if PLUGIN_ENABLED_DYNAMIC(KYRA) REGISTER_PLUGIN_DYNAMIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine); #else -- cgit v1.2.3 From 31c72ace1bb0d084aab1f532b1410ea0aeaeb688 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 12 Sep 2008 12:25:56 +0000 Subject: Fixed slot 0 savefile name in Kyra3. (Now using 'New game' instead of 'German') svn-id: r34502 --- engines/kyra/detection.cpp | 7 ++++++- engines/kyra/kyra_mr.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index ccddbeb64c..854aeec7f4 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1138,8 +1138,13 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { - if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) + if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) { + // Workaround for old savegames using 'German' as description for kyra3 start savegame (slot 0) + if (slotNum == 0 && header.gameID == Kyra::GI_KYRA3) + header.description = "New Game"; + saveList.push_back(SaveStateDescriptor(slotNum, header.description, *file)); + } delete in; } } diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 9e26d5436b..3774cae6b0 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -684,7 +684,7 @@ void KyraEngine_MR::startup() { assert(_invWsa); _invWsa->open("MOODOMTR.WSA", 1, 0); _invWsaFrame = 6; - saveGame(getSavegameFilename(0), (const char*)getTableEntry(_optionsFile, 33), 0); + saveGame(getSavegameFilename(0), "New Game", 0); _soundDigital->beginFadeOut(_musicSoundChannel, 60); delayWithTicks(60); if (_gameToLoad == -1) -- cgit v1.2.3 From 655ce26b3f09628d9408a4d82efe3a26116999fe Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 13 Sep 2008 16:51:46 +0000 Subject: Big patch changing the signature of various Stream methods (some ports may need to be slightly tweaked to fix overloading errors/warnings) svn-id: r34514 --- engines/kyra/resource.cpp | 2 +- engines/kyra/resource_intern.cpp | 26 +++++++++++++------------- engines/kyra/script.cpp | 8 ++++---- engines/kyra/vqa.cpp | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 531f875cc3..0f0a643017 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -262,7 +262,7 @@ bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) { return false; memset(buf, 0, maxSize); - stream->read(buf, (maxSize <= stream->size()) ? maxSize : stream->size()); + stream->read(buf, ((int32)maxSize <= stream->size()) ? maxSize : stream->size()); delete stream; return true; } diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index e6b3b14c8a..f97319a43a 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -127,8 +127,8 @@ bool ResLoaderPak::checkFilename(Common::String filename) const { } bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { - uint32 filesize = stream.size(); - uint32 offset = 0; + int32 filesize = stream.size(); + int32 offset = 0; bool switchEndian = false; bool firstFile = true; @@ -138,7 +138,7 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe offset = SWAP_BYTES_32(offset); } - Common::String file = ""; + Common::String file; while (!stream.eos()) { // The start offset of a file should never be in the filelist if (offset < stream.pos() || offset > filesize) @@ -146,7 +146,7 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe byte c = 0; - file = ""; + file.clear(); while (!stream.eos() && (c = stream.readByte()) != 0) file += c; @@ -196,9 +196,9 @@ struct PlainArchiveListSearch { } // end of anonymous namespace Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filename, Common::SeekableReadStream &stream) const { - uint32 filesize = stream.size(); + int32 filesize = stream.size(); - uint32 startoffset = 0, endoffset = 0; + int32 startoffset = 0, endoffset = 0; bool switchEndian = false; bool firstFile = true; @@ -210,7 +210,7 @@ Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filen PlainArchive::FileInputList files; - Common::String file = ""; + Common::String file; while (!stream.eos()) { // The start offset of a file should never be in the filelist if (startoffset < stream.pos() || startoffset > filesize) { @@ -218,7 +218,7 @@ Common::Archive *ResLoaderPak::load(Resource *owner, const Common::String &filen return false; } - file = ""; + file.clear(); byte c = 0; while (!stream.eos() && (c = stream.readByte()) != 0) @@ -301,7 +301,7 @@ bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const { bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { stream.seek(3, SEEK_SET); - uint32 size = stream.readUint32LE(); + int32 size = stream.readUint32LE(); if (size+7 > stream.size()) return false; @@ -322,13 +322,13 @@ Common::Archive *ResLoaderInsMalcolm::load(Resource *owner, const Common::String // first file is the index table uint32 size = stream.readUint32LE(); - Common::String temp = ""; + Common::String temp; for (uint32 i = 0; i < size; ++i) { byte c = stream.readByte(); if (c == '\\') { - temp = ""; + temp.clear(); } else if (c == 0x0D) { // line endings are CRLF c = stream.readByte(); @@ -363,12 +363,12 @@ bool ResLoaderTlk::checkFilename(Common::String filename) const { bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { uint16 entries = stream.readUint16LE(); - uint32 entryTableSize = (entries * 8); + int32 entryTableSize = (entries * 8); if (entryTableSize + 2 > stream.size()) return false; - uint32 offset = 0; + int32 offset = 0; for (uint i = 0; i < entries; ++i) { stream.readUint32LE(); diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index df933c3ed8..dba09f08ef 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -255,13 +255,13 @@ uint32 ScriptFileParser::getIFFBlockSize(const uint32 chunkName) { _stream->seek(_startOffset + 0x0C); - while (_stream->pos() < _endOffset) { + while ((uint)_stream->pos() < _endOffset) { uint32 chunk = _stream->readUint32LE(); uint32 size_temp = _stream->readUint32BE(); if (chunk != chunkName) { _stream->seek((size_temp + 1) & (~1), SEEK_CUR); - assert(_stream->pos() <= _endOffset); + assert((uint)_stream->pos() <= _endOffset); } else { size = size_temp; break; @@ -274,13 +274,13 @@ uint32 ScriptFileParser::getIFFBlockSize(const uint32 chunkName) { bool ScriptFileParser::loadIFFBlock(const uint32 chunkName, void *loadTo, uint32 ptrSize) { _stream->seek(_startOffset + 0x0C); - while (_stream->pos() < _endOffset) { + while ((uint)_stream->pos() < _endOffset) { uint32 chunk = _stream->readUint32LE(); uint32 chunkSize = _stream->readUint32BE(); if (chunk != chunkName) { _stream->seek((chunkSize + 1) & (~1), SEEK_CUR); - assert(_stream->pos() <= _endOffset); + assert((uint)_stream->pos() <= _endOffset); } else { uint32 loadSize = 0; diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 9a9941e20e..0f6440fd47 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -406,7 +406,7 @@ void VQAMovie::displayFrame(uint frameNum) { byte *inbuf, *outbuf; uint32 insize, outsize; - uint32 end; + int32 end; switch (tag) { case MKID_BE('SND0'): // Uncompressed sound @@ -594,7 +594,7 @@ void VQAMovie::play() { uint32 insize, outsize; if (_stream) { - while (_file->pos() < (_frameInfo[0] & 0x7FFFFFFF)) { + while ((uint)_file->pos() < (_frameInfo[0] & 0x7FFFFFFF)) { uint32 tag = readTag(); uint32 size = _file->readUint32BE(); -- cgit v1.2.3 From ba58358c8d3fce729c834f0f421864a56fb80929 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 14:01:24 +0000 Subject: Rename save slots in KyraMetaEngine::removeSaveState, so it matches behavior in GUI_v2::deleteMenu at least a little bit more. svn-id: r34520 --- engines/kyra/detection.cpp | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 854aeec7f4..f2c929c6fb 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1128,7 +1128,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { Common::StringList filenames; filenames = saveFileMan->listSavefiles(pattern.c_str()); - sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) SaveStateList saveList; for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) { @@ -1154,13 +1154,48 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { } void KyraMetaEngine::removeSaveState(const char *target, int slot) const { + // Slot 0 can't be delted, it's for restarting the game(s) + if (slot == 0) + return; + + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + char extension[6]; snprintf(extension, sizeof(extension), ".%03d", slot); Common::String filename = target; filename += extension; - g_system->getSavefileManager()->removeSavefile(filename.c_str()); + saveFileMan->removeSavefile(filename.c_str()); + + Common::StringList filenames; + Common::String pattern = target; + pattern += ".???"; + filenames = saveFileMan->listSavefiles(pattern.c_str()); + Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 3 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 3); + + // Rename every slot greater than the deleted slot, + // Also do not rename quicksaves. + if (slotNum > slot && slotNum < 990) { + // FIXME: Our savefile renaming done here is inconsitent with what we do in + // GUI_v2::deleteMenu. While here we rename every slot with a greater equal + // number of the deleted slot to deleted slot, deleted slot + 1 etc., + // we only rename the following slots in GUI_v2::deleteMenu until a slot + // is missing. + saveFileMan->renameSavefile(file->c_str(), filename.c_str()); + + ++slot; + snprintf(extension, sizeof(extension), ".%03d", slot); + + filename = target; + filename += extension; + } + } + } #if PLUGIN_ENABLED_DYNAMIC(KYRA) -- cgit v1.2.3 From 9ec7c3eaca458fd1647c51deab0632f5427d5f2d Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 14:08:14 +0000 Subject: Added a hack in KyraMetaEngine::listSaves to prevent slot 0 from being listed. Check comment for additional information. svn-id: r34521 --- engines/kyra/detection.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index f2c929c6fb..834f9f70c6 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1135,7 +1135,10 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { // Obtain the last 3 digits of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 3); - if (slotNum >= 0 && slotNum <= 999) { + // HACK: Until we have a way to check whether a save is deletable in our launcher delete savegame dialog. + // We do not list slot 0 here, since it's for restarting the game and it should never be deleted. + // The downside of it is of course we can not load it via the menu and it isn't listed via --list-saves. + if (slotNum > 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) { @@ -1154,7 +1157,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { } void KyraMetaEngine::removeSaveState(const char *target, int slot) const { - // Slot 0 can't be delted, it's for restarting the game(s) + // Slot 0 can't be deleted, it's for restarting the game(s) if (slot == 0) return; -- cgit v1.2.3 From 53cf9e6409d16842697f19a76a7d7522579ec3c0 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 14:58:37 +0000 Subject: Only setup 'cdaudio' config default for FM-Towns/PC98. svn-id: r34522 --- engines/kyra/kyra_v1.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 95f775d78b..835afd2062 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -247,8 +247,8 @@ void KyraEngine_v1::delayWithTicks(int ticks) { } void KyraEngine_v1::registerDefaultSettings() { - if (_flags.gameID != GI_KYRA3) - ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)); + if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) + ConfMan.registerDefault("cdaudio", true); if (_flags.fanLang != Common::UNK_LANG) { // HACK/WORKAROUND: Since we can't use registerDefault here to overwrite // the global subtitles settings, we're using this hack to enable subtitles @@ -265,7 +265,7 @@ void KyraEngine_v1::readSettings() { if (!ConfMan.getBool("music_mute")) { _configMusic = 1; - if (_flags.gameID != GI_KYRA3 && ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) + if (ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) _configMusic = 2; } _configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1; -- cgit v1.2.3 From fbbe535645b5095b39c68cb386f222e18cbbb3f4 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 15:35:40 +0000 Subject: Fixed regression introduced with r34522. (Now games without 'cdaudio' config value set should startup again). svn-id: r34523 --- engines/kyra/kyra_v1.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 835afd2062..0a935a3e0d 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -264,9 +264,10 @@ void KyraEngine_v1::readSettings() { _configMusic = 0; if (!ConfMan.getBool("music_mute")) { - _configMusic = 1; - if (ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) - _configMusic = 2; + if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) + _configMusic = ConfMan.getBool("cdaudio") ? 2 : 1; + else + _configMusic = 1; } _configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1; -- cgit v1.2.3 From a716fe8393b206cb5eb4913ccc04ef4836d5ff03 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 15:36:16 +0000 Subject: Implemented opcode 151: o1_resetMaskRegion svn-id: r34524 --- engines/kyra/script_lok.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index efa0f8e48f..e965a075bd 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -1747,7 +1747,8 @@ int KyraEngine_LoK::o1_pauseMusicSeconds(EMCState *script) { } int KyraEngine_LoK::o1_resetMaskRegion(EMCState *script) { - warning("STUB: o1_resetMaskRegion"); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_resetMaskRegion(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + _screen->fillRect(stackPos(1), stackPos(2), stackPos(1)+stackPos(3), stackPos(2)+stackPos(4), 0, 5); return 0; } -- cgit v1.2.3 From eddae0e105d8ba323523bccf5c78327e15f6f6c7 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 16:29:14 +0000 Subject: Fixed thumbnail creation / loading in kyra. svn-id: r34527 --- engines/kyra/gui_hof.cpp | 4 +++- engines/kyra/gui_lok.cpp | 5 ++++- engines/kyra/gui_mr.cpp | 4 +++- engines/kyra/saveload.cpp | 1 + engines/kyra/screen.cpp | 19 +++++++++++++++++++ engines/kyra/screen.h | 2 ++ 6 files changed, 32 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 0d7b4d973d..a1391320f4 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -796,7 +796,9 @@ int GUI_HoF::optionsButton(Button *button) { #pragma mark - void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) { - ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(1)); + uint8 screenPal[768]; + _screen->getRealPalette(1, screenPal); + ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, screenPal); } void GUI_HoF::setupPalette() { diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 4d13512751..4efffb0eda 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -204,7 +204,10 @@ void GUI_LoK::createScreenThumbnail(Graphics::Surface &dst) { uint8 *screen = new uint8[Screen::SCREEN_W*Screen::SCREEN_H]; if (screen) { _screen->queryPageFromDisk("SEENPAGE.TMP", 0, screen); - ::createThumbnail(&dst, screen, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(2)); + + uint8 screenPal[768]; + _screen->getRealPalette(2, screenPal); + ::createThumbnail(&dst, screen, Screen::SCREEN_W, Screen::SCREEN_H, screenPal); } delete[] screen; } diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 11e6f6f1f4..72f214f001 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -1141,7 +1141,9 @@ GUI_MR::GUI_MR(KyraEngine_MR *vm) : GUI_v2(vm), _vm(vm), _screen(vm->_screen) { } void GUI_MR::createScreenThumbnail(Graphics::Surface &dst) { - ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(0)); + uint8 screenPal[768]; + _screen->getRealPalette(0, screenPal); + ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, screenPal); } void GUI_MR::flagButtonEnable(Button *button) { diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index da0fd731da..82e896007a 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -43,6 +43,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab header.originalSave = false; header.oldHeader = false; header.flags = 0; + header.thumbnail = 0; if (type == MKID_BE('KYRA') || type == MKID_BE('ARYK')) { // old Kyra1 header ID header.gameID = GI_KYRA1; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 32fef01083..77512771f7 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -476,6 +476,25 @@ void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) { setScreenPalette(_currentPalette); } +void Screen::getRealPalette(int num, uint8 *dst) { + debugC(9, kDebugLevelScreen, "Screen::setRealPalette(%d, %p)", num, (const void *)dst); + const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); + const uint8 *palData = getPalette(num); + + if (!palData) { + memset(dst, 0, colors * 3); + return; + } + + for (int i = 0; i < colors; ++i) { + dst[0] = (palData[0] << 2) | (palData[0] & 3); + dst[1] = (palData[1] << 2) | (palData[1] & 3); + dst[2] = (palData[2] << 2) | (palData[2] & 3); + dst += 3; + palData += 3; + } +} + void Screen::setScreenPalette(const uint8 *palData) { debugC(9, kDebugLevelScreen, "Screen::setScreenPalette(%p)", (const void *)palData); diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 8623856878..58744a9d2a 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -152,6 +152,8 @@ public: void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue); void setScreenPalette(const uint8 *palData); const uint8 *getScreenPalette() const { return _screenPalette; } + + void getRealPalette(int num, uint8 *dst); uint8 *getPalette(int num); // gui specific (processing on _curPage) -- cgit v1.2.3 From 38097172e2cc340f10962a4ff75fb22e8d15a317 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 16:48:20 +0000 Subject: Typo. svn-id: r34528 --- engines/kyra/screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 77512771f7..16cfa6a8b5 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -477,7 +477,7 @@ void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) { } void Screen::getRealPalette(int num, uint8 *dst) { - debugC(9, kDebugLevelScreen, "Screen::setRealPalette(%d, %p)", num, (const void *)dst); + debugC(9, kDebugLevelScreen, "Screen::getRealPalette(%d, %p)", num, (const void *)dst); const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); const uint8 *palData = getPalette(num); -- cgit v1.2.3 From 20a7a9112ffb454a4769f345825916d404e7b083 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 19:05:05 +0000 Subject: Fix potentional bug in Screen::setResolution. svn-id: r34533 --- engines/kyra/screen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 16cfa6a8b5..4bcde9a679 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -188,19 +188,19 @@ void Screen::setResolution() { if (_vm->gameFlags().useHiResOverlay) { _system->beginGFXTransaction(); - _vm->initCommonGFX(true); if (_debugEnabled) _system->initSize(960, 400); else _system->initSize(640, 400); + _vm->initCommonGFX(true); _system->endGFXTransaction(); } else { _system->beginGFXTransaction(); - _vm->initCommonGFX(false); if (_debugEnabled) _system->initSize(640, 200); else _system->initSize(320, 200); + _vm->initCommonGFX(false); _system->endGFXTransaction(); } -- cgit v1.2.3 From 48adf18e21beedc2d56a88d9ca2aee36b507cfcb Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 19:48:40 +0000 Subject: Added autosave support in Kyra. svn-id: r34535 --- engines/kyra/gui.cpp | 2 -- engines/kyra/kyra_hof.cpp | 5 +++++ engines/kyra/kyra_lok.cpp | 2 ++ engines/kyra/kyra_mr.cpp | 5 +++++ engines/kyra/kyra_v1.cpp | 3 +++ engines/kyra/kyra_v1.h | 5 +++++ engines/kyra/lol.h | 3 +++ engines/kyra/saveload.cpp | 9 ++++++++- engines/kyra/script_mr.cpp | 2 +- engines/kyra/timer_mr.cpp | 2 +- 10 files changed, 33 insertions(+), 5 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index 8a5a4dfc91..6864bd9c4d 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -311,8 +311,6 @@ void GUI::updateSaveList() { s1 -= '0'; s2 -= '0'; s3 -= '0'; - if (s1 == 9 && s2 == 9 && s3 == 9) - continue; _saveSlots.push_back(s1*100+s2*10+s3); } diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 2c418e43e3..76d6f6ea05 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -462,8 +462,13 @@ void KyraEngine_HoF::runLoop() { _drawNoShapeFlag = 0; _gui->optionsButton(0); _deathHandler = -1; + + if (!_runFlag || !quit()) + break; } + checkAutosave(); + if (_system->getMillis() > _nextIdleAnim) showIdleAnim(); diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 59127d62ad..f71cc8f409 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -406,6 +406,8 @@ void KyraEngine_LoK::mainLoop() { int32 frameTime = (int32)_system->getMillis(); _skipFlag = false; + checkAutosave(); + if (_currentCharacter->sceneId == 210) { updateKyragemFading(); if (seq_playEnd() && _deathHandler != 8) diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 3774cae6b0..9d3171e723 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -1008,7 +1008,12 @@ void KyraEngine_MR::runLoop() { _drawNoShapeFlag = 0; _gui->optionsButton(0); _deathHandler = -1; + + if (quit()) + break; } + + checkAutosave(); if (_system->getMillis() >= _nextIdleAnim) showIdleAnim(); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 0a935a3e0d..8162232935 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -181,6 +181,9 @@ int KyraEngine_v1::init() { _gameToLoad = -1; } + // Prevent autosave on game startup + _lastAutosave = _system->getMillis(); + return 0; } diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 81871615e8..d2732011be 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -271,6 +271,9 @@ protected: // save/load int _gameToLoad; + uint32 _lastAutosave; + void checkAutosave(); + const char *getSavegameFilename(int num); bool saveFileLoadable(int slot); @@ -295,6 +298,8 @@ protected: static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header); + virtual void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) = 0; + Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header); Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const; }; diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index ee54f8abbb..2ae4d71580 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -147,6 +147,9 @@ private: void setHandItem(uint16) {} void removeHandItem() {} bool lineIsPassable(int, int) { return false; } + + // save + void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) {} }; } // end of namespace Kyra diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 82e896007a..61201a2031 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -220,7 +220,7 @@ const char *KyraEngine_v1::getSavegameFilename(int num) { assert(num >= 0 && num <= 999); char extension[5]; - sprintf(extension, "%.3d", num); + sprintf(extension, "%03d", num); filename = _targetName + "." + extension; @@ -242,5 +242,12 @@ bool KyraEngine_v1::saveFileLoadable(int slot) { return false; } +void KyraEngine_v1::checkAutosave() { + if (shouldPerformAutoSave(_lastAutosave)) { + saveGame(getSavegameFilename(999), "Autosave", 0); + _lastAutosave = _system->getMillis(); + } +} + } // end of namespace Kyra diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index dad870a5f4..bc71e72ce4 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -293,7 +293,7 @@ int KyraEngine_MR::o3_updateScore(EMCState *script) { int KyraEngine_MR::o3_makeSecondChanceSave(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_makeSecondChanceSave(%p) ()", (const void *)script); - saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME", 0); + saveGame(getSavegameFilename(999), "Autosave", 0); return 0; } diff --git a/engines/kyra/timer_mr.cpp b/engines/kyra/timer_mr.cpp index ea7f64fed1..dd749723ce 100644 --- a/engines/kyra/timer_mr.cpp +++ b/engines/kyra/timer_mr.cpp @@ -65,7 +65,7 @@ void KyraEngine_MR::timerRunSceneScript7(int arg) { void KyraEngine_MR::timerFleaDeath(int arg) { debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_MR::timerFleaDeath(%d)", arg); _timer->setCountdown(4, 5400); - saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME", 0); + saveGame(getSavegameFilename(999), "Autosave", 0); _screen->hideMouse(); _timer->disable(4); runAnimationScript("FLEADTH1.EMC", 0, 0, 1, 1); -- cgit v1.2.3 From 92fc264461e1870725310cba38916afaece13022 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 21:00:24 +0000 Subject: - Added thumbnail support to launcher load dialog. - Adopted KYRA to support displaying thumbnails in load dialog (SCUMM engine has yet to follow) svn-id: r34539 --- engines/kyra/detection.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 834f9f70c6..06d96d57bb 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1068,6 +1068,7 @@ public: bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; SaveStateList listSaves(const char *target) const; void removeSaveState(const char *target, int slot) const; + Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot) const; }; bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -1075,7 +1076,8 @@ bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSupportsRTL) || (f == kSupportsListSaves) || (f == kSupportsDirectLoad) || - (f == kSupportsDeleteSave); + (f == kSupportsDeleteSave) || + (f == kSupportsThumbnails); } bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const { @@ -1201,6 +1203,22 @@ void KyraMetaEngine::removeSaveState(const char *target, int slot) const { } +Graphics::Surface *KyraMetaEngine::loadThumbnailFromSlot(const char *target, int slot) const { + char extension[6]; + snprintf(extension, sizeof(extension), ".%03d", slot); + + Common::String filename = target; + filename += extension; + + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str()); + Kyra::KyraEngine_v1::SaveHeader header; + + if (in && Kyra::KyraEngine_v1::readSaveHeader(in, true, header) == Kyra::KyraEngine_v1::kRSHENoError) + return header.thumbnail; + + return 0; +} + #if PLUGIN_ENABLED_DYNAMIC(KYRA) REGISTER_PLUGIN_DYNAMIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine); #else -- cgit v1.2.3 From a4830d813eea7952423338994f0dadf7841a7ada Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 21:41:27 +0000 Subject: Cleanup. svn-id: r34545 --- engines/kyra/detection.cpp | 19 +++---------------- engines/kyra/kyra_v1.h | 1 + engines/kyra/saveload.cpp | 8 +++++--- 3 files changed, 9 insertions(+), 19 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 06d96d57bb..c630e61b05 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1164,12 +1164,7 @@ void KyraMetaEngine::removeSaveState(const char *target, int slot) const { return; Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - - char extension[6]; - snprintf(extension, sizeof(extension), ".%03d", slot); - - Common::String filename = target; - filename += extension; + Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot); saveFileMan->removeSavefile(filename.c_str()); @@ -1193,22 +1188,14 @@ void KyraMetaEngine::removeSaveState(const char *target, int slot) const { // is missing. saveFileMan->renameSavefile(file->c_str(), filename.c_str()); - ++slot; - snprintf(extension, sizeof(extension), ".%03d", slot); - - filename = target; - filename += extension; + filename = Kyra::KyraEngine_v1::getSavegameFilename(target, ++slot); } } } Graphics::Surface *KyraMetaEngine::loadThumbnailFromSlot(const char *target, int slot) const { - char extension[6]; - snprintf(extension, sizeof(extension), ".%03d", slot); - - Common::String filename = target; - filename += extension; + Common::String filename = Kyra::KyraEngine_v1::getSavegameFilename(target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str()); Kyra::KyraEngine_v1::SaveHeader header; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index d2732011be..f4c2442c0e 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -275,6 +275,7 @@ protected: void checkAutosave(); const char *getSavegameFilename(int num); + static Common::String getSavegameFilename(const Common::String &target, int num); bool saveFileLoadable(int slot); struct SaveHeader { diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 61201a2031..76089fdb2c 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -216,15 +216,17 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con const char *KyraEngine_v1::getSavegameFilename(int num) { static Common::String filename; + filename = getSavegameFilename(_targetName, num); + return filename.c_str(); +} +Common::String KyraEngine_v1::getSavegameFilename(const Common::String &target, int num) { assert(num >= 0 && num <= 999); char extension[5]; sprintf(extension, "%03d", num); - filename = _targetName + "." + extension; - - return filename.c_str(); + return target + "." + extension; } bool KyraEngine_v1::saveFileLoadable(int slot) { -- cgit v1.2.3 From c1458bd2bb75bacee89ee5b2bd4bbaf059870e08 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 14 Sep 2008 23:14:38 +0000 Subject: Fixed regression introduced with latest stream changes (it seems compressed savefiles ioFailed never returned true when only eos was set). svn-id: r34551 --- engines/kyra/saveload_hof.cpp | 4 ++-- engines/kyra/saveload_lok.cpp | 4 ++-- engines/kyra/saveload_mr.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp index 2b245f6167..dc7d944cda 100644 --- a/engines/kyra/saveload_hof.cpp +++ b/engines/kyra/saveload_hof.cpp @@ -118,7 +118,7 @@ void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName, const out->finalize(); // check for errors - if (out->ioFailed()) + if (out->err()) warning("Can't write file '%s'. (Disk full?)", fileName); else debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); @@ -279,7 +279,7 @@ void KyraEngine_HoF::loadGame(const char *fileName) { _sceneExit3 = in.readUint16(); _sceneExit4 = in.readUint16(); - if (saveFile->ioFailed()) + if (saveFile->err()) error("Load failed ('%s', '%s').", fileName, header.description.c_str()); else debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 257d762ce8..8be5e102cf 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -206,7 +206,7 @@ void KyraEngine_LoK::loadGame(const char *fileName) { _mousePressFlag = false; setMousePos(brandonX, brandonY); - if (in->ioFailed()) + if (in->err()) error("Load failed ('%s', '%s').", fileName, header.description.c_str()); else debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); @@ -289,7 +289,7 @@ void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName, const out->finalize(); // check for errors - if (out->ioFailed()) + if (out->err()) warning("Can't write file '%s'. (Disk full?)", fileName); else debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp index 8849f99523..07ca5c31f5 100644 --- a/engines/kyra/saveload_mr.cpp +++ b/engines/kyra/saveload_mr.cpp @@ -112,7 +112,7 @@ void KyraEngine_MR::saveGame(const char *fileName, const char *saveName, const G out->finalize(); // check for errors - if (out->ioFailed()) + if (out->err()) warning("Can't write file '%s'. (Disk full?)", fileName); else debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); @@ -283,7 +283,7 @@ void KyraEngine_MR::loadGame(const char *fileName) { _sceneExit3 = in.readUint16(); _sceneExit4 = in.readUint16(); - if (saveFile->ioFailed()) + if (saveFile->err()) error("Load failed ('%s', '%s').", fileName, header.description.c_str()); else debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); -- cgit v1.2.3 From 395536be6eae566be714bd55d6bc4eb79a9a30aa Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 15 Sep 2008 19:34:06 +0000 Subject: also check for premature end-of-stream when loading svn-id: r34563 --- engines/kyra/saveload_hof.cpp | 2 +- engines/kyra/saveload_lok.cpp | 2 +- engines/kyra/saveload_mr.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp index dc7d944cda..be7a74e1c3 100644 --- a/engines/kyra/saveload_hof.cpp +++ b/engines/kyra/saveload_hof.cpp @@ -279,7 +279,7 @@ void KyraEngine_HoF::loadGame(const char *fileName) { _sceneExit3 = in.readUint16(); _sceneExit4 = in.readUint16(); - if (saveFile->err()) + if (saveFile->err() || saveFile->eos()) error("Load failed ('%s', '%s').", fileName, header.description.c_str()); else debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 8be5e102cf..f0d9f1ba82 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -206,7 +206,7 @@ void KyraEngine_LoK::loadGame(const char *fileName) { _mousePressFlag = false; setMousePos(brandonX, brandonY); - if (in->err()) + if (in->err() || in->eos()) error("Load failed ('%s', '%s').", fileName, header.description.c_str()); else debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp index 07ca5c31f5..0db82863ab 100644 --- a/engines/kyra/saveload_mr.cpp +++ b/engines/kyra/saveload_mr.cpp @@ -283,7 +283,7 @@ void KyraEngine_MR::loadGame(const char *fileName) { _sceneExit3 = in.readUint16(); _sceneExit4 = in.readUint16(); - if (saveFile->err()) + if (saveFile->err() || saveFile->eos()) error("Load failed ('%s', '%s').", fileName, header.description.c_str()); else debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); -- cgit v1.2.3 From 259d87a8a68d443d2bbb2bcc1887b4f11b7d342e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 16 Sep 2008 14:10:55 +0000 Subject: Added "querySaveMetaInfos" to MetaEngine. -> Allows easy addition of save state specific infos like playtime, save date atc. -> Removed MetaEngine::loadThumbnailFromSlot, superseded by meta infos -> Changed SCUMM / KYRA to implement the newly added functionallity -> Removed hack in KYRAs listSavefiles, which is now handled via meta infos svn-id: r34581 --- engines/kyra/detection.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index c630e61b05..7a377471c1 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1068,7 +1068,7 @@ public: bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; SaveStateList listSaves(const char *target) const; void removeSaveState(const char *target, int slot) const; - Graphics::Surface *loadThumbnailFromSlot(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; }; bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -1077,6 +1077,7 @@ bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSupportsListSaves) || (f == kSupportsDirectLoad) || (f == kSupportsDeleteSave) || + (f == kSupportsMetaInfos) || (f == kSupportsThumbnails); } @@ -1137,10 +1138,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { // Obtain the last 3 digits of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 3); - // HACK: Until we have a way to check whether a save is deletable in our launcher delete savegame dialog. - // We do not list slot 0 here, since it's for restarting the game and it should never be deleted. - // The downside of it is of course we can not load it via the menu and it isn't listed via --list-saves. - if (slotNum > 0 && slotNum <= 999) { + if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) { @@ -1194,16 +1192,28 @@ void KyraMetaEngine::removeSaveState(const char *target, int slot) const { } -Graphics::Surface *KyraMetaEngine::loadThumbnailFromSlot(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.c_str()); - Kyra::KyraEngine_v1::SaveHeader header; - if (in && Kyra::KyraEngine_v1::readSaveHeader(in, true, header) == Kyra::KyraEngine_v1::kRSHENoError) - return header.thumbnail; + if (in) { + Kyra::KyraEngine_v1::SaveHeader header; + Kyra::KyraEngine_v1::kReadSaveHeaderError error; + + error = Kyra::KyraEngine_v1::readSaveHeader(in, true, header); + delete in; + + if (error == Kyra::KyraEngine_v1::kRSHENoError) { + SaveStateDescriptor desc(slot, header.description, filename); + + desc.setDeletableFlag(slot != 0); + desc.setThumbnail(header.thumbnail); + + return desc; + } + } - return 0; + return SaveStateDescriptor(); } #if PLUGIN_ENABLED_DYNAMIC(KYRA) -- cgit v1.2.3