JSZeddy: a ZX81 emulator in JavaScript

Setting up JSZeddy

JSZeddy uses some HTML5 features, so will only work in a modern browser (and on an OS which is around a factor of 1024 faster than the Zeddy). After loading JSZeddy, it is switched off by default, and may be switched on by using the "Start" button, or clicking on the screen. Alternatively, it may be "Reset" or reset by changing the memory size using the "24K" to "56K" button. "24K" indicates that both the the normal 16K RAM and the 8K RAM at address 8192 are present. The "Stop" button may be used to save energy. The "Status" textarea should display that the ROM is loaded (2000 hex bytes); otherwise, the browser perhaps does not support loading binary data from a remote file.

The layout is dependent on the size of the browser's window. Furthermore, if the height is too small, the space and arrow keys may cause the window to scroll.

Colors

The "B/W" button toggles between the following color modes:

Hires

High resolution schemes are supported at 320x240 pixels: WRX, UDG/CHR (with I register at 0x31, or toggle the WRX/UDG button), HRG (load driver first), Memotech (detected with LOAD "/MEMOHRG.ROM"; if 56K is selected it is assumed that the display file is in the upper 32K), G007 (detected with LOAD "/G007HRG.ROM", but not yet supported) and ARX mode is selected when the loaded filename contains "arx".

zxcity

An SP ROM (Johnson and Bolli) hires demo is available via: press the "Start" button; POKE 16389,102; NEW; LOAD "/SPDEMO.BAS"; press N/L to return to normal display.

sp

Lambda

By default, the ZX81 is emulated. However, by pressing the "Lambda", Lambda emulation will be started. Programs may be loaded and saved; compiling and printing are not, and color and sound effects are partly implemented.

ZX80

Furthermore, by pressing "ZX80", ZX80 emulation will be started; loading a file with "Choose File" is supported.

Science of Cambridge

The Science of Cambridge Microcomputer Kit 14 emulation will be started by pressing the corresponding button. Its memory starts at 0xd000. Press "G", "F", "2", "0", "G" (slowly) for a demo (with a *somewhat* adjusted speed constant).

Science of Cambridge

The following example may be run using "Q" to quit, "NEW" for a new program, copy the statements to the BASIC notepad and compile them (see below), "RUN" to run, and then start as above. The first REM lines starting with a colon are considered; the length, address, and data bytes are used to copy the program to the emulator's RAM.

PICO BASIC is available via LOAD "/PICO.BAS".

Reloading JSZeddy

Click the "Initialize" button to initialize all settings to their default values. Alternatively, click the "Reload" icon of the browser or press Ctrl-Shift-R (depending on the browser) to reload JSZeddy and to initialize all settings. For the key combination to work, click somewhere outside the screen so that the screen does not have the focus. The virtual cassette will not be erased. The "Reset" button starts the CPU at address zero with "hardware" settings unchanged.

Telling JSZeddy What To Do

Commands may be given to JSZeddy by the keyboard or by clicking on the image of the keyboard. If the Shift key does not work, the Backtick (`) key may be used. The Backspace (and Del) key works as Rubout, when used in the screen and textareas (otherwise some browsers go back). Programs may be loaded by

Tape Storage

Programs may be LOADed from and SAVEd to a virtual cassette as "localStorage", which is managed by the browser (similar to cookies, but it may occupy more space), and remains on the user's disk when the browser is closed. The space may be freed using the "Erase" button, or using the browser's settings.

By default, any program loaded by using "Choose File" is also saved to the virtual cassette, and displayed in the Hex Notepad.

Some programs which consist of more than one part may be run by using "Choose File" for all parts first, choosing the first part last. Even if there are errors because the individual parts cannot be run, these will be available from the virtual cassette.

TZX Files

Some .TZX files selected by "Choose File" unpack successfully in the Hex Notepad. The contents may next be loaded - in order - using the LOAD "" command. If a filename is present, a next file may be loaded from the Hex Notepad if it is not present on the virtual cassette - this feature can lead to unexpected results.

HEX Files

Files selected by "Choose File" with the .hex extension are converted to bytes and next loaded as a .P file. This can be used to load codes copied from the Hex Notepad.

BIN Files

The bytes in files selected by "Choose File" with the .bin extension are converted to the contents of a REM line with line number 0 (if the emulator is started).

ASM Files

Files selected by "Choose File" with the .asm extension are assembled (if the emulator is started; see below) to lines 1 and 2, which are displayed in the BASIC Notepad, and merged with the current program. If a syntax error in the assembly code is detected, a message is given in the "Status" textarea. The code is shown in the "Printer" textarea. An "ORG" other than 16514 will store the opcodes in the indicated memory area without creating BASIC lines. The assembler is still under construction, and is likely to contain bugs.

BAS Files

Files selected by "Choose File" with the .bas extension are compiled (if the emulator is started; see below) and merged with the current program.

JS Files

Files selected by "Choose File" with the .js extension are run.

OS Files

Files selected by "Choose File" with the .os extension are loaded to address 0 and run ("os" is used instead of "rom" because the latter are used for loading at any address and without (re)starting the emulator). For example, LOAD "/SPONZY.OS" should work (but of course Speccy emulators do exist ;).

BMP Files

Files selected by "Choose File" with the .bmp extension which are monochrome and have the 256x192 geometry may be used to set the background. The default background is an image of the keyboard. Alternatively, the current display may be set to the background by pressing the "Wallpaper" button. When running in FAST mode, the opacity changes such that the background comes to the foreground. The baseline opacity may be set in the "OP" field, which is updated by pressing the "Start" button.

PT3 Files

Files selected by "Choose File" with the .pt3 extension are loaded to 32768; next the PT3 player is loaded and started.

SCR Files

Files selected by "Choose File" with the .scr extension are loaded to 32768; next the Spectrum screen file viewer is loaded and started.

CVR Files

Files selected by "Choose File" with the .cvr extension are loaded as REM lines and next the Guido van Robot interpreter is started (which should be loaded first via the "CVR" button at address 32768, and then with NEW the current program may be deleted). In this version, the robot is also able to build walls.

TXT Files

Files selected by "Choose File" with the .txt (or an unknown extension) are converted to REM lines (if the emulator is started).

ZeddyNet

There is (limited) support for ZeddyNet via emulation of the W5100 chip; a TNFS server may be connected via a UDP proxy (with a white list) which may or may not be available (but a different one may be coded in the JavaScript source). Siggi's NFM (Network File Manager) may be used for this purpose. Configuration (using IPCONFIG) is not necessary.

ZeddyNet

M1NOT

Emulation of the M1NOT circuit - allowing for machine code to be run in memory range 32768-49152 - is on by default. It may be switched off (and on) by pressing the "M1NOT" button.

Assembling Machine Code

An assembly program for the ZX81 may be loaded using the "Assemble" button from the ASM Notepad. This textarea may be enlarged with the mouse, and may be reset to minimal code using the "Clear" button. As an example, copy the following and paste it in the emulator's Notepad (CTRL-A, CTRL-C to copy all and CTRL-A, CTRL-V to paste should work, and next press the "Assemble" button):

Here is another example, Toni Baker's Spirals (in new tab).

Spirals

Machine code is converted to a BASIC REM line containing hex codes, and a line to run the code. These lines are automatically loaded as a ZX81 program. An "ORG" other than 16514 will store the opcodes in the indicated memory area without creating BASIC lines. A listing is shown in the "Printer" textarea. If a syntax error in the assembly code is detected, a message is given in the "Status" textarea, and the line with the error is marked with "--" by the Printer. For the assembler to work, the emulator should be started and displaying the inverse "K" cursor. The code may be run with the ZX81 RUN command. The assembler is still under construction, and is likely to contain bugs.

Thunor's version of Toni Baker's DISASM may be used by: POKE 16389,100, NEW, LOAD "/SIF-DISASM", and RUN. The (merged) code in REM line 1 may then be checked by unassembling from address 4082, or "start", which is 408b in the above example.

Alternatively, REM lines for, for example, ZXAS may be loaded from the BASIC Notepad.

Compiling BASIC Programs in ASCII

A BASIC program for the ZX81 which is available in text format may be loaded using the "Compile" button from the BASIC Notepad. This textarea may be enlarged with the mouse, and may be emptied using the "Clear" button. As an example, copy the following and paste it in the emulator's Notepad:

A line without a line number gets line number zero, and may be run using GOTO 0.

Lines may be split by using the '\' character. Machine code may be entered using REM [HEX:xx,xx ].

For the compilation to work, the emulator should be started and displaying the inverse "K" cursor. Compilation will stop at the end of the program or at a line with a syntax error (for example if a space after a command is missing, or a missing quote character). This line will be entered in ZX81's memory anyway :)

The Arrow Keys

Games use various keys for moving up, left, down, and right. The arrow keys on a pc are attached to the 7, 5, 6, and 8 keys by default, but this may be changed by entering the uppercase letters in the corresponding textarea.

The Printer

Output to the printer from the LPRINT and LLIST commands is converted to ASCII and shown in the "Printer" textarea (which may be enlarged using the mouse). Symbols that cannot be converted to ASCII are given in hexadecimal notation, preceded by a hash ('#'). The output of the printer may be compiled, but machine code in a REM line will currently not be parsed correctly. Output from the COPY command is only text, but by right-clicking on the screen it may be saved as a .PNG file.

Writing Programs

See Sinclair ZX81 BASIC Programming by Steven Vickers, and Mastering Machine Code on Your ZX81 by Toni Baker.

Saving Programs

A browser cannot create arbitrary files on the user's disk; there are the following options:

SLOW & FAST

The SLOW and FAST commands have their usual function, except that in FAST mode the display remains visible but is not updated, but values of the registers of the Z80 will be changing rapidly.

Depending on the capacity of the computer on which the browser is running, SLOW programs may be run at different speeds using the "Slower" and "Faster" buttons.

Sound

The 14 registers used by the BI-PAK ZON X-81 are shown in the "ZonX" textarea, but sound generation is currently under construction. It may be tested by pressing "NoBeep" to enable keypress beeps; see the "AYdemo", and "PT3" files above, or try LOAD "/SDEMO1" (at 56K memory). At present some browers give a portamento effect unfortunately.

How JSZeddy Works

The JavaScript code for the Z80 was adapted from JSSpeccy. The implementation of the interrupts for the generation of the (hires) display was adapted from, and the AYdemo and the image of the keyboard were found at, the SZ81 emulator. Note that programs that run under JSZeddy may not run correctly on a real ZX81.

The pixels are written to a HTML5 canvas. This canvas is updated 10 times per second, instead of 50 times on a television, to save energy, but the frame skip may be set in textarea FS, which is read before starting. The frame function is called every 20ms, and exits at the end of a VSYNC. Note that the 20ms cannot be exact in a browser. If possible, the timer tries to catch up if there is a delay.

If the screen cannot be created properly, the status message "Crashed" may appear. This may also occur when "warm" loading a new program, if the system variables do not match; in that case a "Reload" is needed.

To get some information on the operation of JSZeddy, the Z80 registers are shown. The stack may be shown by pressing the "Stack" button. By using the "Calls" button, the addresses at which any machine code subroutine is called are listed. Normally, this list consists of four addresses for the generation of the display.

As additional information, the ZX81's frame counter is given (FC), the E-LINE as size of the program (EL), and the number of the BASIC line being interpreted (LN, in decimal).

For a faster initialization, the call to SLOW/FAST at 0x0416 is replaced by NOPs. As soon as a line is entered, or after a LOAD, a call to SLOW/FAST is made, and the system may go to SLOW mode. However, at present if the first action is to assemble or compile a program, the ZX81 will go to FAST mode (otherwise it might crash) - this may be confusing.

When writing data to an address in the upper 32K, the memory size is switched automatically to 56K RAM. This avoids mysterious failures when running programs requiring that memory.

The ZON X-81 emulation uses Web Audio with Theresa's Sound World.

The PT3 player and SCR viewers were found at the Sinclair ZX80/ZX81 Forum.

The "CMandel", "CVR", "Rules", "SameGame", "ZXCity", and "ZX0800" demos were made using z88dk; the source of the former was adapted from a Spectrum code snippet. The "SameGame" and "ZX0800" demos are binary/hex versions/implementations of famous games - see the WWW. The (B/W) "25thanni" demo was written by Bodo Wenzel. The "Galaxians" game was enhanced using UDGs by Moggy.

The Science of Cambridge emulator was also made using z88dk and was inspired to a great extent by this one.

The assembler was written as a grammar for PEG.js.

To the Emulator

Go back to the previous tab or to JSZeddy.

Contact