We have completed the CPU portion of our emulator. Yay! :D
Well, it was completed a while ago, but I've been so busy with school I haven't had time to write about it. I still don't really, but I'm going to update anyway. Here is what I've been up to.
Finishing and Testing Opcodes
Since my last update I was working on building the instructions for the various opcodes. After writing them I decided to try out nestest.nes - a rom designed to help programmers of emulators debug their code. Conveniently, this was possible even without any PPU - By comparing my output to a known-good log from another emulator called Nintendulator, I was able to correct some glitches in how I was addressing memory as well as fixing some instructions to work properly.
Implementing Details
Before the CPU was ready to be called 'done', I needed to implement some final touches so that it would be accurate and ready for a PPU. These details included memory mirroring (which for some reason I had neglected until now), cycle counting (making sure each instruction took as long or as short as it was supposed to) as well as a few smaller things
Added a Configuration File
Do you like recompiling every time you want to change games? Me neither! Cartridge path, number of cycles to perform, as well as execution start address override (mostly for nestest.nes which required 0xc000 rather than whatever was stored at the reset vector) have been placed into a nice config file.
I also reworked the output screens a bit and cleaned up and documented a lot of the code.
Further Improvements.
With that the CPU is "complete". I say it with quotes because there is so much that can be improved. While cleaning up the code I stuck in probably a dozen different //TODO notes. The most significant improvement I believe is to remove ALL string operations. There are A LOT of string operations in the code - Opcodes and addressmodes get assigned a string, and is compared in several dozen if statements every single cycle. Changing these strings to enums or structs would probably result in a massive performance boost. However, I want to move on to the PPU first to see how it performs, then come back to this.
Next Step: PPU
I said I would write a post about the CPU before I started on the PPU, but I lied. I actually did quite a lot of research on the PPU and started the code in a new github branch. The graphics of ALIAneS will be powered by SDL. I've successfully created a window and drawn random pixels to it each cycle, and I estimate I'm 5 hours of coding away from displaying the first graphics from the screen - as primitive as they may be. I'll talk more about the PPU in another post.
My exams are in 2 weeks, and I'm done the school term in about 3-4 weeks. After that point I'll get back into this project more full-time.
Sunday, 22 November 2015
Thursday, 13 August 2015
Creating an NES Emulator From Scratch Part 2.5: CPU Code: Another Progress Update
(I changed my blogger name from Skyline_ to Aliasmk)
Hi again!
Its been a year and a week since I first posted about this project, and though its slow going, we are making progress.
Now, I know I said I'd be teaching as I go, but I found that I'm kinda learning on the fly here.. so I don't feel too qualified to teach. That said, I definitely will post research logs soon, once I know that things are going to work out.
I've implemented a shell so that testing can be done in a sandbox of sorts... you are given an instance of the CPU with a blank memory space, and you can write memory to the space and execute at an address as you would any cartridge. This will make it way easier to make sure addressing modes and opcodes are working correctly for the next stage of the project, which is actually creating the opcode instructions. The shell can also start the emulator as normal. Below is a screenshot comparing ALIAneS with Macifom's Debugger - note that (with a few exceptions) both report the same Opcodes and report the same addressing modes and operands.
You are free to build and try it yourself as always! Currently it works out of the box with OS X, probably works out of the box on Ubuntu and linux etc, and might work if you build it from the source on Windows.
Next steps:
Hi again!
Its been a year and a week since I first posted about this project, and though its slow going, we are making progress.
Now, I know I said I'd be teaching as I go, but I found that I'm kinda learning on the fly here.. so I don't feel too qualified to teach. That said, I definitely will post research logs soon, once I know that things are going to work out.
I've implemented a shell so that testing can be done in a sandbox of sorts... you are given an instance of the CPU with a blank memory space, and you can write memory to the space and execute at an address as you would any cartridge. This will make it way easier to make sure addressing modes and opcodes are working correctly for the next stage of the project, which is actually creating the opcode instructions. The shell can also start the emulator as normal. Below is a screenshot comparing ALIAneS with Macifom's Debugger - note that (with a few exceptions) both report the same Opcodes and report the same addressing modes and operands.
You are free to build and try it yourself as always! Currently it works out of the box with OS X, probably works out of the box on Ubuntu and linux etc, and might work if you build it from the source on Windows.
Next steps:
- Ensure that all opcodes are being read with their correct addressmodes. There is no point continuing until this is complete.
- Code the instructions for each opcode. For example, LDA (load accumulator with memory) would beif(operation = "LDA"){setA(operand); //Where operand is found using relevant addressing techniques}
Friday, 27 March 2015
Creating a NES Emulator From Scratch Part 2.25: CPU Code: Actual Progress Update
This is a project update, not a research log. I will
be posting a blog entry explaining everything I have learned in detail in
coming weeks. I don't have time right now (due to school) to study for
exams, write the emulator, and summarize, edit and post all my research at the
same time. But it will be up, and if you don't understand everything on this post, you will once you read that one. Stay tuned!
I posted a few weeks ago saying that I had rebooted the project and in fact I have. I'm close to having CPU emulation working. Here is a rundown of what I have done over the last few weeks:
I posted a few weeks ago saying that I had rebooted the project and in fact I have. I'm close to having CPU emulation working. Here is a rundown of what I have done over the last few weeks:
- I'm calling the project "ALIAneS" because emulator names are weird and have strange capitalization like that
- I had to re-research everything again because I hadn't made any real notes the first time that I looked into the project way back in August. Focusing mostly on CPU I learned a lot more about the NES file format and CPU memory addressing methods than I remember learning about before. So taking notes would have been good, but looking at it again with more knowledge of programming helped.
- Began coding basic frameworks for the CPU. I'm splitting the class files into System, CPU, Cartridge, PPU, and APU, as well as having headers for all of those of course. Only the first three of these are actually written as PPU and APU are secondary goals of mine for this project.
- Wrote functions for setting and getting all values of registers as well as memory, given a location.
- Coded the startup sequence of actions outlined on NesDev into the emulator init function
- Got the cartridge loading methods done: right now this emulator will load a 8K or 16K PRG-ROM cartridge only; I have not (and will not for a while) support any mappers, as they are a tertiary goal.
- Working currently on opcode decoding..
That last one, opcode decoding is taking the longest time. Luckily the binary of the byte that makes up an opcode can be parsed to more efficiently determine the operation and the addressing mode.
This is
the last step in CPU emulation as far as I know, other than to implement memory
mirroring functions for the RAM, which I haven't done yet for some
reason.
That’s it for now. All source code on GitHub! See you again after exams are done!
That’s it for now. All source code on GitHub! See you again after exams are done!
Wednesday, 11 March 2015
Creating a NES Emulator From Scratch Part 2: CPU Code
I figure it's high time to update this project, and this blog.
After dropping this project for quite a long time, I've picked it up again, armed with new C++ knowledge developed through my first and current school terms. Even though I knew Java before, these classes really helped develop my programming skills in both languages.
Anyway, I have officially started the CPU programming. At the time of writing, here is what it does so far:
Talk soon! :)
After dropping this project for quite a long time, I've picked it up again, armed with new C++ knowledge developed through my first and current school terms. Even though I knew Java before, these classes really helped develop my programming skills in both languages.
Anyway, I have officially started the CPU programming. At the time of writing, here is what it does so far:
- Initializes CPU registers
- Writes to memory
- Reads a cartridge, and writes it to memory
- Framework set up for future functions.
Talk soon! :)
Subscribe to:
Posts (Atom)