diff --git a/patches/camera_transform_tagging.c b/patches/camera_transform_tagging.c new file mode 100644 index 0000000..022c44f --- /dev/null +++ b/patches/camera_transform_tagging.c @@ -0,0 +1,27 @@ +#include "patches.h" +#include "transform_ids.h" + +s32 View_ApplyPerspective(View* view); +s32 View_ApplyOrtho(View* view); + +/** + * Apply view to POLY_OPA_DISP, POLY_XLU_DISP (and OVERLAY_DISP if ortho) + */ +void View_Apply(View* view, s32 mask) { + mask = (view->flags & mask) | (mask >> 4); + + if (mask & VIEW_PROJECTION_ORTHO) { + View_ApplyOrtho(view); + } else { + View_ApplyPerspective(view); + } + + // @recomp Tag the camera matrices + GraphicsContext* gfxCtx = view->gfxCtx; + OPEN_DISPS(gfxCtx); + + gEXMatrixGroup(POLY_OPA_DISP++, CAMERA_TRANSFORM_ID_START, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR); + gEXMatrixGroup(POLY_XLU_DISP++, CAMERA_TRANSFORM_ID_START, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR); + + CLOSE_DISPS(gfxCtx); +} diff --git a/patches/sky_transform_tagging.c b/patches/sky_transform_tagging.c new file mode 100644 index 0000000..90b001f --- /dev/null +++ b/patches/sky_transform_tagging.c @@ -0,0 +1,59 @@ +#include "patches.h" +#include "transform_ids.h" + +extern Mtx* sSkyboxDrawMatrix; + +void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId, s16 blend, f32 x, f32 y, f32 z) { + // @recomp skip drawing skyboxes with null textures as they hurt performance due to the accidental framebuffer effects they incur. + if (skyboxCtx->staticSegments[0] == NULL || skyboxCtx->staticSegments[1] == NULL) { + return; + } + + OPEN_DISPS(gfxCtx); + + Gfx_SetupDL40_Opa(gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x0B, skyboxCtx->paletteStaticSegment); + gSPTexture(POLY_OPA_DISP++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON); + + sSkyboxDrawMatrix = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); + + Matrix_Translate(x, y, z, MTXMODE_NEW); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + Matrix_RotateXFApply(skyboxCtx->rot.x); + Matrix_RotateYF(skyboxCtx->rot.y, MTXMODE_APPLY); + Matrix_RotateZF(skyboxCtx->rot.z, MTXMODE_APPLY); + Matrix_ToMtx(sSkyboxDrawMatrix); + + gSPMatrix(POLY_OPA_DISP++, sSkyboxDrawMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + // @recomp Tag the skybox's matrix. + gEXMatrixGroup(POLY_OPA_DISP++, SKYBOX_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR); + + gDPSetColorDither(POLY_OPA_DISP++, G_CD_MAGICSQ); + gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP); + gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->paletteStaticSegment); + gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_RGBA16); + gDPSetTextureConvert(POLY_OPA_DISP++, G_TC_FILT); + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, TEXEL0, PRIMITIVE_ALPHA, TEXEL0, TEXEL1, TEXEL0, PRIMITIVE, TEXEL0, + PRIMITIVE, ENVIRONMENT, COMBINED, ENVIRONMENT, 0, 0, 0, COMBINED); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, skyboxCtx->prim.r, skyboxCtx->prim.g, skyboxCtx->prim.b, blend); + gDPSetEnvColor(POLY_OPA_DISP++, skyboxCtx->env.r, skyboxCtx->env.g, skyboxCtx->env.b, 0); + + gSPDisplayList(POLY_OPA_DISP++, &skyboxCtx->dListBuf[0]); + gSPDisplayList(POLY_OPA_DISP++, &skyboxCtx->dListBuf[2]); + gSPDisplayList(POLY_OPA_DISP++, &skyboxCtx->dListBuf[4]); + gSPDisplayList(POLY_OPA_DISP++, &skyboxCtx->dListBuf[6]); + gSPDisplayList(POLY_OPA_DISP++, &skyboxCtx->dListBuf[8]); + + if (skyboxId == SKYBOX_CUTSCENE_MAP) { + gSPDisplayList(POLY_OPA_DISP++, &skyboxCtx->dListBuf[10]); + } + + gDPPipeSync(POLY_OPA_DISP++); + + // @recomp Pop the skybox's matrix tag. + gEXPopMatrixGroup(POLY_OPA_DISP++); + + CLOSE_DISPS(gfxCtx); +} diff --git a/patches/terrain_transform_tagging.c b/patches/terrain_transform_tagging.c new file mode 100644 index 0000000..9cfa424 --- /dev/null +++ b/patches/terrain_transform_tagging.c @@ -0,0 +1,41 @@ +#include "patches.h" +#include "transform_ids.h" + +static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f }; + +extern RoomDrawHandler sRoomDrawHandlers[]; + +void Room_Draw(PlayState* play, Room* room, u32 flags) { + if (room->segment != NULL) { + gSegments[3] = OS_K0_TO_PHYSICAL(room->segment); + + OPEN_DISPS(play->state.gfxCtx); + + // @recomp Tag the room's matrices if applicable. + // Tag terrain as being ignored for interpolation, which prevents interpolation glitches where some pieces of terrain swap places when one comes into view. + if (flags & ROOM_DRAW_OPA) { + gEXMatrixGroup(POLY_OPA_DISP++, G_EX_ID_IGNORE, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR); + } + if (flags & ROOM_DRAW_XLU) { + gEXMatrixGroup(POLY_XLU_DISP++, G_EX_ID_IGNORE, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR); + } + + CLOSE_DISPS(play->state.gfxCtx); + + sRoomDrawHandlers[room->roomShape->base.type](play, room, flags); + + OPEN_DISPS(play->state.gfxCtx); + + // @recomp Pop the room's matrix tags if applicable. + if (flags & ROOM_DRAW_OPA) { + gEXPopMatrixGroup(POLY_OPA_DISP++); + } + if (flags & ROOM_DRAW_XLU) { + gEXPopMatrixGroup(POLY_XLU_DISP++); + } + + CLOSE_DISPS(play->state.gfxCtx); + } + return; +} + diff --git a/patches/transform_ids.h b/patches/transform_ids.h index ad4a99b..4768c30 100644 --- a/patches/transform_ids.h +++ b/patches/transform_ids.h @@ -1,6 +1,12 @@ #ifndef __TRANSFORM_IDS_H__ #define __TRANSFORM_IDS_H__ +#define CAMERA_TRANSFORM_ID_START 0x10U + +#define SKYBOX_TRANSFORM_ID_START 0x100U + +#define TERRAIN_TRANSFORM_ID_START 0x200U + #define ACTOR_TRANSFORM_LIMB_COUNT 128 #define ACTOR_TRANSFORM_ID_COUNT (ACTOR_TRANSFORM_LIMB_COUNT * 2) // One ID for each limb and another for each post-draw #define ACTOR_TRANSFORM_ID_START 0x1000000U