Add pillarboxing to cutscenes. (#35)

* Update RT64 to fix scissor origin leaking bug.

* Add pillarboxing to cutscenes.
This commit is contained in:
Darío
2026-01-01 18:43:12 -03:00
committed by GitHub
parent 8206ba4bb3
commit 6aa7f36a6d
8 changed files with 127 additions and 1 deletions
+1
View File
@@ -8,5 +8,6 @@ DECLARE_FUNC(float, recomp_get_target_aspect_ratio, float);
DECLARE_FUNC(s32, recomp_get_target_framerate, s32);
DECLARE_FUNC(s32, recomp_high_precision_fb_enabled);
DECLARE_FUNC(float, recomp_get_resolution_scale);
DECLARE_FUNC(float, recomp_get_cutscene_aspect_ratio);
#endif
+109
View File
@@ -0,0 +1,109 @@
#include "patches.h"
#include "transform_ids.h"
#include "functions.h"
#include "graphics.h"
#define ANIMATED_PILLARBOX_SCALE 0
extern enum map_e map_get(void);
#if ANIMATED_PILLARBOX_SCALE
f32 pillarbox_scale = 0.0f;
#else
f32 pillarbox_scale = 1.0f;
#endif
bool pillarbox_active() {
switch (map_get()) {
case MAP_1E_CS_START_NINTENDO:
case MAP_1F_CS_START_RAREWARE:
case MAP_20_CS_END_NOT_100:
case MAP_7B_CS_INTRO_GL_DINGPOT_1:
case MAP_7C_CS_INTRO_BANJOS_HOUSE_1:
case MAP_7D_CS_SPIRAL_MOUNTAIN_1:
case MAP_7E_CS_SPIRAL_MOUNTAIN_2:
case MAP_81_CS_INTRO_GL_DINGPOT_2:
case MAP_82_CS_ENTERING_GL_MACHINE_ROOM:
case MAP_83_CS_GAME_OVER_MACHINE_ROOM:
case MAP_84_CS_UNUSED_MACHINE_ROOM:
case MAP_85_CS_SPIRAL_MOUNTAIN_3:
case MAP_86_CS_SPIRAL_MOUNTAIN_4:
case MAP_87_CS_SPIRAL_MOUNTAIN_5:
case MAP_88_CS_SPIRAL_MOUNTAIN_6:
case MAP_89_CS_INTRO_BANJOS_HOUSE_2:
case MAP_8A_CS_INTRO_BANJOS_HOUSE_3:
case MAP_94_CS_INTRO_SPIRAL_7:
case MAP_95_CS_END_ALL_100:
case MAP_96_CS_END_BEACH_1:
case MAP_97_CS_END_BEACH_2:
case MAP_98_CS_END_SPIRAL_MOUNTAIN_1:
case MAP_99_CS_END_SPIRAL_MOUNTAIN_2:
return TRUE;
default:
return FALSE;
}
}
void pillarbox_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
#if ANIMATED_PILLARBOX_SCALE
const f32 pillarbox_scale_speed = 1.0f * time_getDelta();
if (pillarbox_active()) {
pillarbox_scale = MIN(pillarbox_scale + pillarbox_scale_speed, 1.0f);
}
else {
pillarbox_scale = MAX(pillarbox_scale - pillarbox_scale_speed, 0.0f);
}
#else
if (!pillarbox_active()) {
return;
}
#endif
float original_aspect = (float)DEFAULT_FRAMEBUFFER_WIDTH / DEFAULT_FRAMEBUFFER_HEIGHT;
float cur_aspect = recomp_get_target_aspect_ratio(original_aspect);
float target_aspect = MIN(recomp_get_cutscene_aspect_ratio(), cur_aspect);
float target_width = DEFAULT_FRAMEBUFFER_HEIGHT * target_aspect;
float wide_width = DEFAULT_FRAMEBUFFER_HEIGHT * cur_aspect;
float pillar_width = wide_width - target_width * pillarbox_scale;
if (pillar_width >= 0.0f) {
u32 prev_ortho_id = cur_ortho_projection_transform_id;
cur_ortho_projection_transform_id = PROJECTION_PILLARBOX_TRANSFORM_ID;
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
Vtx *verts = *vtx;
for (s32 ix = -1; ix < 2; ix += 2) {
for (s32 iy = 0; iy < 2; iy++) {
(*vtx)->v.ob[0] = ix * pillar_width * 2;
(*vtx)->v.ob[1] = iy * DEFAULT_FRAMEBUFFER_HEIGHT * 4 - DEFAULT_FRAMEBUFFER_HEIGHT * 2;
(*vtx)->v.ob[2] = -0x14;
(*vtx)++;
}
}
gEXPushOtherMode((*gfx)++);
gEXPushCombineMode((*gfx)++);
gEXPushGeometryMode((*gfx)++);
gSPClearGeometryMode((*gfx)++, G_CULL_BOTH);
gDPSetRenderMode((*gfx)++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gDPSetCycleType((*gfx)++, G_CYC_1CYCLE);
gDPSetCombineLERP((*gfx)++, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
u32 id = PILLARBOX_RECTANGLE_TRANSFORM_ID_START;
for (s32 ix = -1; ix < 2; ix += 2) {
guTranslate(*mtx, ix * wide_width * 2, 0.0f, 0.0f);
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL(*mtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
(*mtx)++;
gEXMatrixGroupSimpleVerts((*gfx)++, id++, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
gSPVertex((*gfx)++, verts, 4, 0);
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
}
gEXPopOtherMode((*gfx)++);
gEXPopCombineMode((*gfx)++);
gEXPopGeometryMode((*gfx)++);
cur_ortho_projection_transform_id = prev_ortho_id;
}
}
+5
View File
@@ -85,6 +85,7 @@ extern void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
extern u32 cur_pushed_text_transform_id;
extern u32 cur_pushed_text_transform_origin;
extern void pillarbox_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr);
// @recomp Patched to set the projection transform ID for the main projection.
RECOMP_PATCH void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4) {
@@ -173,6 +174,10 @@ RECOMP_PATCH void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuff
) {
gctransition_draw(gdl, mptr, vptr);
}
// @recomp Draw a pillarbox over the current scene to hide the extended widescreen area if active (e.g. cutscenes).
pillarbox_draw(gdl, mptr, vptr);
finishFrame(gdl);
osWritebackDCache(m_start, sizeof(Mtx) * (*mptr - m_start));
osWritebackDCache(v_start, sizeof(Vtx) * (*vptr - v_start));
+1
View File
@@ -47,3 +47,4 @@ recomp_set_right_analog_suppressed = 0x8F0000A8;
osContGetReadData_recomp = 0x8F0000AC;
bcopy_recomp = 0x8F0000B0;
recomp_get_note_saving_enabled = 0x8F0000B4;
recomp_get_cutscene_aspect_ratio = 0x8F0000B8;
+4
View File
@@ -16,6 +16,7 @@
#define PROJECTION_COPYRIGHT_TRANSFORM_ID 0x00001006
#define PROJECTION_GAME_OVER_TRANSFORM_ID 0x00001007
#define PROJECTION_THE_END_TRANSFORM_ID 0x00001008
#define PROJECTION_PILLARBOX_TRANSFORM_ID 0x00001009
#define PROJECTION_PORTRAIT_TRANSFORM_ID_START 0x00001100 // 1 for each portrait ID
// Map models: 0x00400000 - 0x00EFFFFF
@@ -107,6 +108,9 @@
#define RAIN_PARTICLE_ID_COUNT 256
#define RAIN_PARTICLE_ID_MAX 0x8000
// Pillarbox Rectangles: 0x31000000 - 0x31000010
#define PILLARBOX_RECTANGLE_TRANSFORM_ID_START 0x31000000
// Markers: 0x10000000 - 0x1FFFFFFF
#define BANJO_TRANSFORM_ID_START 0x10000000
#define MARKER_TRANSFORM_ID_START (BANJO_TRANSFORM_ID_START + MARKER_TRANSFORM_ID_COUNT)
+5
View File
@@ -101,6 +101,11 @@ extern "C" void recomp_get_target_aspect_ratio(uint8_t* rdram, recomp_context* c
}
}
extern "C" void recomp_get_cutscene_aspect_ratio(uint8_t *rdram, recomp_context *ctx) {
float ar = 16.0f / 9.0f;
_return(ctx, ar);
}
extern "C" void recomp_get_bgm_volume(uint8_t* rdram, recomp_context* ctx) {
_return(ctx, banjo::get_bgm_volume() / 100.0f);
}
+1
View File
@@ -623,6 +623,7 @@ int main(int argc, char** argv) {
REGISTER_FUNC(recomp_get_window_resolution);
REGISTER_FUNC(recomp_get_target_aspect_ratio);
REGISTER_FUNC(recomp_get_target_framerate);
REGISTER_FUNC(recomp_get_cutscene_aspect_ratio);
REGISTER_FUNC(recomp_get_analog_cam_enabled);
REGISTER_FUNC(recomp_get_camera_inputs);
REGISTER_FUNC(recomp_get_bgm_volume);