This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

New here, and a question about CPU/PPU timing

New here, and a question about CPU/PPU timing
by on (#53383)
Hey guys, I've been working on an NES emulator for a while but only recently stumbled upon this forums, so first of all I wanted to say hi!

Here's a gallery of some shots of my emulator-in-progress. Keep in mind I have not looked at the source of any NES emulators. I have simply referenced the hardware tech manuals spread across the internet.

ImageImage
ImageImage

Of course when I'm done I'm releasing it open source and free. My goal is to code my system in such a way that it passes all of those timing and compatibility tests. It seems most emulators fail these tests due to inherit flaws (or shortcuts) in the way it emulates things. I am trying to code it to be as close to the real thing as possible, and plan on passing all of the test ROMs.

Anyway, I have classes for both the CPU, and the PPU. Both of them correctly take X amount of 'cycles' to do certain things (for example, page boundary crossing will cause certain instructions to take more cycles to execute).

The problem is, even after reading all of the docs out there, I'm still not sure how to properly determine the number of CPU cycles per PPU cycle. Can anyone give me any help on this? I'm looking for the math more than a simple spoon-fed answer.

Oh and also, would an IDE and compiler with debugging/tracing/stepping support be welcomed here for NES programming or are there already things for that? I was considering doing something like that once I get the emulator running smoothly.

Anyway, hello again and thanks in advance!

by on (#53387)
Nevermind, I'll answer myself. I found another doc that goes into much better detail about the PPU. It's 3 CPU cycles per PPU cycle, but it looks like I need to re-write my PPU logic to work on a per-cycle basis instead of a per-scanline one.

Although I do wonder if emulators properly drop the odd cycle on scanline 20 of every odd frame (NTSC color burst stuff)..
Re: New here, and a question about CPU/PPU timing
by on (#53391)
essial wrote:
Oh and also, would an IDE and compiler with debugging/tracing/stepping support be welcomed here for NES programming or are there already things for that?


Can you explain what this means? I can't speak for others, but programming for a console doesn't require (or even justify) an IDE; and compile what? Are you using cc65 (and not the ca65 part) to write C on the NES?

If you're saying "Does anyone want a NES emulator with nametable viewing, a real-time debugger with breakpoints, stepping, conditionals, etc., as well as something that lets you view register status, PPU internal details, a CHR viewer/editor, etc.?" then the answer is more or less yes.

I'd like to see the debugging capabilities of numerous emulators (FCEUXD, Nintendulator, NESICIDE (so far the usability of the last one is basically nil)) combined into one, using the PPU accuracy portion of Nintendulator, but with the UI and overall usability ease + feature base of Nestopia.

A simpler version of what I said: Nestopia with all of the debugging features of the above 3 emulators combined, without losing the decently-written UI.

Oh, and if someone would get around to implementing blargg's APU core into a NES emulator, that'd be preferred as well. Damn, I'm just asking for everything under the Christmas tree aren't I?

At present, at least if you're using emulators for debugging/development, you end up having to use 3 or 4 separate emulators to achieve a development environment.

by on (#53392)
essial wrote:
Nevermind, I'll answer myself. I found another doc that goes into much better detail about the PPU. It's 3 CPU cycles per PPU cycle

Backwards?

Quote:
but it looks like I need to re-write my PPU logic to work on a per-cycle basis instead of a per-scanline one.

True, in part because a couple games use mid-scanline raster effects. But you can still run the PPU for an entire scanline at a time as long as the CPU "timestamps" all writes to the PPU. Special handling is needed for reads from PPU register $2002 in lines close to sprite 0 and cases where a mapper watching the PPU can interrupt the CPU, like MMC3.

Quote:
Although I do wonder if emulators properly drop the odd cycle on scanline 20 of every odd frame (NTSC color burst stuff)..

Blargg probably has a test for it.
Re: New here, and a question about CPU/PPU timing
by on (#53395)
koitsu wrote:
Can you explain what this means? I can't speak for others, but programming for a console doesn't require (or even justify) an IDE; and compile what? Are you using cc65 (and not the ca65 part) to write C on the NES?

Well would it not be helpful to trace through lines of code step by step, and evaluate registers on each line during execution? Also although I haven't done any NES dev yet, from writing this emulator I can tell that you need editors for creating SPR data, as well as sound.

As far as the IDE goes, it would just be a central place for all NES editing. You can simply file->new project, and do all of your code, graphics, and sound through the IDE, and when you run the game in debug mode, it can break on lines and let you trace through and inspect certain values, as well as registers. Maybe other helpful info like current scanline and current scanline position and such as well.

koitsu wrote:
If you're saying "Does anyone want a NES emulator with nametable viewing, a real-time debugger with breakpoints, stepping, conditionals, etc., as well as something that lets you view register status, PPU internal details, a CHR viewer/editor, etc.?" then the answer is more or less yes.

I'd like to see the debugging capabilities of numerous emulators (FCEUXD, Nintendulator, NESICIDE (so far the usability of the last one is basically nil)) combined into one, using the PPU accuracy portion of Nintendulator, but with the UI and overall usability ease + feature base of Nestopia.


Well without over complicating things, I figure if I get the emulator emulating as accurately as possible, then provide tools for tracing into the code, as well as SPR RAM viewing and other things, that would be of help to developers. Obviously once I get to this point I'll post back for suggestions.

As for UI, I'm not currently settled on an API for this. Since I use libSDL for the drawing, my knee-jerk reaction is to create a UI in it directly, but I do not think this is a good idea. I think I will end up using either gtk or wxWidgets for the UI interface, I prefer native UIs over custom ones.

koitsu wrote:
A simpler version of what I said: Nestopia with all of the debugging features of the above 3 emulators combined, without losing the decently-written UI.


I'm not sure which "features" each individual emulator has. But if I make my emulator pass as many compatibility tests as possible, and emulate all of the major mappers as well, I'm assuming it will be fine to come back here and ask you guys what debugging/editing features you'd like to see.

koitsu wrote:
Oh, and if someone would get around to implementing blargg's APU core into a NES emulator, that'd be preferred as well.


APU core? I know of Blarggs NTSC filtering and I have sent him an email directly already. I plan on using his NTSC filtering exclusively to produce as true-to-form of a display output as possible.

koitsu wrote:
Damn, I'm just asking for everything under the Christmas tree aren't I?

Well, it is December :D But I doubt I'll be finished anytime close to christmas.. I've been working on it for 2 months in my free time already.

by on (#53397)
tepples wrote:
essial wrote:
Nevermind, I'll answer myself. I found another doc that goes into much better detail about the PPU. It's 3 CPU cycles per PPU cycle

Backwards?


OK, I'll try to do the math, and correct me if I'm wrong about any of this.

The NES as a master clock that runs at 21.477272mhz. The CPU divisor is 12, which results in a CPU clock of roughly 1.7897727mhz. The PPU runs with a divisor of 4, which results in a PPU clock of roughly 5.369318mhz

So yeah, since the CPU seems to runs slower than the PPU, the ratio of CPU:PPU would be
5.369318(ppu) / 1.7897727(cpu) = 2.999999944126983x

So from the math above, I was wrong and you are right, ~3 PPU cycles per CPU cycle. But the decimal points tell me that I need to add timing logic for the PPU instead of simply running it once per loop.

Let me know if this looks right/wrong to you.

by on (#53398)
essial wrote:
But the decimal points tell me that I need to add timing logic for the PPU instead of simply running it once per loop.

If you think about it the CPU is divided by 12, the PPU by 4, exactly. That makes exactly 3 PPU cycles for every CPU, you're looking at round-off error. When I tinkered with emulation I synced everything to the CPU and only caught up the PPU on any PPU actions. The CPU was then synced to the screen update, pretty easy solution.

by on (#53399)
kyuusaku wrote:
essial wrote:
But the decimal points tell me that I need to add timing logic for the PPU instead of simply running it once per loop.

If you think about it the CPU is divided by 12, the PPU by 4, exactly. That makes exactly 3 PPU cycles for every CPU, you're looking at round-off error.


*facepalm*

I can write an 2A03 CPU emulator but I couldn't immediately see that 12/4 ratio. Wow.
Re: New here, and a question about CPU/PPU timing
by on (#53401)
essial wrote:
Of course when I'm done I'm releasing it open source and free. My goal is to code my system in such a way that it passes all of those timing and compatibility tests. It seems most emulators fail these tests due to inherit flaws (or shortcuts) in the way it emulates things. I am trying to code it to be as close to the real thing as possible, and plan on passing all of the test ROMs.

Just a word of warning.. we still don't know everything about how the NES operates on hardware level. We've come a long way from Marat's NES.DOC but there are still a lot of small details that remain unknown. So writing an accurate emulator isn't as simple as reading one or two documents.

Quote:
Oh and also, would an IDE and compiler with debugging/tracing/stepping support be welcomed here for NES programming or are there already things for that? I was considering doing something like that once I get the emulator running smoothly.

I think this would be great, there was some discussion about this on some other thread a month or two ago. If you do end up making one, I think it would be best to make the debugger use a custom API so it could be used with other emulators too.

Nintendulator already has a built-in debugger. FCEUX does too, but it doesn't have quite as accurate emulation as Nintendulator. They're both pretty good but not perfect. I want to see the original source code when debugging! :) (This would of course need to be supported by the assembler/compiler.)
Re: New here, and a question about CPU/PPU timing
by on (#53403)
thefox wrote:
Just a word of warning.. we still don't know everything about how the NES operates on hardware level. We've come a long way from Marat's NES.DOC but there are still a lot of small details that remain unknown. So writing an accurate emulator isn't as simple as reading one or two documents.

Good thing I'm in the process of breaking down my NES to analyze the circuits and test things. Eventually I hope to write a few test roms, run it through with the monitoring tools, and see the results to test accuracy.

thefox wrote:
I think this would be great, there was some discussion about this on some other thread a month or two ago. If you do end up making one, I think it would be best to make the debugger use a custom API so it could be used with other emulators too.

There are several methods I was thinking of. The least invasive is to simply establish a local socket connection (to keep it cross platformy), and send it PC addresses to halt out, as well as commands to set, and to query regs and memory values and such.

thefox wrote:
Nintendulator already has a built-in debugger. FCEUX does too, but it doesn't have quite as accurate emulation as Nintendulator. They're both pretty good but not perfect. I want to see the original source code when debugging! :) (This would of course need to be supported by the assembler/compiler.)

For this would require writing an assembler/compiler. I have not looked at the source of any 6502 compilers yet so I don't know how easy it would be to slip in code breaks and stepping yet. I already plan on an inline disassembler for the CPU debugger in the actual emulator though.

by on (#53420)
The idea of an IDE would be interesting since I mentioned it a few time. But one thing for sure, it would be better to support an existing assembler like ca65 than to build another one, unless there is no way to integrate ca65 in some way. Building your own assembler means more work too.

by on (#53421)
Banshaku wrote:
The idea of an IDE would be interesting since I mentioned it a few time. But one thing for sure, it would be better to support an existing assembler like ca65 than to build another one, unless there is no way to integrate ca65 in some way. Building your own assembler means more work too.


I'll look into it. If it's open source I'll be in business. If not, I'll see if I can still use it, there's a few tricks you can use provided it supports certain output file types.

by on (#53429)
http://www.cc65.org/

All components except the C compiler are under the same permissive license as zlib and libpng.

by on (#53437)
They have the source. Perfect, looks like that's one thing I can strike off my list!

Also, I completely ripped out the PPU rendering engine (ouch) and put in the NTSC filtering library. I had a lot of problems that needed to be fixed, plus the fundamental flaw of it rendering per-scanline. Anyway, we'll see how far I can get tonight, hopefully I'll have a nice screen showing tomorrow (doubtful though :p).
Re: New here, and a question about CPU/PPU timing
by on (#53444)
essial wrote:
For this would require writing an assembler/compiler. I have not looked at the source of any 6502 compilers yet so I don't know how easy it would be to slip in code breaks and stepping yet. I already plan on an inline disassembler for the CPU debugger in the actual emulator though.

First, koitsu, thanks for the honesty! [seriously] I realize that the currently available NESICIDE is not very useable. I continue to strive to make it more so. There's just too much users want...

Hello essial, you seem to be in the same line of thought as me. The version of NESICIDE that is available online is from a year ago now and, at the time, I had built my own assembler into it. I quickly realized after releasing it and getting honest and helpful feedback from the users here and elsewhere, that one man's assembler isn't every man's assembler. Thus, one of the changes-in-direction I have taken is to allow use of external assemblers, and hopefully eventually compilers and linkers [though I sense less of a need/desire for that].

I also struggled with whether or not to embed an available assembler into the tool. I tried it with ASM6 and CA65. But that poses other problems like having to release new versions of the IDE when new versions of the assembler are available [and there was just an update to ASM6 a month or so ago], having to re-do whatever work was necessary to rig the assembler so it could be embedded in the tool, etc. After that, I concluded: not worth it.

With regard to emulator accuracy, I went through the same growing pain. The emulator in the available version is scanline based. The one I have now is pixel-based, and passes quite a few of the test ROMs. Like you, I have a class for the CPU, APU, and PPU, but have been stripping away much of the ++ of the C++ to gain performance. It turns out that once you add things like: inline disassembler, execution tracer, Code/Data logger, PPU viewer, NameTable viewer, OAM viewer, and joypad logger/editor, that you screen-update at 60Hz [data updating at CPU or PPU clocks as in execution tracer] along with your emulation engine, time is of the essence. :D

by on (#53446)
Have you tried threading your application? Most PCs now have multiple cores, and I'm pretty sure your emulator is running on a single core. Believe it or not my emulator is designed from the get-go to support dual-core processing. Obviously certain operations require a lock that bottlenecks performance, but if 50% of the time, things are going 200% as fast, that's still a 150% improvement in engine speed, and that's nothing to shake a stick at.