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.

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.

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.

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.

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.

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.)

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.

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.

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?

Who is online

Users browsing this forum: No registered users and 7 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum