The Capstone project is humming along and our group made its way into the real meat of the project: translating 8080 opcodes from Hex to functional Rust code. Though it absolutely boggles the mind, the creators of Space Invaders on the Intel 8080 Processor made their game using only about 50 different opcodes. This is good, because it means we can get an emulator of the game up and running after implementing those 50 opcodes (and doing some funny business with the ‘machine’). The downside is that the work being done in this program is virtually always so esoteric that it requires much more time to parse than code written in a modern language would.
It can be very difficult to trace through these opcodes and figure out what exactly the Makers were plotting when, say, decrementing the B register and then not referring to it again for quite some time. The good news is that each of these instructions on its own is relatively simple. Take the one just mentioned: 0x05, DCR B. The Intel 8080 processor has 8 bit registers, of which B is one (a, c, d, e, h, and l are others). Decrementing the value held in B is a relatively simple operation; just subtract one and voila! Decrementation implementation. Except we still need to access and potentially change the values in the Condition Codes part of the CPU. There are condition codes for things like sign, carry, zero, and parity in these processors which are used when, say, jumping to another part of the code if the zero flag is set.
Figuring out when to set these flags might seem pretty intuitive at first, we increment a register at 0xFF and it overflows to 0x00, for example, so we’d assume the carry bit ought to be set. This is indeed the case with the Increment instructions, but, strangely, not the case with the Increment Register Pair instructions (0x13). Figuring out which condition flags are set with which instruction is indeed a large portion of implementing these opcodes, and there’s no better resource than the (mercifully digitized) Intel 8080 processor manual. While it’s a little cumbersome, going through this manual has certainly helped me grow as a programmer (and generally as a patient person). Stepping through, 8 bits at a time, and consulting a manual from the 1970s is indeed a new experience for me, but it is greatly rewarding to find the information we need and implement it in a modern language like Rust.
Overall this process has been slow and iterative; as we step through each opcode, we implement it as best we can in Rust, and then move on to the next one. The next part of the project will be perhaps the most trying, as we will be debugging using the actual ROM files of the game itself. Finding errors and reporting on them will be a little more involved than we’re used to with modern languages, but I, for one, am looking forward to the challenge!