Sunday, October 24, 2010

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.

Wednesday, October 20, 2010

I have pretty much completed the cpu portion of the emulator. Emulating the cpu isn't very difficult. Its functionality is well known. It fetches an opcode, processes it, and updates multiple flags. Probably the hardest thing is finding documentation on what each opcode does exactly and how each flag is updated. Not too bad. Some documentation might be a little misleading or a little tough to read -- some of it is written by professional writers, but not much -- there's a lot of it, though, so if you don't understand something there are about 50 other places to look.

Emulating the ppu is a lot harder. Now we're getting into the meat of the system. Again, finding documentation is harder. Also, because the exact functionality of this portion of the system isn't as well understood by me I'm a lot more reliant on documentation. Not to mention the fact that the cpu is used all over the place and is well documented by various people. Not so with the ppu. The ppu is proprietary and any documentation that exists was written by individuals who either experimented on an actual NES or read other documentation elsewhere. None of it is written by professional writers and quite frequently is a work in progress. Kind of like this blog.

So now we're getting to the point that my emulator is actually doing something. Not very much, mind you, but something. It runs for the first 20 or so opcodes then it gets into a position where the opcodes are having it read the ppu state registers to determine whether or not the ppu is in a vblank. Because my ppu is largely unwritten and the registers aren't implemented yet, this doesn't happen and the cpu pretty much just sits there waiting.

The systems all interact via various specific positions in memory. For instance, to set various features on the ppu you can write to addresses 0x2000 and 0x2001. To read what state the ppu is currently in you read from 0x2002. In 0x2002 is a number between 0 and 256 (0x00 and 0xFF). Each bit in that number indicates something about the ppu. For instance, the highest bit -- the bit on the furthest left side of the binary number -- indicates whether or not the ppu is in a vblank period, which is the period in which the television is resetting itself so that it's ready for the next frame. Vblank happens 60 times a second. Interestingly, there are some registers that you should only read from or write to during vblank because reading or writing to or from them when the ppu is drawing the frame affects that frame.

So right now I'm in the process of implementing these registers not to mention the timing mechanism for system so that I can attempt to make the system run at the right speed so that lines are being drawn when they're supposed to be drawn and things run at the expected rate. It's tough work and is quite shittily written at this point. The main loop will probably prove to be pretty buggy. It would clearly have been easier to write a 2d game than to try to emulate the NES. That said, in my opinion this is a far cooler project and one that I'm pretty happy to be involved in. I'm trying to be careful in writing my code, but am also of the opinion that writing dirty code that kind of works helps to understand the problem space and helps you to get to the point that you can clean up the code. It's not an efficient process. It's not agile. But it has its benefits. I feel it works pretty well for hobby projects with a large problem space anyway.

Saturday, October 9, 2010

So, I have pretty much written the code that emulates what the cpu does. I have not yet begun debugging that code. I have been testing as I've gone along. If there are errors, I suspect that most of them will be centered around parts of the cpu that I didn't understand or misunderstood. I've written the code, but there are significant questions that I have not yet found answers for that could seriously affect how the processor functions. These are the known unknowns. There are probably also unknown unknowns. I've created a small text document called known unknowns that documents some of the things I don't know and will likely upload it the next time I get around to uploading the current code to the google code source repository. As in my professional life, the source repository is a necessary evil and something I am going to be lazy about, I guess.

I have been reading up on the GPU. When I set out to emulate the NES, I was a little surprised to find out that the processor in it had been around since 1975. The cpu was not cutting edge. It was a well known processor that had been used in several other video game systems. The GPU was a lot more cutting edge, I think.

The CPU interacts with all of the other systems of the NES via memory. There are sections of memory that function as input and output for both the graphics processing system and the audio processing system. I am still coming up with the design that my emulator will eventually use to emulate the graphics. I have an idea how the GPU does what it does. I have not yet decided how I want to emulate it. I still need to find out exactly what the inputs and outputs for the GPU look like. Especially the output. I believe I've seen some degree of information concerning some of the input registers, but not an awful lot concerning the output registers.

The other thing to think about is the television. The NES was built specifically to interact with television screens and some of the software uses the physical constraints of the actual television to create effects. For instance, they might interact with the input registers at a particular point in the creation of a particular line on the television screen to create some effect. I don't exactly know what they're doing or what these effects look like yet, but it might be necessary for me to emulate the way a television creates images to one degree or another in order to replicate these effects. If I decide to replicate these effects. My project is mostly just to emulate one or two games in order to learn more about hardware and assembly programming, not to create the most accurate NES emulator available.