mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-19 13:00:11 -07:00
Port pause menu framebuffer handling from 2Ship (#4346)
* bring over framebuffer effects methods * Implement framebuffer capture and drawing for pause menu * revert hookshot and title cards to draw using original buffers * remove old game over crash fix * Adjust mirror mode handling for kaleido * Avoid flashing the hud when pausing
This commit is contained in:
parent
7192783451
commit
bd7155179e
14 changed files with 284 additions and 59 deletions
|
@ -184,7 +184,6 @@ extern GraphicsContext* __gfxCtx;
|
||||||
#define POLY_XLU_DISP __gfxCtx->polyXlu.p
|
#define POLY_XLU_DISP __gfxCtx->polyXlu.p
|
||||||
// #region SOH [General]
|
// #region SOH [General]
|
||||||
// Upstream TODO: Document reasoning for these only existing in SoH
|
// Upstream TODO: Document reasoning for these only existing in SoH
|
||||||
#define WORLD_OVERLAY_DISP __gfxCtx->worldOverlay.p
|
|
||||||
#define POLY_KAL_DISP __gfxCtx->polyKal.p
|
#define POLY_KAL_DISP __gfxCtx->polyKal.p
|
||||||
// #endregion
|
// #endregion
|
||||||
#define OVERLAY_DISP __gfxCtx->overlay.p
|
#define OVERLAY_DISP __gfxCtx->overlay.p
|
||||||
|
|
|
@ -92,7 +92,6 @@ typedef struct {
|
||||||
/* 0x00000 */ u16 headMagic; // GFXPOOL_HEAD_MAGIC
|
/* 0x00000 */ u16 headMagic; // GFXPOOL_HEAD_MAGIC
|
||||||
/* 0x00008 */ Gfx polyOpaBuffer[0x2FC0];
|
/* 0x00008 */ Gfx polyOpaBuffer[0x2FC0];
|
||||||
/* 0x0BF08 */ Gfx polyXluBuffer[0x1000];
|
/* 0x0BF08 */ Gfx polyXluBuffer[0x1000];
|
||||||
/* 0xXXXXX */ Gfx worldOverlayBuffer[0x1000];
|
|
||||||
/* 0x0BF08 */ Gfx polyKalBuffer[0x1000];
|
/* 0x0BF08 */ Gfx polyKalBuffer[0x1000];
|
||||||
/* 0x0FF08 */ Gfx overlayBuffer[0x800];
|
/* 0x0FF08 */ Gfx overlayBuffer[0x800];
|
||||||
/* 0x11F08 */ Gfx workBuffer[0x100];
|
/* 0x11F08 */ Gfx workBuffer[0x100];
|
||||||
|
@ -140,7 +139,6 @@ typedef struct OSScTask {
|
||||||
typedef struct GraphicsContext {
|
typedef struct GraphicsContext {
|
||||||
/* 0x0000 */ Gfx* polyOpaBuffer; // Pointer to "Zelda 0"
|
/* 0x0000 */ Gfx* polyOpaBuffer; // Pointer to "Zelda 0"
|
||||||
/* 0x0004 */ Gfx* polyXluBuffer; // Pointer to "Zelda 1"
|
/* 0x0004 */ Gfx* polyXluBuffer; // Pointer to "Zelda 1"
|
||||||
/* 0xXXX */ Gfx* worldOverlayBuffer; // Pointer to "Paris"
|
|
||||||
/* 0xXXX */ Gfx* polyKalBuffer; // Pointer to "Rome"
|
/* 0xXXX */ Gfx* polyKalBuffer; // Pointer to "Rome"
|
||||||
/* 0x0008 */ char unk_008[0x08]; // Unused, could this be pointers to "Zelda 2" / "Zelda 3"
|
/* 0x0008 */ char unk_008[0x08]; // Unused, could this be pointers to "Zelda 2" / "Zelda 3"
|
||||||
/* 0x0010 */ Gfx* overlayBuffer; // Pointer to "Zelda 4"
|
/* 0x0010 */ Gfx* overlayBuffer; // Pointer to "Zelda 4"
|
||||||
|
@ -160,7 +158,6 @@ typedef struct GraphicsContext {
|
||||||
/* 0x02A8 */ TwoHeadGfxArena overlay; // "Zelda 4"
|
/* 0x02A8 */ TwoHeadGfxArena overlay; // "Zelda 4"
|
||||||
/* 0x02B8 */ TwoHeadGfxArena polyOpa; // "Zelda 0"
|
/* 0x02B8 */ TwoHeadGfxArena polyOpa; // "Zelda 0"
|
||||||
/* 0x02C8 */ TwoHeadGfxArena polyXlu; // "Zelda 1"
|
/* 0x02C8 */ TwoHeadGfxArena polyXlu; // "Zelda 1"
|
||||||
/* 0x0XXX */ TwoHeadGfxArena worldOverlay; // When in Paris...
|
|
||||||
/* 0x0XXX */ TwoHeadGfxArena polyKal; // When in Rome...
|
/* 0x0XXX */ TwoHeadGfxArena polyKal; // When in Rome...
|
||||||
/* 0x02D8 */ u32 gfxPoolIdx;
|
/* 0x02D8 */ u32 gfxPoolIdx;
|
||||||
/* 0x02DC */ u16* curFrameBuffer;
|
/* 0x02DC */ u16* curFrameBuffer;
|
||||||
|
|
|
@ -2283,6 +2283,16 @@ extern "C" float OTRGetDimensionFromRightEdge(float v) {
|
||||||
return (SCREEN_WIDTH / 2 + SCREEN_HEIGHT / 2 * OTRGetAspectRatio() - (SCREEN_WIDTH - v));
|
return (SCREEN_WIDTH / 2 + SCREEN_HEIGHT / 2 * OTRGetAspectRatio() - (SCREEN_WIDTH - v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the width of the current render target area
|
||||||
|
extern "C" uint32_t OTRGetGameRenderWidth() {
|
||||||
|
return gfx_current_dimensions.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the height of the current render target area
|
||||||
|
extern "C" uint32_t OTRGetGameRenderHeight() {
|
||||||
|
return gfx_current_dimensions.height;
|
||||||
|
}
|
||||||
|
|
||||||
f32 floorf(f32 x);// RANDOTODO False positive error "allowing all exceptions is incompatible with previous function"
|
f32 floorf(f32 x);// RANDOTODO False positive error "allowing all exceptions is incompatible with previous function"
|
||||||
f32 ceilf(f32 x); // This gets annoying
|
f32 ceilf(f32 x); // This gets annoying
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,8 @@ float OTRGetDimensionFromLeftEdge(float v);
|
||||||
float OTRGetDimensionFromRightEdge(float v);
|
float OTRGetDimensionFromRightEdge(float v);
|
||||||
int16_t OTRGetRectDimensionFromLeftEdge(float v);
|
int16_t OTRGetRectDimensionFromLeftEdge(float v);
|
||||||
int16_t OTRGetRectDimensionFromRightEdge(float v);
|
int16_t OTRGetRectDimensionFromRightEdge(float v);
|
||||||
|
uint32_t OTRGetGameRenderWidth();
|
||||||
|
uint32_t OTRGetGameRenderHeight();
|
||||||
int AudioPlayer_Buffered(void);
|
int AudioPlayer_Buffered(void);
|
||||||
int AudioPlayer_GetDesiredBuffered(void);
|
int AudioPlayer_GetDesiredBuffered(void);
|
||||||
void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
|
void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
|
||||||
|
|
177
soh/soh/framebuffer_effects.c
Normal file
177
soh/soh/framebuffer_effects.c
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
#include "framebuffer_effects.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "OTRGlobals.h"
|
||||||
|
|
||||||
|
int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height,
|
||||||
|
uint8_t resize);
|
||||||
|
|
||||||
|
s32 gPauseFrameBuffer = -1;
|
||||||
|
s32 gBlurFrameBuffer = -1;
|
||||||
|
// A framebuffer that should only be used for drawing in the same frame that it is copied too
|
||||||
|
// i.e. the VisMono and VisFbuf effects
|
||||||
|
s32 gReusableFrameBuffer = -1;
|
||||||
|
|
||||||
|
// N64 resolution sized buffer (320x240), used by picto box and deku bubble
|
||||||
|
s32 gN64ResFrameBuffer = -1;
|
||||||
|
|
||||||
|
void FB_CreateFramebuffers(void) {
|
||||||
|
if (gPauseFrameBuffer == -1) {
|
||||||
|
gPauseFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gBlurFrameBuffer == -1) {
|
||||||
|
gBlurFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gReusableFrameBuffer == -1) {
|
||||||
|
gReusableFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gN64ResFrameBuffer == -1) {
|
||||||
|
gN64ResFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the current texture data from the source frame buffer to the destination frame buffer
|
||||||
|
* Setting oncePerFrame ensures that the copy will only happen once every game frame. This
|
||||||
|
* is important for effects that could be affected by increased frame interpolation (like motion blur).
|
||||||
|
* A pointer to a boolean is passed to the render for the render to set once the copy has been performed.
|
||||||
|
* This function uses opcodes from f3dex2 but may be called when s2dex is loaded, such as during shrink window. Make
|
||||||
|
* sure f3dex2 is loaded before this function is called.
|
||||||
|
*/
|
||||||
|
void FB_CopyToFramebuffer(Gfx** gfxp, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied) {
|
||||||
|
Gfx* gfx = *gfxp;
|
||||||
|
|
||||||
|
gSPMatrix(gfx++, &gMtxClear, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
|
||||||
|
gDPSetOtherMode(gfx++,
|
||||||
|
G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE |
|
||||||
|
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
|
||||||
|
G_AC_NONE | G_ZS_PRIM | G_RM_OPA_SURF | G_RM_OPA_SURF2);
|
||||||
|
|
||||||
|
gSPClearGeometryMode(gfx++, G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR);
|
||||||
|
gSPSetGeometryMode(gfx++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH);
|
||||||
|
|
||||||
|
gDPSetBlendColor(gfx++, 255, 255, 255, 8);
|
||||||
|
gDPSetPrimDepth(gfx++, 0xFFFF, 0xFFFF);
|
||||||
|
|
||||||
|
gDPSetEnvColor(gfx++, 255, 255, 255, 255);
|
||||||
|
gDPSetCombineLERP(gfx++, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0,
|
||||||
|
ENVIRONMENT);
|
||||||
|
|
||||||
|
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
gDPCopyFB(gfx++, fb_dest, fb_src, oncePerFrame, hasCopied);
|
||||||
|
|
||||||
|
*gfxp = gfx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a 4:3 slice of the current framebuffer scaled down to 320x240 to a CPU buffer address.
|
||||||
|
* The buffer output will be in RGBA16 format.
|
||||||
|
* Specify the byteswap flag to force the buffer data to be written as BigEndian, which is
|
||||||
|
* required if the buffer is being used as a texture in F3D.
|
||||||
|
*/
|
||||||
|
void FB_WriteFramebufferSliceToCPU(Gfx** gfxp, void* buffer, u8 byteSwap) {
|
||||||
|
Gfx* gfx = *gfxp;
|
||||||
|
|
||||||
|
FB_CopyToFramebuffer(&gfx, 0, gReusableFrameBuffer, false, NULL);
|
||||||
|
|
||||||
|
// Set the N64 resolution framebuffer as the draw target (320x240)
|
||||||
|
gsSPSetFB(gfx++, gN64ResFrameBuffer);
|
||||||
|
// Reset scissor for new framebuffer
|
||||||
|
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
int16_t s0 = 0, t0 = 0;
|
||||||
|
int16_t s1 = OTRGetGameRenderWidth();
|
||||||
|
int16_t t1 = OTRGetGameRenderHeight();
|
||||||
|
|
||||||
|
float aspectRatio = OTRGetAspectRatio();
|
||||||
|
float fourByThree = 4.0f / 3.0f;
|
||||||
|
|
||||||
|
// Adjust the texture coordinates so that only a 4:3 region from the center is drawn
|
||||||
|
// to the N64 resolution buffer. Currently ratios smaller than 4:3 will just stretch to fill.
|
||||||
|
if (aspectRatio > fourByThree) {
|
||||||
|
int16_t adjustedWidth = OTRGetGameRenderWidth() / (aspectRatio / fourByThree);
|
||||||
|
s0 = (OTRGetGameRenderWidth() - adjustedWidth) / 2;
|
||||||
|
s1 -= s0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gDPSetTextureImageFB(gfx++, 0, 0, 0, gReusableFrameBuffer);
|
||||||
|
gDPImageRectangle(gfx++, 0 << 2, 0 << 2, s0, t0, SCREEN_WIDTH << 2, SCREEN_HEIGHT << 2, s1, t1, G_TX_RENDERTILE,
|
||||||
|
OTRGetGameRenderWidth(), OTRGetGameRenderHeight());
|
||||||
|
|
||||||
|
// Read the final N64 framebuffer back as rgba16 into the CPU-side buffer
|
||||||
|
gDPReadFB(gfx++, gN64ResFrameBuffer, buffer, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, byteSwap);
|
||||||
|
|
||||||
|
gsSPResetFB(gfx++);
|
||||||
|
// Reset scissor for original framebuffer
|
||||||
|
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
*gfxp = gfx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the texture data from the specified frame buffer as a full screen image
|
||||||
|
*/
|
||||||
|
void FB_DrawFromFramebuffer(Gfx** gfxp, s32 fb, u8 alpha) {
|
||||||
|
Gfx* gfx = *gfxp;
|
||||||
|
|
||||||
|
gSPMatrix(gfx++, &gMtxClear, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
|
||||||
|
gDPSetEnvColor(gfx++, 255, 255, 255, alpha);
|
||||||
|
|
||||||
|
gDPSetOtherMode(gfx++,
|
||||||
|
G_AD_NOISE | G_CD_NOISE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP |
|
||||||
|
G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
|
||||||
|
G_AC_NONE | G_ZS_PRIM | G_RM_CLD_SURF | G_RM_CLD_SURF2);
|
||||||
|
|
||||||
|
gSPClearGeometryMode(gfx++, G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR);
|
||||||
|
gSPSetGeometryMode(gfx++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH);
|
||||||
|
|
||||||
|
gDPSetCombineLERP(gfx++, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0,
|
||||||
|
ENVIRONMENT);
|
||||||
|
|
||||||
|
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
gDPSetTextureImageFB(gfx++, 0, 0, 0, fb);
|
||||||
|
gDPImageRectangle(gfx++, OTRGetRectDimensionFromLeftEdge(0) << 2, 0 << 2, 0, 0,
|
||||||
|
OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH) << 2, SCREEN_HEIGHT << 2, OTRGetGameRenderWidth(),
|
||||||
|
OTRGetGameRenderHeight(), G_TX_RENDERTILE, OTRGetGameRenderWidth(), OTRGetGameRenderHeight());
|
||||||
|
|
||||||
|
*gfxp = gfx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to FB_DrawFromFramebuffer, but scales the image relative to the center of the screen.
|
||||||
|
* This function uses opcodes from f3dex2 but may be called when s2dex is loaded, such as during shrink window. Make
|
||||||
|
* sure f3dex2 is loaded before this function is called.
|
||||||
|
*/
|
||||||
|
void FB_DrawFromFramebufferScaled(Gfx** gfxp, s32 fb, u8 alpha, float scaleX, float scaleY) {
|
||||||
|
Gfx* gfx = *gfxp;
|
||||||
|
|
||||||
|
gDPSetEnvColor(gfx++, 255, 255, 255, alpha);
|
||||||
|
|
||||||
|
gDPSetOtherMode(gfx++,
|
||||||
|
G_AD_NOISE | G_CD_NOISE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP |
|
||||||
|
G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
|
||||||
|
G_AC_NONE | G_ZS_PRIM | G_RM_CLD_SURF | G_RM_CLD_SURF2);
|
||||||
|
|
||||||
|
gDPSetCombineLERP(gfx++, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0,
|
||||||
|
ENVIRONMENT);
|
||||||
|
|
||||||
|
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
gDPSetTextureImageFB(gfx++, 0, 0, 0, fb);
|
||||||
|
|
||||||
|
float x0 = gScreenWidth * 0.5f * scaleX;
|
||||||
|
float y0 = gScreenHeight * 0.5f * scaleY;
|
||||||
|
|
||||||
|
gDPImageRectangle(gfx++, OTRGetRectDimensionFromLeftEdge(x0) << 2, (int)(y0) << 2, 0, 0,
|
||||||
|
OTRGetRectDimensionFromRightEdge((float)(gScreenWidth - x0)) << 2,
|
||||||
|
(int)((float)(gScreenHeight - y0)) << 2, OTRGetGameRenderWidth(), OTRGetGameRenderHeight(),
|
||||||
|
G_TX_RENDERTILE, OTRGetGameRenderWidth(), OTRGetGameRenderHeight());
|
||||||
|
|
||||||
|
*gfxp = gfx;
|
||||||
|
}
|
17
soh/soh/framebuffer_effects.h
Normal file
17
soh/soh/framebuffer_effects.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef FRAMEBUFFER_EFFECTS_H
|
||||||
|
#define FRAMEBUFFER_EFFECTS_H
|
||||||
|
|
||||||
|
#include <libultraship/libultra.h>
|
||||||
|
|
||||||
|
extern s32 gPauseFrameBuffer;
|
||||||
|
extern s32 gBlurFrameBuffer;
|
||||||
|
extern s32 gReusableFrameBuffer;
|
||||||
|
extern s32 gN64ResFrameBuffer;
|
||||||
|
|
||||||
|
void FB_CreateFramebuffers(void);
|
||||||
|
void FB_CopyToFramebuffer(Gfx** gfxp, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied);
|
||||||
|
void FB_WriteFramebufferSliceToCPU(Gfx** gfxp, void* buffer, u8 byteSwap);
|
||||||
|
void FB_DrawFromFramebuffer(Gfx** gfxp, s32 fb, u8 alpha);
|
||||||
|
void FB_DrawFromFramebufferScaled(Gfx** gfxp, s32 fb, u8 alpha, float scaleX, float scaleY);
|
||||||
|
|
||||||
|
#endif // FRAMEBUFFER_EFFECTS_H
|
|
@ -104,14 +104,12 @@ void Graph_InitTHGA(GraphicsContext* gfxCtx) {
|
||||||
pool->tailMagic = GFXPOOL_TAIL_MAGIC;
|
pool->tailMagic = GFXPOOL_TAIL_MAGIC;
|
||||||
THGA_Ct(&gfxCtx->polyOpa, pool->polyOpaBuffer, sizeof(pool->polyOpaBuffer));
|
THGA_Ct(&gfxCtx->polyOpa, pool->polyOpaBuffer, sizeof(pool->polyOpaBuffer));
|
||||||
THGA_Ct(&gfxCtx->polyXlu, pool->polyXluBuffer, sizeof(pool->polyXluBuffer));
|
THGA_Ct(&gfxCtx->polyXlu, pool->polyXluBuffer, sizeof(pool->polyXluBuffer));
|
||||||
THGA_Ct(&gfxCtx->worldOverlay, pool->worldOverlayBuffer, sizeof(pool->worldOverlayBuffer));
|
|
||||||
THGA_Ct(&gfxCtx->polyKal, pool->polyKalBuffer, sizeof(pool->polyKalBuffer));
|
THGA_Ct(&gfxCtx->polyKal, pool->polyKalBuffer, sizeof(pool->polyKalBuffer));
|
||||||
THGA_Ct(&gfxCtx->overlay, pool->overlayBuffer, sizeof(pool->overlayBuffer));
|
THGA_Ct(&gfxCtx->overlay, pool->overlayBuffer, sizeof(pool->overlayBuffer));
|
||||||
THGA_Ct(&gfxCtx->work, pool->workBuffer, sizeof(pool->workBuffer));
|
THGA_Ct(&gfxCtx->work, pool->workBuffer, sizeof(pool->workBuffer));
|
||||||
|
|
||||||
gfxCtx->polyOpaBuffer = pool->polyOpaBuffer;
|
gfxCtx->polyOpaBuffer = pool->polyOpaBuffer;
|
||||||
gfxCtx->polyXluBuffer = pool->polyXluBuffer;
|
gfxCtx->polyXluBuffer = pool->polyXluBuffer;
|
||||||
gfxCtx->worldOverlayBuffer = pool->worldOverlayBuffer;
|
|
||||||
gfxCtx->polyKalBuffer = pool->polyKalBuffer;
|
gfxCtx->polyKalBuffer = pool->polyKalBuffer;
|
||||||
gfxCtx->overlayBuffer = pool->overlayBuffer;
|
gfxCtx->overlayBuffer = pool->overlayBuffer;
|
||||||
gfxCtx->workBuffer = pool->workBuffer;
|
gfxCtx->workBuffer = pool->workBuffer;
|
||||||
|
@ -324,8 +322,7 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||||
|
|
||||||
gSPBranchList(WORK_DISP++, gfxCtx->polyOpaBuffer);
|
gSPBranchList(WORK_DISP++, gfxCtx->polyOpaBuffer);
|
||||||
gSPBranchList(POLY_OPA_DISP++, gfxCtx->polyXluBuffer);
|
gSPBranchList(POLY_OPA_DISP++, gfxCtx->polyXluBuffer);
|
||||||
gSPBranchList(POLY_XLU_DISP++, gfxCtx->worldOverlayBuffer);
|
gSPBranchList(POLY_XLU_DISP++, gfxCtx->polyKalBuffer);
|
||||||
gSPBranchList(WORLD_OVERLAY_DISP++, gfxCtx->polyKalBuffer);
|
|
||||||
gSPBranchList(POLY_KAL_DISP++, gfxCtx->overlayBuffer);
|
gSPBranchList(POLY_KAL_DISP++, gfxCtx->overlayBuffer);
|
||||||
gDPPipeSync(OVERLAY_DISP++);
|
gDPPipeSync(OVERLAY_DISP++);
|
||||||
gDPFullSync(OVERLAY_DISP++);
|
gDPFullSync(OVERLAY_DISP++);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "soh/framebuffer_effects.h"
|
||||||
|
|
||||||
uintptr_t sSysCfbFbPtr[2];
|
uintptr_t sSysCfbFbPtr[2];
|
||||||
uintptr_t sSysCfbEnd;
|
uintptr_t sSysCfbEnd;
|
||||||
|
@ -40,6 +41,9 @@ void SysCfb_Init(s32 n64dd) {
|
||||||
|
|
||||||
// "Frame buffer addresses are %08x and %08x"
|
// "Frame buffer addresses are %08x and %08x"
|
||||||
//osSyncPrintf("フレームバッファのアドレスは %08x と %08x です\n", sSysCfbFbPtr[0], sSysCfbFbPtr[1]);
|
//osSyncPrintf("フレームバッファのアドレスは %08x と %08x です\n", sSysCfbFbPtr[0], sSysCfbFbPtr[1]);
|
||||||
|
|
||||||
|
// SOH [Port] Inform LUS on resolution changes
|
||||||
|
FB_CreateFramebuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysCfb_Reset() {
|
void SysCfb_Reset() {
|
||||||
|
|
|
@ -1147,17 +1147,16 @@ void TitleCard_Draw(PlayState* play, TitleCardContext* titleCtx) {
|
||||||
|
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
|
|
||||||
// WORLD_OVERLAY_DISP Goes over POLY_XLU_DISP but under POLY_KAL_DISP
|
OVERLAY_DISP = Gfx_SetupDL_52NoCD(OVERLAY_DISP);
|
||||||
WORLD_OVERLAY_DISP = Gfx_SetupDL_52NoCD(WORLD_OVERLAY_DISP);
|
|
||||||
|
|
||||||
gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, (u8)titleCtx->intensityR, (u8)titleCtx->intensityG, (u8)titleCtx->intensityB,
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, (u8)titleCtx->intensityR, (u8)titleCtx->intensityG, (u8)titleCtx->intensityB,
|
||||||
(u8)titleCtx->alpha);
|
(u8)titleCtx->alpha);
|
||||||
|
|
||||||
gDPLoadTextureBlock(WORLD_OVERLAY_DISP++, (uintptr_t)titleCtx->texture, G_IM_FMT_IA,
|
gDPLoadTextureBlock(OVERLAY_DISP++, (uintptr_t)titleCtx->texture, G_IM_FMT_IA,
|
||||||
G_IM_SIZ_8b,
|
G_IM_SIZ_8b,
|
||||||
width, height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
|
width, height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
|
||||||
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||||
gSPWideTextureRectangle(WORLD_OVERLAY_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4),
|
gSPWideTextureRectangle(OVERLAY_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4),
|
||||||
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
||||||
|
|
||||||
height = titleCtx->height - height;
|
height = titleCtx->height - height;
|
||||||
|
|
|
@ -69,7 +69,7 @@ void KaleidoScopeCall_Update(PlayState* play) {
|
||||||
if (ShrinkWindow_GetCurrentVal() == 0) {
|
if (ShrinkWindow_GetCurrentVal() == 0) {
|
||||||
HREG(80) = 7;
|
HREG(80) = 7;
|
||||||
HREG(82) = 3;
|
HREG(82) = 3;
|
||||||
R_PAUSE_MENU_MODE = 3;
|
R_PAUSE_MENU_MODE = 1;
|
||||||
pauseCtx->unk_1E4 = 0;
|
pauseCtx->unk_1E4 = 0;
|
||||||
pauseCtx->unk_1EC = 0;
|
pauseCtx->unk_1EC = 0;
|
||||||
pauseCtx->state = (pauseCtx->state & 0xFFFF) + 1;
|
pauseCtx->state = (pauseCtx->state & 0xFFFF) + 1;
|
||||||
|
|
|
@ -162,11 +162,7 @@ void Lights_BindAll(Lights* lights, LightNode* listHead, Vec3f* vec) {
|
||||||
|
|
||||||
while (listHead != NULL) {
|
while (listHead != NULL) {
|
||||||
info = listHead->info;
|
info = listHead->info;
|
||||||
// OTRTODO: we do not know the root cause of the info->type value being invalid
|
bindFuncs[info->type](lights, &info->params, vec);
|
||||||
// but this prevents it from crashing the game on the game over screen
|
|
||||||
if (info->type < 3) {
|
|
||||||
bindFuncs[info->type](lights, &info->params, vec);
|
|
||||||
}
|
|
||||||
listHead = listHead->next;
|
listHead = listHead->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h>
|
#include <overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h>
|
||||||
#include "soh/Enhancements/enhancementTypes.h"
|
#include "soh/Enhancements/enhancementTypes.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
#include "soh/framebuffer_effects.h"
|
||||||
|
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
|
||||||
|
@ -1341,6 +1342,24 @@ void Play_Draw(PlayState* play) {
|
||||||
Lights* sp228;
|
Lights* sp228;
|
||||||
Vec3f sp21C;
|
Vec3f sp21C;
|
||||||
|
|
||||||
|
// #region SOH [Port] Frame buffer effects for pause menu
|
||||||
|
// Track render size when paused and that a copy was performed
|
||||||
|
static u32 lastPauseWidth;
|
||||||
|
static u32 lastPauseHeight;
|
||||||
|
static u8 hasCapturedPauseBuffer;
|
||||||
|
u8 recapturePauseBuffer = false;
|
||||||
|
|
||||||
|
// If the size has changed or dropped frames leading to the buffer not being copied,
|
||||||
|
// set the prerender state back to setup to copy a new frame.
|
||||||
|
// This requires not rendering kaleido during this copy to avoid kaleido being copied
|
||||||
|
if ((R_PAUSE_MENU_MODE == 2 || R_PAUSE_MENU_MODE == 3) &&
|
||||||
|
(lastPauseWidth != OTRGetGameRenderWidth() || lastPauseHeight != OTRGetGameRenderHeight() ||
|
||||||
|
!hasCapturedPauseBuffer)) {
|
||||||
|
R_PAUSE_MENU_MODE = 1;
|
||||||
|
recapturePauseBuffer = true;
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
OPEN_DISPS(gfxCtx);
|
OPEN_DISPS(gfxCtx);
|
||||||
|
|
||||||
gSegments[4] = VIRTUAL_TO_PHYSICAL(play->objectCtx.status[play->objectCtx.mainKeepIndex].segment);
|
gSegments[4] = VIRTUAL_TO_PHYSICAL(play->objectCtx.status[play->objectCtx.mainKeepIndex].segment);
|
||||||
|
@ -1374,8 +1393,8 @@ void Play_Draw(PlayState* play) {
|
||||||
func_800AAA50(&play->view, 15);
|
func_800AAA50(&play->view, 15);
|
||||||
|
|
||||||
// Flip the projections and invert culling for the OPA and XLU display buffers
|
// Flip the projections and invert culling for the OPA and XLU display buffers
|
||||||
// These manage the world and effects
|
// These manage the world and effects when we are not drawing kaleido
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) {
|
if (R_PAUSE_MENU_MODE <= 1 && CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) {
|
||||||
gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING);
|
gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING);
|
||||||
gSPSetExtraGeometryMode(POLY_XLU_DISP++, G_EX_INVERT_CULLING);
|
gSPSetExtraGeometryMode(POLY_XLU_DISP++, G_EX_INVERT_CULLING);
|
||||||
gSPMatrix(POLY_OPA_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
gSPMatrix(POLY_OPA_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||||
|
@ -1455,13 +1474,13 @@ void Play_Draw(PlayState* play) {
|
||||||
if (R_PAUSE_MENU_MODE == 3) {
|
if (R_PAUSE_MENU_MODE == 3) {
|
||||||
Gfx* sp84 = POLY_OPA_DISP;
|
Gfx* sp84 = POLY_OPA_DISP;
|
||||||
|
|
||||||
|
// SOH [Port] Draw game framebuffer using our custom handling
|
||||||
//func_800C24BC(&play->pauseBgPreRender, &sp84);
|
//func_800C24BC(&play->pauseBgPreRender, &sp84);
|
||||||
|
FB_DrawFromFramebuffer(&sp84, gPauseFrameBuffer, 255);
|
||||||
POLY_OPA_DISP = sp84;
|
POLY_OPA_DISP = sp84;
|
||||||
|
|
||||||
//goto Play_Draw_DrawOverlayElements;
|
goto Play_Draw_DrawOverlayElements;
|
||||||
}
|
} else {
|
||||||
//else
|
|
||||||
{
|
|
||||||
s32 sp80;
|
s32 sp80;
|
||||||
|
|
||||||
if ((HREG(80) != 10) || (HREG(83) != 0)) {
|
if ((HREG(80) != 10) || (HREG(83) != 0)) {
|
||||||
|
@ -1535,10 +1554,6 @@ void Play_Draw(PlayState* play) {
|
||||||
Environment_FillScreen(gfxCtx, 0, 0, 0, play->unk_11E18, FILL_SCREEN_OPA);
|
Environment_FillScreen(gfxCtx, 0, 0, 0, play->unk_11E18, FILL_SCREEN_OPA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((play->pauseCtx.state != 0) && (HREG(80) != 10) || (HREG(89) != 0)) {
|
|
||||||
Play_DrawOverlayElements(play);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((HREG(80) != 10) || (HREG(85) != 0)) {
|
if ((HREG(80) != 10) || (HREG(85) != 0)) {
|
||||||
func_800315AC(play, &play->actorCtx);
|
func_800315AC(play, &play->actorCtx);
|
||||||
}
|
}
|
||||||
|
@ -1586,17 +1601,36 @@ void Play_Draw(PlayState* play) {
|
||||||
|
|
||||||
play->pauseBgPreRender.fbuf = gfxCtx->curFrameBuffer;
|
play->pauseBgPreRender.fbuf = gfxCtx->curFrameBuffer;
|
||||||
play->pauseBgPreRender.fbufSave = (u16*)gZBuffer;
|
play->pauseBgPreRender.fbufSave = (u16*)gZBuffer;
|
||||||
func_800C1F20(&play->pauseBgPreRender, &sp70);
|
// SOH [Port] Use our custom copy method instead of the prerender system
|
||||||
|
// func_800C1F20(&play->pauseBgPreRender, &sp70);
|
||||||
if (R_PAUSE_MENU_MODE == 1) {
|
if (R_PAUSE_MENU_MODE == 1) {
|
||||||
play->pauseBgPreRender.cvgSave = (u8*)gfxCtx->curFrameBuffer;
|
play->pauseBgPreRender.cvgSave = (u8*)gfxCtx->curFrameBuffer;
|
||||||
func_800C20B4(&play->pauseBgPreRender, &sp70);
|
// func_800C20B4(&play->pauseBgPreRender, &sp70);
|
||||||
R_PAUSE_MENU_MODE = 2;
|
R_PAUSE_MENU_MODE = 2;
|
||||||
|
|
||||||
|
// #region SOH [Port] Custom handling for pause prerender background capture
|
||||||
|
lastPauseWidth = OTRGetGameRenderWidth();
|
||||||
|
lastPauseHeight = OTRGetGameRenderHeight();
|
||||||
|
hasCapturedPauseBuffer = false;
|
||||||
|
|
||||||
|
FB_CopyToFramebuffer(&sp70, 0, gPauseFrameBuffer, false, &hasCapturedPauseBuffer);
|
||||||
|
|
||||||
|
// Set the state back to ready after the recapture is done
|
||||||
|
if (recapturePauseBuffer) {
|
||||||
|
R_PAUSE_MENU_MODE = 3;
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
} else {
|
} else {
|
||||||
gTrnsnUnkState = 2;
|
gTrnsnUnkState = 2;
|
||||||
}
|
}
|
||||||
OVERLAY_DISP = sp70;
|
OVERLAY_DISP = sp70;
|
||||||
play->unk_121C7 = 2;
|
play->unk_121C7 = 2;
|
||||||
SREG(33) |= 1;
|
SREG(33) |= 1;
|
||||||
|
|
||||||
|
// 2S2H [Port] Continue to render the post world for pausing to avoid flashing the HUD
|
||||||
|
if (!(gTrnsnUnkState == 1)) {
|
||||||
|
goto Play_Draw_DrawOverlayElements;
|
||||||
|
}
|
||||||
} else if (R_PAUSE_MENU_MODE != 3) {
|
} else if (R_PAUSE_MENU_MODE != 3) {
|
||||||
Play_Draw_DrawOverlayElements:
|
Play_Draw_DrawOverlayElements:
|
||||||
if ((HREG(80) != 10) || (HREG(89) != 0)) {
|
if ((HREG(80) != 10) || (HREG(89) != 0)) {
|
||||||
|
@ -1627,15 +1661,6 @@ void Play_Draw(PlayState* play) {
|
||||||
|
|
||||||
Camera_Finish(GET_ACTIVE_CAM(play));
|
Camera_Finish(GET_ACTIVE_CAM(play));
|
||||||
|
|
||||||
{
|
|
||||||
Gfx* prevDisplayList = POLY_OPA_DISP;
|
|
||||||
Gfx* gfxP = Graph_GfxPlusOne(POLY_OPA_DISP);
|
|
||||||
gSPDisplayList(OVERLAY_DISP++, gfxP);
|
|
||||||
gSPEndDisplayList(gfxP++);
|
|
||||||
Graph_BranchDlist(prevDisplayList, gfxP);
|
|
||||||
POLY_OPA_DISP = gfxP;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLOSE_DISPS(gfxCtx);
|
CLOSE_DISPS(gfxCtx);
|
||||||
|
|
||||||
Interface_DrawTotalGameplayTimer(play);
|
Interface_DrawTotalGameplayTimer(play);
|
||||||
|
|
|
@ -1672,7 +1672,7 @@ void Player_DrawHookshotReticle(PlayState* play, Player* this, f32 hookshotRange
|
||||||
if (BgCheck_AnyLineTest3(&play->colCtx, &hookshotStart, &hookshotEnd, &firstHit, &colPoly, 1, 1, 1, 1, &bgId)) {
|
if (BgCheck_AnyLineTest3(&play->colCtx, &hookshotStart, &hookshotEnd, &firstHit, &colPoly, 1, 1, 1, 1, &bgId)) {
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
|
|
||||||
WORLD_OVERLAY_DISP = Gfx_SetupDL(WORLD_OVERLAY_DISP, 0x07);
|
OVERLAY_DISP = Gfx_SetupDL(OVERLAY_DISP, 0x07);
|
||||||
|
|
||||||
SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &firstHit, &sp68, &sp64);
|
SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &firstHit, &sp68, &sp64);
|
||||||
|
|
||||||
|
@ -1681,22 +1681,22 @@ void Player_DrawHookshotReticle(PlayState* play, Player* this, f32 hookshotRange
|
||||||
Matrix_Translate(firstHit.x, firstHit.y, firstHit.z, MTXMODE_NEW);
|
Matrix_Translate(firstHit.x, firstHit.y, firstHit.z, MTXMODE_NEW);
|
||||||
Matrix_Scale(sp60, sp60, sp60, MTXMODE_APPLY);
|
Matrix_Scale(sp60, sp60, sp60, MTXMODE_APPLY);
|
||||||
|
|
||||||
gSPMatrix(WORLD_OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
gSPMatrix(WORLD_OVERLAY_DISP++, SEG_ADDR(1, 0), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
gSPMatrix(OVERLAY_DISP++, SEG_ADDR(1, 0), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
||||||
gSPTexture(WORLD_OVERLAY_DISP++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
|
gSPTexture(OVERLAY_DISP++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
|
||||||
gDPLoadTextureBlock(WORLD_OVERLAY_DISP++, gLinkAdultHookshotReticleTex, G_IM_FMT_I, G_IM_SIZ_8b, 64, 64, 0,
|
gDPLoadTextureBlock(OVERLAY_DISP++, gLinkAdultHookshotReticleTex, G_IM_FMT_I, G_IM_SIZ_8b, 64, 64, 0,
|
||||||
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
|
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
|
||||||
if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId) && CVarGetInteger(CVAR_ENHANCEMENT("HookshotableReticle"), false)) {
|
if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId) && CVarGetInteger(CVAR_ENHANCEMENT("HookshotableReticle"), false)) {
|
||||||
const Color_RGBA8 defaultColor = { .r = 0, .g = 255, .b = 0, .a = 255 };
|
const Color_RGBA8 defaultColor = { .r = 0, .g = 255, .b = 0, .a = 255 };
|
||||||
const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.Target.Value"), defaultColor);
|
const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.Target.Value"), defaultColor);
|
||||||
gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a);
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a);
|
||||||
} else {
|
} else {
|
||||||
const Color_RGBA8 defaultColor = { .r = 255, .g = 0, .b = 0, .a = 255 };
|
const Color_RGBA8 defaultColor = { .r = 255, .g = 0, .b = 0, .a = 255 };
|
||||||
const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.NonTarget.Value"), defaultColor);
|
const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.NonTarget.Value"), defaultColor);
|
||||||
gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a);
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a);
|
||||||
}
|
}
|
||||||
gSPVertex(WORLD_OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotReticleVtx, 3, 0);
|
gSPVertex(OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotReticleVtx, 3, 0);
|
||||||
gSP1Triangle(WORLD_OVERLAY_DISP++, 0, 1, 2, 0);
|
gSP1Triangle(OVERLAY_DISP++, 0, 1, 2, 0);
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
@ -2095,8 +2095,14 @@ void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject,
|
||||||
Mtx* perspMtx = Graph_Alloc(play->state.gfxCtx, sizeof(Mtx));
|
Mtx* perspMtx = Graph_Alloc(play->state.gfxCtx, sizeof(Mtx));
|
||||||
Mtx* lookAtMtx = Graph_Alloc(play->state.gfxCtx, sizeof(Mtx));
|
Mtx* lookAtMtx = Graph_Alloc(play->state.gfxCtx, sizeof(Mtx));
|
||||||
|
|
||||||
|
u8 mirrorWorldActive = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0);
|
||||||
|
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
|
|
||||||
|
if (mirrorWorldActive) {
|
||||||
|
gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING);
|
||||||
|
}
|
||||||
|
|
||||||
gSPSegment(POLY_OPA_DISP++, 0x00, NULL);
|
gSPSegment(POLY_OPA_DISP++, 0x00, NULL);
|
||||||
|
|
||||||
gDPPipeSync(POLY_OPA_DISP++);
|
gDPPipeSync(POLY_OPA_DISP++);
|
||||||
|
@ -2148,7 +2154,7 @@ void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject,
|
||||||
|
|
||||||
Matrix_SetTranslateRotateYXZ(pos->x - ((CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0),
|
Matrix_SetTranslateRotateYXZ(pos->x - ((CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0),
|
||||||
pos->y - (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0) ? 16 : 0), pos->z, rot);
|
pos->y - (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0) ? 16 : 0), pos->z, rot);
|
||||||
Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), scale, scale, MTXMODE_APPLY);
|
Matrix_Scale(scale * (mirrorWorldActive ? -1 : 1), scale, scale, MTXMODE_APPLY);
|
||||||
|
|
||||||
gSPSegment(POLY_OPA_DISP++, 0x04, gameplayKeep);
|
gSPSegment(POLY_OPA_DISP++, 0x04, gameplayKeep);
|
||||||
gSPSegment(POLY_OPA_DISP++, 0x06, linkObject);
|
gSPSegment(POLY_OPA_DISP++, 0x06, linkObject);
|
||||||
|
@ -2170,7 +2176,7 @@ void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject,
|
||||||
|
|
||||||
Matrix_SetTranslateRotateYXZ(pos->x - (LINK_AGE_IN_YEARS == YEARS_ADULT ? 25 : 0),
|
Matrix_SetTranslateRotateYXZ(pos->x - (LINK_AGE_IN_YEARS == YEARS_ADULT ? 25 : 0),
|
||||||
pos->y + 280 + (LINK_AGE_IN_YEARS == YEARS_ADULT ? 48 : 0), pos->z, rot);
|
pos->y + 280 + (LINK_AGE_IN_YEARS == YEARS_ADULT ? 48 : 0), pos->z, rot);
|
||||||
Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), scale * 1, scale * 1, MTXMODE_APPLY);
|
Matrix_Scale(scale * (mirrorWorldActive ? -1 : 1), scale * 1, scale * 1, MTXMODE_APPLY);
|
||||||
|
|
||||||
Gfx* ohNo = POLY_XLU_DISP;
|
Gfx* ohNo = POLY_XLU_DISP;
|
||||||
POLY_XLU_DISP = POLY_OPA_DISP;
|
POLY_XLU_DISP = POLY_OPA_DISP;
|
||||||
|
@ -2181,6 +2187,10 @@ void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject,
|
||||||
POLY_XLU_DISP = ohNo;
|
POLY_XLU_DISP = ohNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mirrorWorldActive) {
|
||||||
|
gSPClearExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING);
|
||||||
|
}
|
||||||
|
|
||||||
POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP++);
|
POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP++);
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
|
|
|
@ -3272,14 +3272,6 @@ void KaleidoScope_Draw(PlayState* play) {
|
||||||
|
|
||||||
func_800AAA50(&play->view, 15);
|
func_800AAA50(&play->view, 15);
|
||||||
|
|
||||||
// Flip the OPA and XLU projections again as the set view call above reset the original flips from z_play
|
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) {
|
|
||||||
gSPMatrix(POLY_OPA_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
|
||||||
gSPMatrix(POLY_XLU_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
|
||||||
gSPMatrix(POLY_OPA_DISP++, play->view.viewingPtr, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
|
||||||
gSPMatrix(POLY_XLU_DISP++, play->view.viewingPtr, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue