A Gameboy Classic emulator designed to be played on a Ti-NSpire CX CAS, a commonly used graphing calculator for my school. It emulates all the instructions, registers, memory, interrupts, key bindings, and ran as fast as possible (the calculator simply couldn’t run Lua at the full clock speed of the Gameboy). The only piece that was left out was drawing the image onto the screen.
During my sophomore year, I was just getting into larger scale programming projects (I had been programming since elementary school but never had taken on a truly large project). At the time, my school required me to own a Ti-NSpire CX CAS (a graphing calculator) which had a full color display and keyboard and was completely overkill what we were doing on it.
Since we were high schoolers, we found out that you could run certain exploits that would allow the calculator to run binary programs rather than simply Lua scripts. This was of course used by high schoolers to play Gameboy games through an emulator ported to the calculators architecture.
The problem with this was that the whole calculator would break everytime you updated it, and we'd have to wait until the maintainers attempted to find another exploit to crack the system again. This made me wonder why we even needed to run a fully compiled emulator when the calculator came with a built in scripting language
This question inspired me to learn the inner workings of the Gameboy and learn about emulator and CPU architecture. Over the following months I read everything I could on the subject until I felt that I was ready to write my own emulator. This process started by me writing a simple disassembler, written in Ruby, to convert Gameboy machine code to Assembly so that I could figure out what was actually on a ROM.
To my surprise, it was simply sequential instructions to the CPU (I was 15, cut me some slack). This made me think (incorrectly, but still), that all I would have to do was simply implement run these commands and I would be able to play Pokemon.
Then came the hard part, I started straight away implementing the opcodes that made up the CPU (of which there are hundreds). This process eventually led me to completely scrap the program and start over because it became too unwieldy. In the end, I managed to implement all the opcodes in the CPU and the interrupts but failed to get it to render the screen. The biggest issue, ignoring the simple sluggishness of the calculator’s Lua implementation, was that I never unit tested the program leading to bugs popping up in weird places and slow program bloat.
This project was the first thing that got be truly obsessed with programming. In the end, while it never completely worked I learned so many hard skills like how to write an emulator, assembly, and low level computer architecture. I also learned many soft skills like how the organize large projects, the importance of fully testing code, and how to tackle a large project. But my biggest takeaway was the importance of testing and organization in combating program rot over time.GitHub