From c1bd4c863ffc811c7a5881c45fae15e5d4eea086 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Sat, 23 Sep 2023 14:26:27 +0300 Subject: [PATCH] Adding DMA for OAM --- CMakeLists.txt | 2 +- main.cpp | 2 +- src/Dma.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/Dma.h | 38 ++++++++++++++++++++++++++++++++++++++ src/Nes.cpp | 15 ++++++++++----- src/Nes.h | 2 ++ src/Ppu.cpp | 5 +++++ src/Ppu.h | 3 ++- 8 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 src/Dma.cpp create mode 100644 src/Dma.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ab8c120..f5c1d56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ add_executable(nes src/Controller.cpp src/Controller.h src/SdlKeyboardController.cpp - src/SdlKeyboardController.h) + src/SdlKeyboardController.h src/Dma.cpp src/Dma.h) find_package(SDL2 CONFIG REQUIRED) find_package(fmt REQUIRED) diff --git a/main.cpp b/main.cpp index 0330a9d..9189efe 100644 --- a/main.cpp +++ b/main.cpp @@ -20,7 +20,7 @@ int main() { while(SDL_PollEvent(&e)); }); device.connect(std::make_shared()); - device.insertCartridge("/home/selim/Downloads/smb.nes"); + device.insertCartridge("/home/selim/Downloads/dk.nes"); //device.insertCartridge("/Users/selim/Documents/nestest.nes"); //device.insertCartridge("C:\\Users\\selim\\Documents\\nestest.nes"); diff --git a/src/Dma.cpp b/src/Dma.cpp new file mode 100644 index 0000000..cb07d40 --- /dev/null +++ b/src/Dma.cpp @@ -0,0 +1,44 @@ +// +// Created by selim on 9/23/23. +// + +#include "Dma.h" +#include "Ppu.h" +#include "Nes.h" + +namespace nes { + + Dma::Dma(Nes *system, Ppu *ppu): _system{system}, _ppu{ppu} { + + } + + bool Dma::active() const { + return _active; + } + + void Dma::tick(uint64_t cycles) { + if(_dummy) { + if(cycles % 2 == 1) { + _dummy = false; + } + } else { + if(cycles % 2 == 0) { + _data = _system->read((_page << 8) | _address); + } else { + _ppu->writeOam(_address, _data); + _address++; + + if(_address == 0) { + _active = false; + _dummy = true; + } + } + } + } + + void Dma::start(uint8_t page) { + _page = page; + _active = true; + } + +} diff --git a/src/Dma.h b/src/Dma.h new file mode 100644 index 0000000..0becb15 --- /dev/null +++ b/src/Dma.h @@ -0,0 +1,38 @@ +// +// Created by selim on 9/23/23. +// + +#ifndef NES_DMA_H +#define NES_DMA_H + +#include + +namespace nes { + + class Nes; + class Ppu; + + class Dma { + public: + Dma(Nes* system, Ppu* ppu); + [[nodiscard]] bool active() const; + void tick(uint64_t cycles); + void start(uint8_t page); + + private: + Nes* _system; + Ppu* _ppu; + + private: + uint8_t _page = 0; + uint8_t _address = 0; + uint8_t _data = 0; + + private: + bool _active = false; + bool _dummy = true; + }; + +} + +#endif //NES_DMA_H diff --git a/src/Nes.cpp b/src/Nes.cpp index e5e8e6d..8a286d2 100644 --- a/src/Nes.cpp +++ b/src/Nes.cpp @@ -22,6 +22,7 @@ namespace nes { _ram = std::make_unique(2*1024); _cpu = std::make_unique(this); _ppu = std::make_unique(); + _dma = std::make_unique(this, _ppu.get()); } void Nes::insertCartridge(const fs::path &path, std::optional address) { @@ -54,12 +55,16 @@ namespace nes { #endif if(_cycles % 3 == 0) { - bool instructionExecuted = _cpu->tick(); + if(_dma->active()) { + _dma->tick(_cycles); + } else { + bool instructionExecuted = _cpu->tick(); #ifdef NES_LOGGING - if(instructionExecuted) { - _logger.addLine(_cycles, _cpu->state()); - } + if(instructionExecuted) { + _logger.addLine(_cycles, _cpu->state()); + } #endif + } } if(needInterrupt) { @@ -111,7 +116,7 @@ namespace nes { std::cout << "Cartridge write at address: " << address << std::endl; } else if(address == 0x4014) { - // DMA + _dma->start(value); } else if(address == 0x4016) { _controller1->poll(); diff --git a/src/Nes.h b/src/Nes.h index f8a1f74..38759f6 100644 --- a/src/Nes.h +++ b/src/Nes.h @@ -9,6 +9,7 @@ #include "Cpu.h" #include "Ppu.h" #include "Cartridge.h" +#include "Dma.h" #include #include @@ -40,6 +41,7 @@ namespace nes { std::unique_ptr _ppu; std::unique_ptr _cartridge; std::shared_ptr _controller1; + std::unique_ptr _dma; #ifdef NES_LOGGING Logger _logger; diff --git a/src/Ppu.cpp b/src/Ppu.cpp index 4116cb4..1c9ee90 100644 --- a/src/Ppu.cpp +++ b/src/Ppu.cpp @@ -415,4 +415,9 @@ namespace nes { _bgAttribShifter._lo, _bgAttribShifter._hi); } + + void Ppu::writeOam(uint8_t address, uint8_t data) { + auto oamPtr = reinterpret_cast(_oamData.get()); + oamPtr[address] = data; + } } \ No newline at end of file diff --git a/src/Ppu.h b/src/Ppu.h index d3bd7fd..7ae3c9f 100644 --- a/src/Ppu.h +++ b/src/Ppu.h @@ -112,7 +112,8 @@ namespace nes { void setPixel(uint16_t row, uint16_t column, Pixel pixel); void connect(Cartridge* cartridge); void reset(); - std::string state() const; + [[nodiscard]] std::string state() const; + void writeOam(uint8_t address, uint8_t data); public: std::function onNewFrame;