2 个不稳定版本
0.8.0 | 2019年5月6日 |
---|---|
0.6.0 | 2018年8月21日 |
#144 in 模拟器
每月21次下载
用于 2 crates
335KB
9K 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 线/引脚来处理,这些 I/O 线/引脚提供给芯片构造函数。这允许芯片的实现相互解耦。
状态
类别 | 组件 | 状态 |
---|---|---|
芯片组 | 6510 CPU | 完成 |
芯片组 | 内存 | 完成 |
芯片组 | 6526 CIA | 完成 |
芯片组 | 6581 SID | 完成 |
芯片组 | 6567 VIC | 完成 |
设备 | 卡带 | 完成 |
设备 | 软盘 | 未开始 |
设备 | 数据磁带 | 完成 |
设备 | 键盘 | 完成 |
设备 | 游戏手柄 | 完成 |
设备 | 鼠标 | 未开始 |
调试器 | 远程控制 | 完成 |
调试器 | Radare2 | 完成 |
格式 | 二进制 | 完成 |
格式 | Crt | 完成 |
格式 | D64 | 未开始 |
格式 | P00 | 完成 |
格式 | Prg | 完成 |
格式 | 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库文件从
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\
复制SDL2.dll到zinc64项目目录
调试器
要启动调试器,使用'-d'或'--debug'选项运行模拟器。可选地,您可以使用'--debugaddress'绑定到特定地址。
./target/release/zinc64 --debug
要连接到调试器,使用telnet连接到调试器使用的地址和端口。
telnet localhost 9999
调试器命令和语法模仿Vice模拟器。要查看可用命令列表,在调试会话中输入
help
或要获取特定命令的帮助
help <command>
Radare2
从版本0.3开始支持radare2。要启动带有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功能测试帮助进行了CPU验证,用于6502处理器
./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为我提供了各种硬件组件的参考
依赖项
~745KB
~13K SLoC