aboutsummaryrefslogtreecommitdiff
path: root/engines/tinsel/tinlib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/tinsel/tinlib.cpp')
-rw-r--r--engines/tinsel/tinlib.cpp4535
1 files changed, 3578 insertions, 957 deletions
diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp
index 07c1b22b2a..2313f343e8 100644
--- a/engines/tinsel/tinlib.cpp
+++ b/engines/tinsel/tinlib.cpp
@@ -36,12 +36,16 @@
#include "tinsel/config.h"
#include "tinsel/coroutine.h"
#include "tinsel/cursor.h"
+#include "tinsel/drives.h"
#include "tinsel/dw.h"
+#include "tinsel/events.h"
+#include "tinsel/faders.h"
#include "tinsel/film.h"
#include "tinsel/font.h"
#include "tinsel/graphics.h"
#include "tinsel/handle.h"
-#include "tinsel/inventory.h"
+#include "tinsel/dialogs.h"
+#include "tinsel/mareels.h"
#include "tinsel/move.h"
#include "tinsel/multiobj.h"
#include "tinsel/music.h"
@@ -49,6 +53,7 @@
#include "tinsel/palette.h"
#include "tinsel/pcode.h"
#include "tinsel/pid.h"
+#include "tinsel/play.h"
#include "tinsel/polygons.h"
#include "tinsel/rince.h"
#include "tinsel/savescn.h"
@@ -57,6 +62,7 @@
#include "tinsel/scroll.h"
#include "tinsel/sound.h"
#include "tinsel/strres.h"
+#include "tinsel/sysvar.h"
#include "tinsel/text.h"
#include "tinsel/timers.h" // For ONE_SECOND constant
#include "tinsel/tinlib.h"
@@ -72,49 +78,59 @@ namespace Tinsel {
extern bool bRestart; // restart flag - set to restart the game
extern bool bHasRestarted; // Set after a restart
+// In PCODE.CPP
+extern bool bNoPause;
+
// In DOS_MAIN.C
// TODO/FIXME: From dos_main.c: "Only used on PSX so far"
int clRunMode = 0;
//----------------- EXTERNAL FUNCTIONS ---------------------
-// in BG.C
-extern void startupBackground(SCNHANDLE bfilm);
+// in BG.CPP
extern void ChangePalette(SCNHANDLE hPal);
-extern int BackgroundWidth(void);
-extern int BackgroundHeight(void);
+extern int BgWidth(void);
+extern int BgHeight(void);
-// in DOS_DW.C
-extern void SetHookScene(SCNHANDLE scene, int entrance, int transition);
-extern void SetNewScene(SCNHANDLE scene, int entrance, int transition);
-extern void UnHookScene(void);
-extern void SuspendHook(void);
-extern void UnSuspendHook(void);
+// in BMV.CPP
+void PlayBMV(CORO_PARAM, SCNHANDLE hFileStem, int myEscape);
+bool MoviePlaying(void);
+void AbortMovie(void);
-// in PDISPLAY.C
+// in PDISPLAY.CPP
extern void EnableTags(void);
extern void DisableTags(void);
bool DisableTagsIfEnabled(void);
extern void setshowstring(void);
-// in PLAY.C
-extern void playFilm(SCNHANDLE film, int x, int y, int actorid, bool splay, int sfact, bool escOn, int myescEvent, bool bTop);
-extern void playFilmc(CORO_PARAM, SCNHANDLE film, int x, int y, int actorid, bool splay, int sfact, bool escOn, int myescEvent, bool bTop);
+// in SAVELOAD.CPP
+extern int NewestSavedGame(void);
-// in SCENE.C
+// in SCENE.CPP
extern void setshowpos(void);
+// in TINSEL.CPP
+extern void SetCdChangeScene(SCNHANDLE hScene);
+extern void SetHookScene(SCNHANDLE scene, int entrance, int transition);
+extern void SetNewScene(SCNHANDLE scene, int entrance, int transition);
+extern void UnHookScene(void);
+extern void SuspendHook(void);
+extern void UnSuspendHook(void);
+
#ifdef BODGE
-// In DOS_HAND.C
+// In HANDLE.CPP
bool ValidHandle(SCNHANDLE offset);
-// In SCENE.C
+// In SCENE.CPP
SCNHANDLE GetSceneHandle(void);
#endif
//----------------- GLOBAL GLOBAL DATA --------------------
-bool bEnableF1;
+bool bEnableMenu;
+
+static bool bInstantScroll = false;
+static bool bEscapedCdPlay = false;
//----------------- LOCAL DEFINES --------------------
@@ -125,70 +141,257 @@ bool bEnableF1;
|* Library Procedure and Function codes *|
\*----------------------------------------------------------------------*/
-enum LIB_CODE {
- ACTORATTR = 0, ACTORDIRECTION, ACTORREF, ACTORSCALE, ACTORXPOS = 4,
- ACTORYPOS, ADDICON, ADDINV1, ADDINV2, ADDOPENINV, AUXSCALE = 10,
- BACKGROUND, CAMERA, CLOSEINVENTORY, CONTROL, CONVERSATION = 15,
- CONVICON, CURSORXPOS, CURSORYPOS, DEC_CONVW, DEC_CURSOR = 20,
- DEC_INV1, DEC_INV2, DEC_INVW, DEC_LEAD, DEC_TAGFONT = 25,
- DEC_TALKFONT, DELICON, DELINV, EFFECTACTOR, ESCAPE, EVENT = 31,
- GETINVLIMIT, HELDOBJECT, HIDE, ININVENTORY, INVDEPICT = 36,
- INVENTORY, KILLACTOR, KILLBLOCK, KILLEXIT, KILLTAG, LEFTOFFSET = 42,
- MOVECURSOR, NEWSCENE, NOSCROLL, OBJECTHELD, OFFSET, PAUSE = 48,
- PLAY, PLAYMIDI, PLAYSAMPLE, PREPARESCENE, PRINT, PRINTOBJ = 54,
- PRINTTAG, RANDOM, RESTORE_SCENE, SAVE_SCENE, SCALINGREELS = 59,
- SCANICON, SCROLL, SETACTOR, SETBLOCK, SETEXIT, SETINVLIMIT = 65,
- SETPALETTE, SETTAG, SETTIMER, SHOWPOS, SHOWSTRING, SPLAY = 71,
- STAND, STANDTAG, STOP, SWALK, TAGACTOR, TALK, TALKATTR, TIMER = 79,
- TOPOFFSET, TOPPLAY, TOPWINDOW, UNTAGACTOR, VIBRATE, WAITKEY = 85,
- WAITTIME, WALK, WALKED, WALKINGACTOR, WALKPOLY, WALKTAG = 91,
- WHICHINVENTORY = 92,
- ACTORSON, CUTSCENE, HOOKSCENE, IDLETIME, RESETIDLETIME = 97,
- TALKAT, UNHOOKSCENE, WAITFRAME, DEC_CSTRINGS, STOPMIDI, STOPSAMPLE = 103,
- TALKATS = 104,
- DEC_FLAGS, FADEMIDI, CLEARHOOKSCENE, SETINVSIZE, INWHICHINV = 109,
- NOBLOCKING, SAMPLEPLAYING, TRYPLAYSAMPLE, ENABLEF1 = 113,
- RESTARTGAME, QUITGAME, FRAMEGRAB, PLAYRTF, CDPLAY, CDLOAD = 119,
- HASRESTARTED, RESTORE_CUT, RUNMODE, SUBTITLES, SETLANGUAGE = 124
+enum MASTER_LIB_CODES {
+ ACTORATTR, ACTORBRIGHTNESS, ACTORDIRECTION, ACTORPALETTE, ACTORPRIORITY, ACTORREF,
+ ACTORRGB, ACTORSCALE, ACTORSON, ACTORXPOS, ACTORYPOS, ADDHIGHLIGHT,
+ ADDINV, ADDINV1, ADDINV2, ADDOPENINV, ADDTOPIC, AUXSCALE, BACKGROUND, BLOCKING,
+ CALLACTOR, CALLGLOBALPROCESS, CALLOBJECT, CALLPROCESS, CALLSCENE, CALLTAG,
+ CAMERA, CDCHANGESCENE, CDDOCHANGE, CDENDACTOR, CDLOAD, CDPLAY, CLEARHOOKSCENE,
+ CLOSEINVENTORY, CONTROL, CONVERSATION, CONVTOPIC, CURSOR, CURSORXPOS, CURSORYPOS,
+ CUTSCENE, DECCONVW, DECCSTRINGS, DECCURSOR, DECFLAGS, DECINV1, DECINV2, DECINVW,
+ DECLARELANGUAGE, DECLEAD, DECSCALE, DECTAGFONT, DECTALKFONT, DELICON,
+ DELINV, DELTOPIC, DIMMUSIC, DROP, DROPEVERYTHING, DROPOUT, EFFECTACTOR, ENABLEMENU,
+ ENDACTOR, ESCAPE, ESCAPEOFF, ESCAPEON, EVENT, FACETAG, FADEIN, FADEMIDI,
+ FADEOUT, FRAMEGRAB, FREEZECURSOR, GETINVLIMIT, GHOST, GLOBALVAR, GRABMOVIE, HAILSCENE,
+ HASRESTARTED, HAVE, HELDOBJECT, HIDEACTOR, HIDEBLOCK, HIDEEFFECT, HIDEPATH,
+ HIDEREFER, HIDETAG, HOLD, HOOKSCENE, IDLETIME, ININVENTORY, INSTANTSCROLL, INVDEPICT,
+ INVENTORY, INVPLAY, INWHICHINV, KILLACTOR, KILLBLOCK, KILLEXIT, KILLGLOBALPROCESS,
+ KILLPROCESS, KILLTAG, LOCALVAR, MOVECURSOR, MOVETAG, MOVETAGTO, NEWSCENE,
+ NOBLOCKING, NOPAUSE, NOSCROLL, OBJECTHELD, OFFSET, OTHEROBJECT, PAUSE, PLAY, PLAYMIDI,
+ PLAYMOVIE, PLAYMUSIC, PLAYRTF, PLAYSAMPLE, POINTACTOR, POINTTAG, POSTACTOR, POSTGLOBALPROCESS,
+ POSTOBJECT, POSTPROCESS, POSTTAG, PREPARESCENE, PRINT, PRINTCURSOR, PRINTOBJ, PRINTTAG,
+ QUITGAME, RANDOM, RESETIDLETIME, RESTARTGAME, RESTORESCENE, RESTORE_CUT,
+ RESUMELASTGAME, RUNMODE, SAMPLEPLAYING, SAVESCENE, SAY, SAYAT, SCALINGREELS,
+ SCANICON, SCREENXPOS, SCREENYPOS, SCROLL, SCROLLPARAMETERS, SENDACTOR, SENDGLOBALPROCESS,
+ SENDOBJECT, SENDPROCESS, SENDTAG, SETACTOR, SETBLOCK, SETBRIGHTNESS, SETEXIT, SETINVLIMIT,
+ SETINVSIZE, SETLANGUAGE, SETPALETTE, SETSYSTEMREEL, SETSYSTEMSTRING, SETSYSTEMVAR,
+ SETTAG, SETTIMER, SHELL, SHOWACTOR, SHOWBLOCK, SHOWEFFECT, SHOWMENU, SHOWPATH,
+ SHOWPOS, SHOWREFER, SHOWSTRING, SHOWTAG, SPLAY, STAND, STANDTAG, STARTGLOBALPROCESS,
+ STARTPROCESS, STARTTIMER, STOPMIDI, STOPSAMPLE, STOPWALK, SUBTITLES, SWALK, SWALKZ,
+ SYSTEMVAR, TAGACTOR, TAGTAGXPOS, TAGTAGYPOS, TAGWALKXPOS, TAGWALKYPOS, TALK, TALKAT,
+ TALKATS, TALKATTR, TALKPALETTEINDEX, TALKRGB, TALKVIA, TEMPTAGFONT, TEMPTALKFONT,
+ THISOBJECT, THISTAG, TIMER, TOPIC, TOPPLAY, TOPWINDOW, TRANSLUCENTINDEX,
+ TRYPLAYSAMPLE, UNDIMMUSIC, UNHOOKSCENE, UNTAGACTOR, VIBRATE, WAITFRAME, WAITKEY,
+ WAITSCROLL, WAITTIME, WALK, WALKED, WALKEDPOLY, WALKEDTAG, WALKINGACTOR, WALKPOLY,
+ WALKTAG, WALKXPOS, WALKYPOS, WHICHCD, WHICHINVENTORY, ZZZZZZ,
+ HIGHEST_LIBCODE
};
+const MASTER_LIB_CODES DW1_CODES[] = {
+ ACTORATTR, ACTORDIRECTION, ACTORREF, ACTORSCALE, ACTORXPOS,
+ ACTORYPOS, ADDTOPIC, ADDINV1, ADDINV2, ADDOPENINV, AUXSCALE,
+ BACKGROUND, CAMERA, CLOSEINVENTORY, CONTROL, CONVERSATION,
+ CONVTOPIC, CURSORXPOS, CURSORYPOS, DECCONVW, DECCURSOR,
+ DECINV1, DECINV2, DECINVW, DECLEAD, DECTAGFONT,
+ DECTALKFONT, DELICON, DELINV, EFFECTACTOR, ESCAPE, EVENT,
+ GETINVLIMIT, HELDOBJECT, HIDEACTOR, ININVENTORY, INVDEPICT,
+ INVENTORY, KILLACTOR, KILLBLOCK, KILLEXIT, KILLTAG, SCREENXPOS,
+ MOVECURSOR, NEWSCENE, NOSCROLL, OBJECTHELD, OFFSET, PAUSE,
+ PLAY, PLAYMIDI, PLAYSAMPLE, PREPARESCENE, PRINT, PRINTOBJ,
+ PRINTTAG, RANDOM, RESTORESCENE, SAVESCENE, SCALINGREELS,
+ SCANICON, SCROLL, SETACTOR, SETBLOCK, SETEXIT, SETINVLIMIT,
+ SETPALETTE, SETTAG, SETTIMER, SHOWPOS, SHOWSTRING, SPLAY,
+ STAND, STANDTAG, STOPWALK, SWALK, TAGACTOR, TALK, TALKATTR, TIMER,
+ SCREENYPOS, TOPPLAY, TOPWINDOW, UNTAGACTOR, VIBRATE, WAITKEY,
+ WAITTIME, WALK, WALKED, WALKINGACTOR, WALKPOLY, WALKTAG,
+ WHICHINVENTORY, ACTORSON, CUTSCENE, HOOKSCENE, IDLETIME,
+ RESETIDLETIME, TALKAT, UNHOOKSCENE, WAITFRAME, DECCSTRINGS,
+ STOPMIDI, STOPSAMPLE, TALKATS, DECFLAGS, FADEMIDI,
+ CLEARHOOKSCENE, SETINVSIZE, INWHICHINV, NOBLOCKING,
+ SAMPLEPLAYING, TRYPLAYSAMPLE, ENABLEMENU, RESTARTGAME, QUITGAME,
+ FRAMEGRAB, PLAYRTF, CDPLAY, CDLOAD, HASRESTARTED, RESTORE_CUT,
+ RUNMODE, SUBTITLES, SETLANGUAGE,
+ HIGHEST_LIBCODE
+};
+const MASTER_LIB_CODES DW2_CODES[] = {
+ ACTORBRIGHTNESS, ACTORDIRECTION, ACTORPALETTE, ACTORPRIORITY,
+ ACTORREF, ACTORRGB, ACTORSCALE, ACTORXPOS, ACTORYPOS,
+ ADDHIGHLIGHT, ADDINV, ADDINV1, ADDINV2, ADDOPENINV, ADDTOPIC,
+ BACKGROUND, CALLACTOR, CALLGLOBALPROCESS, CALLOBJECT,
+ CALLPROCESS, CALLSCENE, CALLTAG, CAMERA, CDCHANGESCENE,
+ CDDOCHANGE, CDLOAD, CDPLAY, CLEARHOOKSCENE, CLOSEINVENTORY,
+ CONTROL, CONVERSATION, CURSOR, CURSORXPOS, CURSORYPOS,
+ DECCONVW, DECCURSOR, DECFLAGS, DECINV1, DECINV2, DECINVW,
+ DECLEAD, DECSCALE, DECTAGFONT, DECTALKFONT, DELTOPIC,
+ DIMMUSIC, DROP, DROPOUT, EFFECTACTOR, ENABLEMENU, ENDACTOR,
+ ESCAPEOFF, ESCAPEON, EVENT, FACETAG, FADEIN, FADEOUT, FRAMEGRAB,
+ FREEZECURSOR, GETINVLIMIT, GHOST, GLOBALVAR, GRABMOVIE,
+ HASRESTARTED, HAVE, HELDOBJECT, HIDEACTOR, HIDEBLOCK, HIDEEFFECT,
+ HIDEPATH, HIDEREFER, HIDETAG, HOLD, HOOKSCENE, IDLETIME,
+ INSTANTSCROLL, INVENTORY, INVPLAY, INWHICHINV, KILLACTOR,
+ KILLGLOBALPROCESS, KILLPROCESS, LOCALVAR, MOVECURSOR, MOVETAG,
+ MOVETAGTO, NEWSCENE, NOBLOCKING, NOPAUSE, NOSCROLL, OFFSET,
+ OTHEROBJECT, PAUSE, PLAY, PLAYMUSIC, PLAYRTF, PLAYSAMPLE,
+ POINTACTOR, POINTTAG, POSTACTOR, POSTGLOBALPROCESS, POSTOBJECT,
+ POSTPROCESS, POSTTAG, PRINT, PRINTCURSOR, PRINTOBJ, PRINTTAG,
+ QUITGAME, RANDOM, RESETIDLETIME, RESTARTGAME, RESTORESCENE,
+ RUNMODE, SAVESCENE, SAY, SAYAT, SCALINGREELS, SCREENXPOS,
+ SCREENYPOS, SCROLL, SCROLLPARAMETERS, SENDACTOR, SENDGLOBALPROCESS,
+ SENDOBJECT, SENDPROCESS, SENDTAG, SETBRIGHTNESS, SETINVLIMIT,
+ SETINVSIZE, SETLANGUAGE, SETPALETTE, SETSYSTEMSTRING, SETSYSTEMVAR,
+ SHELL, SHOWACTOR, SHOWBLOCK, SHOWEFFECT, SHOWPATH, SHOWREFER,
+ SHOWTAG, STAND, STANDTAG, STARTGLOBALPROCESS, STARTPROCESS,
+ STARTTIMER, STOPWALK, SUBTITLES, SWALK, SYSTEMVAR, TAGTAGXPOS,
+ TAGTAGYPOS, TAGWALKXPOS, TAGWALKYPOS, TALK, TALKAT, TALKPALETTEINDEX,
+ TALKRGB, TALKVIA, THISOBJECT, THISTAG, TIMER, TOPIC, TOPPLAY,
+ TOPWINDOW, TRANSLUCENTINDEX, UNDIMMUSIC, UNHOOKSCENE, WAITFRAME,
+ WAITKEY, WAITSCROLL, WAITTIME, WALK, WALKED, WALKEDPOLY, WALKEDTAG,
+ WALKINGACTOR, WALKPOLY, WALKTAG, WALKXPOS, WALKYPOS, WHICHCD,
+ WHICHINVENTORY, ZZZZZZ, SWALKZ, DROPEVERYTHING, BLOCKING, STOPSAMPLE,
+ CDENDACTOR, DECLARELANGUAGE, RESUMELASTGAME, SHOWMENU, TEMPTALKFONT,
+ TEMPTAGFONT, PLAYMOVIE, HAILSCENE, SETSYSTEMREEL,
+ HIGHEST_LIBCODE
+};
//----------------- LOCAL GLOBAL DATA --------------------
// Saved cursor co-ordinates for control(on) to restore cursor position
// as it was at control(off).
-// They are global so that movecursor(..) has a net effect if it
+// They are global so that MoveCursor(..) has a net effect if it
// precedes control(on).
static int controlX = 0, controlY = 0;
-static int offtype = 0; // used by control()
-static uint32 lastValue = 0; // used by dw_random()
-static int scrollCount = 0; // used by scroll()
+static int offtype = 0; // used by Control()
+static uint32 lastValue = 0; // used by RandomFn()
+static int scrollNumber = 0; // used by scroll()
-static bool NotPointedRunning = false; // Used in printobj and printobjPointed
+static bool bNotPointedRunning = false; // Used in Printobj and PrintObjPointed
static COLORREF s_talkfontColor = 0;
//----------------- FORWARD REFERENCES --------------------
-void resetidletime(void);
-void stopmidi(void);
-void stopsample(void);
-void walk(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, int hold, bool igPath, bool escOn, int myescTime);
+static int HeldObject(void);
+void Offset(EXTREME extreme, int x, int y);
+static void PostTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape);
+void ResetIdleTime(void);
+static void SendTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape, bool *result);
+static void StandTag(int actor, HPOLYGON hp);
+void StopMidiFn(void);
+void StopSample(int sample = -1);
+static void StopWalk(int actor);
+static void WaitScroll(CORO_PARAM, int myescEvent);
+void Walk(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, int hold, bool igPath,
+ int zOverride, bool escOn, int myescTime);
+
+//----------------- SUPPORT FUNCTIONS --------------------
+
+/**
+ * For Scroll() and Offset(), work out top left for a
+ * given screen position.
+ */
+static void DecodeExtreme(EXTREME extreme, int *px, int *py) {
+ int Loffset, Toffset;
+
+ PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
+
+ switch (extreme) {
+ case EX_BOTTOM:
+ *px = Loffset;
+ *py = BgHeight() - SCREEN_HEIGHT;
+ break;
+ case EX_BOTTOMLEFT:
+ *px = 0;
+ *py = BgHeight() - SCREEN_HEIGHT;
+ break;
+ case EX_BOTTOMRIGHT:
+ *px = BgWidth() - SCREEN_WIDTH;
+ *py = BgHeight() - SCREEN_HEIGHT;
+ break;
+ case EX_LEFT:
+ *px = 0;
+ *py = Toffset;
+ break;
+ case EX_RIGHT:
+ *px = BgWidth() - SCREEN_WIDTH;
+ *py = Toffset;
+ break;
+ case EX_TOP:
+ *px = Loffset;
+ *py = 0;
+ break;
+ case EX_TOPLEFT:
+ *px = *py = 0;
+ break;
+ case EX_TOPRIGHT:
+ *px = BgWidth() - SCREEN_WIDTH;
+ *py = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+static void KillSelf(CORO_PARAM) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+ CORO_KILL_SELF();
+
+ CORO_END_CODE;
+}
+
+struct SCROLL_MONITOR {
+ int x;
+ int y;
+ int thisScroll;
+ int myEscape;
+};
+typedef SCROLL_MONITOR *PSCROLL_MONITOR;
+
+/**
+ * Monitor a scrolling, allowing Escape to interrupt it
+ */
+static void ScrollMonitorProcess(CORO_PARAM, const void *param) {
+ int Loffset, Toffset;
+ const SCROLL_MONITOR *psm = (const SCROLL_MONITOR *)param;;
+
+ // COROUTINE
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ do {
+ CORO_SLEEP(1);
+
+ // give up if have been superseded
+ if (psm->thisScroll != scrollNumber)
+ break;
+
+ // If ESCAPE is pressed...
+ if (psm->myEscape != GetEscEvents())
+ {
+ // Instant completion!
+ Offset(EX_USEXY, psm->x, psm->y);
+ break;
+ }
+
+ PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
+
+ } while(Loffset != psm->x || Toffset != psm->y);
+
+ CORO_END_CODE;
+}
/**
* NOT A LIBRARY FUNCTION
*
- * Poke supplied colours into the DAC queue.
+ * Poke supplied colour into the DAC queue.
*/
-static void setTextPal(COLORREF col) {
+void SetTextPal(COLORREF col) {
s_talkfontColor = col;
- UpdateDACqueue(TALKFONT_COL, 1, &s_talkfontColor);
+ SetTalkColourRef(col);
+ UpdateDACqueue(TalkColour(), 1, &s_talkfontColor);
}
-
+/**
+ * Work out a time depending on length of string and
+ * subtitle speed modification.
+ */
static int TextTime(char *pTstring) {
if (isJapanMode())
return JAP_TEXT_TIME;
@@ -198,45 +401,148 @@ static int TextTime(char *pTstring) {
return strlen(pTstring) + ONE_SECOND + (speedText * 5 * ONE_SECOND) / 100;
}
-/*--------------------------------------------------------------------------*/
+/**
+ * KeepOnScreen
+ */
+void KeepOnScreen(POBJECT pText, int *pTextX, int *pTextY) {
+ int shift;
+
+ // Not off the left
+ shift = MultiLeftmost(pText);
+ if (shift < 0) {
+ MultiMoveRelXY(pText, - shift, 0);
+ *pTextX -= shift;
+ }
+
+ // Not off the right
+ shift = MultiRightmost(pText);
+ if (shift > SCREEN_WIDTH) {
+ MultiMoveRelXY(pText, SCREEN_WIDTH - shift, 0);
+ *pTextX += SCREEN_WIDTH - shift;
+ }
+
+ // Not off the top
+ shift = MultiHighest(pText);
+ if (shift < 0) {
+ MultiMoveRelXY(pText, 0, - shift);
+ *pTextY -= shift;
+ }
+
+ // Not off the bottom
+ shift = MultiLowest(pText);
+ if (shift > SCREEN_BOX_HEIGHT2) {
+ MultiMoveRelXY(pText, 0, SCREEN_BOX_HEIGHT2 - shift);
+ *pTextX += SCREEN_WIDTH - shift;
+ }
+}
+
+/**
+ * Waits until the specified process is finished
+ */
+static void FinishWaiting(CORO_PARAM, const INT_CONTEXT *pic, bool *result = NULL) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ while (pic->resumeCode == RES_WAITING)
+ CORO_SLEEP(1);
+
+ if (result)
+ *result = pic->resumeCode == RES_FINISHED;
+ CORO_END_CODE;
+}
+
+void TinGetVersion(WHICH_VER which, char *buffer, int length) {
+
+ if (length > VER_LEN)
+ length = VER_LEN;
+
+ char *cptr = (char *)FindChunk(MASTER_SCNHANDLE, CHUNK_TIME_STAMPS);
+
+ switch (which) {
+ case VER_GLITTER:
+ memcpy(buffer, cptr, length);
+ break;
+
+ case VER_COMPILE:
+ memcpy(buffer, cptr + VER_LEN, length);
+ break;
+ }
+}
+/********************************************************************\
+|***** Library functions *****|
+\********************************************************************/
/**
* Set actor's attributes.
* - currently only the text colour.
*/
-void actorattr(int actor, int r1, int g1, int b1) {
+static void ActorAttr(int actor, int r1, int g1, int b1) {
storeActorAttr(actor, r1, g1, b1);
}
/**
- * Return the actor's direction.
+ * Behave as if actor has walked into a polygon with given brughtness.
*/
-int actordirection(int actor) {
- PMACTOR pActor;
+void ActorBrightness(int actor, int brightness) {
+ PMOVER pMover = GetMover(actor);
- pActor = GetMover(actor);
- assert(pActor != NULL); // not a moving actor
+ assert(pMover != NULL);
+ assert(brightness >= 0 && brightness <= 10);
- return (int)GetMActorDirection(pActor);
+ MoverBrightness(pMover, brightness);
}
/**
- * Return the actor's scale.
+ * Return a moving actor's current direction.
+ */
+static int ActorDirection(int actor) {
+ PMOVER pMover = GetMover(actor);
+ assert(pMover);
+
+ return (int)GetMoverDirection(pMover);
+}
+
+/**
+ * Set actor's palette details for path brightnesses
+ */
+void ActorPalette(int actor, int startColour, int length) {
+ PMOVER pMover = GetMover(actor);
+ assert(pMover);
+
+ StoreMoverPalette(pMover, startColour, length);
+}
+
+/**
+ * Set actor's Z-factor.
*/
-int actorscale(int actor) {
- PMACTOR pActor;
+static void ActorPriority(int actor, int zFactor) {
+ SetActorZfactor(actor, zFactor);
+}
- pActor = GetMover(actor);
- assert(pActor != NULL); // not a moving actor
+/**
+ * Set actor's text colour.
+ */
+static void ActorRGB(int actor, COLORREF colour) {
+ SetActorRGB(actor, colour);
+}
- return (int)GetMActorScale(pActor);
+/**
+ * Return the actor's scale.
+ */
+static int ActorScale(int actor) {
+ PMOVER pMover = GetMover(actor);
+ assert(pMover);
+
+ return (int)GetMoverScale(pMover);
}
/**
* Returns the x or y position of an actor.
*/
-int actorpos(int xory, int actor) {
+static int ActorPos(int xory, int actor) {
int x, y;
GetActorPos(actor, &x, &y);
@@ -246,22 +552,23 @@ int actorpos(int xory, int actor) {
/**
* Make all actors alive at the start of each scene.
*/
-void actorson(void) {
+static void ActorsOn(void) {
setactorson();
}
/**
* Adds an icon to the conversation window.
*/
-void addicon(int icon) {
+static void AddTopic(int icon) {
AddToInventory(INV_CONV, icon, false);
}
/**
* Place the object in inventory 1 or 2.
*/
-void addinv(int invno, int object) {
- assert(invno == INV_1 || invno == INV_2 || invno == INV_OPEN); // illegal inventory number
+static void AddInv(int invno, int object) {
+ // illegal inventory number
+ assert(invno == INV_1 || invno == INV_2 || invno == INV_OPEN || invno == INV_DEFAULT);
AddToInventory(invno, object, false);
}
@@ -269,58 +576,104 @@ void addinv(int invno, int object) {
/**
* Define an actor's walk and stand reels for an auxilliary scale.
*/
-void auxscale(int actor, int scale, SCNHANDLE *rp) {
- PMACTOR pActor;
-
- pActor = GetMover(actor);
- assert(pActor); // Can't set aux scale for a non-moving actor
+static void AuxScale(int actor, int scale, SCNHANDLE *rp) {
+ PMOVER pMover = GetMover(actor);
+ assert(pMover);
int j;
for (j = 0; j < 4; ++j)
- pActor->WalkReels[scale-1][j] = *rp++;
+ pMover->walkReels[scale-1][j] = *rp++;
for (j = 0; j < 4; ++j)
- pActor->StandReels[scale-1][j] = *rp++;
+ pMover->standReels[scale-1][j] = *rp++;
for (j = 0; j < 4; ++j)
- pActor->TalkReels[scale-1][j] = *rp++;
+ pMover->talkReels[scale-1][j] = *rp++;
}
/**
* Defines the background image for a scene.
*/
-void background(SCNHANDLE bfilm) {
- startupBackground(bfilm);
+static void Background(CORO_PARAM, SCNHANDLE bfilm) {
+ StartupBackground(coroParam, bfilm);
+}
+
+/**
+ * Disable dynamic blocking for current scene.
+ */
+void Blocking(bool onOrOff) {
+ SetSysVar(ISV_NO_BLOCKING, !onOrOff);
}
/**
* Sets focus of the scroll process.
*/
-void camera(int actor) {
+static void Camera(int actor) {
ScrollFocus(actor);
}
/**
+ * Sets the CD Change Scene
+ */
+
+static void CdChangeScene(SCNHANDLE hScene) {
+ SetCdChangeScene(hScene);
+}
+
+/**
+ * CdDoChange
+ */
+void CdDoChange(CORO_PARAM) {
+ if (!GotoCD())
+ return;
+
+ CdCD(coroParam);
+ CdHasChanged();
+}
+
+/**
+ * CdEndActor("actor")
+ */
+void CdEndActor(int actor, int myEscape) {
+ PMOVER pMover; // for if it's a moving actor
+
+ // Only do it if escaped!
+ if (myEscape && myEscape != GetEscEvents()) {
+ // End current graphic
+ dwEndActor(actor);
+
+ // un-hide movers
+ pMover = GetMover(actor);
+ if (pMover)
+ UnHideMover(pMover);
+ }
+}
+
+/**
* A CDPLAY() is imminent.
*/
-void cdload(SCNHANDLE start, SCNHANDLE next) {
+static void CDload(SCNHANDLE start, SCNHANDLE next, int myEscape) {
assert(start && next && start != next); // cdload() fault
-// TODO/FIXME
-// LoadExtraGraphData(start, next);
+ if (TinselV2) {
+ if (myEscape && myEscape != GetEscEvents()) {
+ bEscapedCdPlay = true;
+ return;
+ }
+
+ LoadExtraGraphData(start, next);
+ }
}
/**
* Clear the hooked scene (if any)
*/
-
-void clearhookscene() {
- SetHookScene(0, 0, 0);
+static void ClearHookScene() {
+ SetHookScene(0, 0, TRANS_DEF);
}
/**
* Guess what.
*/
-
-void closeinventory(void) {
+static void CloseInventory(void) {
KillInventory();
}
@@ -328,9 +681,29 @@ void closeinventory(void) {
* Turn off cursor and take control from player - and variations on the theme.
* OR Restore cursor and return control to the player.
*/
+void Control(int param) {
+ if (TinselV2) {
+ if (param)
+ ControlOn();
+ else {
+ ControlOff();
+
+ switch (WhichInventoryOpen()) {
+ case INV_1:
+ case INV_2:
+ case INV_MENU:
+ KillInventory();
+ break;
+ default:
+ break;
+ }
+ }
-void control(int param) {
- bEnableF1 = false;
+ return;
+ }
+
+ // Tinsel 1 handling code
+ bEnableMenu = false;
switch (param) {
case CONTROL_STARTOFF:
@@ -385,46 +758,82 @@ void control(int param) {
/**
* Open or close the conversation window.
*/
-
-void conversation(int fn, HPOLYGON hp, bool escOn, int myescEvent) {
+static void Conversation(CORO_PARAM, int fn, HPOLYGON hp, int actor, bool escOn, int myEscape) {
assert(hp != NOPOLY); // conversation() must (currently) be called from a polygon code block
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
- switch (fn) {
- case CONV_END: // Close down conversation
+ CORO_BEGIN_CODE(_ctx);
+
+ if (fn == CONV_END) {
+ // Close down conversation
CloseDownConv();
- break;
+ } else if ((fn == CONV_TOP) || (fn == CONV_DEF) || (fn == CONV_BOTTOM)) {
+ // TOP of screen, Default (i.e. TOP of screen), or BOTTOM of screen
+
+ // If waiting is enabled, wait for ongoing scroll
+ if (TinselV2 && SysVar(SV_CONVERSATIONWAITS))
+ CORO_INVOKE_1(WaitScroll, myEscape);
- case CONV_DEF: // Default (i.e. TOP of screen)
- case CONV_BOTTOM: // BOTTOM of screen
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
- break;
+ if (escOn && myEscape != GetEscEvents())
+ return;
+ // Don't do it if already in a conversation
if (IsConvWindow())
- break;
+ return;
KillInventory();
- convPos(fn);
- ConvPoly(hp);
+
+ if (TinselV2) {
+ // If this is from a tag polygon, get the associated
+ // actor (the one the polygon is named after), if any.
+ if (!actor) {
+ actor = GetTagPolyId(hp);
+ if (actor & ACTORTAG_KEY)
+ actor &= ~ACTORTAG_KEY;
+ else
+ actor = 0;
+ }
+
+ // Top or bottom; tag polygon or tagged actor
+ SetConvDetails((CONV_PARAM)fn, hp, actor);
+ } else {
+ convPos(fn);
+ ConvPoly(hp);
+ }
+
PopUpInventory(INV_CONV); // Conversation window
ConvAction(INV_OPENICON); // CONVERSATION event
- break;
}
+
+ CORO_END_CODE;
}
/**
* Add icon to conversation window's permanent default list.
*/
+static void ConvTopic(int icon) {
+ PermaConvIcon(icon);
+}
-void convicon(int icon) {
- AddIconToPermanentDefaultList(icon);
+/**
+ * Cursor(on/off)
+ */
+void Cursor(int onoff) {
+ if (onoff) {
+ // Re-instate cursor
+ UnHideCursor();
+ } else {
+ // Blank out cursor
+ DwHideCursor();
+ }
}
/**
* Returns the x or y position of the cursor.
*/
-
-int cursorpos(int xory) {
+static int CursorPos(int xory) {
int x, y;
GetCursorXY(&x, &y, true);
@@ -434,8 +843,7 @@ int cursorpos(int xory) {
/**
* Declare conversation window.
*/
-
-void dec_convw(SCNHANDLE text, int MaxContents, int MinWidth, int MinHeight,
+static void DecConvW(SCNHANDLE text, int MaxContents, int MinWidth, int MinHeight,
int StartWidth, int StartHeight, int MaxWidth, int MaxHeight) {
idec_convw(text, MaxContents, MinWidth, MinHeight,
StartWidth, StartHeight, MaxWidth, MaxHeight);
@@ -444,32 +852,28 @@ void dec_convw(SCNHANDLE text, int MaxContents, int MinWidth, int MinHeight,
/**
* Declare config strings.
*/
-
-void dec_cstrings(SCNHANDLE *tp) {
+static void DecCStrings(SCNHANDLE *tp) {
setConfigStrings(tp);
}
/**
* Declare cursor's reels.
*/
-
-void dec_cursor(SCNHANDLE bfilm) {
- DwInitCursor(bfilm);
+static void DecCursor(SCNHANDLE hFilm) {
+ DwInitCursor(hFilm);
}
/**
* Declare the language flags.
*/
-
-void dec_flags(SCNHANDLE hf) {
- setFlagFilms(hf);
+static void DecFlags(SCNHANDLE hFilm) {
+ setFlagFilms(hFilm);
}
/**
* Declare inventory 1's parameters.
*/
-
-void dec_inv1(SCNHANDLE text, int MaxContents,
+static void DecInv1(SCNHANDLE text, int MaxContents,
int MinWidth, int MinHeight,
int StartWidth, int StartHeight,
int MaxWidth, int MaxHeight) {
@@ -480,8 +884,7 @@ void dec_inv1(SCNHANDLE text, int MaxContents,
/**
* Declare inventory 2's parameters.
*/
-
-void dec_inv2(SCNHANDLE text, int MaxContents,
+static void DecInv2(SCNHANDLE text, int MaxContents,
int MinWidth, int MinHeight,
int StartWidth, int StartHeight,
int MaxWidth, int MaxHeight) {
@@ -492,77 +895,104 @@ void dec_inv2(SCNHANDLE text, int MaxContents,
/**
* Declare the bits that the inventory windows are constructed from.
*/
-
-void dec_invw(SCNHANDLE hf) {
+static void DecInvW(SCNHANDLE hf) {
setInvWinParts(hf);
}
/**
- * Declare lead actor.
- * - the actor's id, walk and stand reels for all the regular scales,
- * and the tag text.
+ * DeclareLanguage
*/
+static void DeclareLanguage(int languageId, SCNHANDLE hDescription, SCNHANDLE hFlagFilm) {
+ LanguageFacts(languageId, hDescription, hFlagFilm);
+}
-void dec_lead(uint32 id, SCNHANDLE *rp, SCNHANDLE text) {
- PMACTOR pActor; // Moving actor structure
+/**
+ * Declare lead actor.
+ * @param id Actor Id
+ * @param rp Walk and stand reels for all the regular scales (v1 only)
+ * @param text Tag text (v1 only)
+ */
+static void DecLead(uint32 id, SCNHANDLE *rp = 0, SCNHANDLE text = 0) {
+ PMOVER pMover; // Moving actor structure
- Tag_Actor(id, text, TAG_DEF); // The lead actor is automatically tagged
- setleadid(id); // Establish this as the lead
- SetMover(id); // Establish as a moving actor
+ if (TinselV2) {
+ // Tinsel 2 only specifies the lead actor Id
+ SetLeadId(id);
+ RegisterMover(id);
- pActor = GetMover(id); // Get moving actor structure
- assert(pActor);
+ } else {
- // Store all those reels
- int i, j;
- for (i = 0; i < 5; ++i) {
- for (j = 0; j < 4; ++j)
- pActor->WalkReels[i][j] = *rp++;
- for (j = 0; j < 4; ++j)
- pActor->StandReels[i][j] = *rp++;
- for (j = 0; j < 4; ++j)
- pActor->TalkReels[i][j] = *rp++;
- }
+ Tag_Actor(id, text, TAG_DEF); // The lead actor is automatically tagged
+ SetLeadId(id); // Establish this as the lead
+ RegisterMover(id); // Establish as a moving actor
+
+ pMover = GetMover(id); // Get moving actor structure
+ assert(pMover);
+
+ // Store all those reels
+ int i, j;
+ for (i = 0; i < 5; ++i) {
+ for (j = 0; j < 4; ++j)
+ pMover->walkReels[i][j] = *rp++;
+ for (j = 0; j < 4; ++j)
+ pMover->standReels[i][j] = *rp++;
+ for (j = 0; j < 4; ++j)
+ pMover->talkReels[i][j] = *rp++;
+ }
- for (i = NUM_MAINSCALES; i < TOTAL_SCALES; i++) {
- for (j = 0; j < 4; ++j) {
- pActor->WalkReels[i][j] = pActor->WalkReels[4][j];
- pActor->StandReels[i][j] = pActor->StandReels[2][j];
- pActor->TalkReels[i][j] = pActor->TalkReels[4][j];
+ for (i = NUM_MAINSCALES; i < TOTAL_SCALES; i++) {
+ for (j = 0; j < 4; ++j) {
+ pMover->walkReels[i][j] = pMover->walkReels[4][j];
+ pMover->standReels[i][j] = pMover->standReels[2][j];
+ pMover->talkReels[i][j] = pMover->talkReels[4][j];
+ }
}
}
}
/**
- * Declare the text font.
+ * DecScale("actor", scale, 12*"reel")
+ * Define an actor's walk and stand reels for a scale.
*/
-
-void dec_tagfont(SCNHANDLE hf) {
- TagFontHandle(hf); // Store the font handle
+static void DecScale(int actor, int scale,
+ SCNHANDLE wkl, SCNHANDLE wkr, SCNHANDLE wkf, SCNHANDLE wka,
+ SCNHANDLE stl, SCNHANDLE str, SCNHANDLE stf, SCNHANDLE sta,
+ SCNHANDLE tal, SCNHANDLE tar, SCNHANDLE taf, SCNHANDLE taa)
+{
+ PMOVER pMover = GetMover(actor);
+ assert(pMover);
+
+ SetWalkReels(pMover, scale, wkl, wkr, wkf, wka);
+ SetStandReels(pMover, scale, stl, str, stf, sta);
+ SetTalkReels(pMover, scale, tal, tar, taf, taa);
}
/**
* Declare the text font.
*/
+static void DecTagFont(SCNHANDLE hf) {
+ SetTagFontHandle(hf); // Store the font handle
+}
-void dec_talkfont(SCNHANDLE hf) {
- TalkFontHandle(hf); // Store the font handle
+/**
+ * Declare the text font.
+ */
+static void DecTalkFont(SCNHANDLE hf) {
+ SetTalkFontHandle(hf); // Store the font handle
}
/**
* Remove an icon from the conversation window.
*/
-
-void delicon(int icon) {
+static void DelIcon(int icon) {
RemFromInventory(INV_CONV, icon);
}
/**
* Delete the object from inventory 1 or 2.
*/
-
-void delinv(int object) {
+static void DelInv(int object) {
if (!RemFromInventory(INV_1, object)) // Remove from inventory 1...
RemFromInventory(INV_2, object); // ...or 2 (whichever)
@@ -570,18 +1000,119 @@ void delinv(int object) {
}
/**
- * enablef1
+ * DelTopic
*/
+static void DelTopic(int icon) {
+ RemFromInventory(INV_CONV, icon);
+}
-void enablef1(void) {
- bEnableF1 = true;
+/**
+ * DimMusic
+ */
+static void DimMusic(void) {
+ _vm->_pcmMusic->dim(true);
}
/**
- * fademidi(in/out)
+ * Delete the object from inventory 1 or 2.
+ */
+static void Drop(int object) {
+ if (object == -1)
+ object = HeldObject();
+
+ if (!RemFromInventory(INV_1, object)) // Remove from inventory 1...
+ RemFromInventory(INV_2, object); // ...or 2 (whichever)
+
+ DropItem(object); // Stop holding it
+}
+
+/**
+ * Delete all objects from inventory 1 and 2.
+ */
+static void DropEverything(void) {
+ HoldItem(NOOBJECT, false);
+
+ ClearInventory(INV_1);
+ ClearInventory(INV_2);
+}
+
+/**
+ * EnableMenu
+ */
+static void EnableMenu(void) {
+ bEnableMenu = true;
+}
+
+/**
+ * Kill an actor's current graphics.
*/
+static void EndActor(int actor) {
+ dwEndActor(actor);
+}
+
+/**
+ * Get the actor to look at the polygon.
+ * If the actor is at the tag, do a StandTag().
+ */
+static void FaceTag(int actor, HPOLYGON hp) {
+ PMOVER pMover; // Moving actor structure
+ int nowx, nowy;
+ int nodex, nodey;
+
+ assert(hp != NOPOLY);
-void fademidi(CORO_PARAM, int inout) {
+ /*
+ * Get which moving actor it is
+ */
+ pMover = GetMover(actor);
+ assert(pMover);
+ if (MoverHidden(pMover))
+ return;
+
+ /*
+ * Stop the actor
+ */
+ StopWalk(actor);
+
+ /*
+ * Face the tag
+ */
+ // See where node is and where actor is
+ GetPolyNode(hp, &nodex, &nodey);
+ GetActorPos(actor, &nowx, &nowy);
+
+ if (nowx == nodex && nowy == nodey) {
+ // Stood at the tag, don't face in silly direction
+ StandTag(actor, hp);
+ } else {
+ // Look towards polygon
+ GetPolyMidBottom(hp, &nodex, &nodey);
+ SetMoverDirection(pMover, GetDirection(nowx, nowy,
+ nodex, nodey,
+ GetMoverDirection(pMover),
+ NOPOLY, YB_X1_5));
+ SetMoverStanding(pMover);
+ }
+}
+
+/**
+ * FadeIn
+ */
+static void FadeIn(void) {
+ FadeInMedium(NULL);
+}
+
+/**
+ * FadeOut
+ */
+static void FadeOut(void) {
+ FadeOutMedium(NULL);
+}
+
+/**
+ * FadeMidi(in/out)
+ */
+static void FadeMidi(CORO_PARAM, int inout) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -595,82 +1126,159 @@ void fademidi(CORO_PARAM, int inout) {
}
/**
- * Guess what.
+ * Freeze the cursor, or not.
*/
+static void FreezeCursor(bool bFreeze) {
+ DoFreezeCursor(bFreeze);
+}
-int getinvlimit(int invno) {
+/**
+ * Guess what.
+ */
+static int GetInvLimit(int invno) {
return InvGetLimit(invno);
}
/**
+ * Ghost
+ */
+static void Ghost(int actor, int tColour, int tPalOffset) {
+ SetSysVar(ISV_GHOST_ACTOR, actor);
+ SetSysVar(ISV_GHOST_COLOUR, tColour);
+ SetSysVar(ISV_GHOST_BASE, tPalOffset);
+ CreateGhostPalette(BgPal());
+}
+
+/**
+ *
+ */
+static void HailScene(SCNHANDLE scene) {
+ DoHailScene(scene);
+}
+
+/**
* Returns TRUE if the game has been restarted, FALSE if not.
*/
-bool hasrestarted(void) {
+static bool HasRestarted(void) {
return bHasRestarted;
}
/**
- * Returns which object is currently held.
+ * See if an object is in the inventory.
*/
+int Have(int object) {
+ return (InventoryPos(object) != NOOBJECT);
+}
-int heldobject(void) {
+/**
+ * Returns which object is currently held.
+ */
+static int HeldObject(void) {
return WhichItemHeld();
}
/**
- * Removes a player from the screen, probably when he's about to be
- * replaced by an animation.
- *
- * Not believed to work anymore! (hide() is not used).
+ * Hides the specified actor
*/
+static void HideActorFn(CORO_PARAM, int ano) {
+ HideActor(coroParam, ano);
+}
-void hide(int actor) {
- HideActor(actor);
+/**
+ * Turn a blocking polygon off.
+ */
+static void HideBlock(int block) {
+ DisableBlock(block);
+}
+
+/**
+ * Turn an effect polygon off.
+ */
+static void HideEffect(int effect) {
+ DisableEffect(effect);
+}
+
+/**
+ * Turn a path polygon off.
+ */
+static void HidePath(int path) {
+ DisablePath(path);
+}
+
+/**
+ * Turn a refer polygon off.
+ */
+static void HideRefer(int refer) {
+ DisableRefer(refer);
+}
+
+/**
+ * Turn a tag polygon off.
+ */
+static void HideTag(CORO_PARAM, int tag, HPOLYGON hp) {
+ // Tag could be zero, meaning calling tag
+ DisableTag(coroParam, tag ? tag : GetTagPolyId(hp));
}
/**
- * hookscene(scene, entrance, transition)
+ * Hold the specified object.
*/
+static void Hold(int object) {
+ HoldItem(object, false);
+}
-void hookscene(SCNHANDLE scene, int entrance, int transition) {
+/**
+ * HookScene(scene, entrance, transition)
+ */
+void HookScene(SCNHANDLE scene, int entrance, int transition) {
SetHookScene(scene, entrance, transition);
}
/**
- * idletime
+ * IdleTime
*/
+static int IdleTime(void) {
+ // If control is off, system is not idle
+ if (!ControlIsOn()) {
+ // Player doesn't currently have control
+ ResetIdleTime();
-int idletime(void) {
- uint32 x;
+ return 0;
+ } else {
+ // Player has control - return time since last event
+ int x = getUserEventTime() / ONE_SECOND;
- x = getUserEventTime() / ONE_SECOND;
-
- if (!TestToken(TOKEN_CONTROL))
- resetidletime();
+ return x;
+ }
+}
- return (int)x;
+/**
+ * Set flag if InstantScroll(on), reset if InstantScroll(off)
+ */
+void InstantScroll(int onoff) {
+ bInstantScroll = (onoff != 0);
}
/**
* invdepict
*/
-void invdepict(int object, SCNHANDLE hFilm) {
- invObjectFilm(object, hFilm);
+static void InvDepict(int object, SCNHANDLE hFilm) {
+ SetObjectFilm(object, hFilm);
}
/**
* See if an object is in the inventory.
*/
-int ininventory(int object) {
+int InInventory(int object) {
return (InventoryPos(object) != INV_NOICON);
}
/**
* Open an inventory.
*/
-void inventory(int invno, bool escOn, int myescEvent) {
+static void Inventory(int invno, bool escOn, int myEscape) {
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
assert((invno == INV_1 || invno == INV_2)); // Trying to open illegal inventory
@@ -679,9 +1287,16 @@ void inventory(int invno, bool escOn, int myescEvent) {
}
/**
+ * Alter inventory object's icon.
+ */
+static void InvPlay(int object, SCNHANDLE hFilm) {
+ SetObjectFilm(object, hFilm);
+}
+
+/**
* See if an object is in the inventory.
*/
-int inwhichinv(int object) {
+static int InWhichInv(int object) {
if (WhichItemHeld() == object)
return 0;
@@ -697,45 +1312,59 @@ int inwhichinv(int object) {
/**
* Kill an actor.
*/
-void killactor(int actor) {
+static void KillActor(int actor) {
DisableActor(actor);
}
/**
* Turn a blocking polygon off.
*/
-void killblock(int block) {
+static void KillBlock(int block) {
DisableBlock(block);
}
/**
* Turn an exit off.
*/
-void killexit(int exit) {
+static void KillExit(int exit) {
DisableExit(exit);
}
/**
* Turn a tag off.
*/
-void killtag(int tagno) {
- DisableTag(tagno);
+static void KillTag(CORO_PARAM, int tagno) {
+ DisableTag(coroParam, tagno);
+}
+
+/**
+ * Kills the specified global process
+ */
+static void KillGlobalProcess(uint32 procID) {
+ xKillGlobalProcess(procID);
+}
+
+/**
+ * Kills the specified process
+ */
+static void KillProcess(uint32 procID) {
+ KillSceneProcess(procID);
}
/**
* Returns the left or top offset of the screen.
*/
-int ltoffset(int lort) {
+static int LToffset(int lort) {
int Loffset, Toffset;
PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
- return (lort == LEFTOFFSET) ? Loffset : Toffset;
+ return (lort == SCREENXPOS) ? Loffset : Toffset;
}
/**
* Set new cursor position.
*/
-void movecursor(int x, int y) {
+static void MoveCursor(int x, int y) {
SetCursorXY(x, y);
controlX = x; // Save these values so that
@@ -743,29 +1372,45 @@ void movecursor(int x, int y) {
}
/**
+ * MoveTag(tag, x, y)
+ */
+void MoveTag(int tag, int x, int y, HPOLYGON hp) {
+ // Tag could be zero, meaning calling tag
+ MovePolygon(TAG, tag ? tag : GetTagPolyId(hp), x, y);
+}
+
+/**
+ * MoveTagTo(tag, x, y)
+ */
+void MoveTagTo(int tag, int x, int y, HPOLYGON hp) {
+ // Tag could be zero, meaning calling tag
+ MovePolygonTo(TAG, tag ? tag : GetTagPolyId(hp), x, y);
+}
+
+/**
* Triggers change to a new scene.
*/
-void newscene(CORO_PARAM, SCNHANDLE scene, int entrance, int transition) {
+void NewScene(CORO_PARAM, SCNHANDLE scene, int entrance, int transition) {
// COROUTINE
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
-#ifdef BODGE
- if (!ValidHandle(scene)) {
- scene = GetSceneHandle();
- entrance = 1;
+ if (TinselV2) {
+ if (MoviePlaying()) {
+ AbortMovie();
+ CORO_SLEEP(2);
+ }
}
- assert(scene); // Non-existant first scene!
-#endif
SetNewScene(scene, entrance, transition);
-#if 1
// Prevent tags and cursor re-appearing
- GetControl(CONTROL_STARTOFF);
-#endif
+ if (TinselV2)
+ ControlStartOff();
+ else
+ GetControl(CONTROL_STARTOFF);
// Prevent code subsequent to this call running before scene changes
if (g_scheduler->getCurrentPID() != PID_MASTER_SCR)
@@ -776,47 +1421,78 @@ void newscene(CORO_PARAM, SCNHANDLE scene, int entrance, int transition) {
/**
* Disable dynamic blocking for current scene.
*/
-void noblocking(void) {
- bNoBlocking = true;
+static void NoBlocking(void) {
+ SetNoBlocking(true);
}
/**
* Define a no-scroll boundary for the current scene.
*/
-void noscroll(int x1, int y1, int x2, int y2) {
+static void NoScroll(int x1, int y1, int x2, int y2) {
SetNoScroll(x1, y1, x2, y2);
}
/**
* Hold the specified object.
*/
-void objectheld(int object) {
+static void ObjectHeld(int object) {
HoldItem(object);
}
/**
* Set the top left offset of the screen.
*/
-void offset(int x, int y) {
+void Offset(EXTREME extreme, int x, int y) {
KillScroll();
+
+ if (TinselV2)
+ DecodeExtreme(extreme, &x, &y);
+
PlayfieldSetPos(FIELD_WORLD, x, y);
}
/**
+ * OtherObject()
+ */
+int OtherObject(INV_OBJECT *pinvo) {
+ assert(pinvo != NULL);
+
+ // return held object or object clicked on - whichever is not the calling object
+
+ // pinvo->id is the calling object
+ // WhichItemHeld() gives the held object
+ // GetIcon() gives the object clicked on
+
+ assert(GetIcon() == pinvo->id || WhichItemHeld() == pinvo->id);
+
+ if (GetIcon() == pinvo->id)
+ return WhichItemHeld();
+ else
+ return GetIcon();
+}
+
+/**
* Play a film.
*/
-void play(CORO_PARAM, SCNHANDLE film, int x, int y, int compit, int actorid, bool splay, int sfact,
- bool escOn, int myescEvent, bool bTop) {
+static void Play(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int compit, int actorid, bool splay, int sfact,
+ bool escOn, int myEscape, bool bTop) {
+ assert(hFilm != 0); // play(): Trying to play NULL film
+
// COROUTINE
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- assert(film != 0); // play(): Trying to play NULL film
+
+ // Don't do CDPlay() for now if already escaped
+ if (bEscapedCdPlay) {
+ bEscapedCdPlay = false;
+ return;
+ }
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
// If this actor is dead, call a stop to the calling process
@@ -825,24 +1501,75 @@ void play(CORO_PARAM, SCNHANDLE film, int x, int y, int compit, int actorid, boo
// 7/4/95
if (!escOn)
- myescEvent = GetEscEvents();
+ myEscape = GetEscEvents();
if (compit == 1) {
// Play to completion before returning
- CORO_INVOKE_ARGS(playFilmc, (CORO_SUBCTX, film, x, y, actorid, splay, sfact, escOn, myescEvent, bTop));
+ CORO_INVOKE_ARGS(PlayFilmc, (CORO_SUBCTX, hFilm, x, y, actorid, splay, sfact, escOn, myEscape, bTop));
} else if (compit == 2) {
error("play(): compit == 2 - please advise John");
} else {
// Kick off the play and return.
- playFilm(film, x, y, actorid, splay, sfact, escOn, myescEvent, bTop);
+ CORO_INVOKE_ARGS(PlayFilm, (CORO_SUBCTX, hFilm, x, y, actorid, splay, sfact, escOn, myEscape, bTop));
+ }
+ CORO_END_CODE;
+}
+
+/**
+ * Play a film
+ */
+static void Play(CORO_PARAM, SCNHANDLE hFilm, int x, int y, bool bComplete, int myEscape,
+ bool bTop, TINSEL_EVENT event, HPOLYGON hPoly, int taggedActor) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ assert(hFilm != 0);
+
+ // Don't do CdPlay() for now if already escaped
+ if (bEscapedCdPlay) {
+ bEscapedCdPlay = false;
+ return;
+ }
+
+ if (event == TALKING) {
+ int actor;
+ if (hPoly == NOPOLY) {
+ // Must be a tagged actor
+
+ assert(taggedActor && IsTaggedActor(taggedActor));
+ actor = taggedActor;
+ } else if (taggedActor == 0) {
+ // Must be a polygon with an actor ID
+ actor = GetTagPolyId(hPoly);
+ assert(actor & ACTORTAG_KEY);
+ actor &= ~ACTORTAG_KEY;
+ }
+ else {
+ return;
+ }
+
+ SetActorTalking(actor, true);
+ SetActorTalkFilm(actor, hFilm);
+ }
+
+ if (bComplete) {
+ // Play to completion before returning
+ CORO_INVOKE_ARGS(PlayFilmc, (CORO_SUBCTX, hFilm, x, y, 0, false, false, myEscape != 0, myEscape, bTop));
+ } else {
+ // Kick off the play and return.
+ CORO_INVOKE_ARGS(PlayFilm, (CORO_SUBCTX, hFilm, x, y, myEscape, bTop));
}
+
CORO_END_CODE;
}
+
/**
* Play a midi file.
*/
-void playmidi(CORO_PARAM, SCNHANDLE hMidi, int loop, bool complete) {
+static void PlayMidi(CORO_PARAM, SCNHANDLE hMidi, int loop, bool complete) {
// FIXME: This is a workaround for the FIXME below
if (GetMidiVolume() == 0)
return;
@@ -877,9 +1604,48 @@ void playmidi(CORO_PARAM, SCNHANDLE hMidi, int loop, bool complete) {
}
/**
+ * Plays a movie
+ */
+
+static void PlayMovie(CORO_PARAM, SCNHANDLE hFileStem, int myEscape) {
+ CORO_BEGIN_CONTEXT;
+ int i;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ if (myEscape && myEscape != GetEscEvents())
+ return;
+
+ // Get rid of the cursor
+ for (_ctx->i = 0; _ctx->i < 3; _ctx->i++) {
+ DwHideCursor();
+ DropCursor();
+ CORO_SLEEP(1);
+ }
+
+ // They claim to be getting "Can't play two movies at once!" error
+ while (MoviePlaying())
+ CORO_SLEEP(1);
+
+ // Play the movie
+ CORO_INVOKE_2(PlayBMV, hFileStem, myEscape);
+
+ CORO_END_CODE;
+}
+
+/**
+ * Play some music
+ */
+static void PlayMusic(int tune) {
+ _vm->_pcmMusic->startPlay(tune);
+}
+
+/**
* Play a sample.
+ * Tinsel 1 version
*/
-void playsample(CORO_PARAM, int sample, bool complete, bool escOn, int myescEvent) {
+static void PlaySample(CORO_PARAM, int sample, bool bComplete, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
Audio::SoundHandle handle;
CORO_END_CONTEXT(_ctx);
@@ -890,7 +1656,7 @@ void playsample(CORO_PARAM, int sample, bool complete, bool escOn, int myescEven
return;
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents()) {
+ if (escOn && myEscape != GetEscEvents()) {
_vm->_sound->stopAllSamples(); // Stop any currently playing sample
return;
}
@@ -898,10 +1664,10 @@ void playsample(CORO_PARAM, int sample, bool complete, bool escOn, int myescEven
if (volSound != 0 && _vm->_sound->sampleExists(sample)) {
_vm->_sound->playSample(sample, Audio::Mixer::kSFXSoundType, &_ctx->handle);
- if (complete) {
+ if (bComplete) {
while (_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
// Abort if escapable and ESCAPE is pressed
- if (escOn && myescEvent != GetEscEvents()) {
+ if (escOn && myEscape != GetEscEvents()) {
_vm->_mixer->stopHandle(_ctx->handle);
break;
}
@@ -917,28 +1683,153 @@ void playsample(CORO_PARAM, int sample, bool complete, bool escOn, int myescEven
}
/**
- * Play a sample.
+ * Play a sample
+ * Tinsel 2 version
*/
-void tryplaysample(CORO_PARAM, int sample, bool complete, bool escOn, int myescEvent) {
+static void PlaySample(CORO_PARAM, int sample, int x, int y, int flags, int myEscape) {
+ int priority;
CORO_BEGIN_CONTEXT;
+ Audio::SoundHandle handle;
+ int myEscape;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- // Don't do it if it's not appropriate
- if (_vm->_sound->sampleIsPlaying()) {
- // return, but prevent Glitter lock-up
- CORO_SLEEP(1);
+
+ _ctx->myEscape = myEscape;
+
+ // Not escapable if PlaySample(..., s)
+ if (flags & PS_SUSTAIN) {
+ _ctx->myEscape = 0;
+ priority = PRIORITY_SPLAY2;
+ } else {
+ priority = PRIORITY_SPLAY1;
+ }
+
+ // Don't do anything if it's already been escaped
+ if (_ctx->myEscape && _ctx->myEscape != GetEscEvents())
return;
+
+ if (volSound != 0 && _vm->_sound->sampleExists(sample)) {
+ if (x == 0)
+ x = -1;
+
+ _vm->_sound->playSample(sample, 0, false, x, y, priority, Audio::Mixer::kSFXSoundType,
+ &_ctx->handle);
+
+ if (flags & PS_COMPLETE) {
+ while (_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
+ // Abort if escapable and ESCAPE is pressed
+ if (_ctx->myEscape && _ctx->myEscape != GetEscEvents()) {
+ _vm->_mixer->stopHandle(_ctx->handle);
+ break;
+ }
+
+ CORO_SLEEP(1);
+ }
+ }
+ } else {
+ // Prevent Glitter lock-up
+ CORO_SLEEP(1);
}
- CORO_INVOKE_ARGS(playsample, (CORO_SUBCTX, sample, complete, escOn, myescEvent));
CORO_END_CODE;
}
/**
+ * Move the cursor to the tagged actor's tag point.
+ */
+void PointActor(int actor) {
+ int x, y;
+
+ // Only do this if the function is enabled
+ if (!SysVar(SV_ENABLEPOINTTAG))
+ return;
+
+ assert(IsTaggedActor(actor));
+
+ GetActorTagPos(actor, &x, &y, true);
+
+ _vm->setMousePosition(Common::Point(x, y));
+}
+
+/**
+ * Move the cursor to the tag's tag point.
+ */
+static void PointTag(int tagno, HPOLYGON hp) {
+ int x, y;
+ SCNHANDLE junk;
+
+ // Only do this if the function is enabled
+ if (!SysVar(SV_ENABLEPOINTTAG))
+ return;
+
+ // Tag could be zero, meaning calling tag
+ if (tagno == 0)
+ tagno = GetTagPolyId(hp);
+
+ GetTagTag(GetTagHandle(tagno), &junk, &x, &y);
+
+ _vm->setMousePosition(Common::Point(x, y));
+}
+
+/**
+ * PostActor("actor", event)
+ */
+static void PostActor(CORO_PARAM, int actor, TINSEL_EVENT event, HPOLYGON hp,
+ int taggedActor, int myEscape) {
+ if (actor == -1) {
+ actor = taggedActor;
+ assert(hp == NOPOLY && taggedActor);
+ assert(IsTaggedActor(actor));
+ }
+
+ if (IsTaggedActor(actor)) {
+ assert(actor);
+ ActorEvent(coroParam, actor, event, false, myEscape);
+ } else {
+ PostTag(coroParam, actor | ACTORTAG_KEY, event, hp, myEscape);
+ }
+}
+
+/**
+ * PostGlobalProcess(process#, event)
+ */
+static void PostGlobalProcess(CORO_PARAM, int procId, TINSEL_EVENT event, int myEscape) {
+ GlobalProcessEvent(coroParam, procId, event, false, myEscape);
+}
+
+/**
+ * PostObject(object, event)
+ */
+static void PostObject(CORO_PARAM, int object, TINSEL_EVENT event, int myEscape) {
+ ObjectEvent(coroParam, object, event, false, myEscape);
+}
+
+/**
+ * PostProcess(process#, event)
+ */
+static void PostProcess(CORO_PARAM, int procId, TINSEL_EVENT event, int myEscape) {
+ SceneProcessEvent(coroParam, procId, event, false, myEscape);
+}
+
+/**
+ * Posts an event to a specified tag
+ */
+static void PostTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape) {
+ // Tag could be zero, meaning calling tag
+ if (tagno == 0) {
+ assert(hp != NOPOLY);
+ PolygonEvent(coroParam, hp, event, 0, false, myEscape);
+ } else {
+ assert(IsTagPolygon(tagno));
+ PolygonEvent(coroParam, GetTagHandle(tagno), event, 0, false, myEscape);
+ }
+}
+
+/**
* Trigger pre-loading of a scene's data.
*/
-void preparescene(SCNHANDLE scene) {
+static void PrepareScene(SCNHANDLE scene) {
#ifdef BODGE
if (!ValidHandle(scene))
return;
@@ -947,11 +1838,11 @@ void preparescene(SCNHANDLE scene) {
/**
* Print the given text at the given place for the given time.
- *
- * Print(....., h) -> hold = 1 (not used)
- * Print(....., s) -> hold = 2 (sustain)
*/
-void print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, int hold, bool escOn, int myescEvent) {
+static void Print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, bool bSustain, bool escOn, int myEscape) {
+ if (TinselV2)
+ escOn = myEscape != 0;
+
CORO_BEGIN_CONTEXT;
OBJECT *pText; // text object pointer
int myleftEvent;
@@ -969,37 +1860,55 @@ void print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, int hold, bool es
_ctx->bSample = false;
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
- // Kick off the voice sample
- if (volVoice != 0 && _vm->_sound->sampleExists(text)) {
- _vm->_sound->playSample(text, Audio::Mixer::kSpeechSoundType, &_ctx->handle);
- _ctx->bSample = _vm->_mixer->isSoundHandleActive(_ctx->handle);
+ if (!TinselV2) {
+ // Kick off the voice sample
+ if (volVoice != 0 && _vm->_sound->sampleExists(text)) {
+ _vm->_sound->playSample(text, Audio::Mixer::kSpeechSoundType, &_ctx->handle);
+ _ctx->bSample = _vm->_mixer->isSoundHandleActive(_ctx->handle);
+ }
}
+ // Get the string
+ LoadStringRes(text, TextBufferAddr(), TBUFSZ);
+
// Calculate display time
- LoadStringRes(text, tBufferAddr(), TBUFSZ);
bJapDoPrintText = false;
if (time == 0) {
// This is a 'talky' print
- _ctx->time = TextTime(tBufferAddr());
+ _ctx->time = TextTime(TextBufferAddr());
// Cut short-able if sustain was not set
- _ctx->myleftEvent = (hold == 2) ? 0 : GetLeftEvents();
+ _ctx->myleftEvent = bSustain ? 0 : GetLeftEvents();
} else {
_ctx->time = time * ONE_SECOND;
- _ctx->myleftEvent = 0;
+ _ctx->myleftEvent = (TinselV2 && !bSustain) ? GetLeftEvents() : 0;
if (isJapanMode())
bJapDoPrintText = true;
}
// Print the text
- if (bJapDoPrintText || (!isJapanMode() && (bSubtitles || !_ctx->bSample))) {
+ if (TinselV2) {
+ int Loffset, Toffset;
+ PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
+ _ctx->pText = ObjectTextOut(nullContext, GetPlayfieldList(FIELD_STATUS),
+ TextBufferAddr(), 0, x - Loffset, y - Toffset, GetTagFontHandle(),
+ TXT_CENTRE, 0);
+ assert(_ctx->pText);
+
+ // Adjust x, y, or z if necessary
+ KeepOnScreen(_ctx->pText, &x, &y);
+ if (IsTopWindow())
+ MultiSetZPosition(_ctx->pText, Z_TOPW_TEXT);
+
+ } else if (bJapDoPrintText || (!isJapanMode() && (bSubtitles || !_ctx->bSample))) {
int Loffset, Toffset; // Screen position
PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
- _ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), tBufferAddr(),
- 0, x - Loffset, y - Toffset, hTalkFontHandle(), TXT_CENTRE);
+ _ctx->pText = ObjectTextOut(coroParam, GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
+ 0, x - Loffset, y - Toffset,
+ TinselV2 ? GetTagFontHandle() : GetTalkFontHandle(), TXT_CENTRE);
assert(_ctx->pText); // string produced NULL text
if (IsTopWindow())
MultiSetZPosition(_ctx->pText, Z_TOPW_TEXT);
@@ -1009,14 +1918,14 @@ void print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, int hold, bool es
*/
int shift;
shift = MultiRightmost(_ctx->pText) + 2;
- if (shift >= BackgroundWidth()) // Not off right
- MultiMoveRelXY(_ctx->pText, BackgroundWidth() - shift, 0);
+ if (shift >= BgWidth()) // Not off right
+ MultiMoveRelXY(_ctx->pText, BgWidth() - shift, 0);
shift = MultiLeftmost(_ctx->pText) - 1;
if (shift <= 0) // Not off left
MultiMoveRelXY(_ctx->pText, -shift, 0);
shift = MultiLowest(_ctx->pText);
- if (shift > BackgroundHeight()) // Not off bottom
- MultiMoveRelXY(_ctx->pText, 0, BackgroundHeight() - shift);
+ if (shift > BgHeight()) // Not off bottom
+ MultiMoveRelXY(_ctx->pText, 0, BgHeight() - shift);
}
// Give up if nothing printed and no sample
@@ -1024,37 +1933,50 @@ void print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, int hold, bool es
return;
// Leave it up until time runs out or whatever
- _ctx->timeout = SAMPLETIMEOUT;
- do {
- CORO_SLEEP(1);
+ if (TinselV2) {
+ do {
+ CORO_SLEEP(1);
- // Abort if escapable and ESCAPE is pressed
- // Abort if left click - hardwired feature for talky-print!
- // Will be ignored if myleftevent happens to be 0!
- // Abort if sample times out
- if ((escOn && myescEvent != GetEscEvents())
- || (_ctx->myleftEvent && _ctx->myleftEvent != GetLeftEvents())
- || (_ctx->bSample && --_ctx->timeout <= 0))
- break;
+ // Cancelled?
+ if ( (myEscape && myEscape != GetEscEvents())
+ || (!bSustain && LeftEventChange(_ctx->myleftEvent)))
+ break;
- if (_ctx->bSample) {
- // Wait for sample to end whether or not
- if (!_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
- if (_ctx->pText == NULL || speedText == DEFTEXTSPEED) {
- // No text or speed modification - just depends on sample
- break;
- } else {
- // Must wait for time
- _ctx->bSample = false;
+ } while (_ctx->time-- >= 0);
+
+ } else {
+ _ctx->timeout = SAMPLETIMEOUT;
+ do {
+ CORO_SLEEP(1);
+
+ // Abort if escapable and ESCAPE is pressed
+ // Abort if left click - hardwired feature for talky-print!
+ // Will be ignored if myleftevent happens to be 0!
+ // Abort if sample times out
+ if ((escOn && myEscape != GetEscEvents())
+ || (_ctx->myleftEvent && _ctx->myleftEvent != GetLeftEvents())
+ || (_ctx->bSample && --_ctx->timeout <= 0))
+ break;
+
+ if (_ctx->bSample) {
+ // Wait for sample to end whether or not
+ if (!_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
+ if (_ctx->pText == NULL || speedText == DEFTEXTSPEED) {
+ // No text or speed modification - just depends on sample
+ break;
+ } else {
+ // Must wait for time
+ _ctx->bSample = false;
+ }
}
+ } else {
+ // No sample - just depends on time
+ if (_ctx->time-- <= 0)
+ break;
}
- } else {
- // No sample - just depends on time
- if (_ctx->time-- <= 0)
- break;
- }
- } while (1);
+ } while (1);
+ }
// Delete the text
if (_ctx->pText != NULL)
@@ -1065,84 +1987,228 @@ void print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, int hold, bool es
}
-static void printobjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, OBJECT *&pText, const int textx, const int texty, const int item);
-static void printobjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *pText);
+static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, OBJECT *&pText, const int textx, const int texty, const int item);
+static void PrintObjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *pText);
/**
* Print the given inventory object's name or whatever.
*/
-void printobj(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, const int event) {
+static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo, const int event, int myEscape) {
CORO_BEGIN_CONTEXT;
OBJECT *pText; // text object pointer
int textx, texty;
int item;
+ bool bSample;
+ int sub;
+ Audio::SoundHandle handle;
+ int ticks;
+ int timeout;
+ bool bTookControl;
+ int myEscape;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- assert(pinvo != 0); // printobj() may only be called from an object code block
+ assert(pinvo != 0); // PrintObj() may only be called from an object code block
+ _ctx->myEscape = myEscape;
- if (text == (SCNHANDLE)-1) { // 'OFF'
- NotPointedRunning = true;
+ if (hText == (SCNHANDLE)-1) { // 'OFF'
+ bNotPointedRunning = true;
return;
}
- if (text == (SCNHANDLE)-2) { // 'ON'
- NotPointedRunning = false;
+ if (hText == (SCNHANDLE)-2) { // 'ON'
+ bNotPointedRunning = false;
return;
}
+ // Don't do it if it's not wanted
+ if (TinselV2 && (myEscape) && (myEscape != GetEscEvents()))
+ return;
+
+ /*
+ * Find out which icon the cursor is over, and where to put the text.
+ */
GetCursorXY(&_ctx->textx, &_ctx->texty, false); // Cursor position..
_ctx->item = InvItem(&_ctx->textx, &_ctx->texty, true); // ..to text position
-
if (_ctx->item == INV_NOICON)
return;
+ /*
+ * POINT/other event PrintObj() arbitration...
+ */
if (event != POINTED) {
- NotPointedRunning = true; // Get POINTED text to die
+ bNotPointedRunning = true; // Get POINTED text to die
CORO_SLEEP(1); // Give it chance to
- } else
- NotPointedRunning = false; // There may have been an OFF without an ON
+ } else if (!TinselV2)
+ bNotPointedRunning = false; // There may have been an OFF without an ON
- // Display the text and set it's Z position
- if (event == POINTED || (!isJapanMode() && (bSubtitles || !_vm->_sound->sampleExists(text)))) {
- int xshift;
+ // Make multi-ones escape
+ if (TinselV2 && (SubStringCount(hText) > 1) && !_ctx->myEscape)
+ _ctx->myEscape = GetEscEvents();
- LoadStringRes(text, tBufferAddr(), TBUFSZ); // The text string
- _ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), tBufferAddr(),
- 0, _ctx->textx, _ctx->texty, hTagFontHandle(), TXT_CENTRE);
- assert(_ctx->pText); // printobj() string produced NULL text
- MultiSetZPosition(_ctx->pText, Z_INV_ITEXT);
+ // Loop once for Tinsel 1 strings, and for Tinsel 2 however many lines are needed
+ for (_ctx->sub = 0; _ctx->sub < (TinselV2 ? SubStringCount(hText) : 1); _ctx->sub++) {
+ if (_ctx->myEscape && _ctx->myEscape != GetEscEvents())
+ break;
- // Don't go off the side of the screen
- xshift = MultiLeftmost(_ctx->pText);
- if (xshift < 0) {
- MultiMoveRelXY(_ctx->pText, - xshift, 0);
- _ctx->textx -= xshift;
+ if (!_vm->_sound->sampleExists(hText))
+ _ctx->bSample = false;
+ else {
+ // Kick off the voice sample
+ _vm->_sound->playSample(hText, _ctx->sub, false, -1, -1, PRIORITY_TALK,
+ Audio::Mixer::kSpeechSoundType, &_ctx->handle);
+ _ctx->bSample = true;
}
- xshift = MultiRightmost(_ctx->pText);
- if (xshift > SCREEN_WIDTH) {
- MultiMoveRelXY(_ctx->pText, SCREEN_WIDTH - xshift, 0);
- _ctx->textx += SCREEN_WIDTH - xshift;
+
+ // Display the text and set it's Z position
+ if (event == POINTED || (!isJapanMode() && (bSubtitles || !_ctx->bSample))) {
+ int xshift;
+
+ // Get the text string
+ if (TinselV2)
+ LoadSubString(hText, _ctx->sub, TextBufferAddr(), TBUFSZ);
+ else
+ LoadStringRes(hText, TextBufferAddr(), TBUFSZ);
+
+ _ctx->pText = ObjectTextOut(coroParam, GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
+ 0, _ctx->textx, _ctx->texty, GetTagFontHandle(), TXT_CENTRE);
+ assert(_ctx->pText); // PrintObj() string produced NULL text
+
+ MultiSetZPosition(_ctx->pText, Z_INV_ITEXT);
+
+ if (TinselV2)
+ KeepOnScreen(_ctx->pText, &_ctx->textx, &_ctx->texty);
+ else {
+ // Don't go off the side of the screen
+ xshift = MultiLeftmost(_ctx->pText);
+ if (xshift < 0) {
+ MultiMoveRelXY(_ctx->pText, - xshift, 0);
+ _ctx->textx -= xshift;
+ }
+ xshift = MultiRightmost(_ctx->pText);
+ if (xshift > SCREEN_WIDTH) {
+ MultiMoveRelXY(_ctx->pText, SCREEN_WIDTH - xshift, 0);
+ _ctx->textx += SCREEN_WIDTH - xshift;
+ }
+ }
+ } else
+ _ctx->pText = NULL;
+
+ if (TinselV2) {
+ if (event == POINTED) {
+ /*
+ * PrintObj() called from POINT event
+ */
+ // Have to give way to non-POINTED-generated text
+ // and go away if the item gets picked up
+ int x, y;
+ do {
+ // Give up if this item gets picked up
+ if (WhichItemHeld() == pinvo->id)
+ break;
+
+ // Give way to non-POINTED-generated text
+ if (bNotPointedRunning) {
+ // Delete the text, and wait for the all-clear
+ MultiDeleteObject(GetPlayfieldList(FIELD_STATUS), _ctx->pText);
+ _ctx->pText = NULL;
+
+ while (bNotPointedRunning)
+ CORO_SLEEP(1);
+
+ GetCursorXY(&x, &y, false);
+ if (InvItem(&x, &y, false) != _ctx->item)
+ break;
+
+ // Re-display in the same place
+ LoadStringRes(hText, TextBufferAddr(), TBUFSZ);
+ _ctx->pText = ObjectTextOut(nullContext, GetPlayfieldList(FIELD_STATUS),
+ TextBufferAddr(), 0, _ctx->textx, _ctx->texty, GetTagFontHandle(),
+ TXT_CENTRE, 0);
+ assert(_ctx->pText);
+
+ KeepOnScreen(_ctx->pText, &_ctx->textx, &_ctx->texty);
+ MultiSetZPosition(_ctx->pText, Z_INV_ITEXT);
+ }
+
+ CORO_SLEEP(1);
+
+ // Carry on until the cursor leaves this icon
+ GetCursorXY(&x, &y, false);
+
+ } while(InvItemId(x, y) == pinvo->id);
+ } else {
+ /*
+ * PrintObj() called from other event
+ */
+ _ctx->myEscape = GetLeftEvents();
+ _ctx->bTookControl = GetControl();
+
+ // Display for a time, but abort if conversation gets hidden
+ if (_ctx->pText)
+ _ctx->ticks = TextTime(TextBufferAddr());
+ _ctx->timeout = SAMPLETIMEOUT;
+
+ for (;;) {
+ CORO_SLEEP(1);
+
+ // Abort if left click - hardwired feature for talky-print!
+ // Abort if sample times out
+ // Abort if conversation hidden
+ if (LeftEventChange(_ctx->myEscape)
+ || --_ctx->timeout <= 0
+ || ConvIsHidden())
+ break;
+
+ if (_ctx->bSample) {
+ // Wait for sample to end whether or not
+ if (!_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
+ if (_ctx->pText == NULL || speedText == DEFTEXTSPEED) {
+ // No text or speed modification - just depends on sample
+ break;
+ } else {
+ // Must wait for time
+ _ctx->bSample = false;
+ }
+ }
+ } else {
+ // No sample - just depends on time
+ if (_ctx->ticks-- <= 0)
+ break;
+ }
+ }
+
+ if (_ctx->bTookControl)
+ ControlOn(); // Free control if we took it
+ }
+
+ } else {
+ if (event == POINTED) {
+ // FIXME: Is there ever an associated sound if in POINTED mode???
+ assert(!_vm->_sound->sampleExists(hText));
+ CORO_INVOKE_ARGS(PrintObjPointed, (CORO_SUBCTX, hText, pinvo, _ctx->pText, _ctx->textx, _ctx->texty, _ctx->item));
+ } else {
+ CORO_INVOKE_2(PrintObjNonPointed, hText, _ctx->pText);
+ }
}
- } else
- _ctx->pText = NULL;
- if (event == POINTED) {
- // FIXME: Is there ever an associated sound if in POINTED mode???
- assert(!_vm->_sound->sampleExists(text));
- CORO_INVOKE_ARGS(printobjPointed, (CORO_SUBCTX, text, pinvo, _ctx->pText, _ctx->textx, _ctx->texty, _ctx->item));
- } else {
- CORO_INVOKE_2(printobjNonPointed, text, _ctx->pText);
+ // Delete the text, if haven't already
+ if (_ctx->pText)
+ MultiDeleteObject(GetPlayfieldList(FIELD_STATUS), _ctx->pText);
+
+ // If it hasn't already finished, stop sample
+ if (_ctx->bSample)
+ _vm->_mixer->stopHandle(_ctx->handle);
}
- // Delete the text, if haven't already
- if (_ctx->pText)
- MultiDeleteObject(GetPlayfieldList(FIELD_STATUS), _ctx->pText);
+ // Let POINTED text back in if this is the last
+ if (event != POINTED)
+ bNotPointedRunning = false;
CORO_END_CODE;
}
-static void printobjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, OBJECT *&pText, const int textx, const int texty, const int item) {
+static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, OBJECT *&pText, const int textx, const int texty, const int item) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1156,11 +2222,11 @@ static void printobjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *
break;
// Give way to non-POINTED-generated text
- if (NotPointedRunning) {
+ if (bNotPointedRunning) {
// Delete the text, and wait for the all-clear
MultiDeleteObject(GetPlayfieldList(FIELD_STATUS), pText);
pText = NULL;
- while (NotPointedRunning)
+ while (bNotPointedRunning)
CORO_SLEEP(1);
GetCursorXY(&x, &y, false);
@@ -1168,10 +2234,10 @@ static void printobjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *
break;
// Re-display in the same place
- LoadStringRes(text, tBufferAddr(), TBUFSZ);
- pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), tBufferAddr(),
- 0, textx, texty, hTagFontHandle(), TXT_CENTRE);
- assert(pText); // printobj() string produced NULL text
+ LoadStringRes(text, TextBufferAddr(), TBUFSZ);
+ pText = ObjectTextOut(coroParam, GetPlayfieldList(FIELD_STATUS), TextBufferAddr(),
+ 0, textx, texty, GetTagFontHandle(), TXT_CENTRE);
+ assert(pText); // PrintObj() string produced NULL text
MultiSetZPosition(pText, Z_INV_ITEXT);
}
@@ -1184,7 +2250,7 @@ static void printobjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *
CORO_END_CODE;
}
-static void printobjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *pText) {
+static void PrintObjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *pText) {
CORO_BEGIN_CONTEXT;
bool bSample; // Set if a sample is playing
Audio::SoundHandle handle;
@@ -1210,7 +2276,7 @@ static void printobjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *p
if (isJapanMode())
_ctx->ticks = JAP_TEXT_TIME;
else if (pText)
- _ctx->ticks = TextTime(tBufferAddr());
+ _ctx->ticks = TextTime(TextBufferAddr());
else
_ctx->ticks = 0;
@@ -1222,7 +2288,7 @@ static void printobjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *p
// Abort if left click - hardwired feature for talky-print!
// Abort if sample times out
// Abort if conversation hidden
- if (_ctx->myleftEvent != GetLeftEvents() || _ctx->timeout <= 0 || convHid())
+ if (_ctx->myleftEvent != GetLeftEvents() || _ctx->timeout <= 0 || ConvIsHidden())
break;
if (_ctx->bSample) {
@@ -1243,10 +2309,10 @@ static void printobjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *p
}
} while (1);
- NotPointedRunning = false; // Let POINTED text back in
+ bNotPointedRunning = false; // Let POINTED text back in
if (_ctx->took_control)
- control(CONTROL_ON); // Free control if we took it
+ Control(CONTROL_ON); // Free control if we took it
_vm->_mixer->stopHandle(_ctx->handle);
@@ -1256,28 +2322,38 @@ static void printobjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *p
/**
* Register the fact that this poly would like its tag displayed.
*/
-void printtag(HPOLYGON hp, SCNHANDLE text) {
- assert(hp != NOPOLY); // printtag() may only be called from a polygon code block
-
- if (PolyTagState(hp) == TAG_OFF) {
- SetPolyTagState(hp, TAG_ON);
- SetPolyTagHandle(hp, text);
+static void PrintTag(HPOLYGON hp, SCNHANDLE text, int actor = 0, bool bCursor = false) {
+ // printtag() may only be called from a polygon code block in Tinsel 1, or
+ // additionally from a moving actor code block in Tinsel 2
+ assert((hp != NOPOLY) || (TinselV2 && (actor != 0)));
+
+ if (hp != NOPOLY) {
+ // Poly handling
+ if (TinselV2)
+ SetPolyTagWanted(hp, true, bCursor, text);
+ else if (PolyTagState(hp) == TAG_OFF) {
+ SetPolyTagState(hp, TAG_ON);
+ SetPolyTagHandle(hp, text);
+ }
+ } else {
+ // Moving actor handling
+ SetActorTagWanted(actor, true, bCursor, text);
}
}
/**
- * quitgame
+ * Quits the game
*/
-void quitgame(void) {
- stopmidi();
- stopsample();
+static void QuitGame(void) {
+ StopMidi();
+ StopSample();
_vm->quitGame();
}
/**
* Return a random number between optional limits.
*/
-int dw_random(int n1, int n2, int norpt) {
+static int RandomFn(int n1, int n2, int norpt) {
int i = 0;
uint32 value;
@@ -1290,44 +2366,71 @@ int dw_random(int n1, int n2, int norpt) {
}
/**
- * resetidletime
+ * ResetIdleTime
*/
-void resetidletime(void) {
+void ResetIdleTime(void) {
resetUserEventTime();
}
/**
* restartgame
*/
-void restartgame(void) {
- stopmidi();
- stopsample();
+static void RestartGame(void) {
+ // TODO: Tinsel 2 comments out the 2 calls, but I'm not sure that this should be done
+ StopMidi();
+ StopSample();
bRestart = true;
}
/**
* Restore saved scene.
*/
-void restore_scene(bool bFade) {
- UnSuspendHook();
- PleaseRestoreScene(bFade);
+static void RestoreScene(CORO_PARAM, TRANSITS transition) {
+ // COROUTINE
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ if (TinselV2) {
+ if (MoviePlaying()) {
+ AbortMovie();
+ CORO_SLEEP(2);
+ }
+
+ CuttingScene(false);
+
+ } else {
+ UnSuspendHook();
+ }
+
+ TinselRestoreScene(transition == TRANS_FADE);
+
+ CORO_END_CODE;
+}
+
+/**
+ * Resumes the last game
+ */
+void ResumeLastGame(void) {
+ RestoreGame(NewestSavedGame());
}
/**
- * runmode
+ * Returns the current run mode
*/
-int runmode(void) {
+static int RunMode(void) {
return clRunMode;
}
/**
- * sampleplaying
+ * SamplePlaying
*/
-bool sampleplaying(bool escOn, int myescEvent) {
+static bool SamplePlaying(bool escOn, int myEscape) {
// escape effects introduced 14/12/95 to fix
// while (sampleplaying()) pause;
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return false;
return _vm->_sound->sampleIsPlaying();
@@ -1336,73 +2439,169 @@ bool sampleplaying(bool escOn, int myescEvent) {
/**
* Save current scene.
*/
-void save_scene(CORO_PARAM) {
- PleaseSaveScene(coroParam);
- SuspendHook();
+void SaveScene(CORO_PARAM) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ if (TinselV2) {
+ CuttingScene(true);
+ SendSceneTinselProcess(LEAVE_T2);
+ CORO_GIVE_WAY;
+
+ CORO_INVOKE_0(TinselSaveScene);
+ } else {
+ CORO_INVOKE_0(TinselSaveScene);
+ SuspendHook();
+ }
+
+ CORO_END_CODE;
}
/**
- * scalingreels
+ * ScalingReels
*/
-void scalingreels(int actor, int scale, int direction,
+static void ScalingReels(int actor, int scale, int direction,
SCNHANDLE left, SCNHANDLE right, SCNHANDLE forward, SCNHANDLE away) {
- setscalingreels(actor, scale, direction, left, right, forward, away);
+ SetScalingReels(actor, scale, direction, left, right, forward, away);
}
/**
* Return the icon that caused the CONVERSE event.
*/
-
-int scanicon(void) {
- return convIcon();
+static int ScanIcon(void) {
+ return GetIcon();
}
/**
* Scroll the screen to target co-ordinates.
*/
-
-void scroll(CORO_PARAM, int x, int y, int iter, bool comp, bool escOn, int myescEvent) {
+static void Scroll(CORO_PARAM, EXTREME extreme, int xp, int yp, int xIter, int yIter, bool bComp, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
- int mycount;
+ int thisScroll;
+ int x, y;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- if (escOn && myescEvent != GetEscEvents()) {
+
+ ++scrollNumber;
+ _ctx->x = xp;
+ _ctx->y = yp;
+
+ if ((TinselV2 && bInstantScroll) || (escOn && myEscape != GetEscEvents())) {
// Instant completion!
- offset(x, y);
+ Offset(extreme, _ctx->x, _ctx->y);
} else {
- _ctx->mycount = ++scrollCount;
+ _ctx->thisScroll = scrollNumber;
+ if (TinselV2)
+ DecodeExtreme(extreme, &_ctx->x, &_ctx->y);
- ScrollTo(x, y, iter);
+ ScrollTo(_ctx->x, _ctx->y, xIter, yIter);
- if (comp) {
+ if (bComp) {
int Loffset, Toffset;
do {
CORO_SLEEP(1);
// If escapable and ESCAPE is pressed...
- if (escOn && myescEvent != GetEscEvents()) {
+ if (escOn && myEscape != GetEscEvents()) {
// Instant completion!
- offset(x, y);
+ Offset(extreme, _ctx->x, _ctx->y);
break;
}
// give up if have been superseded
- if (_ctx->mycount != scrollCount)
+ if (_ctx->thisScroll != scrollNumber)
CORO_KILL_SELF();
PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset);
- } while (Loffset != x || Toffset != y);
+ } while (Loffset != _ctx->x || Toffset != _ctx->y);
+ } else if (TinselV2 && myEscape) {
+ static SCROLL_MONITOR sm;
+
+ // Scroll is escapable even though we're not waiting for it
+ sm.x = _ctx->x;
+ sm.y = _ctx->y;
+ sm.thisScroll = scrollNumber;
+ sm.myEscape = myEscape;
+ g_scheduler->createProcess(PID_TCODE, ScrollMonitorProcess, &sm, sizeof(sm));
}
}
CORO_END_CODE;
}
/**
+ * ScrollParameters
+ */
+static void ScrollParameters(int xTrigger, int xDistance, int xSpeed, int yTriggerTop,
+ int yTriggerBottom, int yDistance, int ySpeed) {
+ SetScrollParameters(xTrigger, xDistance, xSpeed,
+ yTriggerTop, yTriggerBottom, yDistance, ySpeed);
+}
+
+/**
+ * SendActor("actor", event)
+ */
+int SendActor(CORO_PARAM, int actor, TINSEL_EVENT event, HPOLYGON hp, int myEscape) {
+ bool result;
+
+ if (IsTaggedActor(actor)) {
+ assert(actor);
+ ActorEvent(coroParam, actor, event, true, myEscape, &result);
+ } else {
+ SendTag(coroParam, actor | ACTORTAG_KEY, event, hp, myEscape, &result);
+ }
+
+ return result;
+}
+
+/**
+ * SendGlobalProcess(process#, event)
+ */
+static int SendGlobalProcess(CORO_PARAM, int procId, TINSEL_EVENT event, int myEscape) {
+ return GlobalProcessEvent(coroParam, procId, event, true, myEscape);
+}
+
+/**
+ * SendObject(object, event)
+ */
+static int SendObject(CORO_PARAM, int object, TINSEL_EVENT event, int myEscape) {
+ bool result;
+ ObjectEvent(coroParam, object, event, true, myEscape, &result);
+ return result;
+}
+
+/**
+ * SendProcess(process#, event)
+ */
+static int SendProcess(CORO_PARAM, int procId, TINSEL_EVENT event, int myEscape) {
+ bool result;
+ SceneProcessEvent(coroParam, procId, event, true, myEscape, &result);
+ return result;
+}
+
+/**
+ * SendTag(tag#, event)
+ */
+static void SendTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape, bool *result) {
+ // Tag could be zero, meaning calling tag
+ if (tagno == 0) {
+ assert(hp != NOPOLY);
+
+ PolygonEvent(coroParam, hp, event, 0, true, myEscape, result);
+ } else {
+ assert(IsTagPolygon(tagno));
+
+ PolygonEvent(coroParam, GetTagHandle(tagno), event, 0, true, myEscape, result);
+ }
+}
+
+/**
* Un-kill an actor.
*/
-void setactor(int actor) {
+static void SetActor(int actor) {
EnableActor(actor);
}
@@ -1410,7 +2609,7 @@ void setactor(int actor) {
* Turn a blocking polygon on.
*/
-void setblock(int blockno) {
+static void SetBlock(int blockno) {
EnableBlock(blockno);
}
@@ -1418,21 +2617,21 @@ void setblock(int blockno) {
* Turn an exit on.
*/
-void setexit(int exitno) {
+static void SetExit(int exitno) {
EnableExit(exitno);
}
/**
* Guess what.
*/
-void setinvlimit(int invno, int n) {
+static void SetInvLimit(int invno, int n) {
InvSetLimit(invno, n);
}
/**
* Guess what.
*/
-void setinvsize(int invno, int MinWidth, int MinHeight,
+static void SetInvSize(int invno, int MinWidth, int MinHeight,
int StartWidth, int StartHeight, int MaxWidth, int MaxHeight) {
InvSetSize(invno, MinWidth, MinHeight, StartWidth, StartHeight, MaxWidth, MaxHeight);
}
@@ -1440,7 +2639,7 @@ void setinvsize(int invno, int MinWidth, int MinHeight,
/**
* Guess what.
*/
-void setlanguage(LANGUAGE lang) {
+static void SetLanguage(LANGUAGE lang) {
assert(lang == TXT_ENGLISH || lang == TXT_FRENCH
|| lang == TXT_GERMAN || lang == TXT_ITALIAN
|| lang == TXT_SPANISH); // ensure language is valid
@@ -1451,191 +2650,332 @@ void setlanguage(LANGUAGE lang) {
/**
* Set palette
*/
-void setpalette(SCNHANDLE hPal, bool escOn, int myescEvent) {
+static void SetPalette(SCNHANDLE hPal, bool escOn, int myEscape) {
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
ChangePalette(hPal);
}
/**
+ * SetSystemString
+ */
+
+static void SetSystemString(int stringId, SCNHANDLE hString) {
+ SetSysString(stringId, hString);
+}
+
+/**
+ * Set a system variable
+ */
+static void SetSystemVar(int varId, int newValue) {
+ SetSysVar(varId, newValue);
+}
+
+/**
* Turn a tag on.
*/
-void settag(int tagno) {
- EnableTag(tagno);
+static void SetTag(CORO_PARAM, int tagno) {
+ EnableTag(coroParam, tagno);
}
/**
* Initialise a timer.
*/
-void settimer(int timerno, int start, bool up, bool frame) {
- DwSetTimer(timerno, start, up != 0, frame != 0);
+static void SetTimer(int timerno, int start, bool up, bool frame) {
+ StartTimer(timerno, start, up != 0, frame != 0);
+}
+
+/**
+ * Shell("cmdline")
+ */
+static void Shell(SCNHANDLE commandLine) {
+ LoadStringRes(commandLine, TextBufferAddr(), TBUFSZ);
+ error("Tried to execute shell command \"%s\"", TextBufferAddr());
+}
+
+/**
+ * Don't hide an actors graphics.
+ */
+static void ShowActorFn(CORO_PARAM, int actor) {
+ ShowActor(coroParam, actor);
+}
+
+/**
+ * Turn a blocking polygon on.
+ */
+void ShowBlock(int blockno) {
+ EnableBlock(blockno);
+}
+
+/**
+ * Turn an effect polygon on.
+ */
+void ShowEffect(int effect) {
+ EnableEffect(effect);
}
#ifdef DEBUG
/**
* Enable display of diagnostic co-ordinates.
*/
-void showpos(void) {
+static void showpos(void) {
setshowpos();
}
/**
* Enable display of diagnostic co-ordinates.
*/
-void showstring(void) {
+static void showstring(void) {
setshowstring();
}
#endif
/**
+ * Shows the main menu
+ */
+static void ShowMenu(void) {
+ OpenMenu(MAIN_MENU);
+}
+
+/**
+ * Turn a path on.
+ */
+static void ShowPath(int path) {
+ EnablePath(path);
+}
+
+/**
+ * Turn a refer on.
+ */
+void ShowRefer(int refer) {
+ EnableRefer(refer);
+}
+
+/**
+ * Turn a tag on.
+ */
+static void ShowTag(CORO_PARAM, int tag, HPOLYGON hp) {
+ // Tag could be zero, meaning calling tag
+ EnableTag(coroParam, tag ? tag : GetTagPolyId(hp));
+}
+
+/**
* Special play - slow down associated actor's movement while the play
* is running. After the play, position the actor where the play left
* it and continue walking, if the actor still is.
*/
-
-void splay(CORO_PARAM, int sf, SCNHANDLE film, int x, int y, bool complete, int actorid, bool escOn, int myescEvent) {
+static void SPlay(CORO_PARAM, int sf, SCNHANDLE film, int x, int y, bool complete, int actorid, bool escOn, int myEscape) {
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
- play(coroParam, film, x, y, complete, actorid, true, sf, escOn, myescEvent, false);
+ Play(coroParam, film, x, y, complete, actorid, true, sf, escOn, myEscape, false);
}
/**
* (Re)Position an actor.
* If moving actor is not around yet in this scene, start it up.
*/
+void Stand(CORO_PARAM, int actor, int x, int y, SCNHANDLE hFilm) {
+ CORO_BEGIN_CONTEXT;
+ PMOVER pMover; // Moving actor structure
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
-void stand(int actor, int x, int y, SCNHANDLE film) {
- PMACTOR pActor; // Moving actor structure
+ _ctx->pMover = GetMover(actor);
+ assert(!TinselV2 || (_ctx->pMover != NULL));
+
+ if (_ctx->pMover) {
+ if (TinselV2) {
+ // New special. If no paths, just ignore this
+ if (PathCount() == 0)
+ return;
+
+ // Another new special.
+ // If lead actor, and TalkVia, ignore
+ if ((actor == GetLeadId() || actor == LEAD_ACTOR) && SysVar(ISV_DIVERT_ACTOR))
+ return;
+ }
- pActor = GetMover(actor);
- if (pActor) {
- if (pActor->MActorState == NO_MACTOR) {
+ if (!MoverIs(_ctx->pMover)) {
// create a moving actor process
- MActorProcessCreate(x, y, (actor == LEAD_ACTOR) ? LeadId() : actor, pActor);
+ MoverProcessCreate(x, y, (actor == LEAD_ACTOR) ? GetLeadId() : actor, _ctx->pMover);
- if (film == TF_NONE) {
- SetMActorStanding(pActor);
+ if (hFilm == TF_NONE) {
+ // Make sure there is an assigned actorObj
+ while (!_ctx->pMover->actorObj)
+ CORO_SLEEP(1);
+
+ SetMoverStanding(_ctx->pMover);
} else {
- switch (film) {
- case TF_NONE:
- break;
-
- case TF_UP:
- SetMActorDirection(pActor, AWAY);
- SetMActorStanding(pActor);
- break;
- case TF_DOWN:
- SetMActorDirection(pActor, FORWARD);
- SetMActorStanding(pActor);
- break;
- case TF_LEFT:
- SetMActorDirection(pActor, LEFTREEL);
- SetMActorStanding(pActor);
- break;
- case TF_RIGHT:
- SetMActorDirection(pActor, RIGHTREEL);
- SetMActorStanding(pActor);
- break;
-
- default:
- AlterMActor(pActor, film, AR_NORMAL);
- break;
+ // Check hFilm against certain constants. Note that a switch statement isn't
+ // used here because it would interfere with our co-routine implementation
+ if (hFilm == TF_UP) {
+ if (TinselV2) CORO_GIVE_WAY;
+ SetMoverDirection(_ctx->pMover, AWAY);
+ SetMoverStanding(_ctx->pMover);
+ } else if (hFilm == TF_DOWN) {
+ if (TinselV2) CORO_GIVE_WAY;
+ SetMoverDirection(_ctx->pMover, FORWARD);
+ SetMoverStanding(_ctx->pMover);
+ } else if (hFilm == TF_LEFT) {
+ if (TinselV2) CORO_GIVE_WAY;
+ SetMoverDirection(_ctx->pMover, LEFTREEL);
+ SetMoverStanding(_ctx->pMover);
+ } else if (hFilm == TF_RIGHT) {
+ if (TinselV2) CORO_GIVE_WAY;
+ SetMoverDirection(_ctx->pMover, RIGHTREEL);
+ SetMoverStanding(_ctx->pMover);
+ } else if (hFilm != TF_NONE) {
+ if (TinselV2) CORO_GIVE_WAY;
+ AlterMover(_ctx->pMover, hFilm, AR_NORMAL);
}
}
} else {
- switch (film) {
+ switch (hFilm) {
case TF_NONE:
if (x != -1 && y != -1)
- MoveMActor(pActor, x, y);
+ PositionMover(_ctx->pMover, x, y);
break;
case TF_UP:
- SetMActorDirection(pActor, AWAY);
+ SetMoverDirection(_ctx->pMover, AWAY);
if (x != -1 && y != -1)
- MoveMActor(pActor, x, y);
- SetMActorStanding(pActor);
+ PositionMover(_ctx->pMover, x, y);
+ SetMoverStanding(_ctx->pMover);
break;
case TF_DOWN:
- SetMActorDirection(pActor, FORWARD);
+ SetMoverDirection(_ctx->pMover, FORWARD);
if (x != -1 && y != -1)
- MoveMActor(pActor, x, y);
- SetMActorStanding(pActor);
+ PositionMover(_ctx->pMover, x, y);
+ SetMoverStanding(_ctx->pMover);
break;
case TF_LEFT:
- SetMActorDirection(pActor, LEFTREEL);
+ SetMoverDirection(_ctx->pMover, LEFTREEL);
if (x != -1 && y != -1)
- MoveMActor(pActor, x, y);
- SetMActorStanding(pActor);
+ PositionMover(_ctx->pMover, x, y);
+ SetMoverStanding(_ctx->pMover);
break;
case TF_RIGHT:
- SetMActorDirection(pActor, RIGHTREEL);
+ SetMoverDirection(_ctx->pMover, RIGHTREEL);
if (x != -1 && y != -1)
- MoveMActor(pActor, x, y);
- SetMActorStanding(pActor);
+ PositionMover(_ctx->pMover, x, y);
+ SetMoverStanding(_ctx->pMover);
break;
default:
if (x != -1 && y != -1)
- MoveMActor(pActor, x, y);
- AlterMActor(pActor, film, AR_NORMAL);
+ PositionMover(_ctx->pMover, x, y);
+ AlterMover(_ctx->pMover, hFilm, AR_NORMAL);
break;
}
}
} else if (actor == NULL_ACTOR) {
//
} else {
- assert(film != 0); // Trying to play NULL film
+ assert(hFilm != 0); // Trying to play NULL film
// Kick off the play and return.
- playFilm(film, x, y, actor, false, 0, false, 0, false);
+ CORO_INVOKE_ARGS(PlayFilm, (CORO_SUBCTX, hFilm, x, y, actor, false, 0, false, 0, false));
}
+
+ CORO_END_CODE;
}
/**
* Position the actor at the polygon's tag node.
*/
-void standtag(int actor, HPOLYGON hp) {
- SCNHANDLE film;
+static void StandTag(int actor, HPOLYGON hp) {
+ SCNHANDLE hFilm;
int pnodex, pnodey;
- assert(hp != NOPOLY); // standtag() may only be called from a polygon code block
+ assert(hp != NOPOLY); // StandTag() may only be called from a polygon code block
+
+ // Where to stand
+ GetPolyNode(hp, &pnodex, &pnodey);
// Lead actor uses tag node film
- film = getPolyFilm(hp);
- getPolyNode(hp, &pnodex, &pnodey);
- if (film && (actor == LEAD_ACTOR || actor == LeadId()))
- stand(actor, pnodex, pnodey, film);
+ hFilm = GetPolyFilm(hp);
+
+ // other actors can use direction
+ if (TinselV2) {
+ if (actor != LEAD_ACTOR && actor != GetLeadId()
+ && hFilm != TF_UP && hFilm != TF_DOWN
+ && hFilm != TF_LEFT && hFilm != TF_RIGHT)
+ hFilm = 0;
+
+ Stand(nullContext, actor, pnodex, pnodey, hFilm);
+
+ } else if (hFilm && (actor == LEAD_ACTOR || actor == GetLeadId()))
+ Stand(nullContext, actor, pnodex, pnodey, hFilm);
else
- stand(actor, pnodex, pnodey, 0);
+ Stand(nullContext, actor, pnodex, pnodey, 0);
}
+
/**
- * Kill a moving actor's walk.
+ * StartGlobalProcess
*/
-void stop(int actor) {
- PMACTOR pActor;
+static void StartGlobalProcess(CORO_PARAM, uint32 procID) {
+ GlobalProcessEvent(coroParam, procID, STARTUP, false, 0);
+}
- pActor = GetMover(actor);
- assert(pActor); // Trying to stop a null actor
+/**
+ * StartProcess
+ */
+static void StartProcess(CORO_PARAM, uint32 procID) {
+ SceneProcessEvent(coroParam, procID, STARTUP, false, 0);
+}
- GetToken(pActor->actorToken); // Kill the walk process
- pActor->stop = true; // Cause the actor to stop
- FreeToken(pActor->actorToken);
+/**
+ * Initialise a timer.
+ */
+static void StartTimerFn(int timerno, int start, bool up, int fs) {
+ StartTimer(timerno, start, up, fs);
}
-void stopmidi(void) {
+void StopMidiFn(void) {
StopMidi(); // Stop any currently playing midi
}
-void stopsample(void) {
- _vm->_sound->stopAllSamples(); // Stop any currently playing sample
+/**
+ * Kill a specific sample, or all samples.
+ */
+void StopSample(int sample) {
+ if (sample == -1)
+ _vm->_sound->stopAllSamples(); // Stop any currently playing sample
+ else
+ _vm->_sound->stopSpecSample(sample, 0);
+}
+
+/**
+ * Kill a moving actor's walk.
+ */
+static void StopWalk(int actor) {
+ PMOVER pMover;
+
+ pMover = GetMover(actor);
+ assert(pMover);
+
+ if (TinselV2) {
+ if (MoverHidden(pMover))
+ return;
+
+ StopMover(pMover); // Cause the actor to stop
+ } else {
+ GetToken(pMover->actorToken); // Kill the walk process
+ pMover->bStop = true; // Cause the actor to stop
+ FreeToken(pMover->actorToken);
+ }
}
-void subtitles(int onoff) {
+/**
+ * Subtitles on/off
+ */
+static void Subtitles(int onoff) {
assert (onoff == ST_ON || onoff == ST_OFF);
if (isJapanMode())
@@ -1651,271 +2991,468 @@ void subtitles(int onoff) {
* Special walk.
* Walk into or out of a legal path.
*/
-void swalk(CORO_PARAM, int actor, int x1, int y1, int x2, int y2, SCNHANDLE film, bool escOn, int myescEvent) {
+static void Swalk(CORO_PARAM, int actor, int x1, int y1, int x2, int y2, SCNHANDLE film, int zOverride, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
- bool took_control; // Set if this function takes control
+ bool bTookControl; // Set if this function takes control
CORO_END_CONTEXT(_ctx);
+ HPOLYGON hPath;
+
CORO_BEGIN_CODE(_ctx);
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents()) {
+ if (TinselV2) {
+ if (x2 == -1 && y2 == -1)
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x1, y1, 0));
+ else
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x2, y2, 0));
+ }
+
return;
+ }
// For lead actor, lock out the user (if not already locked out)
- if (actor == LeadId() || actor == LEAD_ACTOR)
- _ctx->took_control = GetControl(CONTROL_OFFV2);
- else
- _ctx->took_control = false;
-
- HPOLYGON hPath;
+ if (actor == GetLeadId() || actor == LEAD_ACTOR) {
+ _ctx->bTookControl = GetControl(CONTROL_OFFV2);
+ if (TinselV2 && _ctx->bTookControl)
+ RestoreMainCursor();
+ } else {
+ _ctx->bTookControl = false;
+ }
- hPath = InPolygon(x1, y1, PATH);
- if (hPath != NOPOLY) {
- // Walking out of a path
- stand(actor, x1, y1, 0);
+ if (TinselV2 && (x2 == -1) && (y2 == -1)) {
+ // First co-ordinates are the destination
+ x2 = x1;
+ y2 = y1;
} else {
- hPath = InPolygon(x2, y2, PATH);
- // One of them has to be in a path
- assert(hPath != NOPOLY); //one co-ordinate must be in a legal path
+ // Stand at the start co-ordinates
+ hPath = InPolygon(x1, y1, PATH);
+
+ if (hPath != NOPOLY) {
+ // Walking out of a path
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x1, y1, 0));
+ } else {
+ hPath = InPolygon(x2, y2, PATH);
+ // One of them has to be in a path
+ assert(hPath != NOPOLY); //one co-ordinate must be in a legal path
- // Walking into a path
- stand(actor, x2, y2, 0); // Get path's characteristics
- stand(actor, x1, y1, 0);
+ // Walking into a path
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x2, y2, 0)); // Get path's characteristics
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x1, y1, 0));
+ }
+
+ if (TinselV2 && (zOverride != -1)) {
+ PMOVER pMover = GetMover(actor);
+ assert(pMover);
+
+ SetMoverZ(pMover, y1, zOverride);
+ }
}
- CORO_INVOKE_ARGS(walk, (CORO_SUBCTX, actor, x2, y2, film, 0, true, escOn, myescEvent));
+ CORO_INVOKE_ARGS(Walk, (CORO_SUBCTX, actor, x2, y2, film, 0, true, zOverride, escOn, myEscape));
// Free control if we took it
- if (_ctx->took_control)
- control(CONTROL_ON);
+ if (_ctx->bTookControl)
+ Control(CONTROL_ON);
CORO_END_CODE;
}
/**
- * Define a tagged actor.
+ * Gets a system variable
*/
+static int SystemVar(int varId) {
+ return SysVar(varId);
+}
-void tagactor(int actor, SCNHANDLE text, int tp) {
+/**
+ * Define a tagged actor.
+ */
+static void TagActor(int actor, SCNHANDLE text, int tp) {
Tag_Actor(actor, text, tp);
}
/**
+ * TagPos([tag #])
+ */
+static int TagPos(MASTER_LIB_CODES operand, int tagno, HPOLYGON hp) {
+ int x, y;
+
+ // Tag could be zero, meaning calling tag
+ if (tagno == 0)
+ tagno = GetTagPolyId(hp);
+
+ if (operand == TAGTAGXPOS || operand == TAGTAGYPOS) {
+ SCNHANDLE junk;
+
+ GetTagTag(GetTagHandle(tagno), &junk, &x, &y);
+ } else {
+ GetPolyNode(GetTagHandle(tagno), &x, &y);
+ }
+
+ if (operand == TAGTAGXPOS || operand == TAGWALKXPOS)
+ return x;
+ else
+ return y;
+}
+
+/**
* Text goes over actor's head while actor plays the talk reel.
*/
+static void FinishTalkingReel(CORO_PARAM, PMOVER pMover, int actor) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
-void FinishTalkingReel(PMACTOR pActor, int actor) {
- if (pActor) {
- SetMActorStanding(pActor);
- AlterMActor(pActor, 0, AR_POPREEL);
+ if (pMover) {
+ SetMoverStanding(pMover);
+ AlterMover(pMover, 0, AR_POPREEL);
} else {
- setActorTalking(actor, false);
- playFilm(getActorPlayFilm(actor), -1, -1, 0, false, 0, false, 0, false);
+ SetActorTalking(actor, false);
+ CORO_INVOKE_ARGS(PlayFilm, (CORO_SUBCTX, GetActorPlayFilm(actor), -1, -1, 0, false, 0, false, 0, false));
}
+
+ CORO_END_CODE;
}
-void talk(CORO_PARAM, SCNHANDLE film, const SCNHANDLE text, int actorid, bool escOn, int myescEvent) {
+static void TalkOrSay(CORO_PARAM, SPEECH_TYPE speechType, SCNHANDLE hText, int x, int y,
+ SCNHANDLE hFilm, int actorId, bool bSustain, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
int Loffset, Toffset; // Top left of display
int actor; // The speaking actor
- PMACTOR pActor; // For moving actors
- int myleftEvent;
+ PMOVER pActor; // For moving actors
+ int myLeftEvent;
+ int escEvents;
int ticks;
bool bTookControl; // Set if this function takes control
bool bTookTags; // Set if this function disables tags
OBJECT *pText; // text object pointer
bool bSample; // Set if a sample is playing
+ bool bSamples;
bool bTalkReel; // Set while talk reel is playing
Audio::SoundHandle handle;
int timeout;
+
+ SPEECH_TYPE whatSort;
+ TFTYPE direction;
+ int sub;
+ int x, y;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
+ _ctx->whatSort = speechType;
+ _ctx->escEvents = myEscape;
+ _ctx->x = x;
+ _ctx->y = y;
_ctx->Loffset = 0;
_ctx->Toffset = 0;
_ctx->ticks = 0;
+ _ctx->pText = NULL;
+
+ // If waiting is enabled, wait for ongoing scroll
+ if (TinselV2 && SysVar(SV_SPEECHWAITS))
+ CORO_INVOKE_1(WaitScroll, myEscape);
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
- _ctx->myleftEvent = GetLeftEvents();
+ _ctx->myLeftEvent = GetLeftEvents();
// If this actor is dead, call a stop to the calling process
- if (actorid && !actorAlive(actorid))
+ if (!TinselV2 && (actorId && !actorAlive(actorId)))
CORO_KILL_SELF();
- /*
- * Find out which actor is talking
- * and with which direction if no film supplied
- */
- TFTYPE direction;
- switch (film) {
- case TF_NONE:
- case TF_UP:
- case TF_DOWN:
- case TF_LEFT:
- case TF_RIGHT:
- _ctx->actor = LeadId(); // If no film, actor is lead actor
- direction = (TFTYPE)film;
- break;
+ if (!TinselV2 || (speechType == IS_TALK)) {
+ /*
+ * Find out which actor is talking
+ * and with which direction if no film supplied
+ */
+ switch (hFilm) {
+ case TF_NONE:
+ case TF_UP:
+ case TF_DOWN:
+ case TF_LEFT:
+ case TF_RIGHT:
+ _ctx->actor = GetLeadId(); // If no film, actor is lead actor
+ _ctx->direction = (TFTYPE)hFilm;
+ break;
- default:
- _ctx->actor = extractActor(film);
- assert(_ctx->actor); // talk() - no actor ID in the reel
- direction = TF_BOGUS;
- break;
- }
+ default:
+ _ctx->actor = ExtractActor(hFilm);
+ assert(_ctx->actor); // talk() - no actor ID in the reel
+ _ctx->direction = TF_FILM;
+ break;
+ }
+ assert(_ctx->actor);
+ } else if (TinselV2)
+ _ctx->actor = actorId;
/*
* Lock out the user (for lead actor, if not already locked out)
* May need to disable tags for other actors
*/
- if (_ctx->actor == LeadId())
+ if (_ctx->actor == GetLeadId() || (TinselV2 && (_ctx->actor == LEAD_ACTOR)))
_ctx->bTookControl = GetControl(CONTROL_OFF);
else
_ctx->bTookControl = false;
_ctx->bTookTags = DisableTagsIfEnabled();
+ if (TinselV2) {
+ /*
+ * Divert stuff
+ */
+ if (SysVar(ISV_DIVERT_ACTOR) && (_ctx->actor == GetLeadId() || _ctx->actor == LEAD_ACTOR)) {
+ _ctx->actor = SysVar(ISV_DIVERT_ACTOR);
+ if (_ctx->whatSort == IS_TALK)
+ _ctx->whatSort = IS_SAY;
+ else if (_ctx->whatSort == IS_TALKAT)
+ _ctx->whatSort = IS_SAYAT;
+ }
+ }
+
/*
* Kick off the voice sample
*/
- if (volVoice != 0 && _vm->_sound->sampleExists(text)) {
- _vm->_sound->playSample(text, Audio::Mixer::kSpeechSoundType, &_ctx->handle);
- _ctx->bSample = _vm->_mixer->isSoundHandleActive(_ctx->handle);
+ if (volVoice != 0 && _vm->_sound->sampleExists(hText)) {
+ if (!TinselV2) {
+ _vm->_sound->playSample(hText, Audio::Mixer::kSpeechSoundType, &_ctx->handle);
+ _ctx->bSamples = _vm->_mixer->isSoundHandleActive(_ctx->handle);
+ } else
+ _ctx->bSamples = true;
} else
- _ctx->bSample = false;
+ _ctx->bSamples = false;
/*
* Replace actor with the talk reel, saving the current one
*/
_ctx->pActor = GetMover(_ctx->actor);
- if (_ctx->pActor) {
- if (direction != TF_BOGUS)
- film = GetMactorTalkReel(_ctx->pActor, direction);
- AlterMActor(_ctx->pActor, film, AR_PUSHREEL);
- } else {
- setActorTalking(_ctx->actor, true);
- setActorTalkFilm(_ctx->actor, film);
- playFilm(film, -1, -1, 0, false, 0, escOn, myescEvent, false);
+ if (_ctx->whatSort == IS_TALK) {
+ if (_ctx->pActor) {
+ if (_ctx->direction != TF_FILM)
+ hFilm = GetMoverTalkReel(_ctx->pActor, _ctx->direction);
+ AlterMover(_ctx->pActor, hFilm, AR_PUSHREEL);
+ } else {
+ SetActorTalking(_ctx->actor, true);
+ SetActorTalkFilm(_ctx->actor, hFilm);
+ CORO_INVOKE_ARGS(PlayFilm, (CORO_SUBCTX, hFilm, -1, -1, 0, false, 0, escOn, myEscape, false));
+ }
+ _ctx->bTalkReel = true;
+ CORO_SLEEP(1); // Allow the play to come in
+
+ } else if (_ctx->whatSort == IS_TALKAT) {
+ _ctx->bTalkReel = false;
+
+ } else if ((_ctx->whatSort == IS_SAY) || (_ctx->whatSort == IS_SAYAT)) {
+ _ctx->bTalkReel = false;
+ if (IsTaggedActor(_ctx->actor)) {
+ CORO_INVOKE_ARGS(ActorEvent, (CORO_SUBCTX, _ctx->actor, TALKING, false, 0));
+ } else if (IsTagPolygon(_ctx->actor | ACTORTAG_KEY)) {
+ CORO_INVOKE_ARGS(PolygonEvent, (CORO_SUBCTX, GetTagHandle(_ctx->actor | ACTORTAG_KEY),
+ TALKING, 0, false, 0));
+ }
+
+ if (TinselV2)
+ // Let it all kick in and position this 'waiting' process
+ // down the process list from the playing process(es)
+ // This ensures immediate return when the reel finishes
+ CORO_GIVE_WAY;
}
- _ctx->bTalkReel = true;
- CORO_SLEEP(1); // Allow the play to come in
- /*
- * Display the text.
- */
- _ctx->pText = NULL;
- if (isJapanMode()) {
- _ctx->ticks = JAP_TEXT_TIME;
- } else if (bSubtitles || !_ctx->bSample) {
- int aniX, aniY; // actor position
- int xshift, yshift;
- /*
- * Work out where to display the text
- */
- PlayfieldGetPos(FIELD_WORLD, &_ctx->Loffset, &_ctx->Toffset);
- GetActorMidTop(_ctx->actor, &aniX, &aniY);
- aniY -= _ctx->Toffset;
-
- setTextPal(getActorTcol(_ctx->actor));
- LoadStringRes(text, tBufferAddr(), TBUFSZ);
- _ctx->pText = ObjectTextOut(GetPlayfieldList(FIELD_STATUS), tBufferAddr(),
- 0, aniX - _ctx->Loffset, aniY, hTalkFontHandle(), TXT_CENTRE);
- assert(_ctx->pText); // talk() string produced NULL text;
- if (IsTopWindow())
- MultiSetZPosition(_ctx->pText, Z_TOPW_TEXT);
+ // Make multi-ones escape
+ if (TinselV2 && (SubStringCount(hText) > 1) && !_ctx->escEvents)
+ _ctx->escEvents = GetEscEvents();
- /*
- * Set bottom of text just above the speaker's head
- * But don't go off the top of the screen
- */
- yshift = aniY - MultiLowest(_ctx->pText) - 2; // Just above head
- MultiMoveRelXY(_ctx->pText, 0, yshift); //
- yshift = MultiHighest(_ctx->pText);
- if (yshift < 4)
- MultiMoveRelXY(_ctx->pText, 0, 4 - yshift); // Not off top
+ for (_ctx->sub = 0; _ctx->sub < (TinselV2 ? SubStringCount(hText) : 1); _ctx->sub++) {
+ if (TinselV2 && _ctx->escEvents && _ctx->escEvents != GetEscEvents())
+ break;
/*
- * Don't go off the side of the screen
+ * Display the text.
*/
- xshift = MultiRightmost(_ctx->pText) + 2;
- if (xshift >= SCREEN_WIDTH) // Not off right
- MultiMoveRelXY(_ctx->pText, SCREEN_WIDTH - xshift, 0);
- xshift = MultiLeftmost(_ctx->pText) - 1;
- if (xshift <= 0) // Not off left
- MultiMoveRelXY(_ctx->pText, -xshift, 0);
- /*
- * Work out how long to talk.
- * During this time, reposition the text if the screen scrolls.
- */
- _ctx->ticks = TextTime(tBufferAddr());
- }
+ _ctx->bSample = _ctx->bSamples;
+ _ctx->pText = NULL;
- _ctx->timeout = SAMPLETIMEOUT;
- do {
- // Keep text in place if scrolling
- if (_ctx->pText != NULL) {
- int nLoff, nToff;
+ if (isJapanMode()) {
+ _ctx->ticks = JAP_TEXT_TIME;
+ } else if (bSubtitles || !_ctx->bSample) {
+ /*
+ * Work out where to display the text
+ */
+ int xshift, yshift;
+
+ PlayfieldGetPos(FIELD_WORLD, &_ctx->Loffset, &_ctx->Toffset);
+ if ((_ctx->whatSort == IS_SAY) || (_ctx->whatSort == IS_TALK))
+ GetActorMidTop(_ctx->actor, &_ctx->x, &_ctx->y);
+
+ SetTextPal(GetActorRGB(_ctx->actor));
+ if (TinselV2)
+ LoadSubString(hText, _ctx->sub, TextBufferAddr(), TBUFSZ);
+ else {
+ LoadStringRes(hText, TextBufferAddr(), TBUFSZ);
+
+ _ctx->y -= _ctx->Toffset;
+ }
- PlayfieldGetPos(FIELD_WORLD, &nLoff, &nToff);
- if (nLoff != _ctx->Loffset || nToff != _ctx->Toffset) {
- MultiMoveRelXY(_ctx->pText, _ctx->Loffset - nLoff, _ctx->Toffset - nToff);
- _ctx->Loffset = nLoff;
- _ctx->Toffset = nToff;
+ _ctx->pText = ObjectTextOut(coroParam, GetPlayfieldList(FIELD_STATUS),
+ TextBufferAddr(), 0, _ctx->x - _ctx->Loffset, _ctx->y - _ctx->Toffset,
+ GetTalkFontHandle(), TXT_CENTRE);
+ assert(_ctx->pText); // talk() string produced NULL text;
+
+ if (IsTopWindow())
+ MultiSetZPosition(_ctx->pText, Z_TOPW_TEXT);
+
+ if ((_ctx->whatSort == IS_SAY) || (_ctx->whatSort == IS_TALK)) {
+ /*
+ * Set bottom of text just above the speaker's head
+ * But don't go off the top of the screen
+ */
+ if (TinselV2)
+ MultiMoveRelXY(_ctx->pText, 0, _ctx->y - _ctx->Toffset - MultiLowest(_ctx->pText) - 2);
+ else {
+ yshift = _ctx->y - MultiLowest(_ctx->pText) - 2; // Just above head
+ MultiMoveRelXY(_ctx->pText, 0, yshift); //
+ yshift = MultiHighest(_ctx->pText);
+ if (yshift < 4)
+ MultiMoveRelXY(_ctx->pText, 0, 4 - yshift); // Not off top
+
+ /*
+ * Don't go off the side of the screen
+ */
+ xshift = MultiRightmost(_ctx->pText) + 2;
+ if (xshift >= SCREEN_WIDTH) // Not off right
+ MultiMoveRelXY(_ctx->pText, SCREEN_WIDTH - xshift, 0);
+ xshift = MultiLeftmost(_ctx->pText) - 1;
+ if (xshift <= 0) // Not off left
+ MultiMoveRelXY(_ctx->pText, -xshift, 0);
+ }
}
+
+ if (TinselV2)
+ // Don't go off the screen
+ KeepOnScreen(_ctx->pText, &_ctx->x, &_ctx->y);
+
+ /*
+ * Work out how long to talk.
+ * During this time, reposition the text if the screen scrolls.
+ */
+ _ctx->ticks = TextTime(TextBufferAddr());
}
- CORO_SLEEP(1);
- --_ctx->timeout;
+ if (TinselV2 && _ctx->bSample) {
+ // Kick off the sample now (perhaps with a delay)
+ if (bNoPause)
+ bNoPause = false;
+ else
+ CORO_SLEEP(SysVar(SV_SPEECHDELAY));
- // Abort if escapable and ESCAPE is pressed
- // Abort if left click - hardwired feature for talk!
- // Abort if sample times out
- if ((escOn && myescEvent != GetEscEvents())
- || (_ctx->myleftEvent != GetLeftEvents())
- || (_ctx->timeout <= 0))
- break;
+ //SamplePlay(VOICE, hText, _ctx->sub, false, -1, -1, PRIORITY_TALK);
+ _vm->_sound->playSample(hText, _ctx->sub, false, -1, -1, PRIORITY_TALK, Audio::Mixer::kSpeechSoundType, &_ctx->handle);
+ }
+
+ _ctx->timeout = SAMPLETIMEOUT;
- if (_ctx->bSample) {
- // Wait for sample to end whether or not
- if (!_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
- if (_ctx->pText == NULL || speedText == DEFTEXTSPEED) {
- // No text or speed modification - just depends on sample
+ do {
+ // Keep text in place if scrolling
+ if (_ctx->pText != NULL) {
+ int nLoff, nToff;
+
+ PlayfieldGetPos(FIELD_WORLD, &nLoff, &nToff);
+ if (nLoff != _ctx->Loffset || nToff != _ctx->Toffset) {
+ MultiMoveRelXY(_ctx->pText, _ctx->Loffset - nLoff, _ctx->Toffset - nToff);
+ _ctx->Loffset = nLoff;
+ _ctx->Toffset = nToff;
+ }
+ }
+
+ CORO_SLEEP(1);
+
+ // Handle timeout decrementing and Escape presses
+ if (TinselV2) {
+ if ((_ctx->escEvents && _ctx->escEvents != GetEscEvents()) ||
+ (!bSustain && LeftEventChange(_ctx->myLeftEvent)) ||
+ (--_ctx->timeout <= 0)) {
+ // Left event only kills current sub-string
+ _ctx->myLeftEvent = GetLeftEvents();
break;
- } else {
- // Talk reel stops at end of speech
- FinishTalkingReel(_ctx->pActor, _ctx->actor);
- _ctx->bTalkReel = false;
- _ctx->bSample = false;
}
+ } else {
+ --_ctx->timeout;
+
+ // Abort if escapable and ESCAPE is pressed
+ // Abort if left click - hardwired feature for talk!
+ // Abort if sample times out
+ if ((escOn && myEscape != GetEscEvents())
+ || (_ctx->myLeftEvent != GetLeftEvents())
+ || (_ctx->timeout <= 0))
+ break;
}
- } else {
- // No sample - just depends on time
- if (_ctx->ticks-- <= 0)
- break;
+
+ if (_ctx->bSample) {
+ // Wait for sample to end whether or not
+ if (!_vm->_mixer->isSoundHandleActive(_ctx->handle)) {
+ if (_ctx->pText == NULL || speedText == DEFTEXTSPEED) {
+ // No text or speed modification - just depends on sample
+ break;
+ } else {
+ // Talk reel stops at end of speech
+ if (!TinselV2 || (_ctx->bTalkReel && (_ctx->sub == SubStringCount(hText) - 1))) {
+ CORO_INVOKE_2(FinishTalkingReel, _ctx->pActor, _ctx->actor);
+ _ctx->bTalkReel = false;
+ }
+ _ctx->bSample = false;
+ }
+ }
+ } else {
+ // No sample - just depends on time
+ if (_ctx->ticks-- <= 0)
+ break;
+ }
+ } while (1);
+
+ if (_ctx->pText != NULL) {
+ MultiDeleteObject(GetPlayfieldList(FIELD_STATUS), _ctx->pText);
+ _ctx->pText = NULL;
}
- } while (1);
+ if (TinselV2 && _ctx->bSample)
+ _vm->_sound->stopSpecSample(hText, _ctx->sub);
+ }
/*
* The talk is over now - dump the text
* Stop the sample
* Restore the actor's film or standing reel
*/
+ if (_ctx->bTalkReel)
+ CORO_INVOKE_2(FinishTalkingReel, _ctx->pActor, _ctx->actor);
if (_ctx->pText != NULL)
MultiDeleteObject(GetPlayfieldList(FIELD_STATUS), _ctx->pText);
- _vm->_mixer->stopHandle(_ctx->handle);
- if (_ctx->bTalkReel)
- FinishTalkingReel(_ctx->pActor, _ctx->actor);
+
+ if (TinselV2) {
+ if ((_ctx->whatSort == IS_SAY) || (_ctx->whatSort == IS_SAYAT)) {
+ SetActorTalking(_ctx->actor, false);
+ if (IsTaggedActor(_ctx->actor))
+ CORO_INVOKE_ARGS(ActorEvent, (CORO_SUBCTX, _ctx->actor, ENDTALK, false, 0));
+ else if (IsTagPolygon(_ctx->actor | ACTORTAG_KEY))
+ CORO_INVOKE_ARGS(PolygonEvent, (CORO_SUBCTX,
+ GetTagHandle(_ctx->actor | ACTORTAG_KEY), ENDTALK, 0, false, 0));
+
+ CORO_SLEEP(1);
+ }
+ } else {
+ _vm->_mixer->stopHandle(_ctx->handle);
+ }
/*
* Restore user control and tags, as appropriate
* And, finally, release the talk token.
*/
- if (_ctx->bTookControl)
- control(CONTROL_ON);
+ if (_ctx->bTookControl) {
+ if (TinselV2) ControlOn(); else Control(CONTROL_ON);
+ }
if (_ctx->bTookTags)
EnableTags();
@@ -1923,135 +3460,238 @@ void talk(CORO_PARAM, SCNHANDLE film, const SCNHANDLE text, int actorid, bool es
}
/**
- * talkat(actor, x, y, text)
+ * TalkAt(actor, x, y, text)
*/
-void talkat(CORO_PARAM, int actor, int x, int y, SCNHANDLE text, bool escOn, int myescEvent) {
+static void TalkAt(CORO_PARAM, int actor, int x, int y, SCNHANDLE text, bool escOn, int myEscape) {
if (!coroParam) {
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
if (!isJapanMode() && (bSubtitles || !_vm->_sound->sampleExists(text)))
- setTextPal(getActorTcol(actor));
+ SetTextPal(GetActorRGB(actor));
}
- print(coroParam, x, y, text, 0, 0, escOn, myescEvent);
+ Print(coroParam, x, y, text, 0, false, escOn, myEscape);
}
/**
- * talkats(actor, x, y, text, sustain)
+ * TalkAtS(actor, x, y, text, sustain)
*/
-void talkats(CORO_PARAM, int actor, int x, int y, SCNHANDLE text, int sustain, bool escOn, int myescEvent) {
+static void TalkAtS(CORO_PARAM, int actor, int x, int y, SCNHANDLE text, int sustain, bool escOn, int myEscape) {
if (!coroParam) {
assert(sustain == 2);
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
if (!isJapanMode())
- setTextPal(getActorTcol(actor));
+ SetTextPal(GetActorRGB(actor));
}
- print(coroParam, x, y, text, 0, sustain, escOn, myescEvent);
+ Print(coroParam, x, y, text, 0, sustain == 2, escOn, myEscape);
}
/**
* Set talk font's palette entry.
*/
-void talkattr(int r1, int g1, int b1, bool escOn, int myescEvent) {
+static void TalkAttr(int r1, int g1, int b1, bool escOn, int myEscape) {
if (isJapanMode())
return;
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
if (r1 > MAX_INTENSITY) r1 = MAX_INTENSITY; // } Ensure
if (g1 > MAX_INTENSITY) g1 = MAX_INTENSITY; // } within limits
if (b1 > MAX_INTENSITY) b1 = MAX_INTENSITY; // }
- setTextPal(RGB(r1, g1, b1));
+ SetTextPal(RGB(r1, g1, b1));
+}
+
+/**
+ * TalkPaletteIndex
+ */
+static void TalkPaletteIndex(unsigned index) {
+ assert(index);
+
+ SetTalkTextOffset(index);
+}
+
+/**
+ * Set talk font's palette entry.
+ */
+static void TalkRGB(COLORREF colour, int myescEvent) {
+ // Don't do it if it's not wanted
+ if (myescEvent && myescEvent != GetEscEvents())
+ return;
+
+ SetTextPal(colour);
+}
+
+/**
+ * TalkVia("actor"/off)
+ */
+static void TalkVia(int actor) {
+ SetSysVar(ISV_DIVERT_ACTOR, actor);
+}
+
+/**
+ * Declare a temporary text font.
+ */
+static void TempTagFont(SCNHANDLE hFilm) {
+ SetTempTagFontHandle(hFilm); // Store the font handle
+}
+
+/**
+ * Declare a temporary text font.
+ */
+static void TempTalkFont(SCNHANDLE hFilm) {
+ SetTempTalkFontHandle(hFilm); // Store the font handle
+}
+
+/**
+ * ThisObject
+ */
+static int ThisObject(INV_OBJECT *pinvo) {
+ assert(pinvo != NULL);
+
+ return pinvo->id;
+}
+
+/**
+ * ThisTag
+ */
+static int ThisTag(HPOLYGON hp) {
+ int tagno;
+
+ assert(hp != NOPOLY);
+
+ tagno = GetTagPolyId(hp);
+
+ assert(IsTagPolygon(tagno));
+ assert(tagno);
+
+ return tagno;
}
/**
* Get a timer's current count.
*/
-int timer(int timerno) {
+static int TimerFn(int timerno) {
return Timer(timerno);
}
/**
+ * Return the icon that caused the CONVERSE event.
+ */
+int Topic(void) {
+ return GetIcon();
+}
+
+/**
* topplay(film, x, y, actor, hold, complete)
*/
-void topplay(CORO_PARAM, SCNHANDLE film, int x, int y, int complete, int actorid, bool splay, int sfact, bool escOn, int myescTime) {
- play(coroParam, film, x, y, complete, actorid, splay, sfact, escOn, myescTime, true);
+static void TopPlay(CORO_PARAM, SCNHANDLE film, int x, int y, int complete, int actorid, bool splay, int sfact, bool escOn, int myescTime) {
+ Play(coroParam, film, x, y, complete, actorid, splay, sfact, escOn, myescTime, true);
+}
+static void TopPlay(CORO_PARAM, SCNHANDLE hFilm, int x, int y, bool bComplete, int myescEvent, TINSEL_EVENT event) {
+ Play(coroParam, hFilm, x, y, bComplete, myescEvent, true, event, NOPOLY, 0);
}
/**
* Open or close the 'top window'
*/
-void topwindow(int bpos) {
- assert(bpos == TW_START || bpos == TW_END);
+static void TopWindow(int bpos) {
+ bool isStart = (TinselV2 && (bpos != 0)) || (!TinselV2 && (bpos == TW_START));
- switch (bpos) {
- case TW_END:
- KillInventory();
- break;
+ KillInventory();
- case TW_START:
- KillInventory();
- PopUpConf(TOPWIN);
- break;
+ if (isStart)
+ OpenMenu(TOP_WINDOW);
+}
+
+/**
+ * TranslucentIndex
+ */
+static void TranslucentIndex(unsigned index) {
+ assert(index <= 255);
+
+ SetTranslucencyOffset(index);
+}
+
+/**
+ * Play a sample.
+ */
+static void TryPlaySample(CORO_PARAM, int sample, bool bComplete, bool escOn, int myEscape) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+ // Don't do it if it's not appropriate
+ if (_vm->_sound->sampleIsPlaying()) {
+ // return, but prevent Glitter lock-up
+ CORO_SLEEP(1);
+ return;
}
+
+ CORO_INVOKE_ARGS(PlaySample, (CORO_SUBCTX, sample, bComplete, escOn, myEscape));
+ CORO_END_CODE;
+}
+
+/**
+ * UnDimMusic
+ */
+static void UnDimMusic(void) {
+ _vm->_pcmMusic->unDim(true);
}
/**
* unhookscene
*/
-void unhookscene(void) {
+static void UnHookSceneFn(void) {
UnHookScene();
}
/**
* Un-define an actor as tagged.
*/
-void untagactor(int actor) {
+static void UnTagActorFn(int actor) {
UnTagActor(actor);
}
/**
* vibrate
*/
-void vibrate(void) {
+static void Vibrate(void) {
}
/**
* waitframe(int actor, int frameNumber)
*/
-void waitframe(CORO_PARAM, int actor, int frameNumber, bool escOn, int myescEvent) {
+static void WaitFrame(CORO_PARAM, int actor, int frameNumber, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- // Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
- return;
- while (getActorSteps(actor) < frameNumber) {
- CORO_SLEEP(1);
-
- // Abort if escapable and ESCAPE is pressed
- if (escOn && myescEvent != GetEscEvents())
+ while (GetActorSteps(actor) < frameNumber) {
+ // Don't do it if it's not wanted
+ if (escOn && myEscape != GetEscEvents())
break;
+
+ CORO_SLEEP(1);
}
+
CORO_END_CODE;
}
/**
* Return when a key pressed or button pushed.
*/
-void waitkey(CORO_PARAM, bool escOn, int myescEvent) {
+static void WaitKey(CORO_PARAM, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
int startEvent;
int startX, startY;
@@ -2060,35 +3700,38 @@ void waitkey(CORO_PARAM, bool escOn, int myescEvent) {
CORO_BEGIN_CODE(_ctx);
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
- while (1) {
+ for (;;) {
_ctx->startEvent = getUserEvents();
- // Store cursor position
- while (!GetCursorXYNoWait(&_ctx->startX, &_ctx->startY, false))
- CORO_SLEEP(1);
+ if (!TinselV2) {
+ // Store cursor position
+ while (!GetCursorXYNoWait(&_ctx->startX, &_ctx->startY, false))
+ CORO_SLEEP(1);
+ }
while (_ctx->startEvent == getUserEvents()) {
CORO_SLEEP(1);
// Not necessary to monitor escape as it's an event anyway
+ if (!TinselV2) {
+ int curX, curY;
+ GetCursorXY(&curX, &curY, false); // Store cursor position
+ if (curX != _ctx->startX || curY != _ctx->startY)
+ break;
+ }
- int curX, curY;
- GetCursorXY(&curX, &curY, false); // Store cursor position
- if (curX != _ctx->startX || curY != _ctx->startY)
- break;
-
- if (IsConfWindow())
+ if (MenuActive())
break;
}
- if (!IsConfWindow())
+ if (!MenuActive())
return;
-
+
do {
CORO_SLEEP(1);
- } while (IsConfWindow());
+ } while (MenuActive());
CORO_SLEEP(ONE_SECOND / 2); // Let it die down
}
@@ -2096,16 +3739,38 @@ void waitkey(CORO_PARAM, bool escOn, int myescEvent) {
}
/**
+ * Return when no scrolling is going on.
+ */
+void WaitScroll(CORO_PARAM, int myescEvent) {
+ CORO_BEGIN_CONTEXT;
+ int time;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ // wait for ongoing scroll
+ while (IsScrolling()) {
+ if (myescEvent && myescEvent != GetEscEvents())
+ break;
+
+ CORO_SLEEP(1);
+ }
+
+ CORO_END_CODE;
+}
+
+/**
* Pause for requested time.
*/
-void waittime(CORO_PARAM, int time, bool frame, bool escOn, int myescEvent) {
+static void WaitTime(CORO_PARAM, int time, bool frame, bool escOn, int myEscape) {
CORO_BEGIN_CONTEXT;
int time;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
+
// Don't do it if it's not wanted
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
return;
if (!frame)
@@ -2116,51 +3781,97 @@ void waittime(CORO_PARAM, int time, bool frame, bool escOn, int myescEvent) {
CORO_SLEEP(1);
// Abort if escapable and ESCAPE is pressed
- if (escOn && myescEvent != GetEscEvents())
+ if (escOn && myEscape != GetEscEvents())
break;
} while (_ctx->time--);
+
CORO_END_CODE;
}
/**
* Set a moving actor off on a walk.
*/
-void walk(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, int hold, bool igPath, bool escOn, int myescEvent) {
+void Walk(CORO_PARAM, int actor, int x, int y, SCNHANDLE hFilm, int hold, bool igPath,
+ int zOverride, bool escOn, int myescEvent) {
CORO_BEGIN_CONTEXT;
+ int thisWalk;
CORO_END_CONTEXT(_ctx);
- PMACTOR pActor = GetMover(actor);
- assert(pActor); // Can't walk a non-moving actor
+ bool bQuick = hold != 0;
+ PMOVER pMover = GetMover(actor);
+ assert(pMover); // Can't walk a non-moving actor
CORO_BEGIN_CODE(_ctx);
// Straight there if escaped
if (escOn && myescEvent != GetEscEvents()) {
- stand(actor, x, y, 0);
+ if (TinselV2)
+ StopMover(pMover);
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x, y, 0));
return;
}
- assert(pActor->hCpath != NOPOLY); // moving actor not in path
+ if (TinselV2) {
+ if (MoverHidden(pMover))
+ return;
- GetToken(pActor->actorToken);
- SetActorDest(pActor, x, y, igPath, film);
- DontScrollCursor();
+ // Test 10/10/96
+ while (!MoverIs(pMover))
+ CORO_SLEEP(1);
+ }
+
+ assert(pMover->hCpath != NOPOLY); // moving actor not in path
+
+ // Croak if he is doing an SWalk()
+ if (TinselV2) {
+ // Croak if he is doing an SWalk()
+ if (MoverIsSWalking(pMover))
+ CORO_KILL_SELF();
+
+ _ctx->thisWalk = SetActorDest(pMover, x, y, igPath, hFilm);
+ SetMoverZoverride(pMover, zOverride);
+ DontScrollCursor();
+
+ if (!bQuick) {
+ while (MoverMoving(pMover)) {
+ // Straight there if escaped
+ if (escOn && myescEvent != GetEscEvents()) {
+ StopMover(pMover);
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x, y, 0));
+ break;
+ }
+
+ CORO_SLEEP(1);
- if (hold == 2) {
- ;
+ // Die if superceded
+ if (_ctx->thisWalk != GetWalkNumber(pMover))
+ CORO_KILL_SELF();
+ }
+ }
} else {
- while (MAmoving(pActor)) {
- CORO_SLEEP(1);
- // Straight there if escaped
- if (escOn && myescEvent != GetEscEvents()) {
- stand(actor, x, y, 0);
- FreeToken(pActor->actorToken);
- return;
+ GetToken(pMover->actorToken);
+ SetActorDest(pMover, x, y, igPath, hFilm);
+ DontScrollCursor();
+
+ if (hold == 2) {
+ ;
+ } else {
+ while (MoverMoving(pMover)) {
+ CORO_SLEEP(1);
+
+ // Straight there if escaped
+ if (escOn && myescEvent != GetEscEvents()) {
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x, y, 0));
+ FreeToken(pMover->actorToken);
+ return;
+ }
}
}
+
+ FreeToken(pMover->actorToken);
}
- FreeToken(pActor->actorToken);
+
CORO_END_CODE;
}
@@ -2168,56 +3879,65 @@ void walk(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, int hold, bool ig
* Set a moving actor off on a walk.
* Wait to see if its aborted or completed.
*/
-void walked(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, bool escOn, int myescEvent, bool &retVal) {
+static void Walked(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, bool escOn, int myEscape, bool &retVal) {
// COROUTINE
CORO_BEGIN_CONTEXT;
- int ticket;
+ int thisWalk;
CORO_END_CONTEXT(_ctx);
- PMACTOR pActor = GetMover(actor);
- assert(pActor); // Can't walk a non-moving actor
+ PMOVER pMover = GetMover(actor);
+ assert(pMover); // Can't walk a non-moving actor
CORO_BEGIN_CODE(_ctx);
// Straight there if escaped
- if (escOn && myescEvent != GetEscEvents()) {
- stand(actor, x, y, 0);
+ if (escOn && myEscape != GetEscEvents()) {
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x, y, 0));
retVal = true;
return;
}
- CORO_SLEEP(ONE_SECOND);
-
- assert(pActor->hCpath != NOPOLY); // moving actor not in path
-
- // Briefly aquire token to kill off any other normal walk
- GetToken(pActor->actorToken);
- FreeToken(pActor->actorToken);
-
- SetActorDest(pActor, x, y, false, film);
- DontScrollCursor();
-
- _ctx->ticket = GetActorTicket(pActor);
-
- while (MAmoving(pActor)) {
- CORO_SLEEP(1);
+ if (TinselV2) {
+ if (MoverHidden(pMover) || !MoverIs(pMover)) {
+ retVal = false;
+ return;
+ }
+ assert(pMover->hCpath != NOPOLY); // moving actor not in path
- if (_ctx->ticket != GetActorTicket(pActor)) {
+ // Not if he is doing an SWalk()
+ if (MoverIsSWalking(pMover)) {
retVal = false;
return;
}
+ } else {
+ // Pause before starting the walk
+ CORO_SLEEP(ONE_SECOND);
+
+ assert(pMover->hCpath != NOPOLY); // moving actor not in path
+
+ // Briefly aquire token to kill off any other normal walk
+ GetToken(pMover->actorToken);
+ FreeToken(pMover->actorToken);
+ }
+
+ _ctx->thisWalk = SetActorDest(pMover, x, y, false, film);
+ DontScrollCursor();
+
+ while (MoverMoving(pMover) && (_ctx->thisWalk == GetWalkNumber(pMover))) {
// Straight there if escaped
- if (escOn && myescEvent != GetEscEvents()) {
- stand(actor, x, y, 0);
+ if (escOn && myEscape != GetEscEvents()) {
+ CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, actor, x, y, 0));
retVal = true;
return;
}
+
+ CORO_SLEEP(1);
}
int endx, endy;
- GetMActorPosition(pActor, &endx, &endy);
- retVal = (_ctx->ticket == GetActorTicket(pActor) && endx == x && endy == y);
+ GetMoverPosition(pMover, &endx, &endy);
+ retVal = (_ctx->thisWalk == GetWalkNumber(pMover) && endx == x && endy == y);
CORO_END_CODE;
}
@@ -2225,10 +3945,15 @@ void walked(CORO_PARAM, int actor, int x, int y, SCNHANDLE film, bool escOn, int
/**
* Declare a moving actor.
*/
-void walkingactor(uint32 id, SCNHANDLE *rp) {
- PMACTOR pActor; // Moving actor structure
+static void WalkingActor(uint32 id, SCNHANDLE *rp = NULL) {
+ PMOVER pActor; // Moving actor structure
- SetMover(id); // Establish as a moving actor
+ if (TinselVersion == TINSEL_V2) {
+ RegisterMover(id);
+ return;
+ }
+
+ RegisterMover(id); // Establish as a moving actor
pActor = GetMover(id);
assert(pActor);
@@ -2236,16 +3961,16 @@ void walkingactor(uint32 id, SCNHANDLE *rp) {
int i, j;
for (i = 0; i < 5; ++i) {
for (j = 0; j < 4; ++j)
- pActor->WalkReels[i][j] = *rp++;
+ pActor->walkReels[i][j] = *rp++;
for (j = 0; j < 4; ++j)
- pActor->StandReels[i][j] = *rp++;
+ pActor->standReels[i][j] = *rp++;
}
for (i = NUM_MAINSCALES; i < TOTAL_SCALES; i++) {
for (j = 0; j < 4; ++j) {
- pActor->WalkReels[i][j] = pActor->WalkReels[4][j];
- pActor->StandReels[i][j] = pActor->StandReels[2][j];
+ pActor->walkReels[i][j] = pActor->walkReels[4][j];
+ pActor->standReels[i][j] = pActor->standReels[2][j];
}
}
}
@@ -2254,60 +3979,75 @@ void walkingactor(uint32 id, SCNHANDLE *rp) {
* Walk a moving actor towards the polygon's tag, but return when the
* actor enters the polygon.
*/
-void walkpoly(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int myescEvent) {
+static void WalkPoly(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int myEscape) {
+ int pnodex, pnodey;
+
// COROUTINE
CORO_BEGIN_CONTEXT;
+ int thisWalk;
CORO_END_CONTEXT(_ctx);
- PMACTOR pActor = GetMover(actor);
- assert(pActor); // Can't walk a non-moving actor
+ assert(hp != NOPOLY); // WalkPoly() may only be called from a polygon code block
+ PMOVER pMover = GetMover(actor);
+ assert(pMover); // Can't walk a non-moving actor
CORO_BEGIN_CODE(_ctx);
- int aniX, aniY; // cursor/actor position
- int pnodex, pnodey;
-
- assert(hp != NOPOLY); // walkpoly() may only be called from a polygon code block
-
// Straight there if escaped
- if (escOn && myescEvent != GetEscEvents()) {
- standtag(actor, hp);
+ if (escOn && myEscape != GetEscEvents()) {
+ StandTag(actor, hp);
return;
}
- GetToken(pActor->actorToken);
- getPolyNode(hp, &pnodex, &pnodey);
- SetActorDest(pActor, pnodex, pnodey, false, film);
+ if (TinselV2) {
+ if (MoverHidden(pMover))
+ return;
+
+ // Croak if he is doing an SWalk()
+ if (MoverIsSWalking(pMover))
+ CORO_KILL_SELF();
+
+ } else {
+ GetToken(pMover->actorToken);
+ }
+
+ GetPolyNode(hp, &pnodex, &pnodey);
+ _ctx->thisWalk = SetActorDest(pMover, pnodex, pnodey, false, film);
DoScrollCursor();
- do {
+ while (!MoverIsInPolygon(pMover, hp) && MoverMoving(pMover)) {
CORO_SLEEP(1);
- if (escOn && myescEvent != GetEscEvents()) {
+ if (escOn && myEscape != GetEscEvents()) {
// Straight there if escaped
- standtag(actor, hp);
- FreeToken(pActor->actorToken);
+ StandTag(actor, hp);
+ if (!TinselV2)
+ FreeToken(pMover->actorToken);
return;
}
- GetMActorPosition(pActor, &aniX, &aniY);
- } while (!MActorIsInPolygon(pActor, hp) && MAmoving(pActor));
+ // Die if superceded
+ if (TinselV2 && (_ctx->thisWalk != GetWalkNumber(pMover)))
+ CORO_KILL_SELF();
+ }
- FreeToken(pActor->actorToken);
+ if (!TinselV2)
+ FreeToken(pMover->actorToken);
CORO_END_CODE;
}
/**
- * walktag(actor, reel, hold)
+ * WalkTag(actor, reel, hold)
*/
-void walktag(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int myescEvent) {
+static void WalkTag(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int myEscape) {
// COROUTINE
CORO_BEGIN_CONTEXT;
+ int thisWalk;
CORO_END_CONTEXT(_ctx);
- PMACTOR pActor = GetMover(actor);
- assert(pActor); // Can't walk a non-moving actor
+ PMOVER pMover = GetMover(actor);
+ assert(pMover); // Can't walk a non-moving actor
CORO_BEGIN_CODE(_ctx);
@@ -2316,67 +4056,102 @@ void walktag(CORO_PARAM, int actor, SCNHANDLE film, HPOLYGON hp, bool escOn, int
assert(hp != NOPOLY); // walkpoly() may only be called from a polygon code block
// Straight there if escaped
- if (escOn && myescEvent != GetEscEvents()) {
- standtag(actor, hp);
+ if (escOn && myEscape != GetEscEvents()) {
+ StandTag(actor, hp);
return;
}
- GetToken(pActor->actorToken);
- getPolyNode(hp, &pnodex, &pnodey);
- SetActorDest(pActor, pnodex, pnodey, false, film);
- DoScrollCursor();
+ if (!TinselV2)
+ GetToken(pMover->actorToken);
+ else {
+ if (MoverHidden(pMover))
+ return;
+ }
- while (MAmoving(pActor)) {
- CORO_SLEEP(1);
+ GetPolyNode(hp, &pnodex, &pnodey);
+
+ _ctx->thisWalk = SetActorDest(pMover, pnodex, pnodey, false, film);
+ DoScrollCursor();
- if (escOn && myescEvent != GetEscEvents()) {
+ while (MoverMoving(pMover)) {
+ if (escOn && myEscape != GetEscEvents()) {
// Straight there if escaped
- standtag(actor, hp);
- FreeToken(pActor->actorToken);
+ StandTag(actor, hp);
+ if (!TinselV2)
+ FreeToken(pMover->actorToken);
return;
}
+
+ CORO_SLEEP(1);
+
+ // Die if superceded
+ if (TinselV2 && (_ctx->thisWalk != GetWalkNumber(pMover)))
+ CORO_KILL_SELF();
}
// Adopt the tag-related reel
- SCNHANDLE pfilm = getPolyFilm(hp);
+ SCNHANDLE pFilm = GetPolyFilm(hp);
- switch (pfilm) {
+ switch (pFilm) {
case TF_NONE:
break;
case TF_UP:
- SetMActorDirection(pActor, AWAY);
- SetMActorStanding(pActor);
+ SetMoverDirection(pMover, AWAY);
+ SetMoverStanding(pMover);
break;
case TF_DOWN:
- SetMActorDirection(pActor, FORWARD);
- SetMActorStanding(pActor);
+ SetMoverDirection(pMover, FORWARD);
+ SetMoverStanding(pMover);
break;
case TF_LEFT:
- SetMActorDirection(pActor, LEFTREEL);
- SetMActorStanding(pActor);
+ SetMoverDirection(pMover, LEFTREEL);
+ SetMoverStanding(pMover);
break;
case TF_RIGHT:
- SetMActorDirection(pActor, RIGHTREEL);
- SetMActorStanding(pActor);
+ SetMoverDirection(pMover, RIGHTREEL);
+ SetMoverStanding(pMover);
break;
default:
- if (actor == LEAD_ACTOR || actor == LeadId())
- AlterMActor(pActor, pfilm, AR_NORMAL);
+ if (actor == LEAD_ACTOR || actor == GetLeadId())
+ AlterMover(pMover, pFilm, AR_NORMAL);
else
- SetMActorStanding(pActor);
+ SetMoverStanding(pMover);
break;
}
- FreeToken(pActor->actorToken);
+ if (!TinselV2)
+ FreeToken(pMover->actorToken);
+
CORO_END_CODE;
}
/**
+ * Returns the X co-ordinateof lead actor's last walk.
+ */
+int WalkXPos(void) {
+ return GetLastLeadXdest();
+}
+
+/**
+ * Returns the Y co-ordinateof lead actor's last walk.
+ */
+int WalkYPos(void) {
+ return GetLastLeadYdest();
+}
+
+/**
+ * Return which is the current CD, counting from 1.
+ */
+int WhichCd(void) {
+ return GetCurrentCD();
+}
+
+/**
* whichinventory
*/
-int whichinventory(void) {
+int WhichInventory(void) {
return WhichInventoryOpen();
}
@@ -2395,544 +4170,1350 @@ int whichinventory(void) {
* @param pp Top of parameter stack
*/
int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pic, RESUME_STATE *pResumeState) {
- debug(7, "CallLibraryRoutine op %d (escOn %d, myescEvent %d)", operand, pic->escOn, pic->myescEvent);
- switch (operand) {
+ int libCode = TinselV2 ? DW2_CODES[operand] : DW1_CODES[operand];
+
+ debug(7, "CallLibraryRoutine op %d (escOn %d, myEscape %d)", operand, pic->escOn, pic->myEscape);
+ switch (libCode) {
case ACTORATTR:
+ // DW1 only
pp -= 3; // 4 parameters
- actorattr(pp[0], pp[1], pp[2], pp[3]);
+ ActorAttr(pp[0], pp[1], pp[2], pp[3]);
return -4;
+ case ACTORBRIGHTNESS:
+ // DW2 only
+ pp -= 1;
+ ActorBrightness(pp[0], pp[1]);
+ return -2;
+
case ACTORDIRECTION:
- pp[0] = actordirection(pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = ActorDirection(pp[0]);
return 0;
+ case ACTORPALETTE:
+ // DW2 only
+ pp -= 2; // 3 parameters
+ ActorPalette(pp[0], pp[1], pp[2]);
+ return -3;
+
+ case ACTORPRIORITY:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ ActorPriority(pp[0], pp[1]);
+ return -2;
+
case ACTORREF:
+ // Common to both DW1 & DW2
error("actorref isn't a real function!");
+ case ACTORRGB:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ ActorRGB(pp[0], pp[1]);
+ return -2;
+
case ACTORSCALE:
- pp[0] = actorscale(pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = ActorScale(pp[0]);
return 0;
case ACTORSON:
- actorson();
+ // DW1 only
+ ActorsOn();
return 0;
case ACTORXPOS:
- pp[0] = actorpos(ACTORXPOS, pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = ActorPos(ACTORXPOS, pp[0]);
return 0;
case ACTORYPOS:
- pp[0] = actorpos(ACTORYPOS, pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = ActorPos(ACTORYPOS, pp[0]);
return 0;
- case ADDICON:
- addicon(pp[0]);
+ case ADDHIGHLIGHT:
+ // DW2 only
+ // Command doesn't actually do anything
+ pp -= 1; // 2 parameters
+ return -2;
+
+ case ADDINV:
+ // DW2 only
+ AddInv(INV_DEFAULT, pp[0]);
return -1;
case ADDINV1:
- addinv(INV_1, pp[0]);
+ // Common to both DW1 & DW2
+ AddInv(INV_1, pp[0]);
return -1;
case ADDINV2:
- addinv(INV_2, pp[0]);
+ // Common to both DW1 & DW2
+ AddInv(INV_2, pp[0]);
return -1;
case ADDOPENINV:
- addinv(INV_OPEN, pp[0]);
+ // Common to both DW1 & DW2
+ AddInv(TinselV2 ? DW2_INV_OPEN : INV_OPEN, pp[0]);
+ return -1;
+
+ case ADDTOPIC:
+ // Common to both DW1 & DW2
+ AddTopic(pp[0]);
return -1;
case AUXSCALE:
+ // DW1 only
pp -= 13; // 14 parameters
- auxscale(pp[0], pp[1], (SCNHANDLE *)(pp+2));
+ AuxScale(pp[0], pp[1], (SCNHANDLE *)(pp+2));
return -14;
case BACKGROUND:
- background(pp[0]);
+ // Common to both DW1 & DW2
+ Background(coroParam, pp[0]);
+ return -1;
+
+ case BLOCKING:
+ // DW2 only
+ Blocking(pp[0]);
return -1;
+ case CALLACTOR:
+ case CALLGLOBALPROCESS:
+ case CALLOBJECT:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ bool result;
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic, &result);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+ pp[0] = result ? 1 : 0;
+ } else {
+ uint32 v;
+ if (libCode == CALLACTOR)
+ v = SendActor(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->hPoly, pic->myEscape);
+ else if (libCode == CALLGLOBALPROCESS)
+ v = SendGlobalProcess(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->myEscape);
+ else
+ v = SendObject(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->myEscape);
+
+ if (coroParam)
+ return 0;
+ pp[0] = v;
+ }
+
+ if (!pp[0])
+ KillSelf(coroParam);
+ return -2;
+
+
+ case CALLPROCESS:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ bool result;
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic, &result);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+
+ pp[0] = result ? 1 : 0;
+ } else {
+ int result = SendProcess(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->myEscape);
+ if (coroParam)
+ return 0;
+
+ pp[0] = result;
+ }
+ return -2;
+
+ case CALLSCENE:
+ // DW2 only
+ error("CallScene isn't a real function!");
+
+ case CALLTAG:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ bool result;
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic, &result);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+
+ pp[0] = result ? 1 : 0;
+ } else {
+ bool result;
+ SendTag(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->hPoly, pic->myEscape, &result);
+ if (coroParam)
+ return 0;
+
+ pp[0] = result ? 1 : 0;
+ }
+
+ if (!pp[0])
+ KillSelf(coroParam);
+ return -2;
+
case CAMERA:
- camera(pp[0]);
+ // Common to both DW1 & DW2
+ Camera(pp[0]);
+ return -1;
+
+ case CDCHANGESCENE:
+ // DW2 only
+ CdChangeScene(pp[0]);
+ return -1;
+
+ case CDDOCHANGE:
+ // DW2 only
+ CdDoChange(coroParam);
+ return 0;
+
+ case CDENDACTOR:
+ // DW2 only
+ CdEndActor(pp[0], pic->myEscape);
return -1;
case CDLOAD:
- pp -= 1; // 2 parameters
- cdload(pp[0], pp[1]);
+ // Common to both DW1 & DW2
+ pp -= 1; // 2 parameters
+ CDload(pp[0], pp[1], pic->myEscape);
return -2;
case CDPLAY:
+ // Common to both DW1 & DW2
error("cdplay isn't a real function!");
case CLEARHOOKSCENE:
- clearhookscene();
+ // Common to both DW1 & DW2
+ ClearHookScene();
return 0;
case CLOSEINVENTORY:
- closeinventory();
+ // Common to both DW1 & DW2
+ CloseInventory();
return 0;
case CONTROL:
- control(pp[0]);
+ // Common to both DW1 & DW2
+ Control(pp[0]);
return -1;
case CONVERSATION:
- conversation(pp[0], pic->hpoly, pic->escOn, pic->myescEvent);
+ // Common to both DW1 & DW2
+ Conversation(coroParam, pp[0], pic->hPoly, pic->idActor, pic->escOn, pic->myEscape);
+ return -1;
+
+ case CONVTOPIC:
+ // Common to both DW1 & DW2
+ ConvTopic(pp[0]);
return -1;
- case CONVICON:
- convicon(pp[0]);
+ case CURSOR:
+ // DW2 only
+ Cursor(pp[0]);
return -1;
case CURSORXPOS:
- pp[0] = cursorpos(CURSORXPOS);
+ // Common to both DW1 & DW2
+ pp[0] = CursorPos(CURSORXPOS);
return 0;
case CURSORYPOS:
- pp[0] = cursorpos(CURSORYPOS);
+ // Common to both DW1 & DW2
+ pp[0] = CursorPos(CURSORYPOS);
return 0;
case CUTSCENE:
+ // DW1 only
error("cutscene isn't a real function!");
- case DEC_CONVW:
+ case DECCONVW:
+ // Common to both DW1 & DW2
pp -= 7; // 8 parameters
- dec_convw(pp[0], pp[1], pp[2], pp[3],
+ DecConvW(pp[0], pp[1], pp[2], pp[3],
pp[4], pp[5], pp[6], pp[7]);
return -8;
- case DEC_CSTRINGS:
+ case DECCSTRINGS:
+ // DW1 only
pp -= 19; // 20 parameters
- dec_cstrings((SCNHANDLE *)pp);
+ DecCStrings((SCNHANDLE *)pp);
return -20;
- case DEC_CURSOR:
- dec_cursor(pp[0]);
+ case DECCURSOR:
+ // Common to both DW1 & DW2
+ DecCursor(pp[0]);
return -1;
- case DEC_FLAGS:
- dec_flags(pp[0]);
+ case DECFLAGS:
+ // Common to both DW1 & DW2
+ if (TinselV2)
+ error("DecFlags() is obsolete!");
+
+ DecFlags(pp[0]);
return -1;
- case DEC_INV1:
+ case DECINV1:
+ // Common to both DW1 & DW2
pp -= 7; // 8 parameters
- dec_inv1(pp[0], pp[1], pp[2], pp[3],
+ DecInv1(pp[0], pp[1], pp[2], pp[3],
pp[4], pp[5], pp[6], pp[7]);
return -8;
- case DEC_INV2:
+ case DECINV2:
+ // Common to both DW1 & DW2
pp -= 7; // 8 parameters
- dec_inv2(pp[0], pp[1], pp[2], pp[3],
+ DecInv2(pp[0], pp[1], pp[2], pp[3],
pp[4], pp[5], pp[6], pp[7]);
return -8;
- case DEC_INVW:
- dec_invw(pp[0]);
+ case DECINVW:
+ // Common to both DW1 & DW2
+ DecInvW(pp[0]);
return -1;
- case DEC_LEAD:
- pp -= 61; // 62 parameters
- dec_lead(pp[0], (SCNHANDLE *)&pp[1], pp[61]);
- return -62;
+ case DECLARELANGUAGE:
+ // DW2 only
+ pp -= 2; // 3 parameters
+ DeclareLanguage(pp[0], pp[1], pp[2]);
+ return -3;
+
+ case DECLEAD:
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ DecLead(pp[0]);
+ return -1;
+ } else {
+ pp -= 61; // 62 parameters
+ DecLead(pp[0], (SCNHANDLE *)&pp[1], pp[61]);
+ return -62;
+ }
+
+ case DECSCALE:
+ // DW2 only
+ pp -= 13; // 14 parameters
+ DecScale(pp[0], pp[1], pp[2], pp[3], pp[4],
+ pp[5], pp[6], pp[7], pp[8], pp[9],
+ pp[10], pp[11], pp[12], pp[13]);
+ return -14;
- case DEC_TAGFONT:
- dec_tagfont(pp[0]);
+ case DECTAGFONT:
+ // Common to both DW1 & DW2
+ DecTagFont(pp[0]);
return -1;
- case DEC_TALKFONT:
- dec_talkfont(pp[0]);
+ case DECTALKFONT:
+ // Common to both DW1 & DW2
+ DecTalkFont(pp[0]);
return -1;
case DELICON:
- delicon(pp[0]);
+ // DW1 only
+ DelIcon(pp[0]);
return -1;
case DELINV:
- delinv(pp[0]);
+ // DW1 only
+ DelInv(pp[0]);
+ return -1;
+
+ case DELTOPIC:
+ // DW2 only
+ DelTopic(pp[0]);
return -1;
+ case DIMMUSIC:
+ // DW2 only
+ DimMusic();
+ return 0;
+
+ case DROP:
+ // DW2 only
+ Drop(pp[0]);
+ return -1;
+
+ case DROPEVERYTHING:
+ // DW2 only
+ DropEverything();
+ return 0;
+
+ case DROPOUT:
+ // DW1 only
+ error("DropOut (%d)\n", pp[0]);
+
case EFFECTACTOR:
- assert(pic->event == ENTER || pic->event == LEAVE); // effectactor() must be from effect poly code
+ // Common to both DW1 & DW2
+ assert(pic->event == WALKIN || pic->event == WALKOUT); // effectactor() must be from effect poly code
- pp[0] = pic->actorid;
+ pp[0] = pic->idActor;
return 0;
- case ENABLEF1:
- enablef1();
+ case ENABLEMENU:
+ // Common to both DW1 & DW2
+ EnableMenu();
return 0;
+ case ENDACTOR:
+ // DW2 only
+ EndActor(pp[0]);
+ return -1;
+
+ case ESCAPE:
+ case ESCAPEOFF:
+ case ESCAPEON:
+ // Common to both DW1 & DW2
+ error("Escape isn't a real function!");
+
case EVENT:
- pp[0] = pic->event;
+ // Common to both DW1 & DW2
+ if (TinselVersion == TINSEL_V2)
+ pp[0] = pic->event;
+ else
+ pp[0] = TINSEL1_EVENT_MAP[pic->event];
+ return 0;
+
+ case FACETAG:
+ // DW2 only
+ FaceTag(pp[0], pic->hPoly);
+ return -1;
+
+ case FADEIN:
+ // DW2 only
+ FadeIn();
return 0;
case FADEMIDI:
- fademidi(coroParam, pp[0]);
+ // DW1 only
+ FadeMidi(coroParam, pp[0]);
return -1;
+ case FADEOUT:
+ // DW1 only
+ FadeOut();
+ return 0;
+
case FRAMEGRAB:
+ // Common to both DW1 & DW2
+ return -1;
+
+ case FREEZECURSOR:
+ // DW2 only
+ FreezeCursor(pp[0]);
return -1;
case GETINVLIMIT:
- pp[0] = getinvlimit(pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = GetInvLimit(pp[0]);
return 0;
+ case GHOST:
+ // DW2 only
+ pp -= 2; // 3 parameters
+ Ghost(pp[0], pp[1], pp[2]);
+ return -3;
+
+ case GLOBALVAR:
+ // DW1 only
+ error("GlobalVar isn't a real function!");
+
+ case GRABMOVIE:
+ // DW2 only
+ return -1;
+
+ case HAILSCENE:
+ // DW2 only
+ HailScene(pp[0]);
+ return -1;
+
case HASRESTARTED:
- pp[0] = hasrestarted();
+ // Common to both DW1 & DW2
+ pp[0] = HasRestarted();
return 0;
+ case HAVE:
+ // DW2 only
+ pp[0] = Have(pp[0]);
+ return 0; // using return value
+
case HELDOBJECT:
- pp[0] = heldobject();
+ // Common to both DW1 & DW2
+ pp[0] = HeldObject();
return 0;
- case HIDE:
- hide(pp[0]);
+ case HIDEACTOR:
+ // Common to both DW1 & DW2
+ if (!TinselV2)
+ HideActorFn(coroParam, pp[0]);
+ else if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+ } else
+ HideActorFn(coroParam, pp[0]);
+ return -1;
+
+ case HIDEBLOCK:
+ // DW2 only
+ HideBlock(pp[0]);
+ return -1;
+
+ case HIDEEFFECT:
+ // DW2 only
+ HideEffect(pp[0]);
+ return -1;
+
+ case HIDEPATH:
+ // DW2 only
+ HidePath(pp[0]);
+ return -1;
+
+ case HIDEREFER:
+ // DW2 only
+ HideRefer(pp[0]);
+ return -1;
+
+ case HIDETAG:
+ // DW2 only
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+ } else {
+ HideTag(coroParam, pp[0], pic->hPoly);
+ if (coroParam)
+ return 0;
+ }
+ return -1;
+
+ case HOLD:
+ // DW2 only
+ Hold(pp[0]);
return -1;
case HOOKSCENE:
+ // Common to both DW1 & DW2
pp -= 2; // 3 parameters
- hookscene(pp[0], pp[1], pp[2]);
+ HookScene(pp[0], pp[1], pp[2]);
return -3;
case IDLETIME:
- pp[0] = idletime();
+ // Common to both DW1 & DW2
+ pp[0] = IdleTime();
return 0;
case ININVENTORY:
- pp[0] = ininventory(pp[0]);
+ // DW1 only
+ pp[0] = InInventory(pp[0]);
return 0; // using return value
+ case INSTANTSCROLL:
+ // DW2 only
+ InstantScroll(pp[0]);
+ return -1;
+
case INVDEPICT:
+ // DW1 only
pp -= 1; // 2 parameters
- invdepict(pp[0], pp[1]);
+ InvDepict(pp[0], pp[1]);
return -2;
case INVENTORY:
- inventory(pp[0], pic->escOn, pic->myescEvent);
+ // Common to both DW1 & DW2
+ Inventory(pp[0], pic->escOn, pic->myEscape);
return -1;
+ case INVPLAY:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ InvPlay(pp[0], pp[1]);
+ return -2;
+
case INWHICHINV:
- pp[0] = inwhichinv(pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = InWhichInv(pp[0]);
return 0; // using return value
case KILLACTOR:
- killactor(pp[0]);
+ // DW1 only
+ if (TinselV2)
+ error("KillActor() was not expected to be required!");
+
+ KillActor(pp[0]);
return -1;
case KILLBLOCK:
- killblock(pp[0]);
+ // DW1 only
+ KillBlock(pp[0]);
return -1;
case KILLEXIT:
- killexit(pp[0]);
+ // DW1 only
+ KillExit(pp[0]);
+ return -1;
+
+ case KILLGLOBALPROCESS:
+ // DW2 only
+ KillGlobalProcess(pp[0]);
+ return -1;
+
+ case KILLPROCESS:
+ // DW2 only
+ KillProcess(pp[0]);
return -1;
case KILLTAG:
- killtag(pp[0]);
+ // DW1 only
+ KillTag(coroParam, pp[0]);
return -1;
- case LEFTOFFSET:
- pp[0] = ltoffset(LEFTOFFSET);
- return 0;
+ case LOCALVAR:
+ // DW2 only
+ error("LocalVar isn't a real function!");
case MOVECURSOR:
+ // Common to both DW1 & DW2
pp -= 1; // 2 parameters
- movecursor(pp[0], pp[1]);
+ MoveCursor(pp[0], pp[1]);
return -2;
+ case MOVETAG:
+ // DW2 only
+ pp -= 2; // 3 parameters
+ MoveTag(pp[0], pp[1], pp[2], pic->hPoly);
+ return -3;
+
+ case MOVETAGTO:
+ // DW2 only
+ pp -= 2; // 3 parameters
+ MoveTagTo(pp[0], pp[1], pp[2], pic->hPoly);
+ return -3;
+
case NEWSCENE:
+ // Common to both DW1 & DW2
pp -= 2; // 3 parameters
if (*pResumeState == RES_2)
*pResumeState = RES_NOT;
else
- newscene(coroParam, pp[0], pp[1], pp[2]);
+ NewScene(coroParam, pp[0], pp[1], pp[2]);
return -3;
case NOBLOCKING:
- noblocking();
+ // Common to both DW1 & DW2
+ NoBlocking();
+ return 0;
+
+ case NOPAUSE:
+ // DW2 only
+ bNoPause = true;
return 0;
case NOSCROLL:
+ // Common to both DW1 & DW2
pp -= 3; // 4 parameters
- noscroll(pp[0], pp[1], pp[2], pp[3]);
+ NoScroll(pp[0], pp[1], pp[2], pp[3]);
return -4;
case OBJECTHELD:
- objectheld(pp[0]);
+ // DW1 only
+ ObjectHeld(pp[0]);
return -1;
case OFFSET:
- pp -= 1; // 2 parameters
- offset(pp[0], pp[1]);
- return -2;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 2; // 2 parameters
+ Offset((EXTREME)pp[0], pp[1], pp[2]);
+ return -3;
+ } else {
+ pp -= 1; // 2 parameters
+ Offset(EX_USEXY, pp[0], pp[1]);
+ return -2;
+ }
+
+ case OTHEROBJECT:
+ // DW2 only
+ pp[0] = OtherObject(pic->pinvo);
+ return 0;
+
+ case PAUSE:
+ // DW2 only
+ WaitTime(coroParam, 1, true, pic->escOn, pic->myEscape);
+ return 0;
case PLAY:
- pp -= 5; // 6 parameters
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 3; // 4 parameters
+ if (*pResumeState == RES_1 && IsCdPlayHandle(pp[0]))
+ *pResumeState = RES_NOT;
+ else {
+ Play(coroParam, pp[0], pp[1], pp[2], pp[3], pic->myEscape, false,
+ pic->event, pic->hPoly, pic->idActor);
+
+ if (coroParam)
+ return 0;
+ }
+ return -4;
- if (pic->event == ENTER || pic->event == LEAVE)
- play(coroParam, pp[0], pp[1], pp[2], pp[5], 0, false, 0, pic->escOn, pic->myescEvent, false);
- else
- play(coroParam, pp[0], pp[1], pp[2], pp[5], pic->actorid, false, 0, pic->escOn, pic->myescEvent, false);
- return -6;
+ } else {
+ pp -= 5; // 6 parameters
+
+ if (pic->event == WALKIN || pic->event == WALKOUT)
+ Play(coroParam, pp[0], pp[1], pp[2], pp[5], 0, false, 0, pic->escOn, pic->myEscape, false);
+ else
+ Play(coroParam, pp[0], pp[1], pp[2], pp[5], pic->idActor, false, 0, pic->escOn, pic->myEscape, false);
+ return -6;
+ }
case PLAYMIDI:
+ // Common to both DW1 & DW2
pp -= 2; // 3 parameters
- playmidi(coroParam, pp[0], pp[1], pp[2]);
+ PlayMidi(coroParam, pp[0], pp[1], pp[2]);
return -3;
+ case PLAYMOVIE:
+ // DW2 only
+ PlayMovie(coroParam, pp[0], pic->myEscape);
+ return -1;
+
+ case PLAYMUSIC:
+ // DW2 only
+ PlayMusic(pp[0]);
+ return -1;
+
case PLAYRTF:
+ // Common to both DW1 & DW2
error("playrtf only applies to cdi!");
case PLAYSAMPLE:
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 3; // 4 parameters
+ PlaySample(coroParam, pp[0], pp[1], pp[2], pp[3], pic->myEscape);
+ return -4;
+ } else {
+ pp -= 1; // 2 parameters
+ PlaySample(coroParam, pp[0], pp[1], pic->escOn, pic->myEscape);
+ return -2;
+ }
+
+ case POINTACTOR:
+ // DW2 only
+ PointActor(pp[0]);
+ return -1;
+
+ case POINTTAG:
+ // DW2 only
+ PointTag(pp[0], pic->hPoly);
+ return -1;
+
+ case POSTACTOR:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ PostActor(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->hPoly, pic->idActor, pic->myEscape);
+ return -2;
+
+ case POSTGLOBALPROCESS:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ PostGlobalProcess(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->myEscape);
+ return -2;
+
+ case POSTOBJECT:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ PostObject(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->myEscape);
+ return -2;
+
+ case POSTPROCESS:
+ // DW2 only
pp -= 1; // 2 parameters
- playsample(coroParam, pp[0], pp[1], pic->escOn, pic->myescEvent);
+ PostProcess(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->myEscape);
return -2;
+ case POSTTAG:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ PostTag(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->hPoly, pic->myEscape);
+ return -2;
+
+
case PREPARESCENE:
- preparescene(pp[0]);
+ // DW1 only
+ PrepareScene(pp[0]);
return -1;
case PRINT:
- pp -= 5; // 6 parameters
- /* pp[2] was intended to be attribute */
- print(coroParam, pp[0], pp[1], pp[3], pp[4], pp[5], pic->escOn, pic->myescEvent);
- return -6;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 4; // 5 parameters
+ Print(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4] != 0, pic->escOn, pic->myEscape);
+ return -5;
+ } else {
+ pp -= 5; // 6 parameters
+ /* pp[2] was intended to be attribute */
+ Print(coroParam, pp[0], pp[1], pp[3], pp[4], pp[5] == 2, pic->escOn, pic->myEscape);
+ return -6;
+ }
+
+ case PRINTCURSOR:
+ // DW2 only
+ PrintTag(pic->hPoly, pp[0], pic->idActor, true);
+ return -1;
case PRINTOBJ:
- printobj(coroParam, pp[0], pic->pinvo, pic->event);
+ // Common to both DW1 & DW2
+ PrintObj(coroParam, pp[0], pic->pinvo, pic->event, pic->myEscape);
return -1;
case PRINTTAG:
- printtag(pic->hpoly, pp[0]);
+ // Common to both DW1 & DW2
+ PrintTag(pic->hPoly, pp[0], TinselV2 ? pic->idActor : 0, false);
return -1;
case QUITGAME:
- quitgame();
+ // Common to both DW1 & DW2
+ QuitGame();
return 0;
case RANDOM:
+ // Common to both DW1 & DW2
pp -= 2; // 3 parameters
- pp[0] = dw_random(pp[0], pp[1], pp[2]);
+ pp[0] = RandomFn(pp[0], pp[1], pp[2]);
return -2; // One holds return value
case RESETIDLETIME:
- resetidletime();
+ // Common to both DW1 & DW2
+ ResetIdleTime();
return 0;
case RESTARTGAME:
- restartgame();
+ // Common to both DW1 & DW2
+ RestartGame();
return 0;
+ case RESTORESCENE:
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ RestoreScene(coroParam, (TRANSITS)pp[0]);
+ return -1;
+ } else {
+ RestoreScene(coroParam, TRANS_FADE);
+ return 0;
+ }
+
case RESTORE_CUT:
- restore_scene(false);
+ // DW1 only
+ RestoreScene(coroParam, TRANS_CUT);
return 0;
- case RESTORE_SCENE:
- restore_scene(true);
+ case RESUMELASTGAME:
+ // DW2 only
+ ResumeLastGame();
return 0;
case RUNMODE:
- pp[0] = runmode();
+ // Common to both DW1 & DW2
+ pp[0] = RunMode();
return 0;
case SAMPLEPLAYING:
- pp[0] = sampleplaying(pic->escOn, pic->myescEvent);
+ // DW1 only
+ pp[0] = SamplePlaying(pic->escOn, pic->myEscape);
return 0;
- case SAVE_SCENE:
+ case SAVESCENE:
+ // Common to both DW1 & DW2
if (*pResumeState == RES_1)
*pResumeState = RES_2;
else
- save_scene(coroParam);
+ SaveScene(coroParam);
return 0;
+ case SAY:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ TalkOrSay(coroParam, IS_SAY, pp[1], 0, 0, 0, pp[0], false, pic->escOn, pic->myEscape);
+ return -2;
+
+ case SAYAT:
+ // DW2 only
+ pp -= 4; // 5 parameters
+ TalkOrSay(coroParam, IS_SAYAT, pp[3], pp[1], pp[2], 0, pp[0], pp[4], pic->escOn, pic->myEscape);
+ return -5;
+
case SCALINGREELS:
+ // Common to both DW1 & DW2
pp -= 6; // 7 parameters
- scalingreels(pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pp[6]);
+ ScalingReels(pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pp[6]);
return -7;
case SCANICON:
- pp[0] = scanicon();
+ // DW1 only
+ pp[0] = ScanIcon();
+ return 0;
+
+ case SCREENXPOS:
+ // Common to both DW1 & DW2
+ pp[0] = LToffset(SCREENXPOS);
+ return 0;
+
+ case SCREENYPOS:
+ // Common to both DW1 & DW2
+ pp[0] = LToffset(SCREENYPOS);
return 0;
case SCROLL:
- pp -= 3; // 4 parameters
- scroll(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myescEvent);
- return -4;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 5; // 6 parameters
+ Scroll(coroParam, (EXTREME)pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pic->escOn, pic->myEscape);
+ return -6;
+ } else {
+ pp -= 3; // 4 parameters
+ Scroll(coroParam, EX_USEXY, pp[0], pp[1], pp[2], pp[2], pp[3], pic->escOn, pic->myEscape);
+ return -4;
+ }
+
+ case SCROLLPARAMETERS:
+ // DW2 only
+ pp -= 6; // 7 parameters
+ ScrollParameters(pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pp[6]);
+ return -7;
+
+ case SENDTAG:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ bool result;
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic, &result);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+ pp[0] = result ? 1 : 0;
+ } else {
+ bool result;
+ SendTag(coroParam, pp[0], (TINSEL_EVENT)pp[1], pic->hPoly, pic->myEscape, &result);
+ if (coroParam)
+ return 0;
+
+ pp[0] = result;
+ }
+ return -1;
+
case SETACTOR:
- setactor(pp[0]);
+ // DW1 only
+ SetActor(pp[0]);
return -1;
case SETBLOCK:
- setblock(pp[0]);
+ // DW1 only
+ SetBlock(pp[0]);
return -1;
case SETEXIT:
- setexit(pp[0]);
+ // DW1 only
+ SetExit(pp[0]);
return -1;
case SETINVLIMIT:
+ // Common to both DW1 & DW2
pp -= 1; // 2 parameters
- setinvlimit(pp[0], pp[1]);
+ SetInvLimit(pp[0], pp[1]);
return -2;
case SETINVSIZE:
+ // Common to both DW1 & DW2
pp -= 6; // 7 parameters
- setinvsize(pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pp[6]);
+ SetInvSize(pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pp[6]);
return -7;
case SETLANGUAGE:
- setlanguage((LANGUAGE)pp[0]);
+ // Common to both DW1 & DW2
+ SetLanguage((LANGUAGE)pp[0]);
return -1;
case SETPALETTE:
- setpalette(pp[0], pic->escOn, pic->myescEvent);
- return -1;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ // Note: Although DW2 introduces parameters for start and length, it doesn't use them
+ pp -= 2;
+ SetPalette(pp[0], pic->escOn, pic->myEscape);
+ return -3;
+ } else {
+ SetPalette(pp[0], pic->escOn, pic->myEscape);
+ return -1;
+ }
+
+ case SETSYSTEMSTRING:
+ // DW2 only
+ pp -= 1; // 2 parameters
+ SetSystemString(pp[0], pp[1]);
+ return -2;
+
+ case SETSYSTEMVAR:
+ // DW1 only
+ pp -= 1; // 2 parameters
+ SetSystemVar(pp[0], pp[1]);
+ return -2;
case SETTAG:
- settag(pp[0]);
+ // DW1 only
+ SetTag(coroParam, pp[0]);
return -1;
case SETTIMER:
+ // DW1 only
pp -= 3; // 4 parameters
- settimer(pp[0], pp[1], pp[2], pp[3]);
+ SetTimer(pp[0], pp[1], pp[2], pp[3]);
return -4;
+ case SHELL:
+ // DW2 only
+ Shell(pp[0]);
+ return 0;
+
+ case SHOWACTOR:
+ // DW2 only
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic);
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+ } else
+ ShowActorFn(coroParam, pp[0]);
+ return -1;
+
+ case SHOWBLOCK:
+ // DW2 only
+ ShowBlock(pp[0]);
+ return -1;
+
+ case SHOWEFFECT:
+ // DW2 only
+ ShowEffect(pp[0]);
+ return -1;
+
+ case SHOWMENU:
+ // DW2 only
+ ShowMenu();
+ return 0;
+
+ case SHOWPATH:
+ // DW2 only
+ ShowPath(pp[0]);
+ return -1;
+
case SHOWPOS:
+ // DW1 only
#ifdef DEBUG
showpos();
#endif
return 0;
+ case SHOWREFER:
+ // DW2 only
+ ShowRefer(pp[0]);
+ return -1;
+
case SHOWSTRING:
#ifdef DEBUG
showstring();
#endif
return 0;
+ case SHOWTAG:
+ // DW2 only
+ if (*pResumeState == RES_1 && pic->resumeCode == RES_WAITING) {
+ *pResumeState = RES_NOT;
+ FinishWaiting(coroParam, pic);
+
+ if (coroParam) {
+ *pResumeState = RES_1;
+ return 0;
+ }
+ } else {
+ ShowTag(coroParam, pp[0], pic->hPoly);
+ }
+ return -1;
+
case SPLAY:
+ // DW1 only
pp -= 6; // 7 parameters
- if (pic->event == ENTER || pic->event == LEAVE)
- splay(coroParam, pp[0], pp[1], pp[2], pp[3], pp[6], 0, pic->escOn, pic->myescEvent);
+ if (pic->event == WALKIN || pic->event == WALKOUT)
+ SPlay(coroParam, pp[0], pp[1], pp[2], pp[3], pp[6], 0, pic->escOn, pic->myEscape);
else
- splay(coroParam, pp[0], pp[1], pp[2], pp[3], pp[6], pic->actorid, pic->escOn, pic->myescEvent);
+ SPlay(coroParam, pp[0], pp[1], pp[2], pp[3], pp[6], pic->idActor, pic->escOn, pic->myEscape);
return -7;
case STAND:
+ // Common to both DW1 & DW2
pp -= 3; // 4 parameters
- stand(pp[0], pp[1], pp[2], pp[3]);
+ Stand(coroParam, pp[0], pp[1], pp[2], pp[3]);
return -4;
case STANDTAG:
- standtag(pp[0], pic->hpoly);
+ // Common to both DW1 & DW2
+ StandTag(pp[0], pic->hPoly);
return -1;
- case STOP:
- stop(pp[0]);
+ case STARTGLOBALPROCESS:
+ // DW2 only
+ StartGlobalProcess(coroParam, pp[0]);
return -1;
+ case STARTPROCESS:
+ // DW2 only
+ StartProcess(coroParam, pp[0]);
+ return -1;
+
+ case STARTTIMER:
+ // DW2 only
+ pp -= 3; // 4 parameters
+ StartTimerFn(pp[0], pp[1], pp[2], pp[3]);
+ return -4;
+
case STOPMIDI:
- stopmidi();
+ // DW1 only
+ StopMidiFn();
return 0;
case STOPSAMPLE:
- stopsample();
- return 0;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ StopSample(pp[0]);
+ return -1;
+ } else {
+ StopSample();
+ return 0;
+ }
+
+ case STOPWALK:
+ // Common to both DW1 & DW2 only
+ StopWalk(pp[0]);
+ return -1;
case SUBTITLES:
- subtitles(pp[0]);
+ // Common to both DW1 & DW2
+ Subtitles(pp[0]);
return -1;
case SWALK:
+ // Common to both DW1 & DW2
pp -= 5; // 6 parameters
- swalk(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pic->escOn, pic->myescEvent);
+ Swalk(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], -1, pic->escOn, pic->myEscape);
return -6;
+ case SWALKZ:
+ // DW2 only
+ pp -= 6; // 7 parameters
+ Swalk(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], pp[5], pp[6], pic->escOn, pic->myEscape);
+ return -7;
+
+ case SYSTEMVAR:
+ // DW2 only
+ pp[0] = SystemVar(pp[0]);
+ return 0;
+
case TAGACTOR:
pp -= 2; // 3 parameters
- tagactor(pp[0], pp[1], pp[2]);
+ TagActor(pp[0], pp[1], pp[2]);
return -3;
+ case TAGTAGXPOS:
+ case TAGTAGYPOS:
+ case TAGWALKXPOS:
+ case TAGWALKYPOS:
+ // DW2 only
+ pp[0] = TagPos((MASTER_LIB_CODES)libCode, pp[0], pic->hPoly);
+ return 0;
+
case TALK:
+ // Common to both DW1 & DW2
pp -= 1; // 2 parameters
- if (pic->event == ENTER || pic->event == LEAVE)
- talk(coroParam, pp[0], pp[1], 0, pic->escOn, pic->myescEvent);
+ if (TinselV2)
+ TalkOrSay(coroParam, IS_TALK, pp[1], 0, 0, pp[0], 0, false, pic->escOn, pic->myEscape);
+ else if (pic->event == WALKIN || pic->event == WALKOUT)
+ TalkOrSay(coroParam, IS_TALK, pp[1], 0, 0, pp[0], 0, false, pic->escOn, pic->myEscape);
else
- talk(coroParam, pp[0], pp[1], pic->actorid, pic->escOn, pic->myescEvent);
+ TalkOrSay(coroParam, IS_TALK, pp[1], 0, 0, pp[0], pic->idActor, false, pic->escOn, pic->myEscape);
return -2;
case TALKAT:
- pp -= 3; // 4 parameters
- talkat(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myescEvent);
- return -4;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 4; // 5 parameters
+ TalkOrSay(coroParam, IS_TALKAT, pp[3], pp[1], pp[2], 0, pp[0], pp[4], pic->escOn, pic->myEscape);
+ return -5;
+ } else {
+ pp -= 3; // 4 parameters
+ TalkAt(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myEscape);
+ return -4;
+ }
case TALKATS:
+ // DW1 only
pp -= 4; // 5 parameters
- talkats(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], pic->escOn, pic->myescEvent);
+ TalkAtS(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], pic->escOn, pic->myEscape);
return -5;
case TALKATTR:
+ // DW1 only
pp -= 2; // 3 parameters
- talkattr(pp[0], pp[1], pp[2], pic->escOn, pic->myescEvent);
+ TalkAttr(pp[0], pp[1], pp[2], pic->escOn, pic->myEscape);
+ return -3;
+
+ case TALKPALETTEINDEX:
+ // DW1 only
+ TalkPaletteIndex(pp[0]);
+ return -1;
+
+ case TALKRGB:
+ // DW2 only
+ TalkRGB(pp[0], pic->myEscape);
return -3;
+ case TALKVIA:
+ // DW2 only
+ TalkVia(pp[0]);
+ return -1;
+
+ case TEMPTAGFONT:
+ // DW2 only
+ TempTagFont(pp[0]);
+ return -1;
+
+ case TEMPTALKFONT:
+ // DW2 only
+ TempTalkFont(pp[0]);
+ return -1;
+
+ case THISOBJECT:
+ // DW2 only
+ pp[0] = ThisObject(pic->pinvo);
+ return 0;
+
+ case THISTAG:
+ // DW2 only
+ pp[0] = ThisTag(pic->hPoly);
+ return 0;
+
case TIMER:
- pp[0] = timer(pp[0]);
+ // Common to both DW1 & DW2
+ pp[0] = TimerFn(pp[0]);
return 0;
- case TOPOFFSET:
- pp[0] = ltoffset(TOPOFFSET);
+ case TOPIC:
+ // DW2 only
+ pp[0] = Topic();
return 0;
case TOPPLAY:
- pp -= 5; // 6 parameters
- topplay(coroParam, pp[0], pp[1], pp[2], pp[5], pic->actorid, false, 0, pic->escOn, pic->myescEvent);
- return -6;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 3; // 4 parameters
+ TopPlay(coroParam, pp[0], pp[1], pp[2], pp[3], pic->myEscape, pic->event);
+ return -4;
+ } else {
+ pp -= 5; // 6 parameters
+ TopPlay(coroParam, pp[0], pp[1], pp[2], pp[5], pic->idActor, false, 0, pic->escOn, pic->myEscape);
+ return -6;
+ }
case TOPWINDOW:
- topwindow(pp[0]);
+ // Common to both DW1 & DW2
+ TopWindow(pp[0]);
+ return -1;
+
+ case TRANSLUCENTINDEX:
+ // DW2 only
+ TranslucentIndex(pp[0]);
return -1;
case TRYPLAYSAMPLE:
+ // DW1 only
pp -= 1; // 2 parameters
- tryplaysample(coroParam, pp[0], pp[1], pic->escOn, pic->myescEvent);
+ TryPlaySample(coroParam, pp[0], pp[1], pic->escOn, pic->myEscape);
return -2;
+ case UNDIMMUSIC:
+ // DW2 only
+ UnDimMusic();
+ return 0;
+
case UNHOOKSCENE:
- unhookscene();
+ // Common to both DW1 & DW2
+ UnHookSceneFn();
return 0;
case UNTAGACTOR:
- untagactor(pp[0]);
+ // DW1 only
+ UnTagActorFn(pp[0]);
return -1;
case VIBRATE:
- vibrate();
- return 0;
-
- case WAITKEY:
- waitkey(coroParam, pic->escOn, pic->myescEvent);
+ // DW1 only
+ Vibrate();
return 0;
case WAITFRAME:
+ // Common to both DW1 & DW2
pp -= 1; // 2 parameters
- waitframe(coroParam, pp[0], pp[1], pic->escOn, pic->myescEvent);
+ WaitFrame(coroParam, pp[0], pp[1], pic->escOn, pic->myEscape);
return -2;
+ case WAITKEY:
+ // Common to both DW1 & DW2
+ WaitKey(coroParam, pic->escOn, pic->myEscape);
+ return 0;
+
+ case WAITSCROLL:
+ // DW2 only
+ WaitScroll(coroParam, pic->myEscape);
+ return 0;
+
case WAITTIME:
+ // Common to both DW1 & DW2
pp -= 1; // 2 parameters
- waittime(coroParam, pp[0], pp[1], pic->escOn, pic->myescEvent);
+ WaitTime(coroParam, pp[0], pp[1], pic->escOn, pic->myEscape);
return -2;
case WALK:
+ // Common to both DW1 & DW2
pp -= 4; // 5 parameters
- walk(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], false, pic->escOn, pic->myescEvent);
+ Walk(coroParam, pp[0], pp[1], pp[2], pp[3], pp[4], false, -1, pic->escOn, pic->myEscape);
return -5;
case WALKED: {
+ // Common to both DW1 & DW2
pp -= 3; // 4 parameters
bool tmp;
- walked(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myescEvent, tmp);
+ Walked(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myEscape, tmp);
if (!coroParam) {
// Only write the result to the stack if walked actually completed running.
pp[0] = tmp;
@@ -2941,24 +5522,65 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi
return -3;
case WALKINGACTOR:
- pp -= 40; // 41 parameters
- walkingactor(pp[0], (SCNHANDLE *)&pp[1]);
- return -41;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ // DW2 doesn't use a second parameter to WalkingActor
+ WalkingActor(pp[0]);
+ return -1;
+ } else {
+ pp -= 40; // 41 parameters
+ WalkingActor(pp[0], (SCNHANDLE *)&pp[1]);
+ return -41;
+ }
case WALKPOLY:
- pp -= 2; // 3 parameters
- walkpoly(coroParam, pp[0], pp[1], pic->hpoly, pic->escOn, pic->myescEvent);
- return -3;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 1; // 2 parameters
+ WalkPoly(coroParam, pp[0], pp[1], pic->hPoly, pic->escOn, pic->myEscape);
+ return -2;
+ } else {
+ pp -= 2; // 3 parameters
+ WalkPoly(coroParam, pp[0], pp[1], pic->hPoly, pic->escOn, pic->myEscape);
+ return -3;
+ }
case WALKTAG:
- pp -= 2; // 3 parameters
- walktag(coroParam, pp[0], pp[1], pic->hpoly, pic->escOn, pic->myescEvent);
- return -3;
+ // Common to both DW1 & DW2
+ if (TinselV2) {
+ pp -= 1; // 2 parameters
+ WalkTag(coroParam, pp[0], pp[1], pic->hPoly, pic->escOn, pic->myEscape);
+ return -2;
+ } else {
+ pp -= 2; // 3 parameters
+ WalkTag(coroParam, pp[0], pp[1], pic->hPoly, pic->escOn, pic->myEscape);
+ return -3;
+ }
+
+ case WALKXPOS:
+ // DW2 only
+ pp[0] = WalkXPos();
+ return 0;
+
+ case WALKYPOS:
+ // DW2 only
+ pp[0] = WalkYPos();
+ return 0;
+
+ case WHICHCD:
+ // DW2 only
+ pp[0] = WhichCd();
+ return 0;
case WHICHINVENTORY:
- pp[0] = whichinventory();
+ // Common to both DW1 & DW2
+ pp[0] = WhichInventory();
return 0;
+ case ZZZZZZ:
+ // DW2 only - dummy routine used during debugging
+ return -1;
+
default:
error("Unsupported library function");
}
@@ -2966,5 +5588,4 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi
error("Can't possibly get here");
}
-
} // end of namespace Tinsel