Writing a graphical Z80 emulator in C or C++ [clos

2019-02-01 13:26发布

问题:

I want to take an interest in writing my own simple emulator for the Z80 processor. I have no experience with this type of programming. I am mostly fine with using C-based languages as they are the ones I know best.

What do I need to accomplish this and what are some good tutorials/references that could aid me in this project?

I would also like a tutorial for coding a ROM-dumping application for my TI-84 Plus calculator so I can use its ROM with this emulator.

回答1:

Perhaps start by looking at these:

A good tutorial can be found here: Independent Z80 Assembly Guide

Z80 DOCUMENTATION

The Undocumented Z80 Documented v0.91 (pdf)

The Complete Z80 Instruction Reference

Z80 Microprocessor Instruction Set Summary



回答2:

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.



回答3:

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.

    • 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

  • What's the proper implementation for hardware emulation.

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.



回答4:

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.



回答5:

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.



回答6:

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.



回答7:

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.



回答8:

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