in cores/gb/libgambatte/src/gambatte-memory.cpp [659:1114]
void Memory::nontrivial_ff_write(unsigned const p, unsigned data, unsigned long const cc) {
if (lastOamDmaUpdate_ != disabled_time)
updateOamDma(cc);
switch (p & 0xFF) {
case 0x00:
if ((data ^ ioamhram_[0x100]) & 0x30) {
ioamhram_[0x100] = (ioamhram_[0x100] & ~0x30u) | (data & 0x30);
updateInput();
}
return;
case 0x01:
updateSerial(cc);
break;
case 0x02:
updateSerial(cc);
serialCnt_ = 8;
#ifdef HAVE_NETWORK
if ((data & 0x81) == 0x81)
{
unsigned char receivedByte = 0xFF;
if (serial_io_ != 0)
receivedByte = serial_io_->send(ioamhram_[0x101], (data & isCgb() * 2));
startSerialTransfer(cc, receivedByte, (data & isCgb() * 2));
}
#else
if ((data & 0x81) == 0x81)
{
intreq_.setEventTime<intevent_serial>((data & isCgb() * 2)
? (cc & ~0x07ul) + 0x010 * 8
: (cc & ~0xFFul) + 0x200 * 8);
}
else
intreq_.setEventTime<intevent_serial>(disabled_time);
#endif
data |= 0x7E - isCgb() * 2;
break;
case 0x04:
ioamhram_[0x104] = 0;
divLastUpdate_ = cc;
return;
case 0x05:
tima_.setTima(data, cc, TimaInterruptRequester(intreq_));
break;
case 0x06:
tima_.setTma(data, cc, TimaInterruptRequester(intreq_));
break;
case 0x07:
data |= 0xF8;
tima_.setTac(data, cc, TimaInterruptRequester(intreq_));
break;
case 0x0F:
updateIrqs(cc);
intreq_.setIfreg(0xE0 | data);
return;
case 0x10:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr10(data);
data |= 0x80;
break;
case 0x11:
if (!psg_.isEnabled()) {
if (isCgb())
return;
data &= 0x3F;
}
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr11(data);
data |= 0x3F;
break;
case 0x12:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr12(data);
break;
case 0x13:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr13(data);
return;
case 0x14:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr14(data);
data |= 0xBF;
break;
case 0x16:
if (!psg_.isEnabled()) {
if (isCgb())
return;
data &= 0x3F;
}
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr21(data);
data |= 0x3F;
break;
case 0x17:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr22(data);
break;
case 0x18:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr23(data);
return;
case 0x19:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr24(data);
data |= 0xBF;
break;
case 0x1A:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr30(data);
data |= 0x7F;
break;
case 0x1B:
if (!psg_.isEnabled() && isCgb())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr31(data);
return;
case 0x1C:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr32(data);
data |= 0x9F;
break;
case 0x1D:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr33(data);
return;
case 0x1E:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr34(data);
data |= 0xBF;
break;
case 0x20:
if (!psg_.isEnabled() && isCgb())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr41(data);
return;
case 0x21:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr42(data);
break;
case 0x22:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr43(data);
break;
case 0x23:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setNr44(data);
data |= 0xBF;
break;
case 0x24:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.setSoVolume(data);
break;
case 0x25:
if (!psg_.isEnabled())
return;
psg_.generateSamples(cc, isDoubleSpeed());
psg_.mapSo(data);
break;
case 0x26:
if ((ioamhram_[0x126] ^ data) & 0x80) {
psg_.generateSamples(cc, isDoubleSpeed());
if (!(data & 0x80)) {
for (unsigned i = 0x10; i < 0x26; ++i)
ff_write(i, 0, cc);
psg_.setEnabled(false);
} else {
psg_.reset();
psg_.setEnabled(true);
}
}
data = (data & 0x80) | (ioamhram_[0x126] & 0x7F);
break;
case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F:
psg_.generateSamples(cc, isDoubleSpeed());
psg_.waveRamWrite(p & 0xF, data);
break;
case 0x40:
if (ioamhram_[0x140] != data) {
if ((ioamhram_[0x140] ^ data) & lcdc_en) {
unsigned const lyc = lcd_.getStat(ioamhram_[0x145], cc)
& lcdstat_lycflag;
bool const hdmaEnabled = lcd_.hdmaIsEnabled();
lcd_.lcdcChange(data, cc);
ioamhram_[0x144] = 0;
ioamhram_[0x141] &= 0xF8;
if (data & lcdc_en) {
intreq_.setEventTime<intevent_blit>(blanklcd_
? lcd_.nextMode1IrqTime()
: lcd_.nextMode1IrqTime()
+ (70224 << isDoubleSpeed()));
} else {
ioamhram_[0x141] |= lyc;
intreq_.setEventTime<intevent_blit>(
cc + (456 * 4 << isDoubleSpeed()));
if (hdmaEnabled)
flagHdmaReq(intreq_);
}
} else
lcd_.lcdcChange(data, cc);
ioamhram_[0x140] = data;
}
return;
case 0x41:
lcd_.lcdstatChange(data, cc);
data = (ioamhram_[0x141] & 0x87) | (data & 0x78);
break;
case 0x42:
lcd_.scyChange(data, cc);
break;
case 0x43:
lcd_.scxChange(data, cc);
break;
case 0x45:
lcd_.lycRegChange(data, cc);
break;
case 0x46:
if (lastOamDmaUpdate_ != disabled_time)
endOamDma(cc);
lastOamDmaUpdate_ = cc;
intreq_.setEventTime<intevent_oam>(cc + 8);
ioamhram_[0x146] = data;
oamDmaInitSetup();
return;
case 0x47:
if (!isCgb() || (ioamhram_[0x14C] == 0x04))//allow in gbc gb mode
lcd_.dmgBgPaletteChange(data, cc);
break;
case 0x48:
if (!isCgb() || (ioamhram_[0x14C] == 0x04))//allow in gbc gb mode
lcd_.dmgSpPalette1Change(data, cc);
break;
case 0x49:
if (!isCgb() || (ioamhram_[0x14C] == 0x04))//allow in gbc gb mode
lcd_.dmgSpPalette2Change(data, cc);
break;
case 0x4A:
lcd_.wyChange(data, cc);
break;
case 0x4B:
lcd_.wxChange(data, cc);
break;
case 0x4C://switch to classic gb mode from gbc mode or lock system to gbc mode
if ((ioamhram_[0x14C] != 0x04)/*gb mode*/ && (ioamhram_[0x14C] != 0x80)/*gbc mode*/) {
//mode has not been set yet, set the mode if data is valid
if (data == 0x04) {
ioamhram_[0x14C] = 0x04;//0x04 is gbc gb mode, lock register and switch mode to gb emulation mode
lcd_.swapToDMG();
}
else if (data == 0x80)
ioamhram_[0x14C] = 0x80;//0x80 is gbc mode, no special operations needed, just lock this register
//any other write to this register is invalid and will just be ignored
}
return;
case 0x4D:
if (isCgb())
ioamhram_[0x14D] = (ioamhram_[0x14D] & ~1u) | (data & 1);
return;
case 0x4F:
if (isCgb()) {
cart_.setVrambank(data & 1);
ioamhram_[0x14F] = 0xFE | data;
}
return;
case 0x50://for bootloader, swap bootloader with rom
bootloader.call_FF50();
ioamhram_[0x150] = 0xFF;
return;
case 0x51:
dmaSource_ = data << 8 | (dmaSource_ & 0xFF);
return;
case 0x52:
dmaSource_ = (dmaSource_ & 0xFF00) | (data & 0xF0);
return;
case 0x53:
dmaDestination_ = data << 8 | (dmaDestination_ & 0xFF);
return;
case 0x54:
dmaDestination_ = (dmaDestination_ & 0xFF00) | (data & 0xF0);
return;
case 0x55:
if (isCgb()) {
ioamhram_[0x155] = data & 0x7F;
if (lcd_.hdmaIsEnabled()) {
if (!(data & 0x80)) {
ioamhram_[0x155] |= 0x80;
lcd_.disableHdma(cc);
}
} else {
if (data & 0x80) {
if (ioamhram_[0x140] & lcdc_en) {
lcd_.enableHdma(cc);
} else
flagHdmaReq(intreq_);
} else
flagGdmaReq(intreq_);
}
}
return;
case 0x56:
if (isCgb())
ioamhram_[0x156] = data | 0x3E;
return;
case 0x68:
if (isCgb())
ioamhram_[0x168] = data | 0x40;
return;
case 0x69:
if (isCgb()) {
unsigned index = ioamhram_[0x168] & 0x3F;
lcd_.cgbBgColorChange(index, data, cc);
ioamhram_[0x168] = (ioamhram_[0x168] & ~0x3F)
| ((index + (ioamhram_[0x168] >> 7)) & 0x3F);
}
return;
case 0x6A:
if (isCgb())
ioamhram_[0x16A] = data | 0x40;
return;
case 0x6B:
if (isCgb()) {
unsigned index = ioamhram_[0x16A] & 0x3F;
lcd_.cgbSpColorChange(index, data, cc);
ioamhram_[0x16A] = (ioamhram_[0x16A] & ~0x3F)
| ((index + (ioamhram_[0x16A] >> 7)) & 0x3F);
}
return;
case 0x6C:
if (isCgb())
ioamhram_[0x16C] = data | 0xFE;
return;
case 0x70:
if (isCgb()) {
cart_.setWrambank((data & 0x07) ? data & 0x07 : 1);
ioamhram_[0x170] = data | 0xF8;
}
return;
case 0x72:
case 0x73:
case 0x74:
if (isCgb())
break;
return;
case 0x75:
if (isCgb())
ioamhram_[0x175] = data | 0x8F;
return;
case 0xFF:
intreq_.setIereg(data);
break;
default:
return;
}
ioamhram_[p + 0x100] = data;
}