Skip to content

Commit

Permalink
SCI: Implement accurate renderer architecture for SCI32
Browse files Browse the repository at this point in the history
  • Loading branch information
csnover committed Feb 18, 2016
1 parent 4ba0ff8 commit 75ccabc
Show file tree
Hide file tree
Showing 25 changed files with 6,426 additions and 1,150 deletions.
18 changes: 18 additions & 0 deletions engines/sci/console.cpp
Expand Up @@ -137,6 +137,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("wl", WRAP_METHOD(Console, cmdWindowList)); // alias
registerCmd("plane_list", WRAP_METHOD(Console, cmdPlaneList));
registerCmd("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias
registerCmd("visible_plane_list", WRAP_METHOD(Console, cmdVisiblePlaneList));
registerCmd("vpl", WRAP_METHOD(Console, cmdVisiblePlaneList)); // alias
registerCmd("plane_items", WRAP_METHOD(Console, cmdPlaneItemList));
registerCmd("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias
registerCmd("saved_bits", WRAP_METHOD(Console, cmdSavedBits));
Expand Down Expand Up @@ -380,6 +382,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
debugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n");
debugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n");
debugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n");
debugPrintf(" visible_plane_list / vpl - Shows a list of all the planes in the visible draw list (SCI2+)\n");
debugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n");
debugPrintf(" saved_bits - List saved bits on the hunk\n");
debugPrintf(" show_saved_bits - Display saved bits\n");
Expand Down Expand Up @@ -1766,6 +1769,21 @@ bool Console::cmdPlaneList(int argc, const char **argv) {
return true;
}

bool Console::cmdVisiblePlaneList(int argc, const char **argv) {
#ifdef ENABLE_SCI32
if (_engine->_gfxFrameout) {
debugPrintf("Visible plane list:\n");
_engine->_gfxFrameout->printVisiblePlaneList(this);
} else {
debugPrintf("This SCI version does not have a list of planes\n");
}
#else
debugPrintf("SCI32 isn't included in this compiled executable\n");
#endif
return true;
}


bool Console::cmdPlaneItemList(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Shows the list of items for a plane\n");
Expand Down
1 change: 1 addition & 0 deletions engines/sci/console.h
Expand Up @@ -96,6 +96,7 @@ class Console : public GUI::Debugger {
bool cmdAnimateList(int argc, const char **argv);
bool cmdWindowList(int argc, const char **argv);
bool cmdPlaneList(int argc, const char **argv);
bool cmdVisiblePlaneList(int argc, const char **argv);
bool cmdPlaneItemList(int argc, const char **argv);
bool cmdSavedBits(int argc, const char **argv);
bool cmdShowSavedBits(int argc, const char **argv);
Expand Down
186 changes: 76 additions & 110 deletions engines/sci/engine/kgraphics32.cpp
Expand Up @@ -80,21 +80,18 @@ reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) {
}

reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
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;
g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
return NULL_REG;
}

reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]);
return s->r_acc;
return NULL_REG;
}

reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxFrameout->kernelDeleteScreenItem(argv[0]);
return s->r_acc;
return NULL_REG;
}

reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) {
Expand All @@ -115,55 +112,26 @@ reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) {
reg_t planeObj = argv[0];
GuiResourceId pictureId = argv[1].toUint16();
int16 pictureX = argv[2].toSint16();
int16 pictureY = argv[3].toSint16();
int16 x = argv[2].toSint16();
int16 y = argv[3].toSint16();
bool mirrorX = argc > 4 ? argv[4].toSint16() : false;

g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, pictureX, pictureY);
return s->r_acc;
g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, x, y, mirrorX);
return NULL_REG;
}

reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, g_sci->_gfxFrameout->kernelGetHighPlanePri());
}

reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
/* TODO: Transcribed from SCI engine disassembly.
GraphicsMgr &graphicsMgr = g_sci->_graphicsMgr;
if (graphicsMgr.palMorphNeeded) {
graphicsMgr.PalMorphFrameOut(&g_PalStyleRanges, false);
}
else {
// TODO: Not sure if this is a pointer or not yet.
if (g_ScrollState != nullptr) {
kFrameOutDoScroll();
}
bool showBits = true;
if (argc == 1) {
showBits = (bool) argv[0].toUint16();
}
rect SOL_Rect = { .left = 0, .top = 0, .right = UINT32_MAX, .bottom = UINT32_MAX };
graphicsMgr.FrameOut(showBits, &rect);
}
*/
g_sci->_gfxFrameout->kernelFrameout();
bool showBits = argc > 0 ? argv[0].toUint16() : true;
g_sci->_gfxFrameout->kernelFrameout(showBits);
return NULL_REG;
}

reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv) {
/* TODO: Transcribed from SCI engine disassembly.
uint16 start = argv[0].toUint16();
uint16 end = argv[1].toUint16();
if (end <= start) {
uint16 index = start;
while (index <= end) {
g_PalStyleRanges[index] = 0;
}
}
*/

kStub(s, argc, argv);
g_sci->_gfxFrameout->kernelSetPalStyleRange(argv[0].toUint16(), argv[1].toUint16());
return NULL_REG;
}

Expand Down Expand Up @@ -266,72 +234,59 @@ reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) {
}

/**
* Used for scene transitions, replacing (but reusing parts of) the old
* transition code.
* Causes an immediate plane transition with an optional transition
* effect
*/
reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
// Can be called with 7 or 8 parameters
// The style defines which transition to perform. Related to the transition
// tables inside graphics/transitions.cpp
uint16 showStyle = argv[0].toUint16(); // 0 - 15
reg_t planeObj = argv[1]; // the affected plane
Common::String planeObjName = s->_segMan->getObjectName(planeObj);
uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts
uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff
int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out
uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts
uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out
ShowStyleType type = (ShowStyleType)argv[0].toUint16();
reg_t planeObj = argv[1];
int16 seconds = argv[2].toSint16();
// NOTE: This value seems to indicate whether the transition is an
// “exit” transition (0) or an “enter” transition (-1) for fade
// transitions. For other types of transitions, it indicates a palette
// index value to use when filling the screen.
int16 back = argv[3].toSint16();
int16 priority = argv[4].toSint16();
int16 animate = argv[5].toSint16();
// TODO: Rename to frameOutNow?
int16 refFrame = argv[6].toSint16();
int16 blackScreen;
reg_t pFadeArray;
int16 divisions;

// If the game has the pFadeArray selector, another parameter is used here,
// before the optional last parameter
bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0;
if (hasFadeArray) {
// argv[7]
divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?)
} else {
divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?)
// SCI 2–2.1early
if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
blackScreen = 0;
pFadeArray = NULL_REG;
divisions = argc > 7 ? argv[7].toSint16() : -1;
}

if (showStyle > 15) {
warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj));
return s->r_acc;
// SCI 2.1mid–2.1late
else if (getSciVersion() < SCI_VERSION_3) {
blackScreen = 0;
pFadeArray = argc > 7 ? argv[7] : NULL_REG;
divisions = argc > 8 ? argv[8].toSint16() : -1;
}
// SCI 3
else {
blackScreen = argv[7].toSint16();
pFadeArray = argc > 8 ? argv[8] : NULL_REG;
divisions = argc > 9 ? argv[9].toSint16() : -1;
}

// GK1 calls fadeout (13) / fadein (14) with the following parameters:
// seconds: 1
// backColor: 0 / -1
// fade: 200
// animate: 0
// refFrame: 0
// divisions: 0 / 20

// TODO: Check if the plane is in the list of planes to draw

Common::String effectName = "unknown";
// TODO: Reuse later for SCI2 and SCI3 implementation and then discard
// warning("kSetShowStyle: effect %d, plane: %04x:%04x (%s), sec: %d, "
// "dir: %d, prio: %d, animate: %d, ref frame: %d, black screen: %d, "
// "pFadeArray: %04x:%04x (%s), divisions: %d",
// type, PRINT_REG(planeObj), s->_segMan->getObjectName(planeObj), seconds,
// back, priority, animate, refFrame, blackScreen,
// PRINT_REG(pFadeArray), s->_segMan->getObjectName(pFadeArray), divisions);

switch (showStyle) {
case 0: // no transition / show
effectName = "show";
break;
case 13: // fade out
effectName = "fade out";
// TODO
break;
case 14: // fade in
effectName = "fade in";
// TODO
break;
default:
// TODO
break;
}
// NOTE: The order of planeObj and showStyle are reversed
// because this is how SCI3 called the corresponding method
// on the KernelMgr
g_sci->_gfxFrameout->kernelSetShowStyle(argc, planeObj, type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen);

warning("kSetShowStyle: effect %d (%s) - plane: %04x:%04x (%s), sec: %d, "
"back: %d, prio: %d, animate: %d, ref frame: %d, divisions: %d",
showStyle, effectName.c_str(), PRINT_REG(planeObj), planeObjName.c_str(),
seconds, backColor, priority, animate, refFrame, divisions);
return s->r_acc;
return NULL_REG;
}

reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
Expand Down Expand Up @@ -359,6 +314,8 @@ reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
}

reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
return kStub(s, argc, argv);
#if 0
// 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
Expand Down Expand Up @@ -464,6 +421,7 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
}

return s->r_acc;
#endif
}

reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) {
Expand Down Expand Up @@ -497,6 +455,8 @@ reg_t kFont(EngineState *s, int argc, reg_t *argv) {
// TODO: Eventually, all of the kBitmap operations should be put
// in a separate class

// NOTE: This size is correct only for SCI2.1mid; the size for
// SCI2/2.1early is 36
#define BITMAP_HEADER_SIZE 46

reg_t kBitmap(EngineState *s, int argc, reg_t *argv) {
Expand Down Expand Up @@ -673,6 +633,8 @@ reg_t kEditText(EngineState *s, int argc, reg_t *argv) {
}

reg_t kAddLine(EngineState *s, int argc, reg_t *argv) {
return kStub(s, argc, argv);
#if 0
reg_t plane = argv[0];
Common::Point startPoint(argv[1].toUint16(), argv[2].toUint16());
Common::Point endPoint(argv[3].toUint16(), argv[4].toUint16());
Expand All @@ -681,10 +643,15 @@ reg_t kAddLine(EngineState *s, int argc, reg_t *argv) {
byte priority = (byte)argv[7].toUint16();
byte control = (byte)argv[8].toUint16();
// argv[9] is unknown (usually a small number, 1 or 2). Thickness, perhaps?
return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, control);
// return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, control);
return s->r_acc;
#endif
}

reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) {
return kStub(s, argc, argv);

#if 0
reg_t hunkId = argv[0];
reg_t plane = argv[1];
Common::Point startPoint(argv[2].toUint16(), argv[3].toUint16());
Expand All @@ -694,14 +661,18 @@ reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) {
byte priority = (byte)argv[8].toUint16();
byte control = (byte)argv[9].toUint16();
// argv[10] is unknown (usually a small number, 1 or 2). Thickness, perhaps?
g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control);
// g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control);
return s->r_acc;
#endif
}
reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv) {
return kStub(s, argc, argv);
#if 0
reg_t hunkId = argv[0];
reg_t plane = argv[1];
g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId);
// g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId);
return s->r_acc;
#endif
}

reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {
Expand Down Expand Up @@ -730,12 +701,7 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {

// Used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270)
reg_t kMorphOn(EngineState *s, int argc, reg_t *argv) {
// TODO: g_sci->_gfxManager->palMorphIsOn = true
// This function sets the palMorphIsOn flag which causes kFrameOut to use
// an alternative FrameOut function (GraphicsMgr::PalMorphFrameOut instead
// of GraphicsMgr::FrameOut). At the end of the frame, kFrameOut sets the
// palMorphIsOn flag back to false.
kStub(s, argc, argv);
g_sci->_gfxFrameout->_palMorphIsOn = true;
return NULL_REG;
}

Expand Down
36 changes: 33 additions & 3 deletions engines/sci/engine/object.h
Expand Up @@ -41,8 +41,21 @@ enum {
};

enum infoSelectorFlags {
kInfoFlagClone = 0x0001,
kInfoFlagClass = 0x8000
kInfoFlagClone = 0x0001,
#ifdef ENABLE_SCI32
/**
* When set, indicates to game scripts that a screen
* item can be updated.
*/
kInfoFlagViewVisible = 0x0008, // TODO: "dirty" ?

/**
* When set, the object has an associated screen item in
* the rendering tree.
*/
kInfoFlagViewInserted = 0x0010,
#endif
kInfoFlagClass = 0x8000
};

enum ObjectOffsets {
Expand Down Expand Up @@ -120,7 +133,24 @@ class Object {
_infoSelectorSci3 = info;
}

// No setter for the -info- selector
#ifdef ENABLE_SCI32
void setInfoSelectorFlag(infoSelectorFlags flag) {
if (getSciVersion() < SCI_VERSION_3) {
_variables[_offset + 2] |= flag;
} else {
_infoSelectorSci3 |= flag;
}
}

// NOTE: In real engine, -info- is treated as byte size
void clearInfoSelectorFlag(infoSelectorFlags flag) {
if (getSciVersion() < SCI_VERSION_3) {
_variables[_offset + 2] &= ~flag;
} else {
_infoSelectorSci3 &= ~flag;
}
}
#endif

reg_t getNameSelector() const {
if (getSciVersion() < SCI_VERSION_3)
Expand Down

0 comments on commit 75ccabc

Please sign in to comment.