Showing posts with label ZX Spectrum. Show all posts
Showing posts with label ZX Spectrum. Show all posts

Friday, 6 May 2022

A Tale Of Two Banners: ZX

For the 40th Anniversary of the ZX Spectrum's announcement on April 23rd, 1982, I decided to write a little banner program.

Here's an example of what it can do:

May be a cartoon

ZX Spectrum BASIC is blessed with a large number of useful commands to access graphics, so the program was quite easy to write and relatively short:

No photo description available.

No photo description available.

As you can see, there's very little to this program. How does it work?

The main part of the program, obviously is the mechanism for enlarging the characters. This is surprisingly easy. The ZX Spectrum has 16 graphics characters arranged as Battenberg (as in the cake) graphics which occupy character codes 128 to 143.


The ZX Spectrum also has a POINT(x,y) function, which returns the pixel value at coordinates (x,y). By POINT ing at (x,y), (x+1,y), (x, y+1), (x+1, y+1) we can simply multiply each point by the appropriate Battenberg pixel value and add 128 to generate the correct graphics character. This is why you can see a tiny version of the '!' character in the bottom right-hand corner: the standard character is displayed and then it is scanned and the appropriate Battenberg characters are generated.

The program allows for the banner to be edited by simply supporting a carriage return feature and by wrapping the bottom line back to the top line.

The harder part is to generate the stripy coloured lines at the bottom right-hand corner. The difficulty with the ZX Spectrum is that it's not possible for more than 2 different colours (an INK colour and a PAPER colour) to occupy the same character square. So, to make the stripes we have to carefully make sure that each stripe is exactly 1 character wide and map the colours so that the stripe never clashes.

To do this we define a graphic character, UDG "a", whose address in RAM is returned by USR "a" as a diagonal triangle filling the bottom half of the character. This gives us the diagonal stripes by using the previous ink colour as the next paper colour on the next stripe - a classic ZX Spectrum colour trick! (You can see how it works from the image below where alternate diagonal rows are brighter ).

No photo description available.

To make the program a little bit more fun, each character is assigned a random colour and the cursor flashes.  Because the ZX Spectrum came out in a 16kB form, and one of my friends had one at the time, I thought it would be considerate to make sure the program would run on either model (it's so short, I could hardly fail 😉 !).

You can type in the program by going to the ZX Spectrum Javascript website! Here's the keyboard to help you! https://jsspeccy.zxdemo.org .

Following this I thought I'd do the same, for the Commodore VIC-20. It turns out that, despite arguably superior graphics capabilities (well, it can do 2 bits per pixel graphics!), it's far harder (see Part 2).


Tuesday, 10 December 2013

Z80 Dhrystones

In the early 80s, my schoolmate David Allery's dad's workplace had a pdp-11/34, a minicomputer designed in the 1970s. All the reports at the time implied that a pdp-11 anything had absolutely awesome performance compared with the humble 8-bit computers of our day.

Yet decades later, when you look at the actual performance of a pdp-11/34, it seems pretty bad in theory. You can download the pdp-11 handbook from 1979 which covers it.

First, a brief introduction to computer processors, the CPU, which executes the commands that make up programs. I'll assume you understand something of early 80s BASIC. CPUs execute code by reading in a series of numbers from memory, each of which it looks up and translates into switching operations which perform relatively simple instructions. These instructions are at the level of regn=PEEK(addr), POKE(addr,regn), GOTO/GOSUB addr, RETURN; regn = regn+/-/*/divide/and/or/xor/shift regm; compare regn,regm/number. And not much else.

The pdp-11 was a family of uniform 16-bit computers with 8x16-bit registers, 16-bit instructions and a 16-bit (64Kb) address space (though the 11/34 had built-in bank switching to extend it to 18-bits). The "/number" refers to the particular model.

On the pdp-11/34, an add rn,rm took 2µs; add rn,literalNumber took 3.33µs and an add rn,PEEK(addr) took 5.8µs. Branches took 2.2µs and Subroutines+Return took 3.3µs+3.3µs.
That's not too different to the Z80 in a ZX Spectrum, which can perform a (16-bit) add in 3µs; load literal then add in 6µs, load address then add in 7.7µs; Branch in 3.4µs and subroutine/return in 4.3µs+2.8µs.

So, let's check this.

A 'classic' and simple benchmarking test is the Dhrystone test, a simple synthetic benchmark written in 'C'. A VAX 11/780 was defined as having 1 dhrystone MIP and other computers are calculated according to that.

If you do a search, you'll find the pdp-11/34 managed 0.25 dhrystone MIPs. To compare with a ZX Spectrum I used a modern Z80 'C' compiler: SDCC; compiled a modern version of dhrystone (changed only to comply with modern 'C' syntax) and then ran it on a Z80 emulator. I had to modify the function declarations a little to get it to compile as an ANSI 'C' program, but once it did I was able to ascertain that it could run 1000 dhrystones in 13 959 168 TStates.

The result was that if the emulator was running at 3.5MHz, it would execute 0.142dhrystone MIPs, or about 57% of the speed of a pdp-11/34. Of course perhaps a more modern pdp-11 compiler would generate a better result for the pdp-11, but at least these results largely correlate with my sense that the /34 isn't that much faster :-) !

Compiling SDCC Dhrystone

SDCC supports a default 64Kb RAM Z80 target, basically a Z80 attached to some RAM. I could compile Dhrystone 2.0 with this command line:

/Developer/sdcc/bin/sdcc -mz80 --opt-code-speed -DNOSTRUCTASSIGN -DREG=register dhry.c -o dhry.hex

The object file is in an Intel Hex format, so I had to convert it to a binary format first (using an AVR tool):

avr-objcopy -I ihex dhry.hex -O binary

SDCC also provides a z80 ucSim simulator, but unfortunately it's not cycle-accurate (every instruction executes in one 'cycle'). So, I wrote a simulated environment for libz80, which turned out to be quite easy. I used the following command line to run the test:

./rawz80 dhry.bin 0x47d


The command line simply provides the binary file and a breakpoint address. The total number of TStates is listed at the end.

The entire source code is available from the Libby8 Google site (where you can also find out about the FIGnition DIY 8-bit computer).

So Why Did People Feel The Pdp-11 Was So Fast Then?


By rights the pdp-11 shouldn't have been fast at all.
  1. The pdp-11 was typical for the minicomputer generation: the CPU (and everything else) was built from chains of simple, standard TTL logic chips, which weren't very fast.
  2. It was designed for magnetic core memory and that was slow, with a complete read-write cycle taking around 1µs.
  3. It was part of DECs trend towards more sophisticated processors, which took a lot of logic and slowed it down further. 
But (3) is also what made it a winner. It's sophistication meant that it was a joy to program and develop high-quality programming tools for. That's probably a good reason for why both the language 'C' and the Unix OS started out on a pdp-11.

By contrast, although early 8-bit microprocessors were built from custom logic and faster semiconductor memory, the sophistication of the CPUs were limited by the fabrication technology of the day. So, a Z80 had only 7000 transistors and an architecture geared for assembler programming rather than compiled languages.

And there's one other reason. The pdp-11 supported a fairly fast floating-point processor and could execute, for example, a floating point multiply in typically 5.5µs, something a Z80 certainly can't compete with.

Tuesday, 8 May 2012

Should Have Gone To Xspect Savers!

I'm an old-time ZX Spectrum owner from 1982 and since it was the machine's 30th birthday just last week I figured it's mandatory to run an emulator on every Mac of mine, including my cranky, old, 600MHz Xubuntu-running G3 iBook. I had no idea how much effort would be involved!

For lots of more modern systems it's just pretty easy to install FUSE, the Free Unix Spectrum Emulator; but it's not readily available as a package for my iBook, so I had to recompile it, and when I did: for the SDL library and then just for plain X I found it would crash with an 'illegal instruction' message before doing anything.

My overall impression of compiling FUSE though was of the immensity of the work involved, and the size of the code, the download expands to 10.3Mb and then I needed SDL at a whopping 29.8Mb - you can't get much more simple than that eh!?

And of course, in the end it didn't work.

However, I managed to find an alternative: Spectemu-X11, which wonderfully I could download as a package for my machine. Unfortunately, that too didn't quite work - on my iBook I found that I couldn't generate a Symbol Shift since the keyboard didn't support the Right-Shift key-code. So, then I downloaded the source (which when expanded and compiled uses 1.7Mb, almost small!) plus the diff for the 0.94a-9 version; and then had to learn how to apply the diff to a folder: place the diff file in the root directory of the package (in my case just inside my spectemu-0.94 folder) and then type patch -p1 < theNameOfThePatchFile.diff 

And it did it!

Then I compiled SpectEmu, which it duly did and left me with the same problem, no Symbol Shift. So I did some tracking on why that's the case. It's entirely due to the key codes defined in spkey_p.h. The definition for Symbol Shift is derived from SK_Shift_R which is:

#define SK_Shift_R        0xFFE2    /* Right shift */

With a bit of debugging I found out that the command key on my Mac generated 0xFFEB, so all I had to do was replace the above line with:

#define SK_Shift_R        0xFFEB    /* Right shift */

touch all the files that #include spkey_p.h and then make it again. Easy, and now I have a Spectrum Emulator on my lowly (but lovely) iBook!

Next, back to working on my own project, the FIGnition DIY 8-bit computer!