JSSpeccy: A ZX Spectrum emulator in Javascript

I’m really typecasting myself here. If there were an international “Person most likely to write a Spectrum emulator in Javascript” award, I’d have taken it for the last five years running. So here it is – probably the most stereotypical project I’ll ever come up with.

Writing this wasn’t actually such a big deal – the Z80 core was ported from the one in Fuse, with the Perl-and-C-preprocessor-munging trickery still intact, and Javascript is syntactically close enough to C that that wasn’t a mammoth task. (I got 90% of it done on the train journey back from International Vodka Party alongside recording silly songs about tube stations.) The one fiddly bit was working around the places where the Fuse code used low-level C constructs to its advantage: using unions to chop and change between individual registers and 16-bit register pairs, and relying on limited-size C data types (often in pretty subtle ways) to truncate 8-bit and 16-bit values at the right time, whereas Javascript only has integers. (Actually, the really time-consuming bit was debugging it all… luckily, Fuse has a rather excellent test suite too.)

The rest is just creative abuse of the <canvas> element, as usual… it’ll take advantage of the putImageData interface to do the pixel pushing if available (on my machine Firefox has it, Safari doesn’t) and fall back on drawing 1×1 pixel rectangles otherwise. This time I’ve thrown in Google’s ExplorerCanvas as a nod to those poor unfortunates still stuck with Internet Explorer. Incidentally, I’d be curious to know how it rates on Google Chrome (I don’t have an XP/Vista box to test on) – if the hype is true (and it implements the putImageData interface like all good up-to-date browsers should) then I’d expect it to comfortably reach 100% Spectrum speed on modest hardware.

105 Responses to “JSSpeccy: A ZX Spectrum emulator in Javascript”

  1. Ha! nice to see I’m on the right track :) Thanks for the pointer on endianness, I did think that could be an issue (although really should not be in something like Javascript!). Does that also mean that the alpha component in a Uint8Array for an image would be first of each four bytes one some platforms and on others it would be last?

  2. matt says:

    @Simon Holdsworth – My impression from dabbling with WebGL (and its spin-offs like typed arrays) is that they’ve sacrificed a lot of the ‘javascript-ness’ in favour of providing the thinnest possible wrapper around the hardware…

    Good question about image alpha channels – I’ve just had a dig into the WebGL spec to see how they deal with it, and it appears that they partially side-step the issue by not actually offering 32-bit RGBA as a data format: it’s all done with 4/5/6-bit values packed into shorts (and it specifically tells you to use Uint16Array, so presumably if you used Uint8Array instead you’d encounter the same endian issues.)

  3. Tom says:

    As a youth I cut my programming teeth on the SmallC compiler and tools. I’ve been idly looking around for something to help teach my kids the basics of computing and having seen visual6502 I was wondering about hacking that into a system. Having come across your site I was wondering about digging out the CPU code and mixing it with the Z88dk, http://bluishcoder.co.nz/js8080/ and a few other bits and bobs to make a complete learning environment.
    You dont by any chance have a JS z80 that would be suited to this?

  4. matt says:

    Hi Tom – not sure how well it’ll fit together with your other components, but the Z80 core from JSSpeccy should hopefully separate quite well from the rest of JSSpeccy – you’ll need to provide your own implementations of memory, IO and so on and pass those as parameters to the Z80 object.

  5. Matt, just saw the Register article about the Spectrum symphony, enjoyed watching the video – good job!!!

    I’ve just finished a big revamp of my site including my new Javascript ZX81 emulator. Its fast on my PCs and also works pretty well on an iPad, although there it runs around 75% of the original speed. I’m not sure if you’ve measured the performance of JSSpeccy on iPads and such? I’ve squeezed pretty much every ounce I can out of the code.

    One hitch with an iPad which I’ve solved with my emulator is the lack of keyboard. Something that blew me away – on an iPad the keyboard when zoomed in is almost exactly the same size as an original ZX81, and has the genuine authentic complete lack of feedback, almost 35 years later ;)

Leave a Reply