用 C 或 C++ 编写图形化 Z80 模拟器

发布于 2024-07-29 06:07:39 字数 1542 浏览 9 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

情归归情 2024-08-05 06:07:39

这有点顺便,但既然你说你没有这种类型的编程经验,你可能想从为 通用虚拟机来自 2006 ICFP 编程竞赛。 这是一个需要经验丰富的程序员 90 分钟才能完成的任务,但许多没有经验的团队能够在几天内完成。 当你完成模拟器后,它会解锁一堆有趣的东西,这可能是你使用 Z80 之前的一个很好的热身。

It's a bit of a side trip, but since you say you have no experience with this type of programming, you might want to start by building an emulator for the Universal Virtual Machine from the 2006 ICFP programming contest. This is a task that takes an experienced programmer 90 minutes, but many teams with no experience were able to complete it in a few days. When you finish the emulator it unlocks a bunch of fun stuff, and it might be a good warmup before you tackle the Z80.

凉栀 2024-08-05 06:07:39

需要添加的一些内容(尤其是 Z80):

  1. 不要相信文档 100% 无错误

    我还没有看到任何没有错误的内容,包括这里提到的那些。

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

    它将帮助您避免以后的许多头痛和困惑。

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

  1. 针对已知代码进行单步跟踪(通常带有注释的 ROM 反汇编)

    这是第一步,目前还没有任何效果。 您将看到错误(反)编码的指令。

  2. 在模拟器中包含不同的 Z80 内核,并以双重模拟的方式处理所有内容

    使用相同的步进、跟踪和运行系统制作两个“独立”的模拟器。 两个CPU都应该有自己的内存硬件等。

    我的双模拟器示例

    • 运行模拟器,并在每条指令后比较寄存器和直接内存位置,例如[hl]、[sp]、[sp-1]...
    • 在第一个差异处停下来看看是什么指令导致了它。
      对其进行调试并继续,直到“没有错误”为止。 请注意第二个核心也可能有错误,因此请谨慎调试。
  3. 当您更易于运行时,请使用核心测试器

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

    例如,原始 ZEXALLZX Spectrum 上的许多操作都失败了(就像针对 MSX64K RAM 所做的那样)没有 ROM),但有一些针对真正的 ZX Spectrum 的版本,并且它们在 ZX Spectrum 上 100% OK强>(也在我的模拟器上:))

    Z80all指令练习器 
    
         hl,...确定 
      添加 hl,.........确定 
      添加 ix,.........确定 
      添加 iy,.........OK 
      aluop a,nn...................好的 
      aluop a,.OK 
      aluop a,....OK 
      aluop a,(+1).........OK 
      位 n,(+1)............OK 
      位 n,...确定 
      cpd........................OK 
      cpi........................OK 
      ............确定 
      <增加,减少>   一个OK 
      <增加,减少>   b.................好的 
      <增加,减少>   bc.................好的 
      <增加,减少>   c.................确定 
      <增加,减少>   d......................好的 
      <增加,减少>   德.................好的 
      <增加,减少>   e.................好的 
      <增加,减少>   嗯…………好的 
      <增加,减少>   hl.................好的 
      <增加,减少>   ix.................好的 
      <增加,减少>   我是......好吧 
      <增加,减少>   我…………好的 
      <增加,减少>   (hl)........................好的 
      <增加,减少>   sp.................好的 
      <增加,减少>   (+1)........OK 
      <增加,减少>   ixh........好的 
      <增加,减少>   ixl........好的 
      <增加,减少>   嗯……好吧 
      <增加,减少>   iyl................OK 
      ld ,(nnnn)…………确定 
      ld hl,(nnnn).................好的 
      ld sp,(nnnn).................好的 
      ld ,(nnnn)…………确定 
      ld (nnnn),......OK 
      ld (nnnn),hl.................OK 
      ld (nnnn),sp.................OK 
      ld (nnnn),......OK 
      ld ,nnnn........OK 
      ld ,nnnn........................OK 
      ld a,<(bc),(de)>........................OK 
      ld ,nn...确定 
      ld (+1),nn............OK 
      ld ,(+1).....OK 
      ld ,(+1).........OK 
      ld a,(+1)........................OK 
      ld ,nn......OK 
      ld ,.......确定 
      ld ,.......确定 
      ld a,(nnnn) / ld (nnnn),a....好的 
      ldd   (1)…………好的 
      ldd   (2)…………好的 
      ldi   (1)…………好的 
      ldi   (2)…………好的 
      否定......................好的 
      ........................OK 
      .........确定 
      shf/rot (+1).........OK 
      shf/rot .OK 
      <设置,资源>   n,....好的 
      <设置,资源>   n,(+1)......OK 
      ld (+1),.....OK 
      ld (+1),.........OK 
      ld (+1),a........................OK 
      ld(),a.........OK 
      测试完成 
      

    如果您要使用 ZEXALL,请注意,这确实是一项详尽的测试,并且 IIRC~50MHz 仿真上花费了大约 30-60 分钟即可完成。 而且需要按一个键才能滚动几次...

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

顺便说一句:你的模拟器效果如何? (你做到了吗?)

指令集

我会在这里复制我的指令集,但它有 1792 行和 121 KB,因此它不符合 30 KB 的限制。 相反,您可以在我的这个答案的下载链接中找到它

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

Some things to add (especially for Z80):

  1. Do not trust the documentation is 100% bug free

    I have not see any without bugs including those mentioned here.

  2. Test your CPU core for bugs properly

    It will save you from many headaches and confusion later.

For testing I am using three approaches:

  1. Stepping/tracing against known code (usually commented ROM disassembly)

    It's the first step when nothing works yet. You will see badly (de)coded instructions.

  2. Include different Z80 cores in your emulator and process everything as double emulation

    Make two 'separated' emulators with the same stepping, tracing, and running system. Both CPUs should have its own memory hardware, etc.

    My dual emulator example

    • Run the emulator and after each instruction compare registers and immediate memory locations like [hl],[sp],[sp-1]...
    • At the first difference stop and see what instruction caused it.
      Debug it and continue until you are 'bug-free'. Beware the second core can be also buggy so debug with caution.
  3. When you are more run-able use core tester

    Use ZEXALL Exerciser. It is the best on Z80 (at least from my experience). It helped me with very many things (my core is now 100% ZEXALL compatible). It's done against real hardware so there are no bugs in it. It's from CP/M so some versions need 64K RAM mode to run. Different OS/ROM or whatever can cause some instructions with memory access to fail, so for those you need to find corrected CRCs or compare against real hardware.

    For example, raw ZEXALL fails many things on ZX Spectrum (as it is done for MSX and 64K RAM without ROM), but there are versions done for real ZX Spectrum and they are 100% OK on ZX Spectrum (and on my emulator too :))

    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
    

    In case you are about to use ZEXALL beware it is really exhaustive test and IIRC on ~50MHz emulation it took around 30-60 min to complete. And it needs to press a key for scrolling few times ...

    If you need a contention model, add proper tests. Then find one. For ZX Spectrum there are many floating bus, interrupt and screen testers. For TI I have no idea... (I am not a TI calculator user)

BTW: How did it go with your emulator? (Have you done it?)

Instruction set

I would copy my instruction set here but it has 1792 lines and 121 KB so it will not fit into a 30 KB limit. Instead you can find it in a download link in this answer of mine

It contains 'all' ZX instructions with correct OP codes, coding timing and machine cycles. It took me few years to put together all documentation, so I am passing ZEXALL 100% correctly. My emulator loads this (1792 instruction) text file to the core on init and configures the instruction decoder and processor at runtime, so I was able to change things really fast and simple enough (if a bug was detected)... It saved me a lot of time.

请爱~陌生人 2024-08-05 06:07:39

米奇是完全正确的。 首先了解处理器。 然后通过编写代码来实现特定的指令来尝试一下。 为此请使用 C++,顺便说一句,而不是 C,否则处理器的概念将不会映射到代码中的类。

在实现指令的过程中,您会发现需要定义诸如标志和指令指针之类的东西。 这最终应该会让您到达需要实现内存模型,甚至 I/O 模型的地方。

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

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

Mitch is completely correct. Start by understanding the processor. Then play around a bit by writing code to implement particular instructions. Use C++ for this, BTW, not C, or the concepts of the processor will not map to classes in your code.

In the process of implementing instructions, you'll find you need to define things like the flags, and the instruction pointer. That should eventually get you to where you need to implement the memory model, and even the I/O model.

You'll eventually have to figure out how to load code and data into memory, and maybe how to dump it back out to disk.

Only then do you need to get to the point of emulating the execution of code, loaded into memory, at a given instruction pointer.

筱武穆 2024-08-05 06:07:39

尝试看看 Sega Master System 和 Game Gear 模拟器(我很确定其中一些是开源的)。 这些游戏机有 Z80 作为 CPU,并且
ZX Spectrum 也用过它,http://www.worldofspectrum.org/emulators.html

Try to take a look to Sega Master System and Game Gear emulators (I'm pretty sure that some are open source). Those consoles have a Z80 as CPU, and
ZX Spectrum used it too, http://www.worldofspectrum.org/emulators.html.

梅倚清风 2024-08-05 06:07:39

您似乎想要的模拟器不仅仅是处理器,而是完整的机器。 您还需要模拟其余硬件,而找到相应的文档可能是等待您的更困难的任务。

根据您的目标,您可能希望从现有的 Z80 模拟器开始。 快速搜索后可以找到其中几个,但没有找到 TI-84 的模拟器。 simh,旧计算机模拟框架已经模拟了 Z80 处理器,添加了对您的其余部分的模拟硬件应该比从头开始更容易。 即使您不走那条路,那里也有一些设计文档可以帮助您。

You seem to want an emulator for more than a processor, but for a complete machine. You'll have also the task of emulating the rest of the hardware, and finding the documentation for that could well be the more difficult task waiting you.

Depending on your goal, you may want to start with an already existing emulator for Z80. A quick search gives several of them but no emulator for TI-84. simh, a framework for old computers emulation has already the emulation of a Z80 processor, adding emulation of the rest of your hardware should be easier than starting from scratch. Even if you don't go that road, there are some design documents there which could help you.

野生奥特曼 2024-08-05 06:07:39

我建议您考虑首先为稍微简单但相关的 CPU 编写一个模拟器,即 8080。 Z80实际上相当复杂(多字节指令、更多寻址模式、索引寄存器等),而8080指令非常容易解码(您可以只使用256项查找表,作为一阶解决方案) 。

如果您决定继续尝试 Z80,则您编写的用于控制程序(显示、数据输入、内存转储等)的所有代码都应该可以重复使用,并且实际上您应该将用户界面设计为模拟处理器-独立的。

I'd recommend you consider starting by writing an emulator for a slightly simpler, but related CPU, the 8080. The Z80 is actually rather complicated (multi-byte instructions, more addressing modes, index registers, etc.), whereas 8080 instructions are very easy to decode (you can just use a 256-entry lookup table, as a first-order solution).

All the code you write to control the program (display, data entry, memory dumps, etc.) should be re-useable if you then decide to go on to attempt the Z80, and indeed you should design the user interface to be simulated processor-independent.

沧笙踏歌 2024-08-05 06:07:39

我在这里了解了有关 Z80 和计算器组件的所有知识:http://www.ticalc.org/programming/

I learned all I know about the Z80 and calculator assembly right here: http://www.ticalc.org/programming/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文