PPU_CTRL, PPU_STATUS

This commit is contained in:
william 2024-05-13 17:37:36 -04:00
parent d5fba04314
commit 1bc9d4950f
3 changed files with 94 additions and 30 deletions

View File

@ -22,7 +22,7 @@ byte mem_get_byte(address addr) {
if (addr >= RAM_MAX_ADDR && addr < PPU_MAX_ADDR) { if (addr >= RAM_MAX_ADDR && addr < PPU_MAX_ADDR) {
byte reg = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE; byte reg = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
ppu_sig_read_register(reg); return ppu_read_reg(reg);
} }
return ram[addr]; return ram[addr];
@ -57,14 +57,7 @@ void mem_set_byte(address addr, byte byte) {
} }
} else if (addr < PPU_MAX_ADDR) { } else if (addr < PPU_MAX_ADDR) {
address reg_addr = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE; address reg_addr = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
ppu_write_reg(reg_addr, byte);
int bank_count = (PPU_MAX_ADDR - RAM_MAX_ADDR) / PPU_BANK_SIZE;
for (int i = 0; i < bank_count; i++) {
address ram_addr = reg_addr + PPU_BANK_SIZE * i + RAM_MAX_ADDR;
ram[ram_addr] = byte;
}
ppu_sig_write_register(reg_addr);
} else { } else {
ram[addr] = byte; ram[addr] = byte;

View File

@ -12,6 +12,10 @@
#define PPU_REGISTER_SIZE 0x8 #define PPU_REGISTER_SIZE 0x8
#define PPU_VRAM_SIZE 0x4000 #define PPU_VRAM_SIZE 0x4000
#define PPU_OAM_SIZE 0xff #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_CTRL 0x00
#define PPU_REGISTER_MASK 0x01 #define PPU_REGISTER_MASK 0x01
@ -22,6 +26,8 @@
#define PPU_REGISTER_ADDR 0x06 #define PPU_REGISTER_ADDR 0x06
#define PPU_REGISTER_DATA 0x07 #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_BASE_NAMETABLE_ADDR 0x3
#define PPU_CTRL_VRAM_ADDR_INCREMENT 0x4 #define PPU_CTRL_VRAM_ADDR_INCREMENT 0x4
#define PPU_CTRL_SP_PATTERN_TABLE_ADDR 0x8 #define PPU_CTRL_SP_PATTERN_TABLE_ADDR 0x8
@ -56,8 +62,6 @@ typedef struct ppu {
address t; address t;
byte x; byte x;
bool w; bool w;
} PPU; } PPU;
PPU *ppu_get_state(); PPU *ppu_get_state();
@ -93,8 +97,11 @@ bool ppu_read_flag(size_t reg, byte mask);
* @param reg The register index * @param reg The register index
* @param mask The value mask * @param mask The value mask
*/ */
void ppu_sig_read_register(byte reg); //void ppu_sig_read_register(byte reg);
//
//void ppu_sig_write_register(byte reg);
void ppu_sig_write_register(byte reg); byte ppu_read_reg(byte reg);
void ppu_write_reg(byte reg, byte data);
#endif //NESEMULATOR_PPU_H #endif //NESEMULATOR_PPU_H

View File

@ -14,6 +14,7 @@
// 10. This is where I'm stuck. I think I need to read the "sprites" section of https://wiki.nesdev.com/w/index.php/PPU_rendering very carefully. // 10. This is where I'm stuck. I think I need to read the "sprites" section of https://wiki.nesdev.com/w/index.php/PPU_rendering very carefully.
// //
#include <assert.h>
#include "../include/ppu.h" #include "../include/ppu.h"
#include "../cpu/cpu.h" #include "../cpu/cpu.h"
@ -98,31 +99,94 @@ bool ppu_read_flag(size_t reg, byte mask) {
return ppu_state.registers[reg] & mask; return ppu_state.registers[reg] & mask;
} }
//byte ppu_sig_read_register(size_t reg, byte mask) { byte ppu_read_reg(byte reg) {
// return ppu_state.registers[reg] & mask; assert(reg >= 0);
//} assert(reg <= PPU_REGISTER_SIZE);
void ppu_sig_read_register(byte reg) {
if (reg == PPU_REGISTER_STATUS) { if (reg == PPU_REGISTER_STATUS) {
ppu_state.w = false; ppu_state.w = false;
ppu_state.registers[PPU_REGISTER_STATUS] &= ~PPU_STATUS_VBLANK;
}
if (reg == PPU_REGISTER_DATA) {
// Access to VRAM memory is slow, so reading it a first time generally return the memory at the previous address.
// So we get the data first, then update the register.
byte data = ppu_state.registers[reg];
ppu_state.registers[reg] = ppu_state.vram[ppu_state.v];
if (ppu_state.v > 0x3eff) {
// But the palette data is returned immediately
data = ppu_state.registers[reg];
}
// We then need to increment the VRAM address
byte increment = 1;
if (ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_VRAM_ADDR_INCREMENT)) {
increment = 32;
}
ppu_state.v += increment;
if (ppu_state.v >= PPU_VRAM_SIZE) {
ppu_state.v -= PPU_VRAM_SIZE;
}
return data;
}
return ppu_state.registers[reg];
}
void ppu_write_reg_ram(byte reg, byte data) {
byte *ppu_ram = mem_get_ptr(PPU_RAM_BASE_ADDR);
for (int i = 0; i < PPU_RAM_BANK_COUNT; i++) {
byte ram_offset = (i * PPU_RAM_BANK_SIZE) + reg;
*(ppu_ram + ram_offset) = data;
} }
} }
void ppu_sig_write_register(byte reg) { void ppu_write_reg(byte reg, byte data) {
if (reg == PPU_REGISTER_ADDR) { ppu_state.registers[reg] = data;
byte addr_write = ppu_state.registers[PPU_REGISTER_ADDR];
if (!ppu_state.w) { if (reg == PPU_REGISTER_CTRL && ppu_read_flag(PPU_REGISTER_STATUS, PPU_STATUS_VBLANK) &&
ppu_state.v &= (addr_write << 8) | 0x0f; !ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_GEN_VBLANK_NMI) &&
data & PPU_CTRL_GEN_VBLANK_NMI) {
// The VBlank flag is still set, and the GEN_VBLANK_NMI was set from 0 to 1
cpu_trigger_nmi();
} else if (reg == PPU_REGISTER_SCROLL || reg == PPU_REGISTER_ADDR) {
ppu_state.
w = !ppu_state.w;
} else if (reg == PPU_REGISTER_ADDR) {
address addr = ppu_state.v;
if (ppu_state.w) {
addr &= 0xff &
data;
} else { } else {
ppu_state.v &= 0xff & addr_write; addr &= (data << 8) | 0x0f;
}
} }
if (reg == PPU_REGISTER_SCROLL || reg == PPU_REGISTER_ADDR) { if (addr >= PPU_VRAM_SIZE) {
ppu_state.w = !ppu_state.w; addr -= PPU_VRAM_SIZE;
}
ppu_state.
v = addr;
} else if (reg == PPU_REGISTER_DATA) {
ppu_state.vram[ppu_state.v] =
data;
byte increment = 1;
if (ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_VRAM_ADDR_INCREMENT)) {
increment = 32;
} }
if (reg == PPU_REGISTER_OAM_DATA) { ppu_state.v +=
ppu_state.registers[PPU_REGISTER_OAM_ADDR]++; increment;
if (ppu_state.v >= PPU_VRAM_SIZE) {
ppu_state.v -= PPU_VRAM_SIZE;
} }
} else if (reg == PPU_REGISTER_OAM_DATA) {
byte oam_addr = ppu_state.registers[PPU_REGISTER_OAM_ADDR];
ppu_write_reg(PPU_REGISTER_OAM_ADDR, oam_addr + 1);
}
ppu_write_reg_ram(reg, data);
} }