nanobrush / docs /FORMATS.md
nmarshall's picture
formats: add txt conversion cli
18d65b9
|
Raw History Blame Contribute Delete
10.7 kB

Format map: source and converter evidence

Observed 2026-10-21. Baseline archive: Microbrush-3-wip-2016-03-10-c.zip, SHA-256 f972035324c1ede7e66771c398c035b9a355b569f68ddc30fdc4ed4ed0973982. Paths and line numbers below are relative to assets/references/extracted/2016-03-10-c/. Full member hashes are in the static source map and member inventory. The initial F15–F20 observations below are grammar/writer evidence. E02 now adds two MB3 DAT layouts and executed converter semantics; those reports supersede the explicit unknowns from E01.

F15 β€” Separate the format layers

Layer Evidence Current knowledge
Editable world text data/reference/Mb3 TXT grammar.txt Explicit world/brush/plane/Patch9 syntax; conversion semantics still unknown
Editable world binary saveWorldToFile / loadWorldFromFile, conversion BAT files MB3 DAT boundary and command directions are visible; Both converter layouts recovered; native editor conformance pending (F24/F25)
Imported map formats HL1 MAP, HL2 VMF, Q3 MAP grammars Accepted syntax is described; semantic preservation is limited
Export mesh DAT-to-wfobj BAT file Export-only route is shipped; Computed-geometry polygon/quad export recovered (F27)
Procedural model IXModel.ixpl + grid cursor.ixpl Source writer and opcode catalogue; different from MB3 DAT
Compiled plugin IXPL.exe cso in build BAT files Generated .plugin output; no compiled sample or layout recovered
Runtime config/localization config and key-config grammars; CFG/TXT resources Typed configuration plus a separate key-sequence language
Shader container three .shader files Stage-marked GLSL source with host-dependent uniforms/attributes

The conversion CLI is structurally Mb3 file formats.exe <input-type> <input-path> <output-type> <output-path> <log-path>. Four text formats convert to data/temp/load.mb3dat; saves start from data/temp/save.mb3dat, with an additional wfobj export. File placement and CLI shape are observed in the BAT files. Argument/exit/log/overwrite behavior is now reproduced in F26/F28; concurrent conversion safety remains unmeasured.

F16 β€” MB3 TXT grammar

Source: data/reference/Mb3 TXT grammar.txt:45–101.

  • world(...) starts with required computedFeatures true|false, then optional stringProperties[...], optional uvProperties[...], then zero or more brushes/patches. Their order is constrained by the grammar.
  • brush(...) contains zero or more planes syntactically. The host API says invalid brushes are discarded; syntactic acceptance does not establish geometric validity.
  • A plane(...) has three comma-separated three-component numeric tuples, repeated s <index> <string> entries, repeated uv <index> (<five numbers>, <five numbers>) entries, and an optional polygon vector list.
  • Each UV five-tuple is documented as an axis vector plus scale and shift-before-scaling. The grammar does not specify index bounds, property lookup failure or duplicate property behavior.
  • patch9(...) has four integers and an anchor vector list. If computed points are present, the normals list must also appear, in that order. The grammar imposes no anchor-list length consistency check.
  • Core-QuakeWorld.ixpl:17–21 separately requires odd anchor dimensions of at least three and at least two quads per tile per axis. These are API declaration constraints awaiting runtime verification.
  • The grammar accepts signed integers/floats and exponent forms, ordinary escaped strings, line/block comments and whitespace. Numeric precision and printing are not established.

E02 establishes that the plane's three tuples are P0/U/V (origin plus direction vectors), transferred directly by the converter; MAP point order and coordinate transforms are in F27. Selection sets, hidden state, undo history, view state and named worlds do not have explicit fields in this grammar. Their persistence behavior needs controlled save/load tests.

E02 supplies single-feature fixtures and actual serializer observations for P6.03. P6.02 edge cases and P5 editor numerical/geometry contracts remain open.

F17 β€” Imported dialects and loss boundary

Grammar Observed syntax Limits to preserve in the specification
HL1 MAP Entities require one or more string key/value pairs; brush sides use three points, texture name, two bracketed four-number axes, then three numbers This is the bracketed-axis style in the supplied grammar, not proof of every historical MAP dialect; no line-comment rule is listed
HL2 VMF Lowercase/underscore block names; recursive key/value and block trees; world/entity/solid/side/hidden specializations plus generic OtherStuff Recursive syntax can accept data which the converter later drops; quoted strings have no escape production here
Q3 MAP Entity key/value pairs, plane brushes, and patchDef2; anchors contain five numbers; a plane side has texture name plus eight numbers No brushDef/brushDef3 specialization appears; dimensions and patch counts are not constrained by the grammar

Sources: HL1 MAP grammar.txt:30–58, HL2 VMF grammar.txt:23–91, Q3 MAP grammar.txt:32–83.

data/strings/English/main menu.txt explicitly warns that unsupported features, including textures and entities, are dropped on import/save. Therefore grammar recognition is not a preservation guarantee. Native converters need a supported-subset/loss report, and original files must remain separate from rewritten output.

The Wavefront route is export only in the shipped menu and BAT scripts. F27 now maps material/UV/index/group policy through managed methods and generated fixtures. No original sample MAP/VMF/OBJ/MB3 file is in the recovered archives; E02 generated controlled samples separately.

F18 β€” IXModel writer contract and anomalies

Source: data/sources/include/IXPL/files/IXModel.ixpl.

  • writeHeader:65–70 sends literal I10MODEL to File::writeBytes, sends integer 20160119, and resets the next object ID to zero.
  • writeStrings:76–84 writes string count, then each string length and bytes. Whether string length counts bytes/code units is a runtime question.
  • CMD_*:93–185 declares 92 opcodes, numbered 0–91: node creation, graph/mesh references, attribute/index data, drawing/render state, custom data, animation, waits, and transforms.
  • Constructors allocate implicit IDs using next++. Mesh loading writes target mesh, counts, and data through File primitives. writeShorts:57–62 explicitly emits low then high bytes; this confirms the writer's 16-bit byte order only. It does not prove the host primitive width/endianness for every integer/float.
  • File.ixpl:59–70 writes a vec3 as three float operations in x/y/z order. The File interrupt namespace is distinct from the Core plugin namespace; do not merge their overlapping numeric IDs.
  • Older four builds write version 20111101 and declare 90 opcodes (0–89). The latest uses version 20160119 and 92 opcodes. A decoder needs version-specific tables, not one guessed layout.

Two source inconsistencies need targeted investigation before calling the writer authoritative:

  1. Many reset* functions accept nodeOrMesh but emit only the reset opcode, unlike their set* counterparts (230–261). The reader may have implicit targeting, or the writer may be incomplete. Do not invent a serialized target field.
  2. popFile:91 assigns file to the last stack entry before erasing that same entry. With nested pushes it appears to retain the popped handle rather than restore the previous handle. The single cursor generator does not demonstrate this case.

The cursor generator creates a line mesh from eight positions at Β±0.5 through IXModel. This supplies a small native replacement target once the actual output contract is validated. No .ixm sample is bundled.

F19 β€” Config and keymap languages

Source: config file grammar.txt:4–6, 62–118; key config grammar.txt:58–91.

The config contract explicitly says last entry wins unless a consumer treats repeated entries as an array, and a nested scope is equivalent to a dotted key. Types include bool, integer/long, float/double, strings, vector/color forms, and string tables. Ordinary and delimiter strings are distinct lexical forms. The text declares KeyVec4 but the Entry alternatives include KeyRGBA, not a standalone KeyVec4 branch: treat this as a grammar discrepancy until tested.

Do not apply last-wins globally. The task-priorities plugin collects repeated task.name/task.priority pairs in order and uses indexOf, giving the first matching name priority. This is a consumer-specific repeated-entry rule.

Keymaps bind comma-separated key sequences to named or numeric commands; leading minus unbinds. Unknown commands are documented as unbind operations. A terminal asterisk makes a binding nonmodal outside fly mode, with modifier combinations explicitly unsupported. Alt/control/shift modifier order is encoded as a, c, s. Normal operation and basic pass-through have different rules. This needs its own parser and interaction tests rather than translation to a flat shortcut dictionary.

F20 β€” Shader container observations

brushes.shader and patch9s.shader have @vertex330 and @fragment330 sections and a std140 matrix block; grid.shader has the same stage names and many grid/camera/snap uniforms. Host binding, compilation defines and complete matrix conventions remain unknown.

brushes.shader:92–106 uses face IDs 0/1/2/3 to distinguish unselected/main/set-1/set-2 visualization, including screen-space stripe patterns for auxiliary sets. patch9s.shader:35–41 calculates a lighting value but writes the normal-color expression instead; translating the unused lighting expression as the visible shader would be incorrect. brushes.shader:71–76 has a WA_ATI expression variant. Preserve observable output contracts separately from obsolete driver workarounds.

Native implementation extension β€” F30/F31

The strict TXT profile and native CLI implement the recovered TXT and DAT structures with explicit compatibility differences and guarded publication. Source grammars and legacy converter behavior above remain historical evidence; native formatting, Unicode handling, computed consistency and loss refusal follow the documented F30/F31 profile. E04 adds fixture/process tests without claiming native-editor conformance.