GBA Video: Implement green swap (fixes #1609)
Vicki Pfau vi@endrift.com
Mon, 31 Aug 2020 22:28:19 -0700
5 files changed,
45 insertions(+),
11 deletions(-)
M
CHANGES
→
CHANGES
@@ -42,6 +42,7 @@ - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319)
- GBA Video: Fix Hblank timing - GBA Video: Invalidate map cache when modifying BGCNT (fixes mgba.io/i/1846) - GBA Video: Don't draw sprites using unmapped VRAM in GL renderer (fixes mgba.io/i/1865) + - GBA Video: Implement green swap (fixes mgba.io/i/1609) - SM83: Emulate HALT bug Other fixes: - 3DS: Redo video sync to be more precise
M
include/mgba/core/interface.h
→
include/mgba/core/interface.h
@@ -36,6 +36,23 @@ #define M_RGB5_TO_RGB8(X) ((M_R5(X) << 19) | (M_G5(X) << 11) | (M_B5(X) << 3))
#define M_RGB8_TO_BGR5(X) ((((X) & 0xF8) >> 3) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 9)) #define M_RGB8_TO_RGB5(X) ((((X) & 0xF8) << 7) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 19)) +#ifndef COLOR_16_BIT +#define M_COLOR_RED 0x000000FF +#define M_COLOR_GREEN 0x0000FF00 +#define M_COLOR_BLUE 0x00FF0000 +#define M_COLOR_ALPHA 0xFF000000 +#elif defined(COLOR_5_6_5) +#define M_COLOR_RED 0x001F +#define M_COLOR_GREEN 0x07E0 +#define M_COLOR_BLUE 0xF800 +#define M_COLOR_ALPHA 0x0000 +#else +#define M_COLOR_RED 0x001F +#define M_COLOR_GREEN 0x03E0 +#define M_COLOR_BLUE 0x7C00 +#define M_COLOR_ALPHA 0x1000 +#endif + #ifndef PYCPARSE static inline color_t mColorFrom555(uint16_t value) { #ifdef COLOR_16_BIT
M
include/mgba/internal/gba/renderers/video-software.h
→
include/mgba/internal/gba/renderers/video-software.h
@@ -114,6 +114,7 @@ uint16_t bldb;
uint16_t bldy; GBAMosaicControl mosaic; + bool greenswap; struct WindowN { struct GBAVideoWindowRegion h;
M
src/gba/io.c
→
src/gba/io.c
@@ -341,7 +341,7 @@ }
} void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { - if (address < REG_SOUND1CNT_LO && (address > REG_VCOUNT || address == REG_DISPCNT)) { + if (address < REG_SOUND1CNT_LO && (address > REG_VCOUNT || address < REG_DISPSTAT)) { value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value); } else { switch (address) {
M
src/gba/renderers/video-software.c
→
src/gba/renderers/video-software.c
@@ -122,6 +122,7 @@ softwareRenderer->oamDirty = 1;
softwareRenderer->oamMax = 0; softwareRenderer->mosaic = 0; + softwareRenderer->greenswap = false; softwareRenderer->nextY = 0; softwareRenderer->objOffsetX = 0;@@ -178,6 +179,9 @@ case REG_DISPCNT:
value &= 0xFFF7; softwareRenderer->dispcnt = value; GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer); + break; + case REG_GREENSWP: + softwareRenderer->greenswap = value & 1; break; case REG_BG0CNT: value &= 0xDFFF;@@ -388,9 +392,6 @@ softwareRenderer->objwin.packed = value >> 8;
break; case REG_MOSAIC: softwareRenderer->mosaic = value; - break; - case REG_GREENSWP: - mLOG(GBA_VIDEO, STUB, "Stub video register write: 0x%03X", address); break; default: mLOG(GBA_VIDEO, GAME_ERROR, "Invalid video register: 0x%03X", address);@@ -675,16 +676,30 @@ }
} } + if (softwareRenderer->greenswap) { + for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) { + row[x] = softwareRenderer->row[x] & (M_COLOR_RED | M_COLOR_BLUE); + row[x] |= softwareRenderer->row[x + 1] & M_COLOR_GREEN; + row[x + 1] = softwareRenderer->row[x + 1] & (M_COLOR_RED | M_COLOR_BLUE); + row[x + 1] |= softwareRenderer->row[x] & M_COLOR_GREEN; + row[x + 2] = softwareRenderer->row[x + 2] & (M_COLOR_RED | M_COLOR_BLUE); + row[x + 2] |= softwareRenderer->row[x + 3] & M_COLOR_GREEN; + row[x + 3] = softwareRenderer->row[x + 3] & (M_COLOR_RED | M_COLOR_BLUE); + row[x + 3] |= softwareRenderer->row[x + 2] & M_COLOR_GREEN; + + } + } else { #ifdef COLOR_16_BIT - for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) { - row[x] = softwareRenderer->row[x]; - row[x + 1] = softwareRenderer->row[x + 1]; - row[x + 2] = softwareRenderer->row[x + 2]; - row[x + 3] = softwareRenderer->row[x + 3]; - } + for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) { + row[x] = softwareRenderer->row[x]; + row[x + 1] = softwareRenderer->row[x + 1]; + row[x + 2] = softwareRenderer->row[x + 2]; + row[x + 3] = softwareRenderer->row[x + 3]; + } #else - memcpy(row, softwareRenderer->row, GBA_VIDEO_HORIZONTAL_PIXELS * sizeof(*row)); + memcpy(row, softwareRenderer->row, GBA_VIDEO_HORIZONTAL_PIXELS * sizeof(*row)); #endif + } } static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) {