How important is cycle accuracy for the CPU ?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
How important is cycle accuracy for the CPU ?
by on (#172726)
If my instructions don't take the exact cycles/time as documented (but close..), how disastrous would the emulation be ?
Re: How important is cycle accuracy for the CPU ?
by on (#172728)
Depends on your goals. You will be able to run a lot of games even with an inaccurately timed CPU.
Re: How important is cycle accuracy for the CPU ?
by on (#172731)
As far as I can tell you, the CPU emulation doesn't require a cycle counter. Just do all the required steps for each instruction, like reads/writes, setting flags etc. The accuracy is there. On other side, the PPU communicates directly with the CPU - it sets flags like VBlank, NMI and so on. All of these things are necessary for the CPU running "to be possible".
In short words, the PPU emulation is linked with the CPU, cannot work alone.
Re: How important is cycle accuracy for the CPU ?
by on (#172733)
A while back, I had a bug in the "instruction takes an extra cycle if a page is crossed" logic, for indirect X & Y addressing.

This caused a small portion of instructions to sometimes take an extra cycle - this broke at least 2 games that I was aware of (and in reality it probably broke a lot more than this).
In elevator action, the extra cycles caused the NMI handler to take too many cycles, and it couldn't finish before the next frame started drawing, causing pretty obvious scrolling bugs on the screen. It also caused Battletoads to do its typical freeze at the start of level 1, because of a missed sprite 0 hit.

So it seems like even a minor error in the amount of cycles an instruction takes can cause bugs in a good amount of games.
Re: How important is cycle accuracy for the CPU ?
by on (#172735)
If you want to run Battletoads without a shaky screen/crashes, you need to have the instructions take the proper number of cycles, including page crossing penalties.
Re: How important is cycle accuracy for the CPU ?
by on (#172737)
Thank you for all the responses!
I am going to first get a basic CPU running and care later about the cycle accuracy.

Quote:
A while back, I had a bug in the "instruction takes an extra cycle if a page is crossed" logic, for indirect X & Y addressing.

This caused a small portion of instructions to sometimes take an extra cycle - this broke at least 2 games that I was aware of (and in reality it probably broke a lot more than this).


I had this doubt as well! So now I know it *does* matter.
BTW, can anyone verify this "check" if two addresses (a and b) are in different pages ?
Code:
(a % 0x100) != (b % 0x100)

I cannot find much information about "pages", so my logic went like this: Zero Page is 0x100 i.e. 256 bytes long thus that must be the size of a page, and the above is what I came up thinking if the pages are aligned.
Re: How important is cycle accuracy for the CPU ?
by on (#172749)
No, it's not. It should be (a / 0x100) != (b / 0x100), or (a >> 8) != (b >> 8), or (a & 0xFF00) != (b & 0xFF00). Essentially you should be extracting the high 8 bits (= the page) from the addresses and comparing them.
Re: How important is cycle accuracy for the CPU ?
by on (#172751)
As for the question about how important cycle accuracy is...
Some people use the term "cycle accuracy" to mean emulating the stages of an instruction one by one, including the fetch, memory read, memory write, etc, and also emulating everything the PPU does during those stages. I think it's overkill, catching up significant events is good enough. As long as you get the timing correct for the read/write stage when external hardware is involved, it should be good enough. I actually cheat there and assume that it's always 12 dots from the start of the instruction to the read/write stage.
I think you just mean the correct number of cycles for instructions.

If you are running games which do not do any raster effects at all, such as Megaman and Megaman II, cycle accuracy doesn't matter much at all. Those are some of the simplest games to emulate, even more simple than Super Mario Bros.
But games will use sprite 0 hits, timed code, interrupts at specific PPU timings, and timed scroll writes in the middle of the screen, so getting the timing right for those events matters to avoid shaky screens and stuff.
Re: How important is cycle accuracy for the CPU ?
by on (#172756)
Quote:
Code:
(a / 0x100) != (b / 0x100)

Ah, yes, that's what I was meaning to code, I mistakenly put mod.
Also appreciate those binary shortcuts/alternatives.

Quote:
I think you just mean the correct number of cycles for instructions.

Yup, that's what I meant!
I'm just completing the entire instruction at one cycle, then skip/stall the remaining cycles. I hope that's good enough.

Also, this is just an education "for-fun" project, I am not aiming for perfect accuracy and 100% game coverage.
Re: How important is cycle accuracy for the CPU ?
by on (#172757)
Even if you simulate the whole instruction at once, it might be better to advance the time by 12 dots before the PPU sees a write, because scrolling has such tight timing. The scrolling increment happens at dot 256 of a scanline, so you can treat it as if it happens 12 dots sooner and still avoid most scrolling glitches.
Re: How important is cycle accuracy for the CPU ?
by on (#172760)
What do you mean by a dot ?
A "pixel" in NES ?

P.S. I've only started with the CPU, haven't touched the PPU or any other part yet.
Re: How important is cycle accuracy for the CPU ?
by on (#172767)
On the NTSC NES, for every 1 CPU cycle executed, the PPU draws 3 pixels. Sometimes they are called PPU cycles, sometimes they are called dots.
NTSC NES has 240 visible scanlines, 1 pre-vblank line, 20 vblank lines, and 1 pre-render line. Each scanline is 341 dots wide, the visible area is 256 pixels.
This makes for a total of 341*262 (89342) PPU cycles, or 341*262/3 (29780.66...) CPU cycles per frame.

(On every other frame, one dot is skipped from the pre-render line if rendering is enabled.)
Re: How important is cycle accuracy for the CPU ?
by on (#172802)
My own opinion is that the emulator is not really correct (even though it may be good enough for many things) if it doesn't have cycle accuracy. Each read/write must be done during the proper cycle, in order to properly interact with the mapper and PPU and APU and so on. Cycle accuracy is not as important for CPU register writes though, since as long as the new value of the registers is ready for the next instruction, it does not matter during exactly what cycle they are set. So for example, it is OK to read and do the correct calculation for the address and data as soon as possible, even though the next cycle does not necessarily use correct address/data; what matters is that the externally visible behaviour of all stable instructions matches what is seen on NMOS 6502 without decimal arithmetic. Due to the possibility that the PPU registers, APU registers, and mapper registers, might be touched in the middle of execution of an instruction, it must access them during the correct cycle, and the PPU and so on must know what cycle it is written during in order to time the rendering properly in case it touches them during rendering. But, what mechanisms exactly are used to implement this correct behaviour is up to you; there can be more than one possibility to do it.
Re: How important is cycle accuracy for the CPU ?
by on (#172815)
@Dweddit

Thanks! I'll keep your "cheat" in mind.

zzo38 wrote:
My own opinion is that the emulator is not really correct (even though it may be good enough for many things) if it doesn't have cycle accuracy. Each read/write must be done during the proper cycle, in order to properly interact with the mapper and PPU and APU and so on. Cycle accuracy is not as important for CPU register writes though, since as long as the new value of the registers is ready for the next instruction, it does not matter during exactly what cycle they are set. So for example, it is OK to read and do the correct calculation for the address and data as soon as possible, even though the next cycle does not necessarily use correct address/data; what matters is that the externally visible behaviour of all stable instructions matches what is seen on NMOS 6502 without decimal arithmetic. Due to the possibility that the PPU registers, APU registers, and mapper registers, might be touched in the middle of execution of an instruction, it must access them during the correct cycle, and the PPU and so on must know what cycle it is written during in order to time the rendering properly in case it touches them during rendering. But, what mechanisms exactly are used to implement this correct behaviour is up to you; there can be more than one possibility to do it.


If I understand you correctly, only the PPU, APU and mapper registers need to touched in the proper cycle, the CPU registers. the ROM and the SRAM read-writes are malleable ?
I should say that I'm not really aiming for perfect emulation and 100% game coverage.
Re: How important is cycle accuracy for the CPU ?
by on (#172818)
amhndu wrote:
If I understand you correctly, only the PPU, APU and mapper registers need to touched in the proper cycle, the CPU registers. the ROM and the SRAM read-writes are malleable ?

Correct, with the proviso that some mappers "snoop" RAM writes by placing mapper registers at the same address as certain parts of RAM. This includes a few MMC1/MMC3 multicart mappers' outer bank registers as well as the bank registers in the NINA half of mapper 34. But so far, all such "snooping" that I'm aware of is not cycle sensitive.

amhndu wrote:
I should say that I'm not really aiming for perfect emulation and 100% game coverage.

So in other words, are you saying your project is type "a" (early stage) in this taxonomy?
Re: How important is cycle accuracy for the CPU ?
by on (#172819)
Quote:
So in other words, are you saying your project is type "a" (early stage) in this taxonomy?


Yes, that sounds about right.
Re: How important is cycle accuracy for the CPU ?
by on (#172843)
amhndu wrote:
If I understand you correctly, only the PPU, APU and mapper registers need to touched in the proper cycle, the CPU registers. the ROM and the SRAM read-writes are malleable ?
Yes, if the ROM/SRAM do not have side-effects (possibly with some mappers (even if none such currently exists) can have relevant timing-sensitive side-effects). But since the CPU accesses using one address space and PPU with other address space, it should treat the CPU's address space uniformly and always do the read/writes with the correct timing, and same with the PPU's address space. The A, X, Y, flags, stack pointer, and program counter in the CPU, and the internal calculations it uses, are not externally visible though, so it doesn't matter exactly when the registers are updated and when the calculations are performed, as long as it causes the correct sequence of read/writes, for example to add in the page-crossing penalty if applicable, and so on. For example, a read-modify-write on zero-page must result in the following sequence of operations: Read opcode, read next byte, read from effective address, write the old value to that address, write the new value to that address. During which step you calculate the new value and which step you set the flags is irrelevant, as long as they are done before the next instruction is executed.

Quote:
I should say that I'm not really aiming for perfect emulation and 100% game coverage.
That is OK, but then it isn't quite correct. I am saying that if I was making the emulator, I would want to aim for correctness. (Note that omitting some mappers does not make it incorrect, so a correct emulation does not necessarily do 100% game coverage anyways.)
Re: How important is cycle accuracy for the CPU ?
by on (#172848)
I recommend implementing mappers 0 (NROM/no mapper),1 (MMC1), 2 (UxROM), 3 (CNROM), and 7 (AxROM) first, since they are simple, easy, and widely used. It's nice to try to get Megaman working before Super Mario Bros :)
Re: How important is cycle accuracy for the CPU ?
by on (#172891)
Thank you very much, guys!