From d9f0c676689bd1dc40f8cbb7f876193164cc5fc7 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Fri, 31 May 2024 00:52:28 -0400 Subject: [PATCH] PPU nametable/pattern background rendering!!! --- gui/gui.h | 2 +- include/ppu.h | 1 - main.c | 2 +- ppu/ppu.c | 92 +++++++++++++++++++++++++-------------------------- 4 files changed, 48 insertions(+), 49 deletions(-) diff --git a/gui/gui.h b/gui/gui.h index 24d737e..7d2eab9 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -10,7 +10,7 @@ #define WINDOW_ID_MAIN 1 #define WINDOW_MAIN_WIDTH 256 #define WINDOW_MAIN_HEIGHT 240 -#define WINDOW_MAIN_SCALING 3 +#define WINDOW_MAIN_SCALING 2 #define WINDOW_ID_PATTERN 2 #define WINDOW_PATTERN_WIDTH 128 diff --git a/include/ppu.h b/include/ppu.h index 7582712..ac28c97 100644 --- a/include/ppu.h +++ b/include/ppu.h @@ -57,7 +57,6 @@ #define PALETTE_TABLE_SIZE 0x0020 typedef struct ppu_memory { - byte vram[PPU_VRAM_SIZE]; byte nametable_0[NAMETABLE_SIZE]; byte nametable_1[NAMETABLE_SIZE]; byte palette[PALETTE_TABLE_SIZE]; diff --git a/main.c b/main.c index 2601972..12ebeec 100644 --- a/main.c +++ b/main.c @@ -26,7 +26,7 @@ int main() { log_set_level(LOG_INFO); system_init(); - char *rom_path = "../test_roms/dk_japan.nes"; + char *rom_path = "../test_roms/nestest.nes"; if (!rom_load(rom_path)) { system_uninit(); diff --git a/ppu/ppu.c b/ppu/ppu.c index cc39fb8..124fd69 100644 --- a/ppu/ppu.c +++ b/ppu/ppu.c @@ -60,13 +60,16 @@ void ppu_draw_tile() { PPUTileFetch tile_fetch = ppu_state.tile_fetch; Canvas *canvas = gui_get_canvas(WINDOW_ID_MAIN); - byte tile_fine_x = ppu_state.cycle % 8; + byte tile_fine_x = (ppu_state.cycle - 1) % 8; byte bitmask = 1 << (PATTERN_TILE_SIZE - tile_fine_x - 1); byte p1_byte = tile_fetch.pattern_table_tile_low & bitmask; byte p2_byte = tile_fetch.pattern_table_tile_high & bitmask; Pixel pixel; +// pixel.r = ~tile_fetch.nametable; +// pixel.g = ~tile_fetch.nametable; +// pixel.b = tile_fetch.nametable; if (p1_byte && p2_byte) { pixel.r = 255; pixel.g = 255; @@ -91,39 +94,42 @@ void ppu_draw_tile() { void ppu_visible_frame(unsigned int cycle) { if (cycle == 0) { // Idle... - } else if (cycle <= 256) { - if (!ppu_read_flag(PPU_REGISTER_MASK, PPU_MASK_SHOW_BG) && ppu_state.scanline < 240) { - if (cycle <= 248) { - ppu_draw_tile(); - } + } else if (cycle < 256) { + if (ppu_read_flag(PPU_REGISTER_MASK, PPU_MASK_SHOW_BG)) { + ppu_draw_tile(); - byte tile_fetch_cycle = (cycle - 1) % 8; - switch (tile_fetch_cycle) { - case 1: - address nt_addr = 0x2000 + (ppu_state.scanline * 16) + (ppu_state.cycle / 8); - ppu_state.next_tile_fetch.nametable = ppu_read(nt_addr); - break; - case 3: - address at_addr = 0x23c0 + (ppu_state.cycle % 8); - ppu_state.next_tile_fetch.attribute_table = ppu_read(at_addr); - ppu_state.ppu_address++; - break; - case 5: - ppu_state.next_tile_fetch.pattern_table_tile_low = ppu_read(0x0000); - break; - case 7: - ppu_state.next_tile_fetch.pattern_table_tile_high = ppu_read(0x0008); - ppu_state.tile_fetch = ppu_state.next_tile_fetch; - break; - default: - break; + if (cycle <= 248) { + address read_addr; + byte tile_fetch_cycle = (cycle - 1) % 8; + switch (tile_fetch_cycle) { + case 1: + read_addr = 0x2000 + ((ppu_state.scanline / 8) * 0x20) + (ppu_state.cycle / 8); + ppu_state.next_tile_fetch.nametable = ppu_read(read_addr); + break; + case 3: + read_addr = 0x23c0 + (ppu_state.cycle % 8); + ppu_state.next_tile_fetch.attribute_table = ppu_read(read_addr); + break; + case 5: + read_addr = 0x1000 * ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_BG_PATTERN_TABLE_ADDR); + read_addr += ppu_state.next_tile_fetch.nametable * 16 + ppu_state.scanline % 8; + ppu_state.next_tile_fetch.pattern_table_tile_low = ppu_read(read_addr); + break; + case 7: + read_addr = 0x1000 * ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_BG_PATTERN_TABLE_ADDR); + read_addr += ppu_state.next_tile_fetch.nametable * 16 + ppu_state.scanline % 8 + 8; + ppu_state.next_tile_fetch.pattern_table_tile_high = ppu_read(read_addr); + ppu_state.tile_fetch = ppu_state.next_tile_fetch; + break; + default: + break; + } } } } else if (cycle <= 320) { // OAMADDR is cleared on sprite loading for pre-render and visible lines ppu_write_reg(PPU_REGISTER_OAM_ADDR, 0); - } else { - + } else if (cycle <= 336) { } } @@ -198,7 +204,7 @@ byte ppu_read_reg(byte reg) { // 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.memory.vram[ppu_state.ppu_address]; + ppu_state.registers[reg] = ppu_read(ppu_state.ppu_address); if (ppu_state.ppu_address > 0x3eff) { // But the palette data is returned immediately data = ppu_state.registers[reg]; @@ -211,9 +217,7 @@ byte ppu_read_reg(byte reg) { } ppu_state.ppu_address += increment; - if (ppu_state.ppu_address >= PPU_VRAM_SIZE) { - ppu_state.ppu_address -= PPU_VRAM_SIZE; - } + ppu_state.ppu_address %= PPU_VRAM_SIZE; return data; } @@ -230,37 +234,33 @@ void ppu_write_reg(byte reg, byte data) { // 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) { - 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; + } else if (reg == PPU_REGISTER_ADDR) { address addr = ppu_state.ppu_address; - if (ppu_state.w) { - addr &= 0xff & data; + if (!ppu_state.w) { + addr = data; } else { - addr &= (data << 8) | 0x0f; + addr = data | (addr << 8); } - if (addr >= PPU_VRAM_SIZE) { - addr -= PPU_VRAM_SIZE; - } - ppu_state.ppu_address = addr; + ppu_state.ppu_address = addr % PPU_VRAM_SIZE; + ppu_state.w = !ppu_state.w; } else if (reg == PPU_REGISTER_DATA) { - ppu_write(ppu_state.ppu_address, data); + address addr = ppu_state.ppu_address; + ppu_write(addr, data); byte increment = 1; if (ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_VRAM_ADDR_INCREMENT)) { increment = 32; } - ppu_state.ppu_address += increment; - if (ppu_state.ppu_address >= PPU_VRAM_SIZE) { - ppu_state.ppu_address -= PPU_VRAM_SIZE; - } + addr += increment; + ppu_state.ppu_address = addr % 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);