diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/agi/saveload.cpp | 3 | ||||
-rw-r--r-- | engines/configure.engines | 4 | ||||
-rw-r--r-- | engines/cruise/cruise_main.cpp | 107 | ||||
-rw-r--r-- | engines/dreamweb/detection_tables.h | 16 | ||||
-rw-r--r-- | engines/dreamweb/dreamweb.cpp | 20 | ||||
-rw-r--r-- | engines/dreamweb/module.mk | 1 | ||||
-rw-r--r-- | engines/dreamweb/mouse.cpp | 171 | ||||
-rw-r--r-- | engines/dreamweb/stubs.cpp | 142 | ||||
-rw-r--r-- | engines/kyra/screen.cpp | 19 | ||||
-rw-r--r-- | engines/sci/detection_tables.h | 13 | ||||
-rw-r--r-- | engines/sci/engine/features.cpp | 3 | ||||
-rw-r--r-- | engines/sci/engine/features.h | 7 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.cpp | 8 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 6 | ||||
-rw-r--r-- | engines/scumm/detection.cpp | 10 | ||||
-rw-r--r-- | engines/scumm/scumm-md5.h | 3 | ||||
-rw-r--r-- | engines/sword25/script/luabindhelper.cpp | 2 | ||||
-rw-r--r-- | engines/tinsel/detection_tables.h | 2 | ||||
-rw-r--r-- | engines/tinsel/music.cpp | 94 | ||||
-rw-r--r-- | engines/tinsel/music.h | 6 | ||||
-rw-r--r-- | engines/tinsel/tinlib.cpp | 2 |
21 files changed, 389 insertions, 250 deletions
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 8e524c8d9a..d58e55a6b9 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -831,6 +831,9 @@ int AgiEngine::scummVMSaveLoadDialog(bool isSave) { delete dialog; + if (slot < 0) + return true; + if (isSave) return doSave(slot, desc); else diff --git a/engines/configure.engines b/engines/configure.engines index 93c349378d..91e5e82506 100644 --- a/engines/configure.engines +++ b/engines/configure.engines @@ -7,11 +7,11 @@ add_engine agos "AGOS" yes "agos2" add_engine agos2 "AGOS 2 games" yes add_engine cge "CGE" yes add_engine cine "Cinematique evo 1" yes -add_engine composer "Magic Composer" no +add_engine composer "Magic Composer" yes add_engine cruise "Cinematique evo 2" yes add_engine draci "Dragon History" yes add_engine drascula "Drascula: The Vampire Strikes Back" yes -add_engine dreamweb "Dreamweb" no +add_engine dreamweb "Dreamweb" yes add_engine gob "Gobli*ns" yes add_engine groovie "Groovie" yes "groovie2" add_engine groovie2 "Groovie 2 games" no diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 6e2847d6d7..911041c1a4 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -1799,32 +1799,60 @@ void CruiseEngine::mainLoop() { // Handle frame delay uint32 currentTick = g_system->getMillis(); - if (!bFastMode) { - // Delay for the specified amount of time, but still respond to events - bool skipEvents = false; + // Delay for the specified amount of time, but still respond to events + bool skipEvents = false; - do { - g_system->updateScreen(); + do { + if (userEnabled && !userWait && !autoTrack) { + if (currentActiveMenu == -1) { + static int16 oldMouseX = -1; + static int16 oldMouseY = -1; - g_system->delayMillis(10); - currentTick = g_system->getMillis(); + getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); - if (!skipEvents) - skipEvents = manageEvents(); + if (mouseX != oldMouseX || mouseY != oldMouseY) { + int objectType; + int newCursor1; + int newCursor2; - if (playerDontAskQuit) - break; + oldMouseX = mouseX; + oldMouseY = mouseY; - _vm->getDebugger()->onFrame(); - } while (currentTick < lastTick + _gameSpeed); - } else { - manageEvents(); + objectType = findObject(mouseX, mouseY, &newCursor1, &newCursor2); - if (currentTick >= (lastTickDebug + 10)) { - lastTickDebug = currentTick; - _vm->getDebugger()->onFrame(); + if (objectType == 9) { + changeCursor(CURSOR_EXIT); + } else if (objectType != -1) { + changeCursor(CURSOR_MAGNIFYING_GLASS); + } else { + changeCursor(CURSOR_WALK); + } + } + } else { + changeCursor(CURSOR_NORMAL); + } + } else { + changeCursor(CURSOR_NORMAL); } - } + + g_system->updateScreen(); + + if (!skipEvents || bFastMode) + skipEvents = manageEvents(); + + if (bFastMode) { + if (currentTick >= (lastTickDebug + 10)) + lastTickDebug = currentTick; + } else { + g_system->delayMillis(10); + currentTick = g_system->getMillis(); + } + + if (playerDontAskQuit) + break; + + _vm->getDebugger()->onFrame(); + } while (currentTick < lastTick + _gameSpeed && !bFastMode); if (playerDontAskQuit) break; @@ -1844,6 +1872,14 @@ void CruiseEngine::mainLoop() { // readKeyboard(); bool isUserWait = userWait != 0; + // WORKAROUND: This prevents hotspots responding during + // delays i.e. Menu opening if you click fast on another + // hotspot after trying to open a locked door, which + // occurred with the original interpreter. + if (userDelay) { + currentMouseButton = 0; + } + playerDontAskQuit = processInput(); if (playerDontAskQuit) break; @@ -1855,7 +1891,6 @@ void CruiseEngine::mainLoop() { if (userDelay && !userWait) { userDelay--; - continue; } if (isUserWait & !userWait) { @@ -1918,38 +1953,6 @@ void CruiseEngine::mainLoop() { mainDraw(userWait); flipScreen(); - if (userEnabled && !userWait && !autoTrack) { - if (currentActiveMenu == -1) { - static int16 oldMouseX = -1; - static int16 oldMouseY = -1; - - getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); - - if (mouseX != oldMouseX || mouseY != oldMouseY) { - int objectType; - int newCursor1; - int newCursor2; - - oldMouseX = mouseX; - oldMouseY = mouseY; - - objectType = findObject(mouseX, mouseY, &newCursor1, &newCursor2); - - if (objectType == 9) { - changeCursor(CURSOR_EXIT); - } else if (objectType != -1) { - changeCursor(CURSOR_MAGNIFYING_GLASS); - } else { - changeCursor(CURSOR_WALK); - } - } - } else { - changeCursor(CURSOR_NORMAL); - } - } else { - changeCursor(CURSOR_NORMAL); - } - if (userWait == 1) { // Waiting for press - original wait loop has been integrated into the // main event loop diff --git a/engines/dreamweb/detection_tables.h b/engines/dreamweb/detection_tables.h index 8ca24d1724..d54b2402c8 100644 --- a/engines/dreamweb/detection_tables.h +++ b/engines/dreamweb/detection_tables.h @@ -45,7 +45,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_UNSTABLE, + ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -62,7 +62,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_CD | ADGF_UNSTABLE, + ADGF_CD | ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -96,7 +96,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_CD | ADGF_UNSTABLE, + ADGF_CD | ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -113,7 +113,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_UNSTABLE, + ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -130,7 +130,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_CD | ADGF_UNSTABLE, + ADGF_CD | ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -147,7 +147,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_UNSTABLE, + ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -164,7 +164,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_CD | ADGF_UNSTABLE, + ADGF_CD | ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, @@ -181,7 +181,7 @@ static const DreamWebGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_UNSTABLE, + ADGF_TESTING, GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) }, }, diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index 2e9c7bb2b8..299dd74b53 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -422,25 +422,6 @@ void DreamWebEngine::keyPressed(uint16 ascii) { DreamWeb::g_keyBuffer[in] = ascii; } -void DreamWebEngine::mouseCall(uint16 *x, uint16 *y, uint16 *state) { - processEvents(); - Common::Point pos = _eventMan->getMousePos(); - if (pos.x > 298) - pos.x = 298; - if (pos.x < 15) - pos.x = 15; - if (pos.y < 15) - pos.y = 15; - if (pos.y > 184) - pos.y = 184; - *x = pos.x; - *y = pos.y; - - unsigned newState = _eventMan->getButtonState(); - *state = (newState == _oldMouseState? 0 : newState); - _oldMouseState = newState; -} - void DreamWebEngine::getPalette(uint8 *data, uint start, uint count) { _system->getPaletteManager()->grabPalette(data, start, count); while (count--) @@ -541,6 +522,7 @@ uint8 DreamWebEngine::modifyChar(uint8 c) const { return c; } case Common::FR_FRA: + case Common::IT_ITA: switch(c) { case 133: return 'Z' + 1; diff --git a/engines/dreamweb/module.mk b/engines/dreamweb/module.mk index 6bc4f8728e..3e367c6fdf 100644 --- a/engines/dreamweb/module.mk +++ b/engines/dreamweb/module.mk @@ -7,6 +7,7 @@ MODULE_OBJS := \ dreamweb.o \ keypad.o \ monitor.o \ + mouse.o \ newplace.o \ object.o \ pathfind.o \ diff --git a/engines/dreamweb/mouse.cpp b/engines/dreamweb/mouse.cpp new file mode 100644 index 0000000000..77d907611d --- /dev/null +++ b/engines/dreamweb/mouse.cpp @@ -0,0 +1,171 @@ +/* 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. + * + */ + +#include "common/events.h" +#include "dreamweb/dreamweb.h" + +namespace DreamWeb { + +void DreamWebEngine::mouseCall(uint16 *x, uint16 *y, uint16 *state) { + processEvents(); + Common::Point pos = _eventMan->getMousePos(); + *x = CLIP<int16>(pos.x, 15, 298); + *y = CLIP<int16>(pos.y, 15, 184); + + unsigned newState = _eventMan->getButtonState(); + *state = (newState == _oldMouseState ? 0 : newState); + _oldMouseState = newState; +} + +void DreamWebEngine::readMouse() { + _oldButton = _mouseButton; + _mouseButton = readMouseState(); +} + +uint16 DreamWebEngine::readMouseState() { + _oldX = _mouseX; + _oldY = _mouseY; + uint16 x, y, state; + mouseCall(&x, &y, &state); + _mouseX = x; + _mouseY = y; + return state; +} + +void DreamWebEngine::dumpPointer() { + dumpBlink(); + multiDump(_delHereX, _delHereY, _delXS, _delYS); + if ((_oldPointerX != _delHereX) || (_oldPointerY != _delHereY)) + multiDump(_oldPointerX, _oldPointerY, _pointerXS, _pointerYS); +} + +void DreamWebEngine::showPointer() { + showBlink(); + uint16 x = _mouseX; + _oldPointerX = _mouseX; + uint16 y = _mouseY; + _oldPointerY = _mouseY; + if (_pickUp == 1) { + const GraphicsFile *frames; + if (_objectType != kExObjectType) + frames = &_freeFrames; + else + frames = &_exFrames; + const Frame *frame = &frames->_frames[(3 * _itemFrame + 1)]; + + uint8 width = MAX<uint8>(frame->width, 12); + uint8 height = MAX<uint8>(frame->height, 12); + _pointerXS = width; + _pointerYS = height; + uint16 xMin = (x >= width / 2) ? x - width / 2 : 0; + uint16 yMin = (y >= height / 2) ? y - height / 2 : 0; + _oldPointerX = xMin; + _oldPointerY = yMin; + multiGet(_pointerBack, xMin, yMin, width, height); + showFrame(*frames, x, y, 3 * _itemFrame + 1, 128); + showFrame(_icons1, x, y, 3, 128); + } else { + const Frame *frame = &_icons1._frames[_pointerFrame + 20]; + uint8 width = MAX<uint8>(frame->width, 12); + uint8 height = MAX<uint8>(frame->height, 12); + _pointerXS = width; + _pointerYS = height; + multiGet(_pointerBack, x, y, width, height); + showFrame(_icons1, x, y, _pointerFrame + 20, 0); + } +} + +void DreamWebEngine::delPointer() { + if (_oldPointerX == 0xffff) + return; + _delHereX = _oldPointerX; + _delHereY = _oldPointerY; + _delXS = _pointerXS; + _delYS = _pointerYS; + multiPut(_pointerBack, _delHereX, _delHereY, _pointerXS, _pointerYS); +} + +void DreamWebEngine::animPointer() { + if (_pointerMode == 2) { + _pointerFrame = 0; + if ((_realLocation == 14) && (_commandType == 211)) + _pointerFrame = 5; + return; + } else if (_pointerMode == 3) { + if (_pointerSpeed != 0) { + --_pointerSpeed; + } else { + _pointerSpeed = 5; + ++_pointerCount; + if (_pointerCount == 16) + _pointerCount = 0; + } + _pointerFrame = (_pointerCount <= 8) ? 1 : 2; + return; + } + if (_vars._watchingTime != 0) { + _pointerFrame = 11; + return; + } + _pointerFrame = 0; + if (_inMapArea == 0) + return; + if (_pointerFirstPath == 0) + return; + uint8 flag, flagEx; + getFlagUnderP(&flag, &flagEx); + if (flag < 2) + return; + if (flag >= 128) + return; + if (flag & 4) { + _pointerFrame = 3; + return; + } + if (flag & 16) { + _pointerFrame = 4; + return; + } + if (flag & 2) { + _pointerFrame = 5; + return; + } + if (flag & 8) { + _pointerFrame = 6; + return; + } + _pointerFrame = 8; +} + +void DreamWebEngine::checkCoords(const RectWithCallback *rectWithCallbacks) { + if (_newLocation != 0xff) + return; + const RectWithCallback *r; + for (r = rectWithCallbacks; r->_xMin != 0xffff; ++r) { + if (r->contains(_mouseX, _mouseY)) { + (this->*(r->_callback))(); + return; + } + } +} + +} // End of namespace DreamWeb diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp index 5a53b82510..750dafe7b4 100644 --- a/engines/dreamweb/stubs.cpp +++ b/engines/dreamweb/stubs.cpp @@ -876,22 +876,6 @@ void DreamWebEngine::hangOnCurs(uint16 frameCount) { } } -void DreamWebEngine::readMouse() { - _oldButton = _mouseButton; - uint16 state = readMouseState(); - _mouseButton = state; -} - -uint16 DreamWebEngine::readMouseState() { - _oldX = _mouseX; - _oldY = _mouseY; - uint16 x, y, state; - mouseCall(&x, &y, &state); - _mouseX = x; - _mouseY = y; - return state; -} - void DreamWebEngine::dumpTextLine() { if (_newTextLine != 1) return; @@ -1513,16 +1497,6 @@ void DreamWebEngine::obName(uint8 command, uint8 commandType) { } } -void DreamWebEngine::delPointer() { - if (_oldPointerX == 0xffff) - return; - _delHereX = _oldPointerX; - _delHereY = _oldPointerY; - _delXS = _pointerXS; - _delYS = _pointerYS; - multiPut(_pointerBack, _delHereX, _delHereY, _pointerXS, _pointerYS); -} - void DreamWebEngine::showBlink() { if (_manIsOffScreen == 1) return; @@ -1554,110 +1528,6 @@ void DreamWebEngine::dumpBlink() { multiDump(44, 32, 16, 12); } -void DreamWebEngine::dumpPointer() { - dumpBlink(); - multiDump(_delHereX, _delHereY, _delXS, _delYS); - if ((_oldPointerX != _delHereX) || (_oldPointerY != _delHereY)) - multiDump(_oldPointerX, _oldPointerY, _pointerXS, _pointerYS); -} - -void DreamWebEngine::showPointer() { - showBlink(); - uint16 x = _mouseX; - _oldPointerX = _mouseX; - uint16 y = _mouseY; - _oldPointerY = _mouseY; - if (_pickUp == 1) { - const GraphicsFile *frames; - if (_objectType != kExObjectType) - frames = &_freeFrames; - else - frames = &_exFrames; - const Frame *frame = &frames->_frames[(3 * _itemFrame + 1)]; - - uint8 width = frame->width; - uint8 height = frame->height; - if (width < 12) - width = 12; - if (height < 12) - height = 12; - _pointerXS = width; - _pointerYS = height; - uint16 xMin = (x >= width / 2) ? x - width / 2 : 0; - uint16 yMin = (y >= height / 2) ? y - height / 2 : 0; - _oldPointerX = xMin; - _oldPointerY = yMin; - multiGet(_pointerBack, xMin, yMin, width, height); - showFrame(*frames, x, y, 3 * _itemFrame + 1, 128); - showFrame(_icons1, x, y, 3, 128); - } else { - const Frame *frame = &_icons1._frames[_pointerFrame + 20]; - uint8 width = frame->width; - uint8 height = frame->height; - if (width < 12) - width = 12; - if (height < 12) - height = 12; - _pointerXS = width; - _pointerYS = height; - multiGet(_pointerBack, x, y, width, height); - showFrame(_icons1, x, y, _pointerFrame + 20, 0); - } -} - -void DreamWebEngine::animPointer() { - - if (_pointerMode == 2) { - _pointerFrame = 0; - if ((_realLocation == 14) && (_commandType == 211)) - _pointerFrame = 5; - return; - } else if (_pointerMode == 3) { - if (_pointerSpeed != 0) { - --_pointerSpeed; - } else { - _pointerSpeed = 5; - ++_pointerCount; - if (_pointerCount == 16) - _pointerCount = 0; - } - _pointerFrame = (_pointerCount <= 8) ? 1 : 2; - return; - } - if (_vars._watchingTime != 0) { - _pointerFrame = 11; - return; - } - _pointerFrame = 0; - if (_inMapArea == 0) - return; - if (_pointerFirstPath == 0) - return; - uint8 flag, flagEx; - getFlagUnderP(&flag, &flagEx); - if (flag < 2) - return; - if (flag >= 128) - return; - if (flag & 4) { - _pointerFrame = 3; - return; - } - if (flag & 16) { - _pointerFrame = 4; - return; - } - if (flag & 2) { - _pointerFrame = 5; - return; - } - if (flag & 8) { - _pointerFrame = 6; - return; - } - _pointerFrame = 8; -} - void DreamWebEngine::printMessage(uint16 x, uint16 y, uint8 index, uint8 maxWidth, bool centered) { const uint8 *string = (const uint8 *)_commandText.getString(index); printDirect(string, x, y, maxWidth, centered); @@ -3183,16 +3053,4 @@ void DreamWebEngine::purgeAnItem() { } } -void DreamWebEngine::checkCoords(const RectWithCallback *rectWithCallbacks) { - if (_newLocation != 0xff) - return; - const RectWithCallback *r; - for (r = rectWithCallbacks; r->_xMin != 0xffff; ++r) { - if (r->contains(_mouseX, _mouseY)) { - (this->*(r->_callback))(); - return; - } - } -} - } // End of namespace DreamWeb diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index d3b4d6f943..711fe15348 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -95,8 +95,23 @@ bool Screen::init() { _use16ColorMode = _vm->gameFlags().use16ColorMode; _isAmiga = (_vm->gameFlags().platform == Common::kPlatformAmiga); - if (ConfMan.hasKey("render_mode")) - _renderMode = Common::parseRenderMode(ConfMan.get("render_mode")); + // We only check the "render_mode" setting for both Eye of the Beholder + // games here, since all the other games do not support the render_mode + // setting or handle it differently, like Kyra 1 PC-98. This avoids + // graphics glitches and crashes in other games, when the user sets his + // global render_mode setting to EGA for example. + // TODO/FIXME: It would be nice not to hardcode this. But there is no + // trivial/non annoying way to do mode checks in an easy fashion right + // now. + // In a more general sense, we might want to think about a way to only + // pass valid config values, as in values which the engine can work with, + // to the engines. We already limit the selection via our GUIO flags in + // the game specific settings, but this is not enough due to global + // settings allowing everything. + if (_vm->game() == GI_EOB1 || _vm->game() == GI_EOB2) { + if (ConfMan.hasKey("render_mode")) + _renderMode = Common::parseRenderMode(ConfMan.get("render_mode")); + } // CGA and EGA modes use additional pages to do the CGA/EGA specific graphics conversions. if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) { diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d741bb801f..ff78d4f18b 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -3445,6 +3445,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 4 1.000 - French DOS Floppy (supplied by misterhands in bug report #3515247) + {"sq4", "", { + + {"resource.map", 0, "1fd6f356f6a59ad2057686ce6573caeb", 6159}, + {"resource.000", 0, "8000a55aebc50a68b7cce07a8c33758c", 205287}, + {"resource.001", 0, "99a6df6d366b3f061271ff3450ac0d32", 1269850}, + {"resource.002", 0, "a6a8d7a24dbb7a266a26b084e7275e89", 1242668}, + {"resource.003", 0, "482a99c8103b4bcb5706e5969d1c1193", 1323083}, + {"resource.004", 0, "b2cca3afcf2e013b8ce86b64155af766", 1254353}, + {"resource.005", 0, "9e520577e035547c4b5149a6d12ef85b", 1098814}, + AD_LISTEND}, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 4 1.000 - English DOS Floppy (from abevi, bug report #2612718) {"sq4", "", { {"resource.map", 0, "8f08b97ca093f370c56d99715b015554", 6153}, diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index cad95b1c18..8a932232f8 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -45,6 +45,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan) _usesCdTrack = Common::File::exists("cdaudio.map"); if (!ConfMan.getBool("use_cdaudio")) _usesCdTrack = false; + _forceDOSTracks = false; } reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc, int methodNum) { @@ -642,7 +643,7 @@ MoveCountType GameFeatures::detectMoveCountType() { } bool GameFeatures::useAltWinGMSound() { - if (g_sci && g_sci->getPlatform() == Common::kPlatformWindows && g_sci->isCD()) { + if (g_sci && g_sci->getPlatform() == Common::kPlatformWindows && g_sci->isCD() && !_forceDOSTracks) { SciGameId id = g_sci->getGameId(); return (id == GID_ECOQUEST || id == GID_JONES || diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h index 4592c5be9c..f6bb0b5759 100644 --- a/engines/sci/engine/features.h +++ b/engines/sci/engine/features.h @@ -117,6 +117,12 @@ public: */ bool useAltWinGMSound(); + /** + * Forces DOS soundtracks in Windows CD versions when the user hasn't + * selected a MIDI output device + */ + void forceDOSTracks() { _forceDOSTracks = true; } + private: reg_t getDetectionAddr(const Common::String &objName, Selector slc, int methodNum = -1); @@ -137,6 +143,7 @@ private: MoveCountType _moveCountType; bool _usesCdTrack; + bool _forceDOSTracks; SegManager *_segMan; Kernel *_kernel; diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 71f4598afc..14ffa69f91 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -148,11 +148,13 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey - // Special case for the magnifier cursor in LB1 (bug #3487092). - // No other SCI0 game has a cursor resource of 1, so this is handled - // specifically for LB1. + // TODO: Figure out if the grey color is hardcoded + // HACK for the magnifier cursor in LB1, fixes its color (bug #3487092) if (g_sci->getGameId() == GID_LAURABOW && resourceId == 1) colorMapping[3] = _screen->getColorWhite(); + // HACK for Longbow cursors, fixes the shade of grey they're using (bug #3489101) + if (g_sci->getGameId() == GID_LONGBOW) + colorMapping[3] = _palette->matchColor(223, 223, 223); // Light Grey // Seek to actual data resourceData += 4; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 09cab75c39..918b045cb9 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -88,6 +88,12 @@ void SciMusic::init() { uint32 dev = MidiDriver::detectDevice(deviceFlags); _musicType = MidiDriver::getMusicType(dev); + if (g_sci->_features->useAltWinGMSound() && _musicType != MT_GM) { + warning("A Windows CD version with an alternate MIDI soundtrack has been chosen, " + "but no MIDI music device has been selected. Reverting to the DOS soundtrack"); + g_sci->_features->forceDOSTracks(); + } + switch (_musicType) { case MT_ADLIB: // FIXME: There's no Amiga sound option, so we hook it up to AdLib diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index b47982af00..2da0abb5df 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -589,11 +589,11 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul file.c_str(), md5str.c_str(), filesize); // Sanity check: We *should* have found a matching gameid / variant at this point. - // If not, then there's a bug in our data tables... - assert(dr.game.gameid != 0); - - // Add it to the list of detected games - results.push_back(dr); + // If not, we may have #ifdef'ed the entry out in our detection_tables.h because we + // don't have the required stuff compiled in, or there's a bug in our data tables... + if (dr.game.gameid != 0) + // Add it to the list of detected games + results.push_back(dr); } } diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index c25c875616..3957c7c42d 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Mon Apr 9 12:23:48 2012 + This file was generated by the md5table tool on Tue Apr 24 03:50:58 2012 DO NOT EDIT MANUALLY! */ @@ -621,6 +621,7 @@ static const MD5Table md5table[] = { { "f40a7f495f59188ca57a9d1d50301bb6", "puttputt", "HE 60", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "f5228b0cc1c19e6ea8268ba2eeb61f60", "freddi", "HE 73", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "f73883f13b5a302749a5bad31d909780", "tentacle", "", "CD", -1, Common::DE_DEU, Common::kPlatformMacintosh }, + { "f7635a0e2ab82c9a0f9ace5f232a488f", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, { "f7711f9264d4d43c2a1518ec7c10a607", "pajama3", "", "", 79382, Common::EN_USA, Common::kPlatformUnknown }, { "f79e60c17cca601e411f1f75e8ee9b5a", "spyfox2", "", "", 51286, Common::UNK_LANG, Common::kPlatformUnknown }, { "f8be685007a8b425ba2a455da732f59f", "pajama2", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh }, diff --git a/engines/sword25/script/luabindhelper.cpp b/engines/sword25/script/luabindhelper.cpp index 8fbbe7e272..6900305f5c 100644 --- a/engines/sword25/script/luabindhelper.cpp +++ b/engines/sword25/script/luabindhelper.cpp @@ -412,7 +412,7 @@ Common::String LuaBindhelper::stackDump(lua_State *L) { oss += "------------------- Stack Dump -------------------\n"; while (i) { - oss += i + ": " + getLuaValueInfo(L, i) + "\n"; + oss += Common::String::format("%d: ", i) + getLuaValueInfo(L, i) + "\n"; i--; } diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h index be44b1c462..b6b19f6ee7 100644 --- a/engines/tinsel/detection_tables.h +++ b/engines/tinsel/detection_tables.h @@ -397,7 +397,7 @@ static const TinselGameDescription gameDescriptions[] = { { // multilanguage PSX demo { "dw", - "CD demo", + "CD Demo", { {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914}, {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942}, diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index 781a378f13..fa5334a033 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -131,11 +131,6 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) { g_currentMidi = dwFileOffset; g_currentLoop = bLoop; - // Tinsel V1 PSX uses a different music format, so i - // disable it here. - // TODO: Maybe this should be moved to a better place... - if (TinselV1PSX) return false; - if (_vm->_config->_musicVolume != 0) { bool mute = false; if (ConfMan.hasKey("mute")) @@ -231,14 +226,14 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) { _vm->_midiMusic->send(0x7F07B0 | 13); } - _vm->_midiMusic->playXMIDI(g_midiBuffer.pDat, dwSeqLen, bLoop); + _vm->_midiMusic->playMIDI(dwSeqLen, bLoop); // Store the length //dwLastSeqLen = dwSeqLen; } else { // dwFileOffset == dwLastMidiIndex _vm->_midiMusic->stop(); - _vm->_midiMusic->playXMIDI(g_midiBuffer.pDat, dwSeqLen, bLoop); + _vm->_midiMusic->playMIDI(dwSeqLen, bLoop); } return true; @@ -314,8 +309,7 @@ void OpenMidiFiles() { Common::File midiStream; // Demo version has no midi file - // Also, Discworld PSX uses still unsupported psx SEQ format for music... - if ((_vm->getFeatures() & GF_DEMO) || (TinselVersion == TINSEL_V2) || TinselV1PSX) + if ((_vm->getFeatures() & GF_DEMO) || (TinselVersion == TINSEL_V2)) return; if (g_midiBuffer.pDat) @@ -412,7 +406,7 @@ void MidiMusicPlayer::send(uint32 b) { } } -void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { +void MidiMusicPlayer::playMIDI(uint32 size, bool loop) { Common::StackLock lock(_mutex); if (_isPlaying) @@ -420,6 +414,13 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { stop(); + if (TinselV1PSX) + playSEQ(size, loop); + else + playXMIDI(size, loop); +} + +void MidiMusicPlayer::playXMIDI(uint32 size, bool loop) { // It seems like not all music (the main menu music, for instance) set // all the instruments explicitly. That means the music will sound // different, depending on which music played before it. This appears @@ -433,7 +434,78 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { // Load XMID resource data MidiParser *parser = MidiParser::createParser_XMIDI(); - if (parser->loadMusic(midiData, size)) { + if (parser->loadMusic(g_midiBuffer.pDat, size)) { + parser->setTrack(0); + parser->setMidiDriver(this); + parser->setTimerRate(getBaseTempo()); + parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); + + _parser = parser; + + _isLooping = loop; + _isPlaying = true; + } else { + delete parser; + } +} + +void MidiMusicPlayer::playSEQ(uint32 size, bool loop) { + // MIDI.DAT holds the file names in DW1 PSX + Common::String baseName((char *)g_midiBuffer.pDat, size); + Common::String seqName = baseName + ".SEQ"; + + // TODO: Load the instrument bank (<baseName>.VB and <baseName>.VH) + + Common::File seqFile; + if (!seqFile.open(seqName)) + error("Failed to open SEQ file '%s'", seqName.c_str()); + + if (seqFile.readUint32LE() != MKTAG('S', 'E', 'Q', 'p')) + error("Failed to find SEQp tag"); + + // Make sure we don't have a SEP file (with multiple SEQ's inside) + if (seqFile.readUint32BE() != 1) + error("Can only play SEQ files, not SEP"); + + uint16 ppqn = seqFile.readUint16BE(); + uint32 tempo = seqFile.readUint16BE() << 8; + tempo |= seqFile.readByte(); + /* uint16 beat = */ seqFile.readUint16BE(); + + // SEQ is directly based on SMF and we'll use that to our advantage here + // and convert to SMF and then use the SMF MidiParser. + + // Calculate the SMF size we'll need + uint32 dataSize = seqFile.size() - 15; + uint32 actualSize = dataSize + 7 + 22; + + // Resize the buffer if necessary + if (g_midiBuffer.size < actualSize) { + g_midiBuffer.pDat = (byte *)realloc(g_midiBuffer.pDat, actualSize); + assert(g_midiBuffer.pDat); + } + + // Now construct the header + WRITE_BE_UINT32(g_midiBuffer.pDat, MKTAG('M', 'T', 'h', 'd')); + WRITE_BE_UINT32(g_midiBuffer.pDat + 4, 6); // header size + WRITE_BE_UINT16(g_midiBuffer.pDat + 8, 0); // type 0 + WRITE_BE_UINT16(g_midiBuffer.pDat + 10, 1); // one track + WRITE_BE_UINT16(g_midiBuffer.pDat + 12, ppqn); + WRITE_BE_UINT32(g_midiBuffer.pDat + 14, MKTAG('M', 'T', 'r', 'k')); + WRITE_BE_UINT32(g_midiBuffer.pDat + 18, dataSize + 7); // SEQ data size + tempo change event size + + // Add in a fake tempo change event + WRITE_BE_UINT32(g_midiBuffer.pDat + 22, 0x00FF5103); // no delta, meta event, tempo change, param size = 3 + WRITE_BE_UINT16(g_midiBuffer.pDat + 26, tempo >> 8); + g_midiBuffer.pDat[28] = tempo & 0xFF; + + // Now copy in the rest of the events + seqFile.read(g_midiBuffer.pDat + 29, dataSize); + seqFile.close(); + + MidiParser *parser = MidiParser::createParser_SMF(); + if (parser->loadMusic(g_midiBuffer.pDat, actualSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h index d43fed268d..121bf3d79b 100644 --- a/engines/tinsel/music.h +++ b/engines/tinsel/music.h @@ -64,7 +64,7 @@ public: virtual void setVolume(int volume); - void playXMIDI(byte *midiData, uint32 size, bool loop); + void playMIDI(uint32 size, bool loop); // void stop(); void pause(); @@ -76,6 +76,10 @@ public: // The original sets the "sequence timing" to 109 Hz, whatever that // means. The default is 120. uint32 getBaseTempo() { return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; } + +private: + void playXMIDI(uint32 size, bool loop); + void playSEQ(uint32 size, bool loop); }; class PCMMusicPlayer : public Audio::AudioStream { diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index c652abca25..cd65a4ec32 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -1626,7 +1626,7 @@ static void Play(CORO_PARAM, SCNHANDLE hFilm, int x, int y, bool bComplete, int */ static void PlayMidi(CORO_PARAM, SCNHANDLE hMidi, int loop, bool complete) { // FIXME: This is a workaround for the FIXME below - if (GetMidiVolume() == 0 || TinselV1PSX) + if (GetMidiVolume() == 0) return; CORO_BEGIN_CONTEXT; |