2 个不稳定版本
0.8.0 | 2019年5月6日 |
---|---|
0.6.0 | 2018年8月21日 |
#362 在 模拟器 中
用于 2 crates
280KB
7K SLoC
Zinc64
** 注意:zinc64 crate 已更名为 zinc64-emu **
概述
zinc64 是一个带有“电池”的 Commodore 64 模拟器工具包。它设计为用作独立模拟器或用于构建新模拟器的库。设计理念允许每个组件被替换或用不同的实现替换。因此,特别考虑了建模芯片之间的交互而不将它们耦合在一起。
它实现了 MOS 6510 CPU、MOS 6526 CIA、MOS 6581 SID、MOS 6567/6569 VIC 芯片组以及与 C64 一起提供的各种设备和外围设备。
故事
zinc64 是作为一个学习 Rust 和更详细地探索 Commodore 64 硬件的练习开始的。大约在 2016 年中旬,我需要满足我的 8 位怀旧之情,所以我买了一台可工作的 Commodore 64(物理版本)并开始组装将软件加载到上面的各种配件。很快,我就买了一本 C64 程序员参考指南,其余的就成为历史。
2019 年带来了对修订的 SDL 端口的支持,包括控制台支持和裸机环境,特别是裸机 Raspberry Pi 3 端口。请参阅 zinc64-rpi 以查看早期预览。
设计
功能 std
zinc64-emu crate 可以在没有标准库的环境下工作,例如在裸机环境中。要在 #[no_std] 环境中使用 zinc64-emu,请使用
[dependencies]
zinc64-emu = { version = "0.8.0", default-features = false }
可扩展性
模拟器组件可以通过提供自定义 core::ChipFactory 特征实现来替换。core::ChipFactory 特征的默认实现是通过 system::C64Factory 完成的。芯片工厂对象传递给提供核心模拟器功能的 system::C64 组件。
以下是如何一起使用这些组件的示例
let config = Rc::new(Config::new(SystemModel::from("pal")));
let chip_factory = Box::new(C64Factory::new(config.clone()));
let mut c64 = C64::new(config.clone(), chip_factory).unwrap();
c64.reset(true);
用于模拟系统操作的四个核心特征是 Chip、Cpu、Mmu 和 Addressable。
/// A chip represents a system component that is driven by clock signal.
pub trait Chip {
/// The core method of the chip, emulates one clock cycle of the chip.
fn clock(&mut self);
/// Process delta cycles at once.
fn clock_delta(&mut self, delta: u32);
/// Handle vsync event.
fn process_vsync(&mut self);
/// Handle reset signal.
fn reset(&mut self);
// I/O
/// Read value from the specified register.
fn read(&mut self, reg: u8) -> u8;
/// Write value to the specified register.
fn write(&mut self, reg: u8, value: u8);
}
/// CPU is responsible for decoding and executing instructions.
pub trait Cpu {
...
/// The core method of the cpu, decodes and executes one instruction. Tick callback is invoked
/// for each elapsed clock cycle.
fn step(&mut self, tick_fn: &TickFn);
// I/O
/// Read byte from the specified address.
fn read(&self, address: u16) -> u8;
/// Write byte to the specified address.
fn write(&mut self, address: u16, value: u8);
}
/// Represents memory management unit which controls visible memory banks
/// and is used by CPU to read from and write to memory locations.
pub trait Mmu {
/// Change bank configuration based on the specified mode.
fn switch_banks(&mut self, mode: u8);
// I/O
/// Read byte from the specified address.
fn read(&self, address: u16) -> u8;
/// Write byte to the specified address.
fn write(&mut self, address: u16, value: u8);
}
/// Addressable represents a bank of memory.
pub trait Addressable {
/// Read byte from the specified address.
fn read(&self, address: u16) -> u8;
/// Write byte to the specified address.
fn write(&mut self, address: u16, value: u8);
}
由于除 Cpu 和 Mmu 之外的所有系统组件都实现了 Chip 特征,因此芯片和其他组件之间的交互仅限于并通过提供给芯片构造函数的共享 I/O 线/引脚来处理。这允许将芯片的实现解耦。
状态
类别 | 组件 | 状态 |
---|---|---|
芯片组 | 6510 CPU | 完成 |
芯片组 | 内存 | 完成 |
芯片组 | 6526 CIA | 完成 |
芯片组 | 6581 SID | 完成 |
芯片组 | 6567 VIC | 完成 |
设备 | 卡带 | 完成 |
设备 | 软盘 | 未开始 |
设备 | 数据磁带 | 完成 |
设备 | 键盘 | 完成 |
设备 | 游戏手柄 | 完成 |
设备 | 鼠标 | 未开始 |
调试器 | 远程 | 完成 |
调试器 | Radare2 | 完成 |
格式 | 二进制 | 完成 |
格式 | CRT | 完成 |
格式 | D64 | 未开始 |
格式 | P00 | 完成 |
格式 | 程序 | 完成 |
格式 | Tap | 完成 |
格式 | T64 | 未开始 |
客户端 | SDL | 进行中 |
客户端 | Raspi3 | 进行中 |
路线图
- v0.9 - rpi端口
- v0.10 - 软盘支持
入门指南
-
安装Rust编译器或按照以下步骤操作:@ https://rust-lang.net.cn/en-US/install.html.
curl https://sh.rustup.rs -sSf | sh
-
克隆此仓库。
git clone https://github.com/digitalstreamio/zinc64
或下载zip存档
https://github.com/digitalstreamio/zinc64/archive/master.zip
-
构建模拟器。
cd zinc64 cargo build --release --all
-
运行模拟器。
./target/release/zinc64
或启动程序
./target/release/zinc64 --autostart path
Windows注意事项
-
安装 Microsoft Visual C++ Build Tools 2017. 选择Visual C++构建工具工作负载。
-
安装 SDL2开发库.
-
从
SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\
到
C:\Users\{Your Username}\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\x86_64-pc-windows-msvc\lib
-
从
SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\
到zinc64项目目录
调试器
要启动调试器,使用'-d'或'--debug'选项运行模拟器。可选地,您可以指定'--debugaddress'以绑定到特定地址。
./target/release/zinc64 --debug
要连接到调试器,通过telnet到调试器使用的地址和端口。
telnet localhost 9999
调试器命令和语法模仿Vice模拟器。要查看可用命令列表,在调试会话中输入
help
或要获取特定命令的帮助
help <command>
Radare2
Radare2的初始支持已合并到版本0.3中。要使用RAP服务器支持启动模拟器,运行
./target/release/zinc64 --rap 127.0.0.1:9999
然后通过
radare2 -a 6502 -d rap://localhost:9999/1
示例
我包含了一些来自Kick Assembler的示例,我使用它们测试模拟器的各个组件。它们位于此仓库的bin文件夹中,可以通过模拟器的自动启动选项启动。
./target/release/zinc64 --autostart bin/SineAndGraphics.prg
程序 | 状态 |
---|---|
6502_functional_test.bin | 通过 |
FloydSteinberg.prg | 通过 |
KoalaShower.prg | 通过 |
Message.prg | 通过 |
MusicIrq.prg | 通过 |
Scroll.prg | 通过 |
SID_Player.prg | 通过 |
SimpleSplits.prg | 失败 |
SineAndGraphics.prg | 通过 |
测试
使用Klaus2m5功能测试对6502处理器进行了CPU验证
./target/release/zinc64 --binary bin/6502_functional_test.bin --offset=1024 --console --loglevel trace
键盘快捷键
快捷键 | 功能 |
---|---|
Escape | 控制台 |
Alt-Enter | 切换全屏 |
Alt-F9 | 重置 |
Alt-H | 激活调试器 |
Alt-M | 切换静音 |
Alt-P | 切换暂停 |
Alt-Q | 退出 |
Alt-W | 快速模式 |
Ctrl-F1 | 磁带播放/停止 |
NumPad-2 | 摇杆底部 |
NumPad-4 | 摇杆左 |
NumPad-5 | 摇杆开火 |
NumPad-6 | 摇杆右 |
NumPad-8 | 摇杆顶部 |
致谢
- Commodore团队为构建标志性的8位机器
- Rust开发者们,为开发提供了不可思议的语言
- 感谢Rafal Wiosna将他对8位机的热情传递给我 ;)
- 感谢Klaus Dormann提供的6502_65C02_functional_tests,没有它我将迷失方向
- 感谢Dag Lem为其reSID实现
- 感谢Christian Bauer的精彩论文“MOS 6567/6569视频控制器(VIC-II)及其在Commodore 64中的应用”
- 感谢Peter Schepers的“各种模拟器文件格式介绍”
- 感谢c64-wiki.com为我提供了各种硬件组件的参考
依赖项
~750KB
~13K SLoC