Adding DMA for OAM

This commit is contained in:
Selim Mustafaev 2023-09-23 14:26:27 +03:00
parent cf0a1a5cfe
commit c1bd4c863f
8 changed files with 103 additions and 8 deletions

View File

@ -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)

View File

@ -20,7 +20,7 @@ int main() {
while(SDL_PollEvent(&e));
});
device.connect(std::make_shared<SdlKeyboardController>());
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");

44
src/Dma.cpp Normal file
View File

@ -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;
}
}

38
src/Dma.h Normal file
View File

@ -0,0 +1,38 @@
//
// Created by selim on 9/23/23.
//
#ifndef NES_DMA_H
#define NES_DMA_H
#include <cstdint>
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

View File

@ -22,6 +22,7 @@ namespace nes {
_ram = std::make_unique<uint8_t[]>(2*1024);
_cpu = std::make_unique<Cpu>(this);
_ppu = std::make_unique<Ppu>();
_dma = std::make_unique<Dma>(this, _ppu.get());
}
void Nes::insertCartridge(const fs::path &path, std::optional<uint16_t> 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();

View File

@ -9,6 +9,7 @@
#include "Cpu.h"
#include "Ppu.h"
#include "Cartridge.h"
#include "Dma.h"
#include <filesystem>
#include <optional>
@ -40,6 +41,7 @@ namespace nes {
std::unique_ptr<Ppu> _ppu;
std::unique_ptr<Cartridge> _cartridge;
std::shared_ptr<Controller> _controller1;
std::unique_ptr<Dma> _dma;
#ifdef NES_LOGGING
Logger _logger;

View File

@ -415,4 +415,9 @@ namespace nes {
_bgAttribShifter._lo,
_bgAttribShifter._hi);
}
void Ppu::writeOam(uint8_t address, uint8_t data) {
auto oamPtr = reinterpret_cast<uint8_t*>(_oamData.get());
oamPtr[address] = data;
}
}

View File

@ -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<void(const Pixel*)> onNewFrame;