I uploaded some code to the svn. It's all of the current source. It compiles, but does not really do very much. The PPU is only partially implemented. I've implemented maybe half of the registers that the CPU and PPU use to interact and there's no attempt yet to implement the graphics.
What I have done is emulated a very small portion of the PPU so that it updates the status register with vblanks occasionally. This allows me to look through the logs and see what the project is doing. I cleared up a couple small bugs that were making the CPU error out and quit. It's still hitting a spot somewhere where it's running into an unemulated opcode and I'm trying to figure out if that's a legitimate code or a spot where my cpu has done something unexpected and has jumped the tracks.
The CPU used by the NES uses a byte of memory for each opcode. This means that there are potentially 256 different opcodes that can exist. However, the CPU only officially use something like 150 of those opcodes. The other 100 or so opcodes do things in the CPU, and it wouldn't surprise me if they were occasionally used in production code, but I have decided to capture these codes instead of implementing them. At least for the moment.
So, my CPU hits one of these illegal codes at a point and I'm trying to figure out if this means I need to implement one of these illegal codes that were legitimately put in the source by the programmer, or if it means that my CPU has done something wrong and is now pulling non-opcode data from memory and treating it like it's an opcode. This involves running the CPU for a while and then going through the logs to see what the CPU is doing. I found a disassembled and heavily commented Super Mario source file on the internet and I compare that to what my CPU is doing. I try to figure out what the code is supposed to be doing and make sure the CPU is doing that. It involves looking at a lot of assembly code. It's really gratifying to see my CPU hit these loops in the source and function properly. It's kind of amazing.
So far as I can see, the code never gets to the point that it's setting up the VRAM. This part is essential before I can start implementing the graphical portion of the application. The character ram that is pulled from the cartridge only contains a portion of the actual character information. I'll probably talk more about that when I actually start implementing that.
One thing I'm seeing is that my CPU is SLOW. It also does a metric shit ton of logging. I'm debugging right now, so I'm not all that concerned about it, but at one point or another I will have to do a significant amount of optimization.
I hope to have these very small, but important issues settled in the next few weeks. Once the code appears to be more or less running appropriately and is setting up all of the memory correctly I'll be able to start working on the graphics output. That ought to be kind of fun, but a little daunting.
I'm doing pretty much the same thing as you are, trying to write an emulator to learn more about the NES.
ReplyDeleteI wouldn't use Super Mario Brothers as a test until you at least have the basic PPU code working, since without a Sprite 0 hit it'll just freeze before drawing the title screen. Try Balloon Fight or maybe the nestest ROM that's available on the NESDev wiki. That one is especially good since there's a complete accurate log of what instructions are executed available which is invaluable for tracking down CPU bugs.
Anyway, my code so far is at http://code.google.com/p/halfnes/ but please don't use it as a reference, because it lacks accuracy and good design.