Programming in C on the ZX Spectrum
Back in the 1980’s, if you were writing code for the ZX Spectrum, you could use the built-in basic interpreter or Z80 machine code for better performance.
Now there are other options, including higher level languages such as C. z88dk is a great project that allows you to compile C for the ZX Spectrum and ZX Spectrum Next. It also includes some libraries to make doing common things easier.
There’s a great getting started guide here and I’ve included my quick notes taken from that guide below.
ZX Spectrum C Development
First, make sure that z88dk has been downloaded and compiled. Also double-check that your PATH and ZCCCFG environment variables are set correctly. If you want to do this on a Raspberry Pi, check my other post here.
There are two c libraries in z88dk. These are referred to as the classic c library and the new c library. The classic C library allows generation for 80+ different Z80 machines. The new C library is z88dk’s rewrite. It’s support includes the ZX Spectrum, ZX Spectrum Next, RC2014, Sega Master System amongst others.
There are two c compilers in z88dk – SCCZ80 and ZSDCC. The choice of compiler to be used is driven by which library is used.
Example 1 – Border Colour
This example uses the sdcc_iy library which uses the newer compiler. First , here’s the example code: –
#include <arch/zx.h>
int main()
{
zx_border(INK_RED);
return 0;
}
You can compile this code by using the following command: –
zcc +zx -vn -clib=sdcc_iy -startup=31 red_border.c -o red_border -create-app
+zx sets the target as the Spectrum, -vn reduces the verboseness, -clib sets the library, -startup=31 sets the C runtime to be a very basic one, and -create-app creates a TAP file.
Once you’ve run this you should end up with two files – “red_border_CODE.bin” and “red_border.tap”. You should be able to run the TAP file in an emulator such as Fuse.
The machine code is stored in the BIN file and you can disassemble this to have a look by using the following command: –
z88dk-dis -o 0x8000 red_border_CODE.bin > disassembly.txt
This command uses 0x8000 as the address to load the code into (32768 in decimal), which is what is used by z88dk for the Spectrum by default.
Looking at the machine code you can see what is going on – the code for red is being loaded at address 0x80d2 before code is being called at 0x8068.
ld l,$02 ;[80d2] 2e 02 $02 = Red
call $8068 ;[80d4] cd 68 80 Call code at $8068
The code at 0x8068 runs, with the border colour being updated at 0x8075.
ld a,l ;[8068] 7d This is what gets called
and $07 ;[8069] e6 07
ld l,a ;[806b] 6f
ld a,($80de) ;[806c] 3a de 80
and $f8 ;[806f] e6 f8
or l ;[8071] b5
ld ($80de),a ;[8072] 32 de 80
out ($fe),a ;[8075] d3 fe out(254),a changes the border
ret ;[8077] c9w
Example 2 – Hello World
Here’s a (slightly!) more exciting example, using stdio to output text to the screen.
#include <arch/zx.h>
#include <stdio.h>
int main()
{
zx_cls(PAPER_WHITE);
puts("Hello, world!");
return 0;
}
This can be compiler using C runtime 0 (-startup=0) which sets up the screen in 32×24 mode and enables the stdio channels.
zcc +zx -vn -startup=0 -clib=sdcc_iy hello_world.c -o hello_world -create-app
There are many more advanced things that can be done with other libraries, and as linked at the top of this post, the starter guide here is excellent.