diff options
| author | MegaMech <MegaMech@users.noreply.github.com> | 2024-11-15 03:02:20 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-15 03:02:20 -0700 |
| commit | 75344d87eb0eed56bd366be65934681a5c1ecf15 (patch) | |
| tree | a83eae76378c22fdecbb510caa3c5cd1dcb8c3e4 | |
| parent | 475f167bb2803999c5116bc285601d1f9a05d7de (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-runtime | 0 | ||||
| m--------- | libultraship | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/C/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/asc/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/cython/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/go/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/js/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/lua/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/ocaml/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/py/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/py/setup.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/py2many/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/python-rust/compile.sh | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | mods/rust/compile.sh | 0 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/main.h | 1 | ||||
| -rw-r--r-- | src/racing/framebuffer_effects.c | 221 | ||||
| -rw-r--r-- | src/racing/framebuffer_effects.h | 10 | ||||
| -rw-r--r-- | src/racing/render_courses.c | 33 | ||||
| -rw-r--r-- | src/racing/skybox_and_splitscreen.c | 112 | ||||
| -rw-r--r-- | src/racing/skybox_and_splitscreen.h | 1 | ||||
| m--------- | torch | 0 |
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 |
