394 lines
8.3 KiB
C#
394 lines
8.3 KiB
C#
using System;
|
|
|
|
using BizHawk.Common.BufferExtensions;
|
|
using BizHawk.Emulation.Common;
|
|
|
|
|
|
/*
|
|
$FFFF Interrupt Enable Flag
|
|
$FF80-$FFFE Zero Page - 127 bytes
|
|
$FF00-$FF7F Hardware I/O Registers
|
|
$FEA0-$FEFF Unusable Memory
|
|
$FE00-$FE9F OAM - Object Attribute Memory
|
|
$E000-$FDFF Echo RAM - Reserved, Do Not Use
|
|
$D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only)
|
|
$C000-$CFFF Internal RAM - Bank 0 (fixed)
|
|
$A000-$BFFF Cartridge RAM (If Available)
|
|
$9C00-$9FFF BG Map Data 2
|
|
$9800-$9BFF BG Map Data 1
|
|
$8000-$97FF Character RAM
|
|
$4000-$7FFF Cartridge ROM - Switchable Banks 1-xx
|
|
$0150-$3FFF Cartridge ROM - Bank 0 (fixed)
|
|
$0100-$014F Cartridge Header Area
|
|
$0000-$00FF Restart and Interrupt Vectors
|
|
*/
|
|
|
|
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|
{
|
|
public partial class GBHawk
|
|
{
|
|
public byte ReadMemory(ushort addr)
|
|
{
|
|
MemoryCallbacks.CallReads(addr, "System Bus");
|
|
addr_access = addr;
|
|
|
|
if (ppu.DMA_start)
|
|
{
|
|
// some of gekkio's tests require these to be accessible during DMA
|
|
if (addr < 0x8000)
|
|
{
|
|
if (ppu.DMA_addr < 0x80)
|
|
{
|
|
return 0xFF;
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else if ((addr >= 0xE000) && (addr < 0xF000))
|
|
{
|
|
return RAM[addr - 0xE000];
|
|
}
|
|
else if ((addr >= 0xF000) && (addr < 0xFE00))
|
|
{
|
|
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
|
}
|
|
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
|
{
|
|
return OAM[addr - 0xFE00];
|
|
}
|
|
else if ((addr >= 0xFF00) && (addr < 0xFF80)) // The game GOAL! Requires Hardware Regs to be accessible
|
|
{
|
|
return Read_Registers(addr);
|
|
}
|
|
else if ((addr >= 0xFF80))
|
|
{
|
|
return ZP_RAM[addr - 0xFF80];
|
|
}
|
|
|
|
return 0xFF;
|
|
}
|
|
|
|
if (addr < 0x900)
|
|
{
|
|
if (addr < 0x100)
|
|
{
|
|
// return Either BIOS ROM or Game ROM
|
|
if ((GB_bios_register & 0x1) == 0)
|
|
{
|
|
return _bios[addr]; // Return BIOS
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else if (addr >= 0x200)
|
|
{
|
|
// return Either BIOS ROM or Game ROM
|
|
if (((GB_bios_register & 0x1) == 0) && is_GBC)
|
|
{
|
|
return _bios[addr]; // Return BIOS
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else if (addr < 0x8000)
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
else if (addr < 0xA000)
|
|
{
|
|
if (ppu.VRAM_access_read) { return VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)]; }
|
|
else { return 0xFF; }
|
|
}
|
|
else if (addr < 0xC000)
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
else if (addr < 0xD000)
|
|
{
|
|
return RAM[addr - 0xC000];
|
|
}
|
|
else if (addr < 0xE000)
|
|
{
|
|
return RAM[(RAM_Bank * 0x1000) + (addr - 0xD000)];
|
|
}
|
|
else if (addr < 0xF000)
|
|
{
|
|
return RAM[addr - 0xE000];
|
|
}
|
|
else if (addr < 0xFE00)
|
|
{
|
|
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
|
}
|
|
else if (addr < 0xFEA0)
|
|
{
|
|
if (ppu.OAM_access_read) { return OAM[addr - 0xFE00]; }
|
|
else { return 0xFF; }
|
|
}
|
|
else if (addr < 0xFF00)
|
|
{
|
|
// unmapped memory, returns 0xFF
|
|
return 0xFF;
|
|
}
|
|
else if (addr < 0xFF80)
|
|
{
|
|
return Read_Registers(addr);
|
|
}
|
|
else if (addr < 0xFFFF)
|
|
{
|
|
return ZP_RAM[addr - 0xFF80];
|
|
}
|
|
else
|
|
{
|
|
return Read_Registers(addr);
|
|
}
|
|
|
|
}
|
|
|
|
public void WriteMemory(ushort addr, byte value)
|
|
{
|
|
MemoryCallbacks.CallWrites(addr, "System Bus");
|
|
addr_access = addr;
|
|
|
|
if (ppu.DMA_start)
|
|
{
|
|
// some of gekkio's tests require this to be accessible during DMA
|
|
if ((addr >= 0xE000) && (addr < 0xF000))
|
|
{
|
|
RAM[addr - 0xE000] = value;
|
|
}
|
|
else if ((addr >= 0xF000) && (addr < 0xFE00))
|
|
{
|
|
RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)] = value;
|
|
}
|
|
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
|
{
|
|
OAM[addr - 0xFE00] = value;
|
|
}
|
|
else if ((addr >= 0xFF00) && (addr < 0xFF80)) // The game GOAL! Requires Hardware Regs to be accessible
|
|
{
|
|
Write_Registers(addr, value);
|
|
}
|
|
else if ((addr >= 0xFF80))
|
|
{
|
|
ZP_RAM[addr - 0xFF80] = value;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (addr < 0x900)
|
|
{
|
|
if (addr < 0x100)
|
|
{
|
|
if ((GB_bios_register & 0x1) == 0)
|
|
{
|
|
// No Writing to BIOS
|
|
}
|
|
else
|
|
{
|
|
mapper.WriteMemory(addr, value);
|
|
}
|
|
}
|
|
else if (addr >= 0x200)
|
|
{
|
|
if (((GB_bios_register & 0x1) == 0) && is_GBC)
|
|
{
|
|
// No Writing to BIOS
|
|
}
|
|
else
|
|
{
|
|
mapper.WriteMemory(addr, value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mapper.WriteMemory(addr, value);
|
|
}
|
|
}
|
|
else if (addr < 0x8000)
|
|
{
|
|
mapper.WriteMemory(addr, value);
|
|
}
|
|
else if (addr < 0xA000)
|
|
{
|
|
if (ppu.VRAM_access_write) { VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)] = value; }
|
|
}
|
|
else if (addr < 0xC000)
|
|
{
|
|
mapper.WriteMemory(addr, value);
|
|
}
|
|
else if (addr < 0xD000)
|
|
{
|
|
RAM[addr - 0xC000] = value;
|
|
}
|
|
else if (addr < 0xE000)
|
|
{
|
|
RAM[(RAM_Bank * 0x1000) + (addr - 0xD000)] = value;
|
|
}
|
|
else if (addr < 0xF000)
|
|
{
|
|
RAM[addr - 0xE000] = value;
|
|
}
|
|
else if (addr < 0xFE00)
|
|
{
|
|
RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)] = value;
|
|
}
|
|
else if (addr < 0xFEA0)
|
|
{
|
|
if (ppu.OAM_access_write) { OAM[addr - 0xFE00] = value; }
|
|
}
|
|
else if (addr < 0xFF00)
|
|
{
|
|
// unmapped, writing has no effect
|
|
}
|
|
else if (addr < 0xFF80)
|
|
{
|
|
Write_Registers(addr, value);
|
|
}
|
|
else if (addr < 0xFFFF)
|
|
{
|
|
ZP_RAM[addr - 0xFF80] = value;
|
|
}
|
|
else
|
|
{
|
|
Write_Registers(addr, value);
|
|
}
|
|
}
|
|
|
|
public byte PeekMemory(ushort addr)
|
|
{
|
|
if (ppu.DMA_start)
|
|
{
|
|
// some of gekkio's tests require these to be accessible during DMA
|
|
if (addr < 0x8000)
|
|
{
|
|
if (ppu.DMA_addr < 0x80)
|
|
{
|
|
return 0xFF;
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else if ((addr >= 0xE000) && (addr < 0xF000))
|
|
{
|
|
return RAM[addr - 0xE000];
|
|
}
|
|
else if ((addr >= 0xF000) && (addr < 0xFE00))
|
|
{
|
|
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
|
}
|
|
else if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
|
{
|
|
return OAM[addr - 0xFE00];
|
|
}
|
|
else if ((addr >= 0xFF00) && (addr < 0xFF80)) // The game GOAL! Requires Hardware Regs to be accessible
|
|
{
|
|
return Read_Registers(addr);
|
|
}
|
|
else if ((addr >= 0xFF80))
|
|
{
|
|
return ZP_RAM[addr - 0xFF80];
|
|
}
|
|
|
|
return 0xFF;
|
|
}
|
|
|
|
if (addr < 0x900)
|
|
{
|
|
if (addr < 0x100)
|
|
{
|
|
// return Either BIOS ROM or Game ROM
|
|
if ((GB_bios_register & 0x1) == 0)
|
|
{
|
|
return _bios[addr]; // Return BIOS
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else if (addr >= 0x200)
|
|
{
|
|
// return Either BIOS ROM or Game ROM
|
|
if (((GB_bios_register & 0x1) == 0) && is_GBC)
|
|
{
|
|
return _bios[addr]; // Return BIOS
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return mapper.ReadMemory(addr);
|
|
}
|
|
}
|
|
else if (addr < 0x8000)
|
|
{
|
|
return mapper.PeekMemory(addr);
|
|
}
|
|
else if (addr < 0xA000)
|
|
{
|
|
if (ppu.VRAM_access_read) { return VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)]; }
|
|
else { return 0xFF; }
|
|
}
|
|
else if (addr < 0xC000)
|
|
{
|
|
return mapper.PeekMemory(addr);
|
|
}
|
|
else if (addr < 0xD000)
|
|
{
|
|
return RAM[addr - 0xC000];
|
|
}
|
|
else if (addr < 0xE000)
|
|
{
|
|
return RAM[(RAM_Bank * 0x1000) + (addr - 0xD000)];
|
|
}
|
|
else if (addr < 0xF000)
|
|
{
|
|
return RAM[addr - 0xE000];
|
|
}
|
|
else if (addr < 0xFE00)
|
|
{
|
|
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
|
|
}
|
|
else if (addr < 0xFEA0)
|
|
{
|
|
if (ppu.OAM_access_read) { return OAM[addr - 0xFE00]; }
|
|
else { return 0xFF; }
|
|
}
|
|
else if (addr < 0xFF00)
|
|
{
|
|
// unmapped memory, returns 0xFF
|
|
return 0xFF;
|
|
}
|
|
else if (addr < 0xFF80)
|
|
{
|
|
return Read_Registers(addr);
|
|
}
|
|
else if (addr < 0xFFFF)
|
|
{
|
|
return ZP_RAM[addr - 0xFF80];
|
|
}
|
|
else
|
|
{
|
|
return Read_Registers(addr);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|