Z80 DAA implementation and Blargg's test rom issues

Viewed 1523

I want to first preface my question by first saying that I am quite an experienced programmer, particularly with Java having used it for 8 years.

I decided, in an effort to improve my understanding of hardware operation and operating system topics, to program a simple Gameboy emulator. Having programmed the core functionality in just a few days I tested the emulator only to discover that nothing was drawn on the screen. After stepping through several hundred opcodes in my emulator one at a time and comparing it to the values found in the BGB emulator, I realized that the tiles and sprites in question were being loaded into memory, just not drawn. From this I figured that the issue must be in one or more of my opcode implementations which causes the program to exhibit wrong behavior at some point. Because of this, I decided to use Blargg's cpu test roms (http://gbdev.gg8.se/files/roms/blargg-gb-tests/) to help me pin down the issue. However, running the first test rom, gives the following error message:

01-special

36E1FE30 
DAA

Failed #6

I have checked the DAA operation several times and it appears to be correctly implemented to me. The error code given ("36E1FE30") is totally unhelpful as I cannot seem to find what that means. To me this implies that either DAA is incorrectly implemented and I just can't see my mistake or one of the operations used to validate the correctness of DAA is incorrect. If I run any of the other tests they appear to loop indefinitely

03-op sp,hl

03-op sp,hl

03-op sp,hl

03-op sp,hl

For reference my DAA implementation is on github (https://github.com/qkmaxware/GBemu/blob/master/src/gameboy/cpu/Opcodes.java) or can be seen below as follows:

Op DAA = new Op(0x27, "DAA", map, () -> {
    int a = reg.a();

    if(!reg.subtract()){
        if(reg.halfcarry() || (a & 0xF) > 9)
            a += 0x06;

        if(reg.carry() || a > 0x9F)
            a += 0x60;
    }else{
        if(reg.halfcarry())
            a = (a - 0x6) & 0xFF;

        if(reg.carry())
            a = (a - 0x60) & 0xFF;
    }

    reg.a(a);

    reg.zero(isZero(a));
    reg.carry((a & 0x100) == 0x100);
    reg.halfcarry(false);

    clock.m(1);
    clock.t(4);
});

Where calls such as reg.a() means read from register a, reg.a(value) means write to register a (mask to 8 or 16 bits depending on the register). Similarly, the flags Z,N,H,C can be obtained or set/reset with the zero, subtract, halfcarry, an carry functions of the 'reg' object.

So my question is threefold, have I implemented the DAA operation incorrectly so that it fails Blargg's tests, does anyone know what the error code I have means, or does anyone have any ideas how I can focus my search for the incorrect operation.

1 Answers
Related