pub trait Variant {
// Required methods
fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)>;
fn adc_binary(
accumulator: u8,
value: u8,
carry_set: bool,
) -> ArithmeticOutput;
fn adc_decimal(
accumulator: u8,
value: u8,
carry_set: bool,
) -> ArithmeticOutput;
fn sbc_binary(
accumulator: u8,
value: u8,
carry_set: bool,
) -> ArithmeticOutput;
fn sbc_decimal(
accumulator: u8,
value: u8,
carry_set: bool,
) -> ArithmeticOutput;
// Provided methods
fn penalty_cycles_for_decimal_mode() -> u8 { ... }
fn penalty_cycles_for_indirect_jmp() -> u8 { ... }
}Expand description
Trait for different 6502 CPU variants with their historical differences.
The 6502 family evolved over decades with various manufacturers creating specialized versions for different applications:
-
Revision A (1975): Very early 6502 variant missing the ROR instruction entirely. Found in early KIM-1 systems and some Apple-1 computers. The ROR instruction was intentionally unimplemented due to design constraints, not a “bug” as commonly believed. Production ended around June 1976.
-
NMOS 6502 (1976): Complete MOS Technology processor with working ROR instruction, used in Apple II, Commodore 64, Atari 2600. Has unreliable decimal mode flags but full BCD support. This became the standard reference implementation.
-
65C02 (1983): WDC’s CMOS version with bug fixes, additional instructions, and reliable decimal mode flags. Development began in 1981 with samples released in early 1983. Used in Apple IIc/IIe and many embedded systems.
-
Ricoh 2A03 (1983): Nintendo’s cost-reduced variant for NES/Famicom (released July 15, 1983). Removed decimal mode entirely to avoid patent issues. Used as a core in their custom ASIC which also included sound generation and other features.
Choose the variant that matches your target system for accurate emulation. Note that software written for later variants may not run on earlier ones due to missing instructions (particularly ROR on Revision A).
Required Methods§
fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)>
Sourcefn adc_binary(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
fn adc_binary(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
Sourcefn adc_decimal(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
fn adc_decimal(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
Sourcefn sbc_binary(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
fn sbc_binary(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
Sourcefn sbc_decimal(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
fn sbc_decimal(accumulator: u8, value: u8, carry_set: bool) -> ArithmeticOutput
Provided Methods§
Sourcefn penalty_cycles_for_decimal_mode() -> u8
fn penalty_cycles_for_decimal_mode() -> u8
Returns the cycle penalty for ADC/SBC in decimal mode for this variant.
- NMOS/Ricoh: 0 (no penalty)
- 65C02: 1 (decimal mode adds an extra cycle)
- Future variants may have different values
Sourcefn penalty_cycles_for_indirect_jmp() -> u8
fn penalty_cycles_for_indirect_jmp() -> u8
Returns the cycle penalty for JMP (indirect) for this variant.
- NMOS/Ricoh: 0 (5 cycles total)
- 65C02: 1 (6 cycles total, also fixes page-crossing bug)
- Future HMOS 7501: 0 (5 cycles)
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.