diff options
Diffstat (limited to 'engines/agi/agi.cpp')
-rw-r--r-- | engines/agi/agi.cpp | 593 |
1 files changed, 205 insertions, 388 deletions
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index e907d3835e..34a81b5ec5 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -21,7 +21,6 @@ */ #include "common/md5.h" -#include "common/events.h" #include "common/file.h" #include "common/memstream.h" #include "common/savefile.h" @@ -41,10 +40,15 @@ #include "audio/mixer.h" #include "agi/agi.h" +#include "agi/font.h" #include "agi/graphics.h" +#include "agi/inv.h" #include "agi/sprite.h" +#include "agi/text.h" #include "agi/keyboard.h" #include "agi/menu.h" +#include "agi/systemui.h" +#include "agi/words.h" #include "gui/predictivedialog.h" @@ -54,241 +58,6 @@ void AgiEngine::allowSynthetic(bool allow) { _allowSynthetic = allow; } -void AgiEngine::processEvents() { - Common::Event event; - int key = 0; - - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_PREDICTIVE_DIALOG: { - GUI::PredictiveDialog _predictiveDialog; - _predictiveDialog.runModal(); - strcpy(_predictiveResult, _predictiveDialog.getResult()); - if (strcmp(_predictiveResult, "")) { - if (_game.inputMode == INPUT_NORMAL) { - strcpy((char *)_game.inputBuffer, _predictiveResult); - handleKeys(KEY_ENTER); - } else if (_game.inputMode == INPUT_GETSTRING) { - strcpy(_game.strings[_stringdata.str], _predictiveResult); - newInputMode(INPUT_NORMAL); - _gfx->printCharacter(_stringdata.x + strlen(_game.strings[_stringdata.str]) + 1, - _stringdata.y, ' ', _game.colorFg, _game.colorBg); - } else if (_game.inputMode == INPUT_NONE) { - for (int n = 0; _predictiveResult[n]; n++) - keyEnqueue(_predictiveResult[n]); - } - } - /* - if (predictiveDialog()) { - if (_game.inputMode == INPUT_NORMAL) { - strcpy((char *)_game.inputBuffer, _predictiveResult); - handleKeys(KEY_ENTER); - } else if (_game.inputMode == INPUT_GETSTRING) { - strcpy(_game.strings[_stringdata.str], _predictiveResult); - newInputMode(INPUT_NORMAL); - _gfx->printCharacter(_stringdata.x + strlen(_game.strings[_stringdata.str]) + 1, - _stringdata.y, ' ', _game.colorFg, _game.colorBg); - } else if (_game.inputMode == INPUT_NONE) { - for (int n = 0; _predictiveResult[n]; n++) - keyEnqueue(_predictiveResult[n]); - } - } - */ - } - break; - case Common::EVENT_LBUTTONDOWN: - if (_game.mouseEnabled) { - key = BUTTON_LEFT; - _mouse.button = kAgiMouseButtonLeft; - keyEnqueue(key); - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - } - break; - case Common::EVENT_RBUTTONDOWN: - if (_game.mouseEnabled) { - key = BUTTON_RIGHT; - _mouse.button = kAgiMouseButtonRight; - keyEnqueue(key); - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - } - break; - case Common::EVENT_WHEELUP: - if (_game.mouseEnabled) { - key = WHEEL_UP; - keyEnqueue(key); - } - break; - case Common::EVENT_WHEELDOWN: - if (_game.mouseEnabled) { - key = WHEEL_DOWN; - keyEnqueue(key); - } - break; - case Common::EVENT_MOUSEMOVE: - if (_game.mouseEnabled) { - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - - if (!_game.mouseFence.isEmpty()) { - if (_mouse.x < _game.mouseFence.left) - _mouse.x = _game.mouseFence.left; - if (_mouse.x > _game.mouseFence.right) - _mouse.x = _game.mouseFence.right; - if (_mouse.y < _game.mouseFence.top) - _mouse.y = _game.mouseFence.top; - if (_mouse.y > _game.mouseFence.bottom) - _mouse.y = _game.mouseFence.bottom; - - g_system->warpMouse(_mouse.x, _mouse.y); - } - } - - break; - case Common::EVENT_LBUTTONUP: - case Common::EVENT_RBUTTONUP: - if (_game.mouseEnabled) { - _mouse.button = kAgiMouseButtonUp; - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - } - break; - case Common::EVENT_KEYDOWN: - if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) { - _console->attach(); - break; - } - - switch (key = event.kbd.keycode) { - case Common::KEYCODE_LEFT: - case Common::KEYCODE_KP4: - if (_allowSynthetic || !event.synthetic) - key = KEY_LEFT; - break; - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_KP6: - if (_allowSynthetic || !event.synthetic) - key = KEY_RIGHT; - break; - case Common::KEYCODE_UP: - case Common::KEYCODE_KP8: - if (_allowSynthetic || !event.synthetic) - key = KEY_UP; - break; - case Common::KEYCODE_DOWN: - case Common::KEYCODE_KP2: - if (_allowSynthetic || !event.synthetic) - key = KEY_DOWN; - break; - case Common::KEYCODE_PAGEUP: - case Common::KEYCODE_KP9: - if (_allowSynthetic || !event.synthetic) - key = KEY_UP_RIGHT; - break; - case Common::KEYCODE_PAGEDOWN: - case Common::KEYCODE_KP3: - if (_allowSynthetic || !event.synthetic) - key = KEY_DOWN_RIGHT; - break; - case Common::KEYCODE_HOME: - case Common::KEYCODE_KP7: - if (_allowSynthetic || !event.synthetic) - key = KEY_UP_LEFT; - break; - case Common::KEYCODE_END: - case Common::KEYCODE_KP1: - if (_allowSynthetic || !event.synthetic) - key = KEY_DOWN_LEFT; - break; - case Common::KEYCODE_KP5: - key = KEY_STATIONARY; - break; - case Common::KEYCODE_PLUS: - key = '+'; - break; - case Common::KEYCODE_MINUS: - key = '-'; - break; - case Common::KEYCODE_TAB: - key = 0x0009; - break; - case Common::KEYCODE_F1: - key = 0x3b00; - break; - case Common::KEYCODE_F2: - key = 0x3c00; - break; - case Common::KEYCODE_F3: - key = 0x3d00; - break; - case Common::KEYCODE_F4: - key = 0x3e00; - break; - case Common::KEYCODE_F5: - key = 0x3f00; - break; - case Common::KEYCODE_F6: - key = 0x4000; - break; - case Common::KEYCODE_F7: - key = 0x4100; - break; - case Common::KEYCODE_F8: - key = 0x4200; - break; - case Common::KEYCODE_F9: - key = 0x4300; - break; - case Common::KEYCODE_F10: - key = 0x4400; - break; - case Common::KEYCODE_F11: - key = KEY_STATUSLN; - break; - case Common::KEYCODE_F12: - key = KEY_PRIORITY; - break; - case Common::KEYCODE_ESCAPE: - key = 0x1b; - break; - case Common::KEYCODE_RETURN: - case Common::KEYCODE_KP_ENTER: - key = KEY_ENTER; - break; - case Common::KEYCODE_BACKSPACE: - key = KEY_BACKSPACE; - break; - default: - // Not a special key, so get the ASCII code for it - key = event.kbd.ascii; - - if (Common::isAlpha(key)) { - // Key is A-Z. - // Map Ctrl-A to 1, Ctrl-B to 2, etc. - if (event.kbd.flags & Common::KBD_CTRL) { - key = toupper(key) - 'A' + 1; - } else if (event.kbd.flags & Common::KBD_ALT) { - // Map Alt-A, Alt-B etc. to special scancode values according to an internal scancode table. - key = scancodeTable[toupper(key) - 'A'] << 8; - } - } - break; - } - if (key) - keyEnqueue(key); - break; - - case Common::EVENT_KEYUP: - if (_egoHoldKey) - _game.viewTable[0].direction = 0; - - default: - break; - } - } -} - void AgiEngine::pollTimer() { _lastTick += 50; @@ -305,24 +74,14 @@ void AgiEngine::pollTimer() { void AgiEngine::pause(uint32 msec) { uint32 endTime = _system->getMillis() + msec; - _gfx->setCursor(_renderMode == Common::kRenderAmiga, true); + _gfx->setMouseCursor(true); // Busy mouse cursor while (_system->getMillis() < endTime) { processEvents(); _system->updateScreen(); _system->delayMillis(10); } - _gfx->setCursor(_renderMode == Common::kRenderAmiga); -} - -void AgiEngine::initPriTable() { - int i, p, y = 0; - - for (p = 1; p < 15; p++) { - for (i = 0; i < 12; i++) { - _game.priTable[y++] = p < 4 ? 4 : p; - } - } + _gfx->setMouseCursor(); // regular mouse cursor } int AgiEngine::agiInit() { @@ -335,13 +94,11 @@ int AgiEngine::agiInit() { _game.adjMouseX = _game.adjMouseY = 0; // reset all flags to false and all variables to 0 - for (i = 0; i < MAX_FLAGS; i++) - _game.flags[i] = 0; - for (i = 0; i < MAX_VARS; i++) - _game.vars[i] = 0; + memset(_game.flags, 0, sizeof(_game.flags)); + memset(_game.vars, 0, sizeof(_game.vars)); // clear all resources and events - for (i = 0; i < MAX_DIRS; i++) { + for (i = 0; i < MAX_DIRECTORY_ENTRIES; i++) { memset(&_game.views[i], 0, sizeof(struct AgiView)); memset(&_game.pictures[i], 0, sizeof(struct AgiPicture)); memset(&_game.logics[i], 0, sizeof(struct AgiLogic)); @@ -353,15 +110,17 @@ int AgiEngine::agiInit() { } // clear view table - for (i = 0; i < MAX_VIEWTABLE; i++) - memset(&_game.viewTable[i], 0, sizeof(struct VtEntry)); + for (i = 0; i < SCREENOBJECTS_MAX; i++) + memset(&_game.screenObjTable[i], 0, sizeof(struct ScreenObjEntry)); + + memset(&_game.addToPicView, 0, sizeof(struct ScreenObjEntry)); - initWords(); + _words->clearEgoWords(); if (!_menu) - _menu = new Menu(this, _gfx, _picture); + _menu = new GfxMenu(this, _gfx, _picture, _text); - initPriTable(); + _gfx->initPriorityTable(); // Clear the string buffer on startup, but not when the game restarts, as // some scripts expect that the game strings remain unaffected after a @@ -394,10 +153,6 @@ int AgiEngine::agiInit() { if (getFeatures() & GF_AGDS) _game.gameFlags |= ID_AGDS; - // Make the 256 color AGI screen the default AGI screen when AGI256 or AGI256-2 is used - if (getFeatures() & (GF_AGI256 | GF_AGI256_2)) - _game.sbuf = _game.sbuf256c; - if (_game.gameFlags & ID_AMIGA) debug(1, "Amiga padded game detected."); @@ -413,12 +168,9 @@ int AgiEngine::agiInit() { if (ec == errOK) ec = _loader->loadWords(WORDS); - // FIXME: load IIgs instruments and samples - // load_instruments("kq.sys16"); - // Load logic 0 into memory if (ec == errOK) - ec = _loader->loadResource(rLOGIC, 0); + ec = _loader->loadResource(RESOURCETYPE_LOGIC, 0); #ifdef __DS__ // Normally, the engine loads the predictive text dictionary when the predictive dialog @@ -432,6 +184,12 @@ int AgiEngine::agiInit() { _game.mouseFence.setWidth(0); // Reset + // Reset in-game timer + inGameTimerReset(); + + // Sync volume settings from ScummVM system settings + setVolumeViaSystemSetting(); + return ec; } @@ -443,42 +201,42 @@ void AgiEngine::agiUnloadResources() { int i; // Make sure logic 0 is always loaded - for (i = 1; i < MAX_DIRS; i++) { - _loader->unloadResource(rLOGIC, i); + for (i = 1; i < MAX_DIRECTORY_ENTRIES; i++) { + _loader->unloadResource(RESOURCETYPE_LOGIC, i); } - for (i = 0; i < MAX_DIRS; i++) { - _loader->unloadResource(rVIEW, i); - _loader->unloadResource(rPICTURE, i); - _loader->unloadResource(rSOUND, i); + for (i = 0; i < MAX_DIRECTORY_ENTRIES; i++) { + _loader->unloadResource(RESOURCETYPE_VIEW, i); + _loader->unloadResource(RESOURCETYPE_PICTURE, i); + _loader->unloadResource(RESOURCETYPE_SOUND, i); } } int AgiEngine::agiDeinit() { int ec; - cleanInput(); // remove all words from memory + _words->clearEgoWords(); // remove all words from memory agiUnloadResources(); // unload resources in memory - _loader->unloadResource(rLOGIC, 0); + _loader->unloadResource(RESOURCETYPE_LOGIC, 0); ec = _loader->deinit(); unloadObjects(); - unloadWords(); + _words->unloadDictionary(); clearImageStack(); return ec; } -int AgiEngine::agiLoadResource(int r, int n) { +int AgiEngine::agiLoadResource(int16 resourceType, int16 resourceNr) { int i; - i = _loader->loadResource(r, n); + i = _loader->loadResource(resourceType, resourceNr); // WORKAROUND: Patches broken picture 147 in a corrupted Amiga version of Gold Rush! (v2.05 1989-03-09). // The picture can be seen in room 147 after dropping through the outhouse's hole in room 146. - if (i == errOK && getGameID() == GID_GOLDRUSH && r == rPICTURE && n == 147 && _game.dirPic[n].len == 1982) { - uint8 *pic = _game.pictures[n].rdata; - Common::MemoryReadStream picStream(pic, _game.dirPic[n].len); - Common::String md5str = Common::computeStreamMD5AsString(picStream, _game.dirPic[n].len); + if (i == errOK && getGameID() == GID_GOLDRUSH && resourceType == RESOURCETYPE_PICTURE && resourceNr == 147 && _game.dirPic[resourceNr].len == 1982) { + uint8 *pic = _game.pictures[resourceNr].rdata; + Common::MemoryReadStream picStream(pic, _game.dirPic[resourceNr].len); + Common::String md5str = Common::computeStreamMD5AsString(picStream, _game.dirPic[resourceNr].len); if (md5str == "1c685eb048656cedcee4eb6eca2cecea") { pic[0x042] = 0x4B; // 0x49 -> 0x4B pic[0x043] = 0x66; // 0x26 -> 0x66 @@ -492,8 +250,8 @@ int AgiEngine::agiLoadResource(int r, int n) { return i; } -int AgiEngine::agiUnloadResource(int r, int n) { - return _loader->unloadResource(r, n); +int AgiEngine::agiUnloadResource(int16 resourceType, int16 resourceNr) { + return _loader->unloadResource(resourceType, resourceNr); } struct GameSettings { @@ -510,8 +268,6 @@ AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(sys _rnd = new Common::RandomSource("agi"); _sound = 0; - _fontData = NULL; - initFeatures(); initVersion(); } @@ -523,27 +279,70 @@ AgiBase::~AgiBase() { } void AgiBase::initRenderMode() { + Common::Platform platform = Common::parsePlatform(ConfMan.get("platform")); + Common::RenderMode configRenderMode = Common::parseRenderMode(ConfMan.get("render_mode").c_str()); + + // Default to EGA PC rendering _renderMode = Common::kRenderEGA; - if (ConfMan.hasKey("platform")) { - Common::Platform platform = Common::parsePlatform(ConfMan.get("platform")); - _renderMode = (platform == Common::kPlatformAmiga) ? Common::kRenderAmiga : Common::kRenderEGA; + switch (platform) { + case Common::kPlatformDOS: + switch (configRenderMode) { + case Common::kRenderCGA: + _renderMode = Common::kRenderCGA; + break; + // Hercules is not supported atm + //case Common::kRenderHercA: + //case Common::kRenderHercG: + // _renderMode = Common::kRenderHercG; + // break; + default: + break; + } + break; + case Common::kPlatformAmiga: + _renderMode = Common::kRenderAmiga; + break; + case Common::kPlatformApple2GS: + _renderMode = Common::kRenderApple2GS; + break; + case Common::kPlatformAtariST: + _renderMode = Common::kRenderAtariST; + break; + default: + break; + } + + // If render mode is explicitly set, force rendermode + switch (configRenderMode) { + case Common::kRenderAmiga: + _renderMode = Common::kRenderAmiga; + break; + case Common::kRenderApple2GS: + _renderMode = Common::kRenderApple2GS; + break; + case Common::kRenderAtariST: + _renderMode = Common::kRenderAtariST; + break; + default: + break; } - if (ConfMan.hasKey("render_mode")) { - Common::RenderMode tmpMode = Common::parseRenderMode(ConfMan.get("render_mode").c_str()); - if (tmpMode != Common::kRenderDefault) - _renderMode = tmpMode; + if (getFeatures() & (GF_AGI256 | GF_AGI256_2)) { + // If current game is AGI256, switch (force) to VGA render mode + _renderMode = Common::kRenderVGA; } } +const byte *AgiBase::getFontData() { + return _font->getFontData(); +} + AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) { // Setup mixer syncSoundSettings(); - parseFeatures(); - DebugMan.addDebugChannel(kDebugLevelMain, "Main", "Generic debug level"); DebugMan.addDebugChannel(kDebugLevelResources, "Resources", "Resources debugging"); DebugMan.addDebugChannel(kDebugLevelSprites, "Sprites", "Sprites debugging"); @@ -561,20 +360,18 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas memset(&_mouse, 0, sizeof(struct Mouse)); _game.mouseEnabled = true; + _game.mouseHidden = false; + // don't check for Amiga, Amiga doesn't allow disabling mouse support. It's mandatory. if (!ConfMan.getBool("mousesupport")) { // we effectively disable the mouse for games, that explicitly do not want mouse support to be enabled _game.mouseEnabled = false; - } - - // We are currently using the custom font for all fanmade games - if (!(getFeatures() & (GF_FANMADE | GF_AGDS))) { - _fontData = fontData_Sierra; // original Sierra font - } else { - _fontData = fontData_FanGames; // our (own?) custom font, that supports umlauts etc. + _game.mouseHidden = true; } _game._vm = this; + _game.gfxMode = true; + _game.clockEnabled = false; _game.state = STATE_INIT; @@ -585,17 +382,13 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _intobj = NULL; - _menu = NULL; - _menuSelected = false; - - _lastSentence[0] = 0; memset(&_stringdata, 0, sizeof(struct StringData)); _objects = NULL; _restartGame = false; - _oldMode = INPUT_NONE; + _oldMode = INPUTMODE_NONE; _firstSlot = 0; @@ -603,22 +396,22 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas setupOpcodes(); _game._curLogic = NULL; - _timerHack = 0; _lastSaveTime = 0; _lastTick = 0; memset(_keyQueue, 0, sizeof(_keyQueue)); - memset(_predictiveResult, 0, sizeof(_predictiveResult)); + _text = NULL; _sprites = NULL; _picture = NULL; _loader = NULL; _console = NULL; + _menu = NULL; + _gfx = NULL; + _systemUI = NULL; _egoHoldKey = false; - - } void AgiEngine::initialize() { @@ -658,28 +451,26 @@ void AgiEngine::initialize() { initRenderMode(); - _buttonStyle = AgiButtonStyle(_renderMode); - _defaultButtonStyle = AgiButtonStyle(); _console = new Console(this); + _words = new Words(this); + _font = new GfxFont(this); _gfx = new GfxMgr(this); _sound = new SoundMgr(this, _mixer); _picture = new PictureMgr(this, _gfx); _sprites = new SpritesMgr(this, _gfx); + _text = new TextMgr(this, _words, _gfx); + _systemUI = new SystemUI(this, _gfx, _text); + _inventory = new InventoryMgr(this, _gfx, _text, _systemUI); - _gfx->initMachine(); + _font->init(); + _text->init(_systemUI); _game.gameFlags = 0; - _game.colorFg = 15; - _game.colorBg = 0; + _text->charAttrib_Set(15, 0); _game.name[0] = '\0'; - _game.sbufOrig = (uint8 *)calloc(_WIDTH, _HEIGHT * 2); // Allocate space for two AGI screens vertically - _game.sbuf16c = _game.sbufOrig + SBUF16_OFFSET; // Make sbuf16c point to the 16 color (+control line & priority info) AGI screen - _game.sbuf256c = _game.sbufOrig + SBUF256_OFFSET; // Make sbuf256c point to the 256 color AGI screen - _game.sbuf = _game.sbuf16c; // Make sbuf point to the 16 color (+control line & priority info) AGI screen by default - _gfx->initVideo(); _lastSaveTime = 0; @@ -698,6 +489,33 @@ void AgiEngine::initialize() { debugC(2, kDebugLevelMain, "Init sound"); } +bool AgiEngine::promptIsEnabled() { + return _text->promptIsEnabled(); +} + +void AgiEngine::redrawScreen() { + _game.gfxMode = true; // enable graphics mode + _gfx->setPalette(true); // set graphics mode palette + _text->charAttrib_Set(_text->_textAttrib.foreground, _text->_textAttrib.background); + _gfx->clearDisplay(0); + _picture->showPic(); + _text->statusDraw(); + _text->promptRedraw(); +} + +// Adjust a given coordinate to the local game screen +// Used on mouse cursor coordinates before passing them to scripts +void AgiEngine::adjustPosToGameScreen(int16 &x, int16 &y) { + x = x / 2; // 320 -> 160 + y = y - _gfx->getRenderStartOffsetY(); // remove status bar line + if (y < 0) { + y = 0; + } + if (y >= SCRIPT_HEIGHT) { + y = SCRIPT_HEIGHT + 1; // 1 beyond + } +} + AgiEngine::~AgiEngine() { // If the engine hasn't been initialized yet via // AgiEngine::initialize(), don't attempt to free any resources, as @@ -710,22 +528,21 @@ AgiEngine::~AgiEngine() { agiDeinit(); delete _loader; _gfx->deinitVideo(); + delete _inventory; + delete _systemUI; + delete _text; delete _sprites; delete _picture; - free(_game.sbufOrig); - _gfx->deinitMachine(); delete _gfx; + delete _font; + delete _words; delete _console; } Common::Error AgiBase::init() { - - // Initialize backend - initGraphics(320, 200, false); - initialize(); - _gfx->gfxSetPalette(); + _gfx->setPalette(true); return Common::kNoError; } @@ -734,7 +551,7 @@ Common::Error AgiEngine::go() { if (_game.mouseEnabled) { CursorMan.showMouse(true); } - setTotalPlayTime(0); + inGameTimerReset(); if (_game.state < STATE_LOADED) { do { @@ -747,74 +564,74 @@ Common::Error AgiEngine::go() { return Common::kNoError; } -void AgiEngine::parseFeatures() { - - /* FIXME: Seems this method doesn't really do anything. It might - be a leftover that could be removed, except that some of its - intended purpose may still need to be reimplemented. - - [0:29] <Fingolfin> can you tell me what the point behind AgiEngine::parseFeatures() is? - [0:30] <_sev> when games are created with WAGI studio - [0:31] <_sev> it creates .wag site with game-specific features such as full game title, whether to use AGIMOUSE etc - [0:32] <Fingolfin> ... and the "features" config key is created by our detector based on the wag file, I guess? - [0:33] <_sev> yes - [0:33] <Fingolfin> it's just that I cant seem to find a place we do that - [0:33] <_sev> it is used for fallback - [0:34] <_sev> ah, perhaps it was not updated - [0:34] <Fingolfin> I only see us check the value, but never set it - [0:34] <Fingolfin> maybe I am grepping wrong, who knows :) - [0:44] <Fingolfin> _sev: so, unless I miss something, it seem that function does nothing right now - [0:45] <_sev> Fingolfin: it could be unfinished. It was part of GSoC 3 years ago - [0:45] <Fingolfin> well - [0:45] <_sev> I just don't remember - [0:45] <Fingolfin> but don't we just re-parse the wag when the game is loaded anyway? - [0:45] <_sev> but it documents the format - [0:45] <Fingolfin> the advanced meta engine would re-run the detector, wouldn't it? - [0:45] <_sev> yep - [0:47] <Fingolfin> so... shouldn't we at least add a comment to the function explaining what it does and that it's unfinished etc.? maybe add a TODO to the wiki? - [0:47] <Fingolfin> otherwise it might stay as it is for another 3 years :) - */ - - if (!ConfMan.hasKey("features")) - return; +void AgiEngine::syncSoundSettings() { + Engine::syncSoundSettings(); - char *features = strdup(ConfMan.get("features").c_str()); - const char *feature[100]; - int numFeatures = 0; + setVolumeViaSystemSetting(); +} - char *tok = strtok(features, " "); - if (tok) { - do { - feature[numFeatures++] = tok; - } while ((tok = strtok(NULL, " ")) != NULL); - } else { - feature[numFeatures++] = features; +// Scenes that need this: +// +// Manhunter 1: +// - intro text screen (DrawPic) +// - MAD "zooming in..." during intro and other scenes, for example room 124 (NewRoom) +// The NewRoom call is not done during the same cycle as the "zooming in..." print call. +// Space Quest 1: +// - right at the start of the game (NewRoom) +// Space Quest 2 +// - right at the start of the game (NewRoom) +// - after exiting the very first room, a message pops up, that isn't readable without it (NewRoom) + + +// Games, that must not be triggered: +// +// Fanmade Voodoo Girl: +// - waterfall (DrawPic, room 17) +// - inside shop (NewRoom, changes to same room every new button, room 4) + +void AgiEngine::nonBlockingText_IsShown() { + _game.nonBlockingTextShown = true; + _game.nonBlockingTextCyclesLeft = 2; // 1 additional script cycle is counted too +} +void AgiEngine::nonBlockingText_Forget() { + _game.nonBlockingTextShown = false; + _game.nonBlockingTextCyclesLeft = 0; +} +void AgiEngine::nonBlockingText_CycleDone() { + if (_game.nonBlockingTextCyclesLeft) { + _game.nonBlockingTextCyclesLeft--; + + if (!_game.nonBlockingTextCyclesLeft) { + // cycle count expired, we assume that non-blocking text won't be a problem for room / pic change + _game.nonBlockingTextShown = false; + } } +} + +void AgiEngine::loadingTrigger_NewRoom(int16 newRoomNr) { + if (_game.nonBlockingTextShown) { + _game.nonBlockingTextShown = false; - const struct Flags { - const char *name; - uint32 flag; - } flags[] = { - { "agimouse", GF_AGIMOUSE }, - { "agds", GF_AGDS }, - { "agi256", GF_AGI256 }, - { "agi256-2", GF_AGI256_2 }, - { "agipal", GF_AGIPAL }, - { 0, 0 } - }; - - for (int i = 0; i < numFeatures; i++) { - for (const Flags *flag = flags; flag->name; flag++) { - if (!scumm_stricmp(feature[i], flag->name)) { - debug(2, "Added feature: %s", flag->name); - - setFeature(flag->flag); - break; + int16 curRoomNr = getVar(VM_VAR_CURRENT_ROOM); + + if (newRoomNr != curRoomNr) { + if (!_game.automaticRestoreGame) { + // wait a bit, we detected non-blocking text + pause(2000); // 2 seconds } } } +} + +void AgiEngine::loadingTrigger_DrawPicture() { + if (_game.nonBlockingTextShown) { + _game.nonBlockingTextShown = false; - free(features); + if (!_game.automaticRestoreGame) { + // wait a bit, we detected non-blocking text + pause(2000); // 2 seconds + } + } } } // End of namespace Agi |