Просмотр исходного кода

Add IRQ to MMC3 mapper

- Gun Nac still crashing after first title screen
 - SMB3 halts after game start
master
Nathaniel Walizer 1 год назад
Родитель
Сommit
7507dc30f8
5 измененных файлов: 69 добавлений и 20 удалений
  1. +30
    -15
      src/map/mmc3.c
  2. +22
    -1
      src/mapper.h
  3. +5
    -0
      src/nes.c
  4. +9
    -1
      src/ppu.c
  5. +3
    -3
      src/ppu.h

+ 30
- 15
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,
};

+ 22
- 1
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[];




+ 5
- 0
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);
}



+ 9
- 1
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;


+ 3
- 3
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)



Загрузка…
Отмена
Сохранить