Hi folks,
I'm working on a modern port (not an emulator) of the ZX Spectrum 128K to the raspberry pi. In other words, conversion of the original ROM routines to aarch64, so that Sinclair BASIC and the familiar menus etc are available, but the machine will have more memory, better graphics, better sound etc. So not backwardly compatible with the original spectrum.
In order to do this I've been porting ROM routines, and started writing tests for the raspberry pi port of the routines. However, I would like to verify my assertions about the original routines by writing some tests against the original ZX Spectrum 128K ROM routines too, to line up with the new tests for the ported routines. My plan is to compile some test case data into Z80 assembly, probably use pasmo to compile it and build a snapshot image of a BASIC program to load the machine code and run it, and feed back tests results to the host running fuse. So now ... the question.
The plan is to build a z80 snapshot (or some other format), start up fuse, to load the binary automatically, execute it, and then to somehow shutdown fuse when the test(s) complete. The tests (running under fuse) would communicate either by writing to e.g. RS232 / printer interface / divIDE / some storage medium, and then stop.
1) How can a program running under fuse cause fuse to stop? Is there some way I can signal the tests are complete, and the emulator can stop?
2) What is the most efficient way to communicate test results back to the process that started fuse up?
3) If I have a running fuse process, can I communicate with it using e.g. unix signals, or connect to a control port etc, in order to call APIs such as taking a screenshot, stopping the machine, hitting the NMI reset button, ... all the things you can do in the UI?
4) Can I run fuse without it starting a graphical window? If the z80 assembly has a way to write to a serial port etc that I can get access to from the process that started fuse, I don't need a physical window to open etc. Also this is useful when running e.g. under docker.
Also happy if this is documented, if you can just point me to the docs about communicating with a running fuse process, or how to cause the emulator to stop from inside the machine from a running program.
Many thanks in advance for any tips!
Best wishes,
Pete
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I can probably simplify my use case. So long as I can write to a file on the host machine from code running in the emulator (which seems to be possible, by e.g. outputting data to a virtual printer) then I think I have a solution. The unit tests can output to their results to this file, and write a special marker when the tests are complete, and a script can tail that file on the host and terminate fuse once the marker has been written (which hopefully will also cause the file to be closed cleanly and not leave any open file handles on the host).
Regarding the python interpreter embedding, that looks interesting, although I can also imagine an alternative interface could be appealing - which would be for fuse to have a startup option that allows it to listen on a tcp/ip port, exposing an HTTP REST interface. The REST interface would provide a means to programmatically perform all the actions that are currently available via the API, such as modifying breakpoints, changing configuration dynamically, inspecting register/memory contents, changing aspect ratio, configuring peripherals dynamically, taking screenshots, starting recordings, ….
The reason I favour this approach to a python interpreter is because there are a ton of client-side tools in most modern languages that support interacting with REST interfaces, so it should make it reasonably trivial for people to make their own integrations in their language of choice, to interface with a running fuse process. It is also relatively straightforward to auto-generate docs, describe the interfaces using open standards such as https://swagger.io/https://swagger.io/ etc.
But like I say, I think my use case for now wouldn’t require this, so I have a path to proceed. Many thanks for getting back to me so quickly though.
I think I may have something that could be partially of your interest. Some time ago I proposed following patch: https://sourceforge.net/p/fuse-emulator/patches/426
Basically, it enables two ways communication with emulation session by redirecting fuse's stdin and stdout to the emulated built-in ZX Spectrum 128k (and later models) bit-banging serial port. On emulated ZX Spectrum +3 this can be nicely utilized by CP/M Plus programs (e.g. Qterm), as demonstrated on this video: https://youtu.be/53hfur7ZBJU maybe you'll find it interesting.
Good luck with your project,
Paul
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi folks,
I'm working on a modern port (not an emulator) of the ZX Spectrum 128K to the raspberry pi. In other words, conversion of the original ROM routines to aarch64, so that Sinclair BASIC and the familiar menus etc are available, but the machine will have more memory, better graphics, better sound etc. So not backwardly compatible with the original spectrum.
In order to do this I've been porting ROM routines, and started writing tests for the raspberry pi port of the routines. However, I would like to verify my assertions about the original routines by writing some tests against the original ZX Spectrum 128K ROM routines too, to line up with the new tests for the ported routines. My plan is to compile some test case data into Z80 assembly, probably use pasmo to compile it and build a snapshot image of a BASIC program to load the machine code and run it, and feed back tests results to the host running fuse. So now ... the question.
The plan is to build a z80 snapshot (or some other format), start up fuse, to load the binary automatically, execute it, and then to somehow shutdown fuse when the test(s) complete. The tests (running under fuse) would communicate either by writing to e.g. RS232 / printer interface / divIDE / some storage medium, and then stop.
1) How can a program running under fuse cause fuse to stop? Is there some way I can signal the tests are complete, and the emulator can stop?
2) What is the most efficient way to communicate test results back to the process that started fuse up?
3) If I have a running fuse process, can I communicate with it using e.g. unix signals, or connect to a control port etc, in order to call APIs such as taking a screenshot, stopping the machine, hitting the NMI reset button, ... all the things you can do in the UI?
4) Can I run fuse without it starting a graphical window? If the z80 assembly has a way to write to a serial port etc that I can get access to from the process that started fuse, I don't need a physical window to open etc. Also this is useful when running e.g. under docker.
Also happy if this is documented, if you can just point me to the docs about communicating with a running fuse process, or how to cause the emulator to stop from inside the machine from a running program.
Many thanks in advance for any tips!
Best wishes,
Pete
.... for anyone interested in the project, link is here, btw: https://github.com/spectrum4 - I should have included it above, but forgot!
Hi, I think this proposal of embedding Python in Fuse would help you solve your problem:
https://sourceforge.net/p/fuse-emulator/mailman/fuse-emulator-devel/thread/20180702214116.GA4088%40blackstar.local/#msg36358765
I'm just not sure about the current status of the implementation!
Many thanks Alberto!
I can probably simplify my use case. So long as I can write to a file on the host machine from code running in the emulator (which seems to be possible, by e.g. outputting data to a virtual printer) then I think I have a solution. The unit tests can output to their results to this file, and write a special marker when the tests are complete, and a script can tail that file on the host and terminate fuse once the marker has been written (which hopefully will also cause the file to be closed cleanly and not leave any open file handles on the host).
Regarding the python interpreter embedding, that looks interesting, although I can also imagine an alternative interface could be appealing - which would be for fuse to have a startup option that allows it to listen on a tcp/ip port, exposing an HTTP REST interface. The REST interface would provide a means to programmatically perform all the actions that are currently available via the API, such as modifying breakpoints, changing configuration dynamically, inspecting register/memory contents, changing aspect ratio, configuring peripherals dynamically, taking screenshots, starting recordings, ….
The reason I favour this approach to a python interpreter is because there are a ton of client-side tools in most modern languages that support interacting with REST interfaces, so it should make it reasonably trivial for people to make their own integrations in their language of choice, to interface with a running fuse process. It is also relatively straightforward to auto-generate docs, describe the interfaces using open standards such as https://swagger.io/ https://swagger.io/ etc.
But like I say, I think my use case for now wouldn’t require this, so I have a path to proceed. Many thanks for getting back to me so quickly though.
Pete
Hi Pete,
I think I may have something that could be partially of your interest. Some time ago I proposed following patch: https://sourceforge.net/p/fuse-emulator/patches/426
Basically, it enables two ways communication with emulation session by redirecting fuse's stdin and stdout to the emulated built-in ZX Spectrum 128k (and later models) bit-banging serial port. On emulated ZX Spectrum +3 this can be nicely utilized by CP/M Plus programs (e.g. Qterm), as demonstrated on this video: https://youtu.be/53hfur7ZBJU maybe you'll find it interesting.
Good luck with your project,
Paul