用C或C++编写图形化Z80仿真器

Bob*_* M. 13 c c++ z80 emulation

我想有兴趣为Z80处理器编写自己的简单模拟器.我对这种类型的编程没有经验.使用基于C语言的我很好,因为他们是我最熟悉的.

我需要做些什么以及哪些好的教程/参考资料可以帮助我完成这个项目?

我还想要一个为我的TI-84 Plus计算器编写ROM转储应用程序的教程,这样我就可以将它的ROM用于这个仿真器.

Nor*_*sey 16

这是一次侧面旅行,但由于您说您没有使用此类编程的经验,您可能需要从2006年ICFP编程竞赛中通用虚拟机构建仿真器.这项任务需要有经验的程序员90分钟,但许多没有经验的团队能够在几天内完成它.当你完成模拟器时,它解锁了一堆有趣的东西,在你解决Z80之前它可能是一个很好的热身.


Spe*_*tre 11

一些要添加的东西(特别是对于Z80):

  1. 不要相信文档是100%无bug

    我没有看到任何没有错误,包括这里提到的错误.

  2. 正确测试CPU核心是否存在错误

    它会让你免于许多头痛和困惑.

为了测试我使用三种方法:

  1. 对已知代码的步进/跟踪(通常是注释ROM反汇编)

    这是没有任何作用的第一步.您将看到严格(解)编码的指令.

  2. 在您的模拟器中包含不同的Z80内核,并将所有内容作为双重仿真进行处理

    使用相同的步进,跟踪和运行系统制作两个"分离"仿真器.两个CPU都应该有自己的内存硬件等.

    我的双仿真器示例

    • 运行仿真器,并在每个指令比较寄存器和直接存储器位置之后,如[hl],[sp],[sp-1]...
    • 在第一个差异停止,看看是什么指令造成的.
      调试它并继续,直到你"无错误".要小心第二个核心也可能有问题,所以要谨慎调试.
  3. 当你更可运行时使用核心测试器

    使用ZEXALL Exerciser.它是Z80上最好的(至少从我的经验来看).它帮助了我很多东西(我的核心现在是100%与ZEXALL兼容).这是针对真实硬件完成的,因此没有错误.它来自CP/M,因此某些版本需要运行64K RAM模式.不同的操作系统/ ROM或任何可能导致某些内存访问指令失败的操作,因此对于那些需要找到更正的CRC或与真实硬件进行比较的人.

    例如,原始ZEXALLZX Spectrum上失败很多东西(因为它是针对MSX和没有ROM的64K RAM完成的),但是有真正的ZX Spectrum完成的版本,它们在ZX Spectrum上是100%正常的(在我的模拟器上也是如此: ))

    Z80all instruction exerciser
    
    <adc,sbc> hl,<bc,de,hl,sp>...OK
    add hl,<bc,de,hl,sp>.........OK
    add ix,<bc,de,ix,sp>.........OK
    add iy,<bc,de,iy,sp>.........OK
    aluop a,nn...................OK
    aluop a,<b,c,d,e,h,l,(hl),a>.OK
    aluop a,<ixh,ixl,iyh,iyl>....OK
    aluop a,(<ix,iy>+1)..........OK
    bit n,(<ix,iy>+1)............OK
    bit n,<b,c,d,e,h,l,(hl),a>...OK
    cpd<r>.......................OK
    cpi<r>.......................OK
    <daa,cpl,scf,ccf>............OK
    <inc,dec> a..................OK
    <inc,dec> b..................OK
    <inc,dec> bc.................OK
    <inc,dec> c..................OK
    <inc,dec> d..................OK
    <inc,dec> de.................OK
    <inc,dec> e..................OK
    <inc,dec> h..................OK
    <inc,dec> hl.................OK
    <inc,dec> ix.................OK
    <inc,dec> iy.................OK
    <inc,dec> l..................OK
    <inc,dec> (hl)...............OK
    <inc,dec> sp.................OK
    <inc,dec> (<ix,iy>+1)........OK
    <inc,dec> ixh................OK
    <inc,dec> ixl................OK
    <inc,dec>  iyh...............OK
    <inc,dec> iyl................OK
    ld <bc,de>,(nnnn)............OK
    ld hl,(nnnn).................OK
    ld sp,(nnnn).................OK
    ld <ix,iy>,(nnnn)............OK
    ld (nnnn),<bc,de>............OK
    ld (nnnn),hl.................OK
    ld (nnnn),sp.................OK
    ld (nnnn),<ix,iy>............OK
    ld <bc,de,hl,sp>,nnnn........OK
    ld <ix,iy>,nnnn..............OK
    ld a,<(bc),(de)>.............OK
    ld <b,c,d,e,h,l,(hl),a>,nn...OK
    ld (<ix,iy>+1),nn............OK
    ld <b,c,d,e>,(<ix,iy>+1).....OK
    ld <h,l>,(<ix,iy>+1).........OK
    ld a,(<ix,iy>+1).............OK
    ld <ixh,ixl,iyh,iyl>,nn......OK
    ld <bcdehla>,<bcdehla>.......OK
    ld <bcdexya>,<bcdexya>.......OK
    ld a,(nnnn) / ld (nnnn),a....OK
    ldd<r> (1)...................OK
    ldd<r> (2)...................OK
    ldi<r> (1)...................OK
    ldi<r> (2)...................OK
    neg..........................OK
    <rrd,rld>....................OK
    <rlca,rrca,rla,rra>..........OK
    shf/rot (<ix,iy>+1)..........OK
    shf/rot <b,c,d,e,h,l,(hl),a>.OK
    <set,res> n,<bcdehl(hl)a>....OK
    <set,res> n,(<ix,iy>+1)......OK
    ld (<ix,iy>+1),<b,c,d,e>.....OK
    ld (<ix,iy>+1),<h,l>.........OK
    ld (<ix,iy>+1),a.............OK
    ld (<bc,de>),a...............OK
    Tests complete
    
    Run Code Online (Sandbox Code Playgroud)

    如果您打算使用ZEXALL,请注意它是非常详尽的测试和IIRC~50MHz仿真上需要大约几分钟30-60才能完成.它需要按一个键才能滚动几次......

    如果您需要争用模型,请添加适当的测试.然后找一个.对于ZX Spectrum,有许多浮动总线,中断和屏幕测试器.对于TI我不知道......(我不是TI计算器用户)

顺便说一句:你的模拟器怎么样?(你做完了吗?)

指令系统

我会复制我的指令集,但它有1792行和121 KB,所以它不适合30 KB的限制.相反,你可以在我的这个答案的下载链接中找到它

它包含带有正确OP代码,编码时序和机器周期的"全部" ZX指令.我花了几年的时间来整理所有文档,所以我正确地通过了ZEXALL 100%.我的模拟器将此(1792指令)文本文件加载到核心并在运行时配置指令解码器和处理器,因此我能够非常快速和简单地更改内容(如果检测到错误)...它节省了我一个很多时间.init


Joh*_*ers 5

米奇是完全正确的.首先要了解处理器.然后通过编写代码来实现特定指令.使用C++,BTW,而不是C,或者处理器的概念不会映射到代码中的类.

在实现指令的过程中,您会发现需要定义标志和指令指针之类的内容.这应该最终将您带到您需要实现内存模型的位置,甚至是I/O模型.

您最终必须弄清楚如何将代码和数据加载到内存中,以及如何将其转储回磁盘.

只有这样,您才需要在给定的指令指针处模拟加载到内存中的代码的执行.