PPU registers

This commit is contained in:
william 2024-05-15 13:02:40 -04:00
parent 1bc9d4950f
commit 9629efeeb9
3 changed files with 72 additions and 36 deletions

View File

@ -62,6 +62,10 @@ typedef struct ppu {
address t;
byte x;
bool w;
unsigned long frame;
unsigned int line;
unsigned int line_x;
} PPU;
PPU *ppu_get_state();
@ -102,6 +106,7 @@ bool ppu_read_flag(size_t reg, byte mask);
//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

2
main.c
View File

@ -26,7 +26,7 @@ int main() {
log_set_level(LOG_INFO);
system_init();
char *rom_path = "../test_roms/smb.nes";
char *rom_path = "../test_roms/dk_japan.nes";
if (!rom_load(rom_path)) {
system_uninit();

View File

@ -18,6 +18,13 @@
#include "../include/ppu.h"
#include "../cpu/cpu.h"
#define PPU_VISIBLE_FRAME_END 240
#define PPU_POST_RENDER_LINE_START PPU_VISIBLE_FRAME_END
#define PPU_POST_RENDER_LINE_END 242
#define PPU_PRE_RENDER_LINE 261
#define PPU_LINE_END PPU_PRE_RENDER_LINE
#define PPU_LINE_WIDTH 340
PPU ppu_state;
void ppu_init(byte *registers_ram, byte *oam_dma_register) {
@ -32,6 +39,10 @@ void ppu_init(byte *registers_ram, byte *oam_dma_register) {
ppu_state.registers[PPU_REGISTER_DATA] = 0x00;
ppu_state.oam_dma_register = oam_dma_register;
ppu_state.odd_frame = false;
ppu_state.frame = 0;
ppu_state.line = 0;
ppu_state.line_x = 0;
}
PPU *ppu_get_state() {
@ -55,42 +66,61 @@ void ppu_trigger_vbl_nmi() {
cpu_trigger_nmi();
}
long frame = 0;
int x, y = 0;
void ppu_visible_frame(unsigned int x) {
if (x >= 257 && x <= 320) {
// OAMADDR is cleared on sprite loading for pre-render and visible lines
ppu_write_reg(PPU_REGISTER_OAM_ADDR, 0);
}
}
void ppu_cycle() {
void ppu_pre_render(unsigned int x) {
if (x == 1) {
if (y == 241) {
// VBlank clear
ppu_status_set(PPU_STATUS_VBLANK, false);
}
if (x >= 257 && x <= 320) {
// OAMADDR is cleared on sprite loading for pre-render and visible lines
ppu_write_reg(PPU_REGISTER_OAM_ADDR, 0);
}
}
void ppu_post_render(unsigned int x, unsigned int y) {
if (x == 1 && y == 241) {
// VBlank start
ppu_status_set(PPU_STATUS_VBLANK, true);
ppu_trigger_vbl_nmi();
}
}
if (y == 261) {
// VBlank clear
ppu_status_set(PPU_STATUS_VBLANK, false);
}
void ppu_cycle() {
if (ppu_state.line < PPU_VISIBLE_FRAME_END) {
ppu_visible_frame(ppu_state.line_x);
} else if (ppu_state.line >= PPU_POST_RENDER_LINE_START && ppu_state.line <= PPU_POST_RENDER_LINE_END) {
ppu_post_render(ppu_state.line_x, ppu_state.line);
} else if (ppu_state.line == PPU_PRE_RENDER_LINE) {
ppu_pre_render(ppu_state.line_x);
}
int frame_width = 341;
int frame_height = 262;
int frame_width = PPU_LINE_WIDTH;
int frame_height = PPU_LINE_END;
bool rendering_enabled = ppu_read_flag(PPU_REGISTER_MASK, PPU_MASK_SHOW_BG | PPU_MASK_SHOW_SP);
if (rendering_enabled && ppu_state.odd_frame) {
// With rendering enabled, the odd frames are shorter
// TODO: and doing the last cycle of the last dummy nametable fetch there instead
frame_width = 339;
frame_height = 261;
frame_width = PPU_LINE_WIDTH - 2;
frame_height = PPU_LINE_END - 1;
}
x++;
if (x >= frame_width) {
x = 0;
y++;
ppu_state.line_x++;
if (ppu_state.line_x >= frame_width) {
ppu_state.line_x = 0;
ppu_state.line++;
}
if (y >= frame_height) {
y = 0;
frame++;
if (ppu_state.line >= frame_height) {
ppu_state.line = 0;
ppu_state.frame++;
ppu_state.odd_frame = !ppu_state.odd_frame;
}
}
@ -152,14 +182,18 @@ void ppu_write_reg(byte reg, byte data) {
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_SCROLL) {
ppu_state.w = !ppu_state.w;
if (!ppu_state.w) {
ppu_state.x = data;
} else {
ppu_state.t = data;
}
} else if (reg == PPU_REGISTER_ADDR) {
ppu_state.w = !ppu_state.w;
address addr = ppu_state.v;
if (ppu_state.w) {
addr &= 0xff &
data;
addr &= 0xff & data;
} else {
addr &= (data << 8) | 0x0f;
}
@ -167,19 +201,16 @@ void ppu_write_reg(byte reg, byte data) {
if (addr >= PPU_VRAM_SIZE) {
addr -= PPU_VRAM_SIZE;
}
ppu_state.
v = addr;
ppu_state.v = addr;
} else if (reg == PPU_REGISTER_DATA) {
ppu_state.vram[ppu_state.v] =
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;
ppu_state.v += increment;
if (ppu_state.v >= PPU_VRAM_SIZE) {
ppu_state.v -= PPU_VRAM_SIZE;
}