sm64/scene.c

517 lines
15 KiB
C

/********************************************************************************
Ultra 64 MARIO Brothers
scene management module
Copyright 1996 Nintendo co., ltd. All rights reserved
April 23, 1996
********************************************************************************/
#include "headers.h"
extern void DrawMessage(void);
extern short MessageEvent(void);
extern void MeterGaugeEvent(void);
MapNode *shapeList[SN_NUMSHAPES]; /* shape list memory */
SceneRecord sceneList[SN_NUMSCENES]; /* scene list memory */
ActorRecord starringActor[1]; /* Mario's actor record */
ActorPtr marioActor = &starringActor[0]; /* pointer to the Mario'actor */
MapNode **stageShapes = shapeList; /* pointer to the shape list */
SceneRecord *stageScenes = sceneList; /* pointer to the scene list */
ScenePtr snSceneInfo = NULL; /* pointer to the active scene information */
EndingPtr snEndingScene = NULL; /* pointer to the ending scene information */
SnWipeCtrl wipeControl; /* wipe control record */
static Vp *snViewPort = NULL; /* pointer to the optional view port */
static Vp *snTrimming = NULL; /* pointer to the trimming port */
static short faderDelay = 0; /* delayed fader counter */
static ulong backColor = 0; /* back color (out of trimming) */
static ulong blankColor = 0; /* software blanking color */
static uchar blankColorR = 0; /* software bankking color red level */
static uchar blankColorG = 0; /* software blanking color green level */
static uchar blankColorB = 0; /* software blanking color green level */
short activePlayerNo = 1; /* active player number */
short activeCourseNo; /* active course number */
short activeLevelNo; /* active star level number */
short activeStageNo = 1; /* active stage number */
short activeSceneNo; /* active scene number */
short ramSaveCourse; /* RAM save course number */
short mesgEvent; /* result of message routine */
short mesgLatch; /* latch for message result */
/********************************************************************************/
/* Player entrant path name lists. */
/********************************************************************************/
#define NUM_PATHNAMES 20
extern Path e_player_waiting[];
extern Path e_player_landing[];
extern Path e_player_falling[];
extern Path e_player_rolling[];
extern Path e_player_downing[];
extern Path e_player_entpict[];
extern Path e_player_flight[];
extern Path e_player_swimming[];
extern Path e_player_entwinner[];
extern Path e_player_entloser[];
extern Path e_player_landwinner[];
extern Path e_player_landloser[];
extern Path e_player_pushout[];
extern Path e_player_pushdown[];
static Path *pathNameList[NUM_PATHNAMES] = {
e_tripdoor,
e_tripstar,
e_tripchimney,
e_tripchimney2,
e_dokan,
e_warp,
e_player_waiting,
e_player_landing,
e_player_falling,
e_player_rolling,
e_player_downing,
e_player_entpict,
e_player_flight,
e_player_swimming,
e_player_entwinner,
e_player_entloser,
e_player_landwinner,
e_player_landloser,
e_player_pushout,
e_player_pushdown
};
static uchar portNameList[NUM_PATHNAMES] = {
SN_TRIP_DOOR,
SN_TRIP_STAR,
SN_TRIP_CHIMNEY,
SN_TRIP_CHIMNEY,
SN_TRIP_CHIMNEY,
SN_WARP_POINT,
SN_ENTER_WAITING,
SN_ENTER_LANDING,
SN_ENTER_FALLING,
SN_ENTER_ROLLING,
SN_ENTER_DOWNING,
SN_ENTER_PICTURE,
SN_ENTER_FLIGHT,
SN_ENTER_SWIMMING,
SN_ENTER_WINNER,
SN_ENTER_LOSER,
SN_ENTER_LANDWINNER,
SN_ENTER_LANDLOSER,
SN_ENTER_PUSHOUT,
SN_ENTER_PUSHDOWN
};
/********************************************************************************/
/* Standard view port record. */
/********************************************************************************/
static Vp viewport = {
320*2, 240*2, G_MAXZ/2, 0,
320*2, 240*2, G_MAXZ/2, 0,
};
/*===============================================================================
*
*
* Trip port support routines.
*
*/
#define SnGetBlankColor(r,g,b) (r=blankColorR,g=blankColorG,b=blankColorB)
/********************************************************************************/
/* Set view port. */
/********************************************************************************/
extern void
SnSetViewPort(Vp *viewing, Vp *trimming, uchar red, uchar green, uchar blue)
{
ushort color = RGBA16(red>>3,green>>3,blue>>3,1);
backColor = (color << 16) | color;
snViewPort = viewing;
snTrimming = trimming;
}
/********************************************************************************/
/* Set software blanking color. */
/********************************************************************************/
static void
SnSetBlankColor(uchar red, uchar green, uchar blue)
{
ushort color = RGBA16(red>>3,green>>3,blue>>3,1);
blankColor = (color << 16) | color;
blankColorR = red;
blankColorG = green;
blankColorB = blue;
}
/********************************************************************************/
/* Display demo message. */
/********************************************************************************/
extern void
SnDisplayDemoMessage(void)
{
#if CHINA
unsigned char str[] ={0xb0, 0x00};
#endif
if ((frameCounter & 0x1f) < 20) {
if (contConnection == 0) {
dcprintf(160,20, "NO CONTROLLER");
} else {
#if CHINA
dcprintf(60,38, str);
#else
dcprintf(60,38, "PRESS");
#endif
dcprintf(60,20, "START");
}
}
}
/*===============================================================================
*
*
* Trip port support routines.
*
*/
/********************************************************************************/
/* Get trip port type. */
/********************************************************************************/
extern int
SnGetPortType(StrategyPtr stratp)
{
int count;
Path *pathname = VirtualToSegment(SEGMENT_PATHDATA, stratp->pathname);
for (count = 0; count < NUM_PATHNAMES; count++) {
if (pathname == pathNameList[count]) return((int)portNameList[count]);
}
return(0);
}
/********************************************************************************/
/* Get port pointer. */
/********************************************************************************/
extern PortPtr
SnGetPortPtr(uchar code)
{
PortPtr port = NULL;
for (port = snSceneInfo->ports; port != NULL; port = port->next) {
if (port->number == code) break;
}
return(port);
}
/********************************************************************************/
/* Find port pointer. */
/********************************************************************************/
extern PortPtr
SnFindPortPtr(StrategyPtr stratp)
{
uchar code = (stratp->s[stw_actorcode].d & 0x00ff0000) >> 16;
return( SnGetPortPtr(code));
}
/********************************************************************************/
/* Check player transfer. */
/********************************************************************************/
static void
InitPorts(void)
{
PortPtr port;
MapNode *node = strategyGroup.child;
do {
StrategyPtr stratp = (StrategyPtr)node;
if ((stratp->status != 0) && SnGetPortType(stratp)) {
if ((port = SnFindPortPtr(stratp)) != NULL) port->stratp = stratp;
}
} while ((node = node->next) != strategyGroup.child);
}
/*===============================================================================
*
*
* Scene management routines.
*
*/
//********************************************************************************/
/* */
/* Initialize scene informations. */
/* */
/********************************************************************************/
extern void
SnInitSceneInfo(void)
{
int count;
snSceneInfo = NULL;
wipeControl.active = 0;
wipeControl.blank = 0;
marioActor->sceneNo = -1;
for (count = 0; count < SN_NUMSCENES; count++) {
sceneList[count].sceneNo = count;
sceneList[count].entrant = 0;
sceneList[count].environment = 0;
sceneList[count].mapScene = NULL;
sceneList[count].mapInfo = NULL;
sceneList[count].areaInfo = NULL;
sceneList[count].tagInfo = NULL;
sceneList[count].ports = NULL;
sceneList[count].bgport = NULL;
sceneList[count].connect = NULL;
sceneList[count].actors = NULL;
sceneList[count].camera = NULL;
sceneList[count].windzone = NULL;
sceneList[count].waterjet[0] = NULL;
sceneList[count].waterjet[1] = NULL;
sceneList[count].message[0] = 255;
sceneList[count].message[1] = 255;
sceneList[count].audmode = 0;
sceneList[count].musicno = 0;
}
}
/********************************************************************************/
/* Dispose scene. */
/********************************************************************************/
extern void
SnDisposeScene(void)
{
int count;
if (snSceneInfo != NULL) {
MapSendMessage(snSceneInfo->mapScene, MAP_CBACK_SUSPEND);
snSceneInfo = NULL;
wipeControl.active = 0;
}
for (count = 0; count < SN_NUMSCENES; count++) {
if (sceneList[count].mapScene != NULL) {
MapSendMessage(sceneList[count].mapScene, MAP_CBACK_DISPOSE);
sceneList[count].mapScene = NULL;
}
}
}
/********************************************************************************/
/* Open the scene. */
/********************************************************************************/
extern void
SnOpenScene(int sceneNo)
{
if (snSceneInfo == NULL && sceneList[sceneNo].mapScene != NULL) {
snSceneInfo = &sceneList[sceneNo];
activeSceneNo = snSceneInfo->sceneNo;
if (snSceneInfo->mapInfo != NULL) mcInitBGCheck(sceneNo, snSceneInfo->mapInfo, snSceneInfo->areaInfo, snSceneInfo->tagInfo);
if (snSceneInfo->actors != NULL) SetStrategy(0, snSceneInfo->actors);
InitPorts();
MapSendMessage(snSceneInfo->mapScene, MAP_CBACK_ACTIVAT);
}
}
/********************************************************************************/
/* Close the scene. */
/********************************************************************************/
extern void
SnCloseScene(void)
{
if (snSceneInfo != NULL) {
RemoveStrategy(0, snSceneInfo->sceneNo);
MapSendMessage(snSceneInfo->mapScene, MAP_CBACK_SUSPEND);
snSceneInfo->entrant = 0;
snSceneInfo = NULL;
wipeControl.active = 0;
}
}
/********************************************************************************/
/* Enter the player. */
/********************************************************************************/
extern void
SnEnterPlayer(void)
{
Na_LevelSeAllStop();
SnOpenScene(marioActor->sceneNo);
if (snSceneInfo->sceneNo == marioActor->sceneNo) {
setflag(snSceneInfo->entrant, 1);
SetStrategy(0, marioActor);
}
}
/********************************************************************************/
/* Exit the player. */
/********************************************************************************/
extern void
SnExitPlayer(void)
{
if (snSceneInfo != NULL && (snSceneInfo->entrant & 1)) {
RemoveStrategy(0, marioActor->actorID);
clrflag(snSceneInfo->entrant, 1);
if (snSceneInfo->entrant == 0) SnCloseScene();
}
}
/********************************************************************************/
/* Change the scene. */
/********************************************************************************/
extern void
SnChangeScene(int newScene)
{
int entrant = snSceneInfo->entrant;
if (activeSceneNo != newScene) {
SnCloseScene();
SnOpenScene(newScene);
snSceneInfo->entrant = entrant;
player1stp->s[stw_effect].d = 0;
}
if (entrant & 1) player1stp->map.sceneNo = newScene, marioActor->sceneNo = newScene;
}
/********************************************************************************/
/* Do strategy execution. */
/********************************************************************************/
extern void
SnExecuteStrategy(void)
{
animationCounter += 1;
ExecStrategy(0);
}
/********************************************************************************/
/* Start screen fader. */
/********************************************************************************/
extern void
SnStartFader(short mode, short frame, uchar red, uchar green, uchar blue)
{
wipeControl.active = TRUE;
wipeControl.mode = mode;
wipeControl.frame = frame;
wipeControl.blank = 0;
if (mode & 1) SnSetBlankColor(red, green, blue);
else SnGetBlankColor(red, green, blue);
if (mode < 8) {
wipeControl.params.screen.red = red;
wipeControl.params.screen.green = green;
wipeControl.params.screen.blue = blue;
} else {
wipeControl.params.window.red = red;
wipeControl.params.window.green = green;
wipeControl.params.window.blue = blue;
wipeControl.params.window.start_xo = 160;
wipeControl.params.window.start_yo = 120;
wipeControl.params.window.end_xo = 160;
wipeControl.params.window.end_yo = 120;
wipeControl.params.window.angle_inc = 0;
if (mode & 1) {
wipeControl.params.window.start_side = 320;
wipeControl.params.window.end_side = (mode >= WIPE_DOCRO_WIN_CLOSE) ? 16 : 0;
} else {
wipeControl.params.window.start_side = (mode >= WIPE_DOCRO_WIN_OPEN ) ? 16 : 0;
wipeControl.params.window.end_side = 320;
}
}
}
/********************************************************************************/
/* Start screen fader with delay. */
/********************************************************************************/
extern void
SnDelayFader(short mode, short frame, uchar red, uchar green, uchar blue, short delay)
{
faderDelay = delay;
SnStartFader(mode, frame, red, green, blue);
}
/********************************************************************************/
/* Draw screens. */
/********************************************************************************/
extern void
SnDrawScreen(void)
{
if (snSceneInfo != NULL && wipeControl.blank == 0) {
DrawScene(snSceneInfo->mapScene, snViewPort, snTrimming, backColor);
gSPViewport(graphPtr++, K0_TO_PHYS(&viewport));
gDPSetScissor(graphPtr++, G_SC_NON_INTERLACE, 0, CLIP_UPPER, SCREEN_WIDTH, CLIP_LOWER);
MeterGaugeEvent();
gDPSetScissor(graphPtr++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
DrawMessage();
EndingDemoMessageEvent();
DrawStaffRoll();
gDPSetScissor(graphPtr++, G_SC_NON_INTERLACE, 0, CLIP_UPPER, SCREEN_WIDTH, CLIP_LOWER);
if ((mesgEvent = MessageEvent()) != 0) mesgLatch = mesgEvent;
if (snTrimming != NULL) SetTrimmingRectangle(snTrimming);
else gDPSetScissor(graphPtr++, G_SC_NON_INTERLACE, 0, CLIP_UPPER, SCREEN_WIDTH, CLIP_LOWER);
if (wipeControl.active) {
if (faderDelay == 0) {
wipeControl.active = !Wipe(0, wipeControl.mode, wipeControl.frame, (void *)&wipeControl.params);
if (wipeControl.active == 0) {
if (wipeControl.mode & 1) wipeControl.blank = 1;
else SnSetBlankColor(0, 0, 0);
}
} else {
faderDelay -= 1;
}
}
}
else {
DrawMessage();
if (snTrimming != NULL) SoftwareTrimBlanking(snTrimming, blankColor);
else SoftwareBlanking(blankColor);
}
snViewPort = NULL;
snTrimming = NULL;
}