ZX-Origins - free 8-bit fonts for games

I started designing fonts around 1987 on an 8-bit Sinclair ZX Spectrum. Many years later because of my active involvement in the Spectrum emulation scene Paul Dunn asked me to provide some fonts for his excellent BASIN Sinclair BASIC for Windows. My interest in 8x8 monospaced fonts was suitably rekindled and I ended up delivering about 60 - some even extracted from my original +3 disk images.

I’ve wanted to get these fonts online earlier but the raw files are only of use to BASIN users or those suitably familiar with the convoluted process and tools to get them into a Spectrum or emulator. Even trying to use them on Windows was a pain given that TrueType is all about scalable fonts and getting them pixel-perfect is quite the endeavor.

Fellow typographer and Spectrum fan Paul van der Laan gave me some suitable tips for pixel-perfect fonts at specific multiples (8px on Windows) and I put together an automated pipeline using a modified version of John Elliot’s psftools which converts the original ZX font to PSF and then to BDF. Getting to TrueType TTF involved FontLab 5 Studio and some Python scripting and the various conversion process and uploads were taken care of with some bash scripting.

It’s always hard to get a true feel for a font from a simple run of letters so I created a simulated preview mechanism that re-rendered some hand-picked screens from Sinclair, Commodore, Amiga, Atari and BBC computers to showcase each one. If your browser supports HTML5 canvas you’ll see these! You can also drag any raw Spectrum font file such as those created by BASIN to any of my ZX-Origins pages to see your own font rendered with these samples.

The uploads are now mostly complete - there are 78 typefaces and well over 120 actual fonts once you include the variations, styles and weights that some typefaces have. This number may increase from time to time if and when I finish off styles in my _incomplete folder, resurrect some abandoned ones (sorry Unwanted Attention), or get inspired for something entirely new.

So without further ado head over to ZX Origins and grab a font or two for your latest 8-bit retro game!

WordPress to Jekyll part 6 - A faster build

My site goes back to 2004 and is reasonably sized but not massive even with the comments so waiting 30 seconds for every change to be reflected is not only a pain but quite disappointing.

I investigated several options and ended up using a few in combination, skipping others and holding out for one.

Incremental build

Launching with the --incremental switch e.g. bundle exec jekyll serve --incremental can speed things up a bit but there are issues here. One is that it still builds a lot of pages, tags and categories as it updates and the second is that if you’re using collections it misses rebuilding pages that reference that collection.

Verdict: Not great.

WSL2 or a Mac?

My primary dev box these days is a beefy Windows box. Jekyll doesn’t seem to want to run at all under native Windows and Windows Subsystem for Linux (WSL) can be pretty slow compared to a Mac. Microsoft have announced Windows Subsystem for Linux 2 (WSL2) which will be much faster but it isn’t available until June 2019 and even then that’s to insiders.

Verdict: Hold tight.


Hubber extrodinaire Ben Balter developed the Jekyll Include Cache which can help speed up building.

The approach it uses is that you can switch out a regular include x for include_cached x providing that x doesn’t depend on any state/variables. For me that meant my footer, sidebar and navbar could all easily be parsed and stored just once by changing things like: {% include footer.html %} to {% include_cached footer.html %}

There are however places where state is important and this plugin can still help there. For example my header was called using {% include head.html %} and contained code like this:

<meta name="description" content="{{ page.excerpt | markdownify | strip_html | truncatewords:40 }}" />
<title>{{ page.title }} &raquo; DamienG</title>
<meta name="twitter:url" content="{{ page.url | absolute_url }}" />

What you can do here is pass parameters to include_cached and read them the other side. Replacing the include with:

{% include_cached head.html title=page.title url='page.url | absolute_url' excerpt='page.excerpt | markdownify | strip_html | truncatewords:40' %}

And changing the include itself to:

<meta name="description" content="{{ include.excerpt }}" />
<title>{{ include.title }} &raquo; DamienG</title>
<meta name="twitter:url" content="{{ include.url }}" />

Which actually also made the header easy to read as the title, description and url are used multiple times for the various types of metadata (Twitter, OpenGraph etc).

Verdict: Some good improvement.

No paging, tags and collections for local dev

I never actually browse the pages, tags or collections locally but they’re very important for the CI and publishing. I’ve manually turned them off in the past but it’s error-prone and a pain but there is a way to avoid that!

Simply move the parts of your configuration you don’t want to be part of your local build into a new configuration file, for example I moved the following parts from my _config.yml into a new _config-publish.yml:

  enabled: true
    enabled: true
    enabled: true

  enabled: true

I also moved my Aloglia configuration block here too so that local builds with content not yet published does not turn up in the search index!

It’s important to remember to add --config _config.yml,_config-publish.yml to any Jekyll build steps on your CI server, for example mine has:

 - run:
    name:    Build site
    command: bundle exec jekyll build --config _config.yml,_config-publish.yml 2>&1 | tee $JOB_RESULTS_PATH/build-results.txt


 - run:
    name:    Index with Algolia
    command: bundle exec jekyll algolia --config _config.yml,_config-publish.yml

Verdict: Awesome, drops from 30s to 17s for full build.

Turn off comments for local

I thought this would have more of an impact but it only shaves another couple of seconds off the site build times.

To do this add the following first and last lines to your comments.html include (I’ll probably add this to the Jekyll Blog Comments system)

{% if site.comments.enabled %}
... (existing comments.html contents here)
{% endif %}

and remember to add this to your _config-publish.yml:

  enabled: true

Verdict: Okay, drops from 17s to 15s for full build.


Between these steps my site has gone from almost 50 seconds to about 17 for a full build without incremental and using that now means about 1-2 seconds!

I can’t wait for WSL2 to push this over the edge!


Azure Pipeline Build Variables

Azure Pipelines has been interesting to me especially given the generous free open source tier and seemingly instant availability of build agents. The setup is especially easy if you’re building .NET targets with lots of useful starters available.

A couple of areas have, however, been frustrating however - build variables and the difficulty in getting the app installed and the limitations on triggers if you can’t (non-GitHub apps can’t be installed on Enterprise accounts even if FREE).

We’ll concentrating on the build variable oddities for this post.

The Pipeline configuration helpfully has a tab named Variables that looks much like you’d expect with a big list of names, values, a lock icon and a checkbox for ‘Settable at queue time’.

There are however some oddities when compared to existing CI servers with these especially if you expect to be able to use them as environment variables.


The documentation for these - especially for Predefined build variables shows the expected variables but they use a dot naming convention.

This dot naming convention does not work if you are using them as environment variables. They are upper-cased and . is replaced with _ so for example:

Build.BuildNumber is actually BUILD_BUILDNUMBER.


One even more confusing element is that when you mark you own (sensibly named) value as secret it suddenly stops being available as a environment variable.

Note: You should never build PRs with secret variables. Doing so allows anyone to submit a PR that simply echos them to the build log for harvesting. By default secrets are not available to pull requests in Azure Pipelines - leave it that way!

So how do you get these secret variables re-exposed as environment variables? While Stack Overflow has a bunch of complicated answers there is a much simpler way:

  1. Select the step from your job
  2. Expand the environment variables section
  3. Repeat the following steps for each environment variable
  4. Enter your variable name in the Name box
  5. Enter $(variable_name) in the Value box

Now when you run the job the build step will use the secure variable. This screenshot shows you an example:

Screenshot of the Azure Pipeline Variable being mapped

If I figure out workarounds for the app installations I’ll blog them!


Revisiting my BBC Micro - display, speech & more

It’s been a while since I blogged about Revitalizing my BBC Micro. In that time I’ve performed a few upgrades you might find interesting…

Display requirements

As useful as the tiny Amstrad CRT was I wanted something bigger, brighter and sharper. LCD is terrible for retro systems with blurry scaling attempting to draw images designed to take advantage of CRTs. Emulator authors spend significant effort trying to mimic CRT effects for a true retro feel but the best option is just to use a CRT.

Most machines in the 80s and early 90s were designed for TV compatibility and so operated on a 15KHz horizontal refresh rate. The VGA CRT monitors people struggle to give away aren’t going to work as they start at 31.5KHz. British machines like mine also use the PAL (UK) video system rather than the NTSC (USA) system - ideally a display would handle both.

If you don’t need any VGA frequencies then a Sony PVM is the way to go. I also own an Amiga 1200 which is capable of some VGA modes so it would be nice to have one CRT for everything. Multi-sync monitors can do both but were rare back then and are even rarer now and the shipping cost on CRTs limits can be prohibitive.

Commodore 1942 CRT

Figuring out resistor levels and sync signalsLuckily for me a Commodore 1942 CRT “bi-sync” turned up on Craigslist just 15 minutes from my house for $50. It was designed for the later Amiga models so it does both 15KHz most of my machines can do and some VGA resolutions too. Perfect.

Connecting it to the BBC was a little trickier than I anticipated. That Amiga design means it expects the horizontal (HSYNC) and vertical sync (VSYNC) signals on two different pins to match the Amiga’s video port rather than the composite sync (CSYNC) all my RGB capable machines offer (Amiga excluded).

I briefly experimented with connecting the CSYNC to HSYNC, VSYNC and indeed both but failed failed to get a stable display. Digging in to the Motorola 6845 CRT controller chip that powers the Beeb reveals both VSYNC and HSYNC on pins 40 and 39 respectively. A quick snip of the RGB port’s unused 5v and sync pins let me repurpose them to HSYNC and VSYNC direct on the 6845. A stable but over-saturated picture was a welcome next step that didn’t involve me needing to create a SYNC splitting circuit (I did that later to connect with my Spectrum +3).

Running Citadel on the Commodore 1942The over-saturation is because the BBC Micro outputs either 0V or 5V - off or on - for each color. The Amiga monitor is analogue and accepts any amount of color between 0V and 0.7V. I read guides on calculating the voltage drop but it still looked saturated so I kept increasing resistor values until I found values that looked right.

The final result definitely made me smile. It looked better than the Microvitec CUB monitors our school had back in the day without losing the CRT appeal. Success!

Speech synthesis

Hearing Superior Software’s SPEECH package blurt out any phrase we cared to throw at it was a blown-away moment at school. I’ve always wondered what the official Acorn speech system was like especially as every time I open the case empty sockets IC98 and IC99 call out for the Texas Instruments TMS5220 speech processor and associated TMS6100 voice synthesis memory.

The TMS5220 chip was a successor to that in Speak & Spell, Bally/Midway pinball machines and some arcade games as is quite easy to come by. The TMS6100 was available in many variants and the BBC commissioned some of their own including one sampled by BBC news anchor Kenneth Kendall. This chip is rare now and the fact the TMS6100 is not a regular ROM means you can’t just burn a copy. Thankfully Simon Inns created an emulator which can run on an ATMega32U2 to provide a drop-in replacement!

I obtained a TMS5220 and pre-built TMS6100 emulator board from Mark Haysman at RetroClinic who I can thoroughly recommend! (My SMT soldering skills are not up to this)

After inserting the two chips and powering nothing looks different. This command sequence however provides a good test mechanism:

TMS5220 chip and TMS6100 emulator board


Pressing any key on the keyboard will cause the machine to say aloud the letter although it has some odd ideas about what the symbols on the keyboard are.

I will be experimenting with this more as I dig through the capabilities in the manual as it isn’t as easy to use as Superior Software’s Speech! which lets you type things like:

*SAY Hello there.
*SAY I've got a bad feeling about this.

ROM experiments

My school had a single copy of the Advanced User Guide so I felt privileged when the teacher would let me borrow it although on reflection I doubt anyone else wanted to. Page 395 cryptically teases:

Up to 16 paged ROMS are therefore catered for, 4 of which are on the main circuit board.

So the OS supports 16 ROMs but there are only physical sockets for 4 (IC52, IC88, IC100 and IC101). Typically BASIC and the disc filing system (DFS or ADFS) take two of them leaving just two usable ROM sockets for expansion.

The schematics reveal IC76 is the ROM Select Latch and is a 74LS163 with 4 output pins thus providing 16 possible combinations - one for each ROM you could use so both the OS and the circuitry can support what we need if we could physically get the ROMs wired in.

The Beeb supports either 8K (2764) or 16K (27128) ROMs and EPROMs. Later 64KB (27512) chips became available which are almost pin-compatible with the 27128 except:

A collection of ROMs and an EPROM

27512 Pin 27127
A15 1 Vpp
A14 27 /PGM
/OE 22 /OE, Vpp

The /PGM and Vpp lines are for writing - an EPROM programmer will care about these but our Beeb won’t.

The A14 and A15 lines are the address lines for accessing the higher memory. With them both low the chip just acts like a regular 16K (27128) chip. With A14 high it looks to the next available 16K, with A15 high the next 16K and with A14 and A15 high the final 16K.

So what we can do here is combine four 16K ROM images into a single 64K file and flash it to our 27512 which is just what I did with my Signstek TL866A Universal USB programmer.

Now by connecting A14 and A15 to the IC76 address line C and D outputs we have effectively given whatever socket we connect this two the ability to appear as four ROMs (this works only because a single ROM can be paged in at a time).

The final icing on the cake is that the Beeb sports a push-out section left of the keyboard (affectionately known as the “ash tray”) where a zero insertion force - ZIF socket - could be mounted to allow a ROM to be dropped in without needing to crack open the case (our school was definitely not wanting us to open the machines and yet only one machine had this upgrade installed).

Now I just need to figure out how to mount this ZIF socket in the ash tray hole - there aren’t really any mounts. I suspect I’m going to need to make a PCB of some sort and put legs on it.

Building your own

Parts list

  • 28-pin ZIF socket
  • 28-pin DIP socket 0.6” wide
  • length of 28-way ribbon cable
  • 2.54mm header pins (you just need two)
  • 2x female-to-female jumper wires

Creating the cable

  1. Wire all pins from ZIF to DIP except for 1 & 27
  2. Solder two header pins to 11 & 12 on IC76
  3. Jumper ZIF pin 1 to 11 on IC76
  4. Jumper ZIF pin 27 to 12 on IC76

Now insert a 27512 ROM flashed with four BBC ROMs of your choice, power up and type *HELP or *ROMS to see the images ready.

Also check out alternatives for wiring up 64K ROMs or 32K SRAM chips from J.G. Harston

Second processor via a Pi Zero

The Beeb has a bunch of expansion ports hidden underneath the machine - the most unusual one being the Tube expansion bus which allows for a 2nd processor by way of a FIFO buffers that facilitated message passing IPC for console, errors, data and system calls.

Acorn produced a number of expansions for Tube including:

  • 6502 second processor allowing well-behaved unmodified programs to run faster
  • Z80 for CP/M
  • 80286 for DOS or GEM

Raspberry Pi Zero with Level ShifterThese expansions are hard to come by as they don’t just feature the CPU but necessary additional isolation logic, memory and circuitry. David Banks developed PiTubeDirect to allow a Raspberry Pi to act as second processor plugged into the Tube port by way of a 5V to 3.3V level shifter - I got mine from Kjell Sundby

The Raspberry Pi 3 can emulate these old processors as crazy speeds - 274MHz for the 6502, 112MHz for the Z80, 63MHz for the 80286 and even a 59MHz ARM2 (Acorn were using the Beeb to work on ARM prototypes)

What piqued my interest was using the Raspberry Pi Zero though. It’s small enough to fit under the BBC Micro and remain plugged into the Tube port out of sight. Latency was a problem on the Zero given the lower ARM processor so they ported the CPU emulation core… to the GPU!

The 6502 emulation is reliable and enabled me to run the 6502 Second Processor Elite. I definitely need to try and get GEM running on it just for fun although it’s a little trickier to find suitable disk images for Z80 and 80286 co-processor stuff.