Oliver VieBrooks

6hex / 6hex manual

Contents

6hex

A hex editor with a built-in retro-CPU monitor/debugger, built with C# / .NET 10 / Avalonia 12 and styled after the C64 — dark mode by default, C64 Pro Mono font, configurable colors, a visualizer for spotting graphics data (charsets, sprites, bitmaps), and a VICE-dialect monitor that disassembles/assembles 6502/6510, 68000, and 80x86 with retro-platform awareness (C64, Amiga, DOS).

Contents

Hex editor

Key Action
0-9 a-f edit nibble (hex pane) / type bytes (text pane)
Tab switch hex ↔ text pane
Insert toggle overwrite / insert mode (status bar shows OVR/INS)
Backspace / Delete delete byte before/at cursor (or the selection)
arrows / PgUp / PgDn / Home / End navigate
Ctrl+Home / Ctrl+End start / end of file
Shift + navigation / mouse drag select
Ctrl+F find (hex bytes or text) — F3 / Shift+F3 next / previous
Ctrl+G go to offset (hex; $/0x optional, d: for decimal)
Ctrl+I open a Visualizer window
Ctrl+D open the Debugger / Monitor
Ctrl+Z / Ctrl+Y undo / redo
Ctrl+C / Ctrl+Shift+C copy selection as hex / as text
Ctrl+V paste hex at cursor (insert or overwrite per mode)
Ctrl+A select all
Ctrl+O / Ctrl+S / Ctrl+Shift+S / Ctrl+N open / save / save as / new
Esc clear selection

Bytes that differ from the file on disk are highlighted (orange by default). Edit ▸ Insert Bytes… inserts a run of fill bytes at the cursor; every mutation is undoable. Bytes per row (8/16/32) is set from View ▸ Bytes per Row.

The editor and any open Debugger/Visualizer share one document — edits made in any of them reflect live in the others.

Crunchers — depack a selection in place

Selection ▸ Cruncher (also on the right-click menu) runs the selected bytes through 6crunch, the shared codec library — PowerPacker, StoneCracker, Imploder, CrunchMania, Exomizer, PuCrunch, ZX0, gzip/zlib, and the rest of the set it knows.

Command What it does
Identify… names the codecs that claim the selection, most confident first; changes nothing
Depack in Place replaces the selected bytes with the decoded ones — one undo step, even though what comes back is bigger
Depack to New Window opens the decoded bytes in their own window, leaving the document alone

The selection is handed to the library as a stream over the live buffer: nothing is copied out and no temporary file is written, so a crunched blob sitting at $2200 of a 10 MB disk image is select-and-depack, at no cost in the document's size. If a codec claims the span and then chokes on it — usually because the selection is the wrong extent — the status bar says so and the document is left untouched.

Text pane modes (View ▸ Text Mode)

PETSCII control codes ($00–$1F, $80–$9F) have no printable glyph and render dimmed, like non-printables in ASCII mode.

Visualizer (Tools ▸ Visualizer, Ctrl+I)

Inspect the file's bytes graphically. Multiple windows allowed; renders live as you edit, click any pixel to jump the hex cursor to that byte, and "Follow hex cursor" tracks the editor. Modes:

Multicolor (bit-pair) decoding is available for linear/charset/sprites with four configurable colors. Offset accepts hex; nudge by ±1 byte / row / page, Shift+wheel nudges by one byte for alignment hunting.

The two C64 bitmap modes reconstruct a whole screen from the standard C64 memory layout, with independent offsets for the bitmap (the offset box), the screen RAM, and — for multicolor — the color RAM, plus a background-color register. Colors come from the fixed C64 palette via the screen/color nibbles; click a pixel to jump to its bitmap byte. Defaults assume Koala layout relative to a bitmap base of 0 (screen $1F40, color $2328).

Ripping & file-type detection

Automatic file-type detection (on open)

When you open a file, 6hex sniffs it for a known signature and, if it finds one, switches the text pane and the debugger profile to match — so a DOS .exe opens in ASCII with the MZ profile, a C64 .prg opens in PETSCII, an Amiga MOD or hunk file picks the Amiga profile, and so on. Detection is deliberately signature-only (magic bytes at fixed offsets, plus the filename extension as a tie-breaker); when nothing is certain it leaves everything as-is rather than guessing. If a Debugger window is already open it follows the detected profile live. Recognised: DOS MZ (MZ), Amiga HUNK ($000003F3), SID (PSID/RSID), IFF (FORM/CAT/LIST), ProTracker MOD (format tag at offset 1080), and by extension .prg / .com / .crt / .bin.

Run it by hand any time with Ripping ▸ Detect File Type.

Ripping menu — scan a binary for embedded data

The Ripping menu hunts a loaded binary for embedded files and graphics by recognising common patterns, and moves the cursor to the next match — each item works like find-next: it selects the candidate region, reports its type / offset / size in the status bar, and the next click jumps to the following hit (wrapping once at the end of the file). Ripping ▸ Restart Scan From Top rewinds to offset 0.

Signature formats (exact magic, precise length):

C64 graphics (heuristic — candidates, not certainties):

Amiga graphics (heuristic):

Heuristic scans have no magic bytes to key on, so they flag candidate regions and will produce false positives — they're a fast way to walk the caret to the next likely graphic and eyeball it in the Visualizer, not a guarantee. Sizes marked with ? are best-effort estimates.

Debugger / Monitor (Tools ▸ Debugger / Monitor, Ctrl+D)

A VICE-dialect monitor that operates on the current file as a static memory image. It disassembles and assembles three CPU families, understands several retro executable formats, and builds symbol tables, code maps, and cross-references. The console has per-token syntax highlighting; click any address to jump the editor caret, and press Enter on an empty line to continue the last m/d/i/cop/… from where it stopped.

Toolbar

CPU, profile, illegal-asm flag, console font, and command history all persist across relaunches.

Numbers

Default radix is hex. Prefixes: $ / 0x hex, % binary, & octal, d: decimal. On the DOS EXE profile you can also type seg:off.

Profiles (p)

Profile CPU Base / behaviour
Raw / Custom 6502 flat $0000
C64 PRG 6502 2-byte load-address header → base = load addr
C64 raw (.bin) 6502 base $1000
C64 cartridge 6502 base $8000
DOS COM 8086 base $0100
DOS EXE (MZ) 8086 MZ header parsed; per-segment seg:off display, reloc table
Amiga raw / dump 68000 flat $0000
Amiga executable (hunk) 68000 HUNK_HEADER parsed; CODE/DATA/BSS hunks switchable

Every profile fails soft: a bad or truncated fit prints a note and falls back to a flat image instead of crashing.

Command reference

Memory & data:

Command Action
m [s] [e] memory dump (hex + PETSCII)
mc [s] [e] memory as 8×8 character bitmaps
ms [s] [e] memory as 24×21 sprite bitmaps
i / ii [s] [e] text dump: PETSCII / screen-code
> <addr> <data…> poke bytes
f <s> <e> <data…> fill range with a repeating pattern
h <s> <e> <data…> hunt (find) a pattern — hits are clickable
c <s> <e> <dest> compare two ranges
t <s> <e> <dest> transfer (copy), overlap-safe

Data lists mix byte, word, and string tokens: f 0801 0900 "hi" $20 41. Word tokens (>$FF) pack in the CPU's byte order — big-endian on 68000, little-endian otherwise. String tokens honour \n \t \" \\ escapes.

Files:

Command Action
s "f" <s> <e> / l "f" save / load .prg (2-byte load-address header)
bsave "f" <s> <e> / bload "f" <addr> save / load raw binary

Disassemble & assemble:

Command Action
d [s] [e] disassemble (one addr = 20 instrs; empty = continue)
a <addr> <insn> assemble one line; writes bytes and advances
cop / copper [s] [e] decode as an Amiga copper list (MOVE/WAIT/SKIP)

The disassembler annotates instructions with resolved symbols (JSR $FFD2 ; CHROUT), and the assembler resolves them back (jsr .name). Truncated or out-of-range operands fall back to .BYTE rather than over-reading.

Symbols & imports

Command Action
al <addr> <name> / dl <name> add / delete a user label
cm <addr> [text] attach / clear a free-text comment at an address
shl show user labels + comments
sl "f" / ll "f" save / load labels + comments (VICE .lbl)

User labels win over the CPU's built-in tables and annotate d / resolve in a. ll also imports Amiga .fd files (library LVOs) and LINK/Watcom .map files (x86 SEG:OFF symbol publics). The .lbl round-trips comments as ; @<addr> <text>, which plain ca65/VICE readers ignore.

Code map, cross-reference & export

Command Action
amap [entry…] recursive code/data map + auto sub_ / loc_ / str_ labels
xref <addr> list instructions that reference an address (uses the map; else linear scan)
strings [s e] [n] find printable strings (≥ n chars; z=ASCIIZ, $=DOS)
lst "f" [s e] write a disassembly listing (.lst)
map "f" write a segment / symbol / region map (.map)

amap sweeps from an explicit entry (or the image base), classifies code vs data, and adds non-destructive auto-labels. strings results are clickable and also drive inline string previews in d (a pointer load whose target is a string shows ; "…"). Flow and reference info is populated on all three CPUs, so amap / xref / previews work everywhere. Running amap (or info) also publishes the structure overlay to the Visualizer.

Amiga specifics

DOS EXE (MZ) specifics

Live target — debugging a running emulator

attach connects to an emulator that is already running and turns the document into a window on its RAM: the buffer is the machine's memory. Everything else in 6hex then works against the live machine for free — d disassembles what is executing right now, the visualizer shows the screen as it is being drawn, the Ripping menu scans live chip RAM, and typing a byte in the hex pane pokes it into the emulator.

targets                             list the back-ends and the current attachment
attach vice                         C64  — VICE binary monitor
attach amiga                        Amiga — FS-UAE control socket
attach dosbox                       DOS  — DOSBox control server
attach amiga 0 80000                ...with an explicit window (start, length)
attach vice 127.0.0.1:6502          ...with an explicit host:port
detach                              disconnect; the buffer stays as a snapshot
sync                                re-read the window now
live ro | live rw | live auto off   stop/allow write-through; control auto-refresh

6hex connects to each emulator's own local control socket — no MCP server in the path. For VICE it prefers the vice_broker on :6510 when one is running, because that shares VICE's single monitor slot, so 6hex and an MCP agent can debug the same machine at once; failing that it takes the direct monitor on :6502.

Once attached:

r / r <name> <value> show / set registers (flags decode to letters; the PC line disassembles)
g [addr] · x · pause run (optionally from an address) · run · stop
z [n] / step [n] · n [n] · ret step into · step over · run to return
break [s [e]] [if expr] set an execution breakpoint; bare break lists
watch [r\|w] s [e] · trace [s [e]] data watchpoint · count hits without stopping
until <addr> temporary breakpoint, then run
del <n> · enable/disable <n> · cond <n> <expr> del 0 deletes all
reset [hard] · bank [id\|name] · keys "text" reset · select a memory bank · type on the emulated keyboard
io chip/IO registers — VIC-II on the C64, the decoded custom-register file (with each register's last-writer PC) on the Amiga, VGA state on DOS

Breakpoints that fire while you sit at the prompt are reported as they happen, and the window re-reads itself so the editor shows the machine as it is at the stop.

Back-ends differ in what they can do, and 6hex says so by name rather than failing obscurely — the FS-UAE socket, for instance, has memory and pause/resume but no registers, stepping or breakpoints, so r there answers "FS-UAE does not support register access over this link". targets prints each one's capability list.

Two things to know: edits are poked into the machine the moment you make them (live ro if you would rather look than touch), and inserting or deleting bytes has no meaning against a fixed-size RAM window, so write-through suspends itself if you try. The DOSBox control server serves one client at a time, so attaching takes the slot from the DOSBox MCP server.

Colors, fonts & settings

View ▸ Colors & Font… — all editor colors and the font size are live-editable and persisted to ~/.config/6hex/settings.json, along with bytes-per-row (8/16/32), text mode, PETSCII charset bank, and the debugger's CPU / profile / illegal-assembly / console font / command history.

Fonts are embedded: the C64 Pro Mono font (Style64) and a set of classic Amiga bitmap fonts (Topaz, Topaz+, MicroKnight, P0T-NOoDLE, mO'sOul).