diff options
Diffstat (limited to 'scumm/scumm.cpp')
-rw-r--r-- | scumm/scumm.cpp | 833 |
1 files changed, 92 insertions, 741 deletions
diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index 0672ce4e8c..5e7e433560 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -42,6 +42,7 @@ #include "scumm/dialogs.h" #include "scumm/imuse_digi/dimuse.h" #include "scumm/imuse.h" +#include "scumm/insane/insane.h" #include "scumm/intern.h" #include "scumm/object.h" #include "scumm/player_v1.h" @@ -55,8 +56,6 @@ #include "scumm/sound.h" #include "scumm/verbs.h" -#include "scumm/insane/insane.h" - #include "sound/mididrv.h" #include "sound/mixer.h" @@ -71,11 +70,6 @@ extern bool isSmartphone(void); namespace Scumm { -enum MouseButtonStatus { - msDown = 1, - msClicked = 2 -}; - // Use g_scumm from error() ONLY ScummEngine *g_scumm = 0; @@ -495,7 +489,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS } } - // Init all vars - maybe now we can get rid of our custom new/delete operators? + // Init all vars _imuse = NULL; _imuseDigital = NULL; _musicEngine = NULL; @@ -660,7 +654,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS _useTalkAnims = false; _defaultTalkDelay = 0; _midiDriver = MD_NULL; - tempMusic = 0; + _tempMusic = 0; _saveSound = 0; memset(_extraBoxFlags, 0, sizeof(_extraBoxFlags)); memset(_scaleSlots, 0, sizeof(_scaleSlots)); @@ -875,8 +869,6 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS // differing from the regular version(s) of that game. _gameName = ConfMan.hasKey("basename") ? ConfMan.get("basename") : gs.baseFilename ? gs.baseFilename : gs.name; - _midiDriver = GameDetector::detectMusicDriver(gs.midi); - _copyProtection = ConfMan.getBool("copy_protection"); _demoMode = ConfMan.getBool("demo_mode"); if (ConfMan.hasKey("nosubtitles")) { @@ -885,11 +877,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS ConfMan.set("subtitles", !ConfMan.getBool("nosubtitles")); } _confirmExit = ConfMan.getBool("confirm_exit"); - _native_mt32 = ConfMan.getBool("native_mt32"); - // TODO: We shouldn't rely on the global Language values matching those COMI etc. expect. - // Rather we should explicitly translate them. - _language = Common::parseLanguage(ConfMan.get("language")); - memset(&res, 0, sizeof(res)); + _hexdumpScripts = false; _showStack = false; @@ -911,134 +899,26 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS } // Initialize backend - syst->initSize(_screenWidth, _screenHeight); + _system->initSize(_screenWidth, _screenHeight); int cd_num = ConfMan.getInt("cdrom"); if (cd_num >= 0 && (_features & GF_AUDIOTRACKS)) - syst->openCD(cd_num); - - // Setup GDI object - gdi._numStrips = _screenWidth / 8; + _system->openCD(cd_num); + // Create the sound manager _sound = new Sound(this); + + // Setup the music engine + setupMusic(gs.midi); -#ifndef __GP32__ //ph0x FIXME, "quick dirty hack" - /* Bind the mixer to the system => mixer will be invoked - * automatically when samples need to be generated */ - if (!_mixer->isReady()) { - warning("Sound mixer initialization failed"); - if (_midiDriver == MD_ADLIB || - _midiDriver == MD_PCSPK || - _midiDriver == MD_PCJR) { - _midiDriver = MD_NULL; - warning("MIDI driver depends on sound mixer, switching to null MIDI driver"); - } - } - _mixer->setVolume(ConfMan.getInt("sfx_volume") * ConfMan.getInt("master_volume") / 255); - _mixer->setMusicVolume(ConfMan.getInt("music_volume")); - - // Init iMuse - if (_features & GF_DIGI_IMUSE) { - _musicEngine = _imuseDigital = new IMuseDigital(this, 10); - _mixer->setVolume(ConfMan.getInt("master_volume")); - _imuseDigital->setGroupMusicVolume(ConfMan.getInt("music_volume") / 2); - _imuseDigital->setGroupSfxVolume(ConfMan.getInt("sfx_volume") / 2); - _imuseDigital->setGroupVoiceVolume(ConfMan.getInt("speech_volume") / 2); - } else if ((_features & GF_AMIGA) && (_version == 2)) { - _musicEngine = new Player_V2A(this); - } else if ((_features & GF_AMIGA) && (_version == 3)) { - _musicEngine = new Player_V3A(this); - } else if ((_features & GF_AMIGA) && (_version < 5)) { - _musicEngine = NULL; - } else if (((_midiDriver == MD_PCJR) || (_midiDriver == MD_PCSPK)) && ((_version > 2) && (_version < 5))) { - _musicEngine = new Player_V2(this, _midiDriver != MD_PCSPK); - } else if (_version > 2 && _heversion <= 60) { - MidiDriver *driver = GameDetector::createMidi(_midiDriver); - if (driver && _native_mt32) - driver->property (MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _musicEngine = _imuse = IMuse::create(syst, _mixer, driver); - if (_imuse) { - if (ConfMan.hasKey("tempo")) - _imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo")); - _imuse->property(IMuse::PROP_OLD_ADLIB_INSTRUMENTS, (_features & GF_SMALL_HEADER) ? 1 : 0); - _imuse->property(IMuse::PROP_MULTI_MIDI, ConfMan.getBool("multi_midi") && - _midiDriver != MD_NULL && (gs.midi & MDT_ADLIB)); - _imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32); - if (_features & GF_HUMONGOUS || gs.midi == MDT_TOWNS) { - _imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1); - _imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1); - } - if (gs.midi == MDT_TOWNS) - _imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1); - _imuse->set_music_volume(ConfMan.getInt("music_volume")); - } - } -#endif // ph0x-hack + // TODO: We shouldn't rely on the global Language values matching those COMI etc. expect. + // Rather we should explicitly translate them. + _language = Common::parseLanguage(ConfMan.get("language")); - // Load game from specified slot, if any - if (ConfMan.hasKey("save_slot")) { - requestLoad(ConfMan.getInt("save_slot")); - } + // Load localization data, if present loadLanguageBundle(); - // Load CJK font - _useCJKMode = false; - if ((_gameId == GID_DIG || _gameId == GID_CMI) && (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN)) { - File fp; - const char *fontFile = NULL; - switch(_language) { - case Common::KO_KOR: - fontFile = "korean.fnt"; - break; - case Common::JA_JPN: - fontFile = (_gameId == GID_DIG) ? "kanji16.fnt" : "japanese.fnt"; - break; - case Common::ZH_TWN: - if (_gameId == GID_CMI) { - fontFile = "chinese.fnt"; - } - break; - default: - break; - } - if (fontFile && fp.open(fontFile)) { - debug(2, "Loading CJK Font"); - _useCJKMode = true; - fp.seek(2, SEEK_CUR); - _2byteWidth = fp.readByte(); - _2byteHeight = fp.readByte(); - - int numChar = 0; - switch(_language) { - case Common::KO_KOR: - numChar = 2350; - break; - case Common::JA_JPN: - numChar = (_gameId == GID_DIG) ? 1024 : 2048; //FIXME - break; - case Common::ZH_TWN: - numChar = 1; //FIXME - break; - default: - break; - } - _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar]; - fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); - fp.close(); - } - } else if (_language == Common::JA_JPN && _version == 5) { //FM Towns Kanji - File fp; - int numChar = 256 * 32; - _2byteWidth = 16; - _2byteHeight = 16; - //use FM Towns font rom, since game files don't have kanji font resources - if (fp.open("fmt_fnt.rom")) { - _useCJKMode = true; - debug(2, "Loading FM Towns Kanji rom"); - _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar]; - fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); - fp.close(); - } - } + // Load CJK font, if present + loadCJKFont(); // Create the charset renderer if (_version <= 2) @@ -1061,6 +941,11 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS _insane = new Insane((ScummEngine_v6 *)this); else _insane = 0; + + // Load game from specified slot, if any + if (ConfMan.hasKey("save_slot")) { + requestLoad(ConfMan.getInt("save_slot")); + } } ScummEngine::~ScummEngine() { @@ -1129,7 +1014,7 @@ ScummEngine_v7he::ScummEngine_v7he(GameDetector *detector, OSystem *syst, const } void ScummEngine::go() { - launch(); + mainInit(); mainRun(); } @@ -1137,7 +1022,7 @@ void ScummEngine::go() { #pragma mark --- Initialization --- #pragma mark - -void ScummEngine::launch() { +void ScummEngine::mainInit() { #ifdef __PALM_OS__ if (_features & GF_NEW_COSTUMES) @@ -1197,6 +1082,7 @@ void ScummEngine::launch() { readIndexFile(); scummInit(); + initScummVars(); if (VAR_DEBUGMODE != 0xFF) { // This is NOT for the Mac version of Indy3/Loom @@ -1240,7 +1126,7 @@ void ScummEngine::launch() { void ScummEngine::scummInit() { int i; - tempMusic = 0; + _tempMusic = 0; debug(9, "scummInit"); if ((_gameId == GID_MANIAC) && (_version == 1)) { @@ -1413,8 +1299,6 @@ void ScummEngine::scummInit() { _wizPolygons = (WizPolygon *)calloc(_wizNumPolygons, sizeof(WizPolygon)); } - initScummVars(); - _lastSaveTime = _system->get_msecs(); } @@ -1434,132 +1318,65 @@ void ScummEngine_v6::scummInit() { setCursorHotspot(16, 16); } -void ScummEngine::initScummVars() { - - // This needs to be at least greater than 40 to get the more - // elaborate version of the EGA Zak into. I don't know where - // else it makes any difference. - if (_gameId == GID_ZAK) - VAR(VAR_MACHINE_SPEED) = 0x7FFF; - - if (_version <= 2) - return; - - if (_version >= 4 && _version <= 5) - VAR(VAR_V5_TALK_STRING_Y) = -0x50; +void ScummEngine::setupMusic(int midi) { + _midiDriver = GameDetector::detectMusicDriver(midi); + _native_mt32 = ConfMan.getBool("native_mt32"); - if (_version == 8) { // Fixme: How do we deal with non-cd installs? - VAR(VAR_CURRENTDISK) = 1; - VAR(VAR_LANGUAGE) = _language; - } else if (_version >= 7) { - VAR(VAR_V6_EMSSPACE) = 10000; - VAR(VAR_NUM_GLOBAL_OBJS) = _numGlobalObjects - 1; - } else if (_heversion >= 70) { - VAR(VAR_NUM_SOUND_CHANNELS) = 3; - VAR(VAR_MUSIC_CHANNEL) = 1; - VAR(VAR_SOUND_CHANNEL) = 2; - - if (_heversion >= 72) { - VAR(VAR_NUM_ROOMS) = _numRooms - 1; - VAR(VAR_NUM_SCRIPTS) = _numScripts - 1; - VAR(VAR_NUM_SOUNDS) = _numSounds - 1; - VAR(VAR_NUM_COSTUMES) = _numCostumes - 1; - VAR(VAR_NUM_IMAGES) = _numImages - 1; - VAR(VAR_NUM_CHARSETS) = _numCharsets - 1; - VAR(VAR_NUM_GLOBAL_OBJS) = _numGlobalObjects - 1; - } - if (_heversion >= 80) - VAR(VAR_WINDOWS_VERSION) = 40; - if (_heversion >= 90) - VAR(VAR_NUM_SPRITES) = _numSprites - 1; - } else { - VAR(VAR_CURRENTDRIVE) = 0; - switch (_midiDriver) { - case MD_NULL: VAR(VAR_SOUNDCARD) = 0; break; - case MD_ADLIB: VAR(VAR_SOUNDCARD) = 3; break; - case MD_PCSPK: - case MD_PCJR: VAR(VAR_SOUNDCARD) = 1; break; - default: - if ((_gameId == GID_MONKEY_EGA || _gameId == GID_MONKEY_VGA || _gameId == GID_LOOM) - && (_features & GF_PC)) { - if (_gameId == GID_LOOM) { - char buf[50]; - uint i = 82; - File f; - while (i < 85) { - sprintf(buf, "%d.LFL", i); - f.open(buf); - if (f.isOpen() == false) - error("Native MIDI support requires Roland patch from LucasArts"); - f.close(); - i++; - } - } else if (_gameId == GID_MONKEY_EGA) { - File f; - f.open("DISK09.LEC"); - if (f.isOpen() == false) - error("Native MIDI support requires Roland patch from LucasArts"); - } - VAR(VAR_SOUNDCARD) = 4; - } else - VAR(VAR_SOUNDCARD) = 3; - } - if (_features & GF_FMTOWNS) - VAR(VAR_VIDEOMODE) = 42; - else if (_gameId == GID_INDY3 && (_features & GF_MACINTOSH)) - VAR(VAR_VIDEOMODE) = 50; - else if (_gameId == GID_MONKEY2 && (_features & GF_AMIGA)) - VAR(VAR_VIDEOMODE) = 82; - else - VAR(VAR_VIDEOMODE) = 19; - if (_gameId == GID_LOOM && _features & GF_OLD_BUNDLE) { - // Set number of sound resources - if (!(_features & GF_MACINTOSH)) - VAR(39) = 80; - VAR(VAR_HEAPSPACE) = 1400; - } else if (_version >= 4) { - VAR(VAR_HEAPSPACE) = 1400; - VAR(VAR_FIXEDDISK) = true; - if (_features & GF_HUMONGOUS) { - VAR(VAR_SOUNDPARAM) = 1; // soundblaster for music - VAR(VAR_SOUNDPARAM2) = 1; // soundblaster for sfx - } else { - VAR(VAR_SOUNDPARAM) = 0; - VAR(VAR_SOUNDPARAM2) = 0; - } - VAR(VAR_SOUNDPARAM3) = 0; +#ifndef __GP32__ //ph0x FIXME, "quick dirty hack" + /* Bind the mixer to the system => mixer will be invoked + * automatically when samples need to be generated */ + if (!_mixer->isReady()) { + warning("Sound mixer initialization failed"); + if (_midiDriver == MD_ADLIB || + _midiDriver == MD_PCSPK || + _midiDriver == MD_PCJR) { + _midiDriver = MD_NULL; + warning("MIDI driver depends on sound mixer, switching to null MIDI driver"); } - if (_version >= 5) - VAR(VAR_MOUSEPRESENT) = true; - if (_version == 6) - VAR(VAR_V6_EMSSPACE) = 10000; } - - if ((_features & GF_MACINTOSH) && (_version == 3)) { - // This is the for the Mac version of Indy3/Loom - VAR(39) = 320; - } - - if (VAR_CURRENT_LIGHTS != 0xFF) { - // Setup light - VAR(VAR_CURRENT_LIGHTS) = LIGHTMODE_actor_base | LIGHTMODE_actor_color | LIGHTMODE_screen; - } - - if (_gameId == GID_MONKEY || _gameId == GID_MONKEY_SEGA) - _scummVars[74] = 1225; + _mixer->setVolume(ConfMan.getInt("sfx_volume") * ConfMan.getInt("master_volume") / 255); + _mixer->setMusicVolume(ConfMan.getInt("music_volume")); - if (_version >= 7) { - VAR(VAR_DEFAULT_TALK_DELAY) = 60; - VAR(VAR_VOICE_MODE) = ConfMan.getBool("subtitles"); + // Init iMuse + if (_features & GF_DIGI_IMUSE) { + _musicEngine = _imuseDigital = new IMuseDigital(this, 10); + _mixer->setVolume(ConfMan.getInt("master_volume")); + _imuseDigital->setGroupMusicVolume(ConfMan.getInt("music_volume") / 2); + _imuseDigital->setGroupSfxVolume(ConfMan.getInt("sfx_volume") / 2); + _imuseDigital->setGroupVoiceVolume(ConfMan.getInt("speech_volume") / 2); + } else if ((_features & GF_AMIGA) && (_version == 2)) { + _musicEngine = new Player_V2A(this); + } else if ((_features & GF_AMIGA) && (_version == 3)) { + _musicEngine = new Player_V3A(this); + } else if ((_features & GF_AMIGA) && (_version < 5)) { + _musicEngine = NULL; + } else if (((_midiDriver == MD_PCJR) || (_midiDriver == MD_PCSPK)) && ((_version > 2) && (_version < 5))) { + _musicEngine = new Player_V2(this, _midiDriver != MD_PCSPK); + } else if (_version > 2 && _heversion <= 60) { + MidiDriver *driver = GameDetector::createMidi(_midiDriver); + if (driver && _native_mt32) + driver->property (MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + _musicEngine = _imuse = IMuse::create(_system, _mixer, driver); + if (_imuse) { + if (ConfMan.hasKey("tempo")) + _imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo")); + _imuse->property(IMuse::PROP_OLD_ADLIB_INSTRUMENTS, (_features & GF_SMALL_HEADER) ? 1 : 0); + _imuse->property(IMuse::PROP_MULTI_MIDI, ConfMan.getBool("multi_midi") && + _midiDriver != MD_NULL && (midi & MDT_ADLIB)); + _imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32); + if (_features & GF_HUMONGOUS || midi == MDT_TOWNS) { + _imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1); + _imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1); + } + if (midi == MDT_TOWNS) + _imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1); + _imuse->set_music_volume(ConfMan.getInt("music_volume")); + } } - - if (VAR_FADE_DELAY != 0xFF) - VAR(VAR_FADE_DELAY) = 3; - - VAR(VAR_CHARINC) = 4; - setTalkingActor(0); +#endif // ph0x-hack } + #pragma mark - #pragma mark --- Main loop --- #pragma mark - @@ -1647,8 +1464,6 @@ int ScummEngine::scummLoop(int delta) { // In V1-V3 games, CHARSET_1 is called much earlier than in newer games. // See also bug #770042 for a case were this makes a difference. - // FIXME: Actually I am only sure that this is correct for V1-V2 and Loom. - // We should also check Indy3 & Zak256. if (_version <= 3) CHARSET_1(); @@ -1689,9 +1504,9 @@ int ScummEngine::scummLoop(int delta) { // to get it correct for all games. Without the ability to watch/listen to the // original games, I can't do that myself. const int MUSIC_DELAY = 350; - tempMusic += delta * 15; // Convert delta to milliseconds - if (tempMusic >= MUSIC_DELAY) { - tempMusic -= MUSIC_DELAY; + _tempMusic += delta * 15; // Convert delta to milliseconds + if (_tempMusic >= MUSIC_DELAY) { + _tempMusic -= MUSIC_DELAY; VAR(VAR_MUSIC_TIMER) += 1; } } @@ -1738,12 +1553,8 @@ load_game: displayMessage(0, errMsg, filename); } else if (_saveLoadFlag == 1 && _saveLoadSlot != 0 && !_saveTemporaryState) { // Display "Save successful" message, except for auto saves -#ifdef __PALM_OS__ - char buf[256]; // 1024 is too big overflow the stack -#else - char buf[1024]; -#endif - sprintf(buf, "Successfully saved game state in file:\n\n%s", filename); + char buf[256]; + snprintf(buf, sizeof(buf), "Successfully saved game state in file:\n\n%s", filename); GUI::TimedMessageDialog dialog(buf, 1500); runDialog(dialog); @@ -1917,376 +1728,6 @@ load_game: } #pragma mark - -#pragma mark --- Events / Input --- -#pragma mark - - -void ScummEngine::parseEvents() { - OSystem::Event event; - - while (_system->poll_event(&event)) { - - switch(event.event_code) { - case OSystem::EVENT_KEYDOWN: - if (event.kbd.keycode >= '0' && event.kbd.keycode <= '9' - && (event.kbd.flags == OSystem::KBD_ALT || - event.kbd.flags == OSystem::KBD_CTRL)) { - _saveLoadSlot = event.kbd.keycode - '0'; - - // don't overwrite autosave (slot 0) - if (_saveLoadSlot == 0) - _saveLoadSlot = 10; - - sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot); - _saveLoadFlag = (event.kbd.flags == OSystem::KBD_ALT) ? 1 : 2; - _saveTemporaryState = false; - } else if (event.kbd.flags == OSystem::KBD_CTRL) { - if (event.kbd.keycode == 'f') - _fastMode ^= 1; - else if (event.kbd.keycode == 'g') - _fastMode ^= 2; - else if (event.kbd.keycode == 'd') - _debugger->attach(); - else if (event.kbd.keycode == 's') - resourceStats(); - else - _keyPressed = event.kbd.ascii; // Normal key press, pass on to the game. - } else if (event.kbd.flags & OSystem::KBD_ALT) { - // The result must be 273 for Alt-W - // because that's what MI2 looks for in - // its "instant win" cheat. - _keyPressed = event.kbd.keycode + 154; - } else if (event.kbd.ascii == 315 && (_gameId == GID_CMI && !(_features & GF_DEMO))) { - // FIXME: support in-game menu screen. For now, this remaps F1 to F5 in COMI - _keyPressed = 319; - } else if (_gameId == GID_INDY4 && event.kbd.ascii >= '0' && event.kbd.ascii <= '9') { - // To support keyboard fighting in FOA, we need to remap the number keys. - // FOA apparently expects PC scancode values (see script 46 if you want - // to know where I got these numbers from). - static const int numpad[10] = { - '0', - 335, 336, 337, - 331, 332, 333, - 327, 328, 329 - }; - _keyPressed = numpad[event.kbd.ascii - '0']; - } else if (event.kbd.ascii < 273 || event.kbd.ascii > 276 || _version >= 7) { - // don't let game have arrow keys as we currently steal them - // for keyboard cursor control - // this fixes bug with up arrow (273) corresponding to - // "instant win" cheat in MI2 mentioned above - // - // This is not applicable to Full Throttle as it processes keyboard - // cursor control by itself. Also it fixes derby scene - _keyPressed = event.kbd.ascii; // Normal key press, pass on to the game. - } - - if (_keyPressed >= 512) - debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed); - else - _keyDownMap[_keyPressed] = true; - break; - - case OSystem::EVENT_KEYUP: - // FIXME: for some reason OSystem::KBD_ALT is set sometimes - // possible to a bug in sdl-common.cpp - if (event.kbd.ascii >= 512) - debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii); - else - _keyDownMap[event.kbd.ascii] = false; - break; - - case OSystem::EVENT_MOUSEMOVE: - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - break; - - case OSystem::EVENT_LBUTTONDOWN: - _leftBtnPressed |= msClicked|msDown; -#if defined(_WIN32_WCE) || defined(__PALM_OS__) - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; -#endif - break; - - case OSystem::EVENT_RBUTTONDOWN: - _rightBtnPressed |= msClicked|msDown; -#if defined(_WIN32_WCE) || defined(__PALM_OS__) - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; -#endif - break; - - case OSystem::EVENT_LBUTTONUP: - _leftBtnPressed &= ~msDown; - break; - - case OSystem::EVENT_RBUTTONUP: - _rightBtnPressed &= ~msDown; - break; - - // The following two cases enable dialog choices to be - // scrolled through in the SegaCD version of MI - // as nothing else uses the wheel don't bother - // checking the gameid - - case OSystem::EVENT_WHEELDOWN: - _keyPressed = 55; - break; - - case OSystem::EVENT_WHEELUP: - _keyPressed = 54; - break; - - case OSystem::EVENT_QUIT: - if (_confirmExit) - confirmexitDialog(); - else - _quit = true; - break; - - default: - break; - } - } -} - -void ScummEngine::clearClickedStatus() { - _keyPressed = 0; - _mouseButStat = 0; - _leftBtnPressed &= ~msClicked; - _rightBtnPressed &= ~msClicked; -} - -void ScummEngine::processKbd(bool smushMode) { - int saveloadkey; - - _lastKeyHit = _keyPressed; - _keyPressed = 0; - if (((_version <= 2) || (_features & GF_FMTOWNS && _version == 3)) && 315 <= _lastKeyHit && _lastKeyHit < 315+12) { - // Convert F-Keys for V1/V2 games (they start at 1 instead of at 315) - _lastKeyHit -= 314; - } - - - // - // Clip the mouse coordinates, and compute _virtualMouse.x (and clip it, too) - // - if (_mouse.x < 0) - _mouse.x = 0; - if (_mouse.x > _screenWidth-1) - _mouse.x = _screenWidth-1; - if (_mouse.y < 0) - _mouse.y = 0; - if (_mouse.y > _screenHeight-1) - _mouse.y = _screenHeight-1; - - _virtualMouse.x = _mouse.x + virtscr[0].xstart; - _virtualMouse.y = _mouse.y - virtscr[0].topline; - if (_features & GF_NEW_CAMERA) - _virtualMouse.y += _screenTop; - - if (_virtualMouse.y < 0) - _virtualMouse.y = -1; - if (_virtualMouse.y >= virtscr[0].h) - _virtualMouse.y = -1; - - // - // Determine the mouse button state. - // - _mouseButStat = 0; - - // Interpret 'return' as left click and 'tab' as right click - if (_lastKeyHit && _cursor.state > 0) { - if (_lastKeyHit == 9) { - _mouseButStat = MBS_RIGHT_CLICK; - _lastKeyHit = 0; - } else if (_lastKeyHit == 13) { - _mouseButStat = MBS_LEFT_CLICK; - _lastKeyHit = 0; - } - } - - if (_leftBtnPressed & msClicked && _rightBtnPressed & msClicked && _version > 3) { - // Pressing both mouse buttons is treated as if you pressed - // the cutscene exit key (i.e. ESC in most games). That mimicks - // the behaviour of the original engine where pressing both - // mouse buttons also skips the current cutscene. - _mouseButStat = 0; - _lastKeyHit = (uint)VAR(VAR_CUTSCENEEXIT_KEY); - } else if (_rightBtnPressed & msClicked && (_version < 4 && _gameId != GID_LOOM)) { - // Pressing right mouse button is treated as if you pressed - // the cutscene exit key (i.e. ESC in most games). That mimicks - // the behaviour of the original engine where pressing right - // mouse button also skips the current cutscene. - _mouseButStat = 0; - _lastKeyHit = (uint)VAR(VAR_CUTSCENEEXIT_KEY); - } else if (_leftBtnPressed & msClicked) { - _mouseButStat = MBS_LEFT_CLICK; - } else if (_rightBtnPressed & msClicked) { - _mouseButStat = MBS_RIGHT_CLICK; - } - - if (_version == 8) { - VAR(VAR_MOUSE_BUTTONS) = 0; - VAR(VAR_MOUSE_HOLD) = 0; - VAR(VAR_RIGHTBTN_HOLD) = 0; - - if (_leftBtnPressed & msClicked) - VAR(VAR_MOUSE_BUTTONS) += 1; - - if (_rightBtnPressed & msClicked) - VAR(VAR_MOUSE_BUTTONS) += 2; - - if (_leftBtnPressed & msDown) - VAR(VAR_MOUSE_HOLD) += 1; - - if (_rightBtnPressed & msDown) { - VAR(VAR_RIGHTBTN_HOLD) = 1; - VAR(VAR_MOUSE_HOLD) += 2; - } - } else if (_version >= 6) { - VAR(VAR_LEFTBTN_HOLD) = (_leftBtnPressed & msDown) != 0; - VAR(VAR_RIGHTBTN_HOLD) = (_rightBtnPressed & msDown) != 0; - - if (_version == 7) { - VAR(VAR_LEFTBTN_DOWN) = (_leftBtnPressed & msClicked) != 0; - VAR(VAR_RIGHTBTN_DOWN) = (_rightBtnPressed & msClicked) != 0; - } - } - - _leftBtnPressed &= ~msClicked; - _rightBtnPressed &= ~msClicked; - - if (!_lastKeyHit) - return; - - // If a key script was specified (a V8 feature), and it's trigger - // key was pressed, run it. - if (_keyScriptNo && (_keyScriptKey == _lastKeyHit)) { - runScript(_keyScriptNo, 0, 0, 0); - return; - } - -#ifdef _WIN32_WCE - if (_lastKeyHit == KEY_ALL_SKIP) { - // Skip cutscene - if (smushMode) { - _lastKeyHit = (uint)VAR(VAR_CUTSCENEEXIT_KEY); - } - else - if (vm.cutScenePtr[vm.cutSceneStackPointer]) - _lastKeyHit = (uint)VAR(VAR_CUTSCENEEXIT_KEY); - else - // Skip talk - if (_talkDelay > 0) - _lastKeyHit = (uint)VAR(VAR_TALKSTOP_KEY); - else - // Escape - _lastKeyHit = 27; - } -#endif - - if (VAR_RESTART_KEY != 0xFF && _lastKeyHit == VAR(VAR_RESTART_KEY) || - (((_version <= 2) || (_features & GF_FMTOWNS && _version == 3)) && _lastKeyHit == 8)) { - confirmrestartDialog(); - return; - } - - if ((VAR_PAUSE_KEY != 0xFF && _lastKeyHit == VAR(VAR_PAUSE_KEY)) || - (VAR_PAUSE_KEY == 0xFF && _lastKeyHit == ' ')) { - pauseGame(); - return; - } - - // COMI version string is hard coded - // Dig/FT version strings are partly hard coded too - if (_version == 7 && _lastKeyHit == VAR(VAR_VERSION_KEY)) { - versionDialog(); - return; - } - - if ((_version <= 2) || (_features & GF_FMTOWNS && _version == 3)) - saveloadkey = 5; // F5 - else if ((_version <= 3) || (_gameId == GID_SAMNMAX) || (_gameId == GID_CMI) || (_heversion >= 72)) - saveloadkey = 319; // F5 - else - saveloadkey = VAR(VAR_MAINMENU_KEY); - - if (_lastKeyHit == VAR(VAR_CUTSCENEEXIT_KEY) || - (VAR(VAR_CUTSCENEEXIT_KEY) == 4 && _lastKeyHit == 27)) { - // Skip cutscene (or active SMUSH video). For the V2 games, which - // normally use F4 for this, we add in a hack that makes escape work, - // too (just for convenience). - if (smushMode) { - if (_gameId == GID_FT) - _insane->escapeKeyHandler(); - else - _smushVideoShouldFinish = true; - } - if (!smushMode || _smushVideoShouldFinish) - abortCutscene(); - if (_version <= 2) { - // Ensure that the input script also sees the key press. - // This is necessary so you can abort the airplane travel - // in Zak. - VAR(VAR_KEYPRESS) = VAR(VAR_CUTSCENEEXIT_KEY); - } - } else if (_lastKeyHit == saveloadkey) { - if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0) - runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0); - - mainMenuDialog(); // Display NewGui - - if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0) - runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0); - return; - } else if (VAR_TALKSTOP_KEY != 0xFF && _lastKeyHit == VAR(VAR_TALKSTOP_KEY)) { - _talkDelay = 0; - if (_sound->_sfxMode & 2) - stopTalk(); - return; - } else if (_lastKeyHit == '[') { // [ Music volume down - int vol = ConfMan.getInt("music_volume"); - if (!(vol & 0xF) && vol) - vol -= 16; - vol = vol & 0xF0; - ConfMan.set("music_volume", vol); - if (_imuse) - _imuse->set_music_volume (vol); - } else if (_lastKeyHit == ']') { // ] Music volume up - int vol = ConfMan.getInt("music_volume"); - vol = (vol + 16) & 0xFF0; - if (vol > 255) vol = 255; - ConfMan.set("music_volume", vol); - if (_imuse) - _imuse->set_music_volume (vol); - } else if (_lastKeyHit == '-') { // - text speed down - if (_defaultTalkDelay < 9) - _defaultTalkDelay++; - if (VAR_CHARINC != 0xFF) - VAR(VAR_CHARINC) = _defaultTalkDelay; - } else if (_lastKeyHit == '+') { // + text speed up - if (_defaultTalkDelay > 0) - _defaultTalkDelay--; - if (VAR_CHARINC != 0xFF) - VAR(VAR_CHARINC) = _defaultTalkDelay; - } else if (_lastKeyHit == '~' || _lastKeyHit == '#') { // Debug console - _debugger->attach(); - } else if (_version <= 2) { - // Store the input type. So far we can't distinguish - // between 1, 3 and 5. - // 1) Verb 2) Scene 3) Inv. 4) Key - // 5) Sentence Bar - - if (_lastKeyHit) { // Key Input - VAR(VAR_KEYPRESS) = _lastKeyHit; - } - } - - _mouseButStat = _lastKeyHit; -} - -#pragma mark - #pragma mark --- SCUMM --- #pragma mark - @@ -2831,7 +2272,7 @@ void ScummEngine::initRoomSubBlocks() { // HE 7.0 games load resources but don't use them. if (_version >= 4 && _heversion <= 60) { if (_features & GF_SMALL_HEADER) - ptr = findResourceSmall (MKID('CYCL'), roomptr); + ptr = findResourceSmall(MKID('CYCL'), roomptr); else ptr = findResourceData(MKID('CYCL'), roomptr); if (ptr) { @@ -2910,6 +2351,12 @@ void ScummEngine::restart() { // TODO: Check this function - we should probably be reinitting a lot more stuff, and I suspect // this leaks memory like a sieve +// Fingolfing seez: An alternate way to implement restarting would be to create +// a save state right after startup ... to this end we could introduce a SaveFile +// subclass which is implemented using a memory buffer (i.e. no actual file is +// created). Then to restart we just have to load that pseudo save state. + + int i; // Reset some stuff @@ -2931,6 +2378,7 @@ void ScummEngine::restart() { allocateArrays(); // Reallocate arrays readIndexFile(); // Reread index (reset objectstate etc) scummInit(); // Reinit scumm variables + initScummVars(); if (_imuse) { _imuse->setBase(res.address[rtSound]); } @@ -3036,99 +2484,6 @@ char ScummEngine::displayMessage(const char *altButton, const char *message, ... #pragma mark --- Miscellaneous --- #pragma mark - -int SJIStoFMTChunk(int f, int s) //convert sjis code to fmt font offset -{ - enum { - KANA = 0, - KANJI = 1, - EKANJI = 2 - }; - int base = s - (s % 32) - 1; - int c = 0, p = 0, chunk_f = 0, chunk = 0, cr, kanjiType = KANA; - - if (f >= 0x81 && f <= 0x84) kanjiType = KANA; - if (f >= 0x88 && f <= 0x9f) kanjiType = KANJI; - if (f >= 0xe0 && f <= 0xea) kanjiType = EKANJI; - - if ((f > 0xe8 || (f == 0xe8 && base >= 0x9f)) || (f > 0x90 || (f == 0x90 && base >= 0x9f))) { - c = 48; //correction - p = -8; //correction - } - - if (kanjiType == KANA) {//Kana - chunk_f = (f - 0x81) * 2; - } else if (kanjiType == KANJI) {//Standard Kanji - p += f - 0x88; - chunk_f = c + 2 * p; - } else if (kanjiType == EKANJI) {//Enhanced Kanji - p += f - 0xe0; - chunk_f = c + 2 * p; - } - - if (base == 0x7f && s == 0x7f) - base -= 0x20; //correction - if ((base == 0x7f && s == 0x9e) || (base == 0x9f && s == 0xbe) || (base == 0xbf && s == 0xde)) - base += 0x20; //correction - - switch(base) { - case 0x3f: - cr = 0; //3f - if (kanjiType == KANA) chunk = 1; - else if (kanjiType == KANJI) chunk = 31; - else if (kanjiType == EKANJI) chunk = 111; - break; - case 0x5f: - cr = 0; //5f - if (kanjiType == KANA) chunk = 17; - else if (kanjiType == KANJI) chunk = 47; - else if (kanjiType == EKANJI) chunk = 127; - break; - case 0x7f: - cr = -1; //80 - if (kanjiType == KANA) chunk = 9; - else if (kanjiType == KANJI) chunk = 63; - else if (kanjiType == EKANJI) chunk = 143; - break; - case 0x9f: - cr = 1; //9e - if (kanjiType == KANA) chunk = 2; - else if (kanjiType == KANJI) chunk = 32; - else if (kanjiType == EKANJI) chunk = 112; - break; - case 0xbf: - cr = 1; //be - if (kanjiType == KANA) chunk = 18; - else if (kanjiType == KANJI) chunk = 48; - else if (kanjiType == EKANJI) chunk = 128; - break; - case 0xdf: - cr = 1; //de - if (kanjiType == KANA) chunk = 10; - else if (kanjiType == KANJI) chunk = 64; - else if (kanjiType == EKANJI) chunk = 144; - break; - default: - return 0; - } - - return ((chunk_f + chunk) * 32 + (s - base)) + cr; -} - -byte *ScummEngine::get2byteCharPtr(int idx) { - switch(_language) { - case Common::KO_KOR: - idx = ((idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; - break; - case Common::JA_JPN: - idx = SJIStoFMTChunk((idx % 256), (idx / 256)); - break; - case Common::ZH_TWN: - default: - idx = 0; - } - return _2byteFontPtr + ((_2byteWidth + 7) / 8) * _2byteHeight * idx; -} - void ScummEngine::errorString(const char *buf1, char *buf2) { if (_currentScript != 0xFF) { ScriptSlot *ss = &vm.slot[_currentScript]; @@ -3158,12 +2513,8 @@ void ScummEngine::errorString(const char *buf1, char *buf2) { void checkRange(int max, int min, int no, const char *str) { if (no < min || no > max) { -#ifdef __PALM_OS__ - char buf[256]; // 1024 is too big overflow the stack -#else - char buf[1024]; -#endif - sprintf(buf, str, no); + char buf[256]; + snprintf(buf, sizeof(buf), str, no); error("Value %d is out of bounds (%d,%d) (%s)", no, min, max, buf); } } |