Emulator for the Commander X16 8-bit computer
This is an emulator for the Commander X16 computer system. It only depends on SDL2 and should compile on all modern operating systems.
Binary releases for macOS, Windows and x86_64 Linux are available on the releases page.
The emulator itself is dependent only on SDL2. However, to run the emulated system you will also need a compatible
rom.binROM image. This will be loaded from the directory containing the emulator binary, or you can use the
WARNING: Older versions of the ROM might not work in newer versions of the emulator, and vice versa.
You can build a ROM image yourself using the build instructions in the [x16-rom] repo. The
rom.binincluded in the latest release of the emulator may also work with the HEAD of this repo, but this is not guaranteed.
Install SDL2 using
brew install sdl2.
The SDL2 development package is available as a distribution package with most major versions of Linux: - Red Hat:
yum install SDL2-devel- Debian:
apt-get install libsdl2-dev
maketo build the source. The output will be
x16emuin the current directory. Remember you will also need a
rom.binas described above.
Steps for compiling WebAssembly/HTML5 can be found here.
You can start
x16emu.exeeither by double-clicking it, or from the command line. The latter allows you to specify additional arguments.
x16emuwithout arguments, it will pick up the system ROM (
rom.bin) from the executable's directory.
-romcommand line argument.
-nvramlets you specify a 64 byte file for the system's non-volatile RAM. If it does not exist, it will be created once the NVRAM is modified.
-keymaptells the KERNAL to switch to a specific keyboard layout. Use it without an argument to view the supported layouts.
-sdcardlets you specify an SD card image (partition table + FAT32).
-prglets you specify a
.prgfile that gets injected into RAM after start.
-baslets you specify a BASIC program in ASCII format that automatically typed in (and tokenized).
-runexecutes the application specified through
SYS, depending on the load address.
-geoslaunches GEOS at startup.
-scalescales video output to an integer multiple of 640x480
-echocauses all KERNAL/BASIC output to be printed to the host's terminal. Enable this and use the BASIC command "LIST" to convert a BASIC program to ASCII (detokenize).
-warpcauses the emulator to run as fast as possible, possibly faster than a real X16.
-gif [,wait]to record the screen into a GIF. See below for more info.
-qualitychange image scaling algorithm quality
nearest: nearest pixel sampling
linear: linear filtering
best: (default) anisotropic filtering
-logenables one or more types of logging (e.g.
K: keyboard (key-up and key-down events)
S: speed (CPU load, frame misses)
V: video I/O reads and writes
-debugenables the debugger.
-dumpconfigure system dump (e.g.
C: CPU registers (7 B: A,X,Y,SP,STATUS,PC)
R: RAM (40 KiB)
B: Banked RAM (2 MiB)
V: Video RAM and registers (128 KiB VRAM, 32 B composer registers, 512 B pallete, 16 B layer0 registers, 16 B layer1 registers, 16 B sprite registers, 2 KiB sprite attributes)
-soundcan be used to specify the output sound device.
-abufscan be used to specify the number of audio buffers (defaults to 8). If you're experiencing stuttering in the audio try to increase this number. This will result in additional audio latency though.
-rtccauses the real-time-clock set to the system's time and date.
-tracewill enable an instruction trace on stdout.
x16emu -hto see all command line options.
The X16 uses a PS/2 keyboard, and the ROM currently supports several different layouts. The following table shows their names, and what keys produce different characters than expected:
|Name |Description |Differences| |------|------------------------|-------| |en-us |US |[
] ⇒ [←], [~] ⇒ [π], [\] ⇒ [£]| |en-gb |United Kingdom | ⇒ [←], [~] ⇒ [π]| |de |German |[§] ⇒ [£], [´] ⇒ [^], [^] ⇒ [←], [°] ⇒ [π]| |nordic|Nordic |key left of  ⇒ [←],[π]| |it |Italian |[\] ⇒ [←], [|] ⇒ [π]| |pl |Polish (Programmers) |[`] ⇒ [←], [~] ⇒ [π], [\] ⇒ [£]| |hu |Hungarian |[\] ⇒ [←], [|] ⇒ [π], [§] ⇒ [£]| |es |Spanish |[|] ⇒ π, \ ⇒ [←], Alt + [<] ⇒ [£]| |fr |French |[²] ⇒ [←], [§] ⇒ [£]| |de-ch |Swiss German |[^] ⇒ [←], [°] ⇒ [π]| |fr-be |Belgian French |[²] ⇒ [←], [³] ⇒ [π]| |fi |Finnish |[§] ⇒ [←], [½] ⇒ [π]| |pt-br |Portuguese (Brazil ABNT)|[\] ⇒ [←], [|] ⇒ [π]|
Keys that produce international characters (like [ä] or [ç]) will not produce any character.
Since the emulator tells the computer the position of keys that are pressed, you need to configure the layout for the computer independently of the keyboard layout you have configured on the host.
Use the F9 key to cycle through the layouts, or set the keyboard layout at startup using the
-keymapcommand line argument.
The following keys can be used for controlling games:
|Keyboard Key | SNES Equivalent | |--------------|----------------| |Ctrl | B | |Alt | Y | |Space | SELECT | |Enter | START | |Cursor Up | UP | |Cursor Down | DOWN | |Cursor Left | LEFT | |Cursor Right | RIGHT |
Rwill reset the computer.
Vwill paste the clipboard by injecting key presses.
Swill save a system dump (configurable with
-dump) to disk.
Returnwill toggle full screen mode.
+will toggle warp mode.
On the Mac, use the
With the argument
-gif, followed by a filename, a screen recording will be saved into the given GIF file. Please exit the emulator before reading the GIF file.
If the option
,waitis specified after the filename, it will start recording on
POKE $9FB5,2. It will capture a single frame on
POKE $9FB5,1and pause recording on
PEEK($9FB5)returns a 128 if recording is enabled but not active.
On startup, the X16 presents direct mode of BASIC V2. You can enter BASIC statements, or line numbers with BASIC statements and
RUNthe program, just like on Commodore computers.
Escin the emulator), or
Ctrl + C.
Shift + Backspaces, then type over those spaces.
Shift + Home.
STOP + RESTOREfunction.
The command line argument
-sdcardlets you attach an image file for the emulated SD card. Using an emulated SD card makes filesystem operations go through the X16's DOS implementation, so it supports all filesystem operations (including directory listing though
DOS"$command channel commands using the
DOSstatement) and guarantees full compatibility with the real device.
Images must be greater than 32 MB in size and contain an MBR partition table and a FAT32 filesystem. The file
sdcard.img.zipin this repository is an empty 100 MB image in this format.
On macOS, you can just double-click an image to mount it, or use the command line:
# hdiutil attach sdcard.img /dev/disk2 FDisk_partition_scheme /dev/disk2s1 Windows_FAT_32 /Volumes/X16 DISK # [do something with the filesystem] # hdiutil detach /dev/disk[n] # [n] = number of device as printed above
On Linux, you can use the command line:
# sudo losetup -P /dev/loop21 disk.img # sudo mount /dev/loop21p1 /mnt # pick a location to mount it to, like /mnt # [do something with the filesystem] # sudo umount /mnt # sudo losetup -d /dev/loop21
On Windows, you can use the OSFMount tool.
If the system ROM contains any version of the KERNAL, and there is no SD card image attached, the LOAD (
$FFD5) and SAVE (
$FFD8) KERNAL calls (and BASIC statements) are intercepted by the emulator for device 8 (the default). So the BASIC statements will target the host computer's local filesystem:
LOAD"$ LOAD"FOO.PRG LOAD"IMAGE.PRG",8,1 SAVE"BAR.PRG
Note that this feature is very limited! Manually reading and writing files (e.g.
OPENin BASIC) is not supported by the host filesystem interface. Use SD card images for this.
The emulator will interpret filenames relative to the directory it was started in. On macOS, when double-clicking the executable, this is the home directory.
To avoid incompatibility problems between the PETSCII and ASCII encodings, you can
Ctrl+Oto switch to the X16 to ISO mode for ASCII compatibility.
Ctrl+Nto switch to the upper/lower character set for a workaround.
BASIC programs are encoded in a tokenized form, they are not simply ASCII files. If you want to edit BASIC programs on the host's text editor, you need to convert it between tokenized BASIC form and ASCII.
Ctrl + V(Mac:
Cmd + V). You can now run the program, or use the
SAVEBASIC command to write the tokenized version to disk.
LOADthe BASIC file, and type
LIST. Now copy the ASCII version from the terminal.
Please see the KERNAL/BASIC documentation.
The debugger requires
-debugto start. Without it it is effectively disabled.
There are 2 panels you can control. The code panel, the top left half, and the data panel, the bottom half of the screen. You can also edit the contents of the registers PC, A, X, Y, and SP.
The debugger uses its own command line with the following syntax:
|Statement|Description| |---------|----------------------------------------------------------------------------------------------------| |d %x|Change the code panel to view disassembly starting from the address %x.| |m %x|Change the data panel to view memory starting from the address %x.| |b %s %d|Changes the current memory bank for disassembly and data. The %s param can be either 'ram' or 'rom', the %d is the memory bank to display.| |r %s %x|Changes the value in the specified register. Valid registers in the %s param are 'pc', 'a', 'x', 'y', and 'sp'. %x is the value to store in that register.|
The debugger keys are similar to the Microsoft Debugger shortcut keys, and work as follows
|Key|Description | |---|---------------------------------------------------------------------------------------| |F1 |resets the shown code position to the current PC | |F2 |resets the 65C02 CPU but not any of the hardware. | |F5 |is used to return to Run mode, the emulator should run as normal. | |F9 |sets the breakpoint to the currently code position. | |F10|steps 'over' routines - if the next instruction is JSR it will break on return. | |F11|steps 'into' routines. | |F12|is used to break back into the debugger. This does not happen if you do not have -debug| |TAB|when stopped, or single stepping, hides the debug information when pressed |
-debugis selected the STP instruction (opcode $DB) will break into the debugger automatically.
Effectively keyboard routines only work when the debugger is running normally. Single stepping through keyboard code will not work at present.
-abufsto specify number of audio buffers
-testto auto-run test
-geosto launch GEOS on startup
-testto launch (graphics) unit test on startup
-joy2[John J Bliss]
-echowill now encode non-printable characters like this: \X93 for CHR$(93),
-basas well as pasting accepts this convention again
-echo rawfor the original behavior
-echo isofor correct character encoding in ISO mode
-ramto specify RAM size; now defaults to 512
-dumpoption to allow writing RAM, CPU state or VERA state to disk [Nils Hasenbanck]
-qualityoption to change scaling algorithm; now defaults to "best" [Maurizio Porrato]
-echocan now be fed into UNIX pipes [Anonymous Maarten]
-char(character ROM is now part of
-debugallows specifying a breakpoint [Frank Buss]
Emulator: * VERA can now generate VSYNC interrupts * added
-keymapfor setting the keyboard layout * added
-scalefor integer scaling of the window [Stephen Horn] * added
-logto enable various logging features (can also be enabled at runtime (POKE $9FB0+) [Randall Bohn]) * changed
-runto be an option to
-bas* emulator detection: read $9FBE/$9FBF, must read 0x31 and 0x36 * fix:
-runno longer corrupt BASIC programs. * fix:
LOAD,1into RAM bank [Stephen Horn] * fix: 2bpp and 4bpp drawing [Stephen Horn] * fix: 4bpp sprites [MonstersGoBoom] * fix: build on Linux/ARM
-debugwill enable the new debugger [Paul Robson]
Ctrl + F/R/S/V
Ctrl + Vpastes the clipboard as keypresses
-bas file.txtloads a BASIC program in ASCII encoding
-echoprints all BASIC/KERNAL output to the terminal, use it with LIST to convert a BASIC program to ASCII
-prg, but also autostarts the program
SYS 65535exit the emulator and save memory into the host's storage
LOAD,x,1to load to the correct addressg
DOScommand. Without argument: print disk status; with "$" argument: show directory; with "8" or "9" argument: switch default drive; otherwise: send DOS command; also accessible through F7/F8
SYS65375 (SWAPPER) now also clears the screen, avoid ing side effects.
Cmd + For
Cmd + return
MON: enter monitor; no more SYS65280 required
VPOKE bank, address, valueexample:
VPOKE4,0,VPEEK(4,0) OR 32[for 256 color BASIC]
rom.binis now 3*8 KB:
updated KERNAL with proper power-on message
LOAD and SAVE commands are intercepted by the emulator, can be used to access local file system, like this:
No device number is necessary. Loading absolute works like this:
New optional override load address for PRG files:
./x64emu rom.bin chargen.bin basic.prg,0401
POKE40801,nto switch the RAM bank at $A000.
POKE40800,nto switch the ROM bank at $C000. The ROM file at the command line can be up to 72 KB now (layout: 0: bank 0, 1: KERNAL, 2: bank 1, 3: bank 2 etc.), and the RAM that
Cmd + Ssaves is 2088KB ($0000-$9F00: regular RAM, $9F00-$9FFF: unused, $A000+: extra banks)
Cmd + Snow saves all of memory (linear 64 KB for now, including ROM) to
memory-2.bin, etc. You can extract parts of it with Unix "dd", like:
dd if=memory.bin of=basic.bin bs=1 skip=2049 count=38655