![]() |
![]() |
A machine language monitor for the Commodore 64. Loads at $C000 on a stock C64 β no cartridge or memory expansion required.
- Inspect and modify memory with a hex dump and interactive alter mode.
- View and modify the CPU registers and processor status flags via a shadow-register block; capture the live CPU state when a user routine returns through
BRK. - Fill and copy arbitrary blocks of memory.
- Save and load machine language programs to and from disk, in PRG and SEQ formats; list directories.
- Clear the screen and exit cleanly back to BASIC.
See Commodore VIC-20 version, here.
- π Overview
- π Quick Start
- π Version History
- πΎ Loading and Starting
- π Command Reference
- π¬ Example Session
- π Project Structure
- π» Building From Source
- πΏ Disk Image Listing
- β FAQ
- π€ Contributing
- πββοΈ Acknowledgements
- π License
Code Probe is a software-based machine language monitor that runs at the upper-RAM window $C000-$CFFF on a stock Commodore 64. The address range is permanent RAM, sitting between BASIC ROM (which ends at $BFFF) and the I/O page (which starts at $D000), so the monitor coexists with both ROMs in their default banked-in configuration.
The design of Code Probe was inspired by the DOS DEBUG utility and presents a similar terminal-style user interface and commands. All numeric input is hexadecimal: addresses are 4 digits; byte values, file types, and device numbers are 2 digits each.
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β $E000-$FFFF β KERNAL ROM β
β $D000-$DFFF β I/O page (VIC-II, SID, CIA, color RAM) β
β $C000-$CFFF β βΊ Code Probe (4 KiB) β
β $A000-$BFFF β BASIC ROM β
β $0800-$9FFF β BASIC program + free RAM (PRG load at $0801) β
β $0200-$07FF β System workspace + screen RAM ($0400-$07FF) β
β $0000-$01FF β Zero page + stack β
ββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββ
The $C000-$CFFF window is permanent RAM that sits between BASIC ROM and the I/O page in the C64's default banking, so Code Probe coexists with both ROMs without any banking gymnastics. User machine language programs can live anywhere in the free RAM below BASIC ROM (typically loaded to $0801 or higher).
- Memory inspection - Hex dump with PETSCII character display.
- Memory editing - Interactive alter mode with cursor navigation, auto-space between bytes, and auto-commit at ten bytes per line.
- Register management - View and modify A, X, Y, SP, PC, P, IO; expand the processor status flags as individual bits with
RF. The shadow registers persist acrossGinvocations. - Memory operations - Fill ranges with a constant byte, copy ranges with overlap-safe forward and backward walks; clamp at
$FFFFwith an overflow warning. - Program execution - Run machine language programs via an RTI dispatch with the shadow registers loaded into the live CPU; the user routine returns to the monitor with
BRK, and CPU state is captured back into the shadow block. - Disk I/O - Save and load PRG and SEQ files to and from a 1541 (or compatible) disk drive at device 8; list directories. PRG files round-trip with a chosen load address; SEQ files carry raw bytes only.
- Screen control - Clear the display with a single command.
- Exit to BASIC - Return to BASIC's
READY.prompt; re-enter Code Probe withSYS 49152.
LOAD "CODEPROBE",8,1
SYS 49152
CODE PROBE (2.1) - ROHIN GOSLING
: β
The first two lines load Code Probe from a 1541-compatible drive at device 8 and start it. The third β your first command β dumps the first 256 bytes of the monitor's own code, so you can confirm it's running.
See the Command Reference for the full command set, Loading and Starting for VICE and SD2IEC variants, or docs/user-manual.pdf for worked tutorials.
| Year | Version | Platform | Description |
|---|---|---|---|
| 1988 | 1.0 | VIC-20 | Hand-assembled and poked into RAM with a BASIC machine language loader. |
| 1990 | 2.0 | C64 | Ported to C64, with expanded feature set and C64-specific updates. |
| 2026 | 1.1 | VIC-20 | Assembly reconstruction of original version 1.0 for the VIC-20. |
| 2026 | 2.1 | C64 | Assembly reconstruction of version 2.0 for the C64. |
Code Probe loads at address $C000 (49152 decimal) and occupies up to 4 KiB of RAM in the $C000-$CFFF region. The native C64 RAM at $0801-$BFFF (BASIC's program area + free RAM up to BASIC ROM) is left free for user machine language programs.
LOAD "CODEPROBE",8,1
SYS 49152
The ,8,1 parameter loads the program to the address stored in its PRG header ($C000), rather than to the default BASIC area. SYS 49152 transfers control to Code Probe.
To launch x64sc with build/codeprobe.prg autostarted into the monitor:
x64sc -autostart build/codeprobe.prgTo attach a disk image at the same time so save and load can target it:
x64sc -8 dist/codeprobe.d64 -autostart build/codeprobe.prgx64sc must be on PATH, or substitute the full path to your VICE install (e.g. C:\Programs\GTK3VICE-3.10-win64\bin\x64sc.exe on Windows, /usr/bin/x64sc on most Linux distributions).
- The screen border and background are set to black via VIC-II registers
$D020and$D021. - The KERNAL text colour at
$0286is set to green. - The screen is cleared via
CHROUT $93. - The title banner is displayed.
- A blank line separates the banner from the first prompt.
- The shadow registers are initialised to their defaults.
- The original BRK vector at
$0316/$0317is saved, and Code Probe'sbrk_handleris patched in. - The monitor prompt loop begins.
All address and count values are hexadecimal: addresses are 4 digits; byte values and device numbers are 2 digits each. Filenames are enclosed in double quotes and limited to 16 characters of uppercase PETSCII.
| Command | Syntax | Description |
|---|---|---|
A |
A <address> |
Enter alter mode to write hex bytes to RAM. |
D |
D <start> <end> |
Hex dump memory from start to end (inclusive). |
R |
R |
Display A, X, Y, SP, PC, P, IO from the shadow block. |
R |
R <register> <value> |
Set a shadow register and reprint the line. |
RF |
RF |
Display registers + flag bit-view. |
RF |
RF <flag> <bit> |
Set a processor status flag and reprint. |
F |
F <address> <count> <value> |
Fill memory range with a byte. Clamps at $FFFF. |
T |
T <source> <count> <destination> |
Copy memory range to a destination. Overlap-safe. |
G |
G <address> |
Execute machine code at address; capture regs on BRK. |
S |
S "<file>" <device> <start> <end> [<load_addr>] |
Save range to file. With load_addr = PRG; without = SEQ. |
L |
L <device> |
List files on device. |
L |
L "<file>" <device> |
Load PRG file (uses file's load address). |
L |
L "<file>" <device> <address> |
Load SEQ / raw bytes to specified address. |
CLS |
CLS |
Clear the screen. |
EXIT |
EXIT |
Exit to BASIC. Re-enter with SYS 49152. |
The S and L commands take filenames in "<name>" form because the 1541 disk drive uses unquoted commas to separate the filename from its type and mode flags. Code Probe builds those flags internally (,P,W for PRG save, ,S,W for SEQ save), so the user's filename has to be quoted to disambiguate.
The G command builds an RTI stack frame from the shadow registers and dispatches into the user routine via RTI (not JSR). The user routine must terminate with BRK (opcode $00) to return to Code Probe; an RTS will pull garbage off the stack. On BRK, the live CPU state is captured back into the shadow block, restoring the screen colours and dropping into the monitor prompt.
See docs/user-manual.pdf for the full user manual, including worked tutorials, the memory map, error messages, a quick reference card, and an appendix on launching Code Probe under VICE emulation.
A typical end-to-end session: load a small machine language routine from disk, verify it landed correctly, patch a byte in place, run it, then inspect the captured CPU state.
| BASIC Command Workflow | Description |
|---|---|
LOAD "CODEPROBE", 8, 1 |
Load Code Probe from disk. |
SYS 49152 |
Run Code Probe. |
CODE PROBE (2.1) - ROHIN GOSLING
: β
| Code Probe Command Workflow | Description |
|---|---|
L "HELLO" 08 |
Load HELLO; lands at $1000 per its PRG header. |
D 1000 100F |
Verify the routine landed. |
A 1004 |
Patch a byte interactively; press RETURN to commit. |
G 1000 |
Execute; the routine returns through BRK. |
R |
Show captured A, X, Y, SP, PC, P, IO. |
EXIT |
Return to BASIC's READY. prompt. |
HELLO is one of the demo programs on the distribution disk image (see Disk Image Listing). It writes "HELLO WORLD!" to the screen and terminates with BRK, which hands control back to Code Probe and snapshots the live CPU registers into the shadow block where R can read them.
For deeper walkthroughs, including patching live code, writing machine language programs, fill-and-copy recipes, save/load round-trips, and shadow-register manipulation, see docs/user-manual.pdf.
The repository layout matches the released distribution exactly β what you see here is what ships in the GitHub release archive.
code-probe-c64/
βββ LICENSE
βββ README.md
βββ build/
β βββ codeprobe.prg
βββ dist/
β βββ code-probe-2.1.d64
βββ docs/
β βββ user-manual.pdf
βββ images/
β βββ animation-1.gif
β βββ animation-2.gif
βββ src/
βββ codeprobe.asm
src/ holds the 6502 assembly source; build/ the pre-built .prg; dist/ the distribution disk image; docs/ the rendered user manual; images/ the demo GIFs and supporting images.
Code Probe is a single-file assembly project built with Kick Assembler. Java is required.
Assemble:
java -jar KickAss.jar src/codeprobe.asm -odir buildor, on Windows, run the supplied driver:
build-code-probe.bat
The build produces build/codeprobe.prg β a PRG that loads at $C000. The same PRG runs on a physical Commodore 64 and on the VICE x64sc emulator.
Hardware required:
- A Commodore 64 (PAL or NTSC).
- A means of transferring
build/codeprobe.prgfrom the build host to the C64 β for example a 1541 / 1541-II disk drive with a PRG-to-D64 toolchain, an SD-card drive emulator (SD2IEC, Pi1541, Ultimate II), or a serial cable to a real 1541.
With the PRG on disk:
LOAD "CODEPROBE",8,1
SYS 49152
The ,8,1 parameter forces the file to load at the address in its PRG header ($C000) rather than the default BASIC program area at $0801. SYS 49152 transfers control to the monitor.
x64sc -autostart build/codeprobe.prgRun from the v2/ directory so the relative path to build/ resolves. x64sc must be on PATH, or substitute the full path to your VICE install (e.g. C:\Programs\GTK3VICE-3.10-win64\bin\x64sc.exe on Windows, /usr/bin/x64sc on most Linux distributions).
The supplied run-code-probe.bat (Windows) wraps the same launch with a sensible default install path.
Contents of the distribution disk image dist/code-probe-2.1.d64. The disk doubles as the binary release and a bundle of tutorial examples referenced from the user manual.
| File | Type | Description |
|---|---|---|
CODEPROBEΒ |
PRG | Code Probe machine language monitor (v2.1). Loads at $C000; invoke from BASIC with SYS 49152. |
CLS-MLΒ Β Β Β |
PRG | Screen-clear utility (machine language). Sets the border and background to black, the text colour to green, and clears the screen. |
CLS-BASICΒ |
PRG | Screen-clear utility (BASIC). Functionally identical to CLS-ML, but written in BASIC. Provided as a side-by-side reference of the two languages. |
HELLOΒ Β Β Β Β |
PRG | "Hello, world" demo intended to be loaded under Code Probe at $1000 and executed with the G command. Returns to the monitor via BRK. |
HELLO-RUNΒ |
PRG | Standalone "hello, world" with a BASIC autostart stub at $0801 and an ML body at $080E. RUN from BASIC with either RUN or SYS 2062. |
CUBE-C64Β Β |
PRG | Interactive 3D rotating cube demo for the Commodore 64, ported from the original VIC-20 version. BASIC autostart stub at $0801, ML body at $080E. Used as a multi-KiB stress-test for Code Probe's Save / Load round-trip. |
CUBEβVIC20 |
PRG | Original VIC-20 version of the interactive 3D cube demo. Included for cross-platform reference; it does not run on a C64. |
Why must my routine end in BRK rather than RTS?
The G command builds an RTI stack frame from the shadow registers and dispatches via RTI, not JSR. There is no return address on the stack for RTS to pull, so an RTS would pull garbage and jump into nowhere. BRK (opcode $00) traps into Code Probe's installed BRK handler, which is how the live CPU state is captured back into the shadow block.
Why is all input hexadecimal?
Hex matches how machine language is read in memory and in disassembly listings. Mixing hex and decimal would mean every numeric input needs a prefix or a modal switch, which adds friction. Sticking to hex keeps the prompt minimal and the parser simple β addresses are always 4 digits, byte values always 2.
Does it work on both PAL and NTSC machines?
Yes. Code Probe doesn't touch the VIC-II's raster or timing in a way that distinguishes the two video standards; it only writes the border, background, and text-colour registers, which behave identically on PAL and NTSC.
Can I relocate Code Probe somewhere other than $C000?
Not without rebuilding. The PRG header pins the load address to $C000, and SYS 49152 depends on it. To relocate, change the load address in src/codeprobe.asm, reassemble with Kick Assembler, and update the SYS invocation accordingly. The $C000-$CFFF window is a particularly natural choice on a stock C64 because it's permanent RAM between two ROMs β see the Memory Map for context.
Why does G capture registers via a shadow block instead of the live CPU?
Two reasons. First, the shadow block lets you set the entry-point CPU state by typing R A 5C (etc.) before invoking G β there is no live CPU state to write to before the dispatch. Second, the shadow block survives further monitor commands; if G left the values in the live CPU, the very next instruction Code Probe ran would clobber them.
Contributions are welcome. The recommended workflow:
- Fork the code-probe-c64 repository on GitHub.
- Make your changes β source in
src/codeprobe.asm, documentation underdocs/. - Build locally with Kick Assembler β see Building From Source.
- Test on the VICE emulator, and on real hardware if you have access.
- Open a pull request describing the change and what you tested.
| Tool | AuthorΒ /Β Maintainer | Role in this project |
|---|---|---|
| KickΒ Assembler | MadsΒ Nielsen | 6502 cross-assembler. Builds codeprobe.prg from codeprobe.asm. |
| VICE | TheΒ VICEΒ Team | Commodore emulator suite. xvic and x64sc for development and testing. |
| C64Β TrueType | STYLE | TrueType C64 font set. Used to typeset the user manual in an authentic Commodore style. |
| ClaudeΒ Code | Anthropic | AI coding assistant. Constructed the Kick Assembler listings from the original PRG binaries. |
Copyright Β© 2026 Rohin Gosling.
Code Probe and its accompanying user manual are distributed under the MIT License β a permissive, free-software licence that allows use, modification, and redistribution (including commercial use), provided the copyright notice and licence text are preserved.
This is a personal retrocomputing project shared for historical and educational purposes.

