Skip to content

Commit 57a7912

Browse files
committed
fc: improve frame counter IRQ timing
1 parent f0e30e9 commit 57a7912

File tree

5 files changed

+35
-33
lines changed

5 files changed

+35
-33
lines changed

ares/fc/apu/apu.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ auto APU::tick() -> void {
7373
}
7474

7575
auto APU::setIRQ() -> void {
76-
cpu.apuLine(frame.irqPending | dmc.irqPending);
76+
cpu.apuLine((frame.irqPending & ~frame.irqInhibit) | dmc.irqPending);
7777
}
7878

7979
auto APU::power(bool reset) -> void {
@@ -103,8 +103,7 @@ auto APU::readIO(n16 address) -> n8 {
103103
//bit 5 is open bus
104104
data.bit(6) = frame.irqPending;
105105
data.bit(7) = dmc.irqPending;
106-
frame.irqPending = false;
107-
setIRQ();
106+
frame.delayIRQ = true;
108107
return data;
109108
}
110109

ares/fc/apu/apu.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ struct APU : Thread {
199199
n16 counter;
200200

201201
bool odd;
202-
bool delay;
203-
n3 delayCounter;
202+
bool delayIRQ;
203+
bool delayCounter[2];
204204

205205
constexpr static u16 periodNTSC[2][6] = {
206206
{ 7457, 7456, 7458, 7457, 1, 1, },

ares/fc/apu/framecounter.cpp

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@ auto APU::FrameCounter::main() -> void {
22
--counter;
33
odd = !odd;
44

5-
if (delay && --delayCounter == 0) {
6-
delay = false;
7-
step = 0;
8-
counter = getPeriod() + 2;
9-
if (mode == Freq48Hz) {
10-
apu.clockHalfFrame();
5+
if(!odd) {
6+
//IRQ is reset on next GET cycle
7+
if(delayIRQ) {
8+
delayIRQ = false;
9+
irqPending = 0;
10+
apu.setIRQ();
1111
}
12+
13+
//counter is reloaded on GET cycle after next
14+
if(delayCounter[0]) {
15+
step = 0;
16+
counter = getPeriod();
17+
if(mode == Freq48Hz) apu.clockHalfFrame();
18+
}
19+
delayCounter[0] = delayCounter[1];
20+
delayCounter[1] = false;
1221
}
1322

14-
if (counter != 0)
15-
return;
23+
if(counter != 0) return;
1624

1725
switch(step) {
1826
case 0:
@@ -29,21 +37,22 @@ auto APU::FrameCounter::main() -> void {
2937
break;
3038
case 3:
3139
step = 4;
32-
if (mode == Freq60Hz && irqInhibit == 0)
33-
irqPending = 1;
40+
if(mode == Freq60Hz) irqPending = 1;
3441
break;
3542
case 4:
3643
step = 5;
3744
apu.clockHalfFrame();
38-
if (mode == Freq60Hz && irqInhibit == 0) {
45+
if(mode == Freq60Hz) {
3946
irqPending = 1;
4047
apu.setIRQ();
4148
}
4249
break;
4350
case 5:
4451
step = 0;
45-
if (mode == Freq60Hz && irqInhibit == 0)
46-
irqPending = 1;
52+
if(mode == Freq60Hz) {
53+
irqPending = ~irqInhibit;
54+
apu.setIRQ();
55+
}
4756
break;
4857
}
4958

@@ -52,30 +61,24 @@ auto APU::FrameCounter::main() -> void {
5261

5362
auto APU::FrameCounter::power(bool reset) -> void {
5463
irqInhibit = 0;
55-
if (!reset) mode = Freq60Hz;
64+
if(!reset) mode = Freq60Hz;
5665

5766
irqPending = 0;
5867
step = 0;
5968
counter = getPeriod();
6069

6170
odd = true;
62-
delay = false;
63-
delayCounter = 0;
71+
delayIRQ = false;
72+
delayCounter[0] = false;
73+
delayCounter[1] = false;
6474
}
6575

6676
auto APU::FrameCounter::write(n8 data) -> void {
6777
mode = data.bit(7);
68-
delay = true;
69-
70-
// If the write occurs during an APU cycle,
71-
// the effects occur 3 CPU cycles after the
72-
// $4017 write cycle, and if the write occurs
73-
// between APU cycles, the effects occurs 4 CPU
74-
// cycles after the write cycle.
75-
delayCounter = odd ? 1 : 2;
78+
delayCounter[1] = true;
7679

7780
irqInhibit = data.bit(6);
78-
if (irqInhibit) {
81+
if(irqInhibit) {
7982
irqPending = 0;
8083
apu.setIRQ();
8184
}

ares/fc/apu/serialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,6 @@ auto APU::FrameCounter::serialize(serializer& s) -> void {
9595
s(counter);
9696

9797
s(odd);
98-
s(delay);
99-
s(delayCounter);
98+
s(delayIRQ);
99+
for(auto& delay : delayCounter) s(delay);
100100
}

ares/fc/system/serialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
static const string SerializerVersion = "v148";
1+
static const string SerializerVersion = "v149";
22

33
auto System::serialize(bool synchronize) -> serializer {
44
if(synchronize) scheduler.enter(Scheduler::Mode::Synchronize);

0 commit comments

Comments
 (0)