libretroadmin 010d112156 Currah uSpeech: add the paging and SP0256 hooks the backport left out
Fixes libretro/fuse-libretro#175. With fuse_uspeech enabled and both ROMs
in place, nothing happened: no 'Speech System (c) CURRAH 1983' banner, no
speech.

The peripheral itself was fine. The backport in 6a8cdd2 imported
peripherals/sound/uspeech.c and sp0256.c and wired up settings.dat,
periph.h, machines_periph.c, the startup manager and the two Blip_Synths
in sound.c - everything inside those files and everything that registers
them. What it did not carry over is that the device is driven entirely
from call sites in two files it never touched. uSpeech has no meaningful
I/O port interface: paging and the allophone stream are both memory
side effects, so uspeech_toggle(), uspeech_write() and uspeech_busy()
were compiled, exported and never called by anything.

The reporter's log shows this clearly - both ROMs open, so the option
was reaching uspeech_reset() and the peripheral was activating. It just
had no way to page itself in afterwards.

Four hooks, all taken verbatim from upstream:

  - z80_ops.c, the primary trigger: the Currah pages itself in on an
    opcode fetch at 0x0038, which is the IM1 handler, so an interrupt
    is what puts the ROM in front of the Z80 during boot. Needs a
    matching SETUP_CHECK in z80_checks.h - the computed-goto dispatch
    in z80_do_opcodes() breaks silently if the two lists disagree, so
    the entry goes between usource and multiface in both.

  - readbyte(): data reads of 0x0038 toggle too, and reads in
    0x1000-0x1fff must return uspeech_busy() rather than ROM contents.
    Both conditions imply address < 0x4000, so unlike upstream this
    needs no extra range guard here.

  - writebyte_internal(): writes to 0x1000 and 0x3000 are how allophones
    and the intonation clock actually reach the SP0256. Missing this
    alone would page the ROM in and leave the device mute.

  - unittests.c: uspeech_unittest() was never called.

Verified with a headless libretro harness driving the built core.

Banner: 48K cold boot with the option on renders the Currah copyright
line, matching the screenshot in the issue.

Discriminator: before this commit the option-on and option-off
framebuffers are bit-identical after 250 frames, i.e. the option did
nothing at all. After it, option-off still hashes the same as before
and only option-on differs, so this change is what produces the effect.

Speech: an SZX carrying the USPE chunk, generated through libspectrum
itself, holding a Z80 program that pages in with LD A,(0x0038) and then
writes ten allophones to 0x1000. Before: silence. After: RMS 411.6,
peak 4965, with the envelope showing roughly 1.6s of activity against
1.8s of expected allophone durations, autocorrelation pitch 107Hz and
formants near 640Hz and 1.8kHz - voiced SP0256 output, not noise.

ASan and UBSan clean over the boot, allophone and option-off paths.

Regression: option-off framebuffers are identical before and after
across all twelve machines the core can start without external ROMs,
which also confirms the z80_checks.h insertion did not disturb the
computed-goto table. Pentagon and Scorpion cannot be checked this way -
they fail retro_load_game() looking for 128p-0.rom and 256s-0.rom both
before and after, which is unrelated to this change.

Not fixed here: snapshot loading overrides the option in both
directions. uspeech_enabled_snapshot() writes settings_current.uspeech
straight out of the snapshot, but sync_periph_from_ports_and_options()
only arms a peripheral update when applied_uspeech != opt_uspeech, so
nothing re-applies. A .z80 with no uSpeech chunk therefore switches a
user-enabled uSpeech off, and an SZX with the chunk switches it on with
the option disabled - the latter is visible as full-volume speech in an
option-off run of the test above. That lives entirely in libretro.c and
is left for a separate commit.
2026-08-11 03:44:39 +02:00
2015-06-13 19:35:17 -03:00
2026-08-06 00:55:34 +02:00
2022-02-12 12:32:54 +01:00
2017-10-23 21:24:07 -04:00
2015-02-02 21:38:55 -02:00
2015-08-01 21:57:03 +02:00

fuse-libretro

fuse-libretro is a perpetual work in progress port of the Fuse Unix Spectrum Emulator to libretro. The port was originally developed on Windows with MinGW (32 bits), but it's known to compile and run on Linux x86/x64 and ARM and other systems. fuse-libretro has been tested with the latest RetroArch releases and some Lakka builds.

Games

There are hundreds of free, legally available ZX Spectrum games at World of Spectrum. You should start at the Visitor Voted Top 100 Best Games.

Emulated Machines

  1. Spectrum 48K
  2. Spectrum 48K (NTSC)
  3. Spectrum 128K
  4. Spectrum +2
  5. Spectrum +2A
  6. Spectrum +3
  7. Spectrum +3e
  8. Spectrum SE
  9. Timex TC2048
  10. Timex TC2068
  11. Timex TS2068
  12. Spectrum 16K
  13. Pentagon 128K (needs 128p-0.rom, 128p-1.rom, and trdos.rom)
  14. Pentagon 512K (needs 128p-0.rom, 128p-1.rom, gluck.rom, and trdos.rom)
  15. Pentagon 1024 (needs 128p-0.rom, 128p-1.rom, gluck.rom, and trdos.rom)
  16. Scorpion 256K (needs 256s-0.rom, 256s-1.rom, 256s-2.rom, and 256s-3.rom)

The last four machines need additional ROMs to work. Create a fuse folder inside the system folder, download the required ROMs and put them into that folder.

The port correctly loads and runs many games in all supported formats. If you wish to report an issue with a specific game, please include a link to the exact file you used (e.g., .tap, .tzx, etc.)

Core Options

The core options available on the frontend are:

  • Model (Spectrum 16K|Spectrum 48K|Spectrum 48K (NTSC)|Spectrum 128K|Spectrum +2|Spectrum +2A|Spectrum +3|Spectrum +3e|Spectrum SE|Timex TC2048|Timex TC2068|Timex TS2068|Spectrum 16K|Pentagon 128K|Pentagon 512K|Pentagon 1024|Scorpion 256K): Set the machine to emulate. Note that the this setting will have effect only when a new content is loaded
  • Hide video border (enabled|disabled): Hides the video border, making the game occupy the entire screen area
  • Tape Fast Load (enabled|disabled): Instantly loads tape files if enabled, or disabled it to see the moving horizontal lines in the video border while the game loads
  • Tape Load Sound (enabled|disabled): Outputs the tape sound if fast load is disabled
  • Speaker Type (tv speaker|beeper|unfiltered): Applies an audio filter (libretro should allow for audio filters on the frontend)
  • AY Stereo Separation (none|acb|abc): The AY sound chip stereo separation (whatever it is)
  • TurboSound (disabled|enabled): Emulates a second AY-8910 chip (classic NedoPC protocol), giving 6 sound channels instead of 3. Only used by software written for it
  • Transparent Keyboard Overlay (enabled|disabled): If the keyboard overlay is transparent or opaque
  • Time to Release Key in ms (100|300|500|1000): How much time to keep a key pressed before releasing it (used when a key is pressed using the keyboard overlay)
  • Kempston Mouse Swap Buttons (disabled|enabled): Swaps the left and right Kempston Mouse button mapping

Input Devices

There are seven types of joysticks emulated:

  1. Cursor
  2. Kempston
  3. Sinclair 1
  4. Sinclair 2
  5. Timex 1
  6. Timex 2
  7. Fuller Joystick

Users can configure their joystick types in the input configuration on the front end. However, fuse-libretro allows for two joysticks at maximum so only users one and two can actually use theirs in the emulation.

Users 1 and 2 can choose any of the joysticks as their device types, user 3 can only choose the Sinclair Keyboard.

Buttons A, X and Y are mapped to the joystick's fire button, and button B is mapped to the UP directional button. Buttons L1 and R1 are mapped to RETURN and SPACE, respectively. The SELECT button brings up the embedded, on-screen keyboard which is useful if you only have controllers attached to your box.

There are some conflicts in the way the input devices interact because of the use of the physical keyboard keys as joystick buttons. For a good gaming experience, set the user device types as follows:

  • For joystick games: Set user 1 to a joystick type. Optionally, set user 2 to another joystick type (local cooperative games). Set user 3 to none. This way, you can use L1 as RETURN, R1 as SPACE, and SELECT to bring the embedded keyboard.
  • For keyboard games: Set users 1 and 2 to none, and user 3 to Sinclair Keyboard. You won't have any joystick and the embedded keyboard won't work, but the entire physical keyboard will be available for you to type in those text adventure commands.

If you set a joystick along with the keyboard, the joystick will work just fine except for the bindings to RETURN and SPACE, and the keyboard won't register the keys assigned to the Cursor joystick, or to the L1 and R1 buttons for all other joystick types.

Any of the three users can also be set to the "Kempston Mouse" device type instead. The mouse's left and right buttons map to the host mouse's left and right buttons (see the "Kempston Mouse Swap Buttons" core option to swap them); relative motion drives the Kempston Mouse position directly. Since Kempston Mouse is a single peripheral (not per-player), only set one user to it at a time.

If the pointer doesn't seem to do anything even though it's set to Kempston Mouse, check RetroArch's own Settings > Input > Port N Controls > Mouse Index for that user. Users 2+ default to expecting a second, third, etc. physical mouse (mouse index 1, 2, ...); on a machine with only one physical mouse, point that setting back to index 0.

Supported Formats

Fuse can load a number of different file formats. For now, fuse-libretro only loads tzx, tap, z80, rzx, scl, trd, and dsk files. This decision is somewhat arbitrary (it depends if I can find a file that I can be sure is not corrupted), so feel free to bug me to add other extensions. Please do so via issues here on GitHub.

Multi-disk games

Some Beta 128 disk interface games (TR-DOS .trd/.scl) span more than one disk and prompt you to swap disks mid-game (e.g. Black Raven, UFO 2: Devils of Abyss). Load these via an .m3u playlist listing each disk image path on its own line, and use your frontend's Disk Control menu (in RetroArch: Quick Menu > Disk Control) to eject and swap to the next disk when the game asks for it.

Note: disk writes are kept in memory only. Nothing is ever written back to your image files, and swapping a disk out discards any unsaved in-game changes to it (in-game disk saves do not survive a swap or closing the core). This has always been true of this core; the Disk Control menu just makes it visible.

Save States

Supported.

Setup

  1. Compile fuse-libretro with make -f Makefile.libretro
  2. Copy the resulting fuse_libretro.dll or fuse_libretro.so into the cores folder of your libretro frontend
  3. Profit!

It's not necessary to copy files to the system folder of your libretro frontend anymore! All supporting files are baked into the core, except ROMs for the more exotic Spectrum clones (see Emulated Machines.)

Versions

Versions that are being used to build and test fuse-libretro:

TODO

See the open issues.

Bugs

Many, probably. Open issues or send pull requests.

License

GNU GPLv3.0

S
Description
A port of the Fuse Unix Spectrum Emulator to libretro
Readme GPL-3.0
6.2 MiB
0 Stars 1 Watchers 0 Forks
Languages
C 69.4%
PostScript 10.5%
Shell 7%
Makefile 3.2%
Roff 1.7%
Other 7.9%