diff --git a/include/mgba/internal/ds/video.h b/include/mgba/internal/ds/video.h index 395114fc1..be0d6c0f5 100644 --- a/include/mgba/internal/ds/video.h +++ b/include/mgba/internal/ds/video.h @@ -66,6 +66,10 @@ DECL_BIT(DSRegisterPOWCNT1, Swap, 15); DECL_BIT(GBARegisterBGCNT, ExtPaletteSlot, 13); +DECL_BITFIELD(DSRegisterMASTER_BRIGHT, uint16_t); +DECL_BITS(DSRegisterMASTER_BRIGHT, Y, 0, 5); +DECL_BITS(DSRegisterMASTER_BRIGHT, Mode, 14, 2); + struct DSVideoRenderer { void (*init)(struct DSVideoRenderer* renderer); void (*reset)(struct DSVideoRenderer* renderer); diff --git a/include/mgba/internal/gba/renderers/video-software.h b/include/mgba/internal/gba/renderers/video-software.h index 93729374e..813da5e7a 100644 --- a/include/mgba/internal/gba/renderers/video-software.h +++ b/include/mgba/internal/gba/renderers/video-software.h @@ -167,6 +167,9 @@ struct GBAVideoSoftwareRenderer { int masterEnd; int masterHeight; int masterScanlines; + + int masterBright; + int masterBrightY; }; void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer); diff --git a/src/ds/io.c b/src/ds/io.c index a5939cefc..cf5355a90 100644 --- a/src/ds/io.c +++ b/src/ds/io.c @@ -422,9 +422,9 @@ void DS9IOInit(struct DS* ds) { } void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { - if (address <= DS9_REG_A_BLDY && (address > DS_REG_VCOUNT || address == DS9_REG_A_DISPCNT_LO || address == DS9_REG_A_DISPCNT_HI)) { + if ((address <= DS9_REG_A_BLDY && address > DS_REG_VCOUNT) || address == DS9_REG_A_DISPCNT_LO || address == DS9_REG_A_DISPCNT_HI || address == DS9_REG_A_MASTER_BRIGHT) { value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); - } else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) { + } else if ((address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) || address == DS9_REG_B_MASTER_BRIGHT) { value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); } else if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_12) || address == DS9_REG_DISP3DCNT) { value = DSGXWriteRegister(&ds->gx, address, value); diff --git a/src/ds/renderers/software.c b/src/ds/renderers/software.c index e3b6c9d9d..cbfa776c0 100644 --- a/src/ds/renderers/software.c +++ b/src/ds/renderers/software.c @@ -270,6 +270,20 @@ static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer case DS9_REG_B_BG3CNT: _updateCharBase(softwareRenderer, true); break; + case DS9_REG_A_MASTER_BRIGHT: + softwareRenderer->engA.masterBright = DSRegisterMASTER_BRIGHTGetMode(value); + softwareRenderer->engA.masterBrightY = DSRegisterMASTER_BRIGHTGetY(value); + if (softwareRenderer->engA.masterBrightY > 0x10) { + softwareRenderer->engA.masterBrightY = 0x10; + } + break; + case DS9_REG_B_MASTER_BRIGHT: + softwareRenderer->engB.masterBright = DSRegisterMASTER_BRIGHTGetMode(value); + softwareRenderer->engB.masterBrightY = DSRegisterMASTER_BRIGHTGetY(value); + if (softwareRenderer->engB.masterBrightY > 0x10) { + softwareRenderer->engB.masterBrightY = 0x10; + } + break; case DS9_REG_A_DISPCNT_LO: softwareRenderer->dispcntA &= 0xFFFF0000; softwareRenderer->dispcntA |= value; @@ -323,9 +337,9 @@ static void DSVideoSoftwareRendererInvalidateExtPal(struct DSVideoRenderer* rend static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* renderer, int y) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; + int x; color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) { - int x; for (x = 0; x < softwareRenderer->masterEnd; ++x) { row[x] = GBA_COLOR_WHITE; } @@ -406,7 +420,22 @@ static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* rend } #endif #else - memcpy(row, softwareRenderer->row, softwareRenderer->masterEnd * sizeof(*row)); + switch (softwareRenderer->masterBright) { + case 0: + default: + memcpy(row, softwareRenderer->row, softwareRenderer->masterEnd * sizeof(*row)); + break; + case 1: + for (x = 0; x < softwareRenderer->masterEnd; ++x) { + row[x] = _brighten(softwareRenderer->row[x], softwareRenderer->masterBrightY); + } + break; + case 2: + for (x = 0; x < softwareRenderer->masterEnd; ++x) { + row[x] = _darken(softwareRenderer->row[x], softwareRenderer->masterBrightY); + } + break; + } #endif } diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 91ab27035..6d6315684 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -95,6 +95,8 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) { softwareRenderer->target2Obj = 0; softwareRenderer->target2Bd = 0; softwareRenderer->blendEffect = BLEND_NONE; + softwareRenderer->masterBright = 0; + softwareRenderer->masterBrightY = 0; for (i = 0; i < 1024; i += 2) { uint16_t entry; LOAD_16(entry, i, softwareRenderer->d.palette);