(Using the Brilliant Circle Framework)
This project emulates the Jupiter II, Ricardo Fernandes Lopes' Jupiter Ace compatible computer, with its Expansion board (16 colours, a sound chip, 128K of paged RAM, extra Forth words and a serial port). It runs baremetal (no operating system) on the Raspberry Pi models 4 / 400 (default), 3, 2 and 1, built with the Circle C++ library. It can also be a plain Jupiter II or the original Jupiter Ace (Ctrl+F12).
Please visit the Jupiter ACE Archive to obtain software for this emulator and give your contribution if you find it useful.
Ready to use Zip files with the binaries are provided, so you can directly download them to your PI's formatted sdcard. See the SD Card Preparation paragraph below.
All in src/:
| File | Purpose |
|---|---|
z80.c, z80ops.c, cbops.c, edops.c, z80.h |
Z80 CPU core by Ian Collier (xz80), with changes by Russell Marks and Edward Patel (GPL, see Licence). The *ops.c files are included by z80.c, not compiled separately. |
tape.h |
Declarations of the tape traps called by the Z80 core (Lawrence Woodman, GPL) |
main.cpp, kernel.cpp, kernel.h |
Circle kernel: devices (keyboard, USB joystick, serial port), frame timing, screen rendering (colour with the Expansion), F3 / F5 / F6 / F7 / F8 / F10 / F11 / Ctrl+F12 screens |
machine.cpp, machine.h |
The machine emulated (Ctrl+F12): Jupiter II with or without the Expansion, or Jupiter Ace. Frame timing, the 3000h RAM, screen / character set / memory pages, the sound chip's registers and ports, colour attributes, the Expansion's state for snapshots |
xrom.h |
The Jupiter II Expansion ROM (Forth word extensions, start-up screen) as a C array, from the Expansion's repository (MIT licence) |
ay8910.cpp, ay8910.h |
AY-3-8910 sound generators: tones, noise, envelope |
uart_16c450.cpp, uart_16c450.h |
The Expansion's 16C450 UART (serial port) |
keyboard_circle.cpp, keyboard_circle.h |
USB keyboard and joystick to Jupiter Ace keyboard matrix |
keyboard_layouts.cpp, keyboard_layouts.h |
Keyboard layouts for F8 (UK, US, German, French, …) |
ram_ace.cpp, ram_ace.h |
RAM pack size (Ctrl+F12, Jupiter Ace and plain Jupiter II), and the 96K pack's two pages (switched by the Z80 core on LD R,A) |
spool_ace.cpp, spool_ace.h |
Spooling Forth source files (.fth, .fs, .f) into the machine (F5) |
save_dictionary.cpp, save_dictionary.h |
Saving the dictionary as a Forth source file (F7) |
line_history.cpp, line_history.h |
Line history: TAB / Shift+TAB retype earlier lines, Ctrl+TAB lists them |
sound_ace.cpp, sound_ace.h |
Sound output: the beeper and the sound chip, in stereo |
web_files.cpp, web_files.h |
File exchange web page (F11): cable or Wi-Fi network, web server, the page itself |
wifi_settings.cpp, wifi_settings.h |
The Wi-Fi network to join (F11), kept in wpa_supplicant.conf on the SD card |
update_sd.cpp, update_sd.h |
System update from the web page (F11, /system): checking a release .zip, installing it, trying a new kernel once with the Pi 4's tryboot; the kernel's version marker |
version.h |
The version number, built into the kernel and used by build.sh for the zips and releases |
zip_sd.cpp, zip_sd.h |
Reading .zip files on the SD card (F5 opens them like folders) |
puff.c, puff.h |
Unpacking deflate data (.zip files): puff 2.3 by Mark Adler, from zlib's contrib/puff (zlib 1.3.1), zlib licence, unchanged |
tape_sd.cpp, tape_sd.h |
Tape LOAD / SAVE with .tap and .tzx files on the SD card; loading and saving (F7) .ace snapshots; the programs folder and its subfolders (paths, listing, making, moving and deleting folders). tape_sd.cpp is based on GPL code by Edward Patel and Lawrence Woodman and is GPL. |
ace_rom.h |
The 8 KB Jupiter Ace ROM (ace.rom in the project root) as a C array |
config.txt |
Raspberry Pi boot configuration |
Makefile |
Build rules (uses Circle's Rules.mk) |
Ctrl+F12 chooses the machine, and restarts it:
| Machine | What it is |
|---|---|
| Jupiter II + Expansion (default) | The Jupiter II with its Expansion board: colour, sound chip, 128K paged RAM, serial port, the Expansion ROM's Forth words |
| Jupiter II | The bare Jupiter II, optionally with a Jupiter Ace RAM pack (16K, 32K, 48K or 96K) on its expansion connector |
| Jupiter Ace | The original Jupiter Ace, optionally with a RAM pack |
The Jupiter II runs the Jupiter Ace ROM and its software. Its differences from the Ace, all emulated (from its PLD equations and schematic):
- 60 Hz video (NTSC): 262 lines of 208 t-states, 54,496 t-states per frame, 59.64 Hz at 3.25 MHz (the Ace: 312 lines, 50.08 Hz). The picture is in lines 0-191, the first 128 t-states of each; the interrupt (vsync) is held for 4 lines, 224-227.
- 2K of program RAM at
0x3000 – 0x37FF, seen again at0x3800 – 0x3FFF(the Ace: 1K seen four times). The Ace's system variables at0x3C00are in its second half. - 2K of screen RAM and 2K of character set RAM, in two 1K pages each, chosen by the Expansion board (without it, page 1).
- A 16K boot ROM: the Ace ROM, and a copy patched at
0x008E(JP 0xC000) that starts the Expansion ROM. With the Expansion the patched one is used, without it the original. - The inverse video jumper (black on white): Ctrl+F4.
At power-on the Expansion ROM shows its
start-up screen (on screen page 0, in colour, with a chime) and waits for a key. Then Forth
starts on screen page 1 with the Ace's own character set, and RAMTOP is set to 0x8000, so
Forth stays in RAM that is never paged.
Colour. 16 colours, IRGB (bit 3 intensity): BLACK 0, BLUE 9, RED 12, PURPLE 13,
GREEN 10, CYAN 11, YELLOW 14, WHITE 15, GREY 8; DARK clears the intensity bit
(BLUE DARK is 1). Each character cell has an INK and a PAPER colour, set from the current
INK / PAPER whenever a character is written to the screen; the border has its own
colour. The colours are on the sound chip's port A (PAPER, INK) and port B (BORDER).
CYAN BORDER WHITE PAPER BLUE DARK INK CLS
: COLORBAR CLS 10 8 AT 16 0 DO I INK 144 EMIT LOOP BLACK INK ;
COLORBAR
Memory. 128K of RAM and the 16K Expansion ROM:
| Address | Contents |
|---|---|
0x0000 – 0x1FFF |
ROM (Jupiter Ace ROM, patched to start the Expansion ROM) |
0x2000 – 0x27FF |
Screen RAM: the page shown (0 or 1), mirrored twice |
0x2800 – 0x2FFF |
Character set RAM: the page in use (0 or 1), mirrored twice |
0x3000 – 0x3FFF |
2K RAM, mirrored twice; the Expansion's Forth words are copied to 0x3000 – 0x33FF |
0x4000 – 0x7FFF |
16K RAM, never paged |
0x8000 – 0xFFFF |
Memory page 0, 1 or 2: 32K RAM; page 3: 16K RAM and the Expansion ROM at 0xC000 |
A reset selects memory page 3, screen page 1 and character set 1. n MPAGE,
n SCREEN and n FONT change them:
2 MPAGE 1234 49152 ! 3 MPAGE ( the ROM is back at 0xC000 )
2 MPAGE 49152 @ . ( 1234 )
Changing the screen page also moves the ROM's input line, which is kept in the screen RAM:
switch pages inside a word (: SHOW 0 SCREEN ... 1 SCREEN ;) rather than typing 0 SCREEN
at the prompt.
Sound. An AY-3-8910 at 3.25 MHz: three tone channels, noise and envelopes. PSG!
( value register -- ) writes a register and PSG@ ( register -- value ) reads one; a tone
of period t has a frequency of 203125 / t Hz. Channel A plays on the left, B on the
right, C and the beeper on both.
: PING 200 0 PSG! 254 7 PSG! 16 8 PSG! 20 12 PSG! 1 13 PSG! ;
Serial port. A 16C450 UART, 8 data bits, 1 stop bit, no parity, 9600 baud after a reset.
n BAUD changes the speed (300 to 19200); addr n TX sends n bytes, addr n RX receives
them (Space stops both). Bytes take as long as at the chosen speed. On the Raspberry Pi
4 / 400 it can be connected to the Pi's UART on GPIO 4 (TXD, header pin 7) and
GPIO 5 (RXD, header pin 29), 3.3 V levels (use a 3.3 V USB-serial adapter or level
shifter): add jupiterserial=1 to cmdline.txt on the SD card (all options on one line,
separated by spaces, e.g. sounddev=sndhdmi jupiterserial=1). Without it, and on the other
models (their only UART is the debug log's), the serial port is not connected: bytes sent
are lost and none arrive.
Other words of the Expansion ROM: COUNT, +!, ?, CMOVE, FILL, DEPTH, HEX.
| Port (odd) | Expansion device |
|---|---|
0xFD (1111xx01b) |
Sound chip: select a register |
0xFF (1111xx11b) |
Sound chip: read / write the register (14: port A, 15: port B) |
0xE1 – 0xEF (1110rrr1b) |
UART registers 0 – 7 |
Port B: bits 7-4 BORDER colour, bit 3 character set page, bit 2 screen page, bits 1-0
memory page. Port A: bits 7-4 PAPER, bits 3-0 INK. While the sound chip's ports are inputs
(after a reset) they read 0xFF.
The original machine, as before: 50 Hz, 1K of program RAM, 1K of screen and character set RAM, and a RAM pack (see Memory below).
-
Target Hardware: Raspberry Pi 4 Model B or Raspberry Pi 400 (Broadcom BCM2711, Cortex-A72), 32-bit mode. Both run the same kernel, and it has been tested on both.
-
Display: 640×480 @ 60 Hz HDMI framebuffer.
- The machine's resolution (256×192) scaled 2× to 512×384, centred.
- Without the Expansion: white characters on a black screen and border, like the real Ace. With it: each character cell in its INK and PAPER colours, and the border colour.
- Only changed 8×8 character cells are redrawn, including cells whose character was
redefined in the character set RAM (
0x2C00) or whose colours changed.
-
Input: Standard USB keyboard plugged into any USB port, or the Pi 400's built-in keyboard (which is connected over USB inside the case).
- Uses Circle's USB host controller driver (
CUSBHCIDevice, xHCI on the Pi 4 / 400) andCUSBKeyboardDevicein raw mode. - US layout by default ("Original ACE"): symbols are typed as on the PC keyboard and translated to the Ace Symbol Shift combinations (see below). F8 selects another layout (see Keyboard layouts).
- The keyboard can be unplugged and plugged in again while running.
- A USB joystick or gamepad (
CUSBGamePadDevice) presses the Ace keys assigned to its directions and buttons with F3 (see USB joystick).
- Uses Circle's USB host controller driver (
-
CPU Timing:
-
Z80 at 3.25 MHz: 54,496 t-states per frame (262 lines × 208 t-states, 59.64 Hz) on the Jupiter II, 64,896 (312 lines, 50.08 Hz) on the Jupiter Ace.
-
Instruction timings match the Zilog figures (all unprefixed and
CBinstructions, the documentedEDones and the mainDD/FDones are checked).HALTwaits for the next interrupt, as on the real Z80: the ROM'sVLISTuses it to print one word per frame (144 frames for the ROM's own words, as on EightyOne and the MiSTer Ace core). -
Video waits as on the real machines: the copies of the screen (
0x2400) and character set (0x2C00) that the ROM uses give the video circuit priority, so a CPU access while the picture is drawn waits until the end of that line's picture. The copies at0x2000and0x2800give the CPU priority. The picture is the first 128 t-states of lines 0-191. On the Ace the timing is the MiSTer Ace core's: the interrupt (vsync) at t-state 154 of line 248 of 312. Forth text output is a little slower for it, tight loops writing to the screen up to about 30%. -
The interrupt is the vsync signal: held for 8 lines (1,664 t-states) on the Ace, as in the MiSTer core, and for 4 lines (832 t-states) on the Jupiter II; it can only be taken then. A program that keeps interrupts disabled through it misses that frame's interrupt; a handler that re-enables them while it is still held is entered again (the ROM's handler is longer, so the machine gets one interrupt per frame).
-
The Ace timing was checked against the MiSTer Ace core with Forth loops that count how many times they run in 50 or 500 frames. After a fresh boot, both give the same counts:
0 variable a : tst a ! 0 15403 @ 50 + begin swap 1+ swap a @ c@ drop dup 15403 @ - 0< until drop . ; : t2 0 15403 @ 50 + begin swap 1+ swap dup 15403 @ - 0< until drop . ; : t3 0 15403 @ 500 + begin swap 1+ swap dup 15403 @ - 0< until drop . ;Test SLOW (after boot) FAST 9216 tst(reads the screen at0x2400)392 722 16384 tst(reads RAM at0x4000)400 724 t2539 931 t3(500 frames)5299 9153 The emulator still treats each memory access as happening at the end of its instruction, rather than at its own t-state as on the real Z80. Only machine code that times screen accesses to the exact t-state could show a difference.
-
Paced with the ARM microsecond timer (
CTimer). If the emulator falls more than a frame behind (SD card access, USB enumeration) it resynchronises instead of racing. -
Screen, keyboard and sound are serviced every frame, even while the Z80 has interrupts disabled. The frame interrupt (
RST 38h) is taken when they are enabled.
-
-
Sound: The beeper (IN from port
0xFE= speaker low, OUT = speaker high) and, with the Expansion, the AY-3-8910's register writes are timestamped in t-states, rendered at 48 kHz stereo and played on the headphone jack (default) or HDMI. The Pi 400 has no headphone jack, so it needs HDMI sound. -
Tape:
LOAD/BLOAD/SAVE/BSAVEuse.tapor.tzxfiles on the SD card (see below). -
ROM: The Jupiter Ace ROM is compiled into the kernel (
ace_rom.h), and the Jupiter II Expansion ROM too (xrom.h), so the machine starts without reading any file. The ROM's tape block read (0x18A7) and write (0x1820) routines are patched at boot with emulator traps that do the same with tape files; the rest ofLOAD,SAVE,VERIFY(headers, names, checks) is the ROM's own. -
Memory (Jupiter Ace and plain Jupiter II; for the Expansion see above): the built-in RAM (3 KB on the Ace, 6 KB on the Jupiter II) plus a RAM pack, 48 KB by default. Ctrl+F12 chooses the typical sizes of the time instead:
RAM pack Ace RAM Jupiter II RAM RAMTOP none (a stock machine) 3K 6K 0x400016K 19K 22K 0x800032K 35K 38K 0xC00048K 51K 54K 0x0000(top of memory)96K (two 48K pages) 99K 102K 0x0000(top of memory)Missing RAM ignores writes and reads
0xFF, so the ROM's RAM test at power-on finds the chosen size, as on the real machine. RAM is filled with0xFFat power-on and on F12 reset.The 96K RAM pack is Edwin Blink's design (jupiter-ace.co.uk): two 48K pages, both at
0x4000 – 0xFFFF; the machine's own RAM is never paged. It starts on page 0 and then works as a 48K pack (the ROM finds 51K). Bit 7 of the Z80's R register selects the page: the pack latches it in every refresh cycle, and onlyLD R,Achanges it, soLD A,128 : LD R,Agives page 1 andXOR A : LD R,Apage 0. As on the pack, the new page takes over at the refresh after the next opcode fetch (that opcode still comes from the old page) or at an interrupt acknowledge, so code that switches pages should run below0x4000. A reset (R = 0) goes back to page 0. With the other sizesLD R,Adoes nothing to the memory.Address Size Contents 0x0000 – 0x1FFF8 KB ROM 0x2000 – 0x27FF1 KB Video RAM (32×24 characters), mirrored twice 0x2800 – 0x2FFF1 KB Character set RAM (128 characters × 8 bytes), mirrored twice 0x3000 – 0x3FFF1 KB (Ace) / 2 KB (Jupiter II) Built-in program RAM, mirrored four times (Ace) / twice (Jupiter II) 0x4000 – 0xFFFFup to 48 KB RAM pack (16K: to 0x7FFF, 32K: to0xBFFF; 96K: one of its two pages)
| Standard USB Keyboard | Jupiter Ace Action |
|---|---|
| A – Z | A – Z (Shift gives the other case) |
| 0 – 9, keypad digits | 0 – 9 |
Symbols (# - _ = + [ ] { } ; : ' " , . < > / ? \ | ~) |
The same symbol (Symbol Shift + its key) |
| Shift + 1 / 2 / 4 / 9 / 0 | Delete Line / Caps Lock / Inverse Video / Graphics / Delete, as on the Ace (Original ACE keymap; the F8 layouts type their symbols) |
| Shift + 5 / 6 / 7 / 8 | Move the cursor left / up / down / right, as on the Ace (Original ACE keymap; the F8 layouts type their symbols) |
! @ $ % & ( ) ^ * |
Ctrl + 1 / 2 / 4 / 5 / 6 / 8 / 9 / H / B, as on the Ace (Original ACE keymap, where Shift + digits are the Ace's editing keys); keypad * |
Keypad / * - + . |
The same symbol |
| Enter / keypad Enter | ENTER |
| Space | SPACE |
| Tab / Shift + Tab | Retype an earlier line / a newer one (see Line history) |
| Ctrl + Tab | List the remembered lines and choose one to retype (pauses the Ace) |
| Backspace / Delete | Delete (Shift + 0) |
| Escape | Break (Shift + Space) |
| Left / Right / Up / Down | Move the cursor too, in every keymap (Shift + 5 / 8 / 6 / 7: in the ROM Shift + 6 moves up a row, Shift + 7 down) |
| Caps Lock | Caps Lock (Shift + 2) |
| Ctrl / Alt + key | Ace Symbol Shift + that key position (reaches every legend, e.g. © and £) |
| F1 | Delete Line (Shift + 1) |
| F2 | Caps Lock (Shift + 2) |
| F3 | Assign Ace keys to the USB joystick's directions and buttons (pauses the Ace; see USB joystick) |
| F4 | Inverse Video on / off (Shift + 4) |
| Ctrl + F4 | Swap the screen colours: black on white / white on black (the Jupiter II's inverse video jumper; with the Expansion, INK and PAPER swap) |
| F5 | Browse the programs folder of the SD card: its folders, tapes (.tap, .tzx), snapshots (.ace) and Forth sources (.fth, .fs, .f), and the tape in the player; Enter opens a folder (Backspace goes up), inserts a tape, loads a snapshot or spools a source, E ejects the tape, N makes a new tape, M a new folder (pauses the Ace) |
| F6 | Delete a tape, a snapshot, a Forth source, or a folder with everything in it: choose it in the list, Enter (D for a folder), then Y (pauses the Ace) |
| F7 | Save the dictionary as a Forth source file (.fth, .fs, .f), or the whole Ace as an .ace snapshot: choose which, then type the name (see Saving the dictionary and Snapshots; pauses the Ace) |
| F8 | Choose the keyboard layout (pauses the Ace; see Keyboard layouts) |
| F9 | Graphics Mode (Shift + 9) |
| F10, power key (Fn + F10 on the Pi 400) | Power off the Raspberry Pi (pauses the Ace, then Y/N) |
| F11 | File exchange: join the cable or Wi-Fi network and serve a web page for copying files to and from the SD card (pauses the Ace; see File exchange) |
| F12 | Hard Reset |
| Ctrl + F12 | Choose the machine: Jupiter II + Expansion, Jupiter II or Jupiter Ace, the last two with a RAM pack (see The machines); this restarts it |
The Ace has two shift keys. On the PC keyboard:
| Jupiter Ace | PC / Pi 400 keyboard |
|---|---|
| SHIFT | Shift (left or right) |
| SYMBOL SHIFT | Ctrl (left or right) or Alt; in the layouts with AltGr (German, French, Italian, Spanish, Portuguese, Norwegian, Swedish, Danish) only Left Alt, as Right Alt is AltGr there |
- Ctrl / Alt + key is the Ace's Symbol Shift + the key in the same position, so every
legend on the Ace keyboard can be reached:
Ctrl + X=£,Ctrl + I=©,Ctrl + A=~,Ctrl + B=*,Ctrl + 5=%. - Symbols can also be typed as on a PC (Shift + the key with the symbol): they are translated to the Ace's Symbol Shift combination.
- Shift + digits: on the Ace they are editing keys, and so they are in the Original
ACE keymap: Shift + 1 Delete Line, Shift + 2 Caps Lock, Shift + 4 Inverse
Video, Shift + 5 / 6 / 7 / 8 move the cursor (the ROM moves up a row on Shift + 6 and
down on Shift + 7), Shift + 9 Graphics and Shift + 0 Delete. Shift + 3 has no
function in the ROM, so it types
#. The symbols on the digits (! @ $ % & ( )) are typed the Ace way, with Ctrl (or the keypad*). The F8 layouts type the PC symbols there; the editing functions are also on separate keys in every keymap: Delete Line F1, Caps Lock F2 (or Caps Lock), Inverse Video F4, Graphics F9, Delete Backspace, and the arrow keys.
These function keys are shortcuts for Jupiter Ace key combinations, so you don't need to remember the Shift + digit legends:
- F1 – Delete Line (
Shift + 1): clears the line being typed. - F2 – Caps Lock (
Shift + 2): toggles capitals, like the PC's Caps Lock key. - F4 – Inverse Video (
Shift + 4): switches inverse video on, and pressed again off: characters typed while it is on are stored with their top bit set and show inverted (black on white), e.g. to highlight a word inside." HELLO". - F9 – Graphics (
Shift + 9): toggles graphics mode for typing the Ace's block graphics characters.
F4 only affects the characters typed next; text already on the screen does not change.
Ctrl + F4 is different: it is not an Ace key. It swaps the colours of the whole display (screen and border) between white on black, like the real Ace, and black on white, as the Jupiter II's inverse video jumper does. Inverse video characters swap too, so they still stand out. With the Expansion it swaps each cell's INK and PAPER (the border keeps its colour). Press Ctrl + F4 again to go back.
The last 100 lines entered (with Enter, at the Forth prompt or wherever a program asks for input) are remembered. TAB puts the last one back on the input line, in place of what is being typed; each further TAB goes one line further back, stopping at the oldest. Shift + TAB goes back to newer lines, and past the newest to an empty line. Any other key ends the browsing, so the next TAB starts again from the last line. The line is only retyped, not entered: edit it if you like and press Enter.
Ctrl + TAB shows all the remembered lines, newest first, one per row (a line longer than
the screen ends with >; the selected one scrolls to show the rest, as long names do in
F5). Move with Up / Down (Page Up / Page Down, Home / End;
held down, they repeat) and press Enter to put the chosen line back on the input line;
Esc closes the list. TAB and Shift + TAB then go on from the chosen line.
- A line is not remembered twice in a row; empty lines and spooled lines are not remembered. The history lasts until the Pi is switched off (F12 keeps it).
- Inverse video characters and
£/©are retyped as they were; graphics characters are left out.
This was not part of the original Ace, it was done because I'm a lazy typer. If you dislike it just don't use it :-)
Press F8 to choose the layout of your keyboard, e.g. the national layout of a
Raspberry Pi 400. Use Up / Down (held down, they repeat) and Enter (Esc keeps the
current one; * marks it). The choice lasts until the Pi is switched off.
| Layout | Notes |
|---|---|
| Original ACE (default) | The mapping in the table above: a US keyboard, with Right Alt as Symbol Shift |
| UK, US, Japanese | Right Alt is Symbol Shift, like Ctrl / Left Alt. Japanese is JIS: ¥ types \ |
| German, French, Italian, Spanish, Portuguese, Norwegian, Swedish, Danish | Right Alt is AltGr, for the symbols printed on the keys' third position (e.g. AltGr + 2 = @ in Portuguese) |
With a layout chosen, each key types the character printed on it. Letters follow the layout
too (QWERTZ in German, AZERTY in French). For example in Portuguese, Shift + 3 types #,
AltGr + 3 types £, the + key types + and the ~ key types ~.
- Characters the Ace does not have type nothing: accented letters (é, ç, ñ, ü, ø, å, …),
€,§,¤,°,«»,¡¿and the backtick. Accent keys (dead keys) type the accent itself when the Ace has it (^,~). - Every Ace symbol can be reached in every layout; where a layout has no key for one
(e.g.
~in Italian,©everywhere), use Ctrl / Left Alt + the key labelled with the Ace letter:Ctrl + A=~,Ctrl + I=©,Ctrl + X=£(see the Ace keyboard legends). - The tape name typed after F5 N (new tape) follows the layout too.
The Jupiter Ace had no joystick port: its games read the keyboard. A USB joystick or gamepad plugged into the Raspberry Pi presses Ace keys instead, as if they were typed, so it works with any game: each direction and each button presses the Ace key assigned to it.
By default the directions are the Ace's cursor keys (Shift + 6 / 7 / 5 / 8: in the ROM
Shift + 6 moves up and Shift + 7 down) and the buttons press nothing. To assign a key:
- Press F3 (the Ace pauses). The screen lists the directions and the buttons that have a key, and says whether a joystick is connected.
- Move the joystick or press one of its buttons: it is highlighted.
- Press the key on the keyboard, typed as for the Ace: e.g.
Q,Space,Enter,Shift + 6, orCtrl + Pfor Symbol Shift + P. Backspace removes the key, Esc leaves it unchanged. - Repeat for the other controls; Esc goes back to the Ace.
- Two controls can press the same key, and a direction and a button pressed together press
both their keys (with
Shiftin one of them, the other is shifted too, as on the Ace). - Directions come from the D-pad, the hat switch or the left stick. Buttons are numbered, or named (A, B, X, Y, LB, Start, ...) on gamepads Circle knows.
- The keys are not remembered after power off.
- Generic USB HID joysticks and gamepads work, as well as PS3, PS4, Xbox 360, Xbox One, Switch Pro and 8BitDo controllers (Circle's drivers). The first one plugged in is used, and it can be plugged in or out while running.
- The joystick and the keyboard can be used together; while a Forth source is spooled the joystick is ignored.
The Ace's files (tapes .tap / .tzx, snapshots .ace and Forth sources .fth / .fs /
.f) are kept in the programs folder of the SD card, in any folders you like inside
it (for example: programs/games/arcade/invaders.tap). The root of the card is left to the boot files.
programs is made at start-up if it is missing, and any Ace files in the root of the card
(copied there from a computer), and .zip files, are moved into it then; a file whose name is already taken in programs stays in the root.
Tapes are standard Jupiter Ace .tap files, or .tzx files.
Press F5 to see the folder you are in: its folders first (shown with a / after the
name), then its tapes, snapshots and Forth sources, with their sizes, each sorted by name.
The title bar shows the folder's path. Move with Up / Down (Page Up / Page Down,
Home / End for long lists; held down, Up / Down / Page Up / Page Down repeat) and close
with Esc.
- Enter (or Right) on a folder opens it; Backspace (or Left), or Enter on
.., goes back up. - M makes a new folder here: type its name and press Enter.
- Long names (more than 24 characters, 23 for folders and
.zipfiles) are cut in the list. The selected one scrolls: after a second it moves one character at a time to its end, waits a second there and starts again. Space moves it one character by hand (held down, it repeats; after the end it goes back to the start), and it then stays where Space left it until another entry is selected. The same goes for F6 and for the lines of Ctrl + TAB. - Long folder paths in the title bar (F5 and F6) show their end,
...first. They scroll the same way, towards the start of the path, and back to the end; Space does not move them. So does the folder line of F7, while you type the name. .zipfiles are listed with the folders (collection.zip/, with their size) and open like them: Enter shows the tapes, snapshots and Forth sources in the.zip, with the folders it has, and they are inserted, loaded or spooled as usual. A.zipinside the.zipopens the same way (collections often keep each program in its own.zip): it is unpacked into memory, so it can be at most 4 MB. A.zipis read only: no new tapes (N) or folders (M) in it, and files in it cannot be deleted (F6 deletes the whole.zip). Each file is unpacked into memory when it is used, so it can be at most 4 MB unpacked. Files stored as they are or compressed with deflate (what nearly every zip tool does) can be read; other methods (bzip2, LZMA, ...), encrypted files and ZIP64 archives cannot.- The folder you leave F5 in is remembered (until the Pi is switched off): new files go
into it —
SAVEwith no tape in the player, new tapes (N) and F7's dictionaries and snapshots. If it is in a.zip, they go into the folder the.zipis in.
The bottom line of the screen shows the tape in the player (Tape: none when it is empty).
-
Enter on a
.tapor.tzxinserts it: the tape goes into the player, rewound (>marks it in the list), and the Ace comes back.LOAD/BLOAD/VERIFYread from it, a plainloadlists its files, andSAVE/BSAVEadd files to it. It stays in until another tape is inserted, it is ejected, or it is deleted with F6; F12 and Ctrl+F12 rewind it. -
E ejects the tape.
-
N makes a new, blank tape in the folder shown: type its name ending in
.tapor.tzx(.tapis added if it ends in neither), press Enter, and the empty tape is created and inserted, ready forSAVE. An existing file is never overwritten. -
.tzxtapes:LOAD/BLOADread them, andSAVE/BSAVEadd to one in the player as standard speed data blocks (0x10), with a one second pause after each. The Ace's blocks can be in standard (0x10), turbo (0x11), pure data (0x14) or generalized data (0x19, one bit per symbol) TZX blocks; text, archive information, pauses and other blocks are skipped. Direct recordings (0x15) and CSW blocks (0x18), which hold sampled sound from a real cassette rather than bytes, are not read. -
LOAD name/BLOAD nameread only the tape in the player (inserted with F5), like a cassette: they search it from where it is (after the last file loaded, so multi-file tapes load in sequence) to its end, then from its start. The files passed on the way are shown (Dict: name/Bytes: name), as on a real Ace. If the file is not on the tape they giveERROR 10. -
LOAD/BLOADwithout a name list the files on the tape in the player, from its start, and load nothing (ending withERROR 10, as no file matches). -
With no tape in the player,
LOAD,BLOAD,VERIFYandBVERIFY, with or without a name, giveERROR 10at once. -
SAVE name/BSAVE nameadd the file at the end of the tape in the player (.tapor.tzx), like recording on a cassette. With no tape in the player, they writename.tapin the folder last open in F5, replacing any existing file of that name; characters that are not valid in file names become_. A tape from a.zipcannot be added to: with one in the player,SAVEwritesname.tapas with no tape (next to the.zip), and the tape from the.zipstays in. -
VERIFY name/BVERIFY namecompare the file on the tape with memory, without changing memory:OKif they match,ERROR 10if they differ (or the file is not on the tape). -
Blocks are read as the Ace's ROM reads them from a cassette: the next block on the tape, which must be a header or a data block as asked (
.tzxfiles keep the Ace's flag byte for this; in a.tapa block is a header if it has the header's size and does not follow a header), with exactly the length asked for and the right checksum. As on a real Ace, a damaged header is skipped and damaged data givesERROR 10. Programs that read their own blocks through the ROM's tape routine (0x18A7), such as multi-part games, get the next blocks of the tape; at its end the routine fails, and holding Space gives BREAK (ERROR 3), as on the Ace.
.ace files are memory snapshots, the format of the Ace32, EightyOne and
SpudACE emulators. Select one in the F5 list and press Enter, then Y: the Ace's
memory and CPU registers are replaced by the snapshot's, and the program carries on where
the snapshot was taken (anything not saved to tape is lost). On the Jupiter Ace and the plain
Jupiter II, if the snapshot's machine had more RAM than the current size (see Ctrl+F12), the
RAM pack is enlarged to match it first; snapshots of 51K machines hold all the memory, up to
0xFFFF. With the Expansion, a snapshot of another machine that needs RAM above 0xC000
selects memory page 0 (all RAM) first.
Many snapshots of 35K machines only hold the memory up to 0x7FFF; when they were taken at
the Forth prompt, the missing return stack is rebuilt, so they work as well. A file that
is not a valid snapshot is
rejected without changing anything.
To save a snapshot, press F7, choose Snapshot (.ace) and type a name (.ace is added
if it has no extension; other extensions are refused, and an existing file is never
overwritten). It goes into the folder last open in F5, shown on the screen. It holds the Ace exactly as it was when F7 was pressed: all the RAM there is
(up to the end of the RAM pack), with the screen, the character set and the Z80
registers, so a game or program can be saved in the middle and loaded later with F5 to
carry on from there. Unlike saving the dictionary, it works at any time, not only at the
Forth prompt (but not while a file is being spooled). The format is the one above, so
other emulators can load the file; MAME only loads snapshots of machines up to 19K
(memory up to 0x7FFF).
With the 96K RAM pack the snapshot is still one .ace file: the page in use is saved as
usual, and the other page follows the snapshot's end marker, with which page was in use
(the block starts with ACE-96K). Loading it chooses the 96K pack (and the Jupiter Ace,
if the Expansion was in use) and restores both pages. Other emulators stop reading at the end marker (EightyOne does), so they load it
as a 51K snapshot of the page in use. A snapshot without that block loaded with the 96K
pack goes into the page that bit 7 of its R register selects; the other page is kept.
With the Jupiter II Expansion the snapshot holds the memory as the Z80 sees it (the screen
and character set pages shown, the memory page in use, up to 0xFFFF), and the rest of the
Expansion follows the end marker in a block that starts with JUPITR2: the sound chip's
registers (and so the colours and pages chosen), the screen and character set pages not
shown, the colour attributes of both screen pages and all four memory pages. Loading it
chooses the Jupiter II with the Expansion and restores all of it. Other emulators load such
a file as a 51K Ace snapshot of the memory shown.
A Forth source file (.fth, .fs or .f, plain text) on the SD card can be typed into the Ace as if from
the keyboard: select it in the F5 list and press Enter.
- The text goes through the Ace's own editor, line by line: each line is entered and run (or compiled) before the next one is typed. Definitions can span several lines.
- While spooling, the machine runs as fast as the Pi can, without its frame pacing, and the keyboard is ignored except Esc, which stops spooling.
- Spooling stops at the end of the file and at the first line the Ace does not accept: it is
left in the editor with
?, to be corrected. After anERROR n(which only loses the rest of its line) spooling goes on. - Line ends can be LF, CR LF or CR; tabs become spaces.
£and©(UTF-8 or Latin-1) are typed as the Ace's own characters; other characters the Ace does not have (accented letters, ...) are skipped. Caps Lock, graphics and inverse mode are switched off first. - The file must be written for Ace Forth.
( ... )comments outside definitions are left out (the Ace would answer them withERROR 4), as are the lines left empty. Comments inside definitions are typed: the Ace keeps them in the word, soLISTandEDITshow them. Text in." ..."strings and the character afterASCIIare never taken for comments.
F7, Dictionary (Forth source), writes every word you have defined (or loaded) to a Forth source file on the SD card,
the reverse of spooling: spooling the file into a fresh Ace (F5) defines the same words
again. Type the name, ending in .fth, .fs or .f (.fth is added if it has no
extension; other extensions are refused); an existing file is never overwritten. It goes
into the folder last open in F5, shown on the screen. The Ace must be at the Forth prompt with nothing typed on the input line.
- Colon,
DEFINERandCOMPILERwords are written as the Ace's ownLISTshows them. - Variables and constants are written with their current values (
99 variable SCORE). - Other words (made with
CREATE, by a defining word, or holding machine code) are written ascreate NAMEwith their bytes, followed by their code field when needed. - Hidden words (a program can hide its words by clearing a link) are saved too, and hidden again at the end of the file.
- Words are saved oldest first. A word that uses a newer one (after
REDEFINE) is moved after it, so the file can be spooled; the dictionary is then laid out differently, but the words work the same. - Saving runs at spooling speed; Esc stops it (the file is then deleted). A screen at the end says how many words were saved. The Ace is left exactly as it was.
Words in vocabularies other than FORTH, and addresses stored in variables or data (e.g. a
variable holding the address of a word), are saved as they are and may not work after
spooling into a different dictionary.
Press F6 to delete a tape, a snapshot, a Forth source file or a folder: the same list as F5 appears, starting in the folder last open in F5. Move with Up / Down (Page Up / Page Down, Home / End; held down, they repeat as in F5); Enter (or Right) opens a folder and Backspace (or Left) goes up, as in F5.
- Enter on a file, or D (or Delete) on a file or folder, asks to delete it; Y confirms (N or Esc keeps it).
- Deleting a folder deletes everything in it, files and subfolders: the question says how many files and folders that is.
- A
.zipopens like a folder (Enter); D deletes the whole.zip. Nothing inside a.zipcan be deleted.
The list stays open for more deletions; Esc closes it, leaving F5's folder as it was.
Only the programs folder is shown, so the boot files are safe. Deleting the tape in the
player (or its folder) ejects it.
Folder and file names typed on the Ace (F5 N and M, F7) are plain names: no / \ : * ? " < > |,
and not starting with . or a space.
Note: File names are not case sensitive on the SD card, but Ace names inside a tape are:
LOAD game will not find a file saved as GAME.
Press F11 to copy files between a computer, tablet or phone and the SD card, without taking the card out. The first time, choose how the Pi joins your network:
- 1 Cable network (Ethernet): the Pi 4 / 400's Ethernet port, or a USB Ethernet adapter on the other models.
- 2 Wi-Fi: the on-board Wi-Fi of the Pi 3, 4, 400, Zero W and Zero 2 W. Type the
network name, the password (none for an open network) and your country's two-letter
code (
PT,GB,US, ...: Wi-Fi channels differ by country, and the Wi-Fi will not join without it). Up / Down move between them; Enter on the country connects. They are kept on the SD card inwpa_supplicant.conf, so next time they are already filled in, with the cursor on the country: just press Enter. WPA2 and WPA (personal) and open networks work; WPA3-only networks do not. The Wi-Fi firmware files must be in the card'sfirmwarefolder (build.shputs them insdcard/firmware).
The choice stays until the Pi is switched off. The address comes from your router (DHCP)
and the screen shows the page's address, e.g. http://192.168.1.23, and also
http://jupiter.local where the browser can find it by name. Open it in a web browser on
the same network:
- The page shows the
programsfolder (see The programs folder): the path at the top (click a part to go back to it), then the folders, then the.tap,.tzx,.ace,.fth,.fs,.fand.zipfiles, and the tape in the player. On the page a.zipis a file like the others (uploaded, downloaded, renamed, moved and deleted whole); its contents are seen in F5. Click a folder to open it; the browser's Back button works too. - Upload into the folder shown: drop files on the page or choose them, several at once; or drop a whole folder, or choose one with A folder: it is copied with all its subfolders, keeping their structure (only the Ace's file types are copied; the others are listed as left out). Large uploads are sent in parts of up to 30 MB. A file with the same name as one on the card is kept unless Replace files with the same name is ticked.
- Download: click a name for one file, or tick several files and folders and use
Download selected for a
.zipwith all of them, folders with everything in them (up to 8 MB and 1024 files at once). - New folder makes one in the folder shown.
- Rename a file or a folder; Move selected moves the ticked files and folders to
another folder (type its path in
programs, e.g.games/arcade, or nothing forprogramsitself). - Delete a file, or a folder with everything in it (files and subfolders), after confirming; or the ticked ones.
- Renaming or moving the tape in the player (or its folder) keeps it in the player; deleting it ejects it; replacing it rewinds it.
- Nothing outside
programscan be reached, so the boot files are safe.
The Ace is paused while the F11 screen is open, and the page only answers then: the network is not run while the Ace runs, so its timing is not disturbed. The screen lists what has been done on the page. Esc goes back to the Ace. The network stays connected until the Pi is switched off, so F11 again is ready at once (a Wi-Fi network may have dropped the Pi meanwhile: it joins again by itself). Only plain ASCII file names are handled. The page has no password: use it on a home network only.
On Wi-Fi, C changes the network settings. If the Pi has not joined after 30 seconds
the screen says so: correct the settings with C and it tries again with them. Once the Pi
has an address, new settings are only used after switching it off and on (Circle does not
ask the router for a new address). wpa_supplicant.conf can also be written by hand
(see Circle's sample); the
password is kept in it as typed, unless it has " or # (then as the key made from it).
The web page of F11 has a System update page (link at the bottom, or /system). It
shows the version running, and installs a new release of Jupiter-IIb from its .zip
(Jupiter-IIb-<version>-pi<model>.zip, the one for your Raspberry Pi):
- Choose the
.zipon the page. The Ace checks it: it must hold the kernel for this model with the version marker of a Jupiter-IIb kernel. Only the files that differ from those on the card are to change: the kernel, the boot firmware (start*.elf,fixup*.dat,bootcode.bin,*.dtb), the Wi-Fi firmware and the licences.config.txt,cmdline.txt,wpa_supplicant.confand theprogramsfolder are never touched. The page lists what will change. - The F11 screen on the Ace asks to install it: Y installs, N discards it. Nothing changes on the card before Y, so nobody on the network can install a version without someone at the Ace.
- Pi 4 / 400: the Pi restarts to try the new version once, with the boot firmware's
tryboot (
tryboot.txt, a copy ofconfig.txtnaming the new kernel and boot firmware, is used for that one start only). When the new version has run for a few seconds it puts all the new files in place and says so; the replaced files are kept inupdate-backupon the card. If it does not start, switch the Pi off and on: the old version starts, removes the new files and says that the update did not start. Tryboot needs a Pi 4 bootloader (EEPROM) from 2021 or later; with an older one the update is reported as not started (update the bootloader with Raspberry Pi OS'srpi-eeprom-update). - Pi 1, 2, 3, Zero: they cannot try a version first. The files are put in place at
once, and the screen asks to switch the Pi off and on. If it then does not start, copy
the files in
update-backupback to the root of the card on a computer.
While a new version is tried, the Wi-Fi firmware and .dtb files of the old one are used;
they are replaced with the rest once it has started.
Press F10 (or the keyboard's power key, Fn + F10 on the Pi 400) and then Y to power off: the SD card is unmounted and the Pi halts (N or Esc returns to the Ace). Anything not saved to tape is lost. To start again, unplug and replug the power.
The beeper and, with the Expansion, the AY-3-8910 sound chip play in stereo on the 3.5 mm
headphone jack by default: the chip's channel A on the left, B on the right, C and the
beeper on both. To use HDMI audio instead
(always on the Pi 400, which has no headphone jack), create cmdline.txt on the SD card containing:
sounddev=sndhdmi
All commands are run from the project root (the folder containing src/, circle/
and sdcard/). The project folder can have any name and be anywhere.
The program is developed with Slackware x86_64 Version 15.0, but you should be able to build it with other distros, otherwise just use the provided binaries.
git clone <this repository's URL> Jupiter-IIbEverything needed is in the repository, including Circle (in circle/), so the source
archives of a release build as well.
./download_toolchain.shThis downloads the Arm GNU Toolchain 14.2 (arm-none-eabi) into toolchain/. Circle's
Config.mk uses it automatically, and falls back to an arm-none-eabi-gcc on the PATH
if toolchain/ is missing.
./build.sh [model]model |
Raspberry Pi | Kernel image |
|---|---|---|
4 or 400 (default) |
Pi 4, Pi 400 | kernel7l.img |
3 |
Pi 3, Zero 2 W | kernel8-32.img |
2 |
Pi 2 | kernel7.img |
1 |
Pi 1, Zero, Zero W | kernel.img |
The Pi 4 and Pi 400 have been tested on hardware; the other models build but are untested. The Pi 5 is not supported yet: it needs a 64-bit build, and F10 power off uses registers the Pi 5 does not have.
Note: Since I don't own a Pi5 (or 500) so I didn't develop for it. If many of you ask I could grab one and update the program...
build.sh can be run from any folder. It first empties dist/, then for the model (or
each model with --all):
- copies
circle-config/Config.mktocircle/Config.mkif it is missing; - if the model differs from the previous build, cleans Circle and
src/first, because they are built for one model at a time (the last model is kept in.build-model); - builds the Circle libraries (only what changed, so later runs are quick);
- builds the kernel image, and stops if it is too big to boot (Circle gives the kernel, with its variables, 2 MB of memory; past that the Pi stays on the rainbow screen);
- empties
sdcard/and fills it with the model's boot firmware fromfirmware/pi<model>, its Wi-Fi firmware fromfirmware/wlan(intosdcard/firmware), the kernel image andconfig.txt(which tells each model which kernel image to load). Anything else you put insdcard/is deleted, so keep tapes, snapshots andcmdline.txtelsewhere. - zips the files of
sdcard/intodist/Jupiter-IIb-<version>-pi<model>.zip(the version fromsrc/version.h): the release zip of the model, which the system update page (F11) installs.
Circle is included in circle/: a copy of Circle Step51.1.1, the tested version (the exact
commit is in circle/README.Jupiter-IIb). Its configuration for the Raspberry Pi in 32-bit mode with
the project toolchain is kept in circle-config/Config.mk, because Circle's .gitignore
ignores Config.mk. Don't run
Circle's ./configure: it would replace Config.mk and lose the toolchain selection.
The same steps by hand (for another model, export RASPPI=<model> first and run
./makeall clean and make clean in each folder when switching):
cp circle-config/Config.mk circle/
cd circle
./makeall # Circle core, USB, input, file system, scheduler, sound
make -C addon/SDCard # SD card driver (tape)
make -C addon/fatfs # FAT file system (tape)
make -C addon/wlan # Wi-Fi driver (F11)
make -C addon/wlan/hostap/wpa_supplicant -f Makefile.circle # WPA supplicant (F11)
cd ../src
make # builds the kernel image (kernel7l.img for the Pi 4)
make sdcard # copies it and config.txt to ../sdcard/This paragraphsis mostly for the me, as I need a simple way to publish things along in GitHub as they get developed and tested.
./build.sh --all # builds every model, with each one's zip in dist/
./build.sh --all --publish # also creates the GitHub release v<version> with the zips--all builds the models one after the other, the Pi 4 last (so sdcard/ is left with
it), and dist/ ends with all four zips: dist/Jupiter-IIb-<version>-pi1.zip to
-pi4.zip (pi4 is also for the Pi 400). The version is JUPITER_VERSION in
src/version.h: change it there for a new release. With --publish it creates the
release v<version> on the current commit (which must be committed and pushed, and the
release must not exist yet), with the zips and the <version> section of CHANGELOG.md as
release notes; GitHub adds the source code zip and tar.gz.
-
Format a micro-SD card with a single FAT32 partition (MBR partition table).
-
Run
./build.sh [model](see Build). It fillssdcard/with everything the card needs for that model. The boot firmware comes fromfirmware/, which has one folder per model, taken from the Raspberry Pi firmware repository at the version Circle'sboot/Makefileuses (0641c5b):Folder Models Files firmware/pi1Pi 1 A / B / A+ / B+, CM1, Zero, Zero W bootcode.bin,start.elf,fixup.dat,bcm2708-*.dtbfirmware/pi2Pi 2 (including v1.2), CM2 bootcode.bin,start.elf,fixup.dat,bcm2709-*.dtb,bcm2710-rpi-2-b.dtbfirmware/pi3Pi 3 B / B+ / A+, CM3, Zero 2 W, CM0 bootcode.bin,start.elf,fixup.dat,bcm2710-*.dtbfirmware/pi4Pi 4, Pi 400, CM4, CM4S start4.elf,fixup4.dat,bcm2711-*.dtbEach folder also has the firmware licences,
LICENCE.broadcomandCOPYING.linux.The Wi-Fi firmware (F11) is in
firmware/wlan, from the Raspberry Pi firmware-nonfree repository at the version Circle'saddon/wlan/firmware/Makefileuses (c9d3ae6), with its licences inLICENCE.wlan.build.shcopies the files of the model's Wi-Fi chips tosdcard/firmware:brcmfmac43430-*(Pi 3 B, Zero W),brcmfmac43436-*(Zero 2 W),brcmfmac43455-*(Pi 3 B+ / A+, Pi 4, CM4),brcmfmac43456-*(Pi 400). The Pi 2 has no Wi-Fi. -
Copy the contents of the project's
sdcard/folder to the root of the card. For the Pi 4 / 400 that is:start4.elf,fixup4.dat,bcm2711-*.dtb: boot firmware (the firmware loads the.dtbfor the model it runs on)bcm2711-rpi-400.dtb: only used on a Raspberry Pi 400, which runs the same kernel. The Pi 400 has no headphone jack, so select HDMI sound (see Sound).config.txtkernel7l.imgfirmware/: the Wi-Fi firmware (F11),brcmfmac43455-*for the Pi 4 andbrcmfmac43456-*for the Pi 400
-
Optionally add
cmdline.txt(see Sound), and your.tap,.tzx,.aceand.fth/.fs/.ffiles, and.zipfiles of them, in a folder calledprograms, in any folders you like inside it (files put in the root of the card are moved intoprogramsat start-up).
- Insert the micro-SD card into your Raspberry Pi 4 or Pi 400.
- Connect an HDMI monitor to HDMI0: on the Pi 4 the port closest to the USB-C power port, on the Pi 400 the port next to the micro-SD slot.
- Plug in a standard USB keyboard (the Pi 400 uses its own keyboard).
- Optionally connect headphones or a speaker to the 3.5 mm jack (Pi 4 only; on the Pi 400 sound goes over HDMI, see Sound).
- Power on the Pi.
- After a few seconds the Jupiter II Expansion's start-up screen appears, in colour, with a chime. Press a key: the screen clears to the Forth prompt, with the cursor at the bottom left. (As a plain Jupiter II or Jupiter Ace, chosen with Ctrl+F12, the screen is black with the cursor at the bottom left at once, as on a real Ace.)
- Start typing Forth words, e.g.
2 3 + .and Enter, orCYAN BORDER.
Circle writes a log (USB keyboard attached, SD card mounted, tape LOAD / SAVE, sound device, machine resets, the Expansion's serial port settings) to the serial port at 115200 baud, 8N1, on GPIO 14 (TXD, pin 8) and GPIO 15 (RXD, pin 10). Connect a 3.3 V USB-serial adapter to read it. (The Jupiter II Expansion's serial port is a different UART, on GPIO 4 / 5 of the Pi 4 / 400: see Jupiter II Expansion.)
Jupiter-IIb is free software under the GNU General Public License, version 3 (see
LICENSE). Some parts come from other projects and keep their own licences, all of them
compatible with it:
| Part | Authors | Licence |
|---|---|---|
Z80 core: z80.c, z80ops.c, cbops.c, edops.c, z80.h |
Ian Collier (xz80), Russell Marks, Edward Patel | GPL v2 or later |
tape.h, tape_sd.cpp (based on their tape code) |
Lawrence Woodman, Edward Patel | GPL v2 or later |
puff.c, puff.h |
Mark Adler | zlib |
xrom.h (Jupiter II Expansion ROM) |
Ricardo Fernandes Lopes | MIT |
Jupiter Ace ROM (ace.rom, ace_rom.h) |
Jupiter Cantab (Richard Altwasser, Steven Vickers) | not covered by the GPL; distributed as other Ace emulators do |
forth.txt (Crash course in Forth) |
Edward Patel | not covered by the GPL |
Circle (circle/) |
Rene Stange and contributors | GPL v3 |
The kernel image (kernel*.img) is distributed under the GNU GPL version 3: its complete
source is this repository.
The Jupiter II and its Expansion board were designed by Ricardo Fernandes Lopes (Jupiter-II, Jupiter-II-Expansion, MIT licence); this emulator follows their schematics, PLD equations and ROM source.