Docs · chapter 5

Debugging

Updated 14 November 2026 · version 0.17

In short: open a capture in ProtoTTD and move through the run as in any debugger, except that every command also goes backward. Nothing runs again: each value is read from the recording, so a step back is as exact as a step forward.

1

The window

A capture opens on its first instruction, with the threads on a timeline and the code as it ran.

ProtoTTD on a capture
Top, the buttons (backward on the left, forward on the right) and the timeline of the threads. Middle, the code and its source; right, registers, locals, stack, call stack. Bottom, memory and the searches.
The toolbar and the timeline
BACK: start, run, to the call, over, step. FORWARD: step, over, out, run, end. The instant (#109150), the thread, and go to.
KeyForwardWith Alt: backward
F11Step intoStep back
F10Step over a callStep back over a call
Shift+F11Step out of the functionBack to where it was called
F5Run to the next breakpoint (or the end)Run backward to the previous one (or the start)
Ctrl+PGo to #5000, thread 1234 #5000, a mark, or the next run of an address or function (Shift+Enter: the previous)
Alt+← / Alt+→Back and forth through the places you visited

The panels: the timeline of every thread, coloured by module; the disassembly of the thread as it ran (the wheel steps through it); the code at any address; registers, the stack and memory at this instant; source, parameters and locals from the PDB; the events of the run; searches over the whole run; watches; and a Python panel.

Right-click anything
An address, a register, a value or a line has a menu: follow it in memory, see who wrote it last, every access to it in the run, a breakpoint or a watch on it, copy it. Most work needs no command at all.
2

The prompt

The same debugger as text, WinDbg style: for a terminal, a script, or an agent.

.\ProtoTTD.exe app.proto.cap
0:0> bp kernel32!CreateFileW
0:0> g                       # to the first call
0:0> k                       # how it got there
0:0> gu-                     # back to the caller, before the call
0:0> who rcx                 # the last write to the bytes rcx points to
CommandWhat it does
t [n], t- [n]Step forward, backward.
p, p-Step over a call, forward and backward.
g, g-Run forward, backward, to a breakpoint or the end.
g <a>, g- <a>To the next, the previous execution of an address.
gu, gu-Out of this function, forward; back to its call.
pl, pl- · tl, tl-To the next, previous source line: over calls (pl), into them (tl). Needs the PDB.
!tt C:ITravel to an instant.
bp <expr> [if <cond>] [pass <n>]A breakpoint, only where the condition holds, at the n-th time. bl, bc, bd, be list, clear, disable, enable.
ba <r|w><n> <a>Stop on an access to memory.
mem <a> [L n] [r|w|rw]Every access to those bytes in the run: when, thread, value, by whom.
who <a> [L n]The last write to those bytes before here.
calls <f> [max n]Every call to f: its arguments and its return value.
r [expr] · db dd dq <a>Registers; memory at this instant.
u [n] · uf <a>The next instructions executed; the code at an address, as it ran.
k · dv · dx <path>Call stack (with source lines); parameters and locals, typed; a value and its fields.
.line · lsa [where] [n]The source file and line here; the source around here, a function or file:line.
s <a> L<n> <hex>|"text"Search memory as it is now.
mark <name> · jump <name>Keep an instant, come back to it.
lm · ln [a] · x <mod!mask>Modules; the nearest symbol; find symbols.
~ [id]Threads; switch to one.
$$< <file>Run a script of commands (# comments).
.sympath · .reload · .srcpathWhere symbols come from; load them; where sources moved since the build.
3

Expressions

Addresses, registers, symbols and C, in any command that takes an address or a condition.

WriteMeans
app+0x1000 · app!parse_headerAn address in a module; a function by name.
rsp+8 · poi(rsp+8)Arithmetic on registers; the pointer read at an address.
`order.c:9`A source line: bp `order.c:9`, g `order.c:9`.
order->total · names[i+1]A parameter, a local or a field is its value, as in C; indexes can be expressions.
&order->totalWhere it is. In db, dd, dq, who, mem and ba, a variable names where it is.
0:0> bp `order.c:7` if item == 0
0:0> ? order->total
0:0> who order->total
Values the run never showed
The debugger shows what the recording proves. A register right after a call into a library left out of the trace, or memory the program never touched before this instant, is shown as unknown rather than guessed.
4

Source and types

With the program's PDB, the debugger works in your source: lines, parameters, locals, structures, globals, bit fields.

The Source panel with its files, the current line, typed locals, the stack
The Source panel: the PDB's files on the left, the current line lit; ◀ Line and Line ▶ step by line both ways. Locals show their values typed: item is an Item* whose fields are already read.

The PDB is found beside the program or where the build wrote it. .sympath srv* adds Microsoft's symbol server for Windows' own DLLs. When the sources have moved since the build, .srcpath <folder> (or the Source panel's folder button) says where they are now; .files lists what the PDB names. 64 and 32-bit programs alike; several source files and folders are fine.

5

Python

The whole debugger as a Python module, in the window's Python panel or in your own scripts.

import protottd
t = protottd.attach()                     # the window that is open (its Python panel does this for you)
t = protottd.open("app.proto.cap")        # or a capture, without a window

t.run_to("kernel32!CreateFileW")
print(t.wstring("rcx"), t.source, t.regs.rax)
for c in t.calls("kernel32!CreateFileW"):
    print(c.at, c.args, c.ret)
t.last_write("rsp", 8)                    # who wrote these bytes last
for v in t.values: print(v.name, v.type, v.text)
t.value("order->names[2]").text
t.breakpoint("order.c:9", condition="item == 0"); t.run(back=True)

python\protottd.py is in the zip; its first lines list every call. For other languages, ProtoTTD.exe app.proto.cap --ui takes one JSON request per line and answers one per line: the same operations.