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
- Text pane modes
- Visualizer
- Crunchers — depack a selection in place
- Ripping & file-type detection
- Debugger / Monitor
- Colors, fonts & settings
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)
- ASCII — printable ASCII, dots for the rest
- PETSCII Uppercase — uppercase/graphics bank (C64 Pro Mono's U+E0xx mapping)
- PETSCII Lowercase — lowercase/uppercase (shifted) bank (U+E1xx mapping)
- Screen Codes — C64 screen-code order (U+E2xx mapping)
- Charset — each byte drawn as a 1bpp 8-pixel row; every 8 bytes stack into an 8×8 glyph, just like a C64 character set in memory
- Amiga Font — render the text column in a classic Amiga bitmap font (Topaz and friends); the pane scales to match the debugger's font metrics
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:
- 1bpp bitmap (linear) — each byte = 8 pixels, configurable bytes/row
- Charset tiles (8×8) — consecutive 8-byte cells laid out as a tile grid
- Planar bitmap — 1–6 bitplanes, line-interleaved (Amiga) or sequential planes with configurable plane height; rendered as intensity
- C64 sprites (24×21) — 64-byte stride sprite sheet grid
- C64 MC bitmap (160×200) — full multicolor bitmap screen (Pepto palette)
- C64 hires bitmap (320×200) — full hi-res bitmap screen
- Structure map (amap) — colours the whole file by what the debugger's
amapfound: code (green), data (steel), string (gold), padding (grey), reloc (red). A legend shows live per-kind counts; hover a byte for its kind; click to jump the caret. Updates live when you re-runamap/infoin the debugger.
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):
- ProTracker MOD — the 4-char format tag at offset 1080 (
M.K.,6CHN,FLT8,32CH, …); the sample table + order list give the module's exact byte length - SID tune —
PSID/RSIDheaders (music data length is unknown, so the size is flagged approximate with?) - IFF —
FORM/CAT/LISTcontainers (ILBM, 8SVX, ANIM, SMUS…); the chunk size gives an exact length - Amiga HUNK exe — the
$000003F3executable header - DOS MZ exe — the
MZheader; page count + last-page bytes give the length
C64 graphics (heuristic — candidates, not certainties):
- Charset (8×8) — a run of cells that look like glyphs (not blank, not solid)
- Sprites (24×21) — a run of plausible 63-byte sprite cells on the 64-byte stride
- Koala bitmap — a
$6000load address followed by a full 10001-byte picture
Amiga graphics (heuristic):
- Planar graphics — a stretch of structured, non-flat bytes that could be bitplanes
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 dropdown —
6502/68000/x86(also settable withcpu) - Profile dropdown — the executable format (see below; also
p) - Base box — repoint the flat image's base address (also
base) - illegal asm checkbox — let the 6502/6510 assembler emit undocumented opcodes
- Font dropdown — console font; Auto picks Amiga Topaz for Amiga profiles, C64 Pro Mono otherwise (plus Topaz+, MicroKnight, P0T-NOoDLE, mO'sOul…)
- Clear — clear the console
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.
- 6502 / 6510 — full documented opcode set plus undocumented/illegal opcodes
(marked
*; assembled only when illegal asm is on). Built-in C64 KERNAL symbols. - 68000 — full documented-instruction disassembly (Motorola syntax, big-endian); the assembler covers the common subset.
- 80x86 — 16- and 32-bit decode from 8086 to Pentium; DOS INT resolution
(
mov ah,$09 / int $21→; DOS 09h: …) for INT 21h/10h/13h/16h/15h/2Fh/33h.
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
cop/copper— decodes MOVE/WAIT/SKIP with$DFFxxxregister names, WAIT/SKIP beam positions + masks, the$FFFF,$FFFEterminator, and a clickable jump for the COP1LC/COP2LC pointer pair.lib aN <name>— bind an address register to a library sojsr d16(aN)resolves LVOs;liblists libraries and bindings.custom aN [ciaa|ciab|off]— pin an address register as a hardware base sooffset(aN)shows register names:custom a5pins$DFF000($96(a5)→; DMACON),custom a6 ciaaresolves CIA registers,custom a5 offclears it, barecustomlists bindings. Alea $DFF000,a5in a listing auto-bindsa5too.- Value decode — word-immediate writes to hardware registers are decoded:
move.w #$8020,$DFF096→; DMACON SET DMAEN|COPEN,move.w #$0F00,$DFF180→; COLOR00 RGB $F00; BPLCON0 shows planes/hires/HAM; blitter BLTCON/BLTSIZE decode. The same notes appear incop. seg [N]— list Amiga hunks and switch the active one;m/d/afollow it.
DOS EXE (MZ) specifics
info/hdr— lay out the 14 MZ header fields, entry CS:IP, SS:SP, linear address, and the relocation table (each fixup clickable).dflags an instruction covering a fixup with; reloc → seg.- On the DOS EXE profile,
d/m/ the status bar show addresses asSSSS:OOOOrelative to the active segment;seglists CODE (CS) / STACK (SS) / fixup segments andseg Nrepoints the display origin.
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).