PPU registers
This commit is contained in:
parent
1bc9d4950f
commit
9629efeeb9
|
@ -62,6 +62,10 @@ typedef struct ppu {
|
||||||
address t;
|
address t;
|
||||||
byte x;
|
byte x;
|
||||||
bool w;
|
bool w;
|
||||||
|
|
||||||
|
unsigned long frame;
|
||||||
|
unsigned int line;
|
||||||
|
unsigned int line_x;
|
||||||
} PPU;
|
} PPU;
|
||||||
|
|
||||||
PPU *ppu_get_state();
|
PPU *ppu_get_state();
|
||||||
|
@ -102,6 +106,7 @@ bool ppu_read_flag(size_t reg, byte mask);
|
||||||
//void ppu_sig_write_register(byte reg);
|
//void ppu_sig_write_register(byte reg);
|
||||||
|
|
||||||
byte ppu_read_reg(byte reg);
|
byte ppu_read_reg(byte reg);
|
||||||
|
|
||||||
void ppu_write_reg(byte reg, byte data);
|
void ppu_write_reg(byte reg, byte data);
|
||||||
|
|
||||||
#endif //NESEMULATOR_PPU_H
|
#endif //NESEMULATOR_PPU_H
|
||||||
|
|
2
main.c
2
main.c
|
@ -26,7 +26,7 @@ int main() {
|
||||||
log_set_level(LOG_INFO);
|
log_set_level(LOG_INFO);
|
||||||
system_init();
|
system_init();
|
||||||
|
|
||||||
char *rom_path = "../test_roms/smb.nes";
|
char *rom_path = "../test_roms/dk_japan.nes";
|
||||||
|
|
||||||
if (!rom_load(rom_path)) {
|
if (!rom_load(rom_path)) {
|
||||||
system_uninit();
|
system_uninit();
|
||||||
|
|
93
ppu/ppu.c
93
ppu/ppu.c
|
@ -18,6 +18,13 @@
|
||||||
#include "../include/ppu.h"
|
#include "../include/ppu.h"
|
||||||
#include "../cpu/cpu.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;
|
PPU ppu_state;
|
||||||
|
|
||||||
void ppu_init(byte *registers_ram, byte *oam_dma_register) {
|
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.registers[PPU_REGISTER_DATA] = 0x00;
|
||||||
ppu_state.oam_dma_register = oam_dma_register;
|
ppu_state.oam_dma_register = oam_dma_register;
|
||||||
ppu_state.odd_frame = false;
|
ppu_state.odd_frame = false;
|
||||||
|
|
||||||
|
ppu_state.frame = 0;
|
||||||
|
ppu_state.line = 0;
|
||||||
|
ppu_state.line_x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PPU *ppu_get_state() {
|
PPU *ppu_get_state() {
|
||||||
|
@ -55,42 +66,61 @@ void ppu_trigger_vbl_nmi() {
|
||||||
cpu_trigger_nmi();
|
cpu_trigger_nmi();
|
||||||
}
|
}
|
||||||
|
|
||||||
long frame = 0;
|
void ppu_visible_frame(unsigned int x) {
|
||||||
int x, y = 0;
|
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 (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
|
// VBlank start
|
||||||
ppu_status_set(PPU_STATUS_VBLANK, true);
|
ppu_status_set(PPU_STATUS_VBLANK, true);
|
||||||
ppu_trigger_vbl_nmi();
|
ppu_trigger_vbl_nmi();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y == 261) {
|
|
||||||
// VBlank clear
|
|
||||||
ppu_status_set(PPU_STATUS_VBLANK, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame_width = 341;
|
void ppu_cycle() {
|
||||||
int frame_height = 262;
|
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);
|
bool rendering_enabled = ppu_read_flag(PPU_REGISTER_MASK, PPU_MASK_SHOW_BG | PPU_MASK_SHOW_SP);
|
||||||
if (rendering_enabled && ppu_state.odd_frame) {
|
if (rendering_enabled && ppu_state.odd_frame) {
|
||||||
// With rendering enabled, the odd frames are shorter
|
// With rendering enabled, the odd frames are shorter
|
||||||
// TODO: and doing the last cycle of the last dummy nametable fetch there instead
|
// TODO: and doing the last cycle of the last dummy nametable fetch there instead
|
||||||
frame_width = 339;
|
frame_width = PPU_LINE_WIDTH - 2;
|
||||||
frame_height = 261;
|
frame_height = PPU_LINE_END - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
x++;
|
ppu_state.line_x++;
|
||||||
if (x >= frame_width) {
|
if (ppu_state.line_x >= frame_width) {
|
||||||
x = 0;
|
ppu_state.line_x = 0;
|
||||||
y++;
|
ppu_state.line++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y >= frame_height) {
|
if (ppu_state.line >= frame_height) {
|
||||||
y = 0;
|
ppu_state.line = 0;
|
||||||
frame++;
|
ppu_state.frame++;
|
||||||
ppu_state.odd_frame = !ppu_state.odd_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) {
|
data & PPU_CTRL_GEN_VBLANK_NMI) {
|
||||||
// The VBlank flag is still set, and the GEN_VBLANK_NMI was set from 0 to 1
|
// The VBlank flag is still set, and the GEN_VBLANK_NMI was set from 0 to 1
|
||||||
cpu_trigger_nmi();
|
cpu_trigger_nmi();
|
||||||
} else if (reg == PPU_REGISTER_SCROLL || reg == PPU_REGISTER_ADDR) {
|
} else if (reg == PPU_REGISTER_SCROLL) {
|
||||||
ppu_state.
|
ppu_state.w = !ppu_state.w;
|
||||||
w = !ppu_state.w;
|
if (!ppu_state.w) {
|
||||||
|
ppu_state.x = data;
|
||||||
|
} else {
|
||||||
|
ppu_state.t = data;
|
||||||
|
}
|
||||||
} else if (reg == PPU_REGISTER_ADDR) {
|
} else if (reg == PPU_REGISTER_ADDR) {
|
||||||
|
ppu_state.w = !ppu_state.w;
|
||||||
address addr = ppu_state.v;
|
address addr = ppu_state.v;
|
||||||
if (ppu_state.w) {
|
if (ppu_state.w) {
|
||||||
addr &= 0xff &
|
addr &= 0xff & data;
|
||||||
data;
|
|
||||||
} else {
|
} else {
|
||||||
addr &= (data << 8) | 0x0f;
|
addr &= (data << 8) | 0x0f;
|
||||||
}
|
}
|
||||||
|
@ -167,19 +201,16 @@ void ppu_write_reg(byte reg, byte data) {
|
||||||
if (addr >= PPU_VRAM_SIZE) {
|
if (addr >= PPU_VRAM_SIZE) {
|
||||||
addr -= PPU_VRAM_SIZE;
|
addr -= PPU_VRAM_SIZE;
|
||||||
}
|
}
|
||||||
ppu_state.
|
ppu_state.v = addr;
|
||||||
v = addr;
|
|
||||||
} else if (reg == PPU_REGISTER_DATA) {
|
} else if (reg == PPU_REGISTER_DATA) {
|
||||||
ppu_state.vram[ppu_state.v] =
|
ppu_state.vram[ppu_state.v] = data;
|
||||||
data;
|
|
||||||
|
|
||||||
byte increment = 1;
|
byte increment = 1;
|
||||||
if (ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_VRAM_ADDR_INCREMENT)) {
|
if (ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_VRAM_ADDR_INCREMENT)) {
|
||||||
increment = 32;
|
increment = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_state.v +=
|
ppu_state.v += increment;
|
||||||
increment;
|
|
||||||
if (ppu_state.v >= PPU_VRAM_SIZE) {
|
if (ppu_state.v >= PPU_VRAM_SIZE) {
|
||||||
ppu_state.v -= PPU_VRAM_SIZE;
|
ppu_state.v -= PPU_VRAM_SIZE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue