# CADKEY File Format Analysis

This document is the maintained evidence summary for the three CADKEY file generations examined in `/srv/cadkey-re`. It records confirmed layouts separately from active hypotheses. The Gen 2 section is the current reference for the reverse-engineering work.

## Evidence boundary

The Gen 2 results below come from byte-level analysis of the available PRT corpus, including the original 28-file geometry set and a larger 54-file structural audit. A field is marked **confirmed** only when its interpretation survives cross-file checks, record-size validation, and an independent geometry or SDK sanity check. FACE ownership, raw NURBS evaluation, and render-mesh semantics remain open.

## Gen 1 — v1.x, 1986–1988

- Magic: `04 00 04 00`
- Geometry: IEEE-754 single-precision floats
- Entity markers: `EE 11 XX`
- Parser: `/srv/cadkey-re/cadkey1_parser.py`
- Status: working DXF extraction for the sampled files

## Gen 2 — v6–98, approximately 1997–1998

### File structure

- Magic: `A5 0F F0 5A`
- Header: 32 bytes
- Records: heterogeneous binary database stream; records are interleaved in creation order
- Numeric encoding: little-endian unless explicitly noted
- Record traversal: read the u32 size at marker `+4`; never assume a fixed stride for the whole stream

The common outer wrapper for the decoded fixed records is 20 bytes:

```text
+0   marker
+4   u32 record size
+8   u32 record/entity ID
+12  u32 subtype
+16  u32 reserved
```

### Confirmed record classes in toyclip

| Marker | Interpretation | Count | Size |
|---|---|---:|---:|
| `02 02 00 ff` | COEDGE / half-edge, subtype 1 | 630 | 120 B |
| `02 03 00 ff` | Wireframe entity records | 177 | variable by record size |
| `02 04 00 ff` | FACE-like records, subtype 2 | 84 | 220 B |
| `02 05 00 ff` | Piecewise cubic 3D coefficient splines | 38 | 344–2,072 B |
| `0b 10 0f ff` | Logical-plane to entity mapping | 35 | 16 B |
| `0b 0a 0f ff`, `0b 0d 0f ff` | Polymorphic tail records; large blocks in some files | varies | 16 B or commonly 2,092 B |
| `0b 12 0f ff` | Embedded display/render data; ACIS-like chunks | 23 | 15,372 B in toyclip |
| `02 fc ff ff` | EOF/section terminator | 1 | variable |

Loose byte scans produce many false marker candidates inside payloads. A candidate is not a record until its size, subtype, and surrounding structure validate it.

### Common entity header (`02 03`, starts at marker +20)

| Offset | Size | Interpretation |
|---:|---:|---|
| +0 | 2 | Entity type u16 |
| +2, +4, +6 | 2 each | Constant flags, normally `0x0001` |
| +8 | 4 | Constant zero |
| +12 | 2 | Level |
| +14 | 2 | Constant zero |
| +16 | 4 | Previous ID in linked list |
| +20 | 4 | Next ID in linked list |
| +24 | 4 | Construction-plane ID |
| +28 | 4 | Display/sentinel field |
| +32 | 4 | Display/sentinel field |
| +36 | 4 | Tessellation hint; commonly 1, 5, or 12 |
| +40 | 2 | Pen/color; `0x42` is common |
| +44, +48 | 4 each | Constant zero in the audited entities |
| +52 | 48 | Six little-endian f64 geometry slots |

The `+20` base is essential. Interpreting offsets from the four-byte marker is the source of several earlier false conclusions.

### Entity types and geometry

| Type | Current interpretation | Geometry at +52 |
|---:|---|---|
| 1 | ARC1 / construction arc | `cx, cy, cz, radius, start_angle, sweep_angle` |
| 2 | Standard LINE | `x1, y1, z1, x2, y2, z2` |
| 3–14 | ARC/CIRCLE creation-tool variants | same six-double radial form |
| 15 | CONTROL POINT-like record | `x, y, ?, 0, 0, 0`; purpose unresolved |

The type code identifies the CADKEY creation tool, not necessarily a distinct storage layout. Type 1 is ARC1, not POINT or LINE. Type 2 is a true 3D LINE with six endpoint coordinates. Types 3–14 share the six-double radial representation; the exact creation-tool distinctions are not needed for DXF emission.

### COEDGE records (`02 02 00 ff`)

Subtype 1 records are 120 bytes. The fields that survive corpus checks are:

| Offset | Interpretation |
|---:|---|
| +36 | Previous record ID |
| +40 | Next record ID |
| +44 | Plane ID |
| +72 | Start vertex: 3 little-endian f64 values |
| +96 | End vertex: 3 little-endian f64 values |

The previous/next values are shared-ID database links, not universal curve or face references. Components formed by them are plane-homogeneous in the 54-file audit. In toyclip, reciprocal links and plane grouping are strong evidence that the records organize plane-local components. The vertex payload is the ground truth for the topology-derived 3D wireframe export.

### FACE-like records (`02 04 00 ff`)

Subtype 2 records are 220 bytes. They share the common header and begin their payload at +72 with u32 `0x000f0003`, followed by 18 little-endian f64 values in the audited samples.

Confirmed:

- fixed record size and subtype;
- common previous/next/plane header fields;
- payload size and numeric layout;
- no direct proof that the six apparent 3-vectors are polygon vertices, poses, or boundary references.

Withdrawn interpretations:

- `+36/+40` as direct COEDGE or patch references;
- `+32` as a patch index;
- a complete FACE→COEDGE→CURVE→PATCH graph inferred from those offsets.

### Cubic spline records (`02 05 00 ff`)

For record size `S`, define `N = (S - 152) / 48`. The validated layout is:

| Offset | Contents |
|---:|---|
| +72 | Six f64 values: record start/end points |
| +120 | Eight u16 values: `(256, 6N, 1, N/2, 0, 0, 0, 0)` |
| +136 | Two f64 values: `(0.0, 1.0)` |
| +152 | `N` groups of six f64 values |

The coefficient payload is `N/2` cubic segments, 12 doubles per segment, stored coordinate-major in descending-power order:

```text
x3 x2 x1 x0  y3 y2 y1 y0  z3 z2 z1 z0
```

The CADKEY SDK independently describes `CK_SPL_C3` as a 3D coefficient spline with `num × 12` doubles. Across 5,589 audited records, evaluation reproduces the header endpoints and all 19,000 adjacent joins tested. This is a confirmed cubic coefficient decode, not a NURBS surface decode.

### Plane mapping and profile filtering

`0b 10 0f ff` records map logical plane IDs to entity IDs. Plane geometry is derived from record content; the mapping is not itself a plane-coordinate table.

For toyclip:

| Plane | Role |
|---:|---|
| 2599 | Profile; 8 wireframe lines / 16 COEDGE edges |
| 2600 | Hinge/conic geometry |
| 2605 | Construction/projection geometry |
| 2606 | Construction/projection geometry |
| 0 | World/auxiliary geometry |

Filtering by plane is required to separate useful profile geometry from projection/construction clutter.

### Embedded `0b 12` data

Toyclip contains 23 chunks of 15,372 bytes. Readable fragments include `ACIS BinaryFile`, `body`, `lump`, `shell`, `face`, `loop`, `coedge`, `edge`, `vertex`, `curve`, `surface`, `nubs`, `intcurve`, and `fmesh`.

This is the leading candidate for higher-level B-rep ownership, but the mapping between ACIS object IDs and CADKEY `02 02` / `02 04` / `02 05` IDs has not been proven. Integer alignment alone is not evidence of cross-format identity.

## What is still unknown

1. **FACE ownership and boundary linkage.** The FACE payload is decoded structurally, but its semantic relationship to COEDGE loops, cubic curves, and surfaces is not established.
2. **Raw NURBS control points and evaluation.** `0b 0a`/`0b 0d` blocks contain delimiter and knot-like patterns, but control-point fields, degree, weights, and surface parameterization remain unproven.
3. **ACIS-to-CADKEY identity mapping.** Embedded ACIS-like objects may contain the missing ownership graph; object-schema parsing and cross-ID correlation are unfinished.
4. **TYPE15 purpose.** The coordinate triples may be anchors or control points, but no cross-file semantic proof exists.
5. **Additional `0b` records.** `0b 00`, `0b 01`, `0b 02`, `0b 0c`, and `0b 0e` are index/directory-like records with incomplete interpretations.
6. **Render mesh format.** The large display-data regions are precomputed viewport artifacts and remain low priority until exact surface ownership is solved.

## Current deliverables

- Parser: `/srv/cadkey-re/gen2_parser.py`
- 2D DXF: `gen2_parser.py input.prt --dxf output.dxf`
- 3D COEDGE wireframe: `gen2_parser.py input.prt --3d output_3d.dxf`
- Topology-derived spline DXF: `gen2_parser.py input.prt --nurbs output_nurbs.dxf`
- Blog reference copy: `/root/lngnckr.tech/public/blog-assets/prt-gen2-format.md`
- Main research post: `/root/lngnckr.tech/src/content/blog/cadkey-reverse-engineering.md`
- Part 2: `/root/lngnckr.tech/src/content/blog/cadkey-reverse-engineering-part-2.md`

## Gen 3 — Workshop V20, 2002+

- Magic: `D0 CF 11 E0 A1 B1 1A E1` (OLE2 compound document)
- Geometry: ACIS SAB streams inside OLE2
- Status: extraction remains separate from the Gen 2 investigation
