diff --git a/CMakeLists.txt b/CMakeLists.txt index adf73a6..3ded792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,9 @@ add_executable(nes src/Oam.cpp src/Oam.h src/Mapper/Mapper1.cpp - src/Mapper/Mapper1.h) + src/Mapper/Mapper1.h + src/Bus.cpp + src/Bus.h) find_package(SDL2 CONFIG REQUIRED) find_package(fmt REQUIRED) diff --git a/src/Bus.cpp b/src/Bus.cpp new file mode 100644 index 0000000..3f0c270 --- /dev/null +++ b/src/Bus.cpp @@ -0,0 +1,97 @@ +// +// Created by Selim Mustafaev on 01.07.2025. +// + +#include "Bus.h" +#include + +namespace nes { + + Bus::Bus(uint8_t *ram, + Cpu *cpu, + Ppu *ppu, + Cartridge *cartridge, + Controller *controller1, + Controller *controller2, + Dma *dma): _ram(ram), + _cpu(cpu), + _ppu(ppu), + _cartridge(cartridge), + _controller1(controller1), + _controller2(controller2), + _dma(dma) { + + _cpu->connectToBus(this); + _ppu->connectToBus(this); + _dma->connectToBus(this); + } + + void Bus::connectCartridge(Cartridge *cartridge) { + _cartridge = cartridge; + } + + void Bus::connectController1(Controller *controller1) { + _controller1 = controller1; + } + + void Bus::connectController2(Controller *controller2) { + _controller2 = controller2; + } + + Cartridge::Mirroring Bus::cartridgeMirroring() const { + return _cartridge->mirroring(); + } + + uint8_t Bus::readChr(uint16_t address) const { + return _cartridge->readChr(address); + } + + uint8_t Bus::read(uint16_t address) const { + if(address < 0x2000) { + return _ram[address & 0x07FF]; + } + else if(address >= 0x2000 && address < 0x4000) { + return _ppu->read(address & 0x0007); + } + else if (address >= 0x6000 && address < 0x8000) { + return _cartridge->readRam(address); + } + else if(address >= 0x8000) { + return _cartridge->readPrg(address); + } + else if(address == 0x4016) { + return _controller1->read(); + } + else if(address == 0x4017) { + if (_controller2) { + return _controller2->read(); + } + } + + return 0; + } + + void Bus::write(uint16_t address, uint8_t value) { + if(address < 0x2000) { + _ram[address & 0x07FF] = value; + } + else if(address >= 0x2000 && address < 0x4000) { + _ppu->write(address & 0x0007, value); + } + else if(address >= 0x8000) { + std::cout << "Cartridge (PRG) write at address: " << address << std::endl; + } + else if(address == 0x4014) { + _dma->start(value); + } + else if(address == 0x4016) { + _controller1->poll(); + } + else if(address == 0x4017) { + if (_controller2) { + _controller2->poll(); + } + } + } + +} \ No newline at end of file diff --git a/src/Bus.h b/src/Bus.h new file mode 100644 index 0000000..ca0b98d --- /dev/null +++ b/src/Bus.h @@ -0,0 +1,49 @@ +// +// Created by Selim Mustafaev on 01.07.2025. +// + +#ifndef BUS_H +#define BUS_H + +#include "Cpu.h" +#include "Ppu.h" +#include "Cartridge.h" +#include "Controller.h" +#include "Dma.h" +#include + +namespace nes { + + class Bus { + public: + Bus(uint8_t *ram, + Cpu *cpu, + Ppu *ppu, + Cartridge *cartridge, + Controller *controller1, + Controller *controller2, + Dma *dma); + + void connectCartridge(Cartridge *cartridge); + void connectController1(Controller *controller1); + void connectController2(Controller *controller2); + + [[nodiscard]] Cartridge::Mirroring cartridgeMirroring() const; + uint8_t readChr(uint16_t address) const; + + uint8_t read(uint16_t address) const; + void write(uint16_t address, uint8_t value); + + private: + uint8_t* _ram; + Cpu* _cpu; + Ppu* _ppu; + Cartridge* _cartridge; + Controller* _controller1; + Controller* _controller2; + Dma* _dma; + }; + +} + +#endif //BUS_H diff --git a/src/Cpu.cpp b/src/Cpu.cpp index 32a3dfe..c510e57 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -3,7 +3,7 @@ // #include "Cpu.h" -#include "System.h" +#include "Bus.h" #include #ifdef NES_LOGGING @@ -12,8 +12,7 @@ namespace nes { - Cpu::Cpu(System* system): _ticks{}, A{}, X{}, Y{}, PC{}, SP{}, flags{} { - _system = system; + Cpu::Cpu(): _ticks{}, A{}, X{}, Y{}, PC{}, SP{}, flags{} { _instructions = std::vector(256); _instructions[0x00] = {"BRK", &Cpu::BRK, &Cpu::IMPL, 7, false}; _instructions[0x01] = {"ORA", &Cpu::ORA, &Cpu::IZX, 6, false}; @@ -174,8 +173,8 @@ namespace nes { SP = 0xFD; flags = 0; - uint16_t lo = _system->read(0xFFFC); - uint16_t hi = _system->read(0xFFFD); + uint16_t lo = _bus->read(0xFFFC); + uint16_t hi = _bus->read(0xFFFD); PC = (hi << 8) | lo; @@ -186,7 +185,7 @@ namespace nes { bool executed = false; if(_ticks == 0) { - uint8_t opcode = _system->read(PC++); + uint8_t opcode = _bus->read(PC++); auto instruction = _instructions[opcode]; _currentOpcode = opcode; @@ -211,21 +210,25 @@ namespace nes { } void Cpu::nmi() { - _system->write(STACK_BASE + SP--, PC >> 8); - _system->write(STACK_BASE + SP--, PC & 0x00FF); + _bus->write(STACK_BASE + SP--, PC >> 8); + _bus->write(STACK_BASE + SP--, PC & 0x00FF); setFlag(Break, false); setFlag(Unused, true); setFlag(InterruptDisable, true); - _system->write(STACK_BASE + SP--, flags); + _bus->write(STACK_BASE + SP--, flags); - uint8_t lo = _system->read(0xFFFA); - uint8_t hi = _system->read(0xFFFB); + uint8_t lo = _bus->read(0xFFFA); + uint8_t hi = _bus->read(0xFFFB); PC = (hi << 8) | lo; _ticks = 8; } + void Cpu::connectToBus(Bus *bus) { + _bus = bus; + } + #ifdef NES_LOGGING std::string Cpu::state() const { return fmt::format("{} ({:02X}), PC: {:X}, SP: {:X}, A: {:02X}, X: {:02X}, Y: {:02X}, [N:{}, V:{}, B{}, D{}, I{}, Z:{}, C:{}], H: {:08X}", @@ -239,7 +242,7 @@ namespace nes { (int)getFlag(InterruptDisable), (int)getFlag(Zero), (int)getFlag(Carry), - _system->zpHash()); + _bus->zpHash()); } #endif @@ -280,8 +283,8 @@ namespace nes { } Cpu::InstructionArgs Cpu::ABSL() { - uint8_t lo = _system->read(PC++); - uint8_t hi = _system->read(PC++); + uint8_t lo = _bus->read(PC++); + uint8_t hi = _bus->read(PC++); uint16_t address = (hi << 8) | lo; return {address, 0}; } @@ -291,7 +294,7 @@ namespace nes { } Cpu::InstructionArgs Cpu::REL() { - uint16_t address = _system->read(PC++); + uint16_t address = _bus->read(PC++); if (address & 0x80) { address |= 0xFF00; @@ -301,22 +304,22 @@ namespace nes { } Cpu::InstructionArgs Cpu::ZP0() { - uint16_t address = _system->read(PC++); + uint16_t address = _bus->read(PC++); return {address, 0}; } Cpu::InstructionArgs Cpu::IZX() { - uint8_t ptrAddress = _system->read(PC++) + X; - uint8_t lo = _system->read(ptrAddress); - uint8_t hi = _system->read(++ptrAddress); + uint8_t ptrAddress = _bus->read(PC++) + X; + uint8_t lo = _bus->read(ptrAddress); + uint8_t hi = _bus->read(++ptrAddress); uint16_t address = (hi << 8) | lo; return {address, 0}; } Cpu::InstructionArgs Cpu::IZY() { - uint8_t ptrAddress = _system->read(PC++); - uint8_t lo = _system->read(ptrAddress); - uint8_t hi = _system->read(++ptrAddress); + uint8_t ptrAddress = _bus->read(PC++); + uint8_t lo = _bus->read(ptrAddress); + uint8_t hi = _bus->read(++ptrAddress); uint16_t address = (hi << 8) | lo; address += Y; @@ -329,17 +332,17 @@ namespace nes { } Cpu::InstructionArgs Cpu::IND() { - uint8_t ptrLo = _system->read(PC++); - uint8_t ptrHi = _system->read(PC++); + uint8_t ptrLo = _bus->read(PC++); + uint8_t ptrHi = _bus->read(PC++); uint16_t ptrAddress = (ptrHi << 8) | ptrLo; - uint8_t lo = _system->read(ptrAddress); + uint8_t lo = _bus->read(ptrAddress); uint8_t hi = 0; if(ptrLo == 0xFF) { - hi = _system->read(ptrAddress & 0xFF00); + hi = _bus->read(ptrAddress & 0xFF00); } else { - hi = _system->read(++ptrAddress); + hi = _bus->read(++ptrAddress); } uint16_t address = (hi << 8) | lo; @@ -347,8 +350,8 @@ namespace nes { } Cpu::InstructionArgs Cpu::ABX() { - uint8_t lo = _system->read(PC++); - uint8_t hi = _system->read(PC++); + uint8_t lo = _bus->read(PC++); + uint8_t hi = _bus->read(PC++); uint16_t address = (hi << 8) | lo; address += X; @@ -361,8 +364,8 @@ namespace nes { } Cpu::InstructionArgs Cpu::ABY() { - uint8_t lo = _system->read(PC++); - uint8_t hi = _system->read(PC++); + uint8_t lo = _bus->read(PC++); + uint8_t hi = _bus->read(PC++); uint16_t address = (hi << 8) | lo; address += Y; @@ -375,41 +378,41 @@ namespace nes { } Cpu::InstructionArgs Cpu::ZPX() { - uint8_t address = _system->read(PC++) + X; + uint8_t address = _bus->read(PC++) + X; return {address, 0}; } Cpu::InstructionArgs Cpu::ZPY() { - uint8_t address = _system->read(PC++) + Y; + uint8_t address = _bus->read(PC++) + Y; return {address, 0}; } // CPU instructions void Cpu::LDA(Cpu::InstructionArgs args) { - A = _system->read(args.address); + A = _bus->read(args.address); setFlag(Negative, A & 0x80); setFlag(Zero, A == 0); } void Cpu::LDX(InstructionArgs args) { - X = _system->read(args.address); + X = _bus->read(args.address); setFlag(Negative, X & 0x80); setFlag(Zero, X == 0); } void Cpu::LDY(Cpu::InstructionArgs args) { - Y = _system->read(args.address); + Y = _bus->read(args.address); setFlag(Negative, Y & 0x80); setFlag(Zero, Y == 0); } void Cpu::STA(Cpu::InstructionArgs args) { - _system->write(args.address, A); + _bus->write(args.address, A); } void Cpu::STX(InstructionArgs args) { - _system->write(args.address, X); + _bus->write(args.address, X); } void Cpu::CLC(Cpu::InstructionArgs args) { @@ -417,7 +420,7 @@ namespace nes { } void Cpu::ADC(Cpu::InstructionArgs args) { - uint16_t value = _system->read(args.address); + uint16_t value = _bus->read(args.address); uint16_t result = A + value + getFlag(Carry); setFlag(Carry, result > 255); @@ -429,7 +432,7 @@ namespace nes { } void Cpu::SBC(Cpu::InstructionArgs args) { - uint16_t value = _system->read(args.address) ^ 0xFF; + uint16_t value = _bus->read(args.address) ^ 0xFF; uint16_t result = A + value + getFlag(Carry); setFlag(Carry, result > 255); @@ -479,8 +482,8 @@ namespace nes { void Cpu::JSR(Cpu::InstructionArgs args) { PC--; - _system->write(STACK_BASE + SP--, PC >> 8); - _system->write(STACK_BASE + SP--, PC & 0x00FF); + _bus->write(STACK_BASE + SP--, PC >> 8); + _bus->write(STACK_BASE + SP--, PC & 0x00FF); PC = args.address; } @@ -507,7 +510,7 @@ namespace nes { } void Cpu::BIT(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); + uint8_t value = _bus->read(args.address); setFlag(Zero, (A & value) == 0); setFlag(Negative, value & (1 << 7)); setFlag(Overflow, value & (1 << 6)); @@ -526,8 +529,8 @@ namespace nes { } void Cpu::RTS(Cpu::InstructionArgs args) { - uint16_t lo = _system->read(STACK_BASE + ++SP); - uint16_t hi = _system->read(STACK_BASE + ++SP); + uint16_t lo = _bus->read(STACK_BASE + ++SP); + uint16_t hi = _bus->read(STACK_BASE + ++SP); PC = (hi << 8) | lo; PC++; @@ -538,25 +541,25 @@ namespace nes { } void Cpu::PHP(Cpu::InstructionArgs args) { - _system->write(STACK_BASE + SP--, flags | Break | Unused); + _bus->write(STACK_BASE + SP--, flags | Break | Unused); setFlag(Break, false); setFlag(Unused, false); } void Cpu::PLA(Cpu::InstructionArgs args) { - A = _system->read(STACK_BASE + ++SP); + A = _bus->read(STACK_BASE + ++SP); setFlag(Zero, A == 0); setFlag(Negative, A & 0x80); } void Cpu::AND(Cpu::InstructionArgs args) { - A &= _system->read(args.address);; + A &= _bus->read(args.address);; setFlag(Zero, A == 0); setFlag(Negative, A & 0x80); } void Cpu::CMP(Cpu::InstructionArgs args) { - uint16_t value = _system->read(args.address); + uint16_t value = _bus->read(args.address); uint16_t diff = A - value; setFlag(Carry, A >= value); setFlag(Zero, (diff & 0x00FF) == 0); @@ -570,16 +573,16 @@ namespace nes { } void Cpu::PHA(Cpu::InstructionArgs args) { - _system->write(STACK_BASE + SP--, A); + _bus->write(STACK_BASE + SP--, A); } void Cpu::PLP(Cpu::InstructionArgs args) { - flags = _system->read(STACK_BASE + ++SP); + flags = _bus->read(STACK_BASE + ++SP); setFlag(Unused, true); } void Cpu::ORA(Cpu::InstructionArgs args) { - A |= _system->read(args.address); + A |= _bus->read(args.address); setFlag(Zero, A == 0); setFlag(Negative, A & 0x80); } @@ -589,13 +592,13 @@ namespace nes { } void Cpu::EOR(Cpu::InstructionArgs args) { - A ^= _system->read(args.address); + A ^= _bus->read(args.address); setFlag(Zero, A == 0); setFlag(Negative, A & 0x80); } void Cpu::CPY(Cpu::InstructionArgs args) { - uint16_t value = _system->read(args.address); + uint16_t value = _bus->read(args.address); uint16_t diff = Y - value; setFlag(Carry, Y >= value); setFlag(Zero, (diff & 0x00FF) == 0); @@ -603,7 +606,7 @@ namespace nes { } void Cpu::CPX(Cpu::InstructionArgs args) { - uint16_t value = _system->read(args.address); + uint16_t value = _bus->read(args.address); uint16_t diff = X - value; setFlag(Carry, X >= value); setFlag(Zero, (diff & 0x00FF) == 0); @@ -611,7 +614,7 @@ namespace nes { } void Cpu::STY(Cpu::InstructionArgs args) { - _system->write(args.address, Y); + _bus->write(args.address, Y); } void Cpu::INY(Cpu::InstructionArgs args) { @@ -666,25 +669,25 @@ namespace nes { PC++; setFlag(InterruptDisable, true); - _system->write(STACK_BASE + SP--, PC >> 8); - _system->write(STACK_BASE + SP--, PC & 0x00FF); + _bus->write(STACK_BASE + SP--, PC >> 8); + _bus->write(STACK_BASE + SP--, PC & 0x00FF); setFlag(Break, true); - _system->write(STACK_BASE + SP--, flags); + _bus->write(STACK_BASE + SP--, flags); setFlag(Break, false); - uint16_t lo = _system->read(0xFFFE); - uint16_t hi = _system->read(0xFFFF); + uint16_t lo = _bus->read(0xFFFE); + uint16_t hi = _bus->read(0xFFFF); PC = (hi << 8) | lo; } void Cpu::RTI(Cpu::InstructionArgs args) { - flags = _system->read(STACK_BASE + ++SP); + flags = _bus->read(STACK_BASE + ++SP); setFlag(Break, false); setFlag(Unused, false); - uint16_t lo = _system->read(STACK_BASE + ++SP); - uint16_t hi = _system->read(STACK_BASE + ++SP); + uint16_t lo = _bus->read(STACK_BASE + ++SP); + uint16_t hi = _bus->read(STACK_BASE + ++SP); PC = (hi << 8) | lo; } @@ -696,12 +699,12 @@ namespace nes { } void Cpu::LSR(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); + uint8_t value = _bus->read(args.address); setFlag(Carry, value & 0x01); value = value >> 1; setFlag(Zero, value == 0); setFlag(Negative, value & 0x80); - _system->write(args.address, value); + _bus->write(args.address, value); } void Cpu::ASL_ACC(Cpu::InstructionArgs args) { @@ -712,12 +715,12 @@ namespace nes { } void Cpu::ASL(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); + uint8_t value = _bus->read(args.address); setFlag(Carry, value & 0x80); value = value << 1; setFlag(Zero, value == 0); setFlag(Negative, value & 0x80); - _system->write(args.address, value); + _bus->write(args.address, value); } void Cpu::ROR_ACC(Cpu::InstructionArgs args) { @@ -729,13 +732,13 @@ namespace nes { } void Cpu::ROR(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); + uint8_t value = _bus->read(args.address); uint8_t carryOriginal = getFlag(Carry); setFlag(Carry, value & 0x01); value = (value >> 1) | (carryOriginal << 7); setFlag(Zero, value == 0); setFlag(Negative, value & 0x80); - _system->write(args.address, value); + _bus->write(args.address, value); } void Cpu::ROL_ACC(Cpu::InstructionArgs args) { @@ -747,25 +750,25 @@ namespace nes { } void Cpu::ROL(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); + uint8_t value = _bus->read(args.address); uint8_t carryOriginal = getFlag(Carry); setFlag(Carry, value & 0x80); value = (value << 1) | carryOriginal; setFlag(Zero, value == 0); setFlag(Negative, value & 0x80); - _system->write(args.address, value); + _bus->write(args.address, value); } void Cpu::INC(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); - _system->write(args.address, ++value); + uint8_t value = _bus->read(args.address); + _bus->write(args.address, ++value); setFlag(Zero, value == 0); setFlag(Negative, value & 0x80); } void Cpu::DEC(Cpu::InstructionArgs args) { - uint8_t value = _system->read(args.address); - _system->write(args.address, --value); + uint8_t value = _bus->read(args.address); + _bus->write(args.address, --value); setFlag(Zero, value == 0); setFlag(Negative, value & 0x80); } diff --git a/src/Cpu.h b/src/Cpu.h index e013372..f040872 100644 --- a/src/Cpu.h +++ b/src/Cpu.h @@ -11,7 +11,7 @@ namespace nes { - class System; + class Bus; enum CpuFlags: uint8_t { Carry = (1 << 0), @@ -42,13 +42,14 @@ namespace nes { static constexpr uint16_t STACK_BASE = 0x0100; public: - explicit Cpu(System* system); + explicit Cpu(); void reset(); bool tick(); void setFlag(CpuFlags flag, bool value); bool getFlag(CpuFlags flag) const; void setStartAddress(uint16_t address); void nmi(); + void connectToBus(Bus* bus); #ifdef NES_LOGGING std::string state() const; @@ -56,7 +57,7 @@ namespace nes { private: size_t _ticks; - System* _system; + Bus* _bus; std::vector _instructions; private: diff --git a/src/Dma.cpp b/src/Dma.cpp index e96eca5..a7760eb 100644 --- a/src/Dma.cpp +++ b/src/Dma.cpp @@ -4,11 +4,11 @@ #include "Dma.h" #include "Ppu.h" -#include "System.h" +#include "Bus.h" namespace nes { - Dma::Dma(System *system, Ppu *ppu): _system{system}, _ppu{ppu} { + Dma::Dma(Ppu *ppu): _ppu{ppu} { } @@ -23,7 +23,7 @@ namespace nes { } } else { if(cycles % 2 == 0) { - _data = _system->read((_page << 8) | _address); + _data = _bus->read((_page << 8) | _address); } else { _ppu->writeOam(_address, _data); _address++; @@ -41,4 +41,7 @@ namespace nes { _active = true; } + void Dma::connectToBus(Bus *bus) { + _bus = bus; + } } diff --git a/src/Dma.h b/src/Dma.h index f4b298e..73ec45a 100644 --- a/src/Dma.h +++ b/src/Dma.h @@ -9,18 +9,19 @@ namespace nes { - class System; + class Bus; class Ppu; class Dma { public: - Dma(System* system, Ppu* ppu); + Dma(Ppu* ppu); [[nodiscard]] bool active() const; void tick(uint64_t cycles); void start(uint8_t page); + void connectToBus(Bus *bus); private: - System* _system; + Bus* _bus; Ppu* _ppu; private: diff --git a/src/Ppu.cpp b/src/Ppu.cpp index 37fbcab..fbd47b4 100644 --- a/src/Ppu.cpp +++ b/src/Ppu.cpp @@ -237,8 +237,8 @@ namespace nes { _frameBuffer[index] = pixel; } - void Ppu::connect(Cartridge* cartridge) { - _cartridge = cartridge; + void Ppu::connectToBus(Bus* bus) { + _bus = bus; } void Ppu::reset() { @@ -261,11 +261,11 @@ namespace nes { address &= 0x3FFF; if(address < 0x2000) { - return _cartridge->readChr(address); + return _bus->readChr(address); } else if(address >= 0x2000 && address < 0x3F00) { address &= 0x0FFF; - if(_cartridge->mirroring() == Cartridge::Mirroring::Vertical) { + if(_bus->cartridgeMirroring() == Cartridge::Mirroring::Vertical) { if (address >= 0x0000 && address <= 0x03FF) return _nameTable[address & 0x03FF]; if (address >= 0x0400 && address <= 0x07FF) @@ -305,7 +305,7 @@ namespace nes { } else if(address >= 0x2000 && address < 0x3F00) { address &= 0x0FFF; - if(_cartridge->mirroring() == Cartridge::Mirroring::Vertical) { + if(_bus->cartridgeMirroring() == Cartridge::Mirroring::Vertical) { if (address >= 0x0000 && address <= 0x03FF) _nameTable[address & 0x03FF] = value; if (address >= 0x0400 && address <= 0x07FF) diff --git a/src/Ppu.h b/src/Ppu.h index acc876b..67b362f 100644 --- a/src/Ppu.h +++ b/src/Ppu.h @@ -5,7 +5,7 @@ #ifndef NES_PPU_H #define NES_PPU_H -#include "Cartridge.h" +#include "Bus.h" #include "Shifter.h" #include "Oam.h" @@ -105,7 +105,7 @@ namespace nes { void write(uint16_t address, uint8_t value); uint8_t read(uint16_t address); void setPixel(uint16_t row, uint16_t column, Pixel pixel); - void connect(Cartridge* cartridge); + void connectToBus(Bus* bus); void reset(); void writeOam(uint8_t address, uint8_t data); uint8_t internalRead(uint16_t address); @@ -152,7 +152,7 @@ namespace nes { private: std::unique_ptr _frameBuffer; - Cartridge* _cartridge; + Bus* _bus; }; } diff --git a/src/System.cpp b/src/System.cpp index 0687bb0..4e347dd 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -20,20 +20,28 @@ namespace nes { #endif { _ram = std::make_unique(2*1024); - _cpu = std::make_unique(this); + _cpu = std::make_unique(); _ppu = std::make_unique(); - _dma = std::make_unique(this, _ppu.get()); + _dma = std::make_unique(_ppu.get()); _controller1 = std::make_shared(); + _bus = std::make_unique(_ram.get(), + _cpu.get(), + _ppu.get(), + _cartridge.get(), + _controller1.get(), + nullptr, + _dma.get()); } void System::insertCartridge(const fs::path &path, std::optional address) { _cartridge = std::make_unique(path); - _ppu->connect(_cartridge.get()); + _bus->connectCartridge(_cartridge.get()); reset(address); } void System::connect(std::shared_ptr controller) { _controller1 = std::move(controller); + _bus->connectController1(_controller1.get()); } void System::reset(std::optional address) { @@ -49,7 +57,6 @@ namespace nes { } void System::tick() { - bool needInterrupt = _ppu->tick(); #ifdef NES_LOGGING _logger.addLine(_cycles, _ppu->state()); @@ -85,51 +92,6 @@ namespace nes { _cycles++; } - uint8_t System::read(uint16_t address) { - if(address < 0x2000) { - return _ram[address & 0x07FF]; - } - else if(address >= 0x2000 && address < 0x4000) { - return _ppu->read(address & 0x0007); - } - else if (address >= 0x6000 && address < 0x8000) { - return _cartridge->readRam(address); - } - else if(address >= 0x8000) { - return _cartridge->readPrg(address); - } - else if(address == 0x4016) { - return _controller1->read(); - } - else if(address == 0x4017) { - // Controller 2 - return 0; - } - - return 0; - } - - void System::write(uint16_t address, uint8_t value) { - if(address < 0x2000) { - _ram[address & 0x07FF] = value; - } - else if(address >= 0x2000 && address < 0x4000) { - _ppu->write(address & 0x0007, value); - } - else if(address >= 0x8000) { - std::cout << "Cartridge write at address: " << address << std::endl; - } - else if(address == 0x4014) { - _dma->start(value); - } - else if(address == 0x4016) { - _controller1->poll(); - } - else if(address == 0x4017) { - // Controller 2 - } - } - // For debug // Calc "hash" - just sum of the bytes of RAM // Can be useful for detecting changes in memory diff --git a/src/System.h b/src/System.h index f99a334..70f6eea 100644 --- a/src/System.h +++ b/src/System.h @@ -10,6 +10,7 @@ #include "Ppu.h" #include "Cartridge.h" #include "Dma.h" +#include "Bus.h" #include #include @@ -30,8 +31,6 @@ namespace nes { void setNewFrameCallback(std::function onNewFrame); void tick(); - uint8_t read(uint16_t address); - void write(uint16_t address, uint8_t value); [[nodiscard]] uint32_t zpHash() const; private: @@ -42,6 +41,7 @@ namespace nes { std::unique_ptr _cartridge; std::shared_ptr _controller1; std::unique_ptr _dma; + std::unique_ptr _bus; #ifdef NES_LOGGING Logger _logger;