diff --git a/src/gbemu/cpu.c b/src/gbemu/cpu.c index f70f274..c1ff4b3 100644 --- a/src/gbemu/cpu.c +++ b/src/gbemu/cpu.c @@ -557,8 +557,37 @@ int lr35902_cycle(struct lr35902_state *cpu) LD_D8(cpu, cpu->h); break; case 0x27: /* DAA */ - /* TODO: DAA */ + { + /* The internet agrees that this opcode is terrible. I've + * copied the same implementation (almost) everyone else + * has. */ + uint16_t a = cpu->a; + if (!cpu->nf) { + if (cpu->hf || ((a & 0xf) > 9)) { + a += 0x6; + } + if (cpu->cf || (a > 0x9f)) { + a += 0x60; + } + } else { + if (cpu->hf) { + a -= 0x6; + a &= 0xff; + } + if (cpu->cf) { + a -= 0x60; + } + } + + if (GET_BIT(a,8)) { + cpu->cf = 1; + } + + cpu->hf = 0; + cpu->a = a; + cpu->zf = !cpu->a; break; + } case 0x28: /* JR Z, r8 */ if (cpu->zf) { JR_8(cpu); @@ -1631,7 +1660,9 @@ int lr35902_cycle(struct lr35902_state *cpu) ASSERT(0); break; case 0xde: /* SBC A, d8 */ - ASSERT(0); + val = gb_mem_read(cpu->memory, cpu->pc++); + SBC_8(cpu, cpu->a, val); + break; case 0xdf: /* RST 0x18 */ RST(cpu, 0x18); break;