There's a lot of confusion over DAA, due to it behaving subtly differently between the GameBoy and the Z80 with "illegal" input (i.e. when the accumulator and flags contain something other than the results of a valid BCD addition or subtraction). The table in the document you've linked to is incomplete, as it doesn't indicate what the results will be in those cases.

Do you understand what BCD (binary-coded decimal) arithmetic means? Basically, it means interpreting the upper and lower nybbles (a nybble is 4 bits or 1 hex digit) of a byte as two individual decimal digits, rather than the whole byte as one binary number. There are a few different ways to do BCD arithmetic, and every CPU with BCD support (even CPUs in the same family, like the GameBoy CPU and Z80) tends to do them a bit differently. The CPU-specific implementation details matter when you try to do BCD arithmetic on operands that aren't valid BCD numbers (i.e. the upper and/or lower nybble of one or both operands was greater than 0x9)

The DAA instruction adjusts the results of a binary addition or subtraction (as stored in the accumulator and flags) to

*retroactively* turn it into a BCD addition or subtraction. It does so by adding or subtracting 6 from the result's upper nybble, lower nybble, or both. In order to work it has to know whether the last operation was an addition or a subtraction (the n flag), and whether a carry and/or a half-carry occurred (the c and h flags). Incidentally, the DAA instruction is the only thing that the n and h flags are normally ever used by, unless a program pushes the flags onto the stack and pops them into another register to explicitly inspect them.

The following is the simplest correct implementation of DAA for the GameBoy CPU. Note that it does the upper nybble adjust first to ensure that the two adjusts are independent without anything needing to be copied into a temporary variable (adding/subtracting 0x6 can carry into the upper nybble, but adding/subtracting 0x60 can't change the lower nybble)

**Code:**

// note: assumes a is a uint8_t and wraps from 0xff to 0

if (!n_flag) { // after an addition, adjust if (half-)carry occurred or if result is out of bounds

if (c_flag || a > 0x99) { a += 0x60; c_flag = 1; }

if (h_flag || (a & 0x0f) > 0x09) { a += 0x6; }

} else { // after a subtraction, only adjust if (half-)carry occurred

if (c_flag) { a -= 0x60; }

if (h_flag) { a -= 0x6; }

}

// these flags are always updated

z_flag = (a == 0); // the usual z flag

h_flag = 0; // h flag is always cleared

If you're still having problems, make sure you're setting the h and n flags correctly in your other instructions--remember that many arithmetic instructions set them, but DAA is the only instruction that uses them!