diff options
author | Filippos Karapetis | 2012-06-07 11:26:32 +0300 |
---|---|---|
committer | Filippos Karapetis | 2012-06-07 11:27:59 +0300 |
commit | de3f6a19ed6ca98ad152f5038c1db1f70f2c72ed (patch) | |
tree | 62b222498622c657785c44bbd64b2db0e374d6c6 /engines/sci | |
parent | e73f93e565fc0074da66429fd59db25114f84c12 (diff) | |
download | scummvm-rg350-de3f6a19ed6ca98ad152f5038c1db1f70f2c72ed.tar.gz scummvm-rg350-de3f6a19ed6ca98ad152f5038c1db1f70f2c72ed.tar.bz2 scummvm-rg350-de3f6a19ed6ca98ad152f5038c1db1f70f2c72ed.zip |
SCI: Initial implementation of kScrollWindow, used in some SCI21 games
This is used in LSL6 hires and SQ6. This initial implementation is hackish
and only works in SQ6 (nothing is shown in LSL6)
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics32.cpp | 128 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 45 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.h | 25 | ||||
-rw-r--r-- | engines/sci/graphics/text32.cpp | 39 | ||||
-rw-r--r-- | engines/sci/graphics/text32.h | 6 |
6 files changed, 169 insertions, 76 deletions
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 4ddf0534ea..254a479e65 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -564,7 +564,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(GetSierraProfileInt), SIG_EVERYWHERE, "rri", NULL, NULL }, { MAP_CALL(CelInfo), SIG_EVERYWHERE, "iiiiii", NULL, NULL }, { MAP_CALL(SetLanguage), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "io(.*)", 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 }, diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 2bb8288cb7..71c4949d65 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -308,103 +308,91 @@ reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) { } reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { - // Used by Phantasmagoria 1 and SQ6. In SQ6, it is used for the messages - // shown in the scroll window at the bottom of the screen. - - // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now - kStub(s, argc, argv); - - switch (argv[0].toUint16()) { + // Used by SQ6 and LSL6 hires for the text area in the bottom of the + // screen. The relevant scripts also exist in Phantasmagoria 1, but they're + // unused. This is always called by scripts 64906 (ScrollerWindow) and + // 64907 (ScrollableWindow). + + reg_t kWindow = argv[1]; + uint16 op = argv[0].toUint16(); + switch (op) { case 0: // Init - // 2 parameters - // argv[1] points to the scroll object (e.g. textScroller in SQ6) - // argv[2] is an integer (e.g. 0x32) - break; - case 1: // Show message + g_sci->_gfxFrameout->initScrollText(argv[2].toUint16()); // maxItems + g_sci->_gfxFrameout->clearScrollTexts(); + return argv[1]; // kWindow + case 1: // Show message, called by ScrollableWindow::addString + case 14: // Modify message, called by ScrollableWindow::modifyString // 5 or 6 parameters // Seems to be called with 5 parameters when the narrator speaks, and // with 6 when Roger speaks - // argv[1] unknown (usually 0) - // argv[2] the text to show - // argv[3] a small integer (e.g. 0x32) - // argv[4] a small integer (e.g. 0x54) - // argv[5] optional, unknown (usually 0) - warning("kScrollWindow: '%s'", s->_segMan->getString(argv[2]).c_str()); - break; - case 2: // Clear - // 2 parameters - // TODO - break; - case 3: // Page up - // 2 parameters - // TODO - break; - case 4: // Page down - // 2 parameters - // TODO + { + Common::String text = s->_segMan->getString(argv[2]); + uint16 x = 0;//argv[3].toUint16(); // TODO: can't be x (values are all wrong) + uint16 y = 0;//argv[4].toUint16(); // TODO: can't be y (values are all wrong) + // TODO: argv[5] is an optional unknown parameter (an integer set to 0) + g_sci->_gfxFrameout->addScrollTextEntry(text, kWindow, x, y, (op == 14)); + } break; - case 5: // Up arrow - // 2 parameters - // TODO + case 2: // Clear, called by ScrollableWindow::erase + g_sci->_gfxFrameout->clearScrollTexts(); break; - case 6: // Down arrow - // 2 parameters + case 3: // Page up, called by ScrollableWindow::scrollTo // TODO + kStub(s, argc, argv); break; - case 7: // Home - // 2 parameters + case 4: // Page down, called by ScrollableWindow::scrollTo // TODO + kStub(s, argc, argv); break; - case 8: // End - // 2 parameters - // TODO + case 5: // Up arrow, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->prevScrollText(); break; - case 9: // Resize - // 3 parameters - // TODO + case 6: // Down arrow, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->nextScrollText(); break; - case 10: // Where - // 3 parameters - // TODO + case 7: // Home, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->firstScrollText(); break; - case 11: // Go - // 4 parameters - // TODO + case 8: // End, called by ScrollableWindow::scrollTo + g_sci->_gfxFrameout->lastScrollText(); break; - case 12: // Insert - // 7 parameters + case 9: // Resize, called by ScrollableWindow::resize and ScrollerWindow::resize // TODO + kStub(s, argc, argv); break; - case 13: // Delete - // 3 parameters + case 10: // Where, called by ScrollableWindow::where // TODO + // argv[2] is an unknown integer + kStub(s, argc, argv); break; - case 14: // Modify - // 7 or 8 parameters + case 11: // Go, called by ScrollableWindow::scrollTo + // 2 extra parameters here // TODO + kStub(s, argc, argv); break; - case 15: // Hide - // 2 parameters + case 12: // Insert, called by ScrollableWindow::insertString + // 3 extra parameters here // TODO + kStub(s, argc, argv); break; - case 16: // Show - // 2 parameters - // TODO + // case 13 (Delete) is handled below + // case 14 (Modify) is handled above + case 15: // Hide, called by ScrollableWindow::hide + g_sci->_gfxFrameout->toggleScrollText(false); break; - case 17: // Destroy - // 2 parameters - // TODO + case 16: // Show, called by ScrollableWindow::show + g_sci->_gfxFrameout->toggleScrollText(true); break; - case 18: // Text - // 2 parameters - // TODO + case 17: // Destroy, called by ScrollableWindow::dispose + g_sci->_gfxFrameout->clearScrollTexts(); break; - case 19: // Reconstruct - // 3 parameters - // TODO + case 13: // Delete, unused + case 18: // Text, unused + case 19: // Reconstruct, unused + error("kScrollWindow: Unused subop %d invoked", op); break; default: - error("kScrollWindow: unknown subop %d", argv[0].toUint16()); + error("kScrollWindow: unknown subop %d", op); break; } diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 709a708d8b..450581000b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -59,6 +59,9 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; _scriptsRunningWidth = 320; _scriptsRunningHeight = 200; + _curScrollText = -1; + _showScrollText = false; + _maxScrollTexts = 0; } GfxFrameout::~GfxFrameout() { @@ -69,6 +72,46 @@ void GfxFrameout::clear() { deletePlaneItems(NULL_REG); _planes.clear(); deletePlanePictures(NULL_REG); + clearScrollTexts(); +} + +void GfxFrameout::clearScrollTexts() { + _scrollTexts.clear(); + _curScrollText = -1; +} + +void GfxFrameout::addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace) { + //reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow); + // HACK: We set the container dimensions manually + reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow, 480, 70); + ScrollTextEntry textEntry; + textEntry.bitmapHandle = bitmapHandle; + textEntry.kWindow = kWindow; + textEntry.x = x; + textEntry.y = y; + if (!replace || _scrollTexts.size() == 0) { + if (_scrollTexts.size() > _maxScrollTexts) { + _scrollTexts.remove_at(0); + _curScrollText--; + } + _scrollTexts.push_back(textEntry); + _curScrollText++; + } else { + _scrollTexts.pop_back(); + _scrollTexts.push_back(textEntry); + } +} + +void GfxFrameout::showCurrentScrollText() { + if (!_showScrollText || _curScrollText < 0) + return; + + uint16 size = (uint16)_scrollTexts.size(); + if (size > 0) { + assert(_curScrollText < size); + ScrollTextEntry textEntry = _scrollTexts[_curScrollText]; + g_sci->_gfxText32->drawScrollTextBitmap(textEntry.kWindow, textEntry.bitmapHandle, textEntry.x, textEntry.y); + } } void GfxFrameout::kernelAddPlane(reg_t object) { @@ -673,6 +716,8 @@ void GfxFrameout::kernelFrameout() { } } + showCurrentScrollText(); + _screen->copyToScreen(); g_sci->getEngineState()->_throttleTrigger = true; diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index ec4de62c0a..2d2ca6546c 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -76,6 +76,15 @@ struct PlanePictureEntry { typedef Common::List<PlanePictureEntry> PlanePictureList; +struct ScrollTextEntry { + reg_t bitmapHandle; + reg_t kWindow; + uint16 x; + uint16 y; +}; + +typedef Common::Array<ScrollTextEntry> ScrollTextList; + class GfxCache; class GfxCoordAdjuster32; class GfxPaint32; @@ -104,6 +113,18 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); void clear(); + + // Scroll text functions + void addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace); + void showCurrentScrollText(); + void initScrollText(uint16 maxItems) { _maxScrollTexts = maxItems; } + void clearScrollTexts(); + void firstScrollText() { if (_scrollTexts.size() > 0) _curScrollText = 0; } + void lastScrollText() { if (_scrollTexts.size() > 0) _curScrollText = _scrollTexts.size() - 1; } + void prevScrollText() { if (_curScrollText > 0) _curScrollText--; } + void nextScrollText() { if (_curScrollText + 1 < (uint16)_scrollTexts.size()) _curScrollText++; } + void toggleScrollText(bool show) { _showScrollText = show; } + void printPlaneList(Console *con); void printPlaneItemList(Console *con, reg_t planeObject); @@ -127,6 +148,10 @@ private: FrameoutList _screenItems; PlaneList _planes; PlanePictureList _planePictures; + ScrollTextList _scrollTexts; + int16 _curScrollText; + bool _showScrollText; + uint16 _maxScrollTexts; void sortPlanes(); diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index cd24ca5a99..8ac9582535 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -49,9 +49,12 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) GfxText32::~GfxText32() { } +reg_t GfxText32::createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { + return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk); + +} reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { 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. @@ -59,6 +62,11 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); Common::String text = _segMan->getString(stringObject); + + return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk); +} + +reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { // HACK: The character offsets of the up and down arrow buttons are off by one // in GK1, for some unknown reason. Fix them here. if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) { @@ -91,7 +99,11 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH reg_t memoryId = NULL_REG; if (prevHunk.isNull()) { memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); - writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + + // Scroll text objects have no bitmap selector! + ObjVarRef varp; + if (lookupSelector(_segMan, textObject, SELECTOR(bitmap), &varp, NULL) == kSelectorVariable) + writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); } else { memoryId = prevHunk; } @@ -175,6 +187,24 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) { void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) { reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); + drawTextBitmapInternal(x, y, planeRect, textObject, hunkId); +} + +void GfxText32::drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y) { + /*reg_t plane = readSelector(_segMan, textObject, SELECTOR(plane)); + Common::Rect planeRect; + planeRect.top = readSelectorValue(_segMan, plane, SELECTOR(top)); + planeRect.left = readSelectorValue(_segMan, plane, SELECTOR(left)); + planeRect.bottom = readSelectorValue(_segMan, plane, SELECTOR(bottom)); + planeRect.right = readSelectorValue(_segMan, plane, SELECTOR(right)); + + drawTextBitmapInternal(x, y, planeRect, textObject, hunkId);*/ + + // HACK: we pretty much ignore the plane rect and x, y... + drawTextBitmapInternal(0, 0, Common::Rect(20, 390, 600, 460), textObject, hunkId); +} + +void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId) { uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); // Sanity check: Check if the hunk is set. If not, either the game scripts // didn't set it, or an old saved game has been loaded, where it wasn't set. @@ -188,8 +218,9 @@ void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t t byte *memoryPtr = _segMan->getHunkPointer(hunkId); if (!memoryPtr) { - // Happens when restoring in some SCI32 games - warning("Attempt to draw an invalid text bitmap"); + // Happens when restoring in some SCI32 games (e.g. SQ6). + // Commented out to reduce console spam + //warning("Attempt to draw an invalid text bitmap"); return; } diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 3505de85eb..ce78003fdf 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -33,13 +33,17 @@ public: GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); ~GfxText32(); reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); - void disposeTextBitmap(reg_t hunkId); + reg_t createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject); + void drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y); + void disposeTextBitmap(reg_t hunkId); int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font); void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); private: + reg_t createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t hunkId); + void drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId); int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth); void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont); void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); |