EDIT: Ugh, I've started a new page. I'll recap the emulator briefly:
Clock Signal is an MIT-licensed emulator of the MSX 1 (and various non-MSXs) available here. It has both macOS (with a native Cocoa UI) and SDL (UI-less for file association and/or command-line use) targets .
It tries to do a bunch of things in a way very different from other emulators:
- audio is calculated at the MSX clock rate and resampled to your computer's output;
- video output is not frame-driven, but is predicated on a virtual CRT which can be snapshotted at arbitrary intervals, to avoid 50-on-60, 60-on-144 stutter, etc, and to provide latency that scales with your computer refresh rate so that a gaming machine offers a better gaming experience;
- the primary means of launching is to say which game you want to load — the tape, disk or cartridge. The emulator will inspect the media and pick and configure a machine automatically, then type whatever the loading command is;
- it'll try to do that for all included machines, so you can even try some non-MSX software without consulting some other machine's manual; and
- in general it tries at length to be exactly like any other application. E.g. the macOS version uses a completely native UI, allowing you to open arbitrarily many pieces of original media into arbitrarily many different machines at once, each having an independent window for you to size and place wherever you want, or make fullscreen, or arrange as tabs, or whatever.
Like other modern emulators, everything it implements it seeks to do so with complete accuracy to the original machine — it aims for subcycle accuracy. I'm fallible, but often it succeeds.
The emulator has almost no dependencies, so it's super easy to build — on macOS it has none whatsoever that aren't native frameworks. The SDL version requires SDL 2, OpenGL, and scons to build.
Given that of the MSXs, only the MSX 1 is modelled, this emulator does quite a lot less than other MSX emulators, no mater how much it might do some of those things in novel ways*. Probably the only thing it does well that others do not is full support for TSX, in addition to the more standard CAS, DSK, DMG.
(* of potential technical interest: dynamic analysis for cartridge type detection. Just run all the possibilities simultaneously and show the user whichever one is working best, killing off those that aren't working at all.)
---
The originally scheduled reply now follows:
Re: the MSX 2, I've just kind of boxed myself into a corner with the current TMS implementation by trying to be too clever. It's process-on-demand (e.g. if you write a program that writes to the VDP every q cycles, the emulated VDP will itself run in q cycle bursts), but as written it takes a bunch of steps to run for exactly q cycles but avoiding undue cost by doing all colour fetches in that period as one step, all name table fetches as another, etc. It's efficient only if you make the assumption that there's at most one write to fit somewhere into that sequence.
With a command engine, there's arbitrarily many writes to fit into that sequence. So you can't so trivially reorder it.
What I should have done is something more like: (ignoring the border) there's this pattern of 16 cycles of activity that repeats eight times. And, actually, it doesn't really matter whether I run for exactly q cycles, I can treat those building blocks as atomic and just complete all the ones that have finished prior to now. Nobody can ever tell that there are, say, 13 cycles of activity that I should have done now but actually won't do until later because the data they depend upon can't actually mutate before I do the work.
Then I'm not reordering but I'm also not really trying to create a coroutine. And the atomic blocks pattern scales up to incorporating a command engine a lot more easily than does reordering.
I mean, the whole thing is only 730 lines, with copious commenting, and of course it's completely independent of every other part of the machine implementation. So not a big deal to change, I think. Just a mental burden.
In terms of hassles, on the not-specifically-MSX front I've got the whole making OpenGL optional task ahead of me. Thanks, Apple. But it'll be a really good thing to do because the way that multithreads is really naive and really slow. It's at least an order of magnitude more mutex navigations than it needs to be, and the scheduling of the two threads isn't even intelligent. Having to reopen that box will be a very good thing.
Fingers crossed some of that makes sense.
I like your approaches! Quite refreshing.
Quick note to announce an update. I've primarily been working on the video system to eliminate some severe luminance aliasing that was affecting the TMS-esque VDPs, but have also reworked CAS handling to bring my wrangling of that file format more into line with other tools, and have separately fixed an issue in implementation of fast-tape handling that could stomp on routines paged to the same addresses as the BIOS TAPION and TAPIN routines.
The latter affected TSX usage too, being with the realm of the emulation, into which file-format specifics do not reach. Other file formats [still] supported, as I seem to be on that digression: CSW, DSK, DMK and ROM can all cause the emulator to pick an MSX as the machine to launch. If you already have an MSX started, you can of course just feed to it any disk or tape image file format supported by the emulator in any capacity. Though HFE might be the only interesting one, unless you want to prove to yourself that an MSX really, really can't read Commodore- or Apple-format floppies.
The emulator now finally allows user selection of PAL machines, and for the time being I've made the possibly questionable assertion that tapes are mostly PAL releases, so opening a tape will give you a PAL machine by default.
Downloads are where they always are, and it remains MIT-licensed.
Feedback always appreciated.
Nice to see progress on this emulator!!! Very useful to see how some my of scroll routines work on different types of screens
Quick question, I know it's not the focus of the emulator, but does CLK happen to emulate joysticks? (I've made the same mistake in two of my previous games in joystick handling causing my code to fail to manage joystick properly in real hardware, but OpenMSX emulated it as if the joystick was working fine, so just looking for ways to test for such bug again)
Santi, can you please explain what happened in that code? Why didn't it work on real MSX?
It unambiguously does if you have a real Bluetooth or USB joystick. If you're using the Mac version you can hit command+j to switch your keyboard from acting as a keyboard to acting as a joystick. Then press command+k to switch back again, should you need to. Alas I have yet to implement equivalent functionality for the SDL version; it's a switch in how input is pushed into each machine, so it's owned by whomever is generating the input: the platform-specific stuff.
It'd also be good to know if I have issues with my AY's port handling, since beyond the MSX that stuff is also used by the Oric and the Amstrad CPC, and I'm sure it'll be used by other machines I may add in the future.
EDIT: also, please don't hesitate to engage with Manuel if you're so inclined; openMSX is the only reason I've been able to get good documentation on VDP timing and various other issues so although no code is shared this emulator nevertheless owes that team a debt. A minor digression in this thread would be nothing in comparison, and therefore no big deal.
@TomH Great! will give it a try as soon as I get home tonight, and will let you know what I find!
@Manuel, as for the OpenMSX issue, I just added an additional post with some more details to this post ( https://www.msx.org/forum/msx-talk/emulation/psg-register-7-... ). So, that we don't take over TomH's thread here :)
Based on a quick peek in my code, if you've set the AY for output but then attempt to read it for input, you should end up with the AND of whatever value you've set for output and whatever the connected device (i.e. the joystick plus the tape plus the keyboard switch on an MSX) is providing for input. So whatever you put in register 14.
This is based on real documented behaviour from the Amstrad CPC*; I hope it is something I can assert as true for all AYs and not just a result of the CPC's analogue components or Amstrad's particular source of AYs.
* see http://cpctech.cpc-live.com/docs/psgnotes.htm ; "When a port is defined as output (For port A, set bit 6 of register 7 to "1". For port B set bit 7 of register 7 to "1"), writing to the port register (register 14 for Port A, register 15 for port B) will store the data written. A read of the port register will then return the last value written logically ANDed with the input to that port. All 8-bit values can be written."
I just tried, and joystick seems to work on this ROM according to CLK (and also OpenMSX) (https://github.com/santiontanon/xracing/releases/tag/1.0), but in physical MSX systems it does not work. I know the CPC and MSX handle this bit differently, since when Reidrac reported this same bug, it was because he used the Arkos tracker player, which was programmed for the CPC and ported to MSX without noticing the difference in usage of bit 7 of register 7. But I don't know anything beyond that :)
Hopefully we can figure it out in this thread ( https://www.msx.org/forum/msx-talk/emulation/psg-register-7-... ), and I hope the info is useful for both CLK and OpenMSX development :)
Well, doing something specifically because of the information available and having that thing work as intended is at least the best kind of bug! I'll follow along on the other thread.
For those stumbling upon this: the CPC reads its keyboard via Port A of its AY, but also maps the joysticks into the same matrix. So actually there's a similarity here beyond it merely being an AY.
EDIT: so, per the datasheet and my comment on that other thread, it is definitely the case that my emulator is failing to declare AY output values upon it being switched to an input. That does potentially affect all current and future machines that use an AY, so it's a good catch!