#模拟器 #nes #6502

emulator_6502

Rust语言实现的MOS 6502模拟器,旨在作为2020年冬季实习面试过程中的一个亮点

4个版本 (2个稳定版)

1.1.0 2021年2月10日
1.0.0 2020年4月8日
0.2.0 2019年10月11日
0.1.0 2019年9月24日

#56模拟器

每月下载量 24次
3 个软件包中使用 (通过 gc_nes_core)

MIT 许可证

250KB
6.5K SLoC

Build Status Crate Documentation

emulator_6502

大家好,未来的雇主,以及搜索“6502模拟器 Rust”的人们,你们找到了我自2019年9月初开始的小型个人项目,该项目用于我在2020年冬季实习面试过程中的一个亮点。项目的目标是展示我在开发复杂系统时学习新编程语言的能力。

这是一个通用的Rust语言实现的MOS 6502模拟器,能够独立执行代码或作为6502被使用的许多系统中的一部分执行代码,包括Commodore 64、Apple II和任天堂娱乐系统。为此,该库提供了Interface6502 trait,允许客户端实现自己的函数来读取和写入内存地址。关于一个实际的实现示例,请查看我的gc_nes_emulator

定义接口


struct BasicRam{
    ram: Box<[u8; u16::max_value() as usize + 1]> //The maximum address range of the 6502
}

impl BasicRam {
    fn load_program(&mut self, start: usize, data: &mut Vec<u8>){
        self.ram[start..].clone_from_slice(data);
    }
}

impl Interface6502 for BasicRam{
    fn read(&mut self, address: u16) -> u8{
        self.ram[address as usize]
    }

    fn write(&mut self, address: u16, data: u8){
        self.ram[address as usize] = data
    }
}

在这个例子中,与模拟器一起使用的接口简单地映射地址到ram位置。客户端负责将希望运行的6502二进制程序加载到地址范围内的合适部分。更复杂的接口可以将特定的地址映射到其他模拟设备组件。

例如,使用此6502模拟器的NES实现将地址0x2000-0x2007的读取和写入映射到与NES图像处理单元的通信,而Commodore 64实现将地址0xd000-0xd3ff映射到屏幕绘制。

运行程序


fn main() -> Result<()>{
  let mut ram = BasicRam{ ram: Box::new([0; u16::max_value() as usize + 1]) };

  //Load a program into memory...
  let mut file = File::open("C:/some_6502_program.bin")?;
  let mut buffer = Vec::new();
  file.read_to_end(&mut buffer)?;

  //Copy it into the BasicRam
  ram.load_program(0x0400, &mut buffer);

  let mut cpu = MOS6502::new(); //Create a new emulator instance
  cpu.set_program_counter(0x0400); //Set the program counter to the first byte of the program in memory
  cpu.cycle(&mut ram); // The emulator can execute cycles individually, for systems that require precise timing...
  cpu.execute_instruction(&mut ram); // or instruction by instruction for a coarser approach

  Ok(())
}

每个周期/指令,处理器借用了接口的可变所有权,以便读取和写入。

注意:当执行指令时,整个计算是在处理器简单地等待剩余周期数之前同时完成的,这意味着读取和写入的定时仅基于指令级别,而不是周期级别。

支持的功能

  • 实现了文档化的指令集的全套
  • 模拟了原始6502硬件中存在的错误
  • 当启用“binary_coded_decimal”编译功能时,使用二进制编码的十进制数
  • 当启用“illegal_opcodes”编译功能时,使用非法未记录的操作码

如果未启用“illegal_opcodes”编译功能而调用非法指令码,模拟器将记录警告并在适当数量的周期内运行,不改变状态。

当前版本:1.1.0

许可证:MIT

依赖项

~87KB