The Orange Nerd

ByteBox: Manual and Download

This page is the manual for ByteBox, my Amstrad CPC 6128 emulator (see the making-of for the story behind it). It covers the command-line options, keyboard shortcuts, console commands and the built-in Z80 monitor, and ends with a short guide to writing and running your own Z80 code on the emulator.

Features

By default, subdirectories for images and snapshots are in ~/.bytebox; the config file is in ~/.config/bytebox.

Tape drive

The 6128 has a floppy drive, but the emulator also reproduces a real datacorder: you can load .cdt images, and it even reinjects the tape signal into the audio mix while the motor runs, for the familiar loading whistle. A power cycle (pc) keeps the tape inserted, rewound to its start.

At the BASIC prompt, CTRL + the numeric keypad's Enter (not the main Enter key) types RUN" and validates it automatically — this is a keyboard expansion token built into the firmware itself, not an emulator feature. Once a tape is inserted, just press Enter a second time.

Download

Gallery

Command-line options

Function keys

F1 / F2 / F3   window size x1 / x2 / x3
F4             toggle fullscreen
F5             toggle the CRT shader (RGB phosphor mask, scanlines)
F6             toggle the configuration/media panel (disks, tape,
               drive B, extra RAM, zoom, volume, CRT shader tuning,
               ROM installation — all with an immediate effect, no
               restart needed)
F7             toggle the virtual keyboard (clickable, overlaid on the
               emulator window)
F8             step to next Z80 instruction
F9             step to next video line
F10            toggle the quick command bar (one input line, overlaid
               on the emulator window)
F11            toggle the full console window (scrollable history,
               same commands as the quick command bar) — on macOS,
               Cmd+Shift+C does the same thing, since F11 is claimed
               system-wide by "Show Desktop" before it ever reaches
               the app
F12            toggle the machine status window

Emulator commands

disk d.dsk          Loads the d.dsk disk image on drive A
disk d.dsk b        Loads the d.dsk disk image on drive B (if enabled in config.toml)
disk eject          Ejects the disk image from drive A
disk eject b        Ejects the disk image from drive B
blank d.dsk         Creates a blank formatted disk image and inserts it in drive A
blank d.dsk b       Creates a blank formatted disk image and inserts it in drive B
tape f.cdt          Loads the f.cdt tape image into the tape reader
tape eject          Ejects the tape image
snap f.sna          Saves a .SNA snapshot (readable by other CPC emulators)
pc                  Performs a power cycle
vol                 Displays the audio output volume
vol 30              Sets the audio output volume to 30 %
driveb on           Enables drive B, with immediate effect (unlike
                    config.toml's [drives] drive_b, which only
                    applies at startup)
driveb off          Disables drive B
ram 16              Sets extra RAM banks to 16 (applied at the next
                    power cycle, "pc" — RAM is sized at construction)
tapevol 10          Sets the tape signal level in the audio mix to 10 %
diag on             Enables the Diagnostic ROM at slot 0F (applied at
                    the next power cycle, "pc")
diag off            Disables it

All of the above are also available from the configuration/media panel (F6) as clickable fields, with a native file picker for disk and tape images — no need to type a path.

Emulator monitor commands

d 0x0000          disassembles code at 0x0000 and the 20 next
                  instructions
m 0xeeee          displays memory content at address 0xeeee
m 0xeeee 0xaa     sets memory address 0xeeee to the 0xaa value
mr 0x1000         dumps 256 raw RAM bytes from 0x1000, ignoring any ROM
mr 0x1000 0x1100  dumps the raw RAM range 0x1000..0x1100
s 0xaa            searches for a byte in memory
n                 steps to next Z80 instruction
l                 steps to next video line
j 0x0000          jumps to 0x0000 address
b                 displays set breakpoints
b 0x0002          sets a breakpoint at address 0x0002
f 0x0002          "frees" (deletes) breakpoint at address 0x0002
w                 displays set watchpoints
w 0xeeee          adds a write watchpoint at address 0xeeee
fw 0xeeee         removes watchpoint at address 0xeeee
p                 pause execution
g                 resume execution after the "p" command, or a breakpoint,
                  has been used to halt execution
hw                displays Gate Array and CRTC status
hw kb             keyboard test
r                 displays the contents of flags, registers and interrupts
t                 displays trace status
t on              records every executed instruction in a ring buffer
t calls           records only jumps, calls and returns (far longer reach)
t off             stops recording, keeping what has been captured
t dump 100        displays the last 100 recorded instructions
t save f.txt      writes the whole buffer to a file

Machine status window

A concrete example of combined usage:

  1. launch the emulator.
  2. open the machine status window alongside it using F12.
  3. enter a breakpoint command in the quick command bar or the full console (e.g., b 0x0038 for the interrupt) using F10 or F11.
  4. As soon as the breakpoint is hit, the emulator freezes, and the debug window displays the full machine state.
  5. press F8 several times: you see the disassembly print out in the console, and all register values (PC, SP, A, B, C...) update in the debug window.
  6. press F9: the emulator skips ahead by one video line, and you watch the HSYNC Counter and current_line update in real-time on the debugger screen.

Writing Z80 code for the CPC

If you're developing for the CPC rather than just running software on it, snapshots give you an edit-assemble-run loop with no disk image in the way. RASM assembles straight into a ready-to-run .SNA — RAM laid out and entry point already set — which ByteBox resumes directly:

Here's a complete, working example to copy-paste. Save it as demo.asm:

    BUILDSNA            ; emit a snapshot, not a cartridge
    BANK 0              ; without this, nothing is written to memory
    ORG  #4000
    RUN  #4000          ; where execution starts

start
    ld   bc, #7F10      ; select the border
    out  (c), c
    ld   bc, #7F4C      ; ink 12: bright red
    out  (c), c
loop
    jr   loop           ; stay here

Then assemble it and run it:

rasm demo.asm -oi demo.sna -v2 && bytebox --snapshot=demo.sna

You should get a bright red border around a blue screen. -oi names the snapshot RASM writes; -v2 picks the format ByteBox reads — see the notes below, both matter more than they look.

The whole cycle is a single command away, so re-running after an edit costs nothing — which is the point.

A few things worth knowing: