mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Implement green swap (fixes #1609)
This commit is contained in:
parent
6a97b1dbf5
commit
c825c57281
1
CHANGES
1
CHANGES
|
@ -42,6 +42,7 @@ Emulation fixes:
|
||||||
- GBA Video: Fix Hblank timing
|
- GBA Video: Fix Hblank timing
|
||||||
- GBA Video: Invalidate map cache when modifying BGCNT (fixes mgba.io/i/1846)
|
- 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: 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
|
- SM83: Emulate HALT bug
|
||||||
Other fixes:
|
Other fixes:
|
||||||
- 3DS: Redo video sync to be more precise
|
- 3DS: Redo video sync to be more precise
|
||||||
|
|
|
@ -36,6 +36,23 @@ typedef uint32_t color_t;
|
||||||
#define M_RGB8_TO_BGR5(X) ((((X) & 0xF8) >> 3) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 9))
|
#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))
|
#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
|
#ifndef PYCPARSE
|
||||||
static inline color_t mColorFrom555(uint16_t value) {
|
static inline color_t mColorFrom555(uint16_t value) {
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
|
|
|
@ -114,6 +114,7 @@ struct GBAVideoSoftwareRenderer {
|
||||||
uint16_t bldy;
|
uint16_t bldy;
|
||||||
|
|
||||||
GBAMosaicControl mosaic;
|
GBAMosaicControl mosaic;
|
||||||
|
bool greenswap;
|
||||||
|
|
||||||
struct WindowN {
|
struct WindowN {
|
||||||
struct GBAVideoWindowRegion h;
|
struct GBAVideoWindowRegion h;
|
||||||
|
|
|
@ -341,7 +341,7 @@ void GBAIOInit(struct GBA* gba) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
|
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);
|
value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
|
||||||
} else {
|
} else {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
|
|
|
@ -122,6 +122,7 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
||||||
softwareRenderer->oamMax = 0;
|
softwareRenderer->oamMax = 0;
|
||||||
|
|
||||||
softwareRenderer->mosaic = 0;
|
softwareRenderer->mosaic = 0;
|
||||||
|
softwareRenderer->greenswap = false;
|
||||||
softwareRenderer->nextY = 0;
|
softwareRenderer->nextY = 0;
|
||||||
|
|
||||||
softwareRenderer->objOffsetX = 0;
|
softwareRenderer->objOffsetX = 0;
|
||||||
|
@ -179,6 +180,9 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||||
softwareRenderer->dispcnt = value;
|
softwareRenderer->dispcnt = value;
|
||||||
GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer);
|
GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer);
|
||||||
break;
|
break;
|
||||||
|
case REG_GREENSWP:
|
||||||
|
softwareRenderer->greenswap = value & 1;
|
||||||
|
break;
|
||||||
case REG_BG0CNT:
|
case REG_BG0CNT:
|
||||||
value &= 0xDFFF;
|
value &= 0xDFFF;
|
||||||
GBAVideoSoftwareRendererWriteBGCNT(softwareRenderer, &softwareRenderer->bg[0], value);
|
GBAVideoSoftwareRendererWriteBGCNT(softwareRenderer, &softwareRenderer->bg[0], value);
|
||||||
|
@ -389,9 +393,6 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
||||||
case REG_MOSAIC:
|
case REG_MOSAIC:
|
||||||
softwareRenderer->mosaic = value;
|
softwareRenderer->mosaic = value;
|
||||||
break;
|
break;
|
||||||
case REG_GREENSWP:
|
|
||||||
mLOG(GBA_VIDEO, STUB, "Stub video register write: 0x%03X", address);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
mLOG(GBA_VIDEO, GAME_ERROR, "Invalid video register: 0x%03X", address);
|
mLOG(GBA_VIDEO, GAME_ERROR, "Invalid video register: 0x%03X", address);
|
||||||
}
|
}
|
||||||
|
@ -675,16 +676,30 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#ifdef COLOR_16_BIT
|
||||||
for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) {
|
for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) {
|
||||||
row[x] = softwareRenderer->row[x];
|
row[x] = softwareRenderer->row[x];
|
||||||
row[x + 1] = softwareRenderer->row[x + 1];
|
row[x + 1] = softwareRenderer->row[x + 1];
|
||||||
row[x + 2] = softwareRenderer->row[x + 2];
|
row[x + 2] = softwareRenderer->row[x + 2];
|
||||||
row[x + 3] = softwareRenderer->row[x + 3];
|
row[x + 3] = softwareRenderer->row[x + 3];
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
memcpy(row, softwareRenderer->row, GBA_VIDEO_HORIZONTAL_PIXELS * sizeof(*row));
|
memcpy(row, softwareRenderer->row, GBA_VIDEO_HORIZONTAL_PIXELS * sizeof(*row));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) {
|
static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) {
|
||||||
|
|
Loading…
Reference in New Issue