Implement picto box frame buffer and reading logic (#189)

This commit is contained in:
Archez
2024-05-22 09:05:01 -05:00
committed by Garrett Cox
parent 18d88ec374
commit b4c7a8bd22
5 changed files with 73 additions and 19 deletions
+12 -4
View File
@@ -1,7 +1,8 @@
#include "framebuffer_effects.h"
#include "global.h"
int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height);
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;
@@ -9,17 +10,24 @@ s32 gBlurFrameBuffer = -1;
// i.e. the VisMono and VisFbuf effects
s32 gReusableFrameBuffer = -1;
// Picto box buffer is unscaled at 320x240
s32 gPictoBoxFrameBuffer = -1;
void FB_CreateFramebuffers(void) {
if (gPauseFrameBuffer == -1) {
gPauseFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
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);
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);
gReusableFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, true);
}
if (gPictoBoxFrameBuffer == -1) {
gPictoBoxFrameBuffer = gfx_create_framebuffer(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, false);
}
}
+1
View File
@@ -6,6 +6,7 @@
extern s32 gPauseFrameBuffer;
extern s32 gBlurFrameBuffer;
extern s32 gReusableFrameBuffer;
extern s32 gPictoBoxFrameBuffer;
void FB_CreateFramebuffers(void);
void FB_CopyToFramebuffer(Gfx** gfxp, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied);
+5 -1
View File
@@ -2480,7 +2480,7 @@ void Interface_UpdateButtonsPart1(PlayState* play) {
if (!CHECK_EVENTINF(EVENTINF_41) ||
(CHECK_EVENTINF(EVENTINF_41) && (CutsceneManager_GetCurrentCsId() == CS_ID_NONE))) {
Audio_PlaySfx(NA_SE_SY_CAMERA_SHUTTER);
SREG(89) = 1;
R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_SETUP;
play->haltAllActors = true;
sPictoState = PICTO_BOX_STATE_SETUP_PHOTO;
sPictoPhotoBeingTaken = true;
@@ -7128,6 +7128,10 @@ void Interface_Draw(PlayState* play) {
pictoRectTop = PICTO_PHOTO_TOPLEFT_Y - 33;
for (sp2CC = 0; sp2CC < (PICTO_PHOTO_HEIGHT / 8); sp2CC++, pictoRectTop += 8) {
pictoRectLeft = PICTO_PHOTO_TOPLEFT_X;
// 2S2H [Port] Invalidate each section. This could probably be optimized to only be done once each pic
gSPInvalidateTexCache(OVERLAY_DISP++,
(u8*)((play->pictoPhotoI8 != NULL) ? play->pictoPhotoI8 : gWorkBuffer) +
(0x500 * sp2CC));
gDPLoadTextureBlock(OVERLAY_DISP++,
(u8*)((play->pictoPhotoI8 != NULL) ? play->pictoPhotoI8 : gWorkBuffer) +
(0x500 * sp2CC),
+54 -13
View File
@@ -1451,35 +1451,76 @@ void Play_DrawMain(PlayState* this) {
R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_PROCESS;
this->pauseBgPreRender.fbufSave = gfxCtx->zbuffer;
this->pauseBgPreRender.cvgSave = this->unk_18E58;
// #region 2S2H [Port] Custom handling for pause prerender background capture
lastPauseWidth = OTRGetGameRenderWidth();
lastPauseHeight = OTRGetGameRenderHeight();
hasCapturedPauseBuffer = false;
FB_CopyToFramebuffer(&sp74, 0, gPauseFrameBuffer, false, &hasCapturedPauseBuffer);
// Set the state back to ready after the recapture is done
if (recapturePauseBuffer) {
R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_READY;
}
// #endregion
} else if (R_PICTO_PHOTO_STATE == PICTO_PHOTO_STATE_SETUP) {
R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_PROCESS;
this->pauseBgPreRender.fbufSave = gfxCtx->zbuffer;
this->pauseBgPreRender.cvgSave = this->unk_18E58;
// BENTODO: Add this back when coverage is figured out - for the anti aliasing filter
// this->pauseBgPreRender.cvgSave = this->unk_18E58;
this->pauseBgPreRender.cvgSave = NULL;
// #region 2S2H [Port] Custom handling for picto box capture
// Copy to our reusable buffer first
FB_CopyToFramebuffer(&sp74, 0, gReusableFrameBuffer, false, NULL);
// Set the picto framebuffer as the draw target (320x240)
gsSPSetFB(sp74++, gPictoBoxFrameBuffer);
int16_t s0 = 0, t0 = 0;
int16_t s1 = OTRGetGameRenderWidth();
int16_t t1 = OTRGetGameRenderHeight();
float aspectRatio = OTRGetAspectRatio();
float fourByThree = 4.0f / 3.0f;
// Adjsut the texture coordinates so that only a 4:3 region from the center is drawn
// to the picto buffer. Currently ratios smaller than 4:3 will just stretch to fill.
if (aspectRatio > fourByThree) {
int16_t adjustedWidth = OTRGetGameRenderWidth() / (aspectRatio / fourByThree);
s0 = (OTRGetCurrentWidth() - adjustedWidth) / 2;
s1 -= s0;
}
gDPSetTextureImageFB(sp74++, 0, 0, 0, gReusableFrameBuffer);
gDPImageRectangle(sp74++, 0 << 2, 0 << 2, s0, t0, SCREEN_WIDTH << 2, SCREEN_HEIGHT << 2, s1, t1,
G_TX_RENDERTILE, OTRGetGameRenderWidth(), OTRGetGameRenderHeight());
// Read the picto box framebuffer back as a rgba16 buffer
gDPReadFB(sp74++, gPictoBoxFrameBuffer, this->pauseBgPreRender.fbufSave, 0, 0, SCREEN_WIDTH,
SCREEN_HEIGHT);
gsSPResetFB(sp74++);
// #endregion
} else {
gTransitionTileState = TRANS_TILE_PROCESS;
this->pauseBgPreRender.fbufSave = gfxCtx->zbuffer;
this->pauseBgPreRender.cvgSave = NULL;
// BENTODO: Figure out what the transition does with framebuffers
}
lastPauseWidth = OTRGetGameRenderWidth();
lastPauseHeight = OTRGetGameRenderHeight();
hasCapturedPauseBuffer = false;
FB_CopyToFramebuffer(&sp74, 0, gPauseFrameBuffer, false, &hasCapturedPauseBuffer);
gSPEndDisplayList(sp74++);
Graph_BranchDlist(sp70, sp74);
POLY_OPA_DISP = sp74;
this->unk_18B49 = 2;
SREG(33) |= 1;
// 2S2H [Port] Set the state back to ready after the recapture is done
if (recapturePauseBuffer) {
R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_READY;
// 2S2H [Port] Continue to render the post world for pausing to avoid flashing the HUD
if (gTransitionTileState == TRANS_TILE_PROCESS || R_PICTO_PHOTO_STATE == PICTO_PHOTO_STATE_PROCESS) {
goto SkipPostWorldDraw;
}
// 2S2H [Port] Continue to render the post world to avoid flashing the HUD
// goto SkipPostWorldDraw;
}
PostWorldDraw: