#c64 #模拟器 #Commodore

zinc64-debug

Commodore 64 模拟器调试器支持

2 个不稳定版本

0.8.0 2019年5月6日
0.6.0 2018年8月21日

#144 in 模拟器

每月21次下载
用于 2 crates

GPL-3.0+

335KB
9K SLoC

Zinc64

Build Status Crates.io

** 注意: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 - 软盘支持

入门指南

  1. 安装Rust编译器或按照以下步骤操作:https://rust-lang.net.cn/en-US/install.html.

     curl https://sh.rustup.rs -sSf | sh
    
  2. 克隆此存储库。

     git clone https://github.com/digitalstreamio/zinc64
    

    或下载为zip存档

     https://github.com/digitalstreamio/zinc64/archive/master.zip
    
  3. 构建模拟器。

     cd zinc64
     cargo build --release --all
    
  4. 运行模拟器。

     ./target/release/zinc64
    

    或启动程序

     ./target/release/zinc64 --autostart path
    

Windows注意事项

  1. 安装Microsoft Visual C++ Build Tools 2017。选择Visual C++构建工具工作负载。

  2. 安装SDL2开发库

  3. 将所有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
    
  4.  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