void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; int bank = value & 0xF; switch (address >> 13) { case 0x0: switch (value) { case 0: memory->sramAccess = false; break; case 0xA: memory->sramAccess = true; GBMBCSwitchSramBank(gb, memory->sramCurrentBank); break; default: // TODO mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value); break; } break; case 0x1: if (!bank) { ++bank; } GBMBCSwitchBank(gb, bank); break; default: // TODO mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value); break; }}
void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; int bank = value & 0x1F; switch (address >> 13) { case 0x0: switch (value) { case 0: memory->sramAccess = false; break; case 0xA: memory->sramAccess = true; GBMBCSwitchSramBank(gb, memory->sramCurrentBank); break; default: // TODO mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value); break; } break; case 0x1: if (!bank) { ++bank; } GBMBCSwitchBank(gb, bank | (memory->currentBank & 0x60)); break; case 0x2: bank &= 3; if (!memory->mbcState.mbc1.mode) { GBMBCSwitchBank(gb, (bank << 5) | (memory->currentBank & 0x1F)); } else { GBMBCSwitchSramBank(gb, bank); } break; case 0x3: memory->mbcState.mbc1.mode = value & 1; if (memory->mbcState.mbc1.mode) { GBMBCSwitchBank(gb, memory->currentBank & 0x1F); } else { GBMBCSwitchSramBank(gb, 0); } break; default: // TODO mLOG(GB_MBC, STUB, "MBC1 unknown address: %04X:%02X", address, value); break; } }
void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; int bank; switch (address >> 12) { case 0x0: case 0x1: switch (value) { case 0: memory->sramAccess = false; break; case 0xA: memory->sramAccess = true; GBMBCSwitchSramBank(gb, memory->sramCurrentBank); break; default: // TODO mLOG(GB_MBC, STUB, "MBC5 unknown value %02X", value); break; } break; case 0x2: bank = (memory->currentBank & 0x100) | value; GBMBCSwitchBank(gb, bank); break; case 0x3: bank = (memory->currentBank & 0xFF) | ((value & 1) << 8); GBMBCSwitchBank(gb, bank); break; case 0x4: case 0x5: if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) { memory->rumble->setRumble(memory->rumble, (value >> 3) & 1); value &= ~8; } GBMBCSwitchSramBank(gb, value & 0xF); break; default: // TODO mLOG(GB_MBC, STUB, "MBC5 unknown address: %04X:%02X", address, value); break; }
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; int bank = value & 0x7F; switch (address >> 13) { case 0x0: switch (value) { case 0: memory->sramAccess = false; break; case 0xA: memory->sramAccess = true; GBMBCSwitchSramBank(gb, memory->sramCurrentBank); break; default: // TODO mLOG(GB_MBC, STUB, "MBC3 unknown value %02X", value); break; } break; case 0x1: if (!bank) { ++bank; } GBMBCSwitchBank(gb, bank); break; case 0x2: if (value < 4) { GBMBCSwitchSramBank(gb, value); memory->rtcAccess = false; } else if (value >= 8 && value <= 0xC) { memory->activeRtcReg = value - 8; memory->rtcAccess = true; } break; case 0x3: if (memory->rtcLatched && value == 0) { memory->rtcLatched = false; } else if (!memory->rtcLatched && value == 1) { _latchRtc(gb->memory.rtc, gb->memory.rtcRegs, &gb->memory.rtcLastLatch); memory->rtcLatched = true; } break; } }
void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) { struct GBMemory* memory = &gb->memory; memcpy(memory->wram, state->wram, GB_SIZE_WORKING_RAM); memcpy(memory->hram, state->hram, GB_SIZE_HRAM); LOAD_16LE(memory->currentBank, 0, &state->memory.currentBank); memory->wramCurrentBank = state->memory.wramCurrentBank; memory->sramCurrentBank = state->memory.sramCurrentBank; GBMBCSwitchBank(gb, memory->currentBank); GBMemorySwitchWramBank(memory, memory->wramCurrentBank); GBMBCSwitchSramBank(gb, memory->sramCurrentBank); LOAD_16LE(memory->dmaSource, 0, &state->memory.dmaSource); LOAD_16LE(memory->dmaDest, 0, &state->memory.dmaDest); LOAD_16LE(memory->hdmaSource, 0, &state->memory.hdmaSource); LOAD_16LE(memory->hdmaDest, 0, &state->memory.hdmaDest); LOAD_16LE(memory->hdmaRemaining, 0, &state->memory.hdmaRemaining); memory->dmaRemaining = state->memory.dmaRemaining; memcpy(memory->rtcRegs, state->memory.rtcRegs, sizeof(state->memory.rtcRegs)); uint32_t when; LOAD_32LE(when, 0, &state->memory.dmaNext); if (memory->dmaRemaining) { mTimingSchedule(&gb->timing, &memory->dmaEvent, when); } LOAD_32LE(when, 0, &state->memory.hdmaNext); if (memory->hdmaRemaining) { mTimingSchedule(&gb->timing, &memory->hdmaEvent, when); } GBSerializedMemoryFlags flags; LOAD_16LE(flags, 0, &state->memory.flags); memory->sramAccess = GBSerializedMemoryFlagsGetSramAccess(flags); memory->rtcAccess = GBSerializedMemoryFlagsGetRtcAccess(flags); memory->rtcLatched = GBSerializedMemoryFlagsGetRtcLatched(flags); memory->ime = GBSerializedMemoryFlagsGetIme(flags); memory->isHdma = GBSerializedMemoryFlagsGetIsHdma(flags); memory->activeRtcReg = GBSerializedMemoryFlagsGetActiveRtcReg(flags); switch (memory->mbcType) { case GB_MBC1: memory->mbcState.mbc1.mode = state->memory.mbc1.mode; memory->mbcState.mbc1.multicartStride = state->memory.mbc1.multicartStride; if (memory->mbcState.mbc1.mode) { GBMBCSwitchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride); } break; case GB_MBC3_RTC: LOAD_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch); break; case GB_MBC7: memory->mbcState.mbc7.state = state->memory.mbc7.state; memory->mbcState.mbc7.eeprom = state->memory.mbc7.eeprom; memory->mbcState.mbc7.address = state->memory.mbc7.address & 0x7F; memory->mbcState.mbc7.access = state->memory.mbc7.access; memory->mbcState.mbc7.latch = state->memory.mbc7.latch; memory->mbcState.mbc7.srBits = state->memory.mbc7.srBits; LOAD_16LE(memory->mbcState.mbc7.sr, 0, &state->memory.mbc7.sr); LOAD_32LE(memory->mbcState.mbc7.writable, 0, &state->memory.mbc7.writable); break; default: break; }