From 6bff6116050a892247f9d84a78e21922823bfc47 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Wed, 28 Mar 2012 19:16:29 +0200 Subject: BASE: Destroy singletons on exit. --- base/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/base/main.cpp b/base/main.cpp index 99dcac63d3..6fb56b49c4 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -55,6 +55,9 @@ #include "audio/mididrv.h" #include "audio/musicplugin.h" /* for music manager */ +#include "graphics/cursorman.h" +#include "graphics/fontman.h" + #include "backends/keymapper/keymapper.h" #if defined(_WIN32_WCE) @@ -493,10 +496,15 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { PluginManager::destroy(); GUI::GuiManager::destroy(); Common::ConfigManager::destroy(); + Common::DebugManager::destroy(); + Common::EventRecorder::destroy(); Common::SearchManager::destroy(); #ifdef USE_TRANSLATION Common::TranslationManager::destroy(); #endif + MusicManager::destroy(); + Graphics::CursorManager::destroy(); + Graphics::FontManager::destroy(); return 0; } -- cgit v1.2.3 From fdee01bf04f1d66e4365e39c871c4b00d7b78946 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Wed, 28 Mar 2012 19:16:52 +0200 Subject: GRAPHICS: Don't try to delete static BDF data. --- graphics/fonts/bdf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/fonts/bdf.h b/graphics/fonts/bdf.h index 5b615cc043..b0166a2095 100644 --- a/graphics/fonts/bdf.h +++ b/graphics/fonts/bdf.h @@ -77,7 +77,7 @@ private: #define DEFINE_FONT(n) \ const BdfFont *n = 0; \ void create_##n() { \ - n = new BdfFont(desc, DisposeAfterUse::YES); \ + n = new BdfFont(desc, DisposeAfterUse::NO); \ } #define FORWARD_DECLARE_FONT(n) \ -- cgit v1.2.3 From 6d3927cd7a6e93452366085e179b156558f78a2b Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Wed, 28 Mar 2012 19:17:13 +0200 Subject: GRAPHICS: Take ownership of fonts passed to FontManager. --- graphics/fontman.cpp | 36 ++++++++++++++++++++++++++++++++++++ graphics/fontman.h | 5 ++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/graphics/fontman.cpp b/graphics/fontman.cpp index 8d967d595f..99dd3d664f 100644 --- a/graphics/fontman.cpp +++ b/graphics/fontman.cpp @@ -47,6 +47,13 @@ FontManager::FontManager() { } FontManager::~FontManager() { + for (uint i = 0; i < _ownedFonts.size(); ++i) { + const Font *font = _ownedFonts[i]; + if (font == g_sysfont || font == g_sysfont_big || font == g_consolefont) + continue; + delete font; + } + delete g_sysfont; g_sysfont = 0; delete g_sysfont_big; @@ -90,6 +97,8 @@ bool FontManager::assignFontToName(const Common::String &name, const Font *font) Common::String lowercaseName = name; lowercaseName.toLowercase(); _fontMap[lowercaseName] = font; + if (Common::find(_ownedFonts.begin(), _ownedFonts.end(), font) == _ownedFonts.end()) + _ownedFonts.push_back(font); return true; } @@ -116,8 +125,35 @@ bool FontManager::setFont(FontUsage usage, const BdfFont *font) { void FontManager::removeFontName(const Common::String &name) { Common::String lowercaseName = name; lowercaseName.toLowercase(); + if (!_fontMap.contains(lowercaseName)) + return; + + const Font *font = _fontMap[lowercaseName]; _fontMap.erase(lowercaseName); + // Check if we still have a copy of this font in the map. + bool stillHasFont = false; + for (Common::HashMap::iterator i = _fontMap.begin(); i != _fontMap.end(); ++i) { + if (i->_value != font) + continue; + stillHasFont = true; + break; + } + + if (!stillHasFont) { + // We don't have a copy of the font, so remove it from our list and delete it. + stillHasFont = true; + for (uint i = 0; i < _ownedFonts.size(); ++i) { + if (_ownedFonts[i] != font) + continue; + stillHasFont = false; + _ownedFonts.remove_at(i); + break; + } + assert(!stillHasFont); + delete font; + } + // In case the current localized font is removed, we fall back to the // default font again. if (_localizedFontName == lowercaseName) diff --git a/graphics/fontman.h b/graphics/fontman.h index 42f7d856fa..b06ddea860 100644 --- a/graphics/fontman.h +++ b/graphics/fontman.h @@ -60,7 +60,9 @@ public: const Font *getFontByName(const Common::String &name) const; /** - * Associates a font object with an 'name' + * Associates a font object with an 'name'. + * The FontManager takes ownership of the provided font object + * and will delete it when necesssary. * * @param name the name of the font * @param font the font object @@ -111,6 +113,7 @@ private: ~FontManager(); Common::HashMap _fontMap; + Common::Array _ownedFonts; Common::String _localizedFontName; }; -- cgit v1.2.3 From b470c9af28752a1f360bf8c459ffd8fdcca3e6fb Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Wed, 28 Mar 2012 19:17:53 +0200 Subject: BASE: Free TTFLibrary singleton on shutdown. This uses a helper function because TTFLibrary is internal. --- base/main.cpp | 6 ++++++ graphics/fonts/ttf.cpp | 4 ++++ graphics/fonts/ttf.h | 2 ++ 3 files changed, 12 insertions(+) diff --git a/base/main.cpp b/base/main.cpp index 6fb56b49c4..e103b70d68 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -57,6 +57,9 @@ #include "graphics/cursorman.h" #include "graphics/fontman.h" +#ifdef USE_FREETYPE2 +#include "graphics/fonts/ttf.h" +#endif #include "backends/keymapper/keymapper.h" @@ -505,6 +508,9 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { MusicManager::destroy(); Graphics::CursorManager::destroy(); Graphics::FontManager::destroy(); +#ifdef USE_FREETYPE2 + Graphics::shutdownTTF(); +#endif return 0; } diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp index 7505f7913e..7f5c616710 100644 --- a/graphics/fonts/ttf.cpp +++ b/graphics/fonts/ttf.cpp @@ -70,6 +70,10 @@ private: bool _initialized; }; +void shutdownTTF() { + TTFLibrary::destroy(); +} + #define g_ttf ::Graphics::TTFLibrary::instance() TTFLibrary::TTFLibrary() : _library(), _initialized(false) { diff --git a/graphics/fonts/ttf.h b/graphics/fonts/ttf.h index 7222d6e112..ec7dbe04ef 100644 --- a/graphics/fonts/ttf.h +++ b/graphics/fonts/ttf.h @@ -34,6 +34,8 @@ namespace Graphics { class Font; Font *loadTTFFont(Common::SeekableReadStream &stream, int size, bool monochrome = false, const uint32 *mapping = 0); +void shutdownTTF(); + } // End of namespace Graphics #endif -- cgit v1.2.3 From 29e05ec05eb85cc1402ebee2c399a4a45bcd4933 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Wed, 28 Mar 2012 19:18:25 +0200 Subject: OPENGL: Don't leak surfaces. --- backends/graphics/opengl/opengl-graphics.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 45804b5d6e..cd820ae3b2 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -70,6 +70,11 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { free(_gamePalette); free(_cursorPalette); + _screenData.free(); + _overlayData.free(); + _cursorData.free(); + _osdSurface.free(); + delete _gameTexture; delete _overlayTexture; delete _cursorTexture; -- cgit v1.2.3 From c5363006edf0744adfd0b48a67389213b8bea9ba Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 19 Apr 2012 11:49:06 -0400 Subject: GRAPHICS: Only accept JPEG CompressedQuickTime PICT opcodes --- graphics/decoders/pict.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/graphics/decoders/pict.cpp b/graphics/decoders/pict.cpp index 957342084e..9963873b54 100644 --- a/graphics/decoders/pict.cpp +++ b/graphics/decoders/pict.cpp @@ -541,10 +541,14 @@ void PICTDecoder::decodeCompressedQuickTime(Common::SeekableReadStream &stream) // Now we've reached the image descriptor, so read the relevant data from that uint32 idStart = stream.pos(); uint32 idSize = stream.readUint32BE(); - stream.skip(40); // miscellaneous stuff + uint32 codec = stream.readUint32BE(); + stream.skip(36); // miscellaneous stuff uint32 jpegSize = stream.readUint32BE(); stream.skip(idSize - (stream.pos() - idStart)); // more useless stuff + if (codec != MKTAG('j', 'p', 'e', 'g')) + error("Unhandled CompressedQuickTime format '%s'", tag2str(codec)); + Common::SeekableSubReadStream jpegStream(&stream, stream.pos(), stream.pos() + jpegSize); JPEGDecoder jpeg; -- cgit v1.2.3 From c4b08c0b98331af3d92d3d2fce6b55b3b25adcc8 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Fri, 20 Apr 2012 21:50:26 +0100 Subject: CRUISE: Move cursor update to upper "idle" loop in main function. This is the first part of the patch supplied by Ignaz Forster on bug #3423955 ("CRUISE: Slow / unresponsive game behaviour") for avoiding blocking graphical updates during user wait loops. Hotspots passed during the idle loop do _not_ give any user feedback without this patch. The original patch has been split to allow for better understanding of the changes and to allow fine grained bisection if this introduces any regressions. --- engines/cruise/cruise_main.cpp | 64 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 6e2847d6d7..4f202ca4f6 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -1804,6 +1804,38 @@ void CruiseEngine::mainLoop() { bool skipEvents = false; do { + 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); + } + g_system->updateScreen(); g_system->delayMillis(10); @@ -1918,38 +1950,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 -- cgit v1.2.3 From f351a1d7ba28db0924e602e9ee9677edf4ac72f0 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 21 Apr 2012 01:03:25 +0100 Subject: CRUISE: Modification to main loop to update cursor, even in FastMode. This is the second part of the patch supplied by Ignaz Forster on bug #3423955 ("CRUISE: Slow / unresponsive game behaviour") for avoiding blocking graphical updates during user wait loops. This removes the check for fastMode from the cursor update code and other code in this "idle" loop, and moves it down to qualifying only a few of the function calls. --- engines/cruise/cruise_main.cpp | 78 ++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 4f202ca4f6..fe113deebf 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -1799,64 +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 { - if (userEnabled && !userWait && !autoTrack) { - if (currentActiveMenu == -1) { - static int16 oldMouseX = -1; - static int16 oldMouseY = -1; + do { + if (userEnabled && !userWait && !autoTrack) { + if (currentActiveMenu == -1) { + static int16 oldMouseX = -1; + static int16 oldMouseY = -1; - getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); + getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); - if (mouseX != oldMouseX || mouseY != oldMouseY) { - int objectType; - int newCursor1; - int newCursor2; + if (mouseX != oldMouseX || mouseY != oldMouseY) { + int objectType; + int newCursor1; + int newCursor2; - oldMouseX = mouseX; - oldMouseY = mouseY; + oldMouseX = mouseX; + oldMouseY = mouseY; - objectType = findObject(mouseX, mouseY, &newCursor1, &newCursor2); + objectType = findObject(mouseX, mouseY, &newCursor1, &newCursor2); - if (objectType == 9) { - changeCursor(CURSOR_EXIT); - } else if (objectType != -1) { - changeCursor(CURSOR_MAGNIFYING_GLASS); - } else { - changeCursor(CURSOR_WALK); - } + 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); } + } else { + changeCursor(CURSOR_NORMAL); + } + + g_system->updateScreen(); - 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 (!skipEvents) - skipEvents = manageEvents(); - - if (playerDontAskQuit) - break; - - _vm->getDebugger()->onFrame(); - } while (currentTick < lastTick + _gameSpeed); - } else { - manageEvents(); + if (playerDontAskQuit) + break; - if (currentTick >= (lastTickDebug + 10)) { - lastTickDebug = currentTick; - _vm->getDebugger()->onFrame(); - } - } + _vm->getDebugger()->onFrame(); + } while (currentTick < lastTick + _gameSpeed && !bFastMode); if (playerDontAskQuit) break; -- cgit v1.2.3 From a5745434d30f0039db0f5ca7b5ff6781b777d819 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sat, 21 Apr 2012 01:31:42 +0100 Subject: CRUISE: Fix update of background animations while waiting for user. This is the third and final part of the patch supplied by Ignaz Forster on bug #3423955 ("CRUISE: Slow / unresponsive game behaviour") for avoiding blocking graphical updates during user wait loops. The removal of the continue statement fixes the update of background animations while waiting for user to respond i.e. try opening a locked door on the upper deck of the boat and check the sea background animation, but it also has the side effect of allowing hotspots to respond during this period if the user clicks fast enough. However, this bug was also present in the original interpreter, and a workaround has been added to inhibit this. --- engines/cruise/cruise_main.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index fe113deebf..911041c1a4 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -1872,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; @@ -1883,7 +1891,6 @@ void CruiseEngine::mainLoop() { if (userDelay && !userWait) { userDelay--; - continue; } if (isUserWait & !userWait) { -- cgit v1.2.3 From 6ecf27711c886b1422f26acc87cdfd893897eb64 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 22 Apr 2012 16:05:41 +0300 Subject: DREAMWEB: Move all of the mouse cursor related code into a separate file --- engines/dreamweb/dreamweb.cpp | 19 ----- engines/dreamweb/module.mk | 1 + engines/dreamweb/mouse.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++ engines/dreamweb/stubs.cpp | 142 -------------------------------- 4 files changed, 188 insertions(+), 161 deletions(-) create mode 100644 engines/dreamweb/mouse.cpp diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index 2e9c7bb2b8..0a35bcdecc 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--) 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..043aaeb2f4 --- /dev/null +++ b/engines/dreamweb/mouse.cpp @@ -0,0 +1,187 @@ +/* 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(); + 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::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 = 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::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 -- cgit v1.2.3 From 8a227d69037f4b0a1241c9930657a5457def08a8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 22 Apr 2012 16:32:52 +0300 Subject: DREAMWEB: Slight cleanup --- engines/dreamweb/mouse.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/engines/dreamweb/mouse.cpp b/engines/dreamweb/mouse.cpp index 043aaeb2f4..77d907611d 100644 --- a/engines/dreamweb/mouse.cpp +++ b/engines/dreamweb/mouse.cpp @@ -28,19 +28,11 @@ namespace DreamWeb { 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; + *x = CLIP(pos.x, 15, 298); + *y = CLIP(pos.y, 15, 184); unsigned newState = _eventMan->getButtonState(); - *state = (newState == _oldMouseState? 0 : newState); + *state = (newState == _oldMouseState ? 0 : newState); _oldMouseState = newState; } @@ -80,12 +72,8 @@ void DreamWebEngine::showPointer() { 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; + uint8 width = MAX(frame->width, 12); + uint8 height = MAX(frame->height, 12); _pointerXS = width; _pointerYS = height; uint16 xMin = (x >= width / 2) ? x - width / 2 : 0; @@ -97,12 +85,8 @@ void DreamWebEngine::showPointer() { 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; + uint8 width = MAX(frame->width, 12); + uint8 height = MAX(frame->height, 12); _pointerXS = width; _pointerYS = height; multiGet(_pointerBack, x, y, width, height); -- cgit v1.2.3 From b7a5573dda40a120f3af7333caed7ad1d32b924c Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sun, 22 Apr 2012 14:32:44 +0100 Subject: SWORD25: Correct stack dump debug function output. This was introduced by the change from C++ output streams (<<) to Common::String output. Thanks to salty-horse for finding this. --- engines/sword25/script/luabindhelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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--; } -- cgit v1.2.3 From 4d6f2875de900ea41663b99be0f148096561bf5d Mon Sep 17 00:00:00 2001 From: D G Turner Date: Sun, 22 Apr 2012 16:41:30 +0100 Subject: GRAPHICS: Fix BMP getPalette function definition. The BMP decoder getPalette function definition is now identical to the other image format decoders subclassed from ImageDecoder. This also fixes a overloaded virtual warning reported by salty-horse. --- graphics/decoders/bmp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/decoders/bmp.h b/graphics/decoders/bmp.h index 6360aa81c9..8a37538ee1 100644 --- a/graphics/decoders/bmp.h +++ b/graphics/decoders/bmp.h @@ -51,7 +51,7 @@ public: void destroy(); virtual bool loadStream(Common::SeekableReadStream &stream); virtual const Surface *getSurface() const { return _surface; } - virtual const byte *getPalette() { return _palette; } + const byte *getPalette() const { return _palette; } private: Surface *_surface; -- cgit v1.2.3 From cc1ae7b190b4f586e4b0a9d2f78d9195dd88c09a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 24 Apr 2012 01:11:53 +0200 Subject: KYRA: Fix crahes in Kyra 1-3 and LoL when EGA/CGA graphics mode is selected. This is a regression from 86a817beb5eef248c5f5e28f18133db802a59c2e. Formerly Kyra always queried the render_mode and initializes its Screen functionality accordingly, even when the game actually only supported VGA. While in the "Edit game..." options only VGA was selectable, the global options still allowed for example EGA to be selected and thus messing up the internal state. I only check the render_mode setting for EoB 1 and 2 now, which are the only games which support the setting inside Screen. --- engines/kyra/screen.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) 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) { -- cgit v1.2.3 From a322ee83dd281de93d2ab564366d474821132d90 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Tue, 24 Apr 2012 15:19:32 +1000 Subject: Add another English demo version of the Humongous Interactive Catalog. --- devtools/scumm-md5.txt | 1 + engines/scumm/scumm-md5.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt index 01d806a484..7d2ea94f10 100644 --- a/devtools/scumm-md5.txt +++ b/devtools/scumm-md5.txt @@ -590,6 +590,7 @@ FreddisFunShop Freddi Fish's One-Stop Fun Shop catalog Humongous Interactive Catalog 11e6e244078ff09b0f3832e35420e0a7 -1 en Windows - Demo - khalek, sev 037385a953789190298494d92b89b3d0 -1 en Windows HE 72 Demo - khalek, sev + f7635a0e2ab82c9a0f9ace5f232a488f -1 en Windows HE 72 Demo - Kirben a56e8d9d4281c53c3f63c9bd22a59e21 10978342 en All HE CUP Preview George Kormendi 74da3494fbe1a7d20213b0afe0954755 10841544 fr All HE CUP Preview - George Kormendi 4c4820518e16e1a0e3616a3b021a04f3 10927456 de All HE CUP Preview - Kirben 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 }, -- cgit v1.2.3 From fe4cd8d9ff680e7eb84cba73e0f688e4b64cf68e Mon Sep 17 00:00:00 2001 From: Joost Peters Date: Thu, 26 Apr 2012 21:27:08 +0200 Subject: CONFIGURE: fix typo in --with-freetype2-prefix help message --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index cdc44a8c01..46b7308ceb 100755 --- a/configure +++ b/configure @@ -840,7 +840,7 @@ Optional Libraries: --with-sdl-prefix=DIR Prefix where the sdl-config script is installed (optional) - --with-freetype-prefix=DIR Prefix where the freetype-config script is + --with-freetype2-prefix=DIR Prefix where the freetype-config script is installed (optional) --with-nasm-prefix=DIR Prefix where nasm executable is installed (optional) -- cgit v1.2.3 From cc2b95b068b4dc7cc8dbb33578589d9d3316869c Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Fri, 27 Apr 2012 14:12:55 +0200 Subject: PS3: Fix build using lastest ps3toolchain --- configure | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 46b7308ceb..88dc161595 100755 --- a/configure +++ b/configure @@ -1403,6 +1403,10 @@ ps3) echo "Please set PS3DEV in your environment. export PS3DEV=" exit 1 fi + if test -z "$PSL1GHT"; then + echo "Please set PSL1GHT in your environment. export PSL1GHT=" + exit 1 + fi ;; psp) if test -z "$PSPDEV"; then @@ -2068,8 +2072,8 @@ case $_host_os in _sdlpath="$PS3DEV/portlibs/ppu:$PS3DEV/portlibs/ppu/bin" DEFINES="$DEFINES -DPLAYSTATION3" - CXXFLAGS="$CXXFLAGS -mcpu=cell -mminimal-toc -I$PS3DEV/psl1ght/ppu/include -I$PS3DEV/portlibs/ppu/include" - LDFLAGS="$LDFLAGS -L$PS3DEV/psl1ght/ppu/lib -L$PS3DEV/portlibs/ppu/lib" + CXXFLAGS="$CXXFLAGS -mcpu=cell -mminimal-toc -I$PSL1GHT/ppu/include -I$PS3DEV/portlibs/ppu/include" + LDFLAGS="$LDFLAGS -L$PSL1GHT/ppu/lib -L$PS3DEV/portlibs/ppu/lib" add_line_to_config_mk 'PLAYSTATION3 = 1' add_line_to_config_h "#define PREFIX \"${prefix}\"" ;; -- cgit v1.2.3 From bdb12a9c658fa0e8661c7a8370f1d926ed31ae62 Mon Sep 17 00:00:00 2001 From: Ben Castricum Date: Mon, 23 Apr 2012 18:51:15 +0200 Subject: SCUMM: Fix bug #3493317 by removing assert() in detection algorithm. Bug #3493317 ("SCUMM: Detecting Loom PCE without 16bpp support crashes") is caused by an assert() in detection algorithm. In case an MD5 is found the md5table, but the variant from the md5table is not found in detection_tables.h this assert triggers. However since certain variants can be left out compile-time this situation can occur. By ignoring instead of assert()-ing the entry ScummVM will no longer abort but continue the detection process. --- engines/scumm/detection.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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::ListeditCount && position < Timestamp(0, _parentTrack->editList[_curEdit].timeOffset, _decoder->_timeScale); _curEdit++) + for (_curEdit = 0; _curEdit < _parentTrack->editCount - 1 && position > Timestamp(0, _parentTrack->editList[_curEdit].timeOffset, _decoder->_timeScale); _curEdit++) ; enterNewEdit(position); -- cgit v1.2.3 From ad248c9b0b28a50208930c3b49fa4b51420f1f56 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:21:52 +0300 Subject: SCI: Add the French floppy version of SQ4 (bug #3515247) --- engines/sci/detection_tables.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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}, -- cgit v1.2.3 From 24e57808aa946ad38379b43ca205af6ef151c66a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:26:05 +0300 Subject: SCI: Add a hack to fix the cursor colors in Longbow (bug #3489101) --- engines/sci/graphics/cursor.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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; -- cgit v1.2.3 From e41e412c9ee6c277233ef9f7a5304f8cc40fa370 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:43:04 +0300 Subject: SCI: Fix for bug #3522046 "Detection of SQ4CD as Windows breaks Music" Fall back to the DOS soundtracks in Windows CD versions if the user picks a non-General MIDI music device, as the Windows tracks only contain MIDI music --- engines/sci/engine/features.cpp | 3 ++- engines/sci/engine/features.h | 7 +++++++ engines/sci/sound/music.cpp | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) 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/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 -- cgit v1.2.3 From f23ca8b62b6be15e570311dcaad301067c8e052a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 30 Apr 2012 00:09:56 +0200 Subject: COMMON: Use the file cache in ZipArchive::listMembers for performance. This avoids a new iteration through the .zip file for every listMember call. Instead it uses the "_hash" HashMap, which already contains all the filenames and is filled on initializing the ZipArchive by unzOpen. --- common/unzip.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/common/unzip.cpp b/common/unzip.cpp index 8cfcd605fa..ab659343a2 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -1463,22 +1463,16 @@ bool ZipArchive::hasFile(const String &name) const { } int ZipArchive::listMembers(ArchiveMemberList &list) const { - int matches = 0; - int err = unzGoToFirstFile(_zipFile); + int members = 0; - while (err == UNZ_OK) { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - if (unzGetCurrentFileInfo(_zipFile, NULL, - szCurrentFileName, sizeof(szCurrentFileName)-1, - NULL, 0, NULL, 0) == UNZ_OK) { - list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(szCurrentFileName, this))); - matches++; - } - - err = unzGoToNextFile(_zipFile); + const unz_s *const archive = (const unz_s *)_zipFile; + for (ZipHash::const_iterator i = archive->_hash.begin(), end = archive->_hash.end(); + i != end; ++i) { + list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(i->_key, this))); + ++members; } - return matches; + return members; } const ArchiveMemberPtr ZipArchive::getMember(const String &name) const { -- cgit v1.2.3 From ec1070678caa1070e3d229a80f77ad78a8360b33 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Wed, 2 May 2012 20:22:04 +0100 Subject: CREATE_PROJECT: Fix tool help output to reflect command line changes. --- devtools/create_project/create_project.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp index 293cc0b2de..df220f0934 100644 --- a/devtools/create_project/create_project.cpp +++ b/devtools/create_project/create_project.cpp @@ -654,14 +654,14 @@ void displayHelp(const char *exe) { "\n" "Engines settings:\n" " --list-engines list all available engines and their default state\n" - " --enable-engine enable building of the engine with the name \"engine\"\n" - " --disable-engine disable building of the engine with the name \"engine\"\n" + " --enable-engine= enable building of the engine with the name \"name\"\n" + " --disable-engine= disable building of the engine with the name \"name\"\n" " --enable-all-engines enable building of all engines\n" " --disable-all-engines disable building of all engines\n" "\n" "Optional features settings:\n" - " --enable-name enable inclusion of the feature \"name\"\n" - " --disable-name disable inclusion of the feature \"name\"\n" + " --enable- enable inclusion of the feature \"name\"\n" + " --disable- disable inclusion of the feature \"name\"\n" "\n" " There are the following features available:\n" "\n"; -- cgit v1.2.3 From d6bedc8a36d5a0785f27912cd99a3137a2a7062d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 2 May 2012 23:51:02 +0300 Subject: AGI: Proper handling of the cancel button when saving/loading --- engines/agi/saveload.cpp | 3 +++ 1 file changed, 3 insertions(+) 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 -- cgit v1.2.3 From 8d157ae1858c6aab2acc78c732b547dd4e94723a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 3 May 2012 04:28:43 +0300 Subject: NEWS: Mention all of the new games that have been announced --- NEWS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NEWS b/NEWS index b208646d74..0a48ccab9a 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,17 @@ For a more comprehensive changelog of the latest experimental code, see: 1.5.0 (????-??-??) New Games: + - Added support for Blue Force. + - Added support for Darby the Dragon. + - Added support for Dreamweb. + - Added support for Gregory and the Hot Air Balloon. + - Added support for Magic Tales: Baba Yaga and the Magic Geese. + - Added support for Magic Tales: Imo and the King. + - Added support for Magic Tales: Liam Finds a Story. + - Added support for Magic Tales: The Little Samurai. + - Added support for Sleeping Cub's Test of Courage. - Added support for Soltys. + - Added support for The Princess and the Crab. General: - Updated MT-32 emulation code to latest munt project snapshot. The emulation -- cgit v1.2.3 From e6c317a9226b71af572d2e2004e307c0e895b77c Mon Sep 17 00:00:00 2001 From: Oleksiy Kurochko Date: Thu, 3 May 2012 19:32:08 +0300 Subject: GUI: Implemented pressed state for buttons --- gui/ThemeEngine.cpp | 5 +++ gui/ThemeEngine.h | 6 ++- gui/dialog.cpp | 13 ++++++- gui/dialog.h | 7 ++++ gui/gui-manager.cpp | 13 ++++++- gui/launcher.cpp | 1 - gui/themes/default.inc | 11 ++++++ gui/themes/scummclassic.zip | Bin 93076 -> 93390 bytes gui/themes/scummclassic/THEMERC | 2 +- gui/themes/scummclassic/classic_gfx.stx | 13 +++++++ gui/themes/scummmodern.zip | Bin 1449403 -> 1449894 bytes gui/themes/scummmodern/THEMERC | 2 +- gui/themes/scummmodern/scummmodern_gfx.stx | 21 +++++++++++ gui/widget.cpp | 58 ++++++++++++++++++++++++++--- gui/widget.h | 18 ++++++++- 15 files changed, 155 insertions(+), 15 deletions(-) diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index fdd7750af9..be0a5db601 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -175,6 +175,7 @@ static const DrawDataInfo kDrawDataDefaults[] = { {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider}, {kDDButtonHover, "button_hover", false, kDDButtonIdle}, {kDDButtonDisabled, "button_disabled", true, kDDNone}, + {kDDButtonPressed, "button_pressed", false, kDDButtonIdle}, {kDDSliderFull, "slider_full", false, kDDNone}, {kDDSliderHover, "slider_hover", false, kDDNone}, @@ -877,6 +878,8 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W dd = kDDButtonHover; else if (state == kStateDisabled) dd = kDDButtonDisabled; + else if (state == kStatePressed) + dd = kDDButtonPressed; queueDD(dd, r, 0, hints & WIDGET_CLEARBG); queueDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); @@ -1125,6 +1128,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid break; case kStateEnabled: + case kStatePressed: colorId = kTextColorNormal; break; } @@ -1145,6 +1149,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid break; case kStateEnabled: + case kStatePressed: colorId = kTextColorAlternative; break; } diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 0495a85c88..acded085f5 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -35,7 +35,7 @@ #include "graphics/pixelformat.h" -#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.11" +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.12" class OSystem; @@ -81,6 +81,7 @@ enum DrawData { kDDButtonIdle, kDDButtonHover, kDDButtonDisabled, + kDDButtonPressed, kDDSliderFull, kDDSliderHover, @@ -178,7 +179,8 @@ public: enum State { kStateDisabled, ///< Indicates that the widget is disabled, that does NOT include that it is invisible kStateEnabled, ///< Indicates that the widget is enabled - kStateHighlight ///< Indicates that the widget is highlighted by the user + kStateHighlight, ///< Indicates that the widget is highlighted by the user + kStatePressed ///< Indicates that the widget is pressed, currently works for buttons }; typedef State WidgetStateInfo; diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 2201e83ca5..ffca15bbc8 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -42,7 +42,7 @@ namespace GUI { Dialog::Dialog(int x, int y, int w, int h) : GuiObject(x, y, w, h), - _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), + _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _tickleWidget(0), _visible(false), _backgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) { // Some dialogs like LauncherDialog use internally a fixed size, even though // their widgets rely on the layout to be initialized correctly by the theme. @@ -54,7 +54,7 @@ Dialog::Dialog(int x, int y, int w, int h) Dialog::Dialog(const Common::String &name) : GuiObject(name), - _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), + _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _tickleWidget(0), _visible(false), _backgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) { // It may happen that we have 3x scaler in launcher (960xY) and then 640x480 @@ -117,6 +117,12 @@ void Dialog::reflowLayout() { GuiObject::reflowLayout(); } +void Dialog::lostFocus() { + if (_tickleWidget) { + _tickleWidget->lostFocus(); + } +} + void Dialog::setFocusWidget(Widget *widget) { // The focus will change. Tell the old focused widget (if any) // that it lost the focus. @@ -308,6 +314,9 @@ void Dialog::handleTickle() { // Focused widget receives tickle notifications if (_focusedWidget && _focusedWidget->getFlags() & WIDGET_WANT_TICKLE) _focusedWidget->handleTickle(); + + if (_tickleWidget && _tickleWidget->getFlags() & WIDGET_WANT_TICKLE) + _tickleWidget->handleTickle(); } void Dialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { diff --git a/gui/dialog.h b/gui/dialog.h index f5a5f94a68..f923c1f5b8 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -52,6 +52,7 @@ protected: Widget *_mouseWidget; Widget *_focusedWidget; Widget *_dragWidget; + Widget *_tickleWidget; bool _visible; ThemeEngine::DialogBackground _backgroundType; @@ -71,7 +72,13 @@ public: void setFocusWidget(Widget *widget); Widget *getFocusWidget() { return _focusedWidget; } + void setTickleWidget(Widget *widget) { _tickleWidget = widget; } + void unSetTickleWidget() { _tickleWidget = NULL; } + Widget *getTickleWidget() { return _tickleWidget; } + virtual void reflowLayout(); + virtual void lostFocus(); + virtual void receivedFocus() {}; protected: virtual void open(); diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index ffecd928bc..abd781e1a3 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -381,7 +381,7 @@ void GuiManager::runLoop() { if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) { Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y); - if (wdg && wdg->getTooltip()) { + if (wdg && wdg->getTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) { Tooltip *tooltip = new Tooltip(); tooltip->setup(activeDialog, wdg, _lastMousePosition.x, _lastMousePosition.y); tooltip->runModal(); @@ -441,6 +441,11 @@ void GuiManager::restoreState() { } void GuiManager::openDialog(Dialog *dialog) { + dialog->receivedFocus(); + + if (!_dialogStack.empty()) + getTopDialog()->lostFocus(); + _dialogStack.push(dialog); if (_redrawStatus != kRedrawFull) _redrawStatus = kRedrawOpenDialog; @@ -458,7 +463,11 @@ void GuiManager::closeTopDialog() { return; // Remove the dialog from the stack - _dialogStack.pop(); + _dialogStack.pop()->lostFocus(); + + if (!_dialogStack.empty()) + getTopDialog()->receivedFocus(); + if (_redrawStatus != kRedrawFull) _redrawStatus = kRedrawCloseDialog; diff --git a/gui/launcher.cpp b/gui/launcher.cpp index a86a98f819..c8ed3126c4 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -663,7 +663,6 @@ LauncherDialog::LauncherDialog() _list->setEditable(false); _list->setNumberingMode(kListNumberingOff); - // Populate the list updateListing(); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 542f776dbd..5ee9b9202a 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -460,6 +460,17 @@ "bevel='2' " "/> " " " +" " +" " +" " +" " " " " + + + + + + + + + + + + = 0 && x < _w && y >= 0 && y < _h) + if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) { sendCommand(_cmd, 0); + startAnimatePressedState(); + } +} + +void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) { + setPressedState(); } void ButtonWidget::drawWidget() { @@ -324,6 +334,44 @@ ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32 return button; } +void ButtonWidget::setHighLighted(bool enable) { + (enable) ? setFlags(WIDGET_HILITED) : clearFlags(WIDGET_HILITED); + draw(); +} + +void ButtonWidget::handleTickle() { + if (_lastTime) { + uint32 curTime = g_system->getMillis(); + if (curTime - _lastTime > kPressedButtonTime) { + stopAnimatePressedState(); + } + } +} + +void ButtonWidget::setPressedState() { + wantTickle(true); + setFlags(WIDGET_PRESSED); + draw(); +} + +void ButtonWidget::stopAnimatePressedState() { + wantTickle(false); + _lastTime = 0; + clearFlags(WIDGET_PRESSED); + draw(); +} + +void ButtonWidget::startAnimatePressedState() { + _lastTime = g_system->getMillis(); +} + +void ButtonWidget::wantTickle(bool tickled) { + if (tickled) + ((GUI::Dialog *)_boss)->setTickleWidget(this); + else + ((GUI::Dialog *)_boss)->unSetTickleWidget(); +} + #pragma mark - PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey) diff --git a/gui/widget.h b/gui/widget.h index 789fc09231..6a6c67ced9 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -38,6 +38,7 @@ enum { WIDGET_INVISIBLE = 1 << 1, WIDGET_HILITED = 1 << 2, WIDGET_BORDER = 1 << 3, + WIDGET_PRESSED = 1 << 4, //WIDGET_INV_BORDER = 1 << 4, WIDGET_CLEARBG = 1 << 5, WIDGET_WANT_TICKLE = 1 << 7, @@ -73,6 +74,10 @@ enum { kCaretBlinkTime = 300 }; +enum { + kPressedButtonTime = 200 +}; + /* Widget */ class Widget : public GuiObject { friend class Dialog; @@ -189,11 +194,22 @@ public: void setLabel(const Common::String &label); void handleMouseUp(int x, int y, int button, int clickCount); + void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } - void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } + void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); } + void handleTickle(); + + void setHighLighted(bool enable); + void setPressedState(); + void startAnimatePressedState(); + void stopAnimatePressedState(); + void lostFocusWidget() { stopAnimatePressedState(); } protected: void drawWidget(); + void wantTickle(bool tickled); +private: + uint32 _lastTime; }; /* PicButtonWidget */ -- cgit v1.2.3 From 24a45beceb1d9228168fc0911b90da3bd45a923e Mon Sep 17 00:00:00 2001 From: Oleksiy Kurochko Date: Thu, 3 May 2012 19:32:34 +0300 Subject: GUI: Use pressed state in predictive dialog in keyboard mode. This adds more visual feedback to the user. --- gui/predictivedialog.cpp | 288 +++++++++++++++++++++++++++++------------------ gui/predictivedialog.h | 9 +- 2 files changed, 183 insertions(+), 114 deletions(-) diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp index 9cd18b81ba..b827d49416 100644 --- a/gui/predictivedialog.cpp +++ b/gui/predictivedialog.cpp @@ -69,31 +69,33 @@ enum { PredictiveDialog::PredictiveDialog() : Dialog("Predictive") { new StaticTextWidget(this, "Predictive.Headline", "Enter Text"); - new ButtonWidget(this, "Predictive.Cancel" , _("Cancel"), 0, kCancelCmd); - new ButtonWidget(this, "Predictive.OK" , _("Ok") , 0, kOkCmd); - new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd); - new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd); - new ButtonWidget(this, "Predictive.Button3", "3 def" , 0, kBut3Cmd); - new ButtonWidget(this, "Predictive.Button4", "4 ghi" , 0, kBut4Cmd); - new ButtonWidget(this, "Predictive.Button5", "5 jkl" , 0, kBut5Cmd); - new ButtonWidget(this, "Predictive.Button6", "6 mno" , 0, kBut6Cmd); - new ButtonWidget(this, "Predictive.Button7", "7 pqrs" , 0, kBut7Cmd); - new ButtonWidget(this, "Predictive.Button8", "8 tuv" , 0, kBut8Cmd); - new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd); - new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd); - // I18N: You must leave "#" as is, only word 'next' is translatable - new ButtonWidget(this, "Predictive.Next" , _("# next"), 0, kNextCmd); - _addBtn = new ButtonWidget(this, "Predictive.Add", _("add"), 0, kAddCmd); - _addBtn->setEnabled(false); - -#ifndef DISABLE_FANCY_THEMES - _delbtn = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd); - ((PicButtonWidget *)_delbtn)->useThemeTransparency(true); - ((PicButtonWidget *)_delbtn)->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelbtn)); -#endif - _delbtn = new ButtonWidget(this, "Predictive.Delete" , _("<"), 0, kDelCmd); - // I18N: Pre means 'Predictive', leave '*' as is - _modebutton = new ButtonWidget(this, "Predictive.Pre", _("* Pre"), 0, kModeCmd); + _btns = (ButtonWidget **)calloc(1, sizeof(ButtonWidget *) * 16); + + _btns[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd); + _btns[kOkAct] = new ButtonWidget(this, "Predictive.OK", _("Ok") , 0, kOkCmd); + _btns[kBtn1Act] = new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd); + _btns[kBtn2Act] = new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd); + _btns[kBtn3Act] = new ButtonWidget(this, "Predictive.Button3", "3 def" , 0, kBut3Cmd); + _btns[kBtn4Act] = new ButtonWidget(this, "Predictive.Button4", "4 ghi" , 0, kBut4Cmd); + _btns[kBtn5Act] = new ButtonWidget(this, "Predictive.Button5", "5 jkl" , 0, kBut5Cmd); + _btns[kBtn6Act] = new ButtonWidget(this, "Predictive.Button6", "6 mno" , 0, kBut6Cmd); + _btns[kBtn7Act] = new ButtonWidget(this, "Predictive.Button7", "7 pqrs" , 0, kBut7Cmd); + _btns[kBtn8Act] = new ButtonWidget(this, "Predictive.Button8", "8 tuv" , 0, kBut8Cmd); + _btns[kBtn9Act] = new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd); + _btns[kBtn0Act] = new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd); + // I18N: You must leave "#" as is, only word 'next' is translatable + _btns[kNextAct] = new ButtonWidget(this, "Predictive.Next", _("# next") , 0, kNextCmd); + _btns[kAddAct] = new ButtonWidget(this, "Predictive.Add", _("add") , 0, kAddCmd); + _btns[kAddAct]->setEnabled(false); + + #ifndef DISABLE_FANCY_THEMES + _btns[kDelAct] = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd); + ((PicButtonWidget *)_btns[kDelAct])->useThemeTransparency(true); + ((PicButtonWidget *)_btns[kDelAct])->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelbtn)); + #endif + _btns[kDelAct] = new ButtonWidget(this, "Predictive.Delete" , _("<") , 0, kDelCmd); + // I18N: Pre means 'Predictive', leave '*' as is + _btns[kModeAct] = new ButtonWidget(this, "Predictive.Pre", _("* Pre"), 0, kModeCmd); _edittext = new EditTextWidget(this, "Predictive.Word", _search, 0, 0, 0); _userDictHasChanged = false; @@ -164,6 +166,8 @@ PredictiveDialog::~PredictiveDialog() { free(_userDict.dictLine); free(_predictiveDict.dictLine); free(_unitedDict.dictLine); + + free(_btns); } void PredictiveDialog::saveUserDictToFile() { @@ -182,11 +186,23 @@ void PredictiveDialog::saveUserDictToFile() { } } +void PredictiveDialog::handleKeyUp(Common::KeyState state) { + if (_currBtn != kNoAct && !_needRefresh) { + _btns[_currBtn]->startAnimatePressedState(); + processBtnActive(_currBtn); + } +} + void PredictiveDialog::handleKeyDown(Common::KeyState state) { - ButtonId act = kNoAct; + _currBtn = kNoAct; + _needRefresh = false; if (getFocusWidget() == _edittext) { - setFocusWidget(_addBtn); + setFocusWidget(_btns[kAddAct]); + } + + if (_lastbutton == kNoAct) { + _lastbutton = kBtn5Act; } switch (state.keycode) { @@ -197,96 +213,126 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) { case Common::KEYCODE_LEFT: _navigationwithkeys = true; if (_lastbutton == kBtn1Act || _lastbutton == kBtn4Act || _lastbutton == kBtn7Act) - act = ButtonId(_lastbutton + 2); + _currBtn = ButtonId(_lastbutton + 2); + else if (_lastbutton == kDelAct) + _currBtn = kBtn1Act; + else if (_lastbutton == kModeAct) + _currBtn = kNextAct; else if (_lastbutton == kNextAct) - act = kBtn0Act; - else if (_lastbutton == kDelAct) - act = kDelAct; + _currBtn = kBtn0Act; + else if (_lastbutton == kAddAct) + _currBtn = kOkAct; else if (_lastbutton == kCancelAct) - act = kOkAct; - else if (_lastbutton == kModeAct) - act = kAddAct; + _currBtn = kAddAct; else - act = ButtonId(_lastbutton - 1); - _lastbutton = act; - //needRefresh = true; + _currBtn = ButtonId(_lastbutton - 1); + + + if (_mode != kModeAbc && _lastbutton == kCancelAct) + _currBtn = kOkAct; + + _needRefresh = true; break; case Common::KEYCODE_RIGHT: _navigationwithkeys = true; - if (_lastbutton == kBtn3Act || _lastbutton == kBtn6Act || _lastbutton == kBtn9Act) - act = ButtonId(_lastbutton - 2); + if (_lastbutton == kBtn3Act || _lastbutton == kBtn6Act || _lastbutton == kBtn9Act || _lastbutton == kOkAct) + _currBtn = ButtonId(_lastbutton - 2); + else if (_lastbutton == kDelAct) + _currBtn = kBtn3Act; + else if (_lastbutton == kBtn0Act) + _currBtn = kNextAct; + else if (_lastbutton == kNextAct) + _currBtn = kModeAct; else if (_lastbutton == kAddAct) - act = kModeAct; - else if (_lastbutton == kDelAct) - act = kDelAct; + _currBtn = kCancelAct; else if (_lastbutton == kOkAct) - act = kCancelAct; - else if (_lastbutton == kBtn0Act) - act = kNextAct; + _currBtn = kAddAct; else - act = ButtonId(_lastbutton + 1); - _lastbutton = act; - //needRefresh = true; + _currBtn = ButtonId(_lastbutton + 1); + + if (_mode != kModeAbc && _lastbutton == kOkAct) + _currBtn = kCancelAct; + _needRefresh = true; break; case Common::KEYCODE_UP: _navigationwithkeys = true; if (_lastbutton <= kBtn3Act) - act = kDelAct; - else if (_lastbutton == kNextAct || _lastbutton == kAddAct) - act = ButtonId(_lastbutton - 2); + _currBtn = kDelAct; else if (_lastbutton == kDelAct) - act = kOkAct; - else if (_lastbutton == kModeAct) - act = kBtn9Act; + _currBtn = kOkAct; + else if (_lastbutton == kModeAct) + _currBtn = kBtn7Act; else if (_lastbutton == kBtn0Act) - act = kBtn7Act; + _currBtn = kBtn8Act; + else if (_lastbutton == kNextAct) + _currBtn = kBtn9Act; + else if (_lastbutton == kAddAct) + _currBtn = kModeAct; + else if (_lastbutton == kCancelAct) + _currBtn = kBtn0Act; + else if (_lastbutton == kOkAct) + _currBtn = kNextAct; else - act = ButtonId(_lastbutton - 3); - _lastbutton = act; - //needRefresh = true; + _currBtn = ButtonId(_lastbutton - 3); + _needRefresh = true; break; case Common::KEYCODE_DOWN: _navigationwithkeys = true; - if (_lastbutton == kBtn7Act) - act = kBtn0Act; - else if (_lastbutton == kBtn8Act || _lastbutton == kBtn9Act) - act = ButtonId(_lastbutton + 2); - else if (_lastbutton == kDelAct) - act = kBtn1Act; - else if (_lastbutton == kCancelAct || _lastbutton == kOkAct) - act = kDelAct; - else if (_lastbutton == kModeAct || _lastbutton == kBtn0Act) - act = ButtonId(_lastbutton - 2); + if (_lastbutton == kDelAct) + _currBtn = kBtn3Act; + else if (_lastbutton == kBtn7Act) + _currBtn = kModeAct; + else if (_lastbutton == kBtn8Act) + _currBtn = kBtn0Act; + else if (_lastbutton == kBtn9Act) + _currBtn = kNextAct; + else if (_lastbutton == kModeAct) + _currBtn = kAddAct; + else if (_lastbutton == kBtn0Act) + _currBtn = kCancelAct; + else if (_lastbutton == kNextAct) + _currBtn = kOkAct; + else if (_lastbutton == kAddAct || _lastbutton == kCancelAct || _lastbutton == kOkAct) + _currBtn = kDelAct; else - act = ButtonId(_lastbutton + 3); - _lastbutton = act; - //needRefresh = true; + _currBtn = ButtonId(_lastbutton + 3); + + if (_mode != kModeAbc && _lastbutton == kModeAct) + _currBtn = kCancelAct; + + _needRefresh = true; break; case Common::KEYCODE_KP_ENTER: + case Common::KEYCODE_RETURN: + if (state.flags & Common::KBD_CTRL) { + _currBtn = kOkAct; + break; + } if (_navigationwithkeys) { // when the user has utilized arrow key navigation, - // interpret enter as 'click' on the act button - act = _lastbutton; + // interpret enter as 'click' on the _currBtn button + _currBtn = _lastbutton; + _needRefresh = false; } else { // else it is a shortcut for 'Ok' - act = kOkAct; + _currBtn = kOkAct; } break; case Common::KEYCODE_KP_PLUS: - act = kAddAct; + _currBtn = kAddAct; break; case Common::KEYCODE_BACKSPACE: case Common::KEYCODE_KP_MINUS: - act = kDelAct; + _currBtn = kDelAct; break; case Common::KEYCODE_KP_DIVIDE: - act = kNextAct; + _currBtn = kNextAct; break; case Common::KEYCODE_KP_MULTIPLY: - act = kModeAct; + _currBtn = kModeAct; break; case Common::KEYCODE_KP0: - act = kBtn0Act; + _currBtn = kBtn0Act; break; case Common::KEYCODE_KP1: case Common::KEYCODE_KP2: @@ -297,78 +343,93 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) { case Common::KEYCODE_KP7: case Common::KEYCODE_KP8: case Common::KEYCODE_KP9: - act = ButtonId(state.keycode - Common::KEYCODE_KP1); + _currBtn = ButtonId(state.keycode - Common::KEYCODE_KP1); break; default: Dialog::handleKeyDown(state); } - if (act != kNoAct) { - processBtnActive(act); + if (_lastbutton != _currBtn) + _btns[_lastbutton]->stopAnimatePressedState(); + + if (_currBtn != kNoAct && !_needRefresh) + _btns[_currBtn]->setPressedState(); + else + updateHighLightedButton(_currBtn); +} + +void PredictiveDialog::updateHighLightedButton(ButtonId act) { + if (_currBtn != kNoAct) { + _btns[_lastbutton]->setHighLighted(false); + _lastbutton = act; + _btns[_lastbutton]->setHighLighted(true); } } void PredictiveDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { - ButtonId act = kNoAct; + _currBtn = kNoAct; _navigationwithkeys = false; + if (_lastbutton != kNoAct) + _btns[_lastbutton]->setHighLighted(false); + switch (cmd) { case kDelCmd: - act = kDelAct; + _currBtn = kDelAct; break; case kNextCmd: - act = kNextAct; + _currBtn = kNextAct; break; case kAddCmd: - act = kAddAct; + _currBtn = kAddAct; break; case kModeCmd: - act = kModeAct; + _currBtn = kModeAct; break; case kBut1Cmd: - act = kBtn1Act; + _currBtn = kBtn1Act; break; case kBut2Cmd: - act = kBtn2Act; + _currBtn = kBtn2Act; break; case kBut3Cmd: - act = kBtn3Act; + _currBtn = kBtn3Act; break; case kBut4Cmd: - act = kBtn4Act; + _currBtn = kBtn4Act; break; case kBut5Cmd: - act = kBtn5Act; + _currBtn = kBtn5Act; break; case kBut6Cmd: - act = kBtn6Act; + _currBtn = kBtn6Act; break; case kBut7Cmd: - act = kBtn7Act; + _currBtn = kBtn7Act; break; case kBut8Cmd: - act = kBtn8Act; + _currBtn = kBtn8Act; break; case kBut9Cmd: - act = kBtn9Act; + _currBtn = kBtn9Act; break; case kBut0Cmd: - act = kBtn0Act; + _currBtn = kBtn0Act; break; case kCancelCmd: saveUserDictToFile(); close(); return; case kOkCmd: - act = kOkAct; + _currBtn = kOkAct; break; default: Dialog::handleCommand(sender, cmd, data); } - if (act != kNoAct) { - processBtnActive(act); + if (_currBtn != kNoAct) { + processBtnActive(_currBtn); } } @@ -500,18 +561,18 @@ void PredictiveDialog::processBtnActive(ButtonId button) { bringWordtoTop(_unitedDict.dictActLine, _wordNumber); } else if (button == kModeAct) { // Mode _mode++; - _addBtn->setEnabled(false); + _btns[kAddAct]->setEnabled(false); if (_mode > kModeAbc) { _mode = kModePre; // I18N: Pre means 'Predictive', leave '*' as is - _modebutton->setLabel("* Pre"); + _btns[kModeAct]->setLabel("* Pre"); } else if (_mode == kModeNum) { // I18N: 'Num' means Numbers - _modebutton->setLabel("* Num"); + _btns[kModeAct]->setLabel("* Num"); } else { // I18N: 'Abc' means Latin alphabet input - _modebutton->setLabel("* Abc"); - _addBtn->setEnabled(true); + _btns[kModeAct]->setLabel("* Abc"); + _btns[kAddAct]->setEnabled(true); } // truncate current input at mode change @@ -532,18 +593,23 @@ void PredictiveDialog::processBtnActive(ButtonId button) { if (button == kOkAct) close(); + + if (button == kCancelAct) { + saveUserDictToFile(); + close(); + } } void PredictiveDialog::handleTickle() { - // TODO/FIXME: This code does not seem to make any sense. It is only - // triggered when _lastTime is zero and sets _lastTime to zero again - // under some condition. This should really be a nop. Probably this - // code intends to check "_lastTime" instead of "!_lastTime". - if (!_lastTime) { + if (_lastTime) { if ((_curTime - _lastTime) > kRepeatDelay) { _lastTime = 0; } } + + if (getTickleWidget()) { + getTickleWidget()->handleTickle(); + } } void PredictiveDialog::mergeDicts() { @@ -664,7 +730,7 @@ bool PredictiveDialog::matchWord() { // The entries in the dictionary consist of a code, a space, and then // a space-separated list of words matching this code. - // To exactly match a code, we therefore match the code plus the trailing + // To ex_currBtnly match a code, we therefore match the code plus the trailing // space in the dictionary. Common::String code = _currentCode + " "; diff --git a/gui/predictivedialog.h b/gui/predictivedialog.h index 32de36d5f2..0e3d2967c0 100644 --- a/gui/predictivedialog.h +++ b/gui/predictivedialog.h @@ -68,6 +68,7 @@ public: ~PredictiveDialog(); virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); + virtual void handleKeyUp(Common::KeyState state); virtual void handleKeyDown(Common::KeyState state); virtual void handleTickle(); @@ -98,6 +99,8 @@ private: void saveUserDictToFile(); void mergeDicts(); + + void updateHighLightedButton(ButtonId active); private: Dict _unitedDict; Dict _predictiveDict; @@ -118,6 +121,7 @@ private: uint32 _curTime, _lastTime; ButtonId _lastPressBtn; + ButtonId _currBtn; char _temp[kMaxWordLen + 1]; int _repeatcount[kMaxWordLen]; @@ -128,11 +132,10 @@ private: Common::String _search; bool _navigationwithkeys; + bool _needRefresh; private: EditTextWidget *_edittext; - ButtonWidget *_modebutton; - ButtonWidget *_delbtn; - ButtonWidget *_addBtn; + ButtonWidget **_btns; }; } // namespace GUI -- cgit v1.2.3 From 18ae64ed5a7992b09b55f77c1ee0f973fac48235 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 3 May 2012 18:37:42 +0200 Subject: CONFIGURE: Enable dreamweb and composer by default. --- engines/configure.engines | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engines/configure.engines b/engines/configure.engines index 6e8db01e66..8eaee730cc 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 -- cgit v1.2.3 From 0c312f87531ae6ed8b3ee83a6ac9b452b09f3668 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 3 May 2012 18:43:09 +0200 Subject: GUI: Remove unecessary ";". --- gui/dialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/dialog.h b/gui/dialog.h index f923c1f5b8..1773c6633e 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -78,7 +78,7 @@ public: virtual void reflowLayout(); virtual void lostFocus(); - virtual void receivedFocus() {}; + virtual void receivedFocus() {} protected: virtual void open(); -- cgit v1.2.3 From e72f51129bfd11d0c926a2e21015a57740980928 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 3 May 2012 18:44:02 +0200 Subject: DREAMWEB: Tag all detection entries as testing instead of unstable. --- engines/dreamweb/detection_tables.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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) }, }, -- cgit v1.2.3 From 3b212fdb51c4933bbc7eeb827f514cd1e120b3c5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 3 May 2012 23:25:00 +0200 Subject: GRAPHICS: Remove unused function ftFloor26_6 in ttf.cpp. --- graphics/fonts/ttf.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp index 7f5c616710..96241e923c 100644 --- a/graphics/fonts/ttf.cpp +++ b/graphics/fonts/ttf.cpp @@ -43,10 +43,6 @@ namespace Graphics { namespace { -inline int ftFloor26_6(FT_Pos x) { - return x / 64; -} - inline int ftCeil26_6(FT_Pos x) { return (x + 63) / 64; } -- cgit v1.2.3 From b93b17e7f4af0ad28ad0d2bde36302cdbd3aeeff Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 3 May 2012 12:03:27 -0400 Subject: TINSEL: Capitalize 'demo' --- engines/tinsel/detection_tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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}, -- cgit v1.2.3 From 76dfbbede41dd43dad3fa114f409654807c239a3 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 3 May 2012 12:18:10 -0400 Subject: TINSEL: Add basic PSX SEQ playback support Instrument bank support is not implemented yet --- engines/tinsel/music.cpp | 94 +++++++++++++++++++++++++++++++++++++++++------ engines/tinsel/music.h | 6 ++- engines/tinsel/tinlib.cpp | 2 +- 3 files changed, 89 insertions(+), 13 deletions(-) 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 (.VB and .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; -- cgit v1.2.3 From 5a1f458bd08313e3ae278a9933ef9391ec5f122c Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 4 May 2012 23:33:44 +0200 Subject: DREAMWEB: Add character map for the Italian version. It is the same as the French version. This fixes bug #3523338. --- engines/dreamweb/dreamweb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index 0a35bcdecc..299dd74b53 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -522,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; -- cgit v1.2.3 From e5808c740a62cb87a1ceeef7873af3b21e912c73 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 4 May 2012 23:18:28 -0400 Subject: GRAPHICS: Fix 32-bit DirectBits images --- graphics/decoders/pict.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/graphics/decoders/pict.cpp b/graphics/decoders/pict.cpp index 9963873b54..bdb733a87d 100644 --- a/graphics/decoders/pict.cpp +++ b/graphics/decoders/pict.cpp @@ -361,14 +361,14 @@ void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool hasPal memcpy(_outputSurface->pixels, buffer, _outputSurface->w * _outputSurface->h); break; case 2: - // Convert from 16-bit to whatever surface we need + // We have a 16-bit surface _outputSurface->create(width, height, PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); for (uint16 y = 0; y < _outputSurface->h; y++) for (uint16 x = 0; x < _outputSurface->w; x++) WRITE_UINT16(_outputSurface->getBasePtr(x, y), READ_UINT16(buffer + (y * _outputSurface->w + x) * 2)); break; case 3: - // Convert from 24-bit (planar!) to whatever surface we need + // We have a planar 24-bit surface _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); for (uint16 y = 0; y < _outputSurface->h; y++) { for (uint16 x = 0; x < _outputSurface->w; x++) { @@ -380,15 +380,18 @@ void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool hasPal } break; case 4: - // Convert from 32-bit (planar!) to whatever surface we need + // We have a planar 32-bit surface + // Note that we ignore the alpha channel since it seems to not be correct + // Mac OS X does not ignore it, but then displays it incorrectly. Photoshop + // does ignore it and displays it correctly. _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); for (uint16 y = 0; y < _outputSurface->h; y++) { for (uint16 x = 0; x < _outputSurface->w; x++) { - byte r = *(buffer + y * _outputSurface->w * 4 + x); - byte g = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w + x); - byte b = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 2 + x); - byte a = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 3 + x); - *((uint32 *)_outputSurface->getBasePtr(x, y)) = _outputSurface->format.ARGBToColor(r, g, b, a); + byte a = 0xFF; + byte r = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w + x); + byte g = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 2 + x); + byte b = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 3 + x); + *((uint32 *)_outputSurface->getBasePtr(x, y)) = _outputSurface->format.ARGBToColor(a, r, g, b); } } break; -- cgit v1.2.3