PPU registers
This commit is contained in:
parent
1bc9d4950f
commit
9629efeeb9
|
@ -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
2
main.c
|
@ -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();
|
||||
|
|
93
ppu/ppu.c
93
ppu/ppu.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
int frame_width = 341;
|
||||
int frame_height = 262;
|
||||
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 = 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue