Invalid money division discrepancy: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
No edit summary |
|||
Line 9: | Line 9: | ||
===Explanation=== |
===Explanation=== |
||
There is no BCD instruction for halving (or shifting) a number in hardware; the game must manually perform long division.<ref>https://github.com/pret/pokered/blob/master/engine/math/bcd.asm</ref> |
There is no BCD instruction for halving (or shifting) a number in hardware; the game must manually perform long division.<ref>https://github.com/pret/pokered/blob/master/engine/math/bcd.asm</ref> Long division naturally has subtractions inside. |
||
In order to perform BCD addition/subtraction, the code first performs regular addition/subtraction in hexadecimal, then relies on the '''DAA''' (Decimal Adjust register A) hardware instruction. This instruction automatically adds/subtracts hex:6 or hex:60 from a byte if the previous addition/subtraction resulted in an invalid digit or involved a carry/borrow. For example: |
In order to perform BCD addition/subtraction, the code first performs regular addition/subtraction in hexadecimal, then relies on the '''DAA''' (Decimal Adjust register A) hardware instruction. This instruction automatically adds/subtracts hex:6 or hex:60 from a byte if the previous addition/subtraction resulted in an invalid digit or involved a carry/borrow. For example: |
||
Line 17: | Line 17: | ||
* hex:10 minus hex:1 normally yields hex:F, but it will also report a borrow. The DAA instruction may ''either'' detect the borrow or notice the invalid digit, and subtract another hex:6 to yield hex:9. |
* hex:10 minus hex:1 normally yields hex:F, but it will also report a borrow. The DAA instruction may ''either'' detect the borrow or notice the invalid digit, and subtract another hex:6 to yield hex:9. |
||
Note that in the last case, there is technically no need to look for invalid digits when subtracting, because the only way to get them is through a borrow. |
Note that in the last case, there is technically no need to look for invalid digits when subtracting, because the only way to get them is through a borrow. The Game Boy hardware ignores invalid digits for subtraction, but the 3DS's emulator looks at invalid digits for subtraction. This difference in behavior ultimately leads to the money discrepancy. |
||
Finally, the |
Finally, the DAA instruction only works on one byte at a time, so BCD addition/subtraction must be done one byte at a time. In order to handle more than one byte, the code uses the "add with carry" and "subtract with carry" operations, which report to the CPU if a carry/borrow occurs and automatically add/subtract 1 from the result if the previous add/subtract with carry operation reported a carry/borrow. For example: |
||
* In order to perform hex:1000 minus hex:222, the code must first subtract the rightmost bytes (hex:00 minus hex:22 yielding hex:DE). DAA then turns this into hex:78, then it reports a carry/borrow. |
* In order to perform hex:1000 minus hex:222, the code must first subtract the rightmost bytes (hex:00 minus hex:22 yielding hex:DE). DAA then turns this into hex:78, then it reports a carry/borrow. |
||
* The code then subtracts the leftmost bytes (hex:10 minus hex:2 yielding hex:E), then 1 is automatically subtracted due to the above "subtract with carry" reporting a borrow, then DAA turns the hex:D into hex:7. |
* The code then subtracts the leftmost bytes (hex:10 minus hex:2 yielding hex:E), then 1 is automatically subtracted due to the above "subtract with carry" reporting a borrow, then DAA turns the hex:D into hex:7. |