diff options
Diffstat (limited to 'engines/zvision/zvision.cpp')
-rw-r--r-- | engines/zvision/zvision.cpp | 435 |
1 files changed, 391 insertions, 44 deletions
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index b464f6ee81..62342f02b9 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -8,12 +8,12 @@ * 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. @@ -29,11 +29,17 @@ #include "zvision/graphics/render_manager.h" #include "zvision/cursors/cursor_manager.h" #include "zvision/core/save_manager.h" -#include "zvision/strings/string_manager.h" +#include "zvision/text/string_manager.h" #include "zvision/archives/zfs_archive.h" #include "zvision/detection.h" +#include "zvision/core/menu.h" +#include "zvision/core/search_manager.h" +#include "zvision/text/text.h" +#include "zvision/fonts/truetype_font.h" +#include "zvision/core/midi.h" #include "common/config-manager.h" +#include "common/str.h" #include "common/debug.h" #include "common/debug-channels.h" #include "common/textconsole.h" @@ -48,21 +54,55 @@ namespace ZVision { +#define ZVISION_SETTINGS_KEYS_COUNT 17 + +struct zvisionIniSettings { + const char *name; + int16 slot; + int16 deflt; +} settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = { + {"ZVision_KeyboardTurnSpeed", StateKey_KbdRotateSpeed, 5}, + {"ZVision_PanaRotateSpeed", StateKey_RotateSpeed, 540}, + {"ZVision_QSoundEnabled", StateKey_Qsound, 1}, + {"ZVision_VenusEnabled", StateKey_VenusEnable, 1}, + {"ZVision_HighQuality", StateKey_HighQuality, 1}, + {"ZVision_Platform", StateKey_Platform, 0}, + {"ZVision_InstallLevel", StateKey_InstallLevel, 0}, + {"ZVision_CountryCode", StateKey_CountryCode, 0}, + {"ZVision_CPU", StateKey_CPU, 1}, + {"ZVision_MovieCursor", StateKey_MovieCursor, 1}, + {"ZVision_NoAnimWhileTurning", StateKey_NoTurnAnim, 0}, + {"ZVision_Win958", StateKey_WIN958, 0}, + {"ZVision_ShowErrorDialogs", StateKey_ShowErrorDlg, 0}, + {"ZVision_ShowSubtitles", StateKey_Subtitles, 1}, + {"ZVision_DebugCheats", StateKey_DebugCheats, 0}, + {"ZVision_JapaneseFonts", StateKey_JapanFonts, 0}, + {"ZVision_Brightness", StateKey_Brightness, 0} +}; + ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) - : Engine(syst), - _gameDescription(gameDesc), - _workingWindow(gameDesc->gameId == GID_NEMESIS ? Common::Rect((WINDOW_WIDTH - ZNEM_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZNEM_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZNEM_WORKING_WINDOW_WIDTH) / 2) + ZNEM_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZNEM_WORKING_WINDOW_HEIGHT) / 2) + ZNEM_WORKING_WINDOW_HEIGHT) : - Common::Rect((WINDOW_WIDTH - ZGI_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZGI_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZGI_WORKING_WINDOW_WIDTH) / 2) + ZGI_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZGI_WORKING_WINDOW_HEIGHT) / 2) + ZGI_WORKING_WINDOW_HEIGHT)), - _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/ - _desiredFrameTime(33), /* ~30 fps */ - _clock(_system), - _scriptManager(nullptr), - _renderManager(nullptr), - _saveManager(nullptr), - _stringManager(nullptr), - _cursorManager(nullptr) { + : Engine(syst), + _gameDescription(gameDesc), + _workingWindow_ZGI((WINDOW_WIDTH - WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - WORKING_WINDOW_WIDTH) / 2) + WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - WORKING_WINDOW_HEIGHT) / 2) + WORKING_WINDOW_HEIGHT), + _workingWindow_ZNM((WINDOW_WIDTH - ZNM_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZNM_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZNM_WORKING_WINDOW_WIDTH) / 2) + ZNM_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZNM_WORKING_WINDOW_HEIGHT) / 2) + ZNM_WORKING_WINDOW_HEIGHT), + _workingWindow(gameDesc->gameId == GID_NEMESIS ? _workingWindow_ZNM : _workingWindow_ZGI), + _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/ + _desiredFrameTime(33), /* ~30 fps */ + _clock(_system), + _scriptManager(nullptr), + _renderManager(nullptr), + _saveManager(nullptr), + _stringManager(nullptr), + _cursorManager(nullptr), + _midiManager(nullptr), + _audioId(0), + _rendDelay(2), + _kbdVelocity(0), + _mouseVelocity(0) { debug(1, "ZVision::ZVision"); + + memset(_cheatBuff, 0, sizeof(_cheatBuff)); } ZVision::~ZVision() { @@ -76,39 +116,60 @@ ZVision::~ZVision() { delete _renderManager; delete _scriptManager; delete _rnd; + delete _midiManager; // Remove all of our debug levels DebugMan.clearAllDebugChannels(); } +void ZVision::registerDefaultSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) + ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].deflt); + ConfMan.registerDefault("doublefps", false); +} + +void ZVision::loadSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) + _scriptManager->setStateValue(settingsKeys[i].slot, ConfMan.getInt(settingsKeys[i].name)); + + if (getGameId() == GID_NEMESIS) + _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1); + else + _scriptManager->setStateValue(StateKey_ExecScopeStyle, 0); +} + +void ZVision::saveSettings() { + for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++) + ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot)); + ConfMan.flushToDisk(); +} + void ZVision::initialize() { const Common::FSNode gameDataDir(ConfMan.get("path")); - // TODO: There are 10 file clashes when we flatten the directories. - // From a quick look, the files are exactly the same, so it shouldn't matter. - // But I'm noting it here just in-case it does become a problem. - SearchMan.addSubDirectoryMatching(gameDataDir, "data1", 0, 4, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "data2", 0, 4, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "data3", 0, 4, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "zassets1", 0, 2, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "zassets2", 0, 2, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "znemmx", 0, 1, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "zgi", 0, 4, true); - SearchMan.addSubDirectoryMatching(gameDataDir, "fonts", 0, 1, true); - - // Find zfs archive files - Common::ArchiveMemberList list; - SearchMan.listMatchingMembers(list, "*.zfs"); - - // Register the file entries within the zfs archives with the SearchMan - for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) { - Common::String name = (*iter)->getName(); - Common::SeekableReadStream *stream = (*iter)->createReadStream(); - ZfsArchive *archive = new ZfsArchive(name, stream); - - delete stream; - - SearchMan.add(name, archive); - } + + _searchManager = new SearchManager(ConfMan.get("path"), 6); + + _searchManager->addDir("FONTS"); + _searchManager->addDir("addon"); + + if (_gameDescription->gameId == GID_GRANDINQUISITOR) { + _searchManager->loadZix("INQUIS.ZIX"); + _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC"); + _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC"); + _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC"); + _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC"); + _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC"); + _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC"); + _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC"); + _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC"); + _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC"); + _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC"); + _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC"); + _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC"); + _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC"); + _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC"); + } else if (_gameDescription->gameId == GID_NEMESIS) + _searchManager->loadZix("NEMESIS.ZIX"); initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_pixelFormat); @@ -117,18 +178,30 @@ void ZVision::initialize() { // Create managers _scriptManager = new ScriptManager(this); - _renderManager = new RenderManager(_system, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _pixelFormat); + _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _pixelFormat); _saveManager = new SaveManager(this); _stringManager = new StringManager(this); _cursorManager = new CursorManager(this, &_pixelFormat); + _textRenderer = new TextRenderer(this); + _midiManager = new MidiManager(); + + if (_gameDescription->gameId == GID_GRANDINQUISITOR) + _menu = new MenuZGI(this); + else + _menu = new MenuNemesis(this); // Initialize the managers _cursorManager->initialize(); _scriptManager->initialize(); _stringManager->initialize(_gameDescription->gameId); + registerDefaultSettings(); + + loadSettings(); + // Create debugger console. It requires GFX to be initialized _console = new Console(this); + _halveDelay = ConfMan.getBool("doublefps"); } Common::Error ZVision::run() { @@ -140,29 +213,111 @@ Common::Error ZVision::run() { uint32 currentTime = _clock.getLastMeasuredTime(); uint32 deltaTime = _clock.getDeltaTime(); + _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); + processEvents(); + updateRotation(); // Call _renderManager->update() first so the background renders // before anything that puzzles/controls will render - _renderManager->update(deltaTime); _scriptManager->update(deltaTime); + _menu->process(deltaTime); // Render the backBuffer to the screen + _renderManager->prepareBkg(); + _renderManager->renderMenuToScreen(); + _renderManager->processSubs(deltaTime); _renderManager->renderBackbufferToScreen(); // Update the screen - _system->updateScreen(); + if (_rendDelay <= 0) + _system->updateScreen(); + else + _rendDelay--; // Calculate the frame delay based off a desired frame time int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime); // Ensure non-negative delay = delay < 0 ? 0 : delay; + if (_halveDelay) + delay >>= 1; _system->delayMillis(delay); } return Common::kNoError; } +bool ZVision::askQuestion(const Common::String &str) { + uint16 msgid = _renderManager->createSubArea(); + _renderManager->updateSubArea(msgid, str); + _renderManager->processSubs(0); + _renderManager->renderBackbufferToScreen(); + _clock.stop(); + + int result = 0; + + while (result == 0) { + Common::Event evnt; + while (_eventMan->pollEvent(evnt)) { + if (evnt.type == Common::EVENT_KEYDOWN) { + switch (evnt.kbd.keycode) { + case Common::KEYCODE_y: + result = 2; + break; + case Common::KEYCODE_n: + result = 1; + break; + default: + break; + } + } + } + _system->updateScreen(); + if (_halveDelay) + _system->delayMillis(33); + else + _system->delayMillis(66); + } + _renderManager->deleteSubArea(msgid); + _clock.start(); + return result == 2; +} + +void ZVision::delayedMessage(const Common::String &str, uint16 milsecs) { + uint16 msgid = _renderManager->createSubArea(); + _renderManager->updateSubArea(msgid, str); + _renderManager->processSubs(0); + _renderManager->renderBackbufferToScreen(); + _clock.stop(); + + uint32 stopTime = _system->getMillis() + milsecs; + while (_system->getMillis() < stopTime) { + Common::Event evnt; + while (_eventMan->pollEvent(evnt)) { + if (evnt.type == Common::EVENT_KEYDOWN && + (evnt.kbd.keycode == Common::KEYCODE_SPACE || + evnt.kbd.keycode == Common::KEYCODE_RETURN || + evnt.kbd.keycode == Common::KEYCODE_ESCAPE)) + break; + } + _system->updateScreen(); + if (_halveDelay) + _system->delayMillis(33); + else + _system->delayMillis(66); + } + _renderManager->deleteSubArea(msgid); + _clock.start(); +} + +void ZVision::timedMessage(const Common::String &str, uint16 milsecs) { + uint16 msgid = _renderManager->createSubArea(); + _renderManager->updateSubArea(msgid, str); + _renderManager->processSubs(0); + _renderManager->renderBackbufferToScreen(); + _renderManager->deleteSubArea(msgid, milsecs); +} + void ZVision::pauseEngineIntern(bool pause) { _mixer->pauseAll(pause); @@ -181,4 +336,196 @@ Common::String ZVision::generateAutoSaveFileName() { return Common::String::format("%s.auto", _targetName.c_str()); } +void ZVision::setRenderDelay(uint delay) { + _rendDelay = delay; +} + +bool ZVision::canRender() { + return _rendDelay <= 0; +} + +void ZVision::updateRotation() { + int16 _velocity = _mouseVelocity + _kbdVelocity; + + if (_halveDelay) + _velocity /= 2; + + if (_velocity) { + RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition + (_renderManager->getRenderTable()->getPanoramaReverse() ? -_velocity : _velocity); + + int16 zeroPoint = _renderManager->getRenderTable()->getPanoramaZeroPoint(); + if (startPosition >= zeroPoint && newPosition < zeroPoint) + _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) - 1); + if (startPosition <= zeroPoint && newPosition > zeroPoint) + _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) + 1); + + int16 screenWidth = _renderManager->getBkgSize().x; + if (screenWidth) + newPosition %= screenWidth; + + if (newPosition < 0) + newPosition += screenWidth; + + _renderManager->setBackgroundPosition(newPosition); + } else if (renderState == RenderTable::TILT) { + int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition + _velocity; + + int16 screenHeight = _renderManager->getBkgSize().y; + int16 tiltGap = _renderManager->getRenderTable()->getTiltGap(); + + if (newPosition >= (screenHeight - tiltGap)) + newPosition = screenHeight - tiltGap; + if (newPosition <= tiltGap) + newPosition = tiltGap; + + _renderManager->setBackgroundPosition(newPosition); + } + } +} + +void ZVision::checkBorders() { + RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition; + + int16 screenWidth = _renderManager->getBkgSize().x; + + if (screenWidth) + newPosition %= screenWidth; + + if (newPosition < 0) + newPosition += screenWidth; + + if (startPosition != newPosition) + _renderManager->setBackgroundPosition(newPosition); + } else if (renderState == RenderTable::TILT) { + int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos); + + int16 newPosition = startPosition; + + int16 screenHeight = _renderManager->getBkgSize().y; + int16 tiltGap = _renderManager->getRenderTable()->getTiltGap(); + + if (newPosition >= (screenHeight - tiltGap)) + newPosition = screenHeight - tiltGap; + if (newPosition <= tiltGap) + newPosition = tiltGap; + + if (startPosition != newPosition) + _renderManager->setBackgroundPosition(newPosition); + } +} + +void ZVision::rotateTo(int16 _toPos, int16 _time) { + if (_renderManager->getRenderTable()->getRenderState() != RenderTable::PANORAMA) + return; + + if (_time == 0) + _time = 1; + + int32 maxX = _renderManager->getBkgSize().x; + int32 curX = _renderManager->getCurrentBackgroundOffset(); + int32 dx = 0; + + if (curX == _toPos) + return; + + if (curX > _toPos) { + if (curX - _toPos > maxX / 2) + dx = (_toPos + (maxX - curX)) / _time; + else + dx = -(curX - _toPos) / _time; + } else { + if (_toPos - curX > maxX / 2) + dx = -((maxX - _toPos) + curX) / _time; + else + dx = (_toPos - curX) / _time; + } + + _clock.stop(); + + for (int16 i = 0; i <= _time; i++) { + if (i == _time) + curX = _toPos; + else + curX += dx; + + if (curX < 0) + curX = maxX - curX; + else if (curX >= maxX) + curX %= maxX; + + _renderManager->setBackgroundPosition(curX); + + _renderManager->prepareBkg(); + _renderManager->renderBackbufferToScreen(); + + _system->updateScreen(); + + _system->delayMillis(500 / _time); + } + + _clock.start(); +} + +void ZVision::menuBarEnable(uint16 menus) { + if (_menu) + _menu->setEnable(menus); +} + +uint16 ZVision::getMenuBarEnable() { + if (_menu) + return _menu->getEnable(); + return 0; +} + +bool ZVision::ifQuit() { + if (askQuestion(_stringManager->getTextLine(StringManager::ZVISION_STR_EXITPROMT))) { + quitGame(); + return true; + } + return false; +} + +void ZVision::pushKeyToCheatBuf(uint8 key) { + for (int i = 0; i < KEYBUF_SIZE - 1; i++) + _cheatBuff[i] = _cheatBuff[i + 1]; + + _cheatBuff[KEYBUF_SIZE - 1] = key; +} + +bool ZVision::checkCode(const char *code) { + int codeLen = strlen(code); + + if (codeLen > KEYBUF_SIZE) + return false; + + for (int i = 0; i < codeLen; i++) + if (code[i] != _cheatBuff[KEYBUF_SIZE - codeLen + i] && code[i] != '?') + return false; + + return true; +} + +uint8 ZVision::getBufferedKey(uint8 pos) { + if (pos >= KEYBUF_SIZE) + return 0; + else + return _cheatBuff[KEYBUF_SIZE - pos - 1]; +} + +void ZVision::showDebugMsg(const Common::String &msg, int16 delay) { + uint16 msgid = _renderManager->createSubArea(); + _renderManager->updateSubArea(msgid, msg); + _renderManager->deleteSubArea(msgid, delay); +} + } // End of namespace ZVision |