papermario/src/screen_render_util.c

281 lines
11 KiB
C

#include "common.h"
#include "nu/nusys.h"
Gfx D_8014ED90[] = {
gsSPEndDisplayList(),
};
Vp DarknessStencilViewport = {
.vp = {
.vscale = { 128, 128, 511, 0 },
.vtrans = { 128, 128, 511, 0 }
}
};
Vtx Vtx_DarknessStencil[] = {
{{{ -16,-16, 0 }, 0, { 0x0000, 0x0000 }, { 0, 0, 0, 255 }}},
{{{ 16,-16, 0 }, 0, { 0x1000, 0x0000 }, { 0, 0, 0, 255 }}},
{{{ 16, 16, 0 }, 0, { 0x1000, 0x1000 }, { 0, 0, 0, 255 }}},
{{{ -16, 16, 0 }, 0, { 0x0000, 0x1000 }, { 0, 0, 0, 255 }}},
};
Gfx Gfx_DarknessStencilQuad[] = {
gsSPVertex(Vtx_DarknessStencil, 4, 0),
gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0),
gsDPPipeSync(),
gsSPEndDisplayList(),
};
void appendGfx_draw_prev_frame_buffer(s32 x1, s32 y1, s32 x2, s32 y2, f32 alpha) {
s32 stripY, extraY;
s32 i;
u16* prevGfxCfb = NULL;
// round the x positions
x1 = x1 - (x1 % 4);
x2 = x2 - (x2 % 4) + 4;
// can only load 6 rows of the color buffer at a time: 320*6*2 = 3840 bytes of the 4096 capacity
stripY = (y2 - y1) / 6;
extraY = (y2 - y1) % 6;
// get previous color buffer
for (i = 0; i < nuGfxCfbNum; i++) {
if (nuGfxCfb[i] == nuGfxCfb_ptr) {
prevGfxCfb = nuGfxCfb[(i + nuGfxCfbNum - 1) % nuGfxCfbNum];
}
}
gDPSetCycleType(gMainGfxPos++, G_CYC_1CYCLE);
gDPSetCombineMode(gMainGfxPos++, PM_CC_10, PM_CC_10);
gDPSetRenderMode(gMainGfxPos++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
gDPSetColorDither(gMainGfxPos++, G_CD_DISABLE);
gDPSetAlphaDither(gMainGfxPos++, G_AD_NOISE);
gDPSetTextureFilter(gMainGfxPos++, G_TF_POINT);
gDPSetTexturePersp(gMainGfxPos++, G_TP_NONE);
gSPTexture(gMainGfxPos++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
gDPSetPrimColor(gMainGfxPos++, 0, 0, 255, 255, 255, alpha);
for (i = 0; i < stripY; i++) {
gDPLoadTextureTile(gMainGfxPos++, osVirtualToPhysical(prevGfxCfb), G_IM_FMT_RGBA, G_IM_SIZ_16b, 320, 6,
x1, y1 + i * 6, x2 - 1, y1 + i * 6 + 5, 0,
G_TX_WRAP, G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(gMainGfxPos++, x1 * 4, (y1 + i * 6) * 4, x2 * 4, (y1 + i * 6 + 6) * 4,
G_TX_RENDERTILE, x1 * 32, (y1 + i * 6) * 32, 1024, 1024);
}
if (extraY != 0) {
gDPLoadTextureTile(gMainGfxPos++, osVirtualToPhysical(prevGfxCfb), G_IM_FMT_RGBA, G_IM_SIZ_16b, 320, extraY,
x1, y1 + i * 6, x2 - 1, y1 + i * 6 + extraY - 1, 0,
G_TX_WRAP, G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(gMainGfxPos++, x1 * 4, (y1 + i * 6) * 4, x2 * 4, (y1 + i * 6 + extraY) * 4,
G_TX_RENDERTILE, x1 * 32, (y1 + i * 6) * 32, 1024, 1024);
}
}
void draw_prev_frame_buffer_at_screen_pos(s32 x1, s32 y1, s32 x2, s32 y2, f32 alpha) {
s32 minX;
s32 minY;
s32 maxX;
s32 maxY;
maxX = x2;
maxY = y2;
if (maxX < x1) {
minX = maxX;
maxX = x1;
} else {
minX = x1;
}
if (maxY < y1) {
minY = maxY;
maxY = y1;
} else {
minY = y1;
}
if (minX < maxX && minY < maxY) {
if (minX < 0) {
minX = 0;
}
if (minY < 0) {
minY = 0;
}
if (maxX < 0) {
maxX = 0;
}
if (maxY < 0) {
maxY = 0;
}
if (minX >= SCREEN_WIDTH) {
minX = SCREEN_WIDTH - 1;
}
if (minY >= SCREEN_HEIGHT) {
minY = SCREEN_HEIGHT - 1;
}
if (maxX >= SCREEN_WIDTH) {
maxX = SCREEN_WIDTH - 1;
}
if (maxY >= SCREEN_HEIGHT) {
maxY = SCREEN_HEIGHT - 1;
}
if (minX != maxX && minY != maxY) {
appendGfx_draw_prev_frame_buffer(minX, minY, maxX, maxY, alpha);
}
}
}
void appendGfx_darkness_stencil(b32 isWorld, s32 posX, s32 posY, f32 alpha, f32 progress) {
Camera* camera = &gCameras[gCurrentCameraID];
f32 texScale, f24;
s32 i;
if (alpha == 0.0f) {
return;
}
if (!isWorld) {
texScale = (255.0f - alpha) * 10.0f / 255.0f + 0.14;
} else {
texScale = 0.5f;
texScale = (255.0f - alpha) * 9.5f / 255.0f + texScale;
posX += (camera->viewportW / 2 - posX) * (255.0f - alpha) / 255.0f;
posY += (camera->viewportH / 2 - posY) * (255.0f - alpha) / 255.0f;
}
guOrtho(&gDisplayContext->matrixStack[gMatrixListPos], -16.0f, 0.0f, 0.0f, 16.0f, -1000.0f, 1000.0f, 1.0f);
gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
gDPSetAlphaDither(gMainGfxPos++, G_AD_PATTERN);
gDPSetTextureFilter(gMainGfxPos++, G_TF_POINT);
gDPSetTexturePersp(gMainGfxPos++, G_TP_PERSP);
gDPSetColorImage(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_32b, 64, osVirtualToPhysical(nuGfxZBuffer));
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 0, 0, 64, 64);
gSPViewport(gMainGfxPos++, &DarknessStencilViewport);
gDPSetCombineMode(gMainGfxPos++, PM_CC_CONST_1, PM_CC_CONST_1);
guRotate(&gDisplayContext->matrixStack[gMatrixListPos], 0.0f, 0.0f, 0.0f, 1.0f);
gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gMainGfxPos++, Gfx_DarknessStencilQuad);
gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
gDPPipeSync(gMainGfxPos++);
gDPSetCombineMode(gMainGfxPos++, PM_CC_56, PM_CC_56);
for (i = 0; i < 2; i++) {
f32 f20;
f32 f2;
s32 s0 = 255;
if (i == 0) {
f20 = 0.9 - sin_deg(gGameStatusPtr->frameCounter) * 0.05;
} else {
f20 = 0.9 - sin_deg(gGameStatusPtr->frameCounter * 2 + i * 40) * 0.07;
}
f2 = 0;
if (s0 > 255) {
s0 = 255;
}
gDPSetPrimColor(gMainGfxPos++, 0, 0, 255, 255, 255, s0);
guRotate(&gDisplayContext->matrixStack[gMatrixListPos], i * 70 + f2, 0.0f, 0.0f, 1.0f);
gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
guScale(&gDisplayContext->matrixStack[gMatrixListPos], f20, f20, 1.0f);
gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
gSPDisplayList(gMainGfxPos++, Gfx_DarknessStencilQuad);
gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
}
gDPPipeSync(gMainGfxPos++);
gDPSetTexturePersp(gMainGfxPos++, G_TP_NONE);
gDPSetColorImage(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 64, osVirtualToPhysical(nuGfxZBuffer));
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 0, 0, 64, 64);
gDPSetCombineMode(gMainGfxPos++, PM_CC_0F, PM_CC_0F);
for (i = 0; i < 4; i++) {
gDPLoadTextureTile(gMainGfxPos++, osVirtualToPhysical(&nuGfxZBuffer[i * 2048]), G_IM_FMT_RGBA, G_IM_SIZ_32b, 64, 16, 0, 0, 63, 15, 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);
gDPPipeSync(gMainGfxPos++);
gSPTextureRectangle(gMainGfxPos++, 0, (i * 16) * 4, 64 * 4, (i * 16 + 16) * 4, G_TX_RENDERTILE, 0, 0, 0x400, 0x400);
gDPPipeSync(gMainGfxPos++);
}
gDPLoadTextureTile(gMainGfxPos++, osVirtualToPhysical(nuGfxZBuffer), G_IM_FMT_I, G_IM_SIZ_8b, 64, 64, 0, 0, 63, 63,
0, G_TX_MIRROR | G_TX_CLAMP, G_TX_MIRROR | G_TX_CLAMP, 6, 6, 15, 15);
gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, 0, 0, 0x01FC, 0x01FC);
gDPPipeSync(gMainGfxPos++);
gDPSetCycleType(gMainGfxPos++, G_CYC_FILL);
gDPSetRenderMode(gMainGfxPos++, G_RM_NOOP, G_RM_NOOP2);
gDPSetColorImage(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_32b, 64, osVirtualToPhysical(nuGfxZBuffer));
gDPSetFillColor(gMainGfxPos++, GPACK_ZDZ(G_MAXFBZ, 0)<<16 | GPACK_ZDZ(G_MAXFBZ, 0));
gDPFillRectangle(gMainGfxPos++, 0, 0, 63, 63);
gDPPipeSync(gMainGfxPos++);
gDPSetColorImage(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH, osVirtualToPhysical(nuGfxCfb_ptr));
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
gDPSetCycleType(gMainGfxPos++, G_CYC_1CYCLE);
gDPSetColorDither(gMainGfxPos++, G_CD_MAGICSQ);
gDPSetAlphaDither(gMainGfxPos++, G_AD_PATTERN);
gDPSetTextureFilter(gMainGfxPos++, G_TF_AVERAGE);
gDPSetRenderMode(gMainGfxPos++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
if (alpha != 255.0f || isWorld == 1) {
gDPSetCombineMode(gMainGfxPos++, PM_CC_57, PM_CC_57);
} else {
gDPSetCombineMode(gMainGfxPos++, PM_CC_58, PM_CC_58);
}
alpha *= 0.5f;
gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, alpha * 0.5f * progress / 255.0f);
gDPSetEnvColor(gMainGfxPos++, 255, 255, 255, (255.0f - alpha * 0.5f) * progress / 255.0f);
if (!isWorld) {
gSPTextureRectangle(gMainGfxPos++,
camera->viewportStartX * 4, camera->viewportStartY * 4,
(camera->viewportStartX + camera->viewportW) * 4, (camera->viewportStartY + camera->viewportH) * 4,
G_TX_RENDERTILE,
(12 - posX) * 32.0f / texScale + 16.0f + 1024.0f, (19 - posY) * 32.0f / texScale + 16.0f + 1024.0f,
1024.0f / texScale, 1024.0f / texScale);
} else {
gSPTextureRectangle(gMainGfxPos++,
camera->viewportStartX * 4, camera->viewportStartY * 4,
(camera->viewportStartX + camera->viewportW) * 4, (camera->viewportStartY + camera->viewportH) * 4,
G_TX_RENDERTILE,
(9 - posX) * 32.0f / texScale + 1024.0f, (32 - posY) * 32.0f / texScale + 1024.0f,
1024.0f / texScale, 1024.0f / texScale);
}
}
void appendGfx_screen_transition_stencil(s32 arg0, s32 arg1, f32 progress, s32 primR, s32 primG, s32 primB, s32 primA, s32 camID) {
s32 x1, y1, x2, y2, t5, t6;
f32 texScale;
if (camID >= 0) {
x1 = gCameras[camID].viewportStartX;
y1 = gCameras[camID].viewportStartY;
x2 = gCameras[camID].viewportStartX + gCameras[camID].viewportW;
y2 = gCameras[camID].viewportStartY + gCameras[camID].viewportH;
t5 = x1;
t6 = y1;
} else {
x1 = 0;
y1 = 0;
x2 = SCREEN_WIDTH;
y2 = SCREEN_HEIGHT;
t5 = 0;
t6 = 0;
}
if (progress == 0.0f) {
return;
}
gDPSetScissor(gMainGfxPos++, G_SC_NON_INTERLACE, x1, y1, x2, y2);
if (progress == 255.0f) {
gDPSetCombineMode(gMainGfxPos++, PM_CC_PRIM_FULL_ALPHA, PM_CC_PRIM_FULL_ALPHA);
}
gDPSetPrimColor(gMainGfxPos++, 0, 0, primR, primG, primB, primA);
texScale = (255.0f - progress) * 10.5f / 255.0f + 0.09; // range from
gSPTextureRectangle(gMainGfxPos++, x1 * 4, y1 * 4, x2 * 4, y2 * 4, G_TX_RENDERTILE,
(t5 - arg0) * 32.0f / texScale + 16.0f + 1024.0f, (t6 - arg1) * 32.0f / texScale + 16.0f + 1024.0f,
1024.0f / texScale, 1024.0f / texScale);
gDPPipeSync(gMainGfxPos++);
}