Memory Map:
Taken from nocash-s pandocs we have the following memory map:
0000-3FFF 16KB ROM Bank 00 (in cartridge, fixed at bank 00)
4000-7FFF 16KB ROM Bank 01..NN (in cartridge, switchable bank number)
8000-9FFF 8KB Video RAM (VRAM) (switchable bank 0-1 in CGB Mode)
A000-BFFF 8KB External RAM (in cartridge, switchable bank, if any)
C000-CFFF 4KB Work RAM Bank 0 (WRAM)
D000-DFFF 4KB Work RAM Bank 1 (WRAM) (switchable bank 1-7 in CGB Mode)
E000-FDFF Same as C000-DDFF (ECHO) (typically not used)
FE00-FE9F Sprite Attribute Table (OAM)
FEA0-FEFF Not Usable
FF00-FF7F I/O Ports
FF80-FFFE High RAM (HRAM)
FFFF Interrupt Enable Register
I will discuss the rest of the regions as needed in the following sections.
Memory Control:
Now we have a breakdown of the internal memory it becomes quite obvious that read and write access to the memory needs to be well controlled. For instance the first 0x8000 bytes are read only so nothing should ever get written there. Also anything that gets written to ECHO memory needs to be reflected in work RAM. Also when reading from one of the banks it is important that it gets read from the correct bank. The best way to control read and write access to the memory is creating a ReadMemory function and a WriteMemory function. Whenever you read and write to memory you MUST use these two functions, this way you will be certain your memory access will be controlled correctly. The only exception to this is when you initialize Rom memory which was shown on the previous section Hardware. Below is an example of how the WriteMemory will help you control memory access:
void Emulator::WriteMemory(WORD address, BYTE data)
{
// dont allow any writing to the read only memory
if ( address < 0x8000 )
{
}
// writing to ECHO ram also writes in RAM
else if ( ( address >= 0xE000 ) && (address < 0xFE00) )
{
m_Rom[address] = data ;
WriteMemory(address-0x2000, data) ;
}
// this area is restricted
else if ( ( address >= 0xFEA0 ) && (address < 0xFEFF) )
{
}
// no control needed over this area so write to memory
else
{
m_Rom[address] = data ;
}
}