aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kernel_tables.h2
-rw-r--r--engines/sci/engine/kgraphics32.cpp128
-rw-r--r--engines/sci/graphics/frameout.cpp45
-rw-r--r--engines/sci/graphics/frameout.h25
-rw-r--r--engines/sci/graphics/text32.cpp39
-rw-r--r--engines/sci/graphics/text32.h6
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);