mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-04 01:07:22 +00:00
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)
This commit is contained in:
parent
e73f93e565
commit
de3f6a19ed
@ -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 },
|
||||
|
@ -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.
|
||||
// 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).
|
||||
|
||||
// TODO: This is all a stub/skeleton, thus we're invoking kStub() for now
|
||||
kStub(s, argc, argv);
|
||||
|
||||
switch (argv[0].toUint16()) {
|
||||
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());
|
||||
{
|
||||
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 2: // Clear
|
||||
// 2 parameters
|
||||
// TODO
|
||||
case 2: // Clear, called by ScrollableWindow::erase
|
||||
g_sci->_gfxFrameout->clearScrollTexts();
|
||||
break;
|
||||
case 3: // Page up
|
||||
// 2 parameters
|
||||
case 3: // Page up, called by ScrollableWindow::scrollTo
|
||||
// TODO
|
||||
kStub(s, argc, argv);
|
||||
break;
|
||||
case 4: // Page down
|
||||
// 2 parameters
|
||||
case 4: // Page down, called by ScrollableWindow::scrollTo
|
||||
// TODO
|
||||
kStub(s, argc, argv);
|
||||
break;
|
||||
case 5: // Up arrow
|
||||
// 2 parameters
|
||||
// TODO
|
||||
case 5: // Up arrow, called by ScrollableWindow::scrollTo
|
||||
g_sci->_gfxFrameout->prevScrollText();
|
||||
break;
|
||||
case 6: // Down arrow
|
||||
// 2 parameters
|
||||
// TODO
|
||||
case 6: // Down arrow, called by ScrollableWindow::scrollTo
|
||||
g_sci->_gfxFrameout->nextScrollText();
|
||||
break;
|
||||
case 7: // Home
|
||||
// 2 parameters
|
||||
// TODO
|
||||
case 7: // Home, called by ScrollableWindow::scrollTo
|
||||
g_sci->_gfxFrameout->firstScrollText();
|
||||
break;
|
||||
case 8: // End
|
||||
// 2 parameters
|
||||
// TODO
|
||||
case 8: // End, called by ScrollableWindow::scrollTo
|
||||
g_sci->_gfxFrameout->lastScrollText();
|
||||
break;
|
||||
case 9: // Resize
|
||||
// 3 parameters
|
||||
case 9: // Resize, called by ScrollableWindow::resize and ScrollerWindow::resize
|
||||
// TODO
|
||||
kStub(s, argc, argv);
|
||||
break;
|
||||
case 10: // Where
|
||||
// 3 parameters
|
||||
case 10: // Where, called by ScrollableWindow::where
|
||||
// TODO
|
||||
// argv[2] is an unknown integer
|
||||
kStub(s, argc, argv);
|
||||
break;
|
||||
case 11: // Go
|
||||
// 4 parameters
|
||||
case 11: // Go, called by ScrollableWindow::scrollTo
|
||||
// 2 extra parameters here
|
||||
// TODO
|
||||
kStub(s, argc, argv);
|
||||
break;
|
||||
case 12: // Insert
|
||||
// 7 parameters
|
||||
case 12: // Insert, called by ScrollableWindow::insertString
|
||||
// 3 extra parameters here
|
||||
// TODO
|
||||
kStub(s, argc, argv);
|
||||
break;
|
||||
case 13: // Delete
|
||||
// 3 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 14: // Modify
|
||||
// 7 or 8 parameters
|
||||
// TODO
|
||||
case 16: // Show, called by ScrollableWindow::show
|
||||
g_sci->_gfxFrameout->toggleScrollText(true);
|
||||
break;
|
||||
case 15: // Hide
|
||||
// 2 parameters
|
||||
// TODO
|
||||
case 17: // Destroy, called by ScrollableWindow::dispose
|
||||
g_sci->_gfxFrameout->clearScrollTexts();
|
||||
break;
|
||||
case 16: // Show
|
||||
// 2 parameters
|
||||
// TODO
|
||||
break;
|
||||
case 17: // Destroy
|
||||
// 2 parameters
|
||||
// TODO
|
||||
break;
|
||||
case 18: // Text
|
||||
// 2 parameters
|
||||
// TODO
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user