diff options
author | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
commit | 75e8452b6e6a2bf4fb2f588aa00b428a60d873b5 (patch) | |
tree | f29541d55309487a94bd1d38e8b53bb3dde9aec6 /engines/sci/engine/kgraphics.cpp | |
parent | 48ee83b88957dab86bc763e9ef21a70179fa8679 (diff) | |
parent | e9f50882ea5b6beeefa994040be9d3bab6a1f107 (diff) | |
download | scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.gz scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.bz2 scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.zip |
OPENGL: Merged from trunk, from rev 52105 to 53396.
This includes an rather hacky attempt to merge all the recent gp2x backend
changes into the branch. I suppose the gp2x backend and probably all new
backends, i.e. gph, dingux etc., might not compile anymore.
Since I have no way of testing those it would be nice if porters could look
into getting those up to speed in this branch.
svn-id: r53399
Diffstat (limited to 'engines/sci/engine/kgraphics.cpp')
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 374 |
1 files changed, 210 insertions, 164 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index a3f7a90da3..07385fd3f9 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -57,48 +57,46 @@ namespace Sci { -void _k_dirloop(reg_t object, uint16 angle, EngineState *s, int argc, reg_t *argv) { +void showScummVMDialog(const Common::String &message) { + GUI::MessageDialog dialog(message, "OK"); + dialog.runModal(); +} + +void kDirLoopWorker(reg_t object, uint16 angle, EngineState *s, int argc, reg_t *argv) { GuiResourceId viewId = readSelectorValue(s->_segMan, object, SELECTOR(view)); uint16 signal = readSelectorValue(s->_segMan, object, SELECTOR(signal)); - int16 loopNo; - int16 maxLoops; - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); if (signal & kSignalDoesntTurn) return; - angle %= 360; - - if (!oldScriptHeader) { - if (angle < 45) - loopNo = 3; - else if (angle < 136) - loopNo = 0; - else if (angle < 225) - loopNo = 2; - else if (angle < 316) - loopNo = 1; - else - loopNo = 3; + int16 useLoop = -1; + if (getSciVersion() > SCI_VERSION_0_EARLY) { + if ((angle > 315) || (angle < 45)) { + useLoop = 3; + } else if ((angle > 135) && (angle < 225)) { + useLoop = 2; + } } else { - if (angle >= 330 || angle <= 30) - loopNo = 3; - else if (angle <= 150) - loopNo = 0; - else if (angle <= 210) - loopNo = 2; - else if (angle < 330) - loopNo = 1; - else loopNo = -1; + // SCI0EARLY + if ((angle > 330) || (angle < 30)) { + useLoop = 3; + } else if ((angle > 150) && (angle < 210)) { + useLoop = 2; + } + } + if (useLoop == -1) { + if (angle >= 180) { + useLoop = 1; + } else { + useLoop = 0; + } + } else { + int16 loopCount = g_sci->_gfxCache->kernelViewGetLoopCount(viewId); + if (loopCount < 4) + return; } - maxLoops = g_sci->_gfxCache->kernelViewGetLoopCount(viewId); - - - if ((loopNo > 1) && (maxLoops < 4)) - return; - - writeSelectorValue(s->_segMan, object, SELECTOR(loop), loopNo); + writeSelectorValue(s->_segMan, object, SELECTOR(loop), useLoop); } static reg_t kSetCursorSci0(EngineState *s, int argc, reg_t *argv) { @@ -131,8 +129,7 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelHide(); break; case -1: - // TODO: Special case at least in kq6, check disassembly - // Does something with magCursor, which is set on argc = 10, which we don't support + g_sci->_gfxCursor->kernelClearZoomZone(); break; case -2: g_sci->_gfxCursor->kernelResetMoveZone(); @@ -186,15 +183,10 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { break; case 10: // Freddy pharkas, when using the whiskey glass to read the prescription (bug #3034973) - // magnifier support, disabled using argc == 1, argv == -1 - warning("kSetCursor: unsupported magnifier"); - // we just set the view cursor currently - g_sci->_gfxCursor->kernelSetView(argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(), hotspot); - // argv[0] -> 1, 2, 4 -> maybe magnification multiplier - // argv[1-4] -> rect for magnification - // argv[5, 6, 7] -> view resource for cursor - // argv[8] -> picture resource for mag - // argv[9] -> color for magnifier replacement + g_sci->_gfxCursor->kernelSetZoomZone(argv[0].toUint16(), + Common::Rect(argv[1].toUint16(), argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16()), + argv[5].toUint16(), argv[6].toUint16(), argv[7].toUint16(), + argv[8].toUint16(), argv[9].toUint16()); break; default : error("kSetCursor: Unhandled case: %d arguments given", argc); @@ -264,7 +256,9 @@ reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) { int16 priority = (argc > 5) ? argv[5].toSint16() : -1; int16 control = (argc > 6) ? argv[6].toSint16() : -1; - // TODO: Find out why we get >15 for color in EGA + // TODO: Find out why we get > 15 for color in EGA + // FIXME: EGA? Which EGA? SCI0 or SCI1? Check the + // workarounds inside kGraphFillBoxAny and kNewWindow if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color()) color &= 0x0F; @@ -303,6 +297,13 @@ reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) { int16 priority = argv[6].toSint16(); // yes, we may read from stack sometimes here int16 control = argv[7].toSint16(); // sierra did the same + // WORKAROUND: PQ3 EGA is setting invalid colors (above 0 - 15). + // Colors above 15 are all white in SCI1 EGA games, which is why this was never + // observed. We clip them all to (0, 15) instead, as colors above 15 are used + // for the undithering algorithm in EGA games - bug #3048908. + if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY) + color &= 0x0F; + g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control); return s->r_acc; } @@ -397,7 +398,7 @@ reg_t kPriCoord(EngineState *s, int argc, reg_t *argv) { } reg_t kDirLoop(EngineState *s, int argc, reg_t *argv) { - _k_dirloop(argv[0], argv[1].toUint16(), s, argc, argv); + kDirLoopWorker(argv[0], argv[1].toUint16(), s, argc, argv); return s->r_acc; } @@ -801,6 +802,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { alignment = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode)); debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d", PRINT_REG(controlObject), text.c_str(), x, y, alignment); g_sci->_gfxControls->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite); + s->r_acc = g_sci->_gfxText16->allocAndFillReferenceRectArray(); return; case SCI_CONTROLS_TYPE_TEXTEDIT: @@ -896,6 +898,10 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { reg_t controlObject = argv[0]; Common::String objName = s->_segMan->getObjectName(controlObject); + // Most of the time, we won't return anything to the caller + // but |r| textcodes will trigger creation of rects in memory and will then set s->r_acc + s->r_acc = NULL_REG; + // Disable the "Change Directory" button, as we don't allow the game engine to // change the directory where saved games are placed // "changeDirItem" is used in the import windows of QFG2&3 @@ -922,20 +928,19 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { if (!changeDirButton.isNull()) { // check if checkDirButton is still enabled, in that case we are called the first time during that room if (!(readSelectorValue(s->_segMan, changeDirButton, SELECTOR(state)) & SCI_CONTROLS_STYLE_DISABLED)) { - GUI::MessageDialog dialog("Characters saved inside ScummVM are shown " + showScummVMDialog("Characters saved inside ScummVM are shown " "automatically. Character files saved in the original " "interpreter need to be put inside ScummVM's saved games " "directory and a prefix needs to be added depending on which " "game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' " - "for Quest for Glory 2. Example: 'qfg2-thief.sav'.", - "OK"); - dialog.runModal(); + "for Quest for Glory 2. Example: 'qfg2-thief.sav'."); } } + s->_chosenQfGImportItem = readSelectorValue(s->_segMan, controlObject, SELECTOR(mark)); } _k_GenericDrawControl(s, controlObject, false); - return NULL_REG; + return s->r_acc; } reg_t kHiliteControl(EngineState *s, int argc, reg_t *argv) { @@ -1078,6 +1083,15 @@ reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) { int colorPen = (argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0; int colorBack = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255; + // WORKAROUND: PQ3 EGA is setting invalid colors (above 0 - 15). + // Colors above 15 are all white in SCI1 EGA games, which is why this was never + // observed. We clip them all to (0, 15) instead, as colors above 15 are used + // for the undithering algorithm in EGA games - bug #3048908. + if (g_sci->getResMan()->getViewType() == kViewEga && getSciVersion() >= SCI_VERSION_1_EARLY) { + colorPen &= 0x0F; + colorBack &= 0x0F; + } + // const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL; if (argc>=13) { rect2 = Common::Rect (argv[5].toSint16(), argv[4].toSint16(), argv[7].toSint16(), argv[6].toSint16()); @@ -1152,6 +1166,81 @@ reg_t kTextColors(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +/** + * Debug command, used by the SCI builtin debugger + */ +reg_t kShow(EngineState *s, int argc, reg_t *argv) { + uint16 map = argv[0].toUint16(); + + switch (map) { + case 1: // Visual, substituted by display for us + g_sci->_gfxScreen->debugShowMap(3); + break; + case 2: // Priority + g_sci->_gfxScreen->debugShowMap(1); + break; + case 3: // Control + case 4: // Control + g_sci->_gfxScreen->debugShowMap(2); + break; + default: + warning("Map %d is not available", map); + } + + return s->r_acc; +} + +reg_t kRemapColors(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); + + uint16 operation = argv[0].toUint16(); + + switch (operation) { + case 0: { // Initialize remapping to base. 0 turns remapping off. + //int16 unk1 = (argc >= 2) ? argv[1].toSint16() : 0; + } + break; + case 1: { // unknown + // The demo of QFG4 calls this with 1+3 parameters, thus there are differences here + //int16 unk1 = argv[1].toSint16(); + //int16 unk2 = argv[2].toSint16(); + //int16 unk3 = argv[3].toSint16(); + //uint16 unk4 = argv[4].toUint16(); + //uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0; + } + break; + case 2: { // remap by percent + //int16 unk1 = argv[1].toSint16(); + //uint16 percent = argv[2].toUint16(); + //uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; + } + break; + case 3: { // remap to gray + //int16 unk1 = argv[1].toSint16(); + //int16 percent = argv[2].toSint16(); // 0 - 100 + //uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0; + } + break; + case 4: { // unknown + //int16 unk1 = argv[1].toSint16(); + //uint16 unk2 = argv[2].toUint16(); + //uint16 unk3 = argv[3].toUint16(); + //uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0; + } + break; + case 5: { // increment color + //int16 unk1 = argv[1].toSint16(); + //uint16 unk2 = argv[2].toUint16(); + } + break; + default: + break; + } + + return s->r_acc; +} + #ifdef ENABLE_SCI32 reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { @@ -1172,69 +1261,38 @@ reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) { } reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) { - reg_t viewObj = argv[0]; - - g_sci->_gfxFrameout->kernelAddScreenItem(viewObj); - return NULL_REG; + g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]); + return s->r_acc; } reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) { - //reg_t viewObj = argv[0]; - - //warning("kUpdateScreenItem, object %04x:%04x, view %d, loop %d, cel %d, pri %d", PRINT_REG(viewObj), viewId, loopNo, celNo, priority); - return NULL_REG; + g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]); + return s->r_acc; } reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) { - reg_t viewObj = argv[0]; - - g_sci->_gfxFrameout->kernelDeleteScreenItem(viewObj); - - /* - reg_t viewObj = argv[0]; - uint16 viewId = readSelectorValue(s->_segMan, viewObj, SELECTOR(view)); - int16 loopNo = readSelectorValue(s->_segMan, viewObj, SELECTOR(loop)); - int16 celNo = readSelectorValue(s->_segMan, viewObj, SELECTOR(cel)); - //int16 leftPos = 0; - //int16 topPos = 0; - int16 priority = readSelectorValue(s->_segMan, viewObj, SELECTOR(priority)); - //int16 control = 0; - */ - - // TODO - - //warning("kDeleteScreenItem, view %d, loop %d, cel %d, pri %d", viewId, loopNo, celNo, priority); - return NULL_REG; + g_sci->_gfxFrameout->kernelDeleteScreenItem(argv[0]); + return s->r_acc; } reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) { - reg_t planeObj = argv[0]; - - g_sci->_gfxFrameout->kernelAddPlane(planeObj); - return NULL_REG; + g_sci->_gfxFrameout->kernelAddPlane(argv[0]); + return s->r_acc; } reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv) { - reg_t planeObj = argv[0]; - - g_sci->_gfxFrameout->kernelDeletePlane(planeObj); - return NULL_REG; + g_sci->_gfxFrameout->kernelDeletePlane(argv[0]); + return s->r_acc; } reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) { - reg_t planeObj = argv[0]; - - g_sci->_gfxFrameout->kernelUpdatePlane(planeObj); + g_sci->_gfxFrameout->kernelUpdatePlane(argv[0]); return s->r_acc; } reg_t kRepaintPlane(EngineState *s, int argc, reg_t *argv) { - reg_t picObj = argv[0]; - - // TODO - - warning("kRepaintPlane object %04x:%04x", PRINT_REG(picObj)); - return NULL_REG; + g_sci->_gfxFrameout->kernelRepaintPlane(argv[0]); + return s->r_acc; } reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) { @@ -1261,9 +1319,8 @@ reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } -reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { - // Tests if the cursor is on the passed object - +// Tests if the coordinate is on the passed object +reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { uint16 x = argv[0].toUint16(); uint16 y = argv[1].toUint16(); reg_t targetObject = argv[2]; @@ -1296,75 +1353,9 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { if (g_sci->_gfxCompare->kernelIsItSkip(viewId, loopNo, celNo, Common::Point(x - nsRect.left, y - nsRect.top))) contained = false; } -// these hacks shouldn't be needed anymore -// uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); -// uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); - - // If top and left are negative, we need to adjust coordinates by - // the item's x and y (e.g. happens in GK1, day 1, with detective - // Mosely's hotspot in his office) - -// if (nsRect.left < 0) -// nsRect.translate(itemX, 0); -// -// if (nsRect.top < 0) -// nsRect.translate(0, itemY); - -// // HACK: nsLeft and nsTop can be invalid, so try and fix them here -// // using x and y (e.g. with the inventory screen in GK1) -// if (nsRect.left == itemY && nsRect.top == itemX) { -// // Swap the values, as they're inversed (eh???) -// nsRect.left = itemX; -// nsRect.top = itemY; -// } - return make_reg(0, contained); } -reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { - // Tests if the cursor is on the passed object, after adjusting the - // coordinates of the object according to the object's plane - - uint16 x = argv[0].toUint16(); - uint16 y = argv[1].toUint16(); - reg_t targetObject = argv[2]; - // TODO: argv[3] - it's usually 0 - Common::Rect nsRect; - - // Get the bounding rectangle of the object - nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft)); - nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); - nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); - nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); - - // Get the object's plane -#if 0 - reg_t planeObject = readSelector(s->_segMan, targetObject, SELECTOR(plane)); - if (!planeObject.isNull()) { - //uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); - //uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); - uint16 planeResY = readSelectorValue(s->_segMan, planeObject, SELECTOR(resY)); - uint16 planeResX = readSelectorValue(s->_segMan, planeObject, SELECTOR(resX)); - uint16 planeTop = readSelectorValue(s->_segMan, planeObject, SELECTOR(top)); - uint16 planeLeft = readSelectorValue(s->_segMan, planeObject, SELECTOR(left)); - planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY; - planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX; - - // Adjust the bounding rectangle of the object by the object's - // actual X, Y coordinates - nsRect.top = ((nsRect.top * g_sci->_gfxScreen->getHeight()) / planeResY); - nsRect.left = ((nsRect.left * g_sci->_gfxScreen->getWidth()) / planeResX); - nsRect.bottom = ((nsRect.bottom * g_sci->_gfxScreen->getHeight()) / planeResY); - nsRect.right = ((nsRect.right * g_sci->_gfxScreen->getWidth()) / planeResX); - - nsRect.translate(planeLeft, planeTop); - } -#endif - //warning("kIsOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16()); - - return make_reg(0, nsRect.contains(x, y)); -} - 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()) { @@ -1421,6 +1412,61 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) { + uint16 windowsOption = argv[0].toUint16(); + switch (windowsOption) { + case 0: + // Title bar on/off in Phantasmagoria, we return 0 (off) + return NULL_REG; + default: + warning("GetWindowsOption: Unknown option %d", windowsOption); + return NULL_REG; + } +} + +reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) { + switch (argv[0].toUint16()) { + case 1: + // Load a help file + // Maybe in the future we can implement this, but for now this message should suffice + showScummVMDialog("Please use an external viewer to open the game's help file: " + s->_segMan->getString(argv[1])); + break; + case 2: + // Looks like some init function + break; + default: + warning("Unknown kWinHelp subop %d", argv[0].toUint16()); + } + + return s->r_acc; +} + +/** + * Used to programmatically mass set properties of the target plane + */ +reg_t kSetShowStyle(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); + + // showStyle matches the style selector of the associated plane object + uint16 showStyle = argv[0].toUint16(); // 0 - 15 + reg_t planeObj = argv[1]; + //argv[2] + //int16 priority = argv[3].toSint16(); + //argv[4] + //argv[5] + //argv[6] + //argv[7] + //int16 unk8 = (argc >= 9) ? argv[8].toSint16() : 0; + + if (showStyle > 15) { + warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj)); + return s->r_acc; + } + + return s->r_acc; +} + #endif } // End of namespace Sci |