From 2798c65d756e82db8eb4a58ca3db526215557333 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 28 Aug 2011 14:06:57 +0300 Subject: SCI: Fixed bug #3297883 - "SCI: LB1 (Amiga) - Intro stuck" --- engines/sci/sound/midiparser_sci.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index f48a68dc66..ad7ba7ca36 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -480,11 +480,18 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { info.basic.param2 = 0; if (info.channel() == 0xF) {// SCI special case if (info.basic.param1 != kSetSignalLoop) { - // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately - // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to - // get immediately removed, so we currently filter it. - // Sierra SCI ignores them as well at that time - if ((_position._play_tick) || (info.delta)) { + // At least in kq5/french&mac the first scene in the intro has + // a song that sets signal to 4 immediately on tick 0. Signal + // isn't set at that point by sierra sci and it would cause the + // castle daventry text to get immediately removed, so we + // currently filter it. Sierra SCI ignores them as well at that + // time. However, this filtering should only be performed for + // SCI1 and newer games. Signalling is done differently in SCI0 + // though, so ignoring these signals in SCI0 games will result + // in glitches (e.g. the intro of LB1 Amiga gets stuck - bug + // #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp. + if (_soundVersion <= SCI_VERSION_0_LATE || + _position._play_tick || info.delta) { _signalSet = true; _signalToSet = info.basic.param1; } -- cgit v1.2.3 From 09def52554212871c6b68c60fb5f93b1c96b1002 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 3 Sep 2011 10:24:23 +0200 Subject: SCI: Fix QFG3 run/walk/sleep menu on touch devices The analysis and fix are from m_kiewitz. --- engines/sci/graphics/cursor.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index ec49a38814..18ff1fd0b9 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -229,6 +229,7 @@ static const SciCursorSetPositionWorkarounds setPositionWorkarounds[] = { { GID_ISLANDBRAIN, 84, 109, 46, 76, 174, 243 }, // island of dr. brain / game menu { GID_LSL5, 23, 171, 0, 0, 26, 320 }, // larry 5 / skip forward helper { GID_QFG1VGA, 64, 174, 40, 37, 74, 284 }, // Quest For Glory 1 VGA / run/walk/sleep sub-menu + { GID_QFG3, 70, 170, 40, 61, 81, 258 }, // Quest For Glory 3 / run/walk/sleep sub-menu { (SciGameId)0, -1, -1, -1, -1, -1, -1 } }; -- cgit v1.2.3 From 41cc1932d2cc19e6179f54d1b149a245420dba7a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 3 Sep 2011 14:50:58 +0300 Subject: SCI32: Added an initial skeleton structure for the SCI2 text drawing code This includes kCreateTextBitmap, and moves all of the text drawing code into the new GfxText32 class --- engines/sci/engine/kgraphics.cpp | 18 ++- engines/sci/graphics/frameout.cpp | 86 +------------- engines/sci/graphics/text32.cpp | 238 ++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/text32.h | 71 ++++++++++++ engines/sci/module.mk | 1 + engines/sci/sci.cpp | 4 + engines/sci/sci.h | 2 + 7 files changed, 335 insertions(+), 85 deletions(-) create mode 100644 engines/sci/graphics/text32.cpp create mode 100644 engines/sci/graphics/text32.h (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 36de767464..556e5249b6 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -49,6 +49,7 @@ #include "sci/graphics/text16.h" #include "sci/graphics/view.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/text32.h" #include "sci/graphics/frameout.h" #include "sci/video/robot_decoder.h" #endif @@ -1380,15 +1381,19 @@ reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { } reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { - // TODO: argument 0 is usually 0, and arguments 1 and 2 are usually 1 switch (argv[0].toUint16()) { case 0: { if (argc != 4) { warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc); return NULL_REG; } - //reg_t object = argv[3]; - //Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); + reg_t object = argv[3]; + Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); + debugC(kDebugLevelStrings, "kCreateTextBitmap case 0 (%04x:%04x, %04x:%04x, %04x:%04x)", + PRINT_REG(argv[1]), PRINT_REG(argv[2]), PRINT_REG(argv[3])); + debugC(kDebugLevelStrings, "%s", text.c_str()); + // TODO: arguments 1 and 2 + g_sci->_gfxText32->createTextBitmap(object); break; } case 1: { @@ -1396,8 +1401,11 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { warning("kCreateTextBitmap(0): expected 2 arguments, got %i", argc); return NULL_REG; } - //reg_t object = argv[1]; - //Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); + reg_t object = argv[1]; + Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); + debugC(kDebugLevelStrings, "kCreateTextBitmap case 1 (%04x:%04x)", PRINT_REG(argv[1])); + debugC(kDebugLevelStrings, "%s", text.c_str()); + g_sci->_gfxText32->createTextBitmap(object); break; } default: diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 11948d5d38..5499a2d192 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -43,6 +43,7 @@ #include "sci/graphics/paint32.h" #include "sci/graphics/palette.h" #include "sci/graphics/picture.h" +#include "sci/graphics/text32.h" #include "sci/graphics/frameout.h" #include "sci/video/robot_decoder.h" @@ -316,44 +317,6 @@ void GfxFrameout::sortPlanes() { Common::sort(_planes.begin(), _planes.end(), planeSortHelper); } -static int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font) { - uint16 curChar = 0; - int16 maxChars = 0, curCharCount = 0; - uint16 width = 0; - - while (width <= maxWidth) { - curChar = (*(const byte *)text++); - - switch (curChar) { - // We need to add 0xD, 0xA and 0xD 0xA to curCharCount and then exit - // which means, we split text like - // 'Mature, experienced software analyst available.' 0xD 0xA - // 'Bug installation a proven speciality. "No version too clean."' (normal game text, this is from lsl2) - // and 0xA '-------' 0xA (which is the official sierra subtitle separator) - // Sierra did it the same way. - case 0xD: - // Check, if 0xA is following, if so include it as well - if ((*(const unsigned char *)text) == 0xA) - curCharCount++; - // it's meant to pass through here - case 0xA: - curCharCount++; - // and it's also meant to pass through here - case 0: - return curCharCount; - case ' ': - maxChars = curCharCount; // return count up to (but not including) breaking space - break; - } - if (width + font->getCharWidth(curChar) > maxWidth) - break; - width += font->getCharWidth(curChar); - curCharCount++; - } - - return maxChars; -} - void GfxFrameout::kernelFrameout() { if (g_sci->_robotDecoder->isVideoLoaded()) { bool skipVideo = false; @@ -578,62 +541,25 @@ void GfxFrameout::kernelFrameout() { } } else { // Most likely a text entry - // This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap - // TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap) if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) { - reg_t stringObject = readSelector(_segMan, itemEntry->object, SELECTOR(text)); - - // The object in the text selector of the item can be either a raw string - // or a Str object. In the latter case, we need to access the object's data - // selector to get the raw string. - if (_segMan->isHeapObject(stringObject)) - stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); - - Common::String text = _segMan->getString(stringObject); - GfxFont *font = _cache->getFont(readSelectorValue(_segMan, itemEntry->object, SELECTOR(font))); - bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed)); - uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore)); - - itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight); - itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth); - - uint16 startX = itemEntry->x + it->planeRect.left; - uint16 curY = itemEntry->y + it->planeRect.top; - const char *txt = text.c_str(); + TextEntry *textEntry = g_sci->_gfxText32->getTextEntry(itemEntry->object); + uint16 startX = ((textEntry->x * _screen->getWidth()) / scriptsRunningWidth) + it->planeRect.left; + uint16 startY = ((textEntry->y * _screen->getHeight()) / scriptsRunningHeight) + it->planeRect.top; // HACK. The plane sometimes doesn't contain the correct width. This // hack breaks the dialog options when speaking with Grace, but it's // the best we got up to now. This happens because of the unimplemented // kTextWidth function in SCI32. // TODO: Remove this once kTextWidth has been implemented. uint16 w = it->planeRect.width() >= 20 ? it->planeRect.width() : _screen->getWidth() - 10; - int16 charCount; // Upscale the coordinates/width if the fonts are already upscaled if (_screen->fontIsUpscaled()) { startX = startX * _screen->getDisplayWidth() / _screen->getWidth(); - curY = curY * _screen->getDisplayHeight() / _screen->getHeight(); + startY = startY * _screen->getDisplayHeight() / _screen->getHeight(); w = w * _screen->getDisplayWidth() / _screen->getWidth(); } - while (*txt) { - charCount = GetLongest(txt, w, font); - if (charCount == 0) - break; - - uint16 curX = startX; - - for (int i = 0; i < charCount; i++) { - unsigned char curChar = txt[i]; - font->draw(curChar, curY, curX, foreColor, dimmed); - curX += font->getCharWidth(curChar); - } - - curY += font->getHeight(); - txt += charCount; - while (*txt == ' ') - txt++; // skip over breaking spaces - } - + g_sci->_gfxText32->drawTextBitmap(itemEntry->object, startX, startY, w); } } } diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp new file mode 100644 index 0000000000..21372f1502 --- /dev/null +++ b/engines/sci/graphics/text32.cpp @@ -0,0 +1,238 @@ +/* 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. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/sci/graphics/text16.cpp $ + * $Id: text16.cpp 55178 2011-01-08 23:16:44Z thebluegr $ + * + */ + +#include "common/util.h" +#include "common/stack.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/engine/kernel.h" +#include "sci/engine/selector.h" +#include "sci/engine/state.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/font.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/text32.h" + +namespace Sci { + +GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) + : _segMan(segMan), _cache(fonts), _screen(screen) { +} + +GfxText32::~GfxText32() { + purgeCache(); +} + +void GfxText32::purgeCache() { + for (TextCache::iterator cacheIterator = _textCache.begin(); cacheIterator != _textCache.end(); cacheIterator++) { + delete[] cacheIterator->_value->surface; + delete cacheIterator->_value; + cacheIterator->_value = 0; + } + + _textCache.clear(); +} + +void GfxText32::createTextBitmap(reg_t textObject) { + if (_textCache.size() >= MAX_CACHED_TEXTS) + purgeCache(); + + uint32 textId = (textObject.segment << 16) | textObject.offset; + + if (_textCache.contains(textId)) { + // Delete the old entry + TextEntry *oldEntry = _textCache[textId]; + delete[] oldEntry->surface; + delete oldEntry; + _textCache.erase(textId); + } + + _textCache[textId] = createTextEntry(textObject); +} + +// TODO: Finish this! +void GfxText32::drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 w) { + uint32 textId = (textObject.segment << 16) | textObject.offset; + + if (!_textCache.contains(textId)) + createTextBitmap(textObject); + + TextEntry *entry = _textCache[textId]; + + // This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap + // TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap) + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); + bool dimmed = readSelectorValue(_segMan,textObject, SELECTOR(dimmed)); + uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); + + const char *txt = entry->text.c_str(); + int16 charCount; + + while (*txt) { + charCount = GetLongest(txt, w, font); + if (charCount == 0) + break; + + uint16 curX = textX; + + for (int i = 0; i < charCount; i++) { + unsigned char curChar = txt[i]; + font->draw(curChar, textY, curX, foreColor, dimmed); + curX += font->getCharWidth(curChar); + } + + textY += font->getHeight(); + txt += charCount; + while (*txt == ' ') + txt++; // skip over breaking spaces + } + + // TODO: The "SCI2" way of font drawing. Currently buggy + /* + for (int x = textX; x < entry->width; x++) { + for (int y = textY; y < entry->height; y++) { + byte pixel = entry->surface[y * entry->width + x]; + if (pixel) + _screen->putPixel(x, y, 1, pixel, 0, 0); + } + } + */ +} + +TextEntry *GfxText32::getTextEntry(reg_t textObject) { + uint32 textId = (textObject.segment << 16) | textObject.offset; + + if (!_textCache.contains(textId)) + createTextBitmap(textObject); + + return _textCache[textId]; +} + +// TODO: Finish this! Currently buggy. +TextEntry *GfxText32::createTextEntry(reg_t textObject) { + reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); + + // The object in the text selector of the item can be either a raw string + // or a Str object. In the latter case, we need to access the object's data + // selector to get the raw string. + if (_segMan->isHeapObject(stringObject)) + stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); + + const char *text = _segMan->getString(stringObject).c_str(); + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); + bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed)); + uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); + uint16 x = readSelectorValue(_segMan, textObject, SELECTOR(x)); + uint16 y = readSelectorValue(_segMan, textObject, SELECTOR(y)); + + // Now get the bounding box from the associated plane + reg_t planeObject = readSelector(_segMan, textObject, SELECTOR(plane)); + Common::Rect planeRect; + if (!planeObject.isNull()) { + planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top)); + planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left)); + planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)) + 1; + planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)) + 1; + } else { + planeRect.top = 0; + planeRect.left = 0; + planeRect.bottom = _screen->getHeight(); + planeRect.right = _screen->getWidth(); + } + + TextEntry *newEntry = new TextEntry(); + newEntry->object = stringObject; + newEntry->x = x; + newEntry->y = y; + newEntry->width = planeRect.width(); + newEntry->height = planeRect.height(); + newEntry->surface = new byte[newEntry->width * newEntry->height]; + memset(newEntry->surface, 0, newEntry->width * newEntry->height); + newEntry->text = _segMan->getString(stringObject); + + int16 maxTextWidth, charCount; + uint16 curX = 0, curY = 0; + + maxTextWidth = 0; + while (*text) { + charCount = GetLongest(text, planeRect.width(), font); + if (charCount == 0) + break; + + for (int i = 0; i < charCount; i++) { + unsigned char curChar = text[i]; + font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, newEntry->surface, newEntry->width, newEntry->height); + curX += font->getCharWidth(curChar); + } + + curY += font->getHeight(); + text += charCount; + while (*text == ' ') + text++; // skip over breaking spaces + } + + return newEntry; +} + +int16 GfxText32::GetLongest(const char *text, int16 maxWidth, GfxFont *font) { + uint16 curChar = 0; + int16 maxChars = 0, curCharCount = 0; + uint16 width = 0; + + while (width <= maxWidth) { + curChar = (*(const byte *)text++); + + switch (curChar) { + // We need to add 0xD, 0xA and 0xD 0xA to curCharCount and then exit + // which means, we split text like + // 'Mature, experienced software analyst available.' 0xD 0xA + // 'Bug installation a proven speciality. "No version too clean."' (normal game text, this is from lsl2) + // and 0xA '-------' 0xA (which is the official sierra subtitle separator) + // Sierra did it the same way. + case 0xD: + // Check, if 0xA is following, if so include it as well + if ((*(const unsigned char *)text) == 0xA) + curCharCount++; + // it's meant to pass through here + case 0xA: + curCharCount++; + // and it's also meant to pass through here + case 0: + return curCharCount; + case ' ': + maxChars = curCharCount; // return count up to (but not including) breaking space + break; + } + if (width + font->getCharWidth(curChar) > maxWidth) + break; + width += font->getCharWidth(curChar); + curCharCount++; + } + + return maxChars; +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h new file mode 100644 index 0000000000..39fe710a86 --- /dev/null +++ b/engines/sci/graphics/text32.h @@ -0,0 +1,71 @@ +/* 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. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/sci/graphics/text16.h $ + * $Id: text16.h 55178 2011-01-08 23:16:44Z thebluegr $ + * + */ + +#ifndef SCI_GRAPHICS_TEXT32_H +#define SCI_GRAPHICS_TEXT32_H + +#include "common/hashmap.h" + +namespace Sci { + +struct TextEntry { + reg_t object; + uint16 x; + uint16 y; + uint16 width; + uint16 height; + byte *surface; + Common::String text; +}; + +// TODO: Move to Cache, perhaps? +#define MAX_CACHED_TEXTS 20 +typedef Common::HashMap TextCache; + +/** + * Text32 class, handles text calculation and displaying of text for SCI2, SCI21 and SCI3 games + */ +class GfxText32 { +public: + GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); + ~GfxText32(); + void createTextBitmap(reg_t textObject); + void drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 w); + int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font); + TextEntry *getTextEntry(reg_t textObject); + +private: + TextEntry *createTextEntry(reg_t textObject); + void purgeCache(); + + SegManager *_segMan; + GfxCache *_cache; + TextCache _textCache; + GfxScreen *_screen; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 2202002e2e..c129ae5439 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -80,6 +80,7 @@ ifdef ENABLE_SCI32 MODULE_OBJS += \ graphics/frameout.o \ graphics/paint32.o \ + graphics/text32.o \ video/robot_decoder.o endif diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 792b2b2055..6c1b6e4dd6 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -61,6 +61,7 @@ #include "sci/graphics/transitions.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/text32.h" #include "sci/graphics/frameout.h" #include "sci/video/robot_decoder.h" #endif @@ -146,6 +147,7 @@ SciEngine::~SciEngine() { DebugMan.clearAllDebugChannels(); #ifdef ENABLE_SCI32 + delete _gfxText32; delete _robotDecoder; delete _gfxFrameout; #endif @@ -598,6 +600,7 @@ void SciEngine::initGraphics() { _gfxText16 = 0; _gfxTransitions = 0; #ifdef ENABLE_SCI32 + _gfxText32 = 0; _robotDecoder = 0; _gfxFrameout = 0; _gfxPaint32 = 0; @@ -627,6 +630,7 @@ void SciEngine::initGraphics() { _gfxCompare = new GfxCompare(_gamestate->_segMan, _kernel, _gfxCache, _gfxScreen, _gfxCoordAdjuster); _gfxPaint32 = new GfxPaint32(_resMan, _gamestate->_segMan, _kernel, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); _gfxPaint = _gfxPaint32; + _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen); _robotDecoder = new RobotDecoder(g_system->getMixer(), getPlatform() == Common::kPlatformMacintosh); _gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); } else { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index b419d862a4..81bbdc51de 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -71,6 +71,7 @@ class GfxPalette; class GfxPorts; class GfxScreen; class GfxText16; +class GfxText32; class GfxTransitions; #ifdef ENABLE_SCI32 @@ -313,6 +314,7 @@ public: GfxPorts *_gfxPorts; // Port managment for 16-bit gfx GfxScreen *_gfxScreen; GfxText16 *_gfxText16; + GfxText32 *_gfxText32; GfxTransitions *_gfxTransitions; // transitions between screens for 16-bit gfx GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager -- cgit v1.2.3 From 7b71e9842ee11e5f35256083f3dff63bede0a296 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 5 Sep 2011 12:14:17 +0200 Subject: SCI: Fix Island of Dr. Brain copyprot pause menu on touch devices Patch from m_kiewitz. --- engines/sci/graphics/cursor.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/sci') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 18ff1fd0b9..57c65aa6e0 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -227,6 +227,7 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co // Game, newPosition, validRect static const SciCursorSetPositionWorkarounds setPositionWorkarounds[] = { { GID_ISLANDBRAIN, 84, 109, 46, 76, 174, 243 }, // island of dr. brain / game menu + { GID_ISLANDBRAIN,143, 135, 57, 102, 163, 218 },// island of dr. brain / pause menu within copy protection { GID_LSL5, 23, 171, 0, 0, 26, 320 }, // larry 5 / skip forward helper { GID_QFG1VGA, 64, 174, 40, 37, 74, 284 }, // Quest For Glory 1 VGA / run/walk/sleep sub-menu { GID_QFG3, 70, 170, 40, 61, 81, 258 }, // Quest For Glory 3 / run/walk/sleep sub-menu -- cgit v1.2.3 From 5443ef943fc4758ee9b1bf8842b0cde02d4f0a59 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 8 Sep 2011 00:35:12 +0200 Subject: SCI: Made some static data const. --- engines/sci/engine/kernel_tables.h | 6 +++--- engines/sci/resource.cpp | 6 +++--- engines/sci/sound/drivers/gm_names.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 0c5d4e680d..3c5af6fab7 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -602,7 +602,7 @@ static SciKernelMapEntry s_kernelMap[] = { }; /** Default kernel name table. */ -static const char *s_defaultKernelNames[] = { +static const char *const s_defaultKernelNames[] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", @@ -751,7 +751,7 @@ static const char *s_defaultKernelNames[] = { // NOTE: 0x72-0x79, 0x85-0x86, 0x88 are from the GK2 demo (which has debug support) and are // just Dummy in other SCI2 games. -static const char *sci2_default_knames[] = { +static const char *const sci2_default_knames[] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", @@ -916,7 +916,7 @@ static const char *sci2_default_knames[] = { /*0x9f*/ "MessageBox" }; -static const char *sci21_default_knames[] = { +static const char *const sci21_default_knames[] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 1b8b7b2f0e..17a4af9c17 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -93,7 +93,7 @@ const char *getSciVersionDesc(SciVersion version) { //#define SCI_VERBOSE_RESMAN 1 -static const char *sci_error_types[] = { +static const char *const sci_error_types[] = { "No error", "I/O error", "Resource is empty (size 0)", @@ -107,7 +107,7 @@ static const char *sci_error_types[] = { "SCI version is unsupported" }; -static const char *s_resourceTypeNames[] = { +static const char *const s_resourceTypeNames[] = { "view", "pic", "script", "text", "sound", "memory", "vocab", "font", "cursor", "patch", "bitmap", "palette", "cdaudio", @@ -120,7 +120,7 @@ static const char *s_resourceTypeNames[] = { // Resource type suffixes. Note that the // suffic of SCI3 scripts has been changed from // scr to csc -static const char *s_resourceTypeSuffixes[] = { +static const char *const s_resourceTypeSuffixes[] = { "v56", "p56", "scr", "tex", "snd", "", "voc", "fon", "cur", "pat", "bit", "pal", "cda", "aud", "syn", diff --git a/engines/sci/sound/drivers/gm_names.h b/engines/sci/sound/drivers/gm_names.h index bfe5ff88c7..fbfa413a4a 100644 --- a/engines/sci/sound/drivers/gm_names.h +++ b/engines/sci/sound/drivers/gm_names.h @@ -30,7 +30,7 @@ namespace Sci { // is defined #ifndef REDUCE_MEMORY_USAGE -static const char *GmInstrumentNames[] = { +static const char *const GmInstrumentNames[] = { /*000*/ "Acoustic Grand Piano", /*001*/ "Bright Acoustic Piano", /*002*/ "Electric Grand Piano", @@ -162,7 +162,7 @@ static const char *GmInstrumentNames[] = { }; // The GM Percussion map is downwards compatible to the MT32 map, which is used in SCI -static const char *GmPercussionNames[] = { +static const char *const GmPercussionNames[] = { /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- cgit v1.2.3 From 1d1cd14e65970ae4602858e2d12b102ef59a8acc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Sep 2011 12:36:41 +0300 Subject: SCI: Added another EGA version of Castle of Dr. Brain (bug #3405307) --- engines/sci/detection_tables.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index a3dd305222..455223a086 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -91,7 +91,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH }, - // Castle of Dr. Brain - English DOS Floppy EGA (from omer_mor, bug report #3035349) + // Castle of Dr. Brain - English DOS 5.25" Floppy EGA (from omer_mor, bug report #3035349) {"castlebrain", "EGA", { {"resource.map", 0, "88d106f945f7fd9d1aeda961cfec38a9", 2646}, {"resource.000", 0, "6e125f4ce3f4f5c35f2617c7b66c6e21", 25325}, @@ -104,6 +104,16 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Castle of Dr. Brain - English DOS 3.5" Floppy EGA (from nozomi77, bug report #3405307) + {"castlebrain", "EGA", { + {"resource.map", 0, "dfcf23e36cb81223bdf11166aaf90754", 2730}, + {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 300857}, + {"resource.001", 0, "6e0020a9f9bef9a9d65943dc013f14b5", 222108}, + {"resource.002", 0, "de2f182529efaad2c4b510b452ab77ac", 633662}, + {"resource.003", 0, "38b4b37febc6b4f5061c461a283df148", 430388}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Castle of Dr. Brain - English DOS Floppy (from jvprat) // Executable scanning reports "1.000.044", Floppy label reports "1.0, 10.30.91", VERSION file reports "1.000" // SCI interpreter version 1.000.510 -- cgit v1.2.3 From fa654e942adc5b7c6a01cd61c1d85dfdab4f8c14 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Sep 2011 13:02:15 +0300 Subject: SCI: Added handling of cnick-kq and cnick-longbow in the fallback detector --- engines/sci/detection.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 33ca3a6c9c..56da696592 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -296,8 +296,10 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R sierraId == "mg" || sierraId == "pq" || sierraId == "jones" || sierraId == "cardgames" || sierraId == "solitare" || - sierraId == "hoyle3" || sierraId == "hoyle4") + sierraId == "hoyle4") demoThreshold = 40; + if (sierraId == "hoyle3") + demoThreshold = 45; // cnick-kq has 42 scripts. The actual hoyle 3 demo has 27. if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4") demoThreshold = 150; @@ -310,8 +312,11 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R return "cnick-lsl"; if (sierraId == "sq4" && resources->size() == 34) return "cnick-sq"; - - // TODO: cnick-kq, cnick-laurabow and cnick-longbow (their resources can't be read) + if (sierraId == "hoyle3" && resources->size() == 42) + return "cnick-kq"; + if (sierraId == "rh budget" && resources->size() == 39) + return "cnick-longbow"; + // TODO: cnick-laurabow (the name of the game object contains junk) // Handle Astrochicken 1 (SQ3) and 2 (SQ4) if (sierraId == "sq3" && resources->size() == 20) -- cgit v1.2.3 From d8aaf40090ff32acf80e2433df57f7c74d126ab4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 10 Sep 2011 13:47:02 +0300 Subject: SCI: Fixed bug #3404466 - "ScummVM crashes when trying to add non-SCI resources file" --- engines/sci/resource.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 17a4af9c17..bdd7d6692b 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1158,8 +1158,10 @@ ResVersion ResourceManager::detectMapVersion() { } } - if (!fileStream) - error("Failed to open resource map file"); + if (!fileStream) { + warning("Failed to open resource map file"); + return kResVersionUnknown; + } // detection // SCI0 and SCI01 maps have last 6 bytes set to FF @@ -1259,7 +1261,7 @@ ResVersion ResourceManager::detectVolVersion() { } if (!fileStream) { - error("Failed to open volume file - if you got resource.p01/resource.p02/etc. files, merge them together into resource.000"); + warning("Failed to open volume file - if you got resource.p01/resource.p02/etc. files, merge them together into resource.000"); // resource.p01/resource.p02/etc. may be there when directly copying the files from the original floppies // the sierra installer would merge those together (perhaps we could do this as well?) // possible TODO -- cgit v1.2.3 From 7f675de8554b30e7b14af87a9cbb2e51d66fde5b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 22 Sep 2011 04:07:37 +0300 Subject: SCI: Fixed compilation with VM_DEBUG_SEND defined --- engines/sci/engine/scriptdebug.cpp | 5 ++++- engines/sci/engine/vm.cpp | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 3a18fbc68f..ad3f4fb788 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -31,6 +31,8 @@ namespace Sci { +//#define VM_DEBUG_SEND + // This table is only used for debugging. Don't include it for devices // with not enough available memory (e.g. phones), where REDUCE_MEMORY_USAGE // is defined @@ -618,12 +620,13 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg #ifdef VM_DEBUG_SEND debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj), - s->_segMan->getObjectName(send_obj), selector, + segMan->getObjectName(send_obj), selector, g_sci->getKernel()->getSelectorName(selector).c_str()); #endif // VM_DEBUG_SEND switch (selectorType) { case kSelectorNone: + debugN("\n"); break; case kSelectorVariable: #ifdef VM_DEBUG_SEND diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 274b0bbbc9..7c22b48ece 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -41,7 +41,6 @@ namespace Sci { const reg_t NULL_REG = {0, 0}; const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; const reg_t TRUE_REG = {0, 1}; -//#define VM_DEBUG_SEND // Enable the define below to have the VM abort on cases where a conditional // statement is followed by an unconditional jump (which will most likely lead // to an infinite loop). Aids in detecting script bugs such as #3040722. -- cgit v1.2.3 From b807041ad2527a355be6c1eb56e659e6daac0cb7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 22 Sep 2011 04:17:01 +0300 Subject: SCI: Ignore invalid pointers if the kernel function signature specifies it SCI scripts can send stale pointers to kernel functions (e.g. after loading a saved game). This is normal in some cases (such as kDisplay and kGraphRestoreBox), and their signatures are set to allow invalid pointers. Thus, in such cases, allow invalid pointers, as the kernel functions will handle them themselves. Fixes bug #3412002, and properly fixes bugs #3389579, #3292251, #3308087 and #3056811. Removed a relevant TODO. --- engines/sci/engine/kernel.cpp | 11 +++++++++-- engines/sci/engine/workarounds.cpp | 9 --------- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 8fb6322f55..a83a026762 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -488,8 +488,15 @@ bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) { if ((type & SIG_IS_INVALID) && (!(curSig & SIG_IS_INVALID))) return false; // pointer is invalid and signature doesn't allow that? - if (!((type & ~SIG_IS_INVALID) & curSig)) - return false; // type mismatch + if (!((type & ~SIG_IS_INVALID) & curSig)) { + if ((type & ~SIG_IS_INVALID) == SIG_TYPE_ERROR && (curSig & SIG_IS_INVALID)) { + // Type is unknown (error - usually because of a deallocated object or + // stale pointer) and the signature allows invalid pointers. In this case, + // ignore the invalid pointer. + } else { + return false; // type mismatch + } + } if (!(curSig & SIG_MORE_MAY_FOLLOW)) { sig++; diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 968afcb11c..ac8d5fa262 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -209,15 +209,9 @@ const SciWorkaroundEntry kDeviceInfo_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kDisplay_workarounds[] = { { GID_ISLANDBRAIN, 300, 300, 0, "geneDude", "show", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the gene explanation chart - a parameter is an object - { GID_PQ1, 500, 500, 0, "endInter", "changeState", 0x3e8, 0, { WORKAROUND_IGNORE, 0 } }, // restoring a game at the map scene (bug #3389579) - { GID_PQ1, 500, 500, 0, "endInter", "changeState", 0x46b, 0, { WORKAROUND_IGNORE, 0 } }, // restoring a game at the map scene (bug #3389579) { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4ae, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id { GID_PQ2, 23, 23, 0, "rm23Script", "elements", 0x4c1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id (another pq2 version, bug #3043904) { GID_QFG1, 11, 11, 0, "battle", "", -1, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id - { GID_QFG3, -1, 47, 0, "barterWin", "open", 0x1426, 0, { WORKAROUND_IGNORE, 0 } }, // sometimes when talking with a vendor that can be bartered with, the wrong local variable is checked and the variable contents are wrong - bug #3292251 - { GID_QFG3, -1, 47, 0, "barterIcon", "show", 0x135c, 0, { WORKAROUND_IGNORE, 0 } }, // sometimes when talking with a vendor that can be bartered with, the wrong local variable is checked and the variable contents are wrong - bug #3292251 - { GID_SQ1, -1, 700, 0, "arcadaRegion", "doit", -1, 0, { WORKAROUND_IGNORE, 0 } }, // restoring in some rooms of the arcada (right at the start) - { GID_SQ1, 44, 44, 0, "spinDone", "changeState",0x13b0, 0, { WORKAROUND_IGNORE, 0 } }, // restoring a game at the slot machine in Ulence Flats (bug #3308087) { GID_SQ4, 397, 0, 0, "", "export 12", -1, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store (bug #3044044) { GID_SQ4, 391, 391, 0, "doCatalog", "mode", 0x84, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object @@ -285,10 +279,7 @@ const SciWorkaroundEntry kGraphSaveBox_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, call,index, workaround const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { - { GID_LSL6, -1, 86, 0, "LL6Inv", "show", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time - // ^^ TODO: check, if this is really a script error or an issue with our restore code { GID_LSL6, -1, 86, 0, "LL6Inv", "hide", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens during the game, gets called with 1 extra parameter - { GID_SQ5, 850, 850, 0, NULL, "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // happens while playing Battle Cruiser (invalid segment) - bug #3056811 SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 0b4802c24b35af7dd233a6f06b77ef72cb684a54 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Sep 2011 00:21:49 +0300 Subject: SCI: Fixed bug #3413020 - "SCI: Longbow: Robin is stuck in the final monk chase scene" Special thanks to wjp for his work on bisecting to find the regression and for checking against the KQ5CD disasm --- engines/sci/engine/kmath.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index ef795d7e2f..7570856dff 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -37,6 +37,14 @@ reg_t kRandom(EngineState *s, int argc, reg_t *argv) { // some codes in sq4 are also random and 5 digit (if i remember correctly) const uint16 fromNumber = argv[0].toUint16(); const uint16 toNumber = argv[1].toUint16(); + // Some scripts may request a range in the reverse order (from largest + // to smallest). An example can be found in Longbow, room 710, where a + // random number is requested from 119 to 83. In this case, we're + // supposed to return toNumber (determined by the KQ5CD disasm). + // Fixes bug #3413020. + if (fromNumber > toNumber) + return make_reg(0, toNumber); + uint16 range = toNumber - fromNumber + 1; // calculating range is exactly how sierra sci did it and is required for hoyle 4 // where we get called with kRandom(0, -1) and we are supposed to give back values from 0 to 0 -- cgit v1.2.3 From 077acc5575a1918850e38df06d72579583f55053 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Sep 2011 17:41:30 +0300 Subject: SCI: Fixed bug #3413301 - "SCI: KQ6CD: Game stops responding at the bookworm" --- engines/sci/sound/soundcmd.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index d4cff7614c..e73df69375 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -130,8 +130,14 @@ reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { void SoundCommandParser::processPlaySound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("kDoSound(play): Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(play): Slot not found (%04x:%04x), initializing it manually", PRINT_REG(obj)); + // The sound hasn't been initialized for some reason, so initialize it here. + // Happens in KQ6, room 460, when giving the creature to the bookwork (the + // bookworm's child). Fixes bug #3413301. + processInitSound(obj); + musicSlot = _music->getSlot(obj); + if (!musicSlot) + error("Failed to initialize uninitialized sound slot"); } int resourceId = getSoundResourceId(obj); -- cgit v1.2.3 From 632df097612c927caeb763b43772aa33e618dab2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Sep 2011 18:52:12 +0300 Subject: SCI21: Marked kNewRoom as a debug function --- engines/sci/engine/kernel_tables.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 3c5af6fab7..b01fa9ddb0 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -564,6 +564,9 @@ static SciKernelMapEntry s_kernelMap[] = { // just use GetConfig and mark this one as empty, like the DOS version does. { MAP_EMPTY(GetSierraProfileInt), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // Debug function called whenever the current room changes + { MAP_EMPTY(NewRoom), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // Unused / debug SCI2.1 unused functions, always mapped to kDummy // The debug functions are called from the inbuilt debugger or polygon @@ -593,7 +596,6 @@ static SciKernelMapEntry s_kernelMap[] = { // UpdateLine - used by LSL6 // SetPalStyleRange - 2 integer parameters, start and end. All styles from start-end // (inclusive) are set to 0 - // NewRoom - 1 integer parameter, the current room number // MorphOn - used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270) // SetHotRectangles - used by Phantasmagoria 1 #endif @@ -1059,7 +1061,7 @@ static const char *const sci21_default_knames[] = { /*0x8b*/ "SetPalStyleRange", /*0x8c*/ "AddPicAt", /*0x8d*/ "MessageBox", // SCI3, was Dummy in SCI2.1 - /*0x8e*/ "NewRoom", + /*0x8e*/ "NewRoom", // debug function /*0x8f*/ "Dummy", /*0x90*/ "Priority", /*0x91*/ "MorphOn", -- cgit v1.2.3 From 75fb3b4ef89f531f8d5b95036a38351d3731f577 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 23 Sep 2011 18:53:52 +0300 Subject: SCI21: Added some skeleton code for offsetting pictures vertically (not working yet). Some cleanup --- engines/sci/engine/kgraphics.cpp | 11 +++-------- engines/sci/graphics/frameout.cpp | 16 +++++++++++----- engines/sci/graphics/frameout.h | 6 ++++-- 3 files changed, 18 insertions(+), 15 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 556e5249b6..0eda91b433 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1322,10 +1322,10 @@ reg_t kRepaintPlane(EngineState *s, int argc, reg_t *argv) { reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) { reg_t planeObj = argv[0]; GuiResourceId pictureId = argv[1].toUint16(); - int16 forWidth = argv[2].toSint16(); - // argv[3] seems to be 0 most of the time + int16 pictureX = argv[2].toSint16(); + int16 pictureY = argv[3].toSint16(); - g_sci->_gfxFrameout->kernelAddPicAt(planeObj, forWidth, pictureId); + g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, pictureX, pictureY); return s->r_acc; } @@ -1334,12 +1334,7 @@ reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) { } reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) { - // This kernel call likely seems to be doing the screen updates, - // as its called right after a view is updated - - // TODO g_sci->_gfxFrameout->kernelFrameout(); - return NULL_REG; } diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 5499a2d192..6bd310f1a0 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -198,12 +198,13 @@ void GfxFrameout::kernelDeletePlane(reg_t object) { } } -void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX) { +void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY) { PlanePictureEntry newPicture; newPicture.object = object; newPicture.pictureId = pictureId; newPicture.picture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, pictureId, false); newPicture.startX = startX; + newPicture.startY = startY; newPicture.pictureCels = 0; _planePictures.push_back(newPicture); } @@ -275,9 +276,8 @@ int16 GfxFrameout::kernelGetHighPlanePri() { return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back().object, SELECTOR(priority)); } -// TODO: No idea yet how to implement this -void GfxFrameout::kernelAddPicAt(reg_t planeObj, int16 forWidth, GuiResourceId pictureId) { - addPlanePicture(planeObj, pictureId, forWidth); +void GfxFrameout::kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY) { + addPlanePicture(planeObj, pictureId, pictureX, pictureY); } bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) { @@ -403,6 +403,7 @@ void GfxFrameout::kernelFrameout() { picEntry->y = planePicture->getSci32celY(pictureCelNr); picEntry->x = planePicture->getSci32celX(pictureCelNr); picEntry->picStartX = pictureIt->startX; + picEntry->picStartY = pictureIt->startY; picEntry->priority = planePicture->getSci32celPriority(pictureCelNr); @@ -425,8 +426,9 @@ void GfxFrameout::kernelFrameout() { itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight); itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth); itemEntry->picStartX = ((itemEntry->picStartX * _screen->getWidth()) / scriptsRunningWidth); + itemEntry->picStartY = ((itemEntry->picStartY * _screen->getHeight()) / scriptsRunningHeight); - // Out of view + // Out of view horizontally (sanity checks) int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x; int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo); int16 planeStartX = it->planeOffsetX; @@ -436,6 +438,9 @@ void GfxFrameout::kernelFrameout() { if (pictureCelStartX > planeEndX) continue; + // Out of view vertically (sanity checks) + // TODO + int16 pictureOffsetX = it->planeOffsetX; int16 pictureX = itemEntry->x; if ((it->planeOffsetX) || (itemEntry->picStartX)) { @@ -447,6 +452,7 @@ void GfxFrameout::kernelFrameout() { } } + // TODO: pictureOffsetY itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, it->planePictureMirrored); // warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority); diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 7e5b1a5006..d2c8086f5f 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -58,6 +58,7 @@ struct FrameoutEntry { Common::Rect celRect; GfxPicture *picture; int16 picStartX; + int16 picStartY; }; typedef Common::List FrameoutList; @@ -65,6 +66,7 @@ typedef Common::List FrameoutList; struct PlanePictureEntry { reg_t object; int16 startX; + int16 startY; GuiResourceId pictureId; GfxPicture *picture; FrameoutEntry *pictureCels; // temporary @@ -93,10 +95,10 @@ public: void kernelUpdateScreenItem(reg_t object); void kernelDeleteScreenItem(reg_t object); int16 kernelGetHighPlanePri(); - void kernelAddPicAt(reg_t planeObj, int16 forWidth, GuiResourceId pictureId); + void kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY); void kernelFrameout(); - void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX); + void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); void clear(); -- cgit v1.2.3 From 3bffb8e3f7ce5ebd065b8ba4b9059dee8160868e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 24 Sep 2011 01:31:18 +0300 Subject: SCI: Fixed timer bug #3127824 - "SCI: speed problem - Castle of Dr Brain" --- engines/sci/engine/kmisc.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index e6837242e4..a32480c168 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -54,8 +54,33 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { uint32 neededSleep = 30; - // WORKAROUNDS: + // WORKAROUNDS for scripts that are polling too quickly in scenes that + // are not animating much switch (g_sci->getGameId()) { + case GID_CASTLEBRAIN: + // In Castle of Dr. Brain, memory color matching puzzle in the first + // room (room 100), the game scripts constantly poll the state of each + // stone when the user clicks on one. Since the scene is not animating + // much, this results in activating and deactivating each stone very + // quickly (together with its associated tone sound), depending on how + // low it is in the animate list. This worked somewhat in older PCs, but + // not in modern computers. We throttle the scene in order to allow the + // stones to display, otherwise the game scripts reset them too soon. + // Fixes bug #3127824. + if (s->currentRoomNumber() == 100) { + s->_throttleTrigger = true; + neededSleep = 60; + } + break; + case GID_ICEMAN: + // In ICEMAN the submarine control room is not animating much, so it + // runs way too fast. We calm it down even more, otherwise fighting + // against other submarines is almost impossible. + if (s->currentRoomNumber() == 27) { + s->_throttleTrigger = true; + neededSleep = 60; + } + break; case GID_LSL3: // LSL3 calculates a machinespeed variable during game startup // (right after the filthy questions). This one would go through w/o @@ -65,21 +90,12 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { if (s->currentRoomNumber() == 290) s->_throttleTrigger = true; break; - case GID_ICEMAN: - // In ICEMAN the submarine control room is not animating much, so it runs way too fast - // we calm it down even more otherwise especially fighting against other submarines - // is almost impossible - if (s->currentRoomNumber() == 27) { - s->_throttleTrigger = true; - neededSleep = 60; - } - break; case GID_SQ4: // In SQ4 (floppy and CD) the sequel police appear way too quickly in // the Skate-o-rama rooms, resulting in all sorts of timer issues, like // #3109139 (which occurs because a police officer instantly teleports // just before Roger exits and shoots him). We throttle these scenes a - // bit more, in order to prevent timer bugs related to the sequel police + // bit more, in order to prevent timer bugs related to the sequel police. if (s->currentRoomNumber() == 405 || s->currentRoomNumber() == 406 || s->currentRoomNumber() == 410 || s->currentRoomNumber() == 411) { s->_throttleTrigger = true; -- cgit v1.2.3 From 7b68952726724cfc35a0d9e98b485e8c615907cb Mon Sep 17 00:00:00 2001 From: Tarek Soliman Date: Wed, 21 Sep 2011 21:47:51 -0500 Subject: SCI: change savegame default description day format to YYYY.MM.DD ... and make it optional subject to USE_SAVEGAME_TIMESTAMP --- engines/sci/engine/kfile.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 1bd6754ca5..0c73125bdb 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -578,11 +578,15 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { game_description = dialog->getResultString(); if (game_description.empty()) { // create our own description for the saved game, the user didnt enter it + #if defined(USE_SAVEGAME_TIMESTAMP) TimeDate curTime; g_system->getTimeAndDate(curTime); curTime.tm_year += 1900; // fixup year curTime.tm_mon++; // fixup month - game_description = Common::String::format("%02d.%02d.%04d / %02d:%02d:%02d", curTime.tm_mday, curTime.tm_mon, curTime.tm_year, curTime.tm_hour, curTime.tm_min, curTime.tm_sec); + game_description = Common::String::format("%04d.%02d.%02d / %02d:%02d:%02d", curTime.tm_year, curTime.tm_mon, curTime.tm_mday, curTime.tm_hour, curTime.tm_min, curTime.tm_sec); + #else + game_description = Common::String::format("Save %d", savegameId + 1); + #endif } delete dialog; g_sci->_soundCmd->pauseAll(false); // unpause music ( we can't have it paused during save) -- cgit v1.2.3 From e552bc57baf616daae8fb8831b6bf10c933db106 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 24 Sep 2011 18:44:57 +0300 Subject: SCI: Always reset hold when starting a new song. Fixes bug #3413589 - "SCI: KQ6CD: Game stops responding in the catacombs" kDoSoundSetHold is always called after kDoSoundPlay. A regression from commit 4f3b85f4efc05affb7b4a7080e349360a3352048 --- engines/sci/sound/soundcmd.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index e73df69375..b723117811 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -163,6 +163,9 @@ void SoundCommandParser::processPlaySound(reg_t obj) { musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); + // Reset hold when starting a new song. kDoSoundSetHold is always called after + // kDoSoundPlay to set it properly, if needed. Fixes bug #3413589. + musicSlot->hold = -1; if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); -- cgit v1.2.3 From 300cec119c029008853f36a31084d767332aa73c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 25 Sep 2011 04:09:29 +0300 Subject: SCI: Bugfix for the palette of Longbow Amiga (still not right) --- engines/sci/graphics/palette.cpp | 2 +- engines/sci/graphics/picture.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 38919593b4..c667e3313f 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -114,7 +114,7 @@ bool GfxPalette::isMerging() { void GfxPalette::setDefault() { if (_resMan->getViewType() == kViewEga) setEGA(); - else if (_resMan->getViewType() == kViewAmiga) + else if (_resMan->getViewType() == kViewAmiga || _resMan->getViewType() == kViewAmiga64) setAmiga(); else kernelSetFromResource(999, true); diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index ecb54e89e8..dad2b77036 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -740,7 +740,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { // Left-Over VGA palette, we simply ignore it curPos += 256 + 4 + 1024; } else { - // Setting half of the amiga palette + // Setting half of the Amiga palette _palette->modifyAmigaPalette(&data[curPos]); curPos += 32; } -- cgit v1.2.3 From ecddcc12b77b318304fd8f0d323aaa64a4b46aa5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 25 Sep 2011 23:55:44 +0300 Subject: SCI2: kString(Format) uses %d for unsigned integers. Some cleanup --- engines/sci/engine/kstring.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 783845bb76..1a9359bb26 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -201,8 +201,8 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { char xfer; int i; int startarg; - int str_leng = 0; /* Used for stuff like "%13s" */ - int unsigned_var = 0; + int strLength = 0; /* Used for stuff like "%13s" */ + bool unsignedVar = false; if (position.segment) startarg = 2; @@ -236,7 +236,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { mode = 0; } else { mode = 1; - str_leng = 0; + strLength = 0; } } else if (mode == 1) { /* xfer != '%' */ char fillchar = ' '; @@ -256,22 +256,22 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { else if (isdigit(static_cast(xfer)) || (xfer == '-')) source--; // Go to start of length argument - str_leng = strtol(source, &destp, 10); + strLength = strtol(source, &destp, 10); if (destp > source) source = destp; - if (str_leng < 0) { + if (strLength < 0) { align = ALIGN_LEFT; - str_leng = -str_leng; + strLength = -strLength; } else if (align != ALIGN_CENTER) align = ALIGN_RIGHT; xfer = *source++; } else - str_leng = 0; + strLength = 0; - assert((target - targetbuf) + str_leng + 1 <= maxsize); + assert((target - targetbuf) + strLength + 1 <= maxsize); switch (xfer) { case 's': { /* Copy string */ @@ -286,7 +286,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { Common::String tempsource = g_sci->getKernel()->lookupText(reg, arguments[paramindex + 1]); int slen = strlen(tempsource.c_str()); - int extralen = str_leng - slen; + int extralen = strLength - slen; assert((target - targetbuf) + extralen <= maxsize); if (extralen < 0) extralen = 0; @@ -342,7 +342,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { case 'c': { /* insert character */ assert((target - targetbuf) + 2 <= maxsize); if (align >= 0) - while (str_leng-- > 1) + while (strLength-- > 1) *target++ = ' '; /* Format into the text */ char argchar = arguments[paramindex++]; if (argchar) @@ -353,8 +353,14 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { case 'x': case 'u': - unsigned_var = 1; + unsignedVar = true; case 'd': { /* Copy decimal */ + // In the new SCI2 kString function, %d is used for unsigned + // integers. An example is script 962 in Shivers - it uses %d + // to create file names. + if (getSciVersion() >= SCI_VERSION_2) + unsignedVar = true; + /* int templen; -- unused atm */ const char *format_string = "%d"; @@ -362,14 +368,14 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { format_string = "%x"; int val = arguments[paramindex]; - if (!unsigned_var) + if (!unsignedVar) val = (int16)arguments[paramindex]; target += sprintf(target, format_string, val); paramindex++; assert((target - targetbuf) <= maxsize); - unsigned_var = 0; + unsignedVar = false; mode = 0; } @@ -384,7 +390,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { if (align) { int written = target - writestart; - int padding = str_leng - written; + int padding = strLength - written; if (padding > 0) { if (align > 0) { -- cgit v1.2.3 From 43fb9d32b52d3db7530ba5afac1bfe8e11decde3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 26 Sep 2011 19:52:17 +0300 Subject: SCI: Code formatting --- engines/sci/graphics/view.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 6ca4903e17..a0d5b51a2b 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -471,7 +471,8 @@ void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCo curByte = *rlePtr++; if (curByte & 0xC0) { // fill with color runLength = curByte >> 6; - memset(outPtr + pixelNr, curByte & 0x3F, MIN(runLength, pixelCount - pixelNr)); + curByte = curByte & 0x3F; + memset(outPtr + pixelNr, curByte, MIN(runLength, pixelCount - pixelNr)); } else { // skip the next pixels (transparency) runLength = curByte & 0x3F; } -- cgit v1.2.3 From 9fd66deb43a8ba1bd7b423cb6fe2b7177af74166 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 26 Sep 2011 19:57:50 +0300 Subject: SCI: Changes to the sound resource initialization code - Unified the sound resource initialization code in processInitSound() and reconstructPlayList() - Now checking the "Mixed Adlib/MIDI" mode checkbox for SCI1.1 digital audio sound effects, like it's done for SCI0 - SCI1 sound effects. If it's unchecked, their MIDI counterparts will play instead, if available --- engines/sci/engine/savegame.cpp | 8 ++---- engines/sci/sound/soundcmd.cpp | 55 +++++++++++++++++++++++------------------ engines/sci/sound/soundcmd.h | 3 +++ 3 files changed, 36 insertions(+), 30 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index e43c7097ed..c30518ab42 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -626,12 +626,8 @@ void SoundCommandParser::reconstructPlayList() { const MusicList::iterator end = _music->getPlayListEnd(); for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { - if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) { - (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion); - _music->soundInitSnd(*i); - } else { - (*i)->soundRes = 0; - } + initSoundResource(*i); + if ((*i)->status == kSoundPlaying) { // Sync the sound object's selectors related to playing with the stored // ones in the playlist, as they may have been invalidated when loading. diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index b723117811..a91b103214 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -37,6 +37,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM _music = new SciMusic(_soundVersion); _music->init(); + _bMultiMidi = ConfMan.getBool("multi_midi"); } SoundCommandParser::~SoundCommandParser() { @@ -63,6 +64,35 @@ int SoundCommandParser::getSoundResourceId(reg_t obj) { return resourceId; } +void SoundCommandParser::initSoundResource(MusicEntry *newSound) { + if (newSound->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, newSound->resourceId))) + newSound->soundRes = new SoundResource(newSound->resourceId, _resMan, _soundVersion); + else + newSound->soundRes = 0; + + // In SCI1.1 games, sound effects are started from here. If we can find + // a relevant audio resource, play it, otherwise switch to synthesized + // effects. If the resource exists, play it using map 65535 (sound + // effects map) + bool checkAudioResource = getSciVersion() >= SCI_VERSION_1_1; + if (g_sci->getGameId() == GID_HOYLE4) + checkAudioResource = false; // hoyle 4 has garbled audio resources in place of the sound resources + // if we play those, we will only make the user deaf and break speakers. Sierra SCI doesn't play anything + // on soundblaster. FIXME: check, why this is + + if (checkAudioResource && _resMan->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId))) { + // Found a relevant audio resource, create an audio stream + if (_bMultiMidi || !newSound->soundRes) { + int sampleLen; + newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen); + newSound->soundType = Audio::Mixer::kSpeechSoundType; + } + } + + if (!newSound->pStreamAud && newSound->soundRes) + _music->soundInitSnd(newSound); +} + void SoundCommandParser::processInitSound(reg_t obj) { int resourceId = getSoundResourceId(obj); @@ -73,11 +103,6 @@ void SoundCommandParser::processInitSound(reg_t obj) { MusicEntry *newSound = new MusicEntry(); newSound->resourceId = resourceId; - if (resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, resourceId))) - newSound->soundRes = new SoundResource(resourceId, _resMan, _soundVersion); - else - newSound->soundRes = 0; - newSound->soundObj = obj; newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF; @@ -88,25 +113,7 @@ void SoundCommandParser::processInitSound(reg_t obj) { debugC(kDebugLevelSound, "kDoSound(init): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), resourceId, newSound->loop, newSound->priority, newSound->volume); - // In SCI1.1 games, sound effects are started from here. If we can find - // a relevant audio resource, play it, otherwise switch to synthesized - // effects. If the resource exists, play it using map 65535 (sound - // effects map) - bool checkAudioResource = getSciVersion() >= SCI_VERSION_1_1; - if (g_sci->getGameId() == GID_HOYLE4) - checkAudioResource = false; // hoyle 4 has garbled audio resources in place of the sound resources - // if we play those, we will only make the user deaf and break speakers. Sierra SCI doesn't play anything - // on soundblaster. FIXME: check, why this is - - if (checkAudioResource && _resMan->testResource(ResourceId(kResourceTypeAudio, resourceId))) { - // Found a relevant audio resource, play it - int sampleLen; - newSound->pStreamAud = _audio->getAudioStream(resourceId, 65535, &sampleLen); - newSound->soundType = Audio::Mixer::kSpeechSoundType; - } else { - if (newSound->soundRes) - _music->soundInitSnd(newSound); - } + initSoundResource(newSound); _music->pushBackSlot(newSound); diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index 7f6e2a0fe8..c1dce014d2 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -32,6 +32,7 @@ namespace Sci { class Console; class SciMusic; class SoundCommandParser; +class MusicEntry; //typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value); //struct MusicEntryCommand { @@ -64,6 +65,7 @@ public: void processPlaySound(reg_t obj); void processStopSound(reg_t obj, bool sampleFinishedPlaying); + void initSoundResource(MusicEntry *newSound); MusicType getMusicType() const; @@ -109,6 +111,7 @@ private: SciMusic *_music; AudioPlayer *_audio; SciVersion _soundVersion; + bool _bMultiMidi; void processInitSound(reg_t obj); void processDisposeSound(reg_t obj); -- cgit v1.2.3 From 4717d11862a45991b56f367cc6616ffb1379e8c6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 27 Sep 2011 16:45:17 +0300 Subject: SCI: Added support for the halfbrite palette used in Longbow Amiga This fixes the remaining palette problems in the game (bug #3309036) --- engines/sci/graphics/palette.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index c667e3313f..5f703b90e3 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -206,6 +206,14 @@ bool GfxPalette::setAmiga() { _sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11; _sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11; _sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11; + + if (_totalScreenColors == 64) { + // Set the associated color from the Amiga halfbrite colors + _sysPalette.colors[curColor + 32].used = 1; + _sysPalette.colors[curColor + 32].r = _sysPalette.colors[curColor].r >> 1; + _sysPalette.colors[curColor + 32].g = _sysPalette.colors[curColor].g >> 1; + _sysPalette.colors[curColor + 32].b = _sysPalette.colors[curColor].b >> 1; + } } // Directly set the palette, because setOnScreen() wont do a thing for amiga @@ -226,6 +234,13 @@ void GfxPalette::modifyAmigaPalette(byte *data) { _sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11; _sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11; _sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11; + + if (_totalScreenColors == 64) { + // Set the associated color from the Amiga halfbrite colors + _sysPalette.colors[curColor + 32].r = _sysPalette.colors[curColor].r >> 1; + _sysPalette.colors[curColor + 32].g = _sysPalette.colors[curColor].g >> 1; + _sysPalette.colors[curColor + 32].b = _sysPalette.colors[curColor].b >> 1; + } } copySysPaletteToScreen(); -- cgit v1.2.3 From 1117c8c3ed82315da58b695e1975db84500659b0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 6 Oct 2011 23:30:07 +0300 Subject: SCI: Also default to MIDI for Windows versions of SCI1.1 games --- engines/sci/sound/music.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 2afab3858d..9610b6f847 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -63,12 +63,13 @@ void SciMusic::init() { // SCI sound init _dwTempo = 0; - // Default to MIDI in SCI2.1+ games, as many don't have AdLib support. Common::Platform platform = g_sci->getPlatform(); - uint32 deviceFlags = MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI; - if (getSciVersion() >= SCI_VERSION_2_1) + // Default to MIDI in SCI2.1+ games, as many don't have AdLib support. + // Also, default to MIDI for Windows versions of SCI1.1 games, as their + // soundtrack is written for GM. + if (getSciVersion() >= SCI_VERSION_2_1 || g_sci->_features->useAltWinGMSound()) deviceFlags |= MDT_PREFER_GM; // Currently our CMS implementation only supports SCI1(.1) -- cgit v1.2.3 From 189357dc9b7a7dd7bd20e7214eb0ebe9c5c9df85 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 7 Oct 2011 02:45:56 +0300 Subject: SCI: Added some extra static selectors These aren't needed by the engine, but make debugging easier in games that have no selector vocabulary --- engines/sci/engine/static_selectors.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index cca4c47be8..8f3337743d 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -102,18 +102,28 @@ static const char * const sci2Selectors[] = { #endif static const SelectorRemap sciSelectorRemap[] = { - { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 }, - { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 }, - { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "nodePtr", 44 }, - { SCI_VERSION_1_LATE, SCI_VERSION_1_LATE, "cantBeHere", 57 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 }, + { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 }, + { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 }, + { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "nodePtr", 44 }, + { SCI_VERSION_1_LATE, SCI_VERSION_1_LATE, "cantBeHere", 57 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 }, // SCI1.1 - { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 }, - { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 }, - { SCI_VERSION_1_1, SCI_VERSION_2_1, "-info-",4103 }, - { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 } + { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 }, + // The following are not really needed. They've only been defined to + // ease game debugging. + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-objID-", 4096 }, + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-size-", 4097 }, + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-propDict-", 4098 }, + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-methDict-", 4099 }, + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-classScript-", 4100 }, + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-script-", 4101 }, + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-super-", 4102 }, + // + { SCI_VERSION_1_1, SCI_VERSION_2_1, "-info-", 4103 }, + { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 } }; struct ClassReference { -- cgit v1.2.3 From 19cac9bb11287f007edc1a8db0bc6b97ca5d98fa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 7 Oct 2011 02:46:44 +0300 Subject: SCI21: Some initial work on kBitmap --- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel_tables.h | 1 + engines/sci/engine/kgraphics.cpp | 89 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index ff3c67c84b..b605908dc1 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -476,6 +476,7 @@ reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv); reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv); reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv); reg_t kFont(EngineState *s, int argc, reg_t *argv); +reg_t kBitmap(EngineState *s, int argc, reg_t *argv); #endif reg_t kDoSoundInit(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index b01fa9ddb0..d3adcaccbf 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -546,6 +546,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(SetFontRes), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(Font), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, + { MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", NULL, NULL }, // SCI2.1 Empty Functions diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 0eda91b433..9f309aeab7 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1670,6 +1670,95 @@ reg_t kFont(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { + // Used for bitmap operations in SCI2.1 and SCI3. + // This is the SCI2.1 version, the functionality seems to have changed in SCI3. + + switch (argv[0].toUint16()) { + case 0: // init bitmap surface + { + // 6 params, called e.g. from TextView::init() in Torin's Passage, + // script 64890 and TransView::init() in script 64884 + uint16 width = argv[1].toUint16(); + uint16 height = argv[2].toUint16(); + uint16 skip = argv[3].toUint16(); + uint16 back = argv[4].toUint16(); + uint16 width2 = (argc >= 6) ? argv[5].toUint16() : 0; + uint16 height2 = (argc >= 7) ? argv[6].toUint16() : 0; + uint16 transparent = (argc >= 8) ? argv[7].toUint16() : 0; + warning("kBitmap(0): width %d, height %d, skip %d, back %d, width2 %d, height2 %d, transparent %d", + width, height, skip, back, width2, height2, transparent); + // returns a pointer to a bitmap + } + break; + case 1: // dispose bitmap surface + // 1 param, bitmap pointer, called e.g. from MenuItem::dispose + // in Torin's Passage, script 64893 + warning("kBitmap(1), bitmap ptr %04x:%04x", PRINT_REG(argv[1])); + break; + case 2: // dispose bitmap surface, with extra param + // 2 params, called e.g. from MenuItem::dispose in Torin's Passage, + // script 64893 + warning("kBitmap(2), unk1 %d, bitmap ptr %04x:%04x", argv[1].toUint16(), PRINT_REG(argv[2])); + break; + case 3: // tiled surface + { + // 6 params, called e.g. from TiledBitmap::resize() in Torin's Passage, + // script 64869 + reg_t bitmapPtr = argv[1]; // obtained from kBitmap(0) + // The tiled view seems to always have 2 loops. + // These loops need to have 1 cel in loop 0 and 8 cels in loop 1. + uint16 view = argv[2].toUint16(); // vTiles selector + uint16 loop = argv[3].toUint16(); + uint16 cel = argv[4].toUint16(); + uint16 x = argv[5].toUint16(); + uint16 y = argv[6].toUint16(); + warning("kBitmap(3): bitmap ptr %04x:%04x, view %d, loop %d, cel %d, x %d, y %d", + PRINT_REG(bitmapPtr), view, loop, cel, x, y); + } + break; + case 4: // process text + { + // 13 params, called e.g. from TextButton::createBitmap() in Torin's Passage, + // script 64894 + reg_t bitmapPtr = argv[1]; // obtained from kBitmap(0) + Common::String text = s->_segMan->getString(argv[2]); + // unk3 + // unk4 + // unk5 + // unk6 + // skip? + // back? + uint16 font = argv[9].toUint16(); + uint16 mode = argv[10].toUint16(); + // unk + uint16 dimmed = argv[12].toUint16(); + warning("kBitmap(4): bitmap ptr %04x:%04x, font %d, mode %d, dimmed %d - text: \"%s\"", + PRINT_REG(bitmapPtr), font, mode, dimmed, text.c_str()); + } + break; + case 5: + { + // 6 params, called e.g. from TextView::init() and TextView::draw() + // in Torin's Passage, script 64890 + reg_t bitmapPtr = argv[1]; // obtained from kBitmap(0) + uint16 unk1 = argv[2].toUint16(); // unknown, usually 0, judging from scripts? + uint16 unk2 = argv[3].toUint16(); // unknown, usually 0, judging from scripts? + uint16 width = argv[4].toUint16(); // width - 1 + uint16 height = argv[5].toUint16(); // height - 1 + uint16 back = argv[6].toUint16(); + warning("kBitmap(5): bitmap ptr %04x:%04x, unk1 %d, unk2 %d, width %d, height %d, back %d", + PRINT_REG(bitmapPtr), unk1, unk2, width, height, back); + } + break; + default: + kStub(s, argc, argv); + break; + } + + return s->r_acc; +} + #endif } // End of namespace Sci -- cgit v1.2.3