Hi!
I'm making a Gameboy emulator and I've been trying to get the DAA instruciton to pass Blargg's tests for quite some time now.
I've tried to copy the behavior of how gambatte (which passes the tests) handles it.
Gambattes implmentation:
and this is my current code:
What I find the most confusing is the behavior of the H flag after the DAA instruction. According to the documentation it says "set or reset according to operation", which doesn't really explain how it behaves. Currently I'm always clearing it, because I think that is what gambatte does.
I then started comparing it to VBA-M's DAA table and found that the Z flag doesn't always behave as I thought. For example:
Produces the following:
Also, sometimes (I haven't figured out when), the H flag is set.
I couldn't test whether VBA-M is accurate or not because it fails the test before the DAA test is run.
I'm making a Gameboy emulator and I've been trying to get the DAA instruciton to pass Blargg's tests for quite some time now.
I've tried to copy the behavior of how gambatte (which passes the tests) handles it.
Gambattes implmentation:
Code:
case 0x27:
calcHF(HF1, HF2);
{
unsigned correction = (CF & 0x100) ? 0x60 : 0x00;
if (HF2 & 0x200)
correction |= 0x06;
if (!(HF2 &= 0x400)) {
if ((A & 0x0F) > 0x09)
correction |= 0x06;
if (A > 0x99)
correction |= 0x60;
A += correction;
} else
A -= correction;
CF = correction << 2 & 0x100;
ZF = A;
A &= 0xFF;
}
break;
calcHF(HF1, HF2);
{
unsigned correction = (CF & 0x100) ? 0x60 : 0x00;
if (HF2 & 0x200)
correction |= 0x06;
if (!(HF2 &= 0x400)) {
if ((A & 0x0F) > 0x09)
correction |= 0x06;
if (A > 0x99)
correction |= 0x60;
A += correction;
} else
A -= correction;
CF = correction << 2 & 0x100;
ZF = A;
A &= 0xFF;
}
break;
and this is my current code:
Code:
cycleCounter += 4;
int corr = 0;
corr |= regAF.lo & FLAG_MASK_H? 0x06: 0x00;
corr |= regAF.lo & FLAG_MASK_C? 0x60: 0x00;
if (regAF.lo & FLAG_MASK_N)
{
regAF.hi -= corr;
} else
{
corr |= (regAF.hi & 0x0F) > 0x09? 0x06: 0x00;
corr |= regAF.hi > 0x99? 0x60: 0x00;
regAF.hi += corr;
}
CLEAR_FLAGS(FLAG_MASK_H);
if (corr & 0x60)
{
SET_FLAGS(FLAG_MASK_C);
}
if (corr & 0x06)
{
//SET_FLAGS(FLAG_MASK_H);
}
if (regAF.hi == 0)
{
SET_FLAGS(FLAG_MASK_Z);
} else
{
CLEAR_FLAGS(FLAG_MASK_Z);
}
int corr = 0;
corr |= regAF.lo & FLAG_MASK_H? 0x06: 0x00;
corr |= regAF.lo & FLAG_MASK_C? 0x60: 0x00;
if (regAF.lo & FLAG_MASK_N)
{
regAF.hi -= corr;
} else
{
corr |= (regAF.hi & 0x0F) > 0x09? 0x06: 0x00;
corr |= regAF.hi > 0x99? 0x60: 0x00;
regAF.hi += corr;
}
CLEAR_FLAGS(FLAG_MASK_H);
if (corr & 0x60)
{
SET_FLAGS(FLAG_MASK_C);
}
if (corr & 0x06)
{
//SET_FLAGS(FLAG_MASK_H);
}
if (regAF.hi == 0)
{
SET_FLAGS(FLAG_MASK_Z);
} else
{
CLEAR_FLAGS(FLAG_MASK_Z);
}
What I find the most confusing is the behavior of the H flag after the DAA instruction. According to the documentation it says "set or reset according to operation", which doesn't really explain how it behaves. Currently I'm always clearing it, because I think that is what gambatte does.
I then started comparing it to VBA-M's DAA table and found that the Z flag doesn't always behave as I thought. For example:
Code:
A = 0x00
F = 0x80 // Z flag set
execute DAA
F = 0x80 // Z flag set
execute DAA
Produces the following:
Code:
output:
A = 0x00
F = 0x00
A = 0x00
F = 0x00
Also, sometimes (I haven't figured out when), the H flag is set.
I couldn't test whether VBA-M is accurate or not because it fails the test before the DAA test is run.