NESemu/src/Bus.cpp

176 lines
2.6 KiB
C++
Raw Normal View History

2022-02-28 15:04:25 +00:00
#include "Bus.hpp"
#include "Log.hpp"
#include <stdexcept>
2022-03-01 17:13:47 +00:00
#include "controllers/StandardController.hpp"
2022-02-28 15:04:25 +00:00
Bus::Bus() :
cpu(this), ppu(this), cartridge(this)
{
LOG_CORE_INFO("Allocating RAM");
RAM = std::vector<Byte>(0x800);
LOG_CORE_INFO("Allocating VRAM");
2022-03-01 02:34:19 +00:00
VRAM = std::vector<Byte>(0x800);
2022-02-28 15:04:25 +00:00
LOG_CORE_INFO("Inserting cartridge");
cartridge.Load("roms/nestest.nes");
LOG_CORE_INFO("Powering up CPU");
cpu.Powerup();
LOG_CORE_INFO("Powering up PPU");
ppu.Powerup();
2022-03-01 17:13:47 +00:00
controllerPort.PlugInController<StandardController>(0);
2022-02-28 15:04:25 +00:00
}
void Bus::Reboot()
{
cpu.Powerup();
ppu.Powerup();
}
void Bus::Reset()
{
cpu.Reset();
ppu.Reset();
}
uint8_t Bus::Tick()
{
2022-03-01 17:13:47 +00:00
controllerPort.Tick();
2022-02-28 15:04:25 +00:00
uint8_t result = cpu.Tick();
// 3 ppu ticks per cpu tick
ppu.Tick();
ppu.Tick();
ppu.Tick();
return result;
}
bool Bus::Instruction()
{
try
{
while (Tick());
}
catch (const std::runtime_error& err)
{
LOG_CORE_FATAL("Fatal Bus error: {0}", err.what());
cpu.Halt();
return true;
}
return true;
}
bool Bus::Frame()
{
try
{
while (!ppu.IsFrameDone())
Tick();
}
catch (const std::runtime_error& err)
{
LOG_CORE_FATAL("Fatal Bus error: {0}", err.what());
cpu.Halt();
return true;
}
return true;
}
Byte Bus::ReadCPU(Word addr)
{
if (0x0000 <= addr && addr < 0x2000)
{
return RAM[addr & 0x7FF];
}
else if (0x2000 <= addr && addr < 0x4000)
{
return ppu.ReadRegister(addr & 0x7);
}
else if (0x8000 <= addr && addr <= 0xFFFF)
{
return cartridge.ReadCPU(addr);
}
2022-03-01 17:13:47 +00:00
else if (0x4000 <= addr && addr <= 0x4017)
{
switch (addr)
{
case 0x4016:
case 0x4017:
return controllerPort.Read(addr);
}
}
return 0x00;
2022-02-28 15:04:25 +00:00
}
Byte Bus::ReadPPU(Word addr)
{
addr &= 0x3FFF;
if (0x0000 <= addr && addr < 0x2000)
{
return cartridge.ReadPPU(addr);
}
else if(0x2000 <= addr && addr < 0x4000)
{
2022-03-01 02:34:19 +00:00
if (cartridge.MapCIRAM(addr))
return cartridge.ReadVRAM(addr);
2022-02-28 15:04:25 +00:00
return VRAM[addr & 0xFFF];
}
return 0x00;
}
void Bus::WriteCPU(Word addr, Byte val)
{
if (0x0000 <= addr && addr < 0x2000)
{
RAM[addr & 0x7FF] = val;
}
else if (0x2000 <= addr && addr < 0x4000)
{
ppu.WriteRegister(addr & 0x7, val);
}
else if (0x8000 <= addr && addr <= 0xFFFF)
{
cartridge.WriteCPU(addr, val);
}
2022-03-01 17:13:47 +00:00
else if (0x4000 <= addr && addr <= 0x4017)
{
switch (addr)
{
case 0x4016:
case 0x4017:
controllerPort.Write(addr, val);
break;
}
}
2022-02-28 15:04:25 +00:00
}
void Bus::WritePPU(Word addr, Byte val)
{
addr &= 0x3FFF;
if (0x0000 <= addr && addr < 0x2000)
{
cartridge.WritePPU(addr, val);
}
else if (0x2000 <= addr && addr < 0x4000)
{
2022-03-01 02:34:19 +00:00
if(cartridge.MapCIRAM(addr))
cartridge.WriteVRAM(addr, val);
2022-02-28 15:04:25 +00:00
VRAM[addr & 0xFFF] = val;
}
}