10个版本 (破坏性更新)
0.8.0 | 2019年5月6日 |
---|---|
0.7.0 | 2018年12月29日 |
0.6.0 | 2018年8月21日 |
0.5.2 | 2018年7月25日 |
0.1.0 | 2018年1月13日 |
#173 in 模拟器
每月下载量 29次
用于 zinc64-sdl
480KB
12K 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 trait实现来替换模拟器组件。core::ChipFactory trait的默认实现是通过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 trait,因此芯片与其他组件之间的交互仅限于并通过提供给芯片构造函数的共享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库文件从
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.dll从
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为我提供了各种硬件组件的参考
依赖项
~22MB
~442K SLoC