This pull request addresses several issues with the Add with Carry (ADC)
operation in our 6502 emulator, ensuring correct behavior in both decimal and
non-decimal modes.
It is similar to #106, which improved on our SBC operation.
My hope is that these changes improve the accuracy of our 6502 emulator,
particularly for software that relies on correct decimal mode arithmetic or
precise overflow detection.
- Implement correct decimal mode addition in ADC operation
- Accurate overflow detection for non-decimal mode
- Proper carry flag calculation for both modes
- Preserve overflow flag in decimal mode (as per 6502 specification)
The previous implementation didn't correctly handle Binary-Coded Decimal (BCD)
arithmetic. The new implementation:
1. Performs addition on low and high nibbles separately
2. Adjusts results when they exceed 9 (valid BCD range is 0-9)
3. Propagates carries between nibbles
4. Sets the carry flag correctly based on the final BCD result
- In non-decimal mode: Implemented using the formula `(!(A ^ M) & (A ^ R)) &
0x80 != 0`, where A is the accumulator, M is the memory operand, and R is the
result.
- In decimal mode: The overflow flag is preserved, matching the behavior of the
actual 6502 processor.
- In non-decimal mode: Set if the unsigned result is less than either the
accumulator or the memory operand.
- In decimal mode: Set based on whether the BCD addition resulted in a value
greater than 99.
- Correct decimal mode subtraction in SBC operation
- Implement accurate overflow detection for non-decimal mode
- Fix carry flag calculation as inverse of borrow
- Add comments explaining complex bit manipulation for overflow detection
- Update tests to verify correct behavior in both decimal and non-decimal modes
This commit addresses issues with the Subtract with Carry (SBC) operation,
ensuring correct behavior in both decimal and non-decimal modes, and
improves code readability with added comments.
* start on separating 6502 variants from cpu itself
* add a single variant: the NMOS one
* get examples & tests running again
* Add the Revision A variant, one that has no ROR
* disable failing lint in build-time dependencies
* Variant with no decimal mode
* Revert "disable failing lint in build-time dependencies"
This reverts commit c87975e937.
* some doc comments
* specify the variant in unit test now the API has changed
---------
Co-authored-by: Sam M W <you@example.com>
* extract decimal logic into separate function
* squash me
* I think we should be doing unsigned arithmetic here
* squash me
* remove unused function
* update the sign checks
* cargo fmt
* get tests to compile again
* get tests passing again
* squash me
* remove pointless conversion from u8 to u8
* cargo fmt
* accumulator is now u8
* add adc test from solid65
* pass the new test
---------
Co-authored-by: Sam M W <you@example.com>