The container format is CDF, which can be parsed using libucdf. The result is named binary streams. The structure of these binary streams is discussed in this document. bmil: 32 bit signed int in 1/10000 mil [tlb]: type+length encoded bin records 1 byte of record type 4 bytes of record length $length bytes of data [ilb]: ID+length encoded bin records 2 bytes of record ID 4 bytes of record length $length bytes of data [l4b]: length encoded bin records 4 byte of record length $length bytes of data Board6/Data: [l4b] Same text format as in the protel/ASCII file's RECORD=Board records Polygons6/Data: [l4b] Same text format as in the protel/ASCII file's RECORD=Polygon records Tracks6/Data: [tlb] record type: 0x04; typical record length: 45 @0, len=1: layer @2, len=1: keepout? @3, len=2: net (ID?) @5, len=2: polygon? @7, len=2: component (ID?) @13, len=4: x1 coord in bmil @17, len=4: y1 coord in bmil @21, len=4: x2 coord in bmil @25, len=4: y2 coord in bmil @29, len=4: width coord in bmil @36, len=1: unionindex @44, len=1: user routed Arcs6/Data: [tlb] record type: 0x01; typical record length: 56 @0, len=1: layer @3, len=2: net (ID?) @7, len=2: component (ID?) @13, len=4: x coord in bmil @17, len=4: y coord in bmil @21, len=4: radius in bmil @25, len=8: start angle (double?) @33, len=8: end angle (double?) @41, len=4: width bmil @48, len=1: unionindex @55, len=1: user routed Texts6/Data: [tlb] record type: 0x05; typical length: 230 @0, len=1: layer class @7, len=2: component (ID?), only if layer class is 2 or 5 @13, len=4: x coord in bmil @17, len=4: y coord in bmil @21, len=4: height @27, len=8: rotation (double) @35, len=1: is mirrored @36, len=4: stroke width bmil @40, len=1: is comment @41, len=1: is designator @46, len=64: font name @115, len=1: text ID? @226, len=2: text-specific layer ID @228, len=1: text-specific layer type: 0=copper, 3=non-copper [l4b] text string pascal string (first byte is net length) Figuring the layer is somewhat complicated: - for copper layers (@228=0), check offs (@226): - 1 is top copper - -1 is bottom copper - anything from 2 is intern copper, offset is offs-1 from top copper - for non-copper layers (@228=3), check offs (@226): 6 = top silk 7 = bottom silk 8 = top paste 9 = bottom paste 10 = top mask 11 = bottom mask Fills6/Data: TODO [tlb] record type: 0x06; typical record length: 46 @0, len=1: layer @3, len=2: net (ID?) @7, len=2: component (ID?) @13, len=4: x1 coord in bmil @17, len=4: y1 coord in bmil @21, len=4: x2 coord in bmil @25, len=4: y2 coord in bmil @29, len=8: rotation (double?) @38, len=8: dir2 ??? (double?) @45, len=1: user routed ? Vias6/Data: [tlb] record type: 0x03; typical record length: 209 @0, len=1: bbvia top end layer @1, len=1: bbvia bottom end layer @3, len=2: net (ID?) @13, len=4: x coord in bmil @17, len=4: y coord in bmil @21, len=4: copper dia @25, len=4: hole dia @40, len=1: CAGV, CCSV, CENV ? @70, len=1: unionindex Rules6/Data: [ilb] Same text format as in the protel/ASCII file's RECORD=Rule records Classes6/Data: [l4b] Same text format as in the protel/ASCII file's RECORD=Class records Nets6/Data: [l4b] Same text format as in the protel/ASCII file's RECORD=Net records Pads6/Data: 1 byte record type [l4b] name of the pad (pascal string) [l4b] block 1: unknown [l4b] block 2: unknown [l4b] block 3, length 120 @0, len=1: layer (+23 in the perl script) @1, len=1: altlayer? @3, len=2: net ID @7, len=2: component ID @13, len=4: X, bmil @17, len=4: Y, bmil @21, len=4: sx, bmil @25, len=4: sy, bmil @29, len=4: mid-sx, bmil @33, len=4: mid-sy, bmil @37, len=4: bottom-sx, bmil @41, len=4: bottom-sy, bmil @45, len=4: hole size @49, len=1: top type @50, len=1: mid type @51, len=1: bottom type @52, len=8: pad rotation, double? @60, len=1: plated @62, len=1: padmode 0=simple, 1=top-middle-bottom, 2=full-stack @68, len=4: CCW bmil: thermal geo (Conductor Width?) @72, len=1: CEN: thermal geo (number?) @74, len=4: CAG bmil: thermal geo (gap?) @78, len=4: CPR bmil: Plane thermal something @82, len=4: CPC bmil: Plane Clearance @86, len=4: CPE: paste expansion manual @90, len=4: CSE: mask expansion manual? @94, len=1: CPL? @101, len=1: CPEV: paste expansion mode @102, len=1: CSEV: mask expansion mode @106, len=8: hole rotation, double? (@121, len=1: hole type?) TODO: CSS would be the thermal style [l4b]* Read more blocks until a zero length block is read Record type: 1=arc 2=pstk 4=track (line) 6=fill types: 1=circle or round 2=rect 3=oval or octagon 4=(thermal) 6=(point) 7=(point) 9=roundrect Components6/Data [l4b] Same text format as in the protel/ASCII file's RECORD=Component records ComponentsBodies6/Data (3d model?) skip 23 bytes of header [l4b] Same text format as in the protel/ASCII file's RECORD=CompontentBody records at the end nskip=16 (??? perl line 405): read 4 bytes skiplen skip $nskip*$skiplen skip 4 more bytes for whatever go back and repeat (including skipping 23 bytes) Models/Data: 3d, don't care UniqueIDPrimitiveInformation/Data: 3d, don't care ?