| @@ -24,8 +24,6 @@ static int nes_apu_run(nes_APU* apu, nes_Memory* core_mem, | |||||
| // TODO: 0x00 - 0x13 | // TODO: 0x00 - 0x13 | ||||
| // TODO: 0x15 | // TODO: 0x15 | ||||
| case 0x17: // Frame Counter | case 0x17: // Frame Counter | ||||
| (void)val; | |||||
| #if 0 | |||||
| val &= (apu_Frame_Mode | apu_Frame_Inhibit); | val &= (apu_Frame_Mode | apu_Frame_Inhibit); | ||||
| apu->frame_reg = val; | apu->frame_reg = val; | ||||
| apu->frame = 0; | apu->frame = 0; | ||||
| @@ -34,15 +32,14 @@ static int nes_apu_run(nes_APU* apu, nes_Memory* core_mem, | |||||
| if (val & apu_Frame_Mode) { | if (val & apu_Frame_Mode) { | ||||
| // TODO | // TODO | ||||
| /* | /* | ||||
| nes_apu_clock_quarter_frame(apu); | |||||
| nes_apu_clock_half_frame(apu); | |||||
| nes_apu_clock_quarter_frame(apu, core_mem); | |||||
| nes_apu_clock_half_frame(apu, core_mem); | |||||
| */ | */ | ||||
| } | } | ||||
| if (val & apu_Frame_Inhibit) { | if (val & apu_Frame_Inhibit) { | ||||
| mem->status &= ~apu_Status_Frame_Int; | mem->status &= ~apu_Status_Frame_Int; | ||||
| } | } | ||||
| #endif | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -118,3 +115,7 @@ int nes_apu_finish_qframe(nes_APU* apu, nes_Memory* core_mem) { | |||||
| apu->ticks_handled = apu->frame_delay; | apu->ticks_handled = apu->frame_delay; | ||||
| return nes_apu_run(apu, core_mem, apu->frame_delay); | return nes_apu_run(apu, core_mem, apu->frame_delay); | ||||
| } | } | ||||
| int nes_apu_process(nes_APU* apu, nes_Memory* core_mem) { | |||||
| return nes_apu_run(apu, core_mem, 0); | |||||
| } | |||||
| @@ -101,8 +101,10 @@ 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); | ||||
| int nes_apu_hsync(nes_APU*, struct nes_Memory*); | int nes_apu_hsync(nes_APU*, struct nes_Memory*); | ||||
| int nes_apu_finish_qframe(nes_APU*, struct nes_Memory*); | int nes_apu_finish_qframe(nes_APU*, struct nes_Memory*); | ||||
| int nes_apu_process(nes_APU*, struct nes_Memory*); | |||||
| #endif // NESE_APU_H_ | #endif // NESE_APU_H_ | ||||
| @@ -263,23 +263,6 @@ static inline int f6502_write(nes_Memory* mem, | |||||
| case 0x4000: | case 0x4000: | ||||
| switch (addr & 0x1FU) { | switch (addr & 0x1FU) { | ||||
| case 0x17: // APU Frame | |||||
| { f6502_Core* core = container_of(mem, f6502_Core, memory); | |||||
| nes* sys = container_of(core, nes, core); | |||||
| nes_APU* apu = &sys->apu; | |||||
| // printf("APU: $%04X < %02X\n", addr, val); | |||||
| apu->frame_reg = val; | |||||
| apu->frame = 0; | |||||
| apu->frame_delay = nes_apu_quarter_frame_ticks; | |||||
| // Clear this ASAP | |||||
| if (val & apu_Frame_Inhibit) { | |||||
| mem->apu.status &= ~apu_Status_Frame_Int; | |||||
| f6502_set_IRQ(core, 0); | |||||
| } | |||||
| } | |||||
| case 0x00: | case 0x00: | ||||
| case 0x01: | case 0x01: | ||||
| case 0x02: | case 0x02: | ||||
| @@ -301,6 +284,7 @@ static inline int f6502_write(nes_Memory* mem, | |||||
| case 0x12: | case 0x12: | ||||
| case 0x13: | case 0x13: | ||||
| case 0x15: // APU Status | case 0x15: // APU Status | ||||
| case 0x17: // APU Frame | |||||
| 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 { | ||||
| @@ -310,6 +294,18 @@ static inline int f6502_write(nes_Memory* mem, | |||||
| .val = val, | .val = val, | ||||
| }; | }; | ||||
| } | } | ||||
| // APU Frame | |||||
| if (0x17 == (addr & 0x1FU)) { | |||||
| f6502_Core* core = container_of(mem, f6502_Core, memory); | |||||
| nes* sys = container_of(core, nes, core); | |||||
| nes_APU* apu = &sys->apu; | |||||
| nes_apu_process(apu, mem); | |||||
| if (val & apu_Frame_Inhibit) { | |||||
| f6502_set_IRQ(core, 0); | |||||
| } | |||||
| } | |||||
| break; | break; | ||||
| case 0x14: // OAM DMA | case 0x14: // OAM DMA | ||||