From 2636d3a7678e9aa458ff07c4d0a2cff2086ca52e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 22 Feb 2017 10:57:48 -0800 Subject: [PATCH] DS Video: Display swapping --- include/mgba/internal/ds/renderers/software.h | 1 + include/mgba/internal/ds/video.h | 4 ++++ src/ds/io.c | 5 +++++ src/ds/renderers/software.c | 17 ++++++++++++----- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/mgba/internal/ds/renderers/software.h b/include/mgba/internal/ds/renderers/software.h index 89aad89ea..f15e0d934 100644 --- a/include/mgba/internal/ds/renderers/software.h +++ b/include/mgba/internal/ds/renderers/software.h @@ -21,6 +21,7 @@ struct DSVideoSoftwareRenderer { DSRegisterDISPCNT dispcntA; DSRegisterDISPCNT dispcntB; + DSRegisterPOWCNT1 powcnt; color_t* outputBuffer; int outputBufferStride; diff --git a/include/mgba/internal/ds/video.h b/include/mgba/internal/ds/video.h index 2665453f9..34db43286 100644 --- a/include/mgba/internal/ds/video.h +++ b/include/mgba/internal/ds/video.h @@ -58,6 +58,10 @@ DECL_BITS(DSRegisterDISPCNT, CharBase, 24, 3); DECL_BITS(DSRegisterDISPCNT, ScreenBase, 27, 3); // TODO +DECL_BITFIELD(DSRegisterPOWCNT1, uint16_t); +// TODO +DECL_BIT(DSRegisterPOWCNT1, Swap, 15); + struct DSVideoRenderer { void (*init)(struct DSVideoRenderer* renderer); void (*reset)(struct DSVideoRenderer* renderer); diff --git a/src/ds/io.c b/src/ds/io.c index 3c3c1725f..91022290b 100644 --- a/src/ds/io.c +++ b/src/ds/io.c @@ -440,6 +440,11 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { ds->memory.io9[DS9_REG_SQRTCNT >> 1] = _scheduleSqrt(ds, ds->memory.io9[DS9_REG_SQRTCNT >> 1]); break; + // High Video + case DS9_REG_POWCNT1: + value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); + break; + default: { uint32_t v2 = DSIOWrite(&ds->ds9, address, value); diff --git a/src/ds/renderers/software.c b/src/ds/renderers/software.c index bc5b8a842..bc1869bdb 100644 --- a/src/ds/renderers/software.c +++ b/src/ds/renderers/software.c @@ -42,9 +42,11 @@ static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer) { softwareRenderer->engA.d.palette = &renderer->palette[0]; softwareRenderer->engA.d.oam = &renderer->oam->oam[0]; softwareRenderer->engA.masterEnd = DS_VIDEO_HORIZONTAL_PIXELS; + softwareRenderer->engA.outputBufferStride = softwareRenderer->outputBufferStride; softwareRenderer->engB.d.palette = &renderer->palette[512]; softwareRenderer->engB.d.oam = &renderer->oam->oam[1]; softwareRenderer->engB.masterEnd = DS_VIDEO_HORIZONTAL_PIXELS; + softwareRenderer->engB.outputBufferStride = softwareRenderer->outputBufferStride; DSVideoSoftwareRendererReset(renderer); } @@ -113,6 +115,9 @@ static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer softwareRenderer->dispcntB |= value << 16; GBAVideoSoftwareRendererUpdateDISPCNTB(softwareRenderer); break; + case DS9_REG_POWCNT1: + value &= 0x810F; + softwareRenderer->powcnt = value; } return value; } @@ -222,11 +227,13 @@ static void _drawScanlineB(struct DSVideoSoftwareRenderer* softwareRenderer, int static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y) { struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer; - softwareRenderer->engA.outputBuffer = softwareRenderer->outputBuffer; - softwareRenderer->engB.outputBuffer = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * DS_VIDEO_VERTICAL_PIXELS]; - softwareRenderer->engA.outputBufferStride = softwareRenderer->outputBufferStride; - softwareRenderer->engB.outputBufferStride = softwareRenderer->outputBufferStride; - + if (!DSRegisterPOWCNT1IsSwap(softwareRenderer->powcnt)) { + softwareRenderer->engA.outputBuffer = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * DS_VIDEO_VERTICAL_PIXELS]; + softwareRenderer->engB.outputBuffer = softwareRenderer->outputBuffer; + } else { + softwareRenderer->engA.outputBuffer = softwareRenderer->outputBuffer; + softwareRenderer->engB.outputBuffer = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * DS_VIDEO_VERTICAL_PIXELS]; + } _drawScanlineA(softwareRenderer, y); _drawScanlineB(softwareRenderer, y);