Super Mario 64 OpenGL port for PC. Mirror of https://github.com/sm64pc/sm64pc https://github.com/sm64pc/sm64pc
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

270 lines
11 KiB

#include "ultra64.h"
#include "sm64.h"
#include "prevent_bss_reordering.h"
#include "types.h"
#include "game/memory.h"
#include "game/segment2.h"
#include "game/segment7.h"
#include "intro_geo.h"
#include "gfx_dimensions.h"
// frame counts for the zoom in, hold, and zoom out of title model
#define INTRO_STEPS_ZOOM_IN 20
#define INTRO_STEPS_HOLD_1 75
#define INTRO_STEPS_ZOOM_OUT 91
// background types
#define INTRO_BACKGROUND_SUPER_MARIO 0
#define INTRO_BACKGROUND_GAME_OVER 1
struct GraphNodeMore {
/*0x00*/ struct GraphNode node;
/*0x14*/ void *todo;
/*0x18*/ u32 unk18;
};
// title screen segment A
extern Gfx title_screen_bg_dl_0A000118[];
extern Gfx title_screen_bg_dl_0A000100[];
extern Gfx title_screen_bg_dl_0A000130[];
extern Gfx title_screen_bg_dl_0A000148[];
extern Gfx title_screen_bg_dl_0A000160[];
extern Gfx title_screen_bg_dl_0A000178[];
extern Gfx title_screen_bg_dl_0A000190[];
extern const u8 *const mario_title_texture_table[];
extern const u8 *const game_over_texture_table[];
// intro geo bss
s32 gGameOverFrameCounter;
s32 gGameOverTableIndex;
s16 gTitleZoomCounter;
s32 gTitleFadeCounter;
// intro screen background display lists for each of four 80x20 textures
Gfx *introBackgroundDlRows[] = { title_screen_bg_dl_0A000130, title_screen_bg_dl_0A000148,
title_screen_bg_dl_0A000160, title_screen_bg_dl_0A000178 };
// intro screen background texture X offsets
float introBackgroundOffsetX[] = {
0.0, 80.0, 160.0, 240.0, 0.0, 80.0, 160.0, 240.0, 0.0, 80.0, 160.0, 240.0,
};
// intro screen background texture Y offsets
float introBackgroundOffsetY[] = {
160.0, 160.0, 160.0, 160.0, 80.0, 80.0, 80.0, 80.0, 0.0, 0.0, 0.0, 0.0,
};
// table that points to either the "Super Mario 64" or "Game Over" tables
const u8 *const *introBackgroundTextureType[] = { mario_title_texture_table, game_over_texture_table };
s8 introBackgroundIndexTable[] = {
INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
};
// only one table of indexes listed
s8 *introBackgroundTables[] = { introBackgroundIndexTable };
s8 gameOverBackgroundTable[] = {
INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
};
// order of tiles that are flipped from "Game Over" to "Super Mario 64"
s8 gameOverBackgroundFlipOrder[] = { 0x00, 0x01, 0x02, 0x03, 0x07, 0x0B,
0x0a, 0x09, 0x08, 0x04, 0x05, 0x06 };
Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) {
struct GraphNode *graphNode; // sp4c
Gfx *displayList; // sp48
Gfx *displayListIter; // sp44
Mtx *scaleMat; // sp40
f32 *scaleTable1; // sp3c
f32 *scaleTable2; // sp38
f32 scaleX; // sp34
f32 scaleY; // sp30
f32 scaleZ; // sp2c
graphNode = sp54;
displayList = NULL;
displayListIter = NULL;
scaleTable1 = segmented_to_virtual(intro_seg7_table_0700C790);
scaleTable2 = segmented_to_virtual(intro_seg7_table_0700C880);
if (sp50 != 1) {
gTitleZoomCounter = 0;
} else if (sp50 == 1) {
graphNode->flags = (graphNode->flags & 0xFF) | 0x100;
scaleMat = alloc_display_list(sizeof(*scaleMat));
displayList = alloc_display_list(4 * sizeof(*displayList));
displayListIter = displayList;
if (gTitleZoomCounter >= 0 && gTitleZoomCounter < INTRO_STEPS_ZOOM_IN) {
scaleX = scaleTable1[gTitleZoomCounter * 3];
scaleY = scaleTable1[gTitleZoomCounter * 3 + 1];
scaleZ = scaleTable1[gTitleZoomCounter * 3 + 2];
} else if (gTitleZoomCounter >= INTRO_STEPS_ZOOM_IN && gTitleZoomCounter < INTRO_STEPS_HOLD_1) {
scaleX = 1.0f;
scaleY = 1.0f;
scaleZ = 1.0f;
} else if (gTitleZoomCounter >= INTRO_STEPS_HOLD_1
&& gTitleZoomCounter < INTRO_STEPS_ZOOM_OUT) {
scaleX = scaleTable2[(gTitleZoomCounter - INTRO_STEPS_HOLD_1) * 3];
scaleY = scaleTable2[(gTitleZoomCounter - INTRO_STEPS_HOLD_1) * 3 + 1];
scaleZ = scaleTable2[(gTitleZoomCounter - INTRO_STEPS_HOLD_1) * 3 + 2];
} else {
scaleX = 0.0f;
scaleY = 0.0f;
scaleZ = 0.0f;
}
guScale(scaleMat, scaleX, scaleY, scaleZ);
gSPMatrix(displayListIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
gSPDisplayList(displayListIter++, &intro_seg7_dl_0700B3A0);
gSPPopMatrix(displayListIter++, G_MTX_MODELVIEW);
gSPEndDisplayList(displayListIter);
gTitleZoomCounter++;
}
return displayList;
}
Gfx *geo_fade_transition(s32 sp40, struct GraphNode *sp44, UNUSED void *context) {
struct GraphNode *graphNode = sp44; // sp3c
Gfx *displayList = NULL; // sp38
Gfx *displayListIter = NULL; // sp34
if (sp40 != 1) {
gTitleFadeCounter = 0; // D_801B985C
} else if (sp40 == 1) {
displayList = alloc_display_list(5 * sizeof(*displayList));
displayListIter = displayList;
gSPDisplayList(displayListIter++, dl_proj_mtx_fullscreen);
gDPSetEnvColor(displayListIter++, 255, 255, 255, gTitleFadeCounter);
if (gTitleFadeCounter == 255) {
if (0) {
}
graphNode->flags = (graphNode->flags & 0xFF) | 0x100;
gDPSetRenderMode(displayListIter++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
} else {
graphNode->flags = (graphNode->flags & 0xFF) | 0x500;
gDPSetRenderMode(displayListIter++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
if (0) {
}
}
gSPDisplayList(displayListIter++, &intro_seg7_dl_0700C6A0);
gSPEndDisplayList(displayListIter);
if (gTitleZoomCounter >= 0x13) {
gTitleFadeCounter += 0x1a;
if (gTitleFadeCounter >= 0x100) {
gTitleFadeCounter = 0xFF;
}
}
}
return displayList;
}
Gfx *intro_backdrop_one_image(s32 index, s8 *backgroundTable) {
Mtx *mtx; // sp5c
Gfx *displayList; // sp58
Gfx *displayListIter; // sp54
const u8 *const *vIntroBgTable; // sp50
s32 i; // sp4c
f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO;
int num_tiles_h = (((aspect*SCREEN_HEIGHT)+79)/80);
float x_ofs = (SCREEN_WIDTH/2)-(aspect*SCREEN_HEIGHT/2);
mtx = alloc_display_list(sizeof(*mtx));
displayList = alloc_display_list(36 * sizeof(*displayList));
displayListIter = displayList;
vIntroBgTable = segmented_to_virtual(introBackgroundTextureType[backgroundTable[0]]);
guTranslate(mtx, ((index%num_tiles_h)*80)+x_ofs, (index/num_tiles_h)*80, 0.0f);
gSPMatrix(displayListIter++, mtx, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH);
gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000118);
for (i = 0; i < 4; ++i) {
gDPLoadTextureBlock(displayListIter++, vIntroBgTable[i], G_IM_FMT_RGBA, G_IM_SIZ_16b, 80, 20, 0,
G_TX_CLAMP, G_TX_CLAMP, 7, 6, G_TX_NOLOD, G_TX_NOLOD)
gSPDisplayList(displayListIter++, introBackgroundDlRows[i]);
}
gSPPopMatrix(displayListIter++, G_MTX_MODELVIEW);
gSPEndDisplayList(displayListIter);
return displayList;
}
Gfx *geo_intro_backdrop(s32 sp48, struct GraphNode *sp4c, UNUSED void *context) {
struct GraphNodeMore *graphNode; // sp44
s32 index; // sp40
s8 *backgroundTable; // sp3c
Gfx *displayList; // sp38
Gfx *displayListIter; // sp34
s32 i; // sp30
graphNode = (struct GraphNodeMore *) sp4c;
index = graphNode->unk18 & 0xff; // TODO: word at offset 0x18 of struct GraphNode
backgroundTable = introBackgroundTables[index];
displayList = NULL;
displayListIter = NULL;
f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO;
int num_tiles_h = (((aspect*SCREEN_HEIGHT)+79)/80);
if (sp48 == 1) {
displayList = alloc_display_list(((num_tiles_h*3)+4) * sizeof(*displayList));
displayListIter = displayList;
graphNode->node.flags = (graphNode->node.flags & 0xFF) | 0x100;
gSPDisplayList(displayListIter++, &dl_proj_mtx_fullscreen);
gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000100);
for (i = 0; i < num_tiles_h*3; ++i) {
gSPDisplayList(displayListIter++, intro_backdrop_one_image(i, backgroundTable));
}
gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000190);
gSPEndDisplayList(displayListIter);
}
return displayList;
}
Gfx *geo_game_over_tile(s32 sp40, struct GraphNode *sp44, UNUSED void *context) {
struct GraphNode *graphNode; // sp3c
Gfx *displayList; // sp38
Gfx *displayListIter; // sp34
s32 j; // sp30
s32 i; // sp2c
graphNode = sp44;
displayList = NULL;
displayListIter = NULL;
f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO;
int num_tiles_h = (((aspect*SCREEN_HEIGHT)+79)/80);
if (sp40 != 1) {
gGameOverFrameCounter = 0;
gGameOverTableIndex = -2;
for (i = 0; i < (s32) sizeof(gameOverBackgroundTable); ++i) {
gameOverBackgroundTable[i] = INTRO_BACKGROUND_GAME_OVER;
}
} else {
displayList = alloc_display_list(((num_tiles_h*3)+4) * sizeof(*displayList));
displayListIter = displayList;
if (gGameOverTableIndex == -2) {
if (gGameOverFrameCounter == 180) {
gGameOverTableIndex++;
gGameOverFrameCounter = 0;
}
} else {
// transition tile from "Game Over" to "Super Mario 64"
if (gGameOverTableIndex != 11 && !(gGameOverFrameCounter & 0x1)) {
gGameOverTableIndex++;
gameOverBackgroundTable[gameOverBackgroundFlipOrder[gGameOverTableIndex]] =
INTRO_BACKGROUND_SUPER_MARIO;
}
}
if (gGameOverTableIndex != 11) {
gGameOverFrameCounter++;
}
graphNode->flags = (graphNode->flags & 0xFF) | 0x100;
gSPDisplayList(displayListIter++, &dl_proj_mtx_fullscreen);
gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000100);
for (j = 0; j < (s32) num_tiles_h*3; ++j) {
gSPDisplayList(displayListIter++, intro_backdrop_one_image(j, gameOverBackgroundTable));
}
gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000190);
gSPEndDisplayList(displayListIter);
}
return displayList;
}