ROM software

There's actually two bits of software written specifically for this board - a test ROM for 48K machines, which shows the test status on the LEDs, and a flash utility so that you can program the flash chip from a Spectrum (a working one, obviously!) The flash utility is simple and is designed for 4 megabit (512K) flash chips, allowing you to program and run ROM code from any one of 32 16K pages.

The Spectrum-Diag-Rom zip file contains assembly source for the 48K test ROM, as well as 'testrom.out', which can be sent to a flash programmer, and '48ktestrom.tzx' which can be played to a Spectrum with a utility like PlayTZX, and then written to the flash chip with the flash utility. Documentation on the test routine is here in the How it Works section. Documentation on the flash utility is on this page.


If you use that last download, three of the TZX files are rom images, and the file FlashUtil.tzx is a program ready to run. If you load FlashUtil.tzx first, then you can load one of the other TZX files and RANDOMIZE USR 57344 to program it into the flash chip. The ROM images load at address 32768. It's recommended that you first CLEAR 32767, then load FlashUtil.tzx, then load FlashUtilRom.tzx, program page 4 of the flash chip, so you have the flash util in ROM in case anything goes wrong - it'll save you the time of having to load flashutil.tzx and flashutilrom.tzx if something causes a crash. Complete details follow.

How to use the flash utility

The flash utility is so that you don't need a flash burner to write to the flash chip - you can do it from a (fully functional!) Spectrum. It has been tested with 48K machines and the toastrack 128K machine, and can be started on that machine with either 48K or 128K BASIC. The information below assumes you're starting with an unused Am29F040B flash chip (or equivalent).

Initializing the flash chip

You'll need either a tape containing an audio version of flashutil.tzx, flashutilrom.tzx (from the file) and 48ktestrom.tzx (from the file), or you'll need to hook up a PC to your Spectrum with a set of audio leads, and use PlayTZX to send those three files to the Spectrum.

Before you plug the board into the Spectrum you want to use to program, set the Spectrum/Flash jumper to SPECTRUM (pins 2 to 3). This means the Spectrum will start with its own ROM. Plug the board into the machine, and power it up. You should see the familiar (c) message (or menu on 128K machines). If instead you see vertical stripes up the screen - the jumper is on the wrong pins. Power the machine down and move the jumper. (The vertical lines are caused by the Spectrum executing RST #38 instructions - 0xFF - in an infinte loop, and the stack overwriting screen memory. Unused or freshly erased flash memory has the value 0xFF).

Next, enter CLEAR 32767 to confine BASIC to lower memory so that what you load next won't get overwritten. Then type LOAD "" CODE. Play the flashutil.tzx file. Then type LOAD "" CODE again, and play the flashutilrom.tzx file. The first loads at address 57344 (hex 0xE000), and the second at address 32768 (hex 0x8000). Assuming you don't witness the terror of R: Tape loading error, next type RANDOMIZE USR 57344

You should now see the following:

Flash utility menu

Now press W. A new menu will appear, with a listing of 16K pages. The flash utility is designed to live in page 4, so press 4.

Now the flash utility is in ROM...

The last step put the flash utility in page 4, so it's always there whenever you want to change the contents of ROM pages. Start the flash utility from ZX BASIC by typing:

OUT 31,36

This works from either 48K or 128K BASIC. Note that it copies the flash utility to RAM at address 57344 (and will overwrite anything that's sitting there). The flash utility will not work with the Spectrum/Flash jumper set to Flash. This is because this inverts the ROMCS bit (to determine which ROM - the Spectrum's ROM, or page 0 of the flash chip) - so when the flash utility tries to use the Spectrum ROM's keyboard scanning routine, it falls over. (It would also fall over when trying to page in a new ROM page, so putting in a 'native' keyscan routine won't help). This is important to note in case you feel like invoking the flash utility if you have something like the Gosh Wonderful ZX BASIC ROM in page 0, and have set the jumper to Flash so the Spectrum initializes from this instead of its own ROM.

It probably looks very odd that the flash utility is invoked with OUT 31,36 - rather than RANDOMIZE USR. But there's a method to my madness. Port 31 for output selects the ROM page. 36 is binary 00100100 (or hex 24). So bit 5 is set (which is connected to the ROMCS transistor, so ROMCS is nailed high, paging out the Spectrum's ROM), and flash page 4 is selected. This happens immediately the moment the Z80 places address 31 on the lower half of the address bus, and 36 on the data bus. So the next instruction it executes will not be the Spectrum ROM's RET instruction to return from the BASIC interpreter's OUT routine, but whatever is in that address in page 4 of the flash ROM. The address in question is 0x1E7F. At this point in page 4, there is a routine that copies the flash utility to RAM, and then jumps to it. Before you ask, port 31 doesn't conflict with a Kempston joystick - the Kempston interface only responds to an IN 31 instruction. The diags board only responds to an OUT 31 instruction. Therefore, if you have a Kempston interface (that conforms to the Kempston spec and pays attention to the /RD line) that has a through connector, you can load the interface 2 Jetpac cartridge into a flash page and enjoy it with your joystick! Incidentally, if you program a flash page with the Jetpac IF2 ROM, it can be invoked with an OUT 31 command from BASIC - and it runs properly. I wonder if Ultimate put valid code in at 0x1E7F just for this very eventuality ... It's probably easier to start ROM games with the flash utility though, so you don't need to work out the proper OUT command!

Load the test ROM

Next, LOAD "" CODE again, and play the 48ktestrom.tzx file. Invoke the flash utility with OUT 31,36, and choose W to write a page. Choose page 0. This will write the contents of RAM at address 32768 (which now contain the 48K test ROM) to page 0.

Adding new ROMs to the flash chip

You can now put any ROM image you like in any of the pages. This can be alternative BASIC ROMs, or Interface 2 game ROMs, or other testing ROMs such as the Spectrum 128K memory tester. You need to load them at address 32768. Once a new ROM is loaded, all you need to do to invoke it is to OUT 31,36 - then just press the key corresponding to the page that it is in. As it stands, the flash utility is extremely simple, and doesn't record what you put where, so just keep a note of it. Next I'll list some common tasks you may want to do.

Erasing sectors

Flash doesn't work like RAM - you can't just arbitrarily change values in memory. It's more like EPROM - you have to erase it before you can change it. For example, if you want to change the ROM image in page 0, so you can boot with a different tester, you will need to erase sector 0 first. Note that on a 512K chip, each sector is 64K in size, and so covers four 16K pages. This means you'll lose anything in page 1, 2 and 3 as well. (There are solutions - more on that later).

To erase a sector, choose item X. Then select the sector you wish to delete. The menu looks like this, and reminds you which pages are affected by the sector erase:

Erase sector menu

Enter the corresponding key, and the erase operation will start. If you erase sector 1, you'll be asked if you want to keep the flash utility, since this lives in page 4 (which is about to get blown away). If you choose Y here, it will copy the contents of page 4 to RAM (at address 32768), erase sector 1, then reprogram page 4 with the flash utility. You will normally want to press Y, unless you're replacing the flash utility with a new version.

If you need to save the contents of one or more pages in the sector that you want to erase, you need to have some free pages in the flash chip. You can copy the contents of the page to RAM at address 32768, and use the normal programming menu to program a new page with the contents. Do this for as many pages as you need to copy.

Programming a page with a useable ROM

The 'w' option on the main menu will write a 16K page. It writes whatever is in RAM at address 32768 and 16K long into the selected flash page. You just need to turn whatever it is you want to write into a TZX file, which you then play to the Spectrum, loading at address 32768. I have done this with various Interface 2 ROMs as well as a 128K tester.

Quick and dirty method for turning ROMs into TZX files

      device zxspectrum48
      org 32767
      incbin "name-of-rom.bin"
      savesna "createrandomrom.sna", 32767
My quick and dirty hack is to use sjasmplus to create a snapshot file, which I then load into an emulator. I then use the emulator to create the TZX file (see the sidebar for the short file I give to sjasmplus). To create the TZX file, start the emulator with the resulting snapshot, and SAVE "filename" CODE 32768,16384 - note, you can also at this stage play it directly to a Spectrum if your emulator sends sound to your soundcard when you do this. Otherwise, you'll just have to use your emulator's tape traps to create a TZX which you can play with a utility like PlayTZX.

Changing the test ROM (page 0)

The ROM that gets booted if the jumper is set to 'Flash' is whatever is in page 0. You may want to change this at some point, either to update the test ROM designed for this board, or to use some other test ROM image. My own method is to keep various test ROMs in other pages - I keep the 48K tester in page 8, and a 128K tester in page 9. When I want to change the ROM in page 0, I use the following procedure:

Compiling the code

To build the flash utility from source:

sjasmplus flashutil.asm
sjasmplus flashutilrom.asm

The first invocation builds the utility - the output file runs from address 57344. The second builds a snapshot file that can be turned into a TZX using an emulator. It also includes the ROM bootstrap code so that the utility can be invoked with OUT 31,36. From your emulator, save two files - SAVE "flashutilrom" CODE 32768,16384 and SAVE "flashutil" CODE 57344,3511 (although the last value will change if you've modified it).

To build the 48K Test ROM from source:

sjasmplus testrom.asm

You can use the snapshot hack from earlier to convert this to a TZX file to program from a Spectrum.

Notes on the code itself

Note that I don't have a Windows machine, only Unixy type systems at home (Linux and Mac OS X) - so the format of the text files is Unix. If you're a Windows user and want to edit the code, you'll want a text editor that does Unix line endings as well as the DOS line endings that Windows uses. Or use a utility to convert it. Any half decent programmers editor should do this for you without you noticing (certainly Vim does it, presumably Emacs on Windows does it. But Notepad certainly does not!)

I'm not the world's greatest Z80 assembly language programmer by a very long shot. Improvements welcomed! Note that all the memory testing code must be able to run without needing RAM at all - so no stack, no saving stuff off in RAM, no CALL instructions. All the code was written by me except for the pseudo random number generator, CRC checker and hex to ascii converter in the testing ROM code - which were merely modified by me to work with this project. You can find the original code for those routines from this website. I'd like to thank the author Milos "baze" Bazelides for putting that site up - it was very helpful.

The flash utility is entirely my own dubious creation.

All code written by me is available under the terms of the GNU LGPL so feel free to copy/tinker/put on your own website. (As is all the hardware schematics and PCB layouts. Don't be shy).