Since I don't really have logic to deal with auxiliary carry bits or parity flags, I went through my code and removed opcodes that corresponded to them. Based on the Internet, it didn't look like Space Invaders used any of these flags anyways. If it turns out we do need them, it should be fairly trivial to add them back (I hope).

I had the next task of implementing MOV instructions. Since there are 7 registers that can move to 7 other registers, I had to implement 49 different opcodes. Instead of typing it out manually, I figured I should probably try something more efficient. Looking at MOV in the 8080 assembly manual shows our MOV instruction is structured like this:

I could therefore write code that automatically verifies all my MOV instructions in one go instead of the way I was doing tests before. The manual is nice enough to show which bits goto which register so we can piggy back off of that in our test code. Note that I'm ignoring memory moves since I already covered those instructions.

My new test now looks like this:

// This is DIFFERENT that SP is actually PSW as we can't push/pop SP
// We're gonna leave PSW out for now and get back to it later since the
// logic is slightly different
uint16_t *regpair_pushpop_mapping[3] = {
    &(r_cpu.BC),
    &(r_cpu.DE),
    &(r_cpu.HL)  
};
char *regpair_pushpop_naming[3] = {
    "BC",
    "DE",
    "HL"
};

uint8_t i = 0;
for(i = 0; i < 3; i++) {
    // Build the opcode
    uint8_t dst_byte = 0b00110000 & (i << 4);
    uint8_t opcode = 0b11000101 | dst_byte;

     // Make sure opcode works as expected
    {
        SETUP_TEST_1(opcode);
        (*regpair_pushpop_mapping[i]) = TEST_MEMORY_ROM_LH;

        printf("Testing Opcode %02X (REG %s) works\n", opcode, regpair_pushpop_naming[i]);
        TEST_SUCCESS_OPCODE();

        munit_assert_int(cpu->SP, ==, STACK_START - 2);
        munit_assert_int(program[STACK_START-1], ==, TEST_MEMORY_ROM_L);
        munit_assert_int(program[STACK_START-2], ==, TEST_MEMORY_ROM_H);
    }
}

And with that I have implemented tests for 49 more opcodes into the CPU!

By now, I should have enough opcodes programmed in to at least show a visualization. Here I have to write a function to stream the VRAM directly to the BMP file to avoid allocating any more on our heap. Remember that the device I am running this on has limited RAM! Let's see what the final result looks like:

It's not exactly orientated correctly, but it's at least a start! An interesting fact about space invader cabinets is the monitor was rotated 90 degrees so in reality, my image is fairly accurate to what should actually be displayed (though the x-axis might need to be swapped).

Next is trying to implement the rest of the opcodes!