Skip to content

Emulator of MOS6502 (and eventually NES) with particular focus on understandable design and testing.

License

Notifications You must be signed in to change notification settings

rossdrew/emuRox

Repository files navigation

License Code Coverage by Codecov Mutation Coverage by Pitest GitHub Actions CI

EmuRox - Image by Søren Siebuhr

EmuRox

NOTE: This is not dead. Just on a bit of a hiatus while I wrestle with new fatherhood.

Ostensibly, an Nintendo Entertainment System (NES) emulator with a view to encompassing other systems. Creating a pluggable multi-emulator. In actuality, it is not about getting a working emulator, for a NES or anything else. There are plenty of them out there. It's about taking a complex problem and designing the best abstraction possible. Allowing us to discuss complex ideas in simple language.

Too often I've:

  • had to sacrifice good implementation for fast functionality
  • dealt with code in which concision hampered readability
  • consumed development time in lengthy, bloated builds. Usually caused by complex and brittle system testing
  • written under-specified features which need to be re-written over and over
  • work with naive domain knowledge due to time pressure
  • written solutions to problems I had no time to completely understand.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand. (M. Fowler)

I wanted something I could redesign over and over as my knowledge of the domain grew and as I felt the frustrations of having to reaquaint myself with pirces of code I hadn't seen in a while. Something I could test in a thousand different ways, then tweak and experiment with build processes so that the development cycle is rapid and fluid. That I could tweak the code over and over to make it simpler and simpler to understand.

There are also desirable side effects. I wanted to write my own emulator, play the games of my childhood and know that I wrote the platform that they were running on and becoming even more familiar with the first pieces of software I fell in love with. I wanted a large codebase I had complete control over and could try out tools and technologies. I got to the stage of the latter, quite a while ago and I'm crawling towards the former.

Usage

There is a debug UI for the MOS 6502 which provides a basic register and memory overview for running code through step by step in DebuggerWindow.java. Run with the Gradle command runDebugUI and you'll get an interface that looks something like

EmuRox Test GUI

On the left you'll see tabs of the first 5 memory pages organised in blocks of 4 with their locations displayed in red on the left. The Program Counter location will be colored green.

In the center we have a choice of two tabs

  • Registers: Which display all registers and flags, their names in blue and representations of them as decimal and hexadecimal in red.
  • Code: A simple code window which can be used to compile 6502 assembly and load it into page 0 at location 0.

On the bottom we have a reset button which will reset everything to it's initial state and a step button which will issue the next instruction.

At the top we have the currently executing instruction and on the right a history of instructions both consisting of their location, arguments and a short description.

6502 and progress towards a working NES...

I've seperate (at least) the NES section of this down into 7 stages:

  • I blasted through the first phase due to the massive amount of documentation on the MOS 6502
  • While researching phase 3, I churned through the relitively basic work of parsing iNES files of phase 2 (without edge cases for now)
  • Phase 3 is kinda where I'm stuck at the moment, struggling to find time to consolodate all the documentation and existing on the APU, which is less abundant than of the MOS 6502 and far more messy
  • Phase 4 is going to be a decent challenge I think, where I need to start concentrating on timings
  • Phase 5 and 6 are bringing it all together into a useable system

So currenly large scale features are undergoing research and early design. This also gives me time to improve and tweak what is there.

EmuRox Roadmap

Development & Testing

The current codecov.io coverage chart

The plan was to develop in a TDD (Test Driven Development) centric way, that is via Red-Green testing; i.e. writing failing/red tests that describe functionality then writing that functionality to make the tests pass/green and iteratively writing a complete application.

Current technologies

Technologies that I have used, liked and continued to use as part of the project...

Investigated technologies

Technologies that I have used yet disliked or haven't saw a place for them in my project for whatever reason...

  • JParams toStringTester for toString testing but it didn't seem to work very well, I filed an issue but the project has since been archived.
  • JUnit QuickTheories for property based testing but it's much more verbose for no added benefit over junit-quickcheck
  • Spockito to give the ability to unroll JUnit Theories like in Spock data-driven tests but I'm not a big fan of the syntax and attaches @DataPoints to the methods. It would be great for adding data-driven tests if you were limited to JUnit, however
  • Kotlin for testing and various testing frameworks like Spek and kotlintest but it offers nothing I don't already have and property/data-driven/theory testing is pretty ugly and/or weak.
  • Beads Project currently investigating for audio synthesis until I have the knowledge to roll my own. The library is so small, focused and nice to use I may just keep it. Unfortunately it's not on any repo so it needs to be manually included.

Problems

Javas unsigned byte problem.

Java bytes are signed, meaning it's a pain to deal with them. Sometimes we want to deal with raw bytes such as memory read and writes, sometimes we want to have them signed and later in BCD mode.

JaCoCo coverage in String based switch

JaCoCo doesn't report coverage of String based switch statements well

Sources

  • StackOverflow as always has been a huge help, specifically Godin, also a developer of JaCoCo for his help. eg. here & here
  • The 6502 Programming Facebook group has been invaluable in resolving very specific questions
  • I'm planning on reaching out to communities for code reviews (your comments are always welcome btw), another pair of eyes is always helpful, although so far these have proven to be unfruitful:-

Outputs

Get involved

Beerpay seems to have died so no contribution method. I'll look into replacing it.

For now, make a feature suggestion if you are so inclined.

Lastly, feel free to volunteer solutions, fixes, improvements, pull requests, documentation, technology suggestions. If you are a JavaFX/Swing guru, I'd love to see a better UI on this. Just note that I'm trying to make this, as well as a working project, a highly tested, nice codebase to work on.

Image

EmuRox chip image by Søren Siebuhr