diff --git a/src/map/mmc3.c b/src/map/mmc3.c index 887f8d4..f237ef9 100644 --- a/src/map/mmc3.c +++ b/src/map/mmc3.c @@ -55,21 +55,15 @@ static inline void mmc3_update_rom_mode(mmc3_mapper* map) { static inline void mmc3_update_prg(mmc3_mapper* map, uint8_t bank) { int reg = (map->bank_select & mmc3_Bank_Select_Reg); - if (!(map->bank_select & mmc3_Bank_Select_PRG)) { - if (reg == 7) { - mmc3_map_prg(map, 1, bank); - } else { - mmc3_map_prg(map, 0, bank); - } - + if (reg == 7) { + mmc3_map_prg(map, 1, bank); } else { - if (reg == 7) { - mmc3_map_prg(map, 1, bank); + if (!(map->bank_select & mmc3_Bank_Select_PRG)) { + mmc3_map_prg(map, 0, bank); } else { mmc3_map_prg(map, 2, bank); } } - } static inline uint8_t* mmc3_chr_bank(mmc3_mapper* map, int bank) { @@ -169,7 +163,7 @@ static uint8_t mmc3_read(nes_mapper* nes_map, uint16_t addr) { } else if ( addr >= nes_mem_wram_start && (map->flags & mmc3_Flag_WRAM_Enabled)) { ptr = mmc3_wram_addr(map, addr); - MAP_LOG("WRAM: $%04x > %02x", addr, *ptr); +// MAP_LOG("WRAM: $%04x > %02x", addr, *ptr); } uint8_t val = (NULL == ptr ? 0 : *ptr); @@ -226,16 +220,36 @@ static void mmc3_write(nes_mapper* nes_map, } else if (addr < 0xE000U) { if (addr & 1) { - // TODO: IRQ reload + MAP_LOG("IRQ Reload"); + map->irq_count = 0; } else { - // TODO: IRQ latch + MAP_LOG("IRQ Latch: %d", val); + map->irq_latch = val; } } else { + MAP_LOG("IRQ %s", (addr & 1) ? "Enable" : "Disable"); if (addr & 1) { - // TODO: IRQ enable + map->flags |= mmc3_Flag_IRQ_Enabled; } else { - // TODO: IRQ disable + map->flags &= ~mmc3_Flag_IRQ_Enabled; + nes_map_trigger_irq(nes_map, 0); + } + } +} + +static void mmc3_scanline(nes_mapper* nes_map) { + mmc3_mapper* map = (mmc3_mapper*)nes_map->data; + + if (map->irq_count == 0) { + map->irq_count = map->irq_latch; + + } else { + map->irq_count--; + if ( map->irq_count <= 0 && + (map->flags & mmc3_Flag_IRQ_Enabled)) { + MAP_LOG("IRQ Trigger"); + nes_map_trigger_irq(nes_map, 1); } } } @@ -267,4 +281,5 @@ nes_mapper mapper_mmc3 = { .chr_addr = mmc3_chr_addr, .vram_addr = mmc3_vram_addr, .chr_write = mmc3_chr_write, + .scanline = mmc3_scanline, }; diff --git a/src/mapper.h b/src/mapper.h index 1aacb06..e98b36d 100644 --- a/src/mapper.h +++ b/src/mapper.h @@ -10,15 +10,23 @@ struct nes_cart_t; typedef struct nes_mapper_t { + void* data; + int (*init)(struct nes_mapper_t*, struct nes_cart_t* cart); void (*reset)(struct nes_mapper_t*); void (*done)(struct nes_mapper_t*); + uint8_t (*read)(struct nes_mapper_t*, uint16_t addr); void (*write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); + uint8_t* (*chr_addr)(struct nes_mapper_t*, uint16_t addr); uint8_t* (*vram_addr)(struct nes_mapper_t*, uint16_t addr); void (*chr_write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); - void* data; + + void (*scanline)(struct nes_mapper_t*); + void (*irq_callback)(void*, int); + void* irq_arg; + } nes_mapper; static inline int nes_map_init(nes_mapper* map, @@ -34,6 +42,18 @@ static inline void nes_map_done(nes_mapper* map) { map->done(map); } +static inline void nes_map_set_irq(nes_mapper* map, + void(*callback)(void*, int), + void* arg) { + map->irq_callback = callback; + map->irq_arg = arg; +} + +static inline void nes_map_trigger_irq(nes_mapper* map, + int active) { + map->irq_callback(map->irq_arg, active); +} + static inline uint8_t nes_map_read(nes_mapper* map, uint16_t addr) { return map->read(map, addr); @@ -75,6 +95,7 @@ static inline void nes_vram_write(nes_mapper* map, *(nes_map_vram_addr(map, addr)) = val; } + extern nes_mapper* nes_mappers[]; diff --git a/src/nes.c b/src/nes.c index b3e312b..985198e 100644 --- a/src/nes.c +++ b/src/nes.c @@ -58,9 +58,14 @@ void nes_mem_write(nes* sys, uint16_t addr, uint8_t val) { } } +static void nes_irq(void* sys, int active) { + e6502_set_irq(&((nes*)sys)->cpu, active); +} + int nes_init(nes* sys) { e6502_init(&sys->cpu, (e6502_Read*)nes_mem_read, (e6502_Write*)nes_mem_write, sys); + nes_map_set_irq(sys->cart.mapper, nes_irq, sys); return nes_ppu_init(&sys->ppu, &sys->cart); } diff --git a/src/ppu.c b/src/ppu.c index bf91625..1f619c7 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -195,7 +195,15 @@ int nes_ppu_init(nes_ppu* ppu, const nes_cart* cart) { int nes_ppu_run(nes_ppu* ppu, int cycles) { nes_ppu_Result result = ppu_Result_Running; - ppu->cycle += cycles; + int next_cycle = ppu->cycle + cycles; + + if ( NULL != ppu->mapper->scanline && + ppu->scanline < nes_ppu_render && + ppu->cycle < 260 && next_cycle >= 260) { + ppu->mapper->scanline(ppu->mapper); + } + + ppu->cycle = next_cycle; while (ppu->cycle >= nes_ppu_dots) { ppu->cycle -= nes_ppu_dots; diff --git a/src/ppu.h b/src/ppu.h index 3f563b9..3cfdcc1 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -38,9 +38,9 @@ struct nes_cart_t; #define nes_ppu_postrender (1U) #define nes_ppu_vblank (20U) -#define nes_ppu_active (nes_ppu_prerender + \ - nes_ppu_height + \ - nes_ppu_postrender) +#define nes_ppu_render (nes_ppu_prerender + nes_ppu_height) + +#define nes_ppu_active (nes_ppu_render + nes_ppu_postrender) #define nes_ppu_frame (nes_ppu_active + nes_ppu_vblank)