diff options
| author | Peter Fors <peter.fors@mindkiller.com> | 2025-05-02 23:15:47 +0200 |
|---|---|---|
| committer | Peter Fors <peter.fors@mindkiller.com> | 2025-05-02 23:15:47 +0200 |
| commit | 5808f00555c48e1cc1cc110af6a5cd73ddf13010 (patch) | |
| tree | dff942b61441bafe297e7a99f0e799f32ae978b1 | |
| parent | 9463faa436e1b981ef72000568445a83682f2658 (diff) | |
cleanup and rewrite of ppu_registers.c
35 files changed, 517 insertions, 351 deletions
@@ -8,4 +8,4 @@ fragment_shader.h vertex_shader.h *.fm2 fm2h.py -gmon.out
\ No newline at end of file +gmon.out @@ -3,12 +3,13 @@ # Set the project name here PROJECT_NAME="mknes" # Change this for each new project +CC=gcc-14 + # Base configuration common to all builds CFLAGS="-std=gnu11 -mtune=generic " -CFLAGS+="-mbmi2 " -CFLAGS+="-mfunction-return=keep " -CFLAGS+="-mindirect-branch=keep " -CFLAGS+="-fwrapv -ffast-math -fno-trapping-math -fwhole-program -fvisibility=hidden " +CFLAGS+="-mbmi -mbmi2 " +CFLAGS+="-mfunction-return=keep -mindirect-branch=keep " +CFLAGS+="-fwrapv -ffast-math -fno-trapping-math -fvisibility=hidden " CFLAGS+="-fno-stack-protector -fno-PIE -no-pie -fno-strict-aliasing -fcf-protection=none -ffunction-sections -fdata-sections " # CFLAGS+="-fno-exceptions -fno-rtti -fno-use-cxa-atexit " CFLAGS+="-fno-non-call-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables " @@ -47,7 +48,7 @@ case "$BUILD_TYPE" in CFLAGS+=" -s -Wl,--strip-all -O2" ;; "profile") - CFLAGS+=" -g -O2 -fprofile-generate" + CFLAGS+=" -g -O2 -fprofile-generate -ftest-coverage" ;; "profile_release") CFLAGS+=" -s -Wl,--strip-all -O2 -fprofile-use" @@ -56,6 +57,15 @@ case "$BUILD_TYPE" in CFLAGS+=" -g -O0" LDFLAGS+=" -fno-pie -no-pie" ;; + "coverage") + gcov -b -c *.c + exit 0 + ;; + + "clean") + rm -f *.gcda *.gcno *.gcov + exit 0 + ;; *) echo "Unknown build type: $BUILD_TYPE" exit 1 @@ -72,7 +82,7 @@ set -e # Build Linux version ( # ../bin/ctime -begin .${PROJECT_NAME}_linux - gcc $CFLAGS ${PROJECT_NAME}.c -o ${PROJECT_NAME} $INCLUDE_PATHS $LINUX_INCLUDE $LDFLAGS $LINUX_LIBS + $CC $CFLAGS ${PROJECT_NAME}.c -o ${PROJECT_NAME} $INCLUDE_PATHS $LINUX_INCLUDE $LDFLAGS $LINUX_LIBS # ../bin/ctime -end .${PROJECT_NAME}_linux $? ) & diff --git a/callbacks.c b/callbacks.c index 4523a68..6b62ea6 100644 --- a/callbacks.c +++ b/callbacks.c @@ -53,25 +53,25 @@ static void key_callback(GLFWwindow *window, int key, int scancode, int action, if(action == GLFW_PRESS) { switch(key) { - case GLFW_KEY_X: nes_state->input[0] |= (1 << 0); break; // A - case GLFW_KEY_Z: nes_state->input[0] |= (1 << 1); break; // B - case GLFW_KEY_SPACE: nes_state->input[0] |= (1 << 2); break; // Select - case GLFW_KEY_ENTER: nes_state->input[0] |= (1 << 3); break; // Start - case GLFW_KEY_UP: nes_state->input[0] |= (1 << 4); break; - case GLFW_KEY_DOWN: nes_state->input[0] |= (1 << 5); break; - case GLFW_KEY_LEFT: nes_state->input[0] |= (1 << 6); break; - case GLFW_KEY_RIGHT: nes_state->input[0] |= (1 << 7); break; + case GLFW_KEY_X: nes_state->ppu.input[0] |= (1 << 0); break; // A + case GLFW_KEY_Z: nes_state->ppu.input[0] |= (1 << 1); break; // B + case GLFW_KEY_SPACE: nes_state->ppu.input[0] |= (1 << 2); break; // Select + case GLFW_KEY_ENTER: nes_state->ppu.input[0] |= (1 << 3); break; // Start + case GLFW_KEY_UP: nes_state->ppu.input[0] |= (1 << 4); break; + case GLFW_KEY_DOWN: nes_state->ppu.input[0] |= (1 << 5); break; + case GLFW_KEY_LEFT: nes_state->ppu.input[0] |= (1 << 6); break; + case GLFW_KEY_RIGHT: nes_state->ppu.input[0] |= (1 << 7); break; } } else if(action == GLFW_RELEASE) { switch(key) { - case GLFW_KEY_X: nes_state->input[0] &= ~(1 << 0); break; - case GLFW_KEY_Z: nes_state->input[0] &= ~(1 << 1); break; - case GLFW_KEY_SPACE: nes_state->input[0] &= ~(1 << 2); break; - case GLFW_KEY_ENTER: nes_state->input[0] &= ~(1 << 3); break; - case GLFW_KEY_UP: nes_state->input[0] &= ~(1 << 4); break; - case GLFW_KEY_DOWN: nes_state->input[0] &= ~(1 << 5); break; - case GLFW_KEY_LEFT: nes_state->input[0] &= ~(1 << 6); break; - case GLFW_KEY_RIGHT: nes_state->input[0] &= ~(1 << 7); break; + case GLFW_KEY_X: nes_state->ppu.input[0] &= ~(1 << 0); break; + case GLFW_KEY_Z: nes_state->ppu.input[0] &= ~(1 << 1); break; + case GLFW_KEY_SPACE: nes_state->ppu.input[0] &= ~(1 << 2); break; + case GLFW_KEY_ENTER: nes_state->ppu.input[0] &= ~(1 << 3); break; + case GLFW_KEY_UP: nes_state->ppu.input[0] &= ~(1 << 4); break; + case GLFW_KEY_DOWN: nes_state->ppu.input[0] &= ~(1 << 5); break; + case GLFW_KEY_LEFT: nes_state->ppu.input[0] &= ~(1 << 6); break; + case GLFW_KEY_RIGHT: nes_state->ppu.input[0] &= ~(1 << 7); break; } } @@ -2,7 +2,7 @@ #include <stdio.h> #include <string.h> -// REMOVE FOR NES!!!!! +// DO NOT ENABLE FOR NES!!!!! // #define ENABLE_DECIMAL_MODE __attribute__((hot)) @@ -75,11 +75,11 @@ __attribute__((always_inline, hot)) static inline void check_interrupts(struct nes_state * restrict state) { struct cpu_state * restrict cpu = &state->cpu; - if(state->nmi_pending) { - state->nmi_pending = 0; + if(state->cpu.nmi_pending) { + state->cpu.nmi_pending = 0; do_nmi(state); - } else if(state->irq_pending && cpu->i == 0) { - state->irq_pending = 0; + } else if(state->cpu.irq_pending && cpu->i == 0) { + state->cpu.irq_pending = 0; do_irq(state); } } diff --git a/dump_mappers.c b/dump_mappers.c index 42034de..98dad4e 100644 --- a/dump_mappers.c +++ b/dump_mappers.c @@ -9,6 +9,13 @@ #define INES_HEADER_SIZE 16 +static void print_mapper(uint32_t mapper, const char *path) { + uint32_t mapper_id = mapper >> 4; + uint32_t submapper = mapper & 0xF; + + printf("%03u_%x %s\n", mapper_id, submapper, path); +} + static void process_nes_file(const char *path) { FILE *f = fopen(path, "rb"); if(!f) return; @@ -27,8 +34,10 @@ static void process_nes_file(const char *path) { uint8_t mapper_ext = header[8] & 0x0F; uint8_t submapper = header[8] >> 4; - uint32_t mapper = (submapper << 12) | (mapper_ext << 8) | mapper_high | mapper_low; - printf("0x%04x %s\n", mapper, path); + uint32_t mapper = (mapper_ext << 8) | mapper_high | mapper_low; + mapper = (mapper << 4) | submapper; + + print_mapper(mapper, path); } static void process_zip_file(const char *path) { @@ -73,8 +82,10 @@ static void process_zip_file(const char *path) { uint8_t mapper_ext = header[8] & 0x0F; uint8_t submapper = header[8] >> 4; - uint32_t mapper = (submapper << 12) | (mapper_ext << 8) | mapper_high | mapper_low; - printf("0x%04x %s\n", mapper, path); + uint32_t mapper = (mapper_ext << 8) | mapper_high | mapper_low; + mapper = (mapper << 4) | submapper; + + print_mapper(mapper, path); } static void scan_directory(const char *path) { @@ -104,7 +115,7 @@ static void scan_directory(const char *path) { int main(int argc, char **argv) { if(argc < 2) { - fprintf(stderr, "usage: %s <romdir>\n", argv[0]); + fprintf(stderr, "Usage: %s <romdir>\n", argv[0]); return 1; } scan_directory(argv[1]); diff --git a/mapper.c b/mapper.c deleted file mode 100644 index 935ff61..0000000 --- a/mapper.c +++ /dev/null @@ -1,67 +0,0 @@ - - -#include "mapper_0000.c" -#include "mapper_0003.c" -#include "mapper_0007.c" -#include "mapper_000b.c" -#include "mapper_0042.c" -#include "mapper_2002.c" - - -static uint8_t mapper_default_ciram_read(struct nes_state *state, uint32_t addr) { - if(state->ines.mirroring == 0) { // Horizontal - addr = (addr & 0x800) | (addr & 0x3ff); - } else { // Vertical (default fallback) - addr = addr & 0x7ff; - } - - return state->ciram[addr]; -} - -static void mapper_default_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) { - if(state->ines.mirroring == 0) { - addr = (addr & 0x800) | (addr & 0x3ff); - } else { - addr = addr & 0x7ff; - } - state->ciram[addr] = value; -} - -static void mapper_default_tick(struct nes_state *state) { // No IRQ or timing logic needed -} - -/* - * Mapper numbers are constructed like this: (submapper << 12 | mapperid) both in hex. - * - * NOTE(peter): Mapper 0 always has to be first! - */ -static struct mapper_entry mapper_table[] = { -/* Mapper: 0 */ { 0x00, mapper_0000_prg_read, mapper_0000_prg_write, mapper_0000_chr_read, mapper_0000_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0000_init }, -/* Mapper: 2 */ { 0x02, mapper_2002_prg_read, mapper_2002_prg_write, mapper_2002_chr_read, mapper_2002_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_2002_init }, -/* Mapper: 3 */ { 0x03, mapper_0003_prg_read, mapper_0003_prg_write, mapper_0003_chr_read, mapper_0003_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0003_init }, -/* Mapper: 7 */ { 0x7, mapper_0007_prg_read, mapper_0007_prg_write, mapper_0007_chr_read, mapper_0007_chr_write, mapper_0007_ciram_read, mapper_0007_ciram_write, mapper_default_tick, mapper_0007_init }, -/* Mapper: b */ { 0x0b, mapper_000b_prg_read, mapper_000b_prg_write, mapper_000b_chr_read, mapper_000b_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_000b_init }, -/* Mapper: 66 */ { 0x42, mapper_0042_prg_read, mapper_0042_prg_write, mapper_0042_chr_read, mapper_0042_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0042_init }, -/* Mapper: 2002 */ { 0x2002, mapper_2002_prg_read, mapper_2002_prg_write, mapper_2002_chr_read, mapper_2002_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_2002_init }, -/* Mapper: 2003 */ { 0x2003, mapper_0003_prg_read, mapper_0003_prg_write, mapper_0003_chr_read, mapper_0003_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0003_init }, -/* Mapper: 7 */ { 0x2007, mapper_0007_prg_read, mapper_0007_prg_write, mapper_0007_chr_read, mapper_0007_chr_write, mapper_0007_ciram_read, mapper_0007_ciram_write, mapper_default_tick, mapper_0007_init }, -}; - -static void mapper_setup(struct nes_state *state) { - uint32_t mapper = (state->ines.submapper << 12) | state->ines.mapper; - for(uint32_t i = 0; i < sizeof(mapper_table)/sizeof(mapper_table[0]); i++) { - if(mapper_table[i].id == mapper) { - printf("Mapper %4.4x\n", mapper); - memcpy(&state->mapper, &mapper_table[i], sizeof(struct mapper_entry)); // NOTE(peter): BECAUSE GCC IS BROKEN - // state->mapper = mapper_table[i]; - state->mapper.init(state); - return; - } - } - - printf("Unsupported mapper %4.4x, falling back to NROM\n", mapper); - memcpy(&state->mapper, &mapper_table[0], sizeof(struct mapper_entry)); // NOTE(peter): BECAUSE GCC IS BROKEN - // state->mapper = mapper_table[0]; - state->mapper.init(state); -} - diff --git a/mapper_0000.c b/mapper_0000.c deleted file mode 100644 index e075de5..0000000 --- a/mapper_0000.c +++ /dev/null @@ -1,24 +0,0 @@ - - -static void mapper_0000_init(struct nes_state *state) { - // Nothing to initialize for 001 -} - -__attribute__((hot)) -static uint8_t mapper_0000_prg_read(struct nes_state *state, uint32_t addr) { - uint32_t prg_size = state->ines.prg_size; - - uint32_t mask = (state->ines.prg_size == 16384) ? 0x3fff : 0x7fff; - return state->prg_rom[addr & mask]; -} - -static void mapper_0000_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { -} - -__attribute__((hot)) -static uint8_t mapper_0000_chr_read(struct nes_state *state, uint32_t addr) { - return state->chr_rom[addr]; -} - -static void mapper_0000_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { -} diff --git a/mapper_0003.c b/mapper_0003.c deleted file mode 100644 index a4ae56c..0000000 --- a/mapper_0003.c +++ /dev/null @@ -1,22 +0,0 @@ - - -static void mapper_0003_init(struct nes_state *state) { - state->map.m0003.chr_ptr = state->chr_rom; -} - -static uint8_t mapper_0003_prg_read(struct nes_state *state, uint32_t addr) { - return state->prg_rom[addr & 0x7fff]; -} - -static void mapper_0003_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { - if(addr >= 0x8000) { - state->map.m0003.chr_ptr = state->chr_rom + (value & 3) * 0x2000; - } -} - -static uint8_t mapper_0003_chr_read(struct nes_state *state, uint32_t addr) { - return state->map.m0003.chr_ptr[addr]; -} - -static void mapper_0003_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { -} diff --git a/mapper_0003.h b/mapper_0003.h deleted file mode 100644 index c562519..0000000 --- a/mapper_0003.h +++ /dev/null @@ -1,4 +0,0 @@ - -struct mapper_0003 { - uint8_t *chr_ptr; -}; diff --git a/mapper_0007.c b/mapper_0007.c deleted file mode 100644 index 235f5bb..0000000 --- a/mapper_0007.c +++ /dev/null @@ -1,39 +0,0 @@ - - - -static void mapper_0007_init(struct nes_state *state) { - state->map.m0007.prg_ptr = state->prg_rom; - state->map.m0007.ciram_base = 0x000; -} - -static uint8_t mapper_0007_prg_read(struct nes_state *state, uint32_t addr) { - if(addr >= 0x8000) { - return state->map.m0007.prg_ptr[addr & 0x7fff]; - } - return 0; // openbus -} - -static void mapper_0007_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { - if(addr >= 0x8000) { - state->map.m0007.prg_ptr = state->prg_rom + ((value & 0x0f) * 0x8000); - state->map.m0007.ciram_base = (value & 0x10) ? 0x400 : 0x000; - } -} - -static uint8_t mapper_0007_chr_read(struct nes_state *state, uint32_t addr) { - return state->chr_ram[addr]; -} - -static void mapper_0007_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { - state->chr_ram[addr] = value; -} - -static uint8_t mapper_0007_ciram_read(struct nes_state *state, uint32_t addr) { - addr = state->map.m0007.ciram_base | (addr & 0x3ff); - return state->ciram[addr]; -} - -static void mapper_0007_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) { - addr = state->map.m0007.ciram_base | (addr & 0x3ff); - state->ciram[addr] = value; -} diff --git a/mapper_0007.h b/mapper_0007.h deleted file mode 100644 index 775082b..0000000 --- a/mapper_0007.h +++ /dev/null @@ -1,7 +0,0 @@ - - -struct mapper_0007 { - uint8_t *prg_ptr; - uint32_t ciram_base; -}; - diff --git a/mapper_000b.c b/mapper_000b.c deleted file mode 100644 index 9252060..0000000 --- a/mapper_000b.c +++ /dev/null @@ -1,27 +0,0 @@ - - -static void mapper_000b_init(struct nes_state *state) { - state->map.m000b.prg_ptr = state->prg_rom; - state->map.m000b.chr_ptr = state->chr_rom; -} - -static uint8_t mapper_000b_prg_read(struct nes_state *state, uint32_t addr) { - if(addr >= 0x8000) { - return state->map.m000b.prg_ptr[addr - 0x8000]; - } - return 0; -} - -static void mapper_000b_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { - if(addr >= 0x8000) { - state->map.m000b.prg_ptr = state->prg_rom + ((value >> 4) & 7) * 0x8000; - state->map.m000b.chr_ptr = state->chr_rom + (value & 0x0F) * 0x2000; - } -} - -static uint8_t mapper_000b_chr_read(struct nes_state *state, uint32_t addr) { - return state->map.m000b.chr_ptr[addr]; -} - -static void mapper_000b_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { -} diff --git a/mapper_000b.h b/mapper_000b.h deleted file mode 100644 index 2c3f15a..0000000 --- a/mapper_000b.h +++ /dev/null @@ -1,6 +0,0 @@ - - -struct mapper_000b { - uint8_t *prg_ptr; - uint8_t *chr_ptr; -}; diff --git a/mapper_0042.c b/mapper_0042.c deleted file mode 100644 index 4cf4c86..0000000 --- a/mapper_0042.c +++ /dev/null @@ -1,30 +0,0 @@ - -static void mapper_0042_init(struct nes_state *state) { - state->map.m0042.prg_offset = 0; - state->map.m0042.chr_offset = 0; -} - -static uint8_t mapper_0042_prg_read(struct nes_state *state, uint32_t addr) { - if(addr >= 0x8000) { - uint32_t base = state->map.m0042.prg_offset; - return state->prg_rom[base + (addr - 0x8000)]; - } - return 0; -} - -static void mapper_0042_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { - if(addr >= 0x8000) { - uint32_t prg_bank = (value >> 4) & 3; - uint32_t chr_bank = (value >> 0) & 3; - - state->map.m0042.prg_offset = prg_bank * 0x8000; - state->map.m0042.chr_offset = chr_bank * 0x2000; - } -} - -static uint8_t mapper_0042_chr_read(struct nes_state *state, uint32_t addr) { - return state->chr_rom[state->map.m0042.chr_offset + addr]; -} - -static void mapper_0042_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { -} diff --git a/mapper_0042.h b/mapper_0042.h deleted file mode 100644 index cb201d9..0000000 --- a/mapper_0042.h +++ /dev/null @@ -1,5 +0,0 @@ - -struct mapper_0042 { - uint32_t prg_offset; - uint32_t chr_offset; -}; diff --git a/mapper_2002.c b/mapper_2002.c deleted file mode 100644 index 700a24b..0000000 --- a/mapper_2002.c +++ /dev/null @@ -1,28 +0,0 @@ - -static void mapper_2002_init(struct nes_state *state) { - state->map.m2002.prg_bank0 = state->prg_rom; // default to bank 0 - state->map.m2002.prg_bank1 = state->prg_rom + state->ines.prg_size - 0x4000; -} - -static uint8_t mapper_2002_prg_read(struct nes_state *state, uint32_t addr) { - if(addr >= 0x8000 && addr < 0xc000) { - return state->map.m2002.prg_bank0[addr & 0x3fff]; - } else if(addr >= 0xc000) { - return state->map.m2002.prg_bank1[addr & 0x3fff]; - } - return 0; -} - -static void mapper_2002_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { - if(addr >= 0x8000) { - state->map.m2002.prg_bank0 = state->prg_rom + ((value & 0x0f) * 0x4000); - } -} - -static uint8_t mapper_2002_chr_read(struct nes_state *state, uint32_t addr) { - return state->chr_ram[addr]; -} - -static void mapper_2002_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { - state->chr_ram[addr] = value; -} diff --git a/mappers/mapper.c b/mappers/mapper.c new file mode 100644 index 0000000..d63e2a0 --- /dev/null +++ b/mappers/mapper.c @@ -0,0 +1,63 @@ + +static uint8_t mapper_default_ciram_read(struct nes_state *state, uint32_t addr) { + if(state->ines.mirroring == 0) { // Horizontal + addr = (addr & 0x800) | (addr & 0x3ff); + } else { // Vertical (default fallback) + addr = addr & 0x7ff; + } + + return state->ciram[addr]; +} + +static void mapper_default_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) { + if(state->ines.mirroring == 0) { + addr = (addr & 0x800) | (addr & 0x3ff); + } else { + addr = addr & 0x7ff; + } + state->ciram[addr] = value; +} + +static void mapper_default_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { } +static void mapper_default_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { } +static void mapper_default_tick(struct nes_state *state) { } + +#include "mapper_000_0.c" +#include "mapper_002_2.c" +#include "mapper_003_0.c" +#include "mapper_007_2.c" +#include "mapper_011_0.c" +#include "mapper_066_0.c" + +#define MAPPER_ID(mapper, submapper) (((mapper) << 4) | (submapper)) + +static void (*mapper_table[4096])(struct nes_state *state) = { + [MAPPER_ID( 0, 0)] = mapper_000_0_init, + [MAPPER_ID( 2, 2)] = mapper_002_2_init, + [MAPPER_ID( 3, 0)] = mapper_003_0_init, + [MAPPER_ID( 7, 2)] = mapper_007_2_init, + [MAPPER_ID(11, 0)] = mapper_011_0_init, + [MAPPER_ID(66, 0)] = mapper_011_0_init, +}; + +static void mapper_reset(struct nes_state *state) { + state->mapper.prg_read = 0; + state->mapper.prg_write = mapper_default_prg_write; + state->mapper.chr_read = 0; + state->mapper.chr_write = mapper_default_chr_write; + state->mapper.ciram_read = mapper_default_ciram_read; + state->mapper.ciram_write = mapper_default_ciram_write; + state->mapper.tick = mapper_default_tick; +} + +static void mapper_setup(struct nes_state *state) { + uint32_t mapper = state->ines.mapper << 4 | state->ines.submapper; + mapper_reset(state); + if(mapper_table[mapper]) { + mapper_table[mapper](state); + } else { + printf("Unsupported mapper %d_%x, falling back to NROM\n", state->ines.mapper, state->ines.submapper); + mapper_table[0](state); + } +} + diff --git a/mapper.h b/mappers/mapper.h index 73fafc0..0961370 100644 --- a/mapper.h +++ b/mappers/mapper.h @@ -1,15 +1,14 @@ -// #include "mapper_0000.h" // NOTE(peter): Has no header -#include "mapper_0003.h" -#include "mapper_0007.h" -#include "mapper_000b.h" -#include "mapper_0042.h" -#include "mapper_2002.h" +#include "mapper_000_0.h" +#include "mapper_002_2.h" +#include "mapper_003_0.h" +#include "mapper_007_2.h" +#include "mapper_011_0.h" +#include "mapper_066_0.h" struct nes_state; -struct mapper_entry { - uint64_t id; +struct mapper_functions { uint8_t (*prg_read)(struct nes_state *state, uint32_t addr); void (*prg_write)(struct nes_state *state, uint32_t addr, uint8_t value); uint8_t (*chr_read)(struct nes_state *state, uint32_t addr); @@ -17,14 +16,14 @@ struct mapper_entry { uint8_t (*ciram_read)(struct nes_state *state, uint32_t addr); void (*ciram_write)(struct nes_state *state, uint32_t addr, uint8_t value); void (*tick)(struct nes_state *state); - void (*init)(struct nes_state *state); -}; +} __attribute__((aligned(64))); union mapper_data { - struct mapper_0003 m0003; - struct mapper_0007 m0007; - struct mapper_000b m000b; - struct mapper_0042 m0042; - struct mapper_2002 m2002; -}; + struct mapper_000_0 m000_0; + struct mapper_002_2 m002_2; + struct mapper_003_0 m003_0; + struct mapper_007_2 m007_2; + struct mapper_011_0 m011_0; + struct mapper_066_0 m066_0; +} __attribute__((aligned(64))); diff --git a/mappers/mapper_000_0.c b/mappers/mapper_000_0.c new file mode 100644 index 0000000..b79cdbf --- /dev/null +++ b/mappers/mapper_000_0.c @@ -0,0 +1,22 @@ + + +__attribute__((hot)) +static uint8_t mapper_000_0_prg_read(struct nes_state *state, uint32_t addr) { + struct mapper_000_0 *mapper = (struct mapper_000_0 *)&state->map; + + return state->prg_rom[addr & mapper->mask]; +} + +__attribute__((hot)) +static uint8_t mapper_000_0_chr_read(struct nes_state *state, uint32_t addr) { + return state->chr_rom[addr]; +} + +static void mapper_000_0_init(struct nes_state *state) { + struct mapper_000_0 *mapper = (struct mapper_000_0 *)&state->map; + state->mapper.prg_read = mapper_000_0_prg_read; + state->mapper.chr_read = mapper_000_0_chr_read; + mapper->mask = (state->ines.prg_size == 16384) ? 0x3fff : 0x7fff; +} + + diff --git a/mappers/mapper_000_0.h b/mappers/mapper_000_0.h new file mode 100644 index 0000000..86e279c --- /dev/null +++ b/mappers/mapper_000_0.h @@ -0,0 +1,6 @@ + + + +struct mapper_000_0 { + uint32_t mask; +} __attribute__((packed, aligned(64))); diff --git a/mappers/mapper_002_2.c b/mappers/mapper_002_2.c new file mode 100644 index 0000000..079fb0b --- /dev/null +++ b/mappers/mapper_002_2.c @@ -0,0 +1,41 @@ + + +static uint8_t mapper_002_2_prg_read(struct nes_state *state, uint32_t addr) { + struct mapper_002_2 *mapper = (struct mapper_002_2 *)&state->map; + + if(addr >= 0x8000 && addr < 0xc000) { + return mapper->prg_bank0[addr & 0x3fff]; + + } else if(addr >= 0xc000) { + return mapper->prg_bank1[addr & 0x3fff]; + } + return 0; +} + +static void mapper_002_2_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_002_2 *mapper = (struct mapper_002_2 *)&state->map; + + if(addr >= 0x8000) { + mapper->prg_bank0 = state->prg_rom + ((value & 0x0f) * 0x4000); + } +} + +static uint8_t mapper_002_2_chr_read(struct nes_state *state, uint32_t addr) { + return state->chr_ram[addr]; +} + +static void mapper_002_2_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { + state->chr_ram[addr] = value; +} + +static void mapper_002_2_init(struct nes_state *state) { + struct mapper_002_2 *mapper = (struct mapper_002_2 *)&state->map; + + mapper->prg_bank0 = state->prg_rom; + mapper->prg_bank1 = state->prg_rom + state->ines.prg_size - 0x4000; + + state->mapper.prg_read = mapper_002_2_prg_read; + state->mapper.prg_write = mapper_002_2_prg_write; + state->mapper.chr_read = mapper_002_2_chr_read; + state->mapper.chr_write = mapper_002_2_chr_write; +} diff --git a/mapper_2002.h b/mappers/mapper_002_2.h index 6c648b5..b136274 100644 --- a/mapper_2002.h +++ b/mappers/mapper_002_2.h @@ -1,7 +1,7 @@ -struct mapper_2002 { +struct mapper_002_2 { uint8_t *prg_bank0; // $8000–BFFF (switchable) uint8_t *prg_bank1; // $C000–FFFF (fixed to last 16KB) -}; +} __attribute__((packed, aligned(64))); diff --git a/mappers/mapper_003_0.c b/mappers/mapper_003_0.c new file mode 100644 index 0000000..5ccfb53 --- /dev/null +++ b/mappers/mapper_003_0.c @@ -0,0 +1,27 @@ + +static uint8_t mapper_003_0_prg_read(struct nes_state *state, uint32_t addr) { + return state->prg_rom[addr & 0x7fff]; +} + +static void mapper_003_0_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_003_0 *mapper = (struct mapper_003_0 *)&state->map; + + if(addr >= 0x8000) { + mapper->chr_ptr = state->chr_rom + (value & 3) * 0x2000; + } +} + +static uint8_t mapper_003_0_chr_read(struct nes_state *state, uint32_t addr) { + struct mapper_003_0 *mapper = (struct mapper_003_0 *)&state->map; + return mapper->chr_ptr[addr]; +} + +static void mapper_003_0_init(struct nes_state *state) { + struct mapper_003_0 *mapper = (struct mapper_003_0 *)&state->map; + + mapper->chr_ptr = state->chr_rom; + + state->mapper.prg_read = mapper_003_0_prg_read; + state->mapper.prg_write = mapper_003_0_prg_write; + state->mapper.chr_read = mapper_003_0_chr_read; +} diff --git a/mappers/mapper_003_0.h b/mappers/mapper_003_0.h new file mode 100644 index 0000000..f03b106 --- /dev/null +++ b/mappers/mapper_003_0.h @@ -0,0 +1,4 @@ + +struct mapper_003_0 { + uint8_t *chr_ptr; +} __attribute__((packed, aligned(64))); diff --git a/mappers/mapper_007_2.c b/mappers/mapper_007_2.c new file mode 100644 index 0000000..ed56dd0 --- /dev/null +++ b/mappers/mapper_007_2.c @@ -0,0 +1,53 @@ + + +static uint8_t mapper_007_2_prg_read(struct nes_state *state, uint32_t addr) { + struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map; + if(addr >= 0x8000) { + return mapper->prg_rom[addr & 0x7fff]; + } + return 0; +} + +static void mapper_007_2_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map; + if(addr >= 0x8000) { + uint32_t prg_off = (value & 0x0f) << 15; + uint32_t ciram_off = (value & 0x10) << 11; + mapper->prg_rom = state->prg_rom + prg_off; + mapper->ciram = state->ciram + ciram_off; + + // mapper->prg_rom = state->prg_rom + ((value & 0x0f) * 0x8000); + // mapper->ciram = state->ciram + ((value & 0x10) ? 0x400 : 0x000); + } +} + +static uint8_t mapper_007_2_chr_read(struct nes_state *state, uint32_t addr) { + return state->chr_ram[addr]; +} + +static void mapper_007_2_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { + state->chr_ram[addr] = value; +} + +static uint8_t mapper_007_2_ciram_read(struct nes_state *state, uint32_t addr) { + struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map; + return mapper->ciram[addr & 0x3ff]; +} + +static void mapper_007_2_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map; + mapper->ciram[addr & 0x3ff] = value; +} + +static void mapper_007_2_init(struct nes_state *state) { + struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map; + mapper->prg_rom = state->prg_rom; + mapper->ciram = 0; + + state->mapper.prg_read = mapper_007_2_prg_read; + state->mapper.prg_write = mapper_007_2_prg_write; + state->mapper.chr_read = mapper_007_2_chr_read; + state->mapper.chr_write = mapper_007_2_chr_write; + state->mapper.ciram_read = mapper_007_2_ciram_read; + state->mapper.ciram_write = mapper_007_2_ciram_write; +} diff --git a/mappers/mapper_007_2.h b/mappers/mapper_007_2.h new file mode 100644 index 0000000..c0a2d06 --- /dev/null +++ b/mappers/mapper_007_2.h @@ -0,0 +1,8 @@ + + +struct mapper_007_2 { + uint8_t *prg_rom; + uint8_t *ciram; + // uint32_t ciram_base; +} __attribute__((packed, aligned(64))); + diff --git a/mappers/mapper_011_0.c b/mappers/mapper_011_0.c new file mode 100644 index 0000000..ce390a0 --- /dev/null +++ b/mappers/mapper_011_0.c @@ -0,0 +1,37 @@ + + +static uint8_t mapper_011_0_prg_read(struct nes_state *state, uint32_t addr) { + struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map; + + if(addr >= 0x8000) { + return mapper->prg_rom[addr - 0x8000]; + } + return 0; +} + +static void mapper_011_0_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map; + + if(addr >= 0x8000) { + mapper->prg_rom = state->prg_rom + ((value >> 4) & 7) * 0x8000; + mapper->chr_ptr = state->chr_rom + (value & 0x0F) * 0x2000; + } +} + +static uint8_t mapper_011_0_chr_read(struct nes_state *state, uint32_t addr) { + struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map; + + return mapper->chr_ptr[addr]; +} + +static void mapper_011_0_init(struct nes_state *state) { + struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map; + + mapper->prg_rom = state->prg_rom; + mapper->chr_ptr = state->chr_rom; + + state->mapper.prg_read = mapper_011_0_prg_read; + state->mapper.prg_write = mapper_011_0_prg_write; + state->mapper.chr_read = mapper_011_0_chr_read; +} + diff --git a/mappers/mapper_011_0.h b/mappers/mapper_011_0.h new file mode 100644 index 0000000..8f41e8e --- /dev/null +++ b/mappers/mapper_011_0.h @@ -0,0 +1,6 @@ + + +struct mapper_011_0 { + uint8_t *prg_rom; + uint8_t *chr_ptr; +} __attribute__((packed, aligned(64))); diff --git a/mappers/mapper_066_0.c b/mappers/mapper_066_0.c new file mode 100644 index 0000000..bf31720 --- /dev/null +++ b/mappers/mapper_066_0.c @@ -0,0 +1,38 @@ + +static uint8_t mapper_066_0_prg_read(struct nes_state *state, uint32_t addr) { + struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map; + + if(addr >= 0x8000) { + return state->prg_rom[addr & 0x7fff]; + } + return 0; +} + +static void mapper_066_0_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map; + + if(addr >= 0x8000) { + uint32_t prg_bank = (value >> 4) & 3; + uint32_t chr_bank = (value >> 0) & 3; + + mapper->prg_offset = state->prg_rom + (prg_bank * 0x8000); + mapper->chr_offset = state->chr_rom + (chr_bank * 0x2000); + } +} + +static uint8_t mapper_066_0_chr_read(struct nes_state *state, uint32_t addr) { + struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map; + return mapper->chr_offset[addr]; +} + +static void mapper_066_0_init(struct nes_state *state) { + struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map; + + mapper->prg_offset = state->prg_rom; + mapper->chr_offset = state->chr_rom; + + state->mapper.prg_read = mapper_066_0_prg_read; + state->mapper.prg_write = mapper_066_0_prg_write; + state->mapper.chr_read = mapper_066_0_chr_read; +} + diff --git a/mappers/mapper_066_0.h b/mappers/mapper_066_0.h new file mode 100644 index 0000000..b09ee56 --- /dev/null +++ b/mappers/mapper_066_0.h @@ -0,0 +1,5 @@ + +struct mapper_066_0 { + uint8_t *prg_offset; + uint8_t *chr_offset; +} __attribute__((packed, aligned(64))); @@ -3,7 +3,7 @@ __attribute__((hot)) static uint8_t memory_read(struct nes_state *restrict state, uint32_t offset) { - state->cycles++; + state->cpu.cycles++; ppu_tick(state); // apu_tick(state); @@ -15,8 +15,8 @@ static uint8_t memory_read(struct nes_state *restrict state, uint32_t offset) { } else if(offset == 0x4016 || offset == 0x4017) { uint32_t index = offset & 1; - uint8_t value = (state->input_latch[index] >> state->input_bit[index]) & 1; - state->input_bit[index]++; + uint8_t value = (state->ppu.input_latch[index] >> state->ppu.input_bit[index]) & 1; + state->ppu.input_bit[index]++; return value | 0x40; // Bit 6 open bus high, bit 7 low // } else if(offset == 4015) { @@ -32,7 +32,7 @@ static uint8_t memory_read(struct nes_state *restrict state, uint32_t offset) { __attribute__((hot)) static void memory_write(struct nes_state *restrict state, uint32_t offset, uint8_t value) { - state->cycles++; + state->cpu.cycles++; ppu_tick(state); // apu_tick(state); @@ -51,15 +51,15 @@ static void memory_write(struct nes_state *restrict state, uint32_t offset, uint // state->apu.dmc_dma_enabled = (value & 0x10) ? 1 : 0; } else if(offset == 0x4016) { - uint8_t prev = state->input_strobe; - state->input_strobe = value & 1; + uint8_t prev = state->ppu.input_strobe; + state->ppu.input_strobe = value & 1; if(prev == 1 && (value & 1) == 0) { // Latch current inputs - state->input_latch[0] = state->input[0]; - state->input_latch[1] = state->input[1]; - state->input_bit[0] = 0; - state->input_bit[1] = 0; + state->ppu.input_latch[0] = state->ppu.input[0]; + state->ppu.input_latch[1] = state->ppu.input[1]; + state->ppu.input_bit[0] = 0; + state->ppu.input_bit[1] = 0; } // } else if(offset == 0x4017) { // Frame Counter (APU) @@ -90,7 +90,7 @@ static uint8_t memory_read_dma(struct nes_state *restrict state, uint32_t offset __attribute__((hot)) static uint8_t memory_read_dummy(struct nes_state *restrict state, uint32_t offset) { - state->cycles++; + state->cpu.cycles++; ppu_tick(state); // apu_tick(state); @@ -93,7 +93,7 @@ static uint32_t frames; // debug information // #include "smb_tas.h" // REMOVE ME // NES core -#include "mapper.h" +#include "mappers/mapper.h" #include "mknes.h" // #include "apu.c" #include "ppu.c" @@ -101,7 +101,7 @@ static uint32_t frames; // debug information #include "memory.c" #include "cpu.c" #include "ines2.c" -#include "mapper.c" +#include "mappers/mapper.c" #include "callbacks.c" struct nes_state nstate; @@ -236,7 +236,6 @@ int main(int argc, char **argv) { return 0; #endif - struct timer_handle *timer = timer_new(FRAME_INTERVAL_NS); if(!timer) { fprintf(stderr, "Failed to create timer\n"); @@ -263,7 +262,6 @@ int main(int argc, char **argv) { framebuffer_callback(window, WINDOW_WIDTH, WINDOW_HEIGHT); - for(int jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++) { if(glfwJoystickPresent(jid)) { const char *name = glfwGetJoystickName(jid); @@ -308,7 +306,7 @@ int main(int argc, char **argv) { render_frame(); glfwSwapBuffers(window); } -printf("total frames: %6.6d total cycles: %ld\n", frames, nstate->cycles); +printf("total frames: %6.6d total cycles: %ld\n", frames, nstate->cpu.cycles); glfwDestroyWindow(window); } else { fprintf(stderr, "Failed to create window\n"); @@ -64,6 +64,10 @@ struct ppu_state { uint8_t secondary_oam[32]; uint8_t oam[256]; + uint8_t input[2]; // Controller 1 & 2 + uint8_t input_latch[2]; // Latched inputs after strobe + uint8_t input_bit[2]; // Current bit position being shifted out + uint8_t input_strobe; // Control bit (0 or 1) uint8_t frame_ready; } __attribute__((packed, aligned(64))); @@ -74,9 +78,10 @@ struct apu_state { uint8_t irq_pending; uint8_t dmc_dma_enabled; uint32_t dmc_sample_timer; -}; +} __attribute__((packed, aligned(64))); struct cpu_state { + size_t cycles; uint32_t pc; // Program Counter uint8_t sp; // Stack Pointer uint8_t a; // Accumulator @@ -91,42 +96,35 @@ struct cpu_state { uint8_t z; // Zero Flag uint8_t c; // Carry Flag // -- - uint8_t die; // KIL instruction found! -};// __attribute__((aligned(64))); + uint8_t irq_pending; + uint8_t nmi_pending; +} __attribute__((packed, aligned(64))); struct ines_state { - uint32_t mapper; - uint32_t submapper; + uint8_t mapper; + uint8_t submapper; uint8_t mirroring; // 0 = H, 1 = V, 2 = 4-screen uint32_t prg_size; uint32_t chr_size; -}; +} __attribute__((packed, aligned(64))); struct nes_state { - size_t cycles; - struct cpu_state cpu; - uint8_t irq_pending; - uint8_t nmi_pending; - uint8_t input[2]; // Controller 1 & 2 - uint8_t input_latch[2]; // Latched inputs after strobe - uint8_t input_bit[2]; // Current bit position being shifted out - uint8_t input_strobe; // Control bit (0 or 1) - // struct apu_state apu; struct ppu_state ppu; - - struct mapper_entry mapper; + struct mapper_functions mapper; union mapper_data map; struct ines_state ines; + struct cpu_state cpu; + // struct apu_state apu; - uint8_t *pixels; uint8_t *ram; uint8_t *ciram; - uint8_t *chr_ram; uint8_t *prg_rom; uint8_t *chr_rom; + uint8_t *chr_ram; + uint8_t *pixels; uint8_t *sram; -}; +} __attribute__((packed, aligned(64))); __attribute__((aligned(4096))) static uint32_t nes_palette[65] = { @@ -400,7 +400,7 @@ static void ppu_tick(struct nes_state *state) { ppu->reg_status |= 0x80; if(ppu->reg_ctrl & 0x80) { - state->nmi_pending = 1; + state->cpu.nmi_pending = 1; } } diff --git a/ppu_registers.c b/ppu_registers.c index c698bf2..b426f17 100644 --- a/ppu_registers.c +++ b/ppu_registers.c @@ -2,6 +2,69 @@ __attribute__((always_inline, hot)) static inline void ppu_write(struct nes_state *state, uint32_t offset, uint8_t value) { struct ppu_state *ppu = &state->ppu; + uint32_t reg = offset & 0x7; + + if(reg == 0) { + ppu->reg_ctrl = value; + ppu->temp_addr = (ppu->temp_addr & 0xf3ff) | ((value & 0x03) << 10); + // ppu->open_bus = value; + + } else if(reg == 1) { + ppu->reg_mask = value; + // ppu->open_bus = value; + + } else if(reg == 3) { + ppu->oam_addr = value; + // ppu->open_bus = value; + + } else if(reg == 4) { + ppu->oam[ppu->oam_addr++] = value; + // ppu->open_bus = value; + + } else if(reg == 5) { + if(ppu->write_latch == 0) { + ppu->fine_x = value & 0x07; + ppu->temp_addr = (ppu->temp_addr & ~0x001f) | (value >> 3); + ppu->write_latch = 1; + } else { + ppu->temp_addr = (ppu->temp_addr & ~0x73e0) | ((value & 0x07) << 12) | ((value & 0xf8) << 2); + ppu->write_latch = 0; + } + // ppu->open_bus = value; + + } else if(reg == 6) { + if(ppu->write_latch == 0) { + ppu->temp_addr = (ppu->temp_addr & 0x00ff) | ((value & 0x3f) << 8); + ppu->write_latch = 1; + } else { + ppu->temp_addr = (ppu->temp_addr & 0xff00) | value; + ppu->vram_addr = ppu->temp_addr; + ppu->write_latch = 0; + } + // ppu->open_bus = value; + + } else if(reg == 7) { + uint32_t addr = ppu->vram_addr; + if(LIKELY(addr < 0x2000)) { + state->mapper.chr_write(state, addr, value); + + } else if(LIKELY(addr < 0x3f00)) { + state->mapper.ciram_write(state, addr, value); + + } else if(addr < 0x4000) { + uint32_t pal_addr = addr & 0x1f; + if((pal_addr & 3) == 0) { + pal_addr &= ~0x10; + } + ppu->palette[pal_addr] = value; + } + ppu->vram_addr += (ppu->reg_ctrl & 0x04) ? 32 : 1; + // ppu->open_bus = value; + } + + ppu->open_bus = value; + +#if 0 switch(offset & 7) { case 0: { // 2000 ppu->reg_ctrl = value; @@ -67,6 +130,7 @@ static inline void ppu_write(struct nes_state *state, uint32_t offset, uint8_t v ppu->open_bus = value; } break; } +#endif } __attribute__((always_inline, hot)) @@ -74,6 +138,39 @@ static inline uint8_t ppu_read(struct nes_state *state, uint32_t offset) { struct ppu_state *ppu = &state->ppu; uint8_t result = ppu->open_bus; + uint32_t reg = offset & 0x7; + + if(reg == 2) { + result = ppu->reg_status; + ppu->reg_status &= ~0x80; + ppu->write_latch = 0; + + } else if(reg == 4) { + result = ppu->oam[ppu->oam_addr]; + + } else if(reg == 7) { + uint32_t addr = ppu->vram_addr; + + if(LIKELY(addr < 0x2000)) { + result = ppu->vram_read_buffer; + ppu->vram_read_buffer = state->mapper.chr_read(state, addr); + + } else if(LIKELY(addr < 0x3f00)) { + result = ppu->vram_read_buffer; + ppu->vram_read_buffer = state->mapper.ciram_read(state, addr); + + } else if(addr < 0x4000) { + uint32_t pal_addr = addr & 0x1f; + if((pal_addr & 0x13) == 0x10) { + pal_addr &= ~0x10; + } + result = ppu->palette[pal_addr]; + } + + ppu->vram_addr += (ppu->reg_ctrl & 0x04) ? 32 : 1; + } + +#if 0 switch(offset & 7) { case 2: { // 2002 result = ppu->reg_status; @@ -107,6 +204,8 @@ static inline uint8_t ppu_read(struct nes_state *state, uint32_t offset) { ppu->vram_addr += (ppu->reg_ctrl & 0x04) ? 32 : 1; } break; } +# endif + ppu->open_bus = result; return result; } @@ -118,9 +217,9 @@ static void ppu_dma_4014(struct nes_state *state, uint8_t page) { uint32_t base = page << 8; // Add 1 or 2 idle cycles depending on current CPU cycle - uint8_t idle_cycles = (state->cycles & 1) ? 1 : 2; + uint8_t idle_cycles = (state->cpu.cycles & 1) ? 1 : 2; for(uint8_t i = 0; i < idle_cycles; i++) { - state->cycles++; + state->cpu.cycles++; ppu_tick(state); // apu_tick(state); } @@ -128,12 +227,12 @@ static void ppu_dma_4014(struct nes_state *state, uint8_t page) { for(uint32_t i = 0; i < 256; i++) { uint32_t addr = base + i; - state->cycles++; + state->cpu.cycles++; ppu_tick(state); // apu_tick(state); uint8_t value = memory_read_dma(state, addr); - state->cycles++; + state->cpu.cycles++; ppu_tick(state); // apu_tick(state); |
