Hi, I have been trying to track down an issue in my emulator where my VBlank flag appears to be incorrect. The easiest way to explain this is to see the two traces below. The first trace is from my emulator whereas the second one is from Mesen.
From my emulator
From Mesen
From my understanding, the PPU is supposed to set the VBlank flag on scanline = 241 and cycle = 1. The CPU will then execute BIT $2002 instruction to read the state of the VBlank flag. The BIT $2002 instruction will read the status register ($2002) in the PPU and set the negative (N) flag in the CPU status register (P) equal to the VBlank flag. With this understanding, it appears that my emulator is behaving correctly. However, when comparing the trace for my emulator with Mesen's emulator, my emulator seems to be setting the VBlank flag too late. If you look at the traces above, my P flag gets set to $86 on line #4, whereas in the Mesen trace, it gets set on line #2.
Also, what's puzzling me, is that in the Mesen's trace, even though the BIT $2002 gets executed (line #1 in Mesen trace) which reads $00, the CPU status register gets updated magically to $86. Is there some documentation that describes this behavior?
One idea I had to get the similar behavior as Mesen was in my CPU logic, to always set the N flag in my P register when the PPU has scanline = 241 and cycle = 1. This seems like a hack though and I am not sure whether I would end up with issues in the future.
From my emulator
Code:
0 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:06 SP:F9 CYC:333 SL:240 FC:2 CPU Cycle:27381
1 E484 $2C $02 $20 BIT $2002 = $00 >>>>> A:00 X:00 Y:00 P:06 SP:F9 CYC:1 SL:241 FC:2 CPU Cycle:27384
2 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:06 SP:F9 CYC:13 SL:241 FC:2 CPU Cycle:27388
3 E484 $2C $02 $20 BIT $2002 = $80 A:00 X:00 Y:00 P:06 SP:F9 CYC:22 SL:241 FC:2 CPU Cycle:27391
4 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:86 SP:F9 CYC:34 SL:241 FC:2 CPU Cycle:27395
5 E489 $60 RTS A:00 X:00 Y:00 P:86 SP:F9 CYC:40 SL:241 FC:2 CPU Cycle:27397
1 E484 $2C $02 $20 BIT $2002 = $00 >>>>> A:00 X:00 Y:00 P:06 SP:F9 CYC:1 SL:241 FC:2 CPU Cycle:27384
2 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:06 SP:F9 CYC:13 SL:241 FC:2 CPU Cycle:27388
3 E484 $2C $02 $20 BIT $2002 = $80 A:00 X:00 Y:00 P:06 SP:F9 CYC:22 SL:241 FC:2 CPU Cycle:27391
4 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:86 SP:F9 CYC:34 SL:241 FC:2 CPU Cycle:27395
5 E489 $60 RTS A:00 X:00 Y:00 P:86 SP:F9 CYC:40 SL:241 FC:2 CPU Cycle:27397
From Mesen
Code:
0 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:06 SP:F9 CYC:333 SL:240 FC:2 CPU Cycle:27381
1 E484 $2C $02 $20 BIT $2002 = $00 >>>> A:00 X:00 Y:00 P:06 SP:F9 CYC:1 SL:241 FC:2 CPU Cycle:27384
2 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:86 SP:F9 CYC:13 SL:241 FC:2 CPU Cycle:27388
3 E489 $60 RTS A:00 X:00 Y:00 P:86 SP:F9 CYC:19 SL:241 FC:2 CPU Cycle:27390
4 E0C7 $20 $81 $E4 JSR $E481 = $2C A:00 X:00 Y:00 P:86 SP:FB CYC:37 SL:241 FC:2 CPU Cycle:27396
5 E481 $2C $02 $20 BIT $2002 = $00 A:00 X:00 Y:00 P:86 SP:F9 CYC:55 SL:241 FC:2 CPU Cycle:27402
1 E484 $2C $02 $20 BIT $2002 = $00 >>>> A:00 X:00 Y:00 P:06 SP:F9 CYC:1 SL:241 FC:2 CPU Cycle:27384
2 E487 $10 $FB BPL $E484 = $2C A:00 X:00 Y:00 P:86 SP:F9 CYC:13 SL:241 FC:2 CPU Cycle:27388
3 E489 $60 RTS A:00 X:00 Y:00 P:86 SP:F9 CYC:19 SL:241 FC:2 CPU Cycle:27390
4 E0C7 $20 $81 $E4 JSR $E481 = $2C A:00 X:00 Y:00 P:86 SP:FB CYC:37 SL:241 FC:2 CPU Cycle:27396
5 E481 $2C $02 $20 BIT $2002 = $00 A:00 X:00 Y:00 P:86 SP:F9 CYC:55 SL:241 FC:2 CPU Cycle:27402
From my understanding, the PPU is supposed to set the VBlank flag on scanline = 241 and cycle = 1. The CPU will then execute BIT $2002 instruction to read the state of the VBlank flag. The BIT $2002 instruction will read the status register ($2002) in the PPU and set the negative (N) flag in the CPU status register (P) equal to the VBlank flag. With this understanding, it appears that my emulator is behaving correctly. However, when comparing the trace for my emulator with Mesen's emulator, my emulator seems to be setting the VBlank flag too late. If you look at the traces above, my P flag gets set to $86 on line #4, whereas in the Mesen trace, it gets set on line #2.
Also, what's puzzling me, is that in the Mesen's trace, even though the BIT $2002 gets executed (line #1 in Mesen trace) which reads $00, the CPU status register gets updated magically to $86. Is there some documentation that describes this behavior?
One idea I had to get the similar behavior as Mesen was in my CPU logic, to always set the N flag in my P register when the PPU has scanline = 241 and cycle = 1. This seems like a hack though and I am not sure whether I would end up with issues in the future.