void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) { struct GB* gb = (struct GB*) cpu->master; struct GBMemory* memory = &gb->memory; switch (address >> 12) { case GB_REGION_CART_BANK0: case GB_REGION_CART_BANK0 + 1: case GB_REGION_CART_BANK0 + 2: case GB_REGION_CART_BANK0 + 3: case GB_REGION_CART_BANK1: case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 3: memory->mbc(gb, address, value); cpu->memory.setActiveRegion(cpu, cpu->pc); return; case GB_REGION_VRAM: case GB_REGION_VRAM + 1: gb->video.renderer->writeVRAM(gb->video.renderer, (address & (GB_SIZE_VRAM_BANK0 - 1)) | (GB_SIZE_VRAM_BANK0 * gb->video.vramCurrentBank)); gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value; return; case GB_REGION_EXTERNAL_RAM: case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { memory->rtcRegs[memory->activeRtcReg] = value; } else if (memory->sramAccess) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; } else if (memory->mbcType == GB_MBC7) { GBMBC7Write(memory, address, value); } gb->sramDirty |= GB_SRAM_DIRT_NEW; return; case GB_REGION_WORKING_RAM_BANK0: case GB_REGION_WORKING_RAM_BANK0 + 2: memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value; return; case GB_REGION_WORKING_RAM_BANK1: memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value; return; default: if (address < GB_BASE_OAM) { memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value; } else if (address < GB_BASE_UNUSABLE) { if (gb->video.mode < 2) { gb->video.oam.raw[address & 0xFF] = value; } } else if (address < GB_BASE_IO) { mLOG(GB_MEM, GAME_ERROR, "Attempt to write to unusable memory: %04X:%02X", address, value); } else if (address < GB_BASE_HRAM) { GBIOWrite(gb, address & (GB_SIZE_IO - 1), value); } else if (address < GB_BASE_IE) { memory->hram[address & GB_SIZE_HRAM] = value; } else { GBIOWrite(gb, REG_IE, value); } } }
void GBIOReset(struct GB* gb) { memset(gb->memory.io, 0, sizeof(gb->memory.io)); GBIOWrite(gb, REG_TIMA, 0); GBIOWrite(gb, REG_TMA, 0); GBIOWrite(gb, REG_TAC, 0); GBIOWrite(gb, REG_IF, 1); GBIOWrite(gb, REG_NR52, 0xF1); GBIOWrite(gb, REG_NR10, 0x80); GBIOWrite(gb, REG_NR11, 0xBF); GBIOWrite(gb, REG_NR12, 0xF3); GBIOWrite(gb, REG_NR13, 0xF3); GBIOWrite(gb, REG_NR14, 0xBF); GBIOWrite(gb, REG_NR21, 0x3F); GBIOWrite(gb, REG_NR22, 0x00); GBIOWrite(gb, REG_NR24, 0xBF); GBIOWrite(gb, REG_NR30, 0x7F); GBIOWrite(gb, REG_NR31, 0xFF); GBIOWrite(gb, REG_NR32, 0x9F); GBIOWrite(gb, REG_NR34, 0xBF); GBIOWrite(gb, REG_NR41, 0xFF); GBIOWrite(gb, REG_NR42, 0x00); GBIOWrite(gb, REG_NR43, 0x00); GBIOWrite(gb, REG_NR44, 0xBF); GBIOWrite(gb, REG_NR50, 0x77); GBIOWrite(gb, REG_NR51, 0xF3); GBIOWrite(gb, REG_LCDC, 0x91); GBIOWrite(gb, REG_SCY, 0x00); GBIOWrite(gb, REG_SCX, 0x00); GBIOWrite(gb, REG_LYC, 0x00); GBIOWrite(gb, REG_BGP, 0xFC); GBIOWrite(gb, REG_OBP0, 0xFF); GBIOWrite(gb, REG_OBP1, 0xFF); GBIOWrite(gb, REG_WY, 0x00); GBIOWrite(gb, REG_WX, 0x00); GBIOWrite(gb, REG_VBK, 0); GBIOWrite(gb, REG_BCPS, 0); GBIOWrite(gb, REG_OCPS, 0); GBIOWrite(gb, REG_SVBK, 1); GBIOWrite(gb, REG_HDMA1, 0xFF); GBIOWrite(gb, REG_HDMA2, 0xFF); GBIOWrite(gb, REG_HDMA3, 0xFF); GBIOWrite(gb, REG_HDMA4, 0xFF); gb->memory.io[REG_HDMA5] = 0xFF; GBIOWrite(gb, REG_IE, 0x00); }
void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) { struct GB* gb = (struct GB*) cpu->master; struct GBMemory* memory = &gb->memory; if (gb->memory.dmaRemaining) { const enum GBBus* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB; enum GBBus dmaBus = block[memory->dmaSource >> 13]; enum GBBus accessBus = block[address >> 13]; if (dmaBus != GB_BUS_CPU && dmaBus == accessBus) { return; } if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) { return; } } switch (address >> 12) { case GB_REGION_CART_BANK0: case GB_REGION_CART_BANK0 + 1: case GB_REGION_CART_BANK0 + 2: case GB_REGION_CART_BANK0 + 3: case GB_REGION_CART_BANK1: case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 3: memory->mbcWrite(gb, address, value); cpu->memory.setActiveRegion(cpu, cpu->pc); return; case GB_REGION_VRAM: case GB_REGION_VRAM + 1: gb->video.renderer->writeVRAM(gb->video.renderer, (address & (GB_SIZE_VRAM_BANK0 - 1)) | (GB_SIZE_VRAM_BANK0 * gb->video.vramCurrentBank)); gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value; return; case GB_REGION_EXTERNAL_RAM: case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { memory->rtcRegs[memory->activeRtcReg] = value; } else if (memory->sramAccess && memory->sram && memory->mbcType != GB_MBC2) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; } else if (memory->mbcType == GB_MBC7) { GBMBC7Write(memory, address, value); } gb->sramDirty |= GB_SRAM_DIRT_NEW; return; case GB_REGION_WORKING_RAM_BANK0: case GB_REGION_WORKING_RAM_BANK0 + 2: memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value; return; case GB_REGION_WORKING_RAM_BANK1: memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value; return; default: if (address < GB_BASE_OAM) { memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value; } else if (address < GB_BASE_UNUSABLE) { if (gb->video.mode < 2) { gb->video.oam.raw[address & 0xFF] = value; gb->video.renderer->writeOAM(gb->video.renderer, address & 0xFF); } } else if (address < GB_BASE_IO) { mLOG(GB_MEM, GAME_ERROR, "Attempt to write to unusable memory: %04X:%02X", address, value); } else if (address < GB_BASE_HRAM) { GBIOWrite(gb, address & (GB_SIZE_IO - 1), value); } else if (address < GB_BASE_IE) { memory->hram[address & GB_SIZE_HRAM] = value; } else { GBIOWrite(gb, REG_IE, value); } } }