all repos — mgba @ 456dbc482f9ee76e8b632e296ff4162ac38f18a1

mGBA Game Boy Advance Emulator

3DS: Interframe blending
Vicki Pfau vi@endrift.com
Wed, 29 May 2019 15:13:30 -0700
commit

456dbc482f9ee76e8b632e296ff4162ac38f18a1

parent

252b9409b66ba0e5fe8d86d530d0b19587c16586

1 files changed, 43 insertions(+), 22 deletions(-)

jump to
M src/platform/3ds/main.csrc/platform/3ds/main.c

@@ -89,7 +89,8 @@ static color_t* screenshotBuffer = NULL;

static struct mAVStream stream; static int16_t* audioLeft = 0; static size_t audioPos = 0; -static C3D_Tex outputTexture; +static C3D_Tex outputTexture[2]; +static int activeOutputTexture = 0; static ndspWaveBuf dspBuffer[DSP_BUFFERS]; static int bufferId = 0; static bool frameLimiter = true;

@@ -102,6 +103,7 @@ static bool frameStarted = false;

static C3D_RenderTarget* upscaleBuffer; static C3D_Tex upscaleBufferTex; +static bool interframeBlending = false; static aptHookCookie cookie; static bool core2;

@@ -150,7 +152,8 @@ C3D_RenderTargetDelete(bottomScreen[0]);

C3D_RenderTargetDelete(bottomScreen[1]); C3D_RenderTargetDelete(upscaleBuffer); C3D_TexDelete(&upscaleBufferTex); - C3D_TexDelete(&outputTexture); + C3D_TexDelete(&outputTexture[0]); + C3D_TexDelete(&outputTexture[1]); C3D_Fini(); gfxExit();

@@ -374,6 +377,11 @@ CAMU_Activate(camera.cam);

} } } + + int fakeBool; + if (mCoreConfigGetIntValue(&runner->config, "interframeBlending", &fakeBool)) { + interframeBlending = fakeBool; + } } static void _gameUnloaded(struct mGUIRunner* runner) {

@@ -404,7 +412,7 @@ break;

} } -static void _drawTex(struct mCore* core, bool faded) { +static void _drawTex(struct mCore* core, bool faded, bool both) { unsigned screen_w, screen_h; switch (screenMode) { case SM_PA_BOTTOM:

@@ -466,7 +474,6 @@ ctrSetViewportSize(screen_w, screen_h, false);

break; } - ctrActivateTexture(&outputTexture); u32 color; if (!faded) { color = 0xFFFFFFFF;

@@ -502,7 +509,12 @@ break;

} } + ctrActivateTexture(&outputTexture[activeOutputTexture]); ctrAddRectEx(color, x, y, w, h, 0, 0, corew, coreh, 0); + if (both) { + ctrActivateTexture(&outputTexture[activeOutputTexture ^ 1]); + ctrAddRectEx(color & 0x7FFFFFFF, x, y, w, h, 0, 0, corew, coreh, 0); + } ctrFlushBatch(); corew = w;

@@ -544,11 +556,16 @@ y = (screen_h - h) / 2;

ctrActivateTexture(&upscaleBufferTex); ctrAddRectEx(0xFFFFFFFF, x, y, w, h, 0, 0, corew, coreh, 0); ctrFlushBatch(); +} + +static void _prepareForFrame(struct mGUIRunner* runner) { + UNUSED(runner); + activeOutputTexture ^= 1; } static void _drawFrame(struct mGUIRunner* runner, bool faded) { UNUSED(runner); - C3D_Tex* tex = &outputTexture; + C3D_Tex* tex = &outputTexture[activeOutputTexture]; GSPGPU_FlushDataCache(outputBuffer, 256 * GBA_VIDEO_VERTICAL_PIXELS * 2); C3D_SyncDisplayTransfer(

@@ -563,11 +580,11 @@ blip_clear(runner->core->getAudioChannel(runner->core, 0));

blip_clear(runner->core->getAudioChannel(runner->core, 1)); } - _drawTex(runner->core, faded); + _drawTex(runner->core, faded, interframeBlending); } static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { - C3D_Tex* tex = &outputTexture; + C3D_Tex* tex = &outputTexture[activeOutputTexture]; if (!screenshotBuffer) { screenshotBuffer = linearMemAlign(256 * 224 * sizeof(color_t), 0x80);

@@ -586,7 +603,7 @@ GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |

GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB565) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_FLIP_VERT(1)); - _drawTex(runner->core, faded); + _drawTex(runner->core, faded, false); } static uint16_t _pollGameInput(struct mGUIRunner* runner) {

@@ -804,25 +821,29 @@

gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, true); if (!_initGpu()) { - outputTexture.data = 0; + outputTexture[0].data = 0; _cleanup(); return 1; } - if (!C3D_TexInitVRAM(&outputTexture, 256, 256, GPU_RGB565)) { - _cleanup(); - return 1; - } - C3D_TexSetWrap(&outputTexture, GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); - C3D_TexSetFilter(&outputTexture, GPU_NEAREST, GPU_NEAREST); C3D_TexSetFilter(&upscaleBufferTex, GPU_LINEAR, GPU_LINEAR); - void* outputTextureEnd = (u8*)outputTexture.data + 256 * 256 * 2; - // Zero texture data to make sure no garbage around the border interferes with filtering - GX_MemoryFill( - outputTexture.data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER, - NULL, 0, NULL, 0); - gspWaitForPSC0(); + int i; + for (i = 0; i < 2; ++i) { + if (!C3D_TexInitVRAM(&outputTexture[i], 256, 256, GPU_RGB565)) { + _cleanup(); + return 1; + } + C3D_TexSetWrap(&outputTexture[i], GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); + C3D_TexSetFilter(&outputTexture[i], GPU_NEAREST, GPU_NEAREST); + void* outputTextureEnd = (u8*)outputTexture[i].data + 256 * 256 * 2; + + // Zero texture data to make sure no garbage around the border interferes with filtering + GX_MemoryFill( + outputTexture[i].data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER, + NULL, 0, NULL, 0); + gspWaitForPSC0(); + } struct GUIFont* font = GUIFontCreate();

@@ -937,7 +958,7 @@ .setup = _setup,

.teardown = 0, .gameLoaded = _gameLoaded, .gameUnloaded = _gameUnloaded, - .prepareForFrame = 0, + .prepareForFrame = _prepareForFrame, .drawFrame = _drawFrame, .drawScreenshot = _drawScreenshot, .paused = _gameUnloaded,