nes/src/Ppu.h
2023-09-03 16:03:08 +03:00

131 lines
3.3 KiB
C++

//
// Created by selim on 8/22/23.
//
#ifndef NES_PPU_H
#define NES_PPU_H
#include "Cartridge.h"
#include <cstdint>
#include <memory>
#include <functional>
namespace nes {
struct Pixel {
uint8_t R = 0;
uint8_t G = 0;
uint8_t B = 0;
uint8_t A = 0xFF;
};
class Ppu {
public:
static constexpr uint16_t SCREEN_WIDTH = 256;
static constexpr uint16_t SCREEN_HEIGHT = 240;
enum ControlAddress: uint16_t {
Control = 0x0000,
Mask = 0x0001,
Status = 0x0002,
OamAddress = 0x0003,
OamData = 0x0004,
Scroll = 0x0005,
PpuAddress = 0x0006,
PpuData = 0x0007
};
union StatusRegister {
struct {
uint8_t unused: 5;
uint8_t spriteOverflow: 1;
uint8_t spriteZeroHit: 1;
uint8_t verticalBlank: 1;
};
uint8_t value;
};
union ControlRegister {
struct {
uint8_t nameTableX: 1;
uint8_t nameTableY: 1;
uint8_t incrementMode: 1;
uint8_t patternSprite: 1;
uint8_t patternBackground: 1;
uint8_t spriteSize: 1;
uint8_t slaveMode: 1;
uint8_t enableNmi: 1;
};
uint8_t value;
};
union MaskRegister {
struct {
uint8_t grayscale: 1;
uint8_t renderBackgroundLeft: 1;
uint8_t renderSpritesLeft: 1;
uint8_t renderBackground: 1;
uint8_t renderSprites: 1;
uint8_t enhanceRed: 1;
uint8_t enhanceGreen: 1;
uint8_t enhanceBlue: 1;
};
uint8_t value;
};
union LoopyRegister {
struct {
uint8_t coarseX : 5;
uint8_t coarseY : 5;
uint8_t nameTableX : 1;
uint8_t nameTableY : 1;
uint8_t fineY : 3;
uint8_t unused : 1;
};
uint16_t value;
};
public:
Ppu();
bool tick();
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(std::shared_ptr<Cartridge> cartridge);
public:
std::function<void(const Pixel*)> onNewFrame;
private:
uint8_t internalRead(uint16_t address);
void internalWrite(uint16_t address, uint8_t value);
Pixel getColor(uint8_t palette, uint8_t pixel);
private:
int16_t _column;
int16_t _scanline;
StatusRegister _status;
ControlRegister _control;
MaskRegister _mask;
LoopyRegister _vRamAddress;
LoopyRegister _tRamAddress;
bool _addressWriteInProgress;
uint8_t _dataTemp;
uint8_t _fineX;
private:
std::unique_ptr<uint8_t[]> _nameTable;
std::unique_ptr<Pixel[]> _palette;
std::unique_ptr<uint8_t[]> _paletteTable;
private:
std::unique_ptr<Pixel[]> _frameBuffer;
std::shared_ptr<Cartridge> _cartridge;
};
}
#endif //NES_PPU_H