zerowalker wrote:Hmm, well my method was to just do precisely as the Table said, with a ton of If/Else, but there are some cases which just doesn't exist, which you might be talking about.
I tried the code you linked and it works.
Though i am a bit confused how.
I have read up on BCD, and i get the principle of it, but not much else.
I do understand that it uses the flags to determine what has happened and how to adjust it into a decimal equivalent if you will.
Looking at your code, the first check is if it's above 0x99 or the carry flag is set.
The table usually says both must be set in some cases.
Let's look at a couple of examples, with only one significant digit to keep things simple.
0x60 + 0x60 = 0xc0
Adding 0x60 + 0x60 doesn't produce a carry, but the result is not a valid BCD number; it needs to be adjusted to 0x120, and the carry flag needs to be newly set because 0x120 doesn't fit in a byte.
0x90 + 0x90 = 0x120 (0x20 + carry)
This time the result is a valid BCD number, but it isn't the
right BCD number; it should be 0x180. The carry flag indicates that a result does need to be adjusted even if it looks like a valid BCD number.
The same logic applies to the ones digit and the half-carry flag, except that the CPU doesn't bother
setting the half-carry flag after a DAA, because only DAA uses the half-carry flag and doing two DAAs in a row makes no sense.
When it comes to subtraction, as long as the operands were two valid BCD numbers, the only time a hex digit > 9 can appear in the result is if a borrow occurred. Think about it: if you subtract 0-9 from 0-9, the result can't be more than 9. So for subtraction the value in A doesn't matter, only the flags (note that this only applies to the GameBoy CPU. The Z80 does DAA after subtraction a bit differently)
And also, isn't it "high nibble is above 0x09" that's what i did as the table said so, which i think is equal to A > 0x90.
A > 0x90 includes 0x91 to 0x99, which are perfectly good BCD numbers. On the other hand, if A is between 0x9a and 0x9f, then the high nybble
will be greater than 9 after the lower nybble has been adjusted. Comparing A to 0x99 is equivalent to adjusting the lower nybble first and then comparing A to 0x9f. However, if you adjust the lower nybble first then you have to worry about 0xfa-0xff wrapping around to 0x00-0x05. You want the non-wrapped result when deciding whether to adjust the upper nybble (0xfa-0xff should get both nybbles adjusted) but you want the wrapped 8 bit result for the Z flag (Z should be set if the result of adjustment is 0x100) Doing the upper nybble first spares you the trouble of juggling different integer sizes or explicitly masking.
Also, it's not relevant to the GameBoy, but on the Z80, comparing with 0x99 before adjusting either nybble is the
only way to nail all the edge cases of subtraction of non-valid BCD operands (some online documents and Z80 emulators describe or implement excessively complicated tests which work out to be arithmetically equivalent to "A > 0x99")