| @@ -5,7 +5,7 @@ void nes_apu_init(nes_APU* apu, nes_APU_Memory* mem, int freq) { | |||||
| // TODO | // TODO | ||||
| } | } | ||||
| void nes_apu_hsync(nes_APU* apu, nes_Memory* core_mem) { | |||||
| int nes_apu_hsync(nes_APU* apu, nes_Memory* core_mem) { | |||||
| nes_APU_Memory* mem = &core_mem->apu; | nes_APU_Memory* mem = &core_mem->apu; | ||||
| for (int i = 0; i < core_mem->apu.n_events; ++i) { | for (int i = 0; i < core_mem->apu.n_events; ++i) { | ||||
| @@ -88,4 +88,8 @@ void nes_apu_hsync(nes_APU* apu, nes_Memory* core_mem) { | |||||
| apu->frame++; | apu->frame++; | ||||
| } | } | ||||
| } | } | ||||
| // TODO: DMC Interrupt | |||||
| return (mem->status & apu_Status_Frame_Int); | |||||
| } | } | ||||
| @@ -99,7 +99,7 @@ typedef struct { | |||||
| struct nes_Memory; | struct nes_Memory; | ||||
| void nes_apu_init(nes_APU* apu, nes_APU_Memory* mem, int freq); | void nes_apu_init(nes_APU* apu, nes_APU_Memory* mem, int freq); | ||||
| void nes_apu_hsync(nes_APU*, struct nes_Memory*); | |||||
| int nes_apu_hsync(nes_APU*, struct nes_Memory*); | |||||
| #endif // NESE_APU_H_ | #endif // NESE_APU_H_ | ||||
| @@ -90,8 +90,11 @@ static inline uint8_t f6502_read(nes_Memory* mem, | |||||
| case 0x4000: | case 0x4000: | ||||
| switch (addr & 0x1FU) { | switch (addr & 0x1FU) { | ||||
| case 0x15: | |||||
| return mem->apu.status; | |||||
| case 0x15: /* APU Status */ | |||||
| { uint8_t ret = mem->apu.status; | |||||
| mem->apu.status &= ~apu_Status_Frame_Int; | |||||
| return ret; | |||||
| } | |||||
| case 0x16: | case 0x16: | ||||
| case 0x17: | case 0x17: | ||||
| @@ -253,6 +256,13 @@ static inline int f6502_write(nes_Memory* mem, | |||||
| case 0x4000: | case 0x4000: | ||||
| switch (addr & 0x1FU) { | switch (addr & 0x1FU) { | ||||
| case 0x17: // APU Frame | |||||
| // TODO: Clear interrupt here? | |||||
| /* | |||||
| if (val & apu_Frame_apu_Frame_Inhibit) { | |||||
| f6502_Int_IRQ(core, 0); | |||||
| } | |||||
| */ | |||||
| case 0x00: | case 0x00: | ||||
| case 0x01: | case 0x01: | ||||
| case 0x02: | case 0x02: | ||||
| @@ -273,8 +283,7 @@ static inline int f6502_write(nes_Memory* mem, | |||||
| case 0x11: | case 0x11: | ||||
| case 0x12: | case 0x12: | ||||
| case 0x13: | case 0x13: | ||||
| case 0x15: | |||||
| case 0x17: | |||||
| case 0x15: // APU Status | |||||
| if (mem->apu.n_events >= APU_MAX_EVENTS) { | if (mem->apu.n_events >= APU_MAX_EVENTS) { | ||||
| LOGE("APU event buffer full"); | LOGE("APU event buffer full"); | ||||
| } else { | } else { | ||||
| @@ -33,9 +33,6 @@ static int nes_vsync(nes* sys, void* plat) { | |||||
| f6502_set_NMI(&sys->core, 1); | f6502_set_NMI(&sys->core, 1); | ||||
| } | } | ||||
| // TODO: APU Sync | |||||
| // TODO: APU Frame IRQ | |||||
| nes_Memory* mem = &sys->core.memory; | nes_Memory* mem = &sys->core.memory; | ||||
| if (0 == status && NULL != mem->mapper.vsync) { | if (0 == status && NULL != mem->mapper.vsync) { | ||||
| mem->mapper.vsync(&mem->mapper); | mem->mapper.vsync(&mem->mapper); | ||||
| @@ -48,7 +45,9 @@ static int nes_vsync(nes* sys, void* plat) { | |||||
| static int nes_hsync(nes* sys, void* plat) { | static int nes_hsync(nes* sys, void* plat) { | ||||
| int status = 0; | int status = 0; | ||||
| nes_apu_hsync(&sys->apu, &sys->core.memory); | |||||
| int irq = nes_apu_hsync(&sys->apu, &sys->core.memory); | |||||
| // TODO: How might this interfere with MMC3? | |||||
| f6502_set_IRQ(&sys->core, irq); | |||||
| if (sys->ppu.scanline < nes_ppu_postrender_line) { | if (sys->ppu.scanline < nes_ppu_postrender_line) { | ||||
| if (sys->ppu.scanline < nes_ppu_visible_line) { | if (sys->ppu.scanline < nes_ppu_visible_line) { | ||||