in cores/gba/src/gba/renderers/video-software.c [152:386]
static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
if (renderer->cache) {
GBAVideoCacheWriteVideoRegister(renderer->cache, address, value);
}
switch (address) {
case REG_DISPCNT:
value &= 0xFFF7;
softwareRenderer->dispcnt = value;
GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer);
break;
case REG_BG0CNT:
value &= 0xDFFF;
GBAVideoSoftwareRendererWriteBGCNT(softwareRenderer, &softwareRenderer->bg[0], value);
break;
case REG_BG1CNT:
value &= 0xDFFF;
GBAVideoSoftwareRendererWriteBGCNT(softwareRenderer, &softwareRenderer->bg[1], value);
break;
case REG_BG2CNT:
value &= 0xFFFF;
GBAVideoSoftwareRendererWriteBGCNT(softwareRenderer, &softwareRenderer->bg[2], value);
break;
case REG_BG3CNT:
value &= 0xFFFF;
GBAVideoSoftwareRendererWriteBGCNT(softwareRenderer, &softwareRenderer->bg[3], value);
break;
case REG_BG0HOFS:
value &= 0x01FF;
softwareRenderer->bg[0].x = value;
break;
case REG_BG0VOFS:
value &= 0x01FF;
softwareRenderer->bg[0].y = value;
break;
case REG_BG1HOFS:
value &= 0x01FF;
softwareRenderer->bg[1].x = value;
break;
case REG_BG1VOFS:
value &= 0x01FF;
softwareRenderer->bg[1].y = value;
break;
case REG_BG2HOFS:
value &= 0x01FF;
softwareRenderer->bg[2].x = value;
break;
case REG_BG2VOFS:
value &= 0x01FF;
softwareRenderer->bg[2].y = value;
break;
case REG_BG3HOFS:
value &= 0x01FF;
softwareRenderer->bg[3].x = value;
break;
case REG_BG3VOFS:
value &= 0x01FF;
softwareRenderer->bg[3].y = value;
break;
case REG_BG2PA:
softwareRenderer->bg[2].dx = value;
break;
case REG_BG2PB:
softwareRenderer->bg[2].dmx = value;
break;
case REG_BG2PC:
softwareRenderer->bg[2].dy = value;
break;
case REG_BG2PD:
softwareRenderer->bg[2].dmy = value;
break;
case REG_BG2X_LO:
GBAVideoSoftwareRendererWriteBGX_LO(&softwareRenderer->bg[2], value);
if (softwareRenderer->bg[2].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[0][0]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG2X_HI:
GBAVideoSoftwareRendererWriteBGX_HI(&softwareRenderer->bg[2], value);
if (softwareRenderer->bg[2].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[0][0]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG2Y_LO:
GBAVideoSoftwareRendererWriteBGY_LO(&softwareRenderer->bg[2], value);
if (softwareRenderer->bg[2].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[0][1]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG2Y_HI:
GBAVideoSoftwareRendererWriteBGY_HI(&softwareRenderer->bg[2], value);
if (softwareRenderer->bg[2].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[0][1]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG3PA:
softwareRenderer->bg[3].dx = value;
break;
case REG_BG3PB:
softwareRenderer->bg[3].dmx = value;
break;
case REG_BG3PC:
softwareRenderer->bg[3].dy = value;
break;
case REG_BG3PD:
softwareRenderer->bg[3].dmy = value;
break;
case REG_BG3X_LO:
GBAVideoSoftwareRendererWriteBGX_LO(&softwareRenderer->bg[3], value);
if (softwareRenderer->bg[3].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[1][0]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG3X_HI:
GBAVideoSoftwareRendererWriteBGX_HI(&softwareRenderer->bg[3], value);
if (softwareRenderer->bg[3].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[1][0]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG3Y_LO:
GBAVideoSoftwareRendererWriteBGY_LO(&softwareRenderer->bg[3], value);
if (softwareRenderer->bg[3].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[1][1]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BG3Y_HI:
GBAVideoSoftwareRendererWriteBGY_HI(&softwareRenderer->bg[3], value);
if (softwareRenderer->bg[3].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[1][1]) {
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
break;
case REG_BLDCNT:
GBAVideoSoftwareRendererWriteBLDCNT(softwareRenderer, value);
value &= 0x3FFF;
break;
case REG_BLDALPHA:
softwareRenderer->blda = value & 0x1F;
if (softwareRenderer->blda > 0x10) {
softwareRenderer->blda = 0x10;
}
softwareRenderer->bldb = (value >> 8) & 0x1F;
if (softwareRenderer->bldb > 0x10) {
softwareRenderer->bldb = 0x10;
}
value &= 0x1F1F;
break;
case REG_BLDY:
value &= 0x1F;
if (value > 0x10) {
value = 0x10;
}
if (softwareRenderer->bldy != value) {
softwareRenderer->bldy = value;
softwareRenderer->blendDirty = true;
}
break;
case REG_WIN0H:
softwareRenderer->winN[0].h.end = value;
softwareRenderer->winN[0].h.start = value >> 8;
if (softwareRenderer->winN[0].h.start > VIDEO_HORIZONTAL_PIXELS && softwareRenderer->winN[0].h.start > softwareRenderer->winN[0].h.end) {
softwareRenderer->winN[0].h.start = 0;
}
if (softwareRenderer->winN[0].h.end > VIDEO_HORIZONTAL_PIXELS) {
softwareRenderer->winN[0].h.end = VIDEO_HORIZONTAL_PIXELS;
if (softwareRenderer->winN[0].h.start > VIDEO_HORIZONTAL_PIXELS) {
softwareRenderer->winN[0].h.start = VIDEO_HORIZONTAL_PIXELS;
}
}
break;
case REG_WIN1H:
softwareRenderer->winN[1].h.end = value;
softwareRenderer->winN[1].h.start = value >> 8;
if (softwareRenderer->winN[1].h.start > VIDEO_HORIZONTAL_PIXELS && softwareRenderer->winN[1].h.start > softwareRenderer->winN[1].h.end) {
softwareRenderer->winN[1].h.start = 0;
}
if (softwareRenderer->winN[1].h.end > VIDEO_HORIZONTAL_PIXELS) {
softwareRenderer->winN[1].h.end = VIDEO_HORIZONTAL_PIXELS;
if (softwareRenderer->winN[1].h.start > VIDEO_HORIZONTAL_PIXELS) {
softwareRenderer->winN[1].h.start = VIDEO_HORIZONTAL_PIXELS;
}
}
break;
case REG_WIN0V:
softwareRenderer->winN[0].v.end = value;
softwareRenderer->winN[0].v.start = value >> 8;
if (softwareRenderer->winN[0].v.start > VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[0].v.start > softwareRenderer->winN[0].v.end) {
softwareRenderer->winN[0].v.start = 0;
}
if (softwareRenderer->winN[0].v.end > VIDEO_VERTICAL_PIXELS) {
softwareRenderer->winN[0].v.end = VIDEO_VERTICAL_PIXELS;
if (softwareRenderer->winN[0].v.start > VIDEO_VERTICAL_PIXELS) {
softwareRenderer->winN[0].v.start = VIDEO_VERTICAL_PIXELS;
}
}
break;
case REG_WIN1V:
softwareRenderer->winN[1].v.end = value;
softwareRenderer->winN[1].v.start = value >> 8;
if (softwareRenderer->winN[1].v.start > VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[1].v.start > softwareRenderer->winN[1].v.end) {
softwareRenderer->winN[1].v.start = 0;
}
if (softwareRenderer->winN[1].v.end > VIDEO_VERTICAL_PIXELS) {
softwareRenderer->winN[1].v.end = VIDEO_VERTICAL_PIXELS;
if (softwareRenderer->winN[1].v.start > VIDEO_VERTICAL_PIXELS) {
softwareRenderer->winN[1].v.start = VIDEO_VERTICAL_PIXELS;
}
}
break;
case REG_WININ:
value &= 0x3F3F;
softwareRenderer->winN[0].control.packed = value;
softwareRenderer->winN[1].control.packed = value >> 8;
break;
case REG_WINOUT:
value &= 0x3F3F;
softwareRenderer->winout.packed = value;
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);
}
softwareRenderer->nextIo[address >> 1] = value;
if (softwareRenderer->cache[softwareRenderer->nextY].io[address >> 1] != value) {
softwareRenderer->cache[softwareRenderer->nextY].io[address >> 1] = value;
DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
}
return value;
}