in cores/gba/src/gb/io.c [196:502]
void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
switch (address) {
case REG_SB:
GBSIOWriteSB(&gb->sio, value);
break;
case REG_SC:
GBSIOWriteSC(&gb->sio, value);
break;
case REG_DIV:
GBTimerDivReset(&gb->timer);
return;
case REG_NR10:
if (gb->audio.enable) {
GBAudioWriteNR10(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR11:
if (gb->audio.enable) {
GBAudioWriteNR11(&gb->audio, value);
} else {
if (gb->audio.style == GB_AUDIO_DMG) {
GBAudioWriteNR11(&gb->audio, value & _registerMask[REG_NR11]);
}
value = 0;
}
break;
case REG_NR12:
if (gb->audio.enable) {
GBAudioWriteNR12(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR13:
if (gb->audio.enable) {
GBAudioWriteNR13(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR14:
if (gb->audio.enable) {
GBAudioWriteNR14(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR21:
if (gb->audio.enable) {
GBAudioWriteNR21(&gb->audio, value);
} else {
if (gb->audio.style == GB_AUDIO_DMG) {
GBAudioWriteNR21(&gb->audio, value & _registerMask[REG_NR21]);
}
value = 0;
}
break;
case REG_NR22:
if (gb->audio.enable) {
GBAudioWriteNR22(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR23:
if (gb->audio.enable) {
GBAudioWriteNR23(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR24:
if (gb->audio.enable) {
GBAudioWriteNR24(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR30:
if (gb->audio.enable) {
GBAudioWriteNR30(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR31:
if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
GBAudioWriteNR31(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR32:
if (gb->audio.enable) {
GBAudioWriteNR32(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR33:
if (gb->audio.enable) {
GBAudioWriteNR33(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR34:
if (gb->audio.enable) {
GBAudioWriteNR34(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR41:
if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
GBAudioWriteNR41(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR42:
if (gb->audio.enable) {
GBAudioWriteNR42(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR43:
if (gb->audio.enable) {
GBAudioWriteNR43(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR44:
if (gb->audio.enable) {
GBAudioWriteNR44(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR50:
if (gb->audio.enable) {
GBAudioWriteNR50(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR51:
if (gb->audio.enable) {
GBAudioWriteNR51(&gb->audio, value);
} else {
value = 0;
}
break;
case REG_NR52:
GBAudioWriteNR52(&gb->audio, value);
value &= 0x80;
value |= gb->memory.io[REG_NR52] & 0x0F;
break;
case REG_WAVE_0:
case REG_WAVE_1:
case REG_WAVE_2:
case REG_WAVE_3:
case REG_WAVE_4:
case REG_WAVE_5:
case REG_WAVE_6:
case REG_WAVE_7:
case REG_WAVE_8:
case REG_WAVE_9:
case REG_WAVE_A:
case REG_WAVE_B:
case REG_WAVE_C:
case REG_WAVE_D:
case REG_WAVE_E:
case REG_WAVE_F:
if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) {
gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
} else if(gb->audio.ch3.readable) {
gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
}
break;
case REG_JOYP:
if (gb->model == GB_MODEL_SGB) {
_writeSGBBits(gb, (value >> 4) & 3);
}
break;
case REG_TIMA:
if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 1) {
mTimingDeschedule(&gb->timing, &gb->timer.irq);
}
if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
return;
}
break;
case REG_TMA:
if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
gb->memory.io[REG_TIMA] = value;
}
break;
case REG_TAC:
value = GBTimerUpdateTAC(&gb->timer, value);
break;
case REG_IF:
gb->memory.io[REG_IF] = value | 0xE0;
GBUpdateIRQs(gb);
return;
case REG_LCDC:
// TODO: handle GBC differences
GBVideoProcessDots(&gb->video, 0);
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
GBVideoWriteLCDC(&gb->video, value);
break;
case REG_LYC:
GBVideoWriteLYC(&gb->video, value);
break;
case REG_DMA:
GBMemoryDMA(gb, value << 8);
break;
case REG_SCY:
case REG_SCX:
case REG_WY:
case REG_WX:
GBVideoProcessDots(&gb->video, 0);
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
break;
case REG_BGP:
case REG_OBP0:
case REG_OBP1:
GBVideoProcessDots(&gb->video, 0);
GBVideoWritePalette(&gb->video, address, value);
break;
case REG_STAT:
GBVideoWriteSTAT(&gb->video, value);
value = gb->video.stat;
break;
case 0x50:
GBUnmapBIOS(gb);
if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) {
gb->model = GB_MODEL_DMG;
GBVideoDisableCGB(&gb->video);
}
break;
case REG_IE:
gb->memory.ie = value;
GBUpdateIRQs(gb);
return;
default:
if (gb->model >= GB_MODEL_CGB) {
switch (address) {
case REG_UNK4C:
break;
case REG_KEY1:
value &= 0x1;
value |= gb->memory.io[address] & 0x80;
break;
case REG_VBK:
GBVideoSwitchBank(&gb->video, value);
break;
case REG_HDMA1:
case REG_HDMA2:
case REG_HDMA3:
case REG_HDMA4:
// Handled transparently by the registers
break;
case REG_HDMA5:
value = GBMemoryWriteHDMA5(gb, value);
break;
case REG_BCPS:
gb->video.bcpIndex = value & 0x3F;
gb->video.bcpIncrement = value & 0x80;
gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1));
break;
case REG_BCPD:
GBVideoProcessDots(&gb->video, 0);
GBVideoWritePalette(&gb->video, address, value);
return;
case REG_OCPS:
gb->video.ocpIndex = value & 0x3F;
gb->video.ocpIncrement = value & 0x80;
gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1));
break;
case REG_OCPD:
GBVideoProcessDots(&gb->video, 0);
GBVideoWritePalette(&gb->video, address, value);
return;
case REG_SVBK:
GBMemorySwitchWramBank(&gb->memory, value);
value = gb->memory.wramCurrentBank;
break;
default:
goto failed;
}
goto success;
}
failed:
mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
if (address >= GB_SIZE_IO) {
return;
}
break;
}
success:
gb->memory.io[address] = value;
}