gfx: Add support for the top screen's 800px high resolution mode (!!!)

This commit is contained in:
fincs 2020-06-13 22:48:36 +02:00
parent 09d629aa85
commit d521c99769
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
2 changed files with 68 additions and 15 deletions

View File

@ -5,6 +5,10 @@
* This API provides basic functionality needed to bring up framebuffers for both screens,
* as well as managing display mode (stereoscopic 3D) and double buffering.
* It is mainly an abstraction over the gsp service.
*
* Please note that the 3DS uses *portrait* screens rotated 90 degrees counterclockwise.
* Width/height refer to the physical dimensions of the screen; that is, the top screen
* is 240 pixels wide and 400 pixels tall; while the bottom screen is 240x320.
*/
#pragma once
@ -80,6 +84,22 @@ void gfxSet3D(bool enable);
*/
bool gfxIs3D(void);
/**
* @brief Retrieves the status of the 800px (double-height) high resolution display mode of the top screen.
* @return true if wide mode enabled, false otherwise.
*/
bool gfxIsWide(void);
/**
* @brief Enables or disables the 800px (double-height) high resolution display mode of the top screen.
* @param enable Pass true to enable, false to disable.
* @note Wide mode is disabled by default.
* @note Wide and stereoscopic 3D modes are mutually exclusive.
* @note In wide mode pixels are not square, since scanlines are half as tall as they normally are.
* @warning Wide mode does not work on Old 2DS consoles (however it does work on New 2DS XL consoles).
*/
void gfxSetWide(bool enable);
/**
* @brief Changes the pixel format of a screen.
* @param screen Screen ID (see \ref gfxScreen_t)

View File

@ -10,7 +10,12 @@ static u32 gfxTopFramebufferMaxSize;
static u32 gfxBottomFramebufferMaxSize;
static GSPGPU_FramebufferFormat gfxFramebufferFormats[2];
static bool gfxEnable3D, gfxIsVram;
static enum {
MODE_2D = 0,
MODE_3D = 1,
MODE_WIDE = 2,
} gfxTopMode;
static bool gfxIsVram;
static u8 gfxCurBuf[2];
static u8 gfxIsDoubleBuf[2];
@ -19,12 +24,22 @@ static void *(*screenAlloc)(size_t);
void gfxSet3D(bool enable)
{
gfxEnable3D = enable;
gfxTopMode = enable ? MODE_3D : MODE_2D;
}
bool gfxIs3D(void)
{
return gfxEnable3D;
return gfxTopMode == MODE_3D;
}
void gfxSetWide(bool enable)
{
gfxTopMode = enable ? MODE_WIDE : MODE_2D;
}
bool gfxIsWide(void)
{
return gfxTopMode == MODE_WIDE;
}
void gfxSetScreenFormat(gfxScreen_t screen, GSPGPU_FramebufferFormat format)
@ -77,15 +92,20 @@ static void gfxPresentFramebuffer(gfxScreen_t screen, u8 id)
if (screen == GFX_TOP)
{
fb_a = gfxTopFramebuffers[id];
if (gfxEnable3D)
switch (gfxTopMode)
{
mode |= BIT(5);
fb_b = fb_a + gfxTopFramebufferMaxSize/2;
}
else
{
mode |= BIT(6);
fb_b = fb_a;
default:
case MODE_2D:
mode |= BIT(6);
fb_b = fb_a;
break;
case MODE_3D:
mode |= BIT(5);
fb_b = fb_a + gfxTopFramebufferMaxSize/2;
break;
case MODE_WIDE:
fb_b = fb_a;
break;
}
}
else
@ -173,8 +193,19 @@ u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* hei
{
fb = gfxTopFramebuffers[id];
scr_height = GSP_SCREEN_HEIGHT_TOP;
if (gfxEnable3D && side != GFX_LEFT)
fb += gfxTopFramebufferMaxSize/2;
switch (gfxTopMode)
{
default:
case MODE_2D:
break;
case MODE_3D:
if (side != GFX_LEFT)
fb += gfxTopFramebufferMaxSize/2;
break;
case MODE_WIDE:
scr_height = GSP_SCREEN_HEIGHT_TOP_2X;
break;
}
}
else // GFX_BOTTOM
{
@ -194,10 +225,12 @@ void gfxFlushBuffers(void)
{
const u32 baseSize = GSP_SCREEN_WIDTH * gspGetBytesPerPixel(gfxGetScreenFormat(GFX_TOP));
const u32 topSize = GSP_SCREEN_HEIGHT_TOP * baseSize;
const u32 topSize2x = GSP_SCREEN_HEIGHT_TOP_2X * baseSize;
const u32 bottomSize = GSP_SCREEN_HEIGHT_BOTTOM * baseSize;
GSPGPU_FlushDataCache(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), topSize);
if(gfxEnable3D)GSPGPU_FlushDataCache(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), topSize);
GSPGPU_FlushDataCache(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), gfxTopMode == MODE_WIDE ? topSize2x : topSize);
if (gfxTopMode == MODE_3D)
GSPGPU_FlushDataCache(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), topSize);
GSPGPU_FlushDataCache(gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), bottomSize);
}