PPU_CTRL, PPU_STATUS
This commit is contained in:
parent
d5fba04314
commit
1bc9d4950f
11
cpu/memory.c
11
cpu/memory.c
|
@ -22,7 +22,7 @@ byte mem_get_byte(address addr) {
|
|||
|
||||
if (addr >= RAM_MAX_ADDR && addr < PPU_MAX_ADDR) {
|
||||
byte reg = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
|
||||
ppu_sig_read_register(reg);
|
||||
return ppu_read_reg(reg);
|
||||
}
|
||||
|
||||
return ram[addr];
|
||||
|
@ -57,14 +57,7 @@ void mem_set_byte(address addr, byte byte) {
|
|||
}
|
||||
} else if (addr < PPU_MAX_ADDR) {
|
||||
address reg_addr = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
|
||||
|
||||
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);
|
||||
ppu_write_reg(reg_addr, byte);
|
||||
} else {
|
||||
ram[addr] = byte;
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#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
|
||||
|
@ -22,6 +26,8 @@
|
|||
#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
|
||||
|
@ -56,8 +62,6 @@ typedef struct ppu {
|
|||
address t;
|
||||
byte x;
|
||||
bool w;
|
||||
|
||||
|
||||
} PPU;
|
||||
|
||||
PPU *ppu_get_state();
|
||||
|
@ -93,8 +97,11 @@ bool ppu_read_flag(size_t reg, byte mask);
|
|||
* @param reg The register index
|
||||
* @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
|
||||
|
|
98
ppu/ppu.c
98
ppu/ppu.c
|
@ -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.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include "../include/ppu.h"
|
||||
#include "../cpu/cpu.h"
|
||||
|
||||
|
@ -98,31 +99,94 @@ bool ppu_read_flag(size_t reg, byte mask) {
|
|||
return ppu_state.registers[reg] & mask;
|
||||
}
|
||||
|
||||
//byte ppu_sig_read_register(size_t reg, byte mask) {
|
||||
// return ppu_state.registers[reg] & mask;
|
||||
//}
|
||||
byte ppu_read_reg(byte reg) {
|
||||
assert(reg >= 0);
|
||||
assert(reg <= PPU_REGISTER_SIZE);
|
||||
|
||||
void ppu_sig_read_register(byte reg) {
|
||||
if (reg == PPU_REGISTER_STATUS) {
|
||||
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) {
|
||||
if (reg == PPU_REGISTER_ADDR) {
|
||||
byte addr_write = ppu_state.registers[PPU_REGISTER_ADDR];
|
||||
if (!ppu_state.w) {
|
||||
ppu_state.v &= (addr_write << 8) | 0x0f;
|
||||
void ppu_write_reg(byte reg, byte data) {
|
||||
ppu_state.registers[reg] = data;
|
||||
|
||||
if (reg == PPU_REGISTER_CTRL && ppu_read_flag(PPU_REGISTER_STATUS, PPU_STATUS_VBLANK) &&
|
||||
!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 {
|
||||
ppu_state.v &= 0xff & addr_write;
|
||||
addr &= (data << 8) | 0x0f;
|
||||
}
|
||||
|
||||
if (addr >= PPU_VRAM_SIZE) {
|
||||
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;
|
||||
}
|
||||
|
||||
ppu_state.v +=
|
||||
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);
|
||||
}
|
||||
|
||||
if (reg == PPU_REGISTER_SCROLL || reg == PPU_REGISTER_ADDR) {
|
||||
ppu_state.w = !ppu_state.w;
|
||||
}
|
||||
|
||||
if (reg == PPU_REGISTER_OAM_DATA) {
|
||||
ppu_state.registers[PPU_REGISTER_OAM_ADDR]++;
|
||||
}
|
||||
ppu_write_reg_ram(reg, data);
|
||||
}
|
Loading…
Reference in New Issue