summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2024-11-15 03:02:20 -0700
committerGitHub <noreply@github.com>2024-11-15 03:02:20 -0700
commit75344d87eb0eed56bd366be65934681a5c1ecf15 (patch)
treea83eae76378c22fdecbb510caa3c5cd1dcb8c3e4
parent475f167bb2803999c5116bc285601d1f9a05d7de (diff)
[modding] Implement jumbtron fb effect (#125)
* Update Engine.cpp * minor fix and update LUS (#119) * minor fix and update LUS * update torch * Update torch * Implement jumbotron framebuffer effect * Update skybox_and_splitscreen.c --------- Co-authored-by: coco875 <59367621+coco875@users.noreply.github.com> Co-authored-by: Adam Bird <archez39@me.com>
m---------lib/wasm-micro-runtime0
m---------libultraship0
-rw-r--r--[-rwxr-xr-x]mods/C/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/asc/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/cython/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/go/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/js/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/lua/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/ocaml/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/py/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/py/setup.sh0
-rw-r--r--[-rwxr-xr-x]mods/py2many/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/python-rust/compile.sh0
-rw-r--r--[-rwxr-xr-x]mods/rust/compile.sh0
-rw-r--r--src/main.c5
-rw-r--r--src/main.h1
-rw-r--r--src/racing/framebuffer_effects.c221
-rw-r--r--src/racing/framebuffer_effects.h10
-rw-r--r--src/racing/render_courses.c33
-rw-r--r--src/racing/skybox_and_splitscreen.c112
-rw-r--r--src/racing/skybox_and_splitscreen.h1
m---------torch0
22 files changed, 218 insertions, 165 deletions
diff --git a/lib/wasm-micro-runtime b/lib/wasm-micro-runtime
deleted file mode 160000
-Subproject 51a71092bf97116685986ebfcdf858e59a3834d
diff --git a/libultraship b/libultraship
-Subproject 00c6bcc88286173ce22b8a6656373d3aa5830c6
+Subproject 736ad68251e49c24a8f11bb3499d3467a7ab670
diff --git a/mods/C/compile.sh b/mods/C/compile.sh
index b417dc02b..b417dc02b 100755..100644
--- a/mods/C/compile.sh
+++ b/mods/C/compile.sh
diff --git a/mods/asc/compile.sh b/mods/asc/compile.sh
index d31353e3a..d31353e3a 100755..100644
--- a/mods/asc/compile.sh
+++ b/mods/asc/compile.sh
diff --git a/mods/cython/compile.sh b/mods/cython/compile.sh
index 47b15d0e0..47b15d0e0 100755..100644
--- a/mods/cython/compile.sh
+++ b/mods/cython/compile.sh
diff --git a/mods/go/compile.sh b/mods/go/compile.sh
index acea4fa45..acea4fa45 100755..100644
--- a/mods/go/compile.sh
+++ b/mods/go/compile.sh
diff --git a/mods/js/compile.sh b/mods/js/compile.sh
index 5b3607792..5b3607792 100755..100644
--- a/mods/js/compile.sh
+++ b/mods/js/compile.sh
diff --git a/mods/lua/compile.sh b/mods/lua/compile.sh
index 39dbc2b45..39dbc2b45 100755..100644
--- a/mods/lua/compile.sh
+++ b/mods/lua/compile.sh
diff --git a/mods/ocaml/compile.sh b/mods/ocaml/compile.sh
index 853ad51c6..853ad51c6 100755..100644
--- a/mods/ocaml/compile.sh
+++ b/mods/ocaml/compile.sh
diff --git a/mods/py/compile.sh b/mods/py/compile.sh
index f7b5779c5..f7b5779c5 100755..100644
--- a/mods/py/compile.sh
+++ b/mods/py/compile.sh
diff --git a/mods/py/setup.sh b/mods/py/setup.sh
index 86e15774c..86e15774c 100755..100644
--- a/mods/py/setup.sh
+++ b/mods/py/setup.sh
diff --git a/mods/py2many/compile.sh b/mods/py2many/compile.sh
index 5e9844009..5e9844009 100755..100644
--- a/mods/py2many/compile.sh
+++ b/mods/py2many/compile.sh
diff --git a/mods/python-rust/compile.sh b/mods/python-rust/compile.sh
index 5c9a66906..5c9a66906 100755..100644
--- a/mods/python-rust/compile.sh
+++ b/mods/python-rust/compile.sh
diff --git a/mods/rust/compile.sh b/mods/rust/compile.sh
index 7c15987c8..7c15987c8 100755..100644
--- a/mods/rust/compile.sh
+++ b/mods/rust/compile.sh
diff --git a/src/main.c b/src/main.c
index 1435944b0..01857b6f5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -145,6 +145,7 @@ struct SPTask* gGfxSPTask;
s32 D_801502A0;
s32 D_801502A4;
u16* gPhysicalFramebuffers[3];
+u16 gPortFramebuffers[3][SCREEN_WIDTH * SCREEN_HEIGHT];
uintptr_t gPhysicalZBuffer;
UNUSED u32 D_801502B8;
UNUSED u32 D_801502BC;
@@ -889,6 +890,10 @@ void race_logic_loop(void) {
#if DVDL
display_dvdl();
#endif
+ // Copies after all the main rendering is complete. This is accurate to hardware.
+ // This means things like jumbotron will have the pause menu rendered in it.
+ // To avoid that, this line can be moved above func_800591B4.
+ FB_WriteFramebufferSliceToCPU(&gDisplayListHead, gPortFramebuffers[sRenderingFramebuffer], true);
gDPFullSync(gDisplayListHead++);
gSPEndDisplayList(gDisplayListHead++);
}
diff --git a/src/main.h b/src/main.h
index fd313838d..af9b2d6eb 100644
--- a/src/main.h
+++ b/src/main.h
@@ -183,6 +183,7 @@ extern struct SPTask* gGfxSPTask;
extern s32 D_801502A0;
extern s32 D_801502A4;
extern u16* gPhysicalFramebuffers[];
+extern u16 gPortFramebuffers[3][SCREEN_WIDTH * SCREEN_HEIGHT];
extern uintptr_t gPhysicalZBuffer;
extern Mat4 sBillBoardMtx;
diff --git a/src/racing/framebuffer_effects.c b/src/racing/framebuffer_effects.c
index be1b917a7..5e6fd394f 100644
--- a/src/racing/framebuffer_effects.c
+++ b/src/racing/framebuffer_effects.c
@@ -8,8 +8,6 @@
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;
@@ -18,46 +16,14 @@ s32 gReusableFrameBuffer = -1;
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);
- // }
-}
+ if (gReusableFrameBuffer == -1) {
+ gReusableFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true);
+ }
-// Fixed point macros
-#define FTOFIX(f) ((s32) ((f) * 65536.0))
-#define ITOFIX(i) ((s32) ((i) << 16))
-#define FIXTOF(x) ((double) ((x) / 65536.0))
-#define FIXTOI(x) ((s32) ((x) >> 16))
-
-#define toFixedInt(f) (FTOFIX(f) >> 16)
-#define toFrac(f) (FTOFIX(f) & 0xFFFF)
-
-// Setup a fixed-point matrix using floats or doubles. Recommend using doubles for more precision.
-#define toFixedPointMatrix(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16) \
- { \
- { ((toFixedInt(x1)) << 16) | toFixedInt(x2), ((toFixedInt(x3)) << 16) | toFixedInt(x4), \
- (toFixedInt(x5) << 16) | toFixedInt(x6), (toFixedInt(x7) << 16) | toFixedInt(x8) }, \
- { ((toFixedInt(x9)) << 16) | toFixedInt(x10), ((toFixedInt(x11)) << 16) | toFixedInt(x12), \
- (toFixedInt(x13) << 16) | toFixedInt(x14), (toFixedInt(x15) << 16) | toFixedInt(x16) }, \
- { ((toFrac(x1)) << 16) | toFrac(x2), ((toFrac(x3)) << 16) | toFrac(x4), (toFrac(x5) << 16) | toFrac(x6), \
- (toFrac(x7) << 16) | toFrac(x8) }, \
- { \
- ((toFrac(x9)) << 16) | toFrac(x10), ((toFrac(x11)) << 16) | toFrac(x12), \
- (toFrac(x13) << 16) | toFrac(x14), (toFrac(x15) << 16) | toFrac(x16) \
- } \
+ 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
@@ -67,28 +33,31 @@ void FB_CreateFramebuffers(void) {
* 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* gfx, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied) {
+void FB_CopyToFramebuffer(Gfx** gfxP, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied) {
+ Gfx* gfx = *gfxP;
+
+ gSPMatrix(gfx++, LOAD_ASSET(D_0D008E98), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- // gSPMatrix(gfx++, LOAD_ASSET(D_0D008E98), 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);
- // 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);
- // 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);
- // 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);
- // 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);
- // gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ gDPCopyFB(gfx++, fb_dest, fb_src, oncePerFrame, hasCopied);
- // gDPCopyFB(gfx++, fb_dest, fb_src, oncePerFrame, hasCopied);
+ *gfxP = gfx;
}
/**
@@ -97,70 +66,73 @@ void FB_CopyToFramebuffer(Gfx* gfx, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8
* 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* gfx, void* buffer, u8 byteSwap) {
- // Gfx* gfx = *gfxp;
- // printf("write!\n");
- // 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();
- // printf("half!\n");
- // 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;
- // }
- // printf("Aspect!\n");
- // 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);
- // printf("Complete!\n");
+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* gfx, s32 fb, u8 alpha) {
+void FB_DrawFromFramebuffer(Gfx** gfxP, s32 fb, u8 alpha) {
+ Gfx* gfx = *gfxP;
+
+ gSPMatrix(gfx++, LOAD_ASSET(D_0D008E98), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- // gSPMatrix(gfx++, LOAD_ASSET(D_0D008E98), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gDPSetEnvColor(gfx++, 255, 255, 255, alpha);
- // 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);
- // 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);
- // 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);
- // 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);
- // 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());
- // 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;
}
/**
@@ -168,27 +140,30 @@ void FB_DrawFromFramebuffer(Gfx* gfx, s32 fb, u8 alpha) {
* 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* gfx, s32 fb, u8 alpha, float scaleX, float scaleY) {
+void FB_DrawFromFramebufferScaled(Gfx** gfxP, s32 fb, u8 alpha, float scaleX, float scaleY) {
+ Gfx* gfx = *gfxP;
+
+ gDPSetEnvColor(gfx++, 255, 255, 255, alpha);
- // 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);
- // 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);
- // 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);
- // gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ gDPSetTextureImageFB(gfx++, 0, 0, 0, fb);
- // gDPSetTextureImageFB(gfx++, 0, 0, 0, fb);
+ float x0 = SCREEN_WIDTH * 0.5f * scaleX;
+ float y0 = SCREEN_HEIGHT * 0.5f * scaleY;
- // float x0 = SCREEN_WIDTH * 0.5f * scaleX;
- // float y0 = SCREEN_HEIGHT * 0.5f * scaleY;
+ gDPImageRectangle(gfx++, OTRGetRectDimensionFromLeftEdge(x0) << 2, (int) (y0) << 2, 0, 0,
+ OTRGetRectDimensionFromRightEdge((float) (SCREEN_WIDTH - x0)) << 2,
+ (int) ((float) (SCREEN_HEIGHT - y0)) << 2, OTRGetGameRenderWidth(), OTRGetGameRenderHeight(),
+ G_TX_RENDERTILE, OTRGetGameRenderWidth(), OTRGetGameRenderHeight());
- // gDPImageRectangle(gfx++, OTRGetRectDimensionFromLeftEdge(x0) << 2, (int) (y0) << 2, 0, 0,
- // OTRGetRectDimensionFromRightEdge((float) (SCREEN_WIDTH - x0)) << 2,
- // (int) ((float) (SCREEN_HEIGHT - y0)) << 2, OTRGetGameRenderWidth(), OTRGetGameRenderHeight(),
- // G_TX_RENDERTILE, OTRGetGameRenderWidth(), OTRGetGameRenderHeight());
+ *gfxP = gfx;
}
diff --git a/src/racing/framebuffer_effects.h b/src/racing/framebuffer_effects.h
index a24d07456..6d9216cc4 100644
--- a/src/racing/framebuffer_effects.h
+++ b/src/racing/framebuffer_effects.h
@@ -3,15 +3,13 @@
#include <libultraship.h>
-extern s32 gPauseFrameBuffer;
-extern s32 gBlurFrameBuffer;
extern s32 gReusableFrameBuffer;
extern s32 gN64ResFrameBuffer;
void FB_CreateFramebuffers(void);
-void FB_CopyToFramebuffer(Gfx* gfx, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied);
-void FB_WriteFramebufferSliceToCPU(Gfx* gfx, void* buffer, u8 byteSwap);
-void FB_DrawFromFramebuffer(Gfx* gfx, s32 fb, u8 alpha);
-void FB_DrawFromFramebufferScaled(Gfx* gfx, s32 fb, u8 alpha, float scaleX, float scaleY);
+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
diff --git a/src/racing/render_courses.c b/src/racing/render_courses.c
index 7238a02e3..7af74516b 100644
--- a/src/racing/render_courses.c
+++ b/src/racing/render_courses.c
@@ -869,6 +869,16 @@ void render_luigi_raceway(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ // Invalidate Jumbotron textures so they update each frame
+ // This could be more efficient if we exposed the non-opcode based invalidation to be called
+ // inside copy_framebuffers_port
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0xF800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x10800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x11800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x12800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x13800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x14800);
+
if (func_80290C20(arg0->camera) == 1) {
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
@@ -906,11 +916,6 @@ void render_luigi_raceway(struct UnkStruct_800DC5EC* arg0) {
currentScreenSection = 0;
}
- u16* fb = (u16*) gSegmentTable[5] + 0xF800;
-
- // FB_WriteFramebufferSliceToCPU(gDisplayListHead, fb, true);
- // FB_DrawFromFramebuffer(gDisplayListHead, 0, fb, true);
- // FB_CopyToFramebuffer(gDisplayListHead, 0, fb, false, NULL);
/**
* The jumbo television screen is split into six sections each section is copied one at a time.
* This is done to fit within the n64's texture size requirements; 64x32
@@ -959,6 +964,10 @@ void render_luigi_raceway(struct UnkStruct_800DC5EC* arg0) {
#endif
break;
}
+
+ copy_jumbotron_fb_port(D_800DC5DC, D_800DC5E0, currentScreenSection,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPortFramebuffers[prevFrame]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xF800));
}
}
@@ -1122,6 +1131,16 @@ void render_wario_stadium(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ // Invalidate Jumbotron textures so they update each frame
+ // This could be more efficient if we exposed the non-opcode based invalidation to be called
+ // inside copy_framebuffers_port
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x8800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0x9800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0xA800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0xB800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0xC800);
+ gSPInvalidateTexCache(gDisplayListHead++, gSegmentTable[5] + 0xD800);
+
if (func_80290C20(arg0->camera) == 1) {
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
@@ -1200,6 +1219,10 @@ void render_wario_stadium(struct UnkStruct_800DC5EC* arg0) {
#endif
break;
}
+
+ copy_jumbotron_fb_port(D_800DC5DC, D_800DC5E0, currentScreenSection,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPortFramebuffers[prevFrame]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x8800));
}
}
diff --git a/src/racing/skybox_and_splitscreen.c b/src/racing/skybox_and_splitscreen.c
index f93394b0c..a3755987f 100644
--- a/src/racing/skybox_and_splitscreen.c
+++ b/src/racing/skybox_and_splitscreen.c
@@ -980,6 +980,46 @@ void copy_framebuffer(s32 arg0, s32 arg1, s32 width, s32 height, u16* source, u1
}
}
+// Handles copying framebuffer to course texture data region for the Jumbotron in the port
+// This only supports framebuffers and copy regions being within 320x240
+// Any attempt to support larger sizes would require reworking course data
+void copy_jumbotron_fb_port(s32 ulx, s32 uly, s16 portionToDraw, u16* source, u16* target) {
+ // Add CVar if we want to expose a user toggle for only updating 1/6 of the jumbotron per frame
+ u8 updateWholeJumbo = true;
+
+ if (portionToDraw == -1 || updateWholeJumbo) {
+ copy_framebuffer(ulx, uly, 64, 32, source, target);
+ copy_framebuffer(ulx + 64, uly, 64, 32, source, target + (64 * 32 * 1));
+ copy_framebuffer(ulx, uly + 32, 64, 32, source, target + (64 * 32 * 2));
+ copy_framebuffer(ulx + 64, uly + 32, 64, 32, source, target + (64 * 32 * 3));
+ copy_framebuffer(ulx, uly + 64, 64, 32, source, target + (64 * 32 * 4));
+ copy_framebuffer(ulx + 64, uly + 64, 64, 32, source, target + (64 * 32 * 5));
+ } else {
+ switch (portionToDraw) {
+ case 0:
+ copy_framebuffer(ulx, uly, 64, 32, source, target);
+ break;
+ case 1:
+ copy_framebuffer(ulx + 64, uly, 64, 32, source, target + (64 * 32 * 1));
+ break;
+ case 2:
+ copy_framebuffer(ulx, uly + 32, 64, 32, source, target + (64 * 32 * 2));
+ break;
+ case 3:
+ copy_framebuffer(ulx + 64, uly + 32, 64, 32, source, target + (64 * 32 * 3));
+ break;
+ case 4:
+ copy_framebuffer(ulx, uly + 64, 64, 32, source, target + (64 * 32 * 4));
+ break;
+ case 5:
+ copy_framebuffer(ulx + 64, uly + 64, 64, 32, source, target + (64 * 32 * 5));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
void func_802A7728(void) {
s16 temp_v0;
@@ -995,20 +1035,25 @@ void func_802A7728(void) {
} else if (temp_v0 > 2) {
temp_v0 = 0;
}
- // copy_framebuffer(D_800DC5DC, D_800DC5E0, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x8800));
- // copy_framebuffer(D_800DC5DC + 64, D_800DC5E0, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x9800));
- // copy_framebuffer(D_800DC5DC, D_800DC5E0 + 32, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xA800));
- // copy_framebuffer(D_800DC5DC + 64, D_800DC5E0 + 32, 64, 32,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xB800));
- // copy_framebuffer(D_800DC5DC, D_800DC5E0 + 64, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xC800));
- // copy_framebuffer(D_800DC5DC + 64, D_800DC5E0 + 64, 64, 32,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xD800));
+#if TARGET_N64
+ copy_framebuffer(D_800DC5DC, D_800DC5E0, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x8800));
+ copy_framebuffer(D_800DC5DC + 64, D_800DC5E0, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x9800));
+ copy_framebuffer(D_800DC5DC, D_800DC5E0 + 32, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xA800));
+ copy_framebuffer(D_800DC5DC + 64, D_800DC5E0 + 32, 64, 32,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xB800));
+ copy_framebuffer(D_800DC5DC, D_800DC5E0 + 64, 64, 32, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xC800));
+ copy_framebuffer(D_800DC5DC + 64, D_800DC5E0 + 64, 64, 32,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xD800));
+#else
+ copy_jumbotron_fb_port(D_800DC5DC, D_800DC5E0, -1, PHYSICAL_TO_VIRTUAL(gPortFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x8800));
+#endif
}
void func_802A7940(void) {
@@ -1026,21 +1071,26 @@ void func_802A7940(void) {
} else if (temp_v0 > 2) {
temp_v0 = 0;
}
- // copy_framebuffer(D_800DC5DC, D_800DC5E0, 0x40, 0x20, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xF800));
- // copy_framebuffer(D_800DC5DC + 0x40, D_800DC5E0, 0x40, 0x20,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x10800));
- // copy_framebuffer(D_800DC5DC, D_800DC5E0 + 0x20, 0x40, 0x20,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x11800));
- // copy_framebuffer(D_800DC5DC + 0x40, D_800DC5E0 + 0x20, 0x40, 0x20,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x12800));
- // copy_framebuffer(D_800DC5DC, D_800DC5E0 + 0x40, 0x40, 0x20,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x13800));
- // copy_framebuffer(D_800DC5DC + 0x40, D_800DC5E0 + 0x40, 0x40, 0x20,
- // (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
- // (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x14800));
+#if TARGET_N64
+ copy_framebuffer(D_800DC5DC, D_800DC5E0, 0x40, 0x20, (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xF800));
+ copy_framebuffer(D_800DC5DC + 0x40, D_800DC5E0, 0x40, 0x20,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x10800));
+ copy_framebuffer(D_800DC5DC, D_800DC5E0 + 0x20, 0x40, 0x20,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x11800));
+ copy_framebuffer(D_800DC5DC + 0x40, D_800DC5E0 + 0x20, 0x40, 0x20,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x12800));
+ copy_framebuffer(D_800DC5DC, D_800DC5E0 + 0x40, 0x40, 0x20,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x13800));
+ copy_framebuffer(D_800DC5DC + 0x40, D_800DC5E0 + 0x40, 0x40, 0x20,
+ (u16*) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0x14800));
+#else
+ copy_jumbotron_fb_port(D_800DC5DC, D_800DC5E0, -1, (u16*) PHYSICAL_TO_VIRTUAL(gPortFramebuffers[temp_v0]),
+ (u16*) PHYSICAL_TO_VIRTUAL(gSegmentTable[5] + 0xF800));
+#endif
}
diff --git a/src/racing/skybox_and_splitscreen.h b/src/racing/skybox_and_splitscreen.h
index 50f7d71e2..a648e0fe6 100644
--- a/src/racing/skybox_and_splitscreen.h
+++ b/src/racing/skybox_and_splitscreen.h
@@ -54,6 +54,7 @@ void render_player_four_3p_4p_screen(void);
void render_screens(s32 mode, s32 cameraId, s32 playerId);
void func_802A74BC(void);
void copy_framebuffer(s32, s32, s32, s32, u16*, u16*);
+void copy_jumbotron_fb_port(s32 ulx, s32 uly, s16 portionToDraw, u16* source, u16* target);
void func_802A7728(void);
void func_802A7940(void);
diff --git a/torch b/torch
-Subproject ff8c2d13c71069f3117faf42ed25f0816229a87
+Subproject 6edf65beca37954d6d2243c92875a1dc84b6b3f