aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kgraphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kgraphics.cpp')
-rw-r--r--engines/sci/engine/kgraphics.cpp293
1 files changed, 210 insertions, 83 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 556e5249b6..fd8e9ee9f0 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -49,9 +49,9 @@
#include "sci/graphics/text16.h"
#include "sci/graphics/view.h"
#ifdef ENABLE_SCI32
+#include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class
#include "sci/graphics/text32.h"
#include "sci/graphics/frameout.h"
-#include "sci/video/robot_decoder.h"
#endif
namespace Sci {
@@ -354,11 +354,9 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16();
#ifdef ENABLE_SCI32
- if (!g_sci->_gfxText16) {
- // TODO: Implement this
- textWidth = 0; textHeight = 0;
- warning("TODO: implement kTextSize for SCI32");
- } else
+ if (g_sci->_gfxText32)
+ g_sci->_gfxText32->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ else
#endif
g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
@@ -381,8 +379,13 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
}
debugC(kDebugLevelStrings, "GetTextSize '%s' -> %dx%d", text.c_str(), textWidth, textHeight);
- dest[2] = make_reg(0, textHeight);
- dest[3] = make_reg(0, textWidth);
+ if (getSciVersion() <= SCI_VERSION_1_1) {
+ dest[2] = make_reg(0, textHeight);
+ dest[3] = make_reg(0, textWidth);
+ } else {
+ dest[2] = make_reg(0, textWidth);
+ dest[3] = make_reg(0, textHeight);
+ }
return s->r_acc;
}
@@ -1285,7 +1288,10 @@ reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) {
}
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
+ if (g_sci->_gfxFrameout->findScreenItem(argv[0]) == NULL)
+ g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
+ else
+ g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]);
return s->r_acc;
}
@@ -1314,18 +1320,13 @@ reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRepaintPlane(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gfxFrameout->kernelRepaintPlane(argv[0]);
- return s->r_acc;
-}
-
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 +1335,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;
}
@@ -1392,70 +1388,29 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
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;
+ uint16 maxWidth = argv[1].toUint16(); // nsRight - nsLeft + 1
+ uint16 maxHeight = argv[2].toUint16(); // nsBottom - nsTop + 1
+ return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight);
}
case 1: {
if (argc != 2) {
- warning("kCreateTextBitmap(0): expected 2 arguments, got %i", argc);
+ warning("kCreateTextBitmap(1): 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)));
debugC(kDebugLevelStrings, "kCreateTextBitmap case 1 (%04x:%04x)", PRINT_REG(argv[1]));
debugC(kDebugLevelStrings, "%s", text.c_str());
- g_sci->_gfxText32->createTextBitmap(object);
- break;
+ return g_sci->_gfxText32->createTextBitmap(object);
}
default:
warning("CreateTextBitmap(%d)", argv[0].toUint16());
+ return NULL_REG;
}
-
- return NULL_REG;
}
-reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
-
- int16 subop = argv[0].toUint16();
-
- switch (subop) {
- case 0: { // init
- int id = argv[1].toUint16();
- reg_t obj = argv[2];
- int16 flag = argv[3].toSint16();
- int16 x = argv[4].toUint16();
- int16 y = argv[5].toUint16();
- warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y);
- g_sci->_robotDecoder->load(id);
- g_sci->_robotDecoder->setPos(x, y);
- }
- break;
- case 1: // LSL6 hires (startup)
- // TODO
- return NULL_REG; // an integer is expected
- case 4: { // start - we don't really have a use for this one
- //int id = argv[1].toUint16();
- //warning("kRobot(start), id %d", id);
- }
- break;
- case 7: // unknown, called e.g. by Phantasmagoria
- warning("kRobot(%d)", subop);
- break;
- case 8: // sync
- if ((uint32)g_sci->_robotDecoder->getCurFrame() != g_sci->_robotDecoder->getFrameCount() - 1) {
- writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG);
- } else {
- g_sci->_robotDecoder->close();
- // Signal the engine scripts that the video is done
- writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG);
- }
- break;
- default:
- warning("kRobot(%d)", subop);
- break;
- }
-
+reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxText32->disposeTextBitmap(argv[0]);
return s->r_acc;
}
@@ -1517,30 +1472,38 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
}
reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
- // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now
- kStub(s, argc, argv);
-
- // Used by Shivers 1, room 23601
+ // Used by Shivers 1, room 23601 to determine what blocks on the red door puzzle board
+ // are occupied by pieces already
// 6 arguments, all integers:
// argv[0] - subop (0 - 4). It's constantly called with 4 in Shivers 1
// argv[1] - view (used with view 23602 in Shivers 1)
// argv[2] - loop
// argv[3] - cel
- // argv[4] - unknown (row?)
- // argv[5] - unknown (column?)
+ // argv[4] - x (subfunction 4 only)
+ // argv[5] - y (subfunction 4 only)
// Subops:
// 0 - return the view
// 1 - return the loop
// 2, 3 - nop
- // 4 - returns some kind of hash (?) based on the view and the two last params
+ // 4 - return value of pixel at x, y
- // This seems to be a debug function, but it could be used to check if
- // the jigsaw pieces "stick" together (they currently don't, unless I'm missing
- // something)
-
- return s->r_acc;
+ switch (argv[0].toUint16()) {
+ case 4: {
+ GuiResourceId viewId = argv[1].toSint16();
+ int16 loopNo = argv[2].toSint16();
+ int16 celNo = argv[3].toSint16();
+ int16 x = argv[4].toUint16();
+ int16 y = argv[5].toUint16();
+ byte color = g_sci->_gfxCache->kernelViewGetColorAtCoordinate(viewId, loopNo, celNo, x, y);
+ return make_reg(0, color);
+ }
+ default: {
+ kStub(s, argc, argv);
+ return s->r_acc;
+ }
+ }
}
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
@@ -1675,6 +1638,170 @@ reg_t kFont(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+// TODO: Eventually, all of the kBitmap operations should be put
+// in a separate class
+
+#define BITMAP_HEADER_SIZE 46
+
+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(); // usually equals skip
+ //uint16 width2 = (argc >= 6) ? argv[5].toUint16() : 0;
+ //uint16 height2 = (argc >= 7) ? argv[6].toUint16() : 0;
+ //uint16 transparentFlag = (argc >= 8) ? argv[7].toUint16() : 0;
+
+ // TODO: skip, width2, height2, transparentFlag
+ // (used for transparent bitmaps)
+ int entrySize = width * height + BITMAP_HEADER_SIZE;
+ reg_t memoryId = s->_segMan->allocateHunkEntry("Bitmap()", entrySize);
+ byte *memoryPtr = s->_segMan->getHunkPointer(memoryId);
+ memset(memoryPtr, 0, BITMAP_HEADER_SIZE); // zero out the bitmap header
+ memset(memoryPtr + BITMAP_HEADER_SIZE, back, width * height);
+ // Save totalWidth, totalHeight
+ // TODO: Save the whole bitmap header, like SSCI does
+ WRITE_LE_UINT16((void *)memoryPtr, width);
+ WRITE_LE_UINT16((void *)(memoryPtr + 2), height);
+ return memoryId;
+ }
+ break;
+ case 1: // dispose text bitmap surface
+ return kDisposeTextBitmap(s, argc - 1, argv + 1);
+ 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 hunkId = 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 viewNum = 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();
+
+ byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
+ // Get totalWidth, totalHeight
+ uint16 totalWidth = READ_LE_UINT16((void *)memoryPtr);
+ uint16 totalHeight = READ_LE_UINT16((void *)(memoryPtr + 2));
+ byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
+
+ GfxView *view = g_sci->_gfxCache->getView(viewNum);
+ uint16 tileWidth = view->getWidth(loop, cel);
+ uint16 tileHeight = view->getHeight(loop, cel);
+ const byte *tileBitmap = view->getBitmap(loop, cel);
+ uint16 width = MIN<uint16>(totalWidth - x, tileWidth);
+ uint16 height = MIN<uint16>(totalHeight - y, tileHeight);
+
+ for (uint16 curY = 0; curY < height; curY++) {
+ for (uint16 curX = 0; curX < width; curX++) {
+ bitmap[(curY + y) * totalWidth + (curX + x)] = tileBitmap[curY * tileWidth + curX];
+ }
+ }
+
+ }
+ break;
+ case 4: // add text to bitmap
+ {
+ // 13 params, called e.g. from TextButton::createBitmap() in Torin's Passage,
+ // script 64894
+ reg_t hunkId = argv[1]; // obtained from kBitmap(0)
+ Common::String text = s->_segMan->getString(argv[2]);
+ uint16 textX = argv[3].toUint16();
+ uint16 textY = argv[4].toUint16();
+ //reg_t unk5 = argv[5];
+ //reg_t unk6 = argv[6];
+ //reg_t unk7 = argv[7]; // skip?
+ //reg_t unk8 = argv[8]; // back?
+ //reg_t unk9 = argv[9];
+ uint16 fontId = argv[10].toUint16();
+ //uint16 mode = argv[11].toUint16();
+ 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());
+ uint16 foreColor = 255; // TODO
+
+ byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
+ // Get totalWidth, totalHeight
+ uint16 totalWidth = READ_LE_UINT16((void *)memoryPtr);
+ uint16 totalHeight = READ_LE_UINT16((void *)(memoryPtr + 2));
+ byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
+
+ GfxFont *font = g_sci->_gfxCache->getFont(fontId);
+
+ int16 charCount = 0;
+ uint16 curX = textX, curY = textY;
+ const char *txt = text.c_str();
+
+ while (*txt) {
+ charCount = g_sci->_gfxText32->GetLongest(txt, totalWidth, font);
+ if (charCount == 0)
+ break;
+
+ for (int i = 0; i < charCount; i++) {
+ unsigned char curChar = txt[i];
+ font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, bitmap, totalWidth, totalHeight);
+ curX += font->getCharWidth(curChar);
+ }
+
+ curX = textX;
+ curY += font->getHeight();
+ txt += charCount;
+ while (*txt == ' ')
+ txt++; // skip over breaking spaces
+ }
+
+ }
+ break;
+ case 5: // fill with color
+ {
+ // 6 params, called e.g. from TextView::init() and TextView::draw()
+ // in Torin's Passage, script 64890
+ reg_t hunkId = argv[1]; // obtained from kBitmap(0)
+ uint16 x = argv[2].toUint16();
+ uint16 y = argv[3].toUint16();
+ uint16 fillWidth = argv[4].toUint16(); // width - 1
+ uint16 fillHeight = argv[5].toUint16(); // height - 1
+ uint16 back = argv[6].toUint16();
+
+ byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
+ // Get totalWidth, totalHeight
+ uint16 totalWidth = READ_LE_UINT16((void *)memoryPtr);
+ uint16 totalHeight = READ_LE_UINT16((void *)(memoryPtr + 2));
+ uint16 width = MIN<uint16>(totalWidth - x, fillWidth);
+ uint16 height = MIN<uint16>(totalHeight - y, fillHeight);
+ byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
+
+ for (uint16 curY = 0; curY < height; curY++) {
+ for (uint16 curX = 0; curX < width; curX++) {
+ bitmap[(curY + y) * totalWidth + (curX + x)] = back;
+ }
+ }
+
+ }
+ break;
+ default:
+ kStub(s, argc, argv);
+ break;
+ }
+
+ return s->r_acc;
+}
+
#endif
} // End of namespace Sci