Adding DMA for OAM
This commit is contained in:
parent
cf0a1a5cfe
commit
c1bd4c863f
@ -26,7 +26,7 @@ add_executable(nes
|
|||||||
src/Controller.cpp
|
src/Controller.cpp
|
||||||
src/Controller.h
|
src/Controller.h
|
||||||
src/SdlKeyboardController.cpp
|
src/SdlKeyboardController.cpp
|
||||||
src/SdlKeyboardController.h)
|
src/SdlKeyboardController.h src/Dma.cpp src/Dma.h)
|
||||||
|
|
||||||
find_package(SDL2 CONFIG REQUIRED)
|
find_package(SDL2 CONFIG REQUIRED)
|
||||||
find_package(fmt REQUIRED)
|
find_package(fmt REQUIRED)
|
||||||
|
|||||||
2
main.cpp
2
main.cpp
@ -20,7 +20,7 @@ int main() {
|
|||||||
while(SDL_PollEvent(&e));
|
while(SDL_PollEvent(&e));
|
||||||
});
|
});
|
||||||
device.connect(std::make_shared<SdlKeyboardController>());
|
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("/Users/selim/Documents/nestest.nes");
|
||||||
//device.insertCartridge("C:\\Users\\selim\\Documents\\nestest.nes");
|
//device.insertCartridge("C:\\Users\\selim\\Documents\\nestest.nes");
|
||||||
|
|
||||||
|
|||||||
44
src/Dma.cpp
Normal file
44
src/Dma.cpp
Normal 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
38
src/Dma.h
Normal 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
|
||||||
@ -22,6 +22,7 @@ namespace nes {
|
|||||||
_ram = std::make_unique<uint8_t[]>(2*1024);
|
_ram = std::make_unique<uint8_t[]>(2*1024);
|
||||||
_cpu = std::make_unique<Cpu>(this);
|
_cpu = std::make_unique<Cpu>(this);
|
||||||
_ppu = std::make_unique<Ppu>();
|
_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) {
|
void Nes::insertCartridge(const fs::path &path, std::optional<uint16_t> address) {
|
||||||
@ -54,6 +55,9 @@ namespace nes {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(_cycles % 3 == 0) {
|
if(_cycles % 3 == 0) {
|
||||||
|
if(_dma->active()) {
|
||||||
|
_dma->tick(_cycles);
|
||||||
|
} else {
|
||||||
bool instructionExecuted = _cpu->tick();
|
bool instructionExecuted = _cpu->tick();
|
||||||
#ifdef NES_LOGGING
|
#ifdef NES_LOGGING
|
||||||
if(instructionExecuted) {
|
if(instructionExecuted) {
|
||||||
@ -61,6 +65,7 @@ namespace nes {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(needInterrupt) {
|
if(needInterrupt) {
|
||||||
_cpu->nmi();
|
_cpu->nmi();
|
||||||
@ -111,7 +116,7 @@ namespace nes {
|
|||||||
std::cout << "Cartridge write at address: " << address << std::endl;
|
std::cout << "Cartridge write at address: " << address << std::endl;
|
||||||
}
|
}
|
||||||
else if(address == 0x4014) {
|
else if(address == 0x4014) {
|
||||||
// DMA
|
_dma->start(value);
|
||||||
}
|
}
|
||||||
else if(address == 0x4016) {
|
else if(address == 0x4016) {
|
||||||
_controller1->poll();
|
_controller1->poll();
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "Cpu.h"
|
#include "Cpu.h"
|
||||||
#include "Ppu.h"
|
#include "Ppu.h"
|
||||||
#include "Cartridge.h"
|
#include "Cartridge.h"
|
||||||
|
#include "Dma.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -40,6 +41,7 @@ namespace nes {
|
|||||||
std::unique_ptr<Ppu> _ppu;
|
std::unique_ptr<Ppu> _ppu;
|
||||||
std::unique_ptr<Cartridge> _cartridge;
|
std::unique_ptr<Cartridge> _cartridge;
|
||||||
std::shared_ptr<Controller> _controller1;
|
std::shared_ptr<Controller> _controller1;
|
||||||
|
std::unique_ptr<Dma> _dma;
|
||||||
|
|
||||||
#ifdef NES_LOGGING
|
#ifdef NES_LOGGING
|
||||||
Logger _logger;
|
Logger _logger;
|
||||||
|
|||||||
@ -415,4 +415,9 @@ namespace nes {
|
|||||||
_bgAttribShifter._lo,
|
_bgAttribShifter._lo,
|
||||||
_bgAttribShifter._hi);
|
_bgAttribShifter._hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ppu::writeOam(uint8_t address, uint8_t data) {
|
||||||
|
auto oamPtr = reinterpret_cast<uint8_t*>(_oamData.get());
|
||||||
|
oamPtr[address] = data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +112,8 @@ namespace nes {
|
|||||||
void setPixel(uint16_t row, uint16_t column, Pixel pixel);
|
void setPixel(uint16_t row, uint16_t column, Pixel pixel);
|
||||||
void connect(Cartridge* cartridge);
|
void connect(Cartridge* cartridge);
|
||||||
void reset();
|
void reset();
|
||||||
std::string state() const;
|
[[nodiscard]] std::string state() const;
|
||||||
|
void writeOam(uint8_t address, uint8_t data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::function<void(const Pixel*)> onNewFrame;
|
std::function<void(const Pixel*)> onNewFrame;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user