AudionAudion

The TourBox `.tb` preset format

FORMAT.md

The TourBox .tb preset format

Everything here was derived from a TourBox Elite on Windows with Console 5.11.3, by writing files, importing them, reading the control list back, and re-exporting. Each claim carries a status:

Nothing below is guessed. Where a value is unknown it says so.


1. Container — confirmed

.tb  →  gzip (deflate level 6, MTIME = 0, OS = 0xFF, no FNAME/FEXTRA)
     →  XML <TableTransfer>, 2-space indent, no XML declaration
        <configBytes>  base64 → 3350-byte control table
        <presetName>   display name
        <presetConf>   section layout (which control ids appear in which group)
        <hudList>      HUD geometry and visible item ids
        <shortCuts>    optional <ShortDesc> dictionary, see §7

Writing the gzip header this way makes the round trip byte-identical. Verified on four independent vendor exports.

2. Control table — confirmed

3350 bytes = 22-byte header + 256 records × 13 bytes
record[0] == record index on all 256 slots   (self-validating; assert on load)

Header. header[1] is 0x02 everywhere; header[2..21] are zero. header[0] is the preset's slot number inside Console, assigned on import (inferred): three probes written with 0x01 came back as 0x08, 0x11, 0x12. A generator can write anything there.

3. Record — confirmed

[0]      control id (equals the index)
[1]      flags: 0x08 marks a rotational control
[2]      reserved (zero in every sample)
[3..7]   action A
[8..12]  action B — the second rotation direction

4. Action block

[0] modifier mask   (when the kind is keyboard)
[1] action kind
[2] parameter       (non-zero for some non-keyboard kinds)
[3] reserved        (zero except three vendor blocks holding 63)
[4] key code within the kind
Correction to earlier descriptions. Byte [1] is not a two-valued "key
page". Across 581 vendor presets it takes 41 distinct values. It selects the
kind of action. Only kinds 0 and 1 are keyboard.
KindMeaningStatus
0ASCII characterconfirmed
1special key, compact vendor enumconfirmed
everything elsemouse, plugin commands, TourMenu, macrosunresolved

A kind-0 block whose code is 0 and whose byte [0] is 32 or 128 is not a keyboard action despite the kind.

5. Modifiers — confirmed

BitKey
0x02Shift
0x04Alt
0x08Ctrl

Bits 0x01, 0x10, 0x20, 0x40, 0x80 are unresolved — they never appear on a keyboard action in any vendor preset.

Two independent lines agree. The vendor's own Photoshop preset binds the four Prime Four buttons to bare modifiers, and Console renders them [CTRL], [SHIFT], [ALT] against bytes holding 8, 2 and 4. Separately, the shipped shortcut dictionaries use the same encoding, and publicly known shortcuts pin each bit — m=8 s=Z labelled "Отменить" is Ctrl+Z, m=12 s=C labelled "Размер холста..." is Ctrl+Alt+C.

This contradicts the upstream project YongHee-Kim/tourbox-preset, which
documents a bare Alt binding as 0x02. On this device and firmware 0x02 is
Shift and Alt is 0x04. Anyone generating presets from the upstream table will
emit Shift where they meant Alt.

6. Special keys (kind 1) — confirmed

Each name below was written into a probe, imported, and read back from Console's control list under that name.

CodeKeyCodeKey
1Up20F11
2Down21F12
3Left22F13
4Right23F14
5PageUp24F15
6PageDown25F16
7Home26F17
8End27F18
9Insert28F19
10F129F20
11F232F23
12F342Numpad *
13F443Numpad +
14F545Numpad -
15F646Numpad .
16F747Numpad /
17F848–57Numpad 0–9
18F9
19F10

Function keys run F1–F24 across codes 10–33. Numpad digits are 48 + digit.

Red rows. Codes 30, 31, 33, 34–41, 44, 58, 59, 60 are accepted and stored, but Console paints them red — its marker for a key it will not deliver. Re-exporting and diffing shows records identical, so red is a display verdict, not a rejection. Their names were unreadable at screenshot resolution, so they are left unnamed here even where arithmetic makes them obvious (30, 31, 33 fall inside the F-key run; 44 sits where Windows places VK_SEPARATOR).

Codes above 60 were never probed.

7. The <ShortDesc> dictionary — what it is and is not

Vendor presets ship a dictionary of <m> modifier mask, <s> key value, <d> human label. Values above 0x01000000 are Qt::Key constants.

It is a catalogue of the application's shortcuts, not a label list for the device's bindings. It cannot be used to name kind-1 codes: intersecting its candidates for compact code 3 yields {Backspace, Return}, while code 3 is confirmed Left. Its real value is §5 — <m> shares the control table's modifier encoding.

8. Control id map — confirmed

47 slots. Slot 59 carries the rotational flag, belongs to no section, and should be left alone.

Console is localised, so the same control has a different label depending on the interface language. English names are what this project uses everywhere — manifests, tools, documentation:

EnglishРусский (Console)Physically
KnobРучкаround ridged wheel, centre right
ScrollКолесоvertical wheel top left, like a mouse wheel
DialДискlarge flat disc, bottom left — the biggest control
TallДлиннаяtall button on the right side
SideБоковаяnarrow button on the left edge
TopПоперечнаяwide flat button across the top
ShortКороткаяsmall rounded button below Tall
D-padВверх / Вниз / Левый / Правыйfour small keys at the bottom
C1 / C2C1 / C2two round buttons, upper right
TourTourteardrop button, lower left

The two easiest to confuse are Scroll (Колесо) and Dial (Диск) — both round in Russian. Scroll is the little mouse-style wheel; Dial is the big flat disc.

SlotControlSlotControl
0Tall20–23Side + D-pad ↑↓←→
1Side24Tall ×2
2Top25Top + Tall
3Short26Tall + Short
4Knob27Side + Tall
5–8Tall/Short/Top/Side + Knob28Short ×2
9Scroll29Top + Short
10Scroll press30Side + Short
11–14Tall/Short/Top/Side + Scroll31Top ×2
15Dial32Side + Top
16–19D-pad ↑↓←→33Side ×2
34C136, 37Tall + C1, Tall + C2
35C243–46Top + D-pad ↑↓←→
42Tour55, 56Knob press, Dial press
57, 58Short + C1, Short + C2

Cross-check: <presetConf> lists the Prime Four combinations in the order [33,31,24,28,32,27,30,25,29,26], and Console's UI lists them in exactly that order.

Dial combinations

The Rotating Section exposes Prime Four combinations for the Knob and the Scroll, but not for the Dial — there is no Side+Dial row among the 47 slots above.

That is a limit of the standard section, not of the hardware. Console's Custom Section lets you build a combination by hand, and the vendor's own presets use it: across the corpus, custom entries live in slots 62, 72, 135, 149, 150, 153, 155, 158, listed in <presetConf> under Custom Section.html.

Every vendor example there is a button combination — flags clear, action A only, no second direction — so none of them shows what a Dial combination looks like. Until one is created in Console and exported, the translator cannot address Side+Dial, and it says so rather than picking a neighbouring slot.

To settle it: create the combination in Console's Custom Section, export, and diff against the same preset without it. The slot that changed is the answer.

9. Not decoded

are not.

A generator that emits kinds 0, 1 and 2 — any ASCII character, any special key, the mouse wheel, each with any combination of Ctrl, Alt and Shift, on any of the 47 slots, at a chosen turn speed and haptic strength — needs none of it.

4a. Mouse wheel — confirmed

Action kind 2 is the mouse wheel: code 4 up, code 5 down. Console renders such a row as "Колесико мыши вверх / вниз", and with a modifier byte set, as "ALT+Колесико мыши".

Code 0 also appears in vendor presets — Photoshop puts it on the Scroll — but a slot holding it reads as unassigned in Console. Not usable.

This is what makes pointer-driven adjustment work: a rotation sending the wheel moves whatever control the mouse is hovering, so Lightroom, Lumetri and Resolve sliders can be turned without any per-parameter shortcut existing.

4b. Turn speed and haptic strength

Both live in the flags byte of a rotation, one 2-bit field each. Across every vendor preset the byte only ever takes 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A — which is exactly two 2-bit fields and nothing else.

BitsMeaningValues
0x03turn speed — inferred0 normal, 1 slow, 2 slower
0x0Chaptic strength — confirmed0x00 off, 0x04 light, 0x08 normal

Haptic is confirmed by probe6: the indicator icon in Console's control list differs on exactly the two rows where the probe changed those bits, and nowhere else. Speed is inferred from the same corpus range and still wants a read-back from the per-rotation settings panel.

10. How this was established

The method is reproducible on any Elite:

  1. Export an empty preset from Console. Confirm a byte-identical round trip.
  2. Generate a probe that writes known values into chosen slots.
  3. Import it into Console as a new preset.
  4. Read the control list — Console names each row, which names the code.
  5. Re-export and diff — records identical means the value is stored verbatim.

Step 4 gives meaning, step 5 gives validity. Both are needed: a code can survive the round trip and still be one Console refuses to deliver.

Alle Projekte