[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/balt-dev/r6502/.github%2Fworkflows%2Frust.yml?branch=master&style=flat&label=tests)](https://github.com/balt-dev/descape/actions/)
[![Documentation](https://docs.rs/r6502/badge.svg)](https://docs.rs/r6502)
[![MSRV](https://img.shields.io/badge/MSRV-1.66.1-gold)](https://gist.github.com/alexheretic/d1e98d8433b602e57f5d0a9637927e0c)
[![Repository](https://img.shields.io/badge/-GitHub-%23181717?style=flat&logo=github&labelColor=%23555555&color=%23181717)](https://github.com/balt-dev/r6502)
[![Latest version](https://img.shields.io/crates/v/r6502.svg)](https://crates.io/crates/r6502)
[![License](https://img.shields.io/crates/l/r6502.svg)](https://github.com/balt-dev/r6502/blob/master/LICENSE-MIT)
[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
# r6502
### Yet another NMOS 6502 emulator.
---
Designed to support `no-std` and not require an allocator nor any unsafe code.
The API of this crate shies away from implementing interrupt handling,
instead having you step the emulator one opcode at a time and handle them yourself.
## Feature Flags
The following feature flags exist:
| Name | Description |
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| bcd | Enable binary-coded decimal arithmetic.
Enabled by default. Disable if you're writing a NES emulator.
Note that invalid BCD is left untested and will not function faithfully to the NMOS 6502. |
| bytemuck | Enables [bytemuck](https://docs.rs/bytemuck/) support. |
| arbitrary | Enables [arbitrary](https://docs.rs/arbitrary/) support. This will pull in `std`. |
| serde | Enables [serde](https://docs.rs/serde) support. |
| hashbrown | Enables [hashbrown](https://docs.rs/hashbrown) support. |
## Example
```rust ignore
extern crate std;
use std::eprintln;
use r6502::{Emulator, FunctionReadCallback, FunctionWriteCallback};
fn main() {
let mut emu = Emulator::default()
.with_read_callback(FunctionReadCallback(|state: &mut State, addr| {
// Log reads
eprintln!("Read from #${addr:04x}");
state.memory[addr as usize]
}))
.with_write_callback(FunctionWriteCallback(|state: &mut State, addr, byte|
// Don't write to ROM
if addr < 0xFF00 {
state.memory[addr as usize] = byte
})
)
.with_rom(include_bytes!("rom.bin"))
.with_program_counter(0x200);
loop {
let interrupt_requested = emu.step()
.expect("found an invalid opcode (only NMOS 6502 opcodes are supported)");
if interrupt_requested { // Go to IRQ interrupt vector
let vector = u16::from_le_bytes([
emu.read(0xFFFE),
emu.read(0xFFFF)
]);
emu.state.program_counter = vector;
}
}
}
```
---
## Licensing
This may be licensed under either the MIT or Apache-2.0 license, at your option.