// // Created by william on 12/30/23. // #include #include #include "types.h" #ifndef NESEMULATOR_PPU_H #define NESEMULATOR_PPU_H #define PPU_REGISTER_SIZE 0x8 #define PPU_VRAM_SIZE 0x4000 #define PPU_OAM_SIZE 0xff #define PPU_RAM_BASE_ADDR 0x2000 #define PPU_RAM_MAX_ADDR 0x4000 #define PPU_RAM_BANK_SIZE 0x8 #define PPU_RAM_BANK_COUNT ((PPU_RAM_MAX_ADDR - PPU_RAM_BASE_ADDR) / PPU_RAM_BANK_SIZE) #define PPU_REGISTER_CTRL 0x00 #define PPU_REGISTER_MASK 0x01 #define PPU_REGISTER_STATUS 0x02 #define PPU_REGISTER_OAM_ADDR 0x03 #define PPU_REGISTER_OAM_DATA 0x04 #define PPU_REGISTER_SCROLL 0x05 #define PPU_REGISTER_ADDR 0x06 #define PPU_REGISTER_DATA 0x07 #define PPU_CTRL_SCROLL_X 0x1 #define PPU_CTRL_SCROLL_Y 0x2 #define PPU_CTRL_BASE_NAMETABLE_ADDR 0x3 #define PPU_CTRL_VRAM_ADDR_INCREMENT 0x4 #define PPU_CTRL_SP_PATTERN_TABLE_ADDR 0x8 #define PPU_CTRL_BG_PATTERN_TABLE_ADDR 0x10 #define PPU_CTRL_SP_SIZE 0x20 #define PPU_CTRL_MODE_SELECT 0x40 #define PPU_CTRL_GEN_VBLANK_NMI 0x80 #define PPU_MASK_GREYSCALE 0x1 #define PPU_MASK_SHOW_BG_LEFT 0x2 #define PPU_MASK_SHOW_SP_LEFT 0x4 #define PPU_MASK_SHOW_BG 0x8 #define PPU_MASK_SHOW_SP 0x10 #define PPU_MASK_EMP_RED 0x20 #define PPU_MASK_EMP_GREEN 0x40 #define PPU_MASK_EMP_BLUE 0x80 #define PPU_STATUS_OPEN_BUS 0x1f #define PPU_STATUS_SP_OVERFLOW 0x20 #define PPU_STATUS_SP_0_HIT 0x40 #define PPU_STATUS_VBLANK 0x80 #define PPU_MASK_NONE 0xff #define PATTERN_TABLE_BYTES_SIZE 0x1000 #define NAMETABLE_BYTES_SIZE 0x0400 #define PALETTE_TABLE_BYTES_SIZE 0x0020 typedef struct ppu_memory { byte nametable_0[NAMETABLE_BYTES_SIZE]; byte nametable_1[NAMETABLE_BYTES_SIZE]; byte palette[PALETTE_TABLE_BYTES_SIZE]; } PPUMemory; typedef struct ppu_tile_fetch { byte tile_id; byte attribute_table; byte pattern_table_tile_low; byte pattern_table_tile_high; } PPUTileFetch; #if DEBUG typedef union { struct { byte tile_debugger: 1; byte tile_debugger_pattern_half: 2; } flags; byte flags_byte; } PPUDebugFlags; #endif typedef struct ppu { PPUMemory memory; pixel pixels[256 * 240]; byte registers[8]; byte oam_dma_register; byte oam[PPU_OAM_SIZE]; bool odd_frame; byte x_scroll; byte fine_x_scroll; byte y_scroll; byte x; bool w; byte ppu_addr_increment; address ppu_address; address temp_ppu_addr; address bg_pattern_table_addr; PPUTileFetch fetch; unsigned long frame; unsigned int scanline; unsigned int cycle; #if DEBUG PPUDebugFlags debug; #endif } PPU; PPU *ppu_get_state(); /** * Initializes the PPU, according to the power up state. * https://www.nesdev.org/wiki/PPU_power_up_state * * @param ppu */ void ppu_init(); /** * Cycles the PPU. * * @param ppu * @param ram */ void ppu_cycle(); /** * Read a flag from the PPU registers. * * @param reg The register index * @param mask The flag mask */ bool ppu_read_flag(size_t reg, byte mask); byte ppu_read_reg(byte reg); void ppu_write_reg(byte reg, byte data); void ppu_write_oamaddr(byte data); void ppu_write(address addr, byte data); #endif //NESEMULATOR_PPU_H