Adding SDL window with static noise, generated by PPU
This commit is contained in:
parent
7a954c705e
commit
db3b744ab2
36
main.cpp
36
main.cpp
@ -1,28 +1,28 @@
|
||||
#include "src/Nes.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "src/Window.h"
|
||||
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
int main() {
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
nes::Nes device;
|
||||
nes::SdlWindow window(nes::Ppu::SCREEN_WIDTH, nes::Ppu::SCREEN_HEIGHT);
|
||||
|
||||
// std::stringstream ss;
|
||||
// ss << "A2 0A 8E 00 00 A2 03 8E 01 00 AC 00 00 A9 00 18 6D 01 00 88 D0 FA 8D 02 00 EA EA EA";
|
||||
// uint16_t nOffset = 0x8000;
|
||||
// while (!ss.eof())
|
||||
// {
|
||||
// std::string b;
|
||||
// ss >> b;
|
||||
// device.write(nOffset++, (uint8_t)std::stoul(b, nullptr, 16));
|
||||
// }
|
||||
//
|
||||
// // Set Reset Vector
|
||||
// device.write(0xFFFC, 0x00);
|
||||
// device.write(0xFFFD, 0x80);
|
||||
//
|
||||
// device.reset();
|
||||
device.setNewFrameCallback(std::bind(&nes::SdlWindow::drawFrame, &window, _1));
|
||||
device.insertCartridge("/home/selim/Downloads/nestest.nes");
|
||||
|
||||
device.runRom("/home/selim/Downloads/nestest.nes", 0xC000);
|
||||
uint64_t cycles = 0;
|
||||
while (cycles < 1000000000) {
|
||||
device.tick();
|
||||
cycles++;
|
||||
|
||||
//int64_t us = static_cast<int64_t>(1000000000.0/(60*nes::Ppu::SCREEN_WIDTH*nes::Ppu::SCREEN_HEIGHT));
|
||||
//std::this_thread::sleep_for(std::chrono::nanoseconds(1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ namespace nes {
|
||||
return _ram[address & 0x07FF];
|
||||
}
|
||||
else if(address >= 0x2000 && address < 0x4000) {
|
||||
std::cout << "PPU read at address: " << address << std::endl;
|
||||
//std::cout << "PPU read at address: " << address << std::endl;
|
||||
return _ppu->read(address & 0x0007);
|
||||
}
|
||||
else if(address >= 0x8000) {
|
||||
|
||||
23
src/Nes.cpp
23
src/Nes.cpp
@ -6,15 +6,16 @@
|
||||
#include "Cartridge.h"
|
||||
#include "Cpu.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
namespace nes {
|
||||
|
||||
Nes::Nes() {
|
||||
Nes::Nes(): _cycles{} {
|
||||
_cpu = std::make_unique<Cpu>();
|
||||
_ppu = std::make_shared<Ppu>();
|
||||
}
|
||||
|
||||
void Nes::runRom(const fs::path &path, std::optional<uint16_t> address) {
|
||||
void Nes::insertCartridge(const fs::path &path, std::optional<uint16_t> address) {
|
||||
_cartridge = std::make_shared<Cartridge>(path);
|
||||
_cpu->bus()->connect(_cartridge);
|
||||
_cpu->bus()->connect(_ppu);
|
||||
@ -23,21 +24,21 @@ namespace nes {
|
||||
|
||||
void Nes::reset(std::optional<uint16_t> address) {
|
||||
_cpu->reset();
|
||||
|
||||
if(address) {
|
||||
_cpu->setStartAddress(address.value());
|
||||
}
|
||||
}
|
||||
|
||||
size_t ticks = 0;
|
||||
while (ticks <= 15000) {
|
||||
void Nes::setNewFrameCallback(std::function<void(const Pixel *)> onNewFrame) {
|
||||
_ppu->onNewFrame = std::move(onNewFrame);
|
||||
}
|
||||
|
||||
void Nes::tick() {
|
||||
_ppu->tick();
|
||||
if(ticks % 3 == 0) {
|
||||
if(_cycles % 3 == 0) {
|
||||
_cpu->tick();
|
||||
}
|
||||
ticks++;
|
||||
}
|
||||
|
||||
std::cout << "The end" << std::endl;
|
||||
_cycles++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,10 +19,13 @@ namespace nes {
|
||||
class Nes {
|
||||
public:
|
||||
Nes();
|
||||
void runRom(const fs::path& path, std::optional<uint16_t> address = std::nullopt);
|
||||
void insertCartridge(const fs::path& path, std::optional<uint16_t> address = std::nullopt);
|
||||
void reset(std::optional<uint16_t> address = std::nullopt);
|
||||
void setNewFrameCallback(std::function<void(const Pixel*)> onNewFrame);
|
||||
void tick();
|
||||
|
||||
private:
|
||||
uint64_t _cycles;
|
||||
std::unique_ptr<Cpu> _cpu;
|
||||
std::shared_ptr<Ppu> _ppu;
|
||||
std::shared_ptr<Cartridge> _cartridge;
|
||||
|
||||
@ -12,7 +12,12 @@ namespace nes {
|
||||
|
||||
void Ppu::tick() {
|
||||
|
||||
setPixel(_scanline, _column, {});
|
||||
if(_column < SCREEN_WIDTH && _scanline < SCREEN_HEIGHT && _scanline >= 0) {
|
||||
Pixel black = {0, 0, 0, 100};
|
||||
Pixel white = {255, 255, 255, 100};
|
||||
Pixel pixel = std::rand() % 2 == 0 ? black : white;
|
||||
setPixel(_scanline, _column, pixel);
|
||||
}
|
||||
|
||||
_column++;
|
||||
if(_column >= 341) {
|
||||
|
||||
@ -6,4 +6,26 @@
|
||||
|
||||
namespace nes {
|
||||
|
||||
SdlWindow::SdlWindow(uint16_t width, uint16_t height): _width(width), _height(height) {
|
||||
int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
|
||||
if(res < 0) throw std::runtime_error("Error initializing SDL");
|
||||
|
||||
Uint32 flags = SDL_WINDOW_ALLOW_HIGHDPI; //| SDL_WINDOW_VULKAN | SDL_WINDOW_METAL;
|
||||
_wnd.reset(SDL_CreateWindow("NES", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags));
|
||||
if(!_wnd) throw std::runtime_error("Error creating SDL window");
|
||||
|
||||
_renderer.reset(SDL_CreateRenderer(_wnd.get(), -1, 0));
|
||||
if(!_renderer) throw std::runtime_error("Error creating SDL renderer");
|
||||
|
||||
_texture.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height));
|
||||
if(!_texture) throw std::runtime_error("Error creating SDL texture");
|
||||
}
|
||||
|
||||
void SdlWindow::drawFrame(const Pixel *buffer) {
|
||||
int pitch = static_cast<int>(_width*sizeof(Pixel));
|
||||
SDL_UpdateTexture(_texture.get(), nullptr, buffer, pitch);
|
||||
SDL_RenderClear(_renderer.get());
|
||||
SDL_RenderCopy(_renderer.get(), _texture.get(), nullptr, nullptr);
|
||||
SDL_RenderPresent(_renderer.get());
|
||||
}
|
||||
}
|
||||
26
src/Window.h
26
src/Window.h
@ -5,12 +5,36 @@
|
||||
#ifndef NES_WINDOW_H
|
||||
#define NES_WINDOW_H
|
||||
|
||||
#include "Ppu.h"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <memory>
|
||||
|
||||
namespace nes {
|
||||
|
||||
class Window {
|
||||
class SdlWindow {
|
||||
public:
|
||||
struct SdlDeleter {
|
||||
void operator()(SDL_Window* ptr) { SDL_DestroyWindow(ptr); }
|
||||
void operator()(SDL_Renderer* ptr) { SDL_DestroyRenderer(ptr); }
|
||||
void operator()(SDL_Texture* ptr) { SDL_DestroyTexture(ptr); }
|
||||
};
|
||||
|
||||
template<typename T> using SdlUniquePtr = std::unique_ptr<T, SdlDeleter>;
|
||||
using SdlWindowPtr = SdlUniquePtr<SDL_Window>;
|
||||
using SdlRendererPtr = SdlUniquePtr<SDL_Renderer>;
|
||||
using SdlTexturePtr = SdlUniquePtr<SDL_Texture>;
|
||||
|
||||
public:
|
||||
SdlWindow(uint16_t width, uint16_t height);
|
||||
void drawFrame(const Pixel* buffer);
|
||||
|
||||
private:
|
||||
uint16_t _width;
|
||||
uint16_t _height;
|
||||
SdlWindowPtr _wnd;
|
||||
SdlRendererPtr _renderer;
|
||||
SdlTexturePtr _texture;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user