- Gun Nac still crashing after first title screen - SMB3 halts after game startmaster
| @@ -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, | |||
| }; | |||
| @@ -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[]; | |||
| @@ -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); | |||
| } | |||
| @@ -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; | |||
| @@ -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) | |||