Git Product home page Git Product logo

zx's Introduction

Build Status

zx

ZX Spectrum Emulator written in a mix of Python and C++.

Elven

More screenshots

Features

  • Designed to be suitable for research and development purposes such as unattended testing of Spectrum software, timing analysis, etc.
  • Meant to be easy to customize and re-use via Python interfaces.
  • Fast and accurate emulation.
  • Based on the fast and flexible Z80 emulator.

Development status

  • General status: working pre-alpha.
  • Supported machines: 48K only for now.
  • Display: multi-colour effects, accurate timings.
  • Sound: not supported yet.
  • Tape: TAP and TZX formats supported as well as conversion to WAV.
  • Snapshots: Z80.
  • Playback recordings: RZX.

Installation and running

For the latest release:

$ sudo pip3 install zx

Or directly from the repository for current development version:

$ sudo pip3 install git+https://github.com/kosarev/zx

Local development setups are also supported:

$ git clone --recursive https://github.com/kosarev/zx
$ cd zx
$ python3 setup.py develop --prefix ~/.local

Running:

$ zx

Controls

F1 displays help.

F2 is to save snapshot.

F3 is to load snapshot or tape file.

F6 pauses/resumes tape.

F10 and ESC quit the emulator.

F11 and double click switch between fullscreen and windowed mode.

PAUSE and mouse click pause/resume emulation or RZX playback.

Any Spectrum key stroke resumes emulation and leaves the RZX playback mode back to the regular emulation mode.

Running snapshots, recordings and tapes

$ zx elven.z80
$ zx exolon.rzx
$ zx https://www.worldofspectrum.org/pub/sinclair/games/e/EricTheFloaters.tzx.zip

Supported formats

Snapshots: .z80.

Tapes: .tap, .tzx, .wav.

Playbacks: .rzx.

Screenshots: .scr.

ZX Basic compiler sources: .zxb.

Archives: .zip.

Converting files

$ zx jack.tzx jack.wav
$ zx eric.tap eric.z80

Dumping files

$ zx dump rick.z80
OrderedDict([('id', 'z80_snapshot'), ('a', 213), ('f', 66), ...

On the dump command, zx parses the specified file (that can be of any supported format) in the form of raw Python data.

Reference papers

zx's People

Contributors

kosarev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

danadrianmirea

zx's Issues

Separate the core emulator facilities from the GUI

The emulator is meant to be a library with the Python API serving as one of the available user interfaces. For many applications this does not need any GUI at all. It would thus be great to not require any graphic capabilities unless they are explicitly requested.

Use exceptions for quitting from the emulation loop

Using the done kind of flags is complicated because with several run() calls in place, e.g., a tape_load() followed by a regular run(), the caller side would need to take explicit measures to make sure the the runs in the middle did not terminate due to user actions, such as pressing ESC or F10. These extra checks are easy to forget and misimplement whereas with exceptions it looks like it would be pretty straightforward and natural.

Once done, the stop() function should merely raise that exception.

Support sound

With sound in place we would emulate all 48K features, if I don't miss anything.

Support the ZX basic compiler directly

It might be a good idea to add a direct support for the https://github.com/boriel/zxbasic compiler in the emulator.

Benefits

  • The users of both the compiler and the emulator do not need to bother with intermediate steps such as generating .tzx files.
  • Speed-up. The compiled code can be executed instantly; no need to wait for the emulator to load the tape file. Sounds like a huge potential win in terms of development and testing time?
  • Further extension of the variety of possible unattended scenarios such as converting the compiler .bas programs to .z80 snapshots and .scr screenshots.

What needs to be done

  • The compiler infrastructure has to be available as a library (if not already). This includes handling of translation diagnostics (errors and warnings).
  • The emulator would need a mean to get the compiled program in a form of memory blocks and an entry point rather than a tape file.
  • We need a way to distinct the compiler sources from the regular ZX Basic files, which too use the .bas extension. Possible options may range from giving compiler sources some more special extension (which is probably the simplest way) to scanning the source in order to guess its type (perhaps not very reliable and relatively hard to implement).

Jose @boriel, what do you think?

Emulator crashes executing z80tests.tap

Hi,

Trying your emulator I've found that crashes executing the Mark Woodmass z80tests.tap with:

python3: zx/../z80/z80.h:948: void z80::z80_decoder::on_decode_ed_prefix() [with B = z80::z80_state<z80::root<{anonymous}::Spectrum48::machine_emulator> >]: La declaración `0' no se cumple.

I'm using Fedora 34, Python 3.9.7, G++ 11.2.1.

I attach the test:
z80tests.tap.gz

Thanks for your work.
José Luis

Breakpoint not catched

When using a breakpoint at 0x0008 (i.e. RST #8) the breakpoint is ignored sometimes.

Compile this listing with ZX Basic using zxb.py -TaB --debug-memory xor.bas and try to set a bp at address 0x0008

#define FINISH \
  ASM \
    RST 8 \
    DB 8 ;; "STOP" \
  END ASM


#define SHOW_OK \
  PRINT PAPER 4; INK 0; " OK "; PAPER 8; TAB 31;

#define SHOW_ERROR \
  PRINT PAPER 2; INK 0; FLASH 1; " ERROR "; PAPER 8; FLASH 0; TAB 31;

#define INIT(msg) \
  BORDER 0: PAPER 0: INK 7: CLS \
  PRINT msg


INIT("Test logical XOR")

DIM a as uByte = 5
DIM b as UByte = 0

if a xor b then
  SHOW_OK: PRINT
else SHOW_ERROR: PRINT
END IF

FINISH

Refine and public the API

That's our current largest aim for the project. So far all the changes made to the code were essentially attempts to figure out the right design for various parts of the emulator and related infrastructure. In many ways this work is still in progress. We can remember that some time ago there were changes towards refining the emulation terminating/exiting mechanism -- an effort triggered by using the emulator in https://github.com/boriel/zxbasic, a befriended project of zx (thanks, @boriel!).

Similarly, #17 motivated us to revisit parts of the code related to exceptions and also led to adding API tests that not only check that the exceptions are implemented correctly, but also declare the conventions for the public API and hopefully work as examples and, in a way, documentation.

This task is to continue the work on moving towards mature public API. The project was always meant to be an infrastructure for a wide range of applications, so having a proper public API is vital.

Decide which GUI technology we'd like to stick with

Part of #3.

General directions to consider:

  • No-GUI libraries: Cairo, PyGame, probably strengthened with SDL.
    It might be, our needs in terms of GUI are not very vast, in which case drawing icons manually (like we currently do on tape start/pause for example) may be considered acceptable or even desired.
  • "Classic" widget libraries: Qt, GTK/tkinter, wxWidgets, etc.
    Time-proven solutions, but not very appealing and may take a lot of time to implement desired GUI things.
  • Browser/JS-based solutions: Electron, NW.js, Flexx, etc.
    Relatively easy to use and allow great looking interfaces, though binding with Python and C++ and displaying pixel textures at acceptable FPS would be a pain.
  • A custom GUI on top of a low-level library like Skia.
    I wonder how much effort this approach would take.
  • A third-party GUI solution on top of other low-level libraries, such as ImGUI, Kivy, NanoVG, etc.
    Both seem like they do well with shaders/animations and generally look like a good fit for an emulator's interface.

Split the monolithic emulator code into sets of 'devices'

A sub-task of #18.

Some substantial work has been done under #18 (all the commits mentioned there) to redesign the emulator code into independently cusomisable 'devices', such as screen windows implementing all the GUI features, tape players, keyboards, etc. This gives this work a dedicated ticket for better visibility.

The idea is to give users the freedom of composing their own emulation systems comprised of arbitrary sets of devices. For example, a user may want to have an emulator that has no keyboards or to have two GUI windows (probably serving different purposes) or to have a custom playback player (other than the RZX one).

This work is an important step towards figuring out the desired high-level design of the whole emulation framework.

Better GUI

Presently, all out GUI is basically a GTK window with some key stroke handlers attached. When necessary, e.g., when we have to ask for a file name, all the interactive communication with the user is performed in the underlying terminal window, which works, but doesn't look and feel very appealing. In addition to that, we want, at some point, to have some navigation on recently used/saved snapshots and tapes, browse online directories, etc. That too requires some richer graphical interface comparing what we currently have.

This is an umbrella ticket for this work toward a better user interface.

  • #4 Decide which GUI technology we'd like to stick with

Re-design the input machinery

Functions like __generate_key_strokes() should be rewritten to install Python generators that produce input data and perform other actions as the emulator executes __run_quantum(), that is, as part of the usual execution path and without taking control for all the time of generating port inputs, key strokes, etc. Same mechanism should be used to interface with tape, playback players and, later, the time machine.

The problem with control-taking functions that execute out of the usual emulation loop is that we thus may attempt to load file (e.g., via F3) while being in the process of loading another file, and we don't actually (want to) support that.

This seems to be not only a bug-fixing work, but also an enhancement and a refactoring. :-)

Feature request: send data to I/O ports

Not a bug but a feature request: It would be nice to programmatically send ports values which could be read by the CPU using IN. This could allow to send simulated "keypresses" or "joystick events" to the program to automate QA testing.

EmulationExit exception is protected

If one wants to catch EmulationExit exception, s/he has to write:

from zx._except import EmulationExit

The member _except is prefixed with _ and marked as "protected".
Of course it works, but many linters complain with "accessing a protected member".
Could it be possible to have exceptions in the zx namespace? (I can issue you a PR :) )

Fix installing the zx package

Jose @boriel reports that pip3 install git+https://github.com/kosarev/zx does not work as expected.

It seems the emulator can't find the ROM file when installed this way. Will look into it. Thanks, Jose!

Clean up public API

  • Remove internal and definitions not-mature-enough definitions from the scope for the zx module.
  • Prepend the names of the internal class fields and methods with underscore.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.