KiCad PCB EDA Suite
Loading...
Searching...
No Matches
orcad_structures.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * Based on the dsn2kicad reference implementation and on OrCAD file format
7 * documentation from the OpenOrCadParser project (MIT licensed).
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
24
25#include <limits>
26#include <memory>
27#include <utility>
28#include <variant>
29
30#include <ki_exception.h>
31
33
34
35ORCAD_STRUCT_READER::ORCAD_STRUCT_READER( ORCAD_STREAM& aStream, const std::vector<std::string>* aStrings,
36 ORCAD_WARN_FN aWarn ) :
37 m_stream( aStream ),
38 m_strings( aStrings ),
39 m_warn( std::move( aWarn ) )
40{
41}
42
43
44void ORCAD_STRUCT_READER::Warn( const wxString& aMsg ) const
45{
46 if( m_warn )
47 m_warn( aMsg );
48}
49
50
51std::optional<size_t> OrcadLongPrefixCount( int aTypeId )
52{
53 switch( aTypeId )
54 {
55 case 9:
56 case 66:
57 case 67:
58 case 68:
59 case 69:
60 case 82:
61 case 91: return 1;
62
63 case 10:
64 case 16:
65 case 17:
66 case 20:
67 case 21:
68 case 26:
69 case 27:
70 case 29:
71 case 32:
72 case 37:
73 case 38:
74 case 39:
75 case 48:
76 case 49:
77 case 55:
78 case 56:
79 case 57:
80 case 58:
81 case 59:
82 case 60:
83 case 61:
84 case 62:
85 case 88:
86 case 89: return 2;
87
88 case 2:
89 case 6:
90 case 12:
91 case 23:
92 case 31:
93 case 65:
94 case 77: return 3;
95
96 case 13:
97 case 33:
98 case 34:
99 case 35:
100 case 64:
101 case 75:
102 case 76: return 4;
103
104 case 24: return 5;
105
106 default: return std::nullopt;
107 }
108}
109
110
111ORCAD_PREFIXES ORCAD_STRUCT_READER::ReadPrefixes( int aExpectedType, size_t aEnclosingEnd, size_t aLongPrefixCount )
112{
113 ORCAD_PREFIXES pfx;
114 pfx.start = m_stream.GetOffset();
115
116 int typeId = m_stream.PeekU8();
117
118 if( typeId < 0 )
119 THROW_IO_ERROR( wxS( "OrCAD structure: missing structure type" ) );
120
121 if( aExpectedType >= 0 && typeId != aExpectedType )
122 THROW_IO_ERRORF( wxS( "OrCAD structure: expected type %d, got %d" ), aExpectedType, typeId );
123
124 std::optional<size_t> longCount = aLongPrefixCount == ORCAD_STREAM::npos
125 ? OrcadLongPrefixCount( typeId )
126 : std::optional<size_t>( aLongPrefixCount );
127
128 if( !longCount )
129 THROW_IO_ERRORF( wxS( "OrCAD structure: unregistered structure type %d" ), typeId );
130
131 if( *longCount == 0 )
132 THROW_IO_ERROR( wxS( "OrCAD structure: long prefix count is zero" ) );
133
134 size_t bound = aEnclosingEnd == ORCAD_STREAM::npos ? m_stream.Size() : aEnclosingEnd;
135
136 if( bound > m_stream.Size() )
137 THROW_IO_ERROR( wxS( "OrCAD structure: enclosing bound exceeds stream" ) );
138
139 for( size_t i = 0; i < *longCount; ++i )
140 {
141 int prefixType = m_stream.ReadU8();
142
143 if( prefixType != typeId )
144 THROW_IO_ERRORF( wxS( "OrCAD structure: prefix type mismatch %d != %d" ), prefixType, typeId );
145
146 pfx.bodyLens.push_back( m_stream.ReadU32() );
147
148 if( m_stream.ReadU32() != 0 )
149 THROW_IO_ERROR( wxS( "OrCAD structure: long prefix pad not zero" ) );
150 }
151
152 if( m_stream.ReadU8() != typeId )
153 THROW_IO_ERROR( wxS( "OrCAD structure: short prefix type mismatch" ) );
154
155 // Short prefix i16 pair count, then (u32 nameIdx, u32 valueIdx) pairs. Negative count = no pairs.
156 int16_t propertyCount = m_stream.ReadI16();
157
158 for( int i = 0; i < propertyCount; ++i )
159 {
160 uint32_t nameIdx = m_stream.ReadU32();
161 uint32_t valueIdx = m_stream.ReadU32();
162 pfx.props.emplace_back( nameIdx, valueIdx );
163 }
164
165 m_stream.ExpectPreamble( wxS( "structure preamble" ) );
166 uint32_t trail = m_stream.ReadU32();
167 m_stream.Skip( trail );
168 pfx.bodyStart = m_stream.GetOffset();
169 pfx.typeId = typeId;
170
171 for( size_t i = 0; i < pfx.bodyLens.size(); ++i )
172 {
173 // Body length counts bytes after own 9-byte record; outermost bounds whole structure.
174 size_t headerEnd = pfx.start + 9 * i + 9;
175
176 if( pfx.bodyLens[i] > std::numeric_limits<size_t>::max() - headerEnd )
177 THROW_IO_ERROR( wxS( "OrCAD structure: structure stop overflow" ) );
178
179 size_t stop = headerEnd + pfx.bodyLens[i];
180
181 if( stop < pfx.bodyStart || stop > bound )
182 THROW_IO_ERRORF( wxS( "OrCAD structure: stop 0x%zx outside the enclosing bound" ), stop );
183
184 pfx.stops.push_back( stop );
185 }
186
187 pfx.end = pfx.stops.front();
188
189 return pfx;
190}
191
192
193std::string ORCAD_STRUCT_READER::Resolve( uint32_t aIndex ) const
194{
195 if( m_strings && aIndex < m_strings->size() )
196 return ( *m_strings )[aIndex];
197
198 return std::string();
199}
200
201
202std::map<std::string, std::string> ORCAD_STRUCT_READER::PropsDict( const ORCAD_PREFIXES& aPrefixes ) const
203{
204 std::map<std::string, std::string> out;
205
206 for( const std::pair<uint32_t, uint32_t>& prop : aPrefixes.props )
207 {
208 std::string name = Resolve( prop.first );
209
210 if( !name.empty() )
211 out[name] = Resolve( prop.second );
212 }
213
214 return out;
215}
216
217
218void ORCAD_STRUCT_READER::SkipStructure( const ORCAD_PREFIXES& aPrefixes, const wxString& aWhat )
219{
220 if( aPrefixes.end != 0 && aPrefixes.end >= m_stream.GetOffset() )
221 {
222 m_stream.Seek( aPrefixes.end );
223 }
224 else
225 {
226 THROW_IO_ERRORF( wxS( "OrCAD structure: cannot skip structure %s" ), aWhat );
227 }
228}
229
230
232{
233 ORCAD_STREAM::NEST_GUARD guard( m_stream, wxS( "structure" ) );
234
235 size_t start = m_stream.GetOffset();
237
239 result.typeId = pfx.typeId;
240
241 try
242 {
244
245 switch( pfx.typeId )
246 {
248 case ORCAD_ST_WIRE_BUS: result.record = OrcadReadWire( *this, pfx ); break;
249
250 case ORCAD_ST_ALIAS: result.record = OrcadReadAlias( *this, pfx ); break;
251
252 case ORCAD_ST_SYMBOL_DISPLAY_PROP: result.record = OrcadReadDisplayProp( *this, pfx ); break;
253
254 case ORCAD_ST_PLACED_INSTANCE: result.record = OrcadReadPlacedInstance( *this, pfx ); break;
255
256 case ORCAD_ST_PORT: result.record = OrcadReadPort( *this, pfx ); break;
257
258 case ORCAD_ST_GLOBAL:
269 case ORCAD_ST_GRAPHIC_OLE_INST: result.record = OrcadReadGraphicInst( *this, pfx ); break;
270
271 case ORCAD_ST_TITLEBLOCK: result.record = OrcadReadTitleBlock( *this, pfx ); break;
272
273 case ORCAD_ST_ERC_OBJECT: result.record = OrcadReadErcObject( *this, pfx ); break;
274
275 case ORCAD_ST_BUS_ENTRY: result.record = OrcadReadBusEntry( *this, pfx ); break;
276
277 case ORCAD_ST_T0X10:
278 case ORCAD_ST_T0X11: result.record = OrcadReadPinInst( *this, pfx ); break;
279
280 case ORCAD_ST_STH_IN_PAGES0: result.record = OrcadReadSthInPages0( *this, pfx ); break;
281
282 case ORCAD_ST_DRAWN_INSTANCE: result.record = OrcadReadDrawnInstance( *this, pfx ); break;
283
284 default: SkipStructure( pfx, wxString::Format( wxS( "type %d" ), pfx.typeId ) ); break;
285 }
286 }
287 catch( const IO_ERROR& e )
288 {
289 // Recover via prefix offsets on body-parse failure; one bad record must not abort page/cache parse.
290 if( pfx.end != 0 && pfx.end > start )
291 {
292 Warn( wxString::Format( wxS( "OrCAD structure type %d at 0x%zx: %s; skipped" ), pfx.typeId, start,
293 e.What() ) );
294 m_stream.Seek( pfx.end );
295 result.record = std::monostate();
296 return result;
297 }
298
299 throw;
300 }
301
302 return result;
303}
304
305
306// -- per-type body readers ----------------------------------------------------------------
307
308
310{
311 ORCAD_STREAM& ds = aReader.Stream();
313
314 prop.nameIdx = ds.ReadU32();
315 prop.name = aReader.Resolve( prop.nameIdx );
316 prop.x = ds.ReadI16();
317 prop.y = ds.ReadI16();
318
319 // u16 bits 0..13 = 1-based font index, bits 14..15 = quarter turns.
320 uint16_t rotFont = ds.ReadU16();
321 prop.fontIdx = rotFont & 0x3FFF;
322 prop.rotation = ( rotFont >> 14 ) & 0x3;
323
324 prop.color = ds.ReadU8();
325 prop.dispMode = ds.ReadU16();
326 ds.ExpectByte( 0x00, wxS( "display prop tail" ) );
327
328 return prop;
329}
330
331
333{
334 ORCAD_STREAM& ds = aReader.Stream();
335 ORCAD_ALIAS alias;
336
337 alias.x = ds.ReadI32();
338 alias.y = ds.ReadI32();
339 alias.color = static_cast<int>( ds.ReadU32() );
340 alias.rotation = static_cast<int>( ds.ReadU32() );
341 alias.fontIdx = static_cast<int>( ds.ReadU32() );
342 alias.name = ds.ReadLzt();
343
344 return alias;
345}
346
347
349{
350 ORCAD_STREAM& ds = aReader.Stream();
351 ORCAD_WIRE wire;
352
353 wire.dbId = ds.ReadU32();
354 wire.id = ds.ReadU32();
355 wire.color = static_cast<int>( ds.ReadU32() );
356 wire.x1 = ds.ReadI32();
357 wire.y1 = ds.ReadI32();
358 wire.x2 = ds.ReadI32();
359 wire.y2 = ds.ReadI32();
360 ds.Skip( 1 );
361
362 uint16_t aliasCount = ds.ReadU16();
363
364 for( int i = 0; i < aliasCount; i++ )
365 {
366 ORCAD_READ_RESULT r = aReader.ReadStructure();
367
368 if( ORCAD_ALIAS* alias = std::get_if<ORCAD_ALIAS>( &r.record ) )
369 wire.aliases.push_back( std::move( *alias ) );
370 }
371
372 uint16_t propCount = ds.ReadU16();
373
374 for( int i = 0; i < propCount; i++ )
375 aReader.ReadStructure();
376
377 wire.lineWidth = static_cast<int>( ds.ReadU32() );
378 wire.lineStyle = static_cast<int>( ds.ReadU32() );
379
380 wire.isBus = ( aPrefixes.typeId == ORCAD_ST_WIRE_BUS );
381
382 return wire;
383}
384
385
387{
388 ORCAD_STREAM& ds = aReader.Stream();
390
391 ds.ReadU32();
392 uint32_t headerWordB = ds.ReadU32();
393 inst.pkgName = ds.ReadLzt();
394 inst.sourceLibrary = aReader.Resolve( headerWordB );
395 inst.dbId = ds.ReadU32();
396
397 // Placed bbox stored y-first; includes displayed text.
398 int by1 = ds.ReadI16();
399 int bx1 = ds.ReadI16();
400 int by2 = ds.ReadI16();
401 int bx2 = ds.ReadI16();
402 inst.bbox.x1 = bx1;
403 inst.bbox.y1 = by1;
404 inst.bbox.x2 = bx2;
405 inst.bbox.y2 = by2;
406
407 inst.x = ds.ReadI16();
408 inst.y = ds.ReadI16();
409 inst.color = ds.ReadU8();
410
411 // Orientation byte bits 0..1 = quarter turns, bit 2 = mirror.
412 uint8_t orientation = ds.ReadU8();
413 inst.rotation = orientation & 0x3;
414 inst.mirror = ( orientation & 0x4 ) != 0;
415
416 inst.partIndex = ds.ReadU8();
417 inst.partByte = ds.ReadU8();
418
419 inst.displayProps = OrcadReadDisplayPropList( aReader );
420
421 ds.Skip( 1 );
422 inst.reference = ds.ReadLzt();
423
424 // Part Value = u32 string-table index after reference; next 10 bytes unknown.
425 uint32_t valueIdx = ds.ReadU32();
426 inst.value = aReader.Resolve( valueIdx );
427 ds.Skip( 10 );
428
429 uint16_t pinCount = ds.ReadU16();
430
431 for( int i = 0; i < pinCount; i++ )
432 {
433 ORCAD_READ_RESULT r = aReader.ReadStructure();
434
435 if( ORCAD_PIN_INST* pin = std::get_if<ORCAD_PIN_INST>( &r.record ) )
436 inst.pins.push_back( std::move( *pin ) );
437 }
438
439 inst.sourcePackage = ds.ReadLzt();
440 inst.unitIndex = ds.ReadU16();
441
442 inst.props = aReader.PropsDict( aPrefixes );
443
444 return inst;
445}
446
447
449{
450 ORCAD_STREAM& ds = aReader.Stream();
452
453 uint32_t nameIdx = ds.ReadU32(); // logical net/port name string index (ports)
454 ds.ReadU32(); // source library string index
455 inst.name = ds.ReadLzt();
456 inst.dbId = ds.ReadU32();
457
458 // Anchor and bbox stored interleaved: y, x, y2, x2, x1, y1.
459 inst.y = ds.ReadI16();
460 inst.x = ds.ReadI16();
461 int y2 = ds.ReadI16();
462 int x2 = ds.ReadI16();
463 int x1 = ds.ReadI16();
464 int y1 = ds.ReadI16();
465 inst.bbox.x1 = x1;
466 inst.bbox.y1 = y1;
467 inst.bbox.x2 = x2;
468 inst.bbox.y2 = y2;
469
470 inst.color = ds.ReadU8();
471
472 // Orientation byte bits 0..1 = quarter turns, bit 2 = mirror.
473 uint8_t orientation = ds.ReadU8();
474 inst.rotation = orientation & 0x3;
475 inst.mirror = ( orientation & 0x4 ) != 0;
476
477 ds.Skip( 2 ); // structId, unknown
478
479 inst.displayProps = OrcadReadDisplayPropList( aReader );
480
481 // Flag 0x02 = one nested structure, usually SthInPages0 symbol body with drawable primitives.
482 uint8_t flag = ds.ReadU8();
483
484 if( flag == 0x02 )
485 {
486 ORCAD_READ_RESULT nested = aReader.ReadStructure();
487
488 if( ORCAD_SYMBOL_DEF* def = std::get_if<ORCAD_SYMBOL_DEF>( &nested.record ) )
489 inst.nested = std::make_unique<ORCAD_SYMBOL_DEF>( std::move( *def ) );
490 }
491
492 inst.typeId = aPrefixes.typeId;
493 inst.props = aReader.PropsDict( aPrefixes );
494 inst.logicalName = aReader.Resolve( nameIdx );
495
496 return inst;
497}
498
499
501{
502 ORCAD_GRAPHIC_INST inst = OrcadReadGraphicInst( aReader, aPrefixes );
503 aReader.Stream().Skip( 9 );
504
505 return inst;
506}
507
508
510{
511 ORCAD_GRAPHIC_INST inst = OrcadReadGraphicInst( aReader, aPrefixes );
512 aReader.Stream().Skip( 12 );
513
514 return inst;
515}
516
517
519{
520 ORCAD_GRAPHIC_INST inst = OrcadReadGraphicInst( aReader, aPrefixes );
521
522 aReader.Stream().ReadLzt();
523 aReader.Stream().ReadLzt();
524 aReader.Stream().ReadLzt();
525
526 return inst;
527}
528
529
531{
532 ORCAD_STREAM& ds = aReader.Stream();
534
535 pin.pinIndex = ds.ReadI16();
536 pin.x = ds.ReadI16();
537 pin.y = ds.ReadI16();
538 pin.wordA = ds.ReadU32();
539 pin.wordB = ds.ReadU32();
540 pin.displayProps = OrcadReadDisplayPropList( aReader );
541
542 // Remaining body bytes padding; record ends at outer stop.
543 if( aPrefixes.end != 0 && aPrefixes.end > ds.GetOffset() )
544 ds.Seek( aPrefixes.end );
545
546 return pin;
547}
548
549
551{
552 ORCAD_BUS_ENTRY entry;
553
554 entry.color = static_cast<int>( aStream.ReadU32() );
555 entry.x1 = aStream.ReadI32();
556 entry.y1 = aStream.ReadI32();
557 entry.x2 = aStream.ReadI32();
558 entry.y2 = aStream.ReadI32();
559 aStream.Skip( 8 );
560
561 return entry;
562}
563
564
566{
567 return OrcadReadBusEntryBody( aReader.Stream() );
568}
569
570
571std::vector<ORCAD_DISPLAY_PROP> OrcadReadDisplayPropList( ORCAD_STRUCT_READER& aReader )
572{
573 std::vector<ORCAD_DISPLAY_PROP> out;
574
575 uint16_t count = aReader.Stream().ReadU16();
576
577 for( int i = 0; i < count; i++ )
578 {
579 ORCAD_READ_RESULT r = aReader.ReadStructure();
580
581 if( ORCAD_DISPLAY_PROP* prop = std::get_if<ORCAD_DISPLAY_PROP>( &r.record ) )
582 out.push_back( std::move( *prop ) );
583 }
584
585 return out;
586}
587
588
590{
591 ORCAD_NET_GROUP net;
592
593 aStream.Skip( 9 );
594 net.id = aStream.ReadU32();
595 net.name = aStream.ReadLzt();
596 aStream.ReadU32();
597 aStream.ReadU32(); // color
598 aStream.ReadU32(); // line style
599 aStream.ReadU32(); // line width
600
601 return net;
602}
603
604
606{
607 ORCAD_NET_GROUP net = OrcadReadT0x34Raw( aStream );
608
609 uint16_t count = aStream.ReadU16();
610
611 for( uint16_t i = 0; i < count; ++i )
612 net.members.push_back( aStream.ReadU32() );
613
614 return net;
615}
const char * name
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Limit reads to one record so a malformed body cannot consume the next record.
Bound shared parser recursion; entering a level above MAX_NESTING throws IO_ERROR.
The caller owns the buffer.
uint8_t ReadU8()
– scalars (little-endian, bounds-checked, throw IO_ERROR on overrun) ----—
static constexpr size_t npos
Generic invalid offset sentinel.
size_t GetOffset() const
uint16_t ReadU16()
void Skip(size_t aCount)
Advance the cursor; throws IO_ERROR when aCount exceeds the remaining bytes.
std::string ReadLzt()
– strings ----------------------------------------------------------------—
void Seek(size_t aOffset)
Set the absolute cursor position; throws IO_ERROR when aOffset exceeds Size().
int32_t ReadI32()
void ExpectByte(uint8_t aValue, const wxString &aWhat)
Consume one byte and require the given value.
uint32_t ReadU32()
int16_t ReadI16()
ReadStructure can recover from a body error when the prefix supplies a valid end offset.
std::map< std::string, std::string > PropsDict(const ORCAD_PREFIXES &aPrefixes) const
Resolve the short-prefix (nameIdx, valueIdx) pairs; empty names are dropped.
void SkipStructure(const ORCAD_PREFIXES &aPrefixes, const wxString &aWhat)
Throws IO_ERROR if the end is unknown or behind the cursor.
ORCAD_PREFIXES ReadPrefixes(int aExpectedType=-1, size_t aEnclosingEnd=ORCAD_STREAM::npos, size_t aLongPrefixCount=ORCAD_STREAM::npos)
aLongPrefixCount overrides the type depth; aEnclosingEnd bounds all stops.
ORCAD_STREAM & Stream()
void Warn(const wxString &aMsg) const
Report a recoverable problem to the warning sink (no-op when none was given).
std::string Resolve(uint32_t aIndex) const
String-table lookup; returns "" for out-of-range indices.
ORCAD_STRUCT_READER(ORCAD_STREAM &aStream, const std::vector< std::string > *aStrings=nullptr, ORCAD_WARN_FN aWarn=nullptr)
ORCAD_READ_RESULT ReadStructure()
Skip unknown bodies.
const std::vector< std::string > * m_strings
ORCAD_STREAM & m_stream
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
STL namespace.
ORCAD_DRAWN_INSTANCE OrcadReadDrawnInstance(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_SYMBOL_DEF OrcadReadSthInPages0(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
std::function< void(const wxString &aMsg)> ORCAD_WARN_FN
Coordinates use DBU with Y down.
@ ORCAD_ST_STH_IN_PAGES0
nested symbol body inside Graphic*Inst
@ ORCAD_ST_T0X10
scalar pin instance (absolute pos)
@ ORCAD_ST_WIRE_SCALAR
@ ORCAD_ST_PLACED_INSTANCE
@ ORCAD_ST_GRAPHIC_ARC_INST
@ ORCAD_ST_DRAWN_INSTANCE
hierarchical block instance
@ ORCAD_ST_TITLEBLOCK
@ ORCAD_ST_GLOBAL
placed power symbol
@ ORCAD_ST_GRAPHIC_BITMAP_INST
@ ORCAD_ST_OFFPAGE_CONNECTOR
@ ORCAD_ST_PORT
@ ORCAD_ST_GRAPHIC_LINE_INST
@ ORCAD_ST_GRAPHIC_COMMENT_TEXT_INST
@ ORCAD_ST_GRAPHIC_ELLIPSE_INST
@ ORCAD_ST_GRAPHIC_BOX_INST
@ ORCAD_ST_ERC_OBJECT
saved design-rule-check marker
@ ORCAD_ST_GRAPHIC_POLYLINE_INST
@ ORCAD_ST_GRAPHIC_BEZIER_INST
@ ORCAD_ST_GRAPHIC_POLYGON_INST
@ ORCAD_ST_ALIAS
net alias attached to a wire
@ ORCAD_ST_WIRE_BUS
@ ORCAD_ST_SYMBOL_DISPLAY_PROP
@ ORCAD_ST_T0X11
bus pin instance (absolute pos)
@ ORCAD_ST_BUS_ENTRY
@ ORCAD_ST_GRAPHIC_OLE_INST
ORCAD_WIRE OrcadReadWire(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Types 20 (wire) and 21 (bus); isBus is set from the prefix type.
ORCAD_PLACED_INSTANCE OrcadReadPlacedInstance(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_GRAPHIC_INST OrcadReadPort(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 9-byte trailer.
std::vector< ORCAD_DISPLAY_PROP > OrcadReadDisplayPropList(ORCAD_STRUCT_READER &aReader)
Keep only display properties that ReadStructure decodes.
ORCAD_NET_GROUP OrcadReadT0x34Raw(ORCAD_STREAM &aStream)
T0x34 records have no prefixes; consume their fixed layout to preserve alignment.
ORCAD_PIN_INST OrcadReadPinInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_DISPLAY_PROP OrcadReadDisplayProp(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &)
Body readers start after the prefixes.
ORCAD_BUS_ENTRY OrcadReadBusEntryBody(ORCAD_STREAM &aStream)
ORCAD_GRAPHIC_INST OrcadReadErcObject(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by 3 lzt strings.
ORCAD_ALIAS OrcadReadAlias(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &)
ORCAD_GRAPHIC_INST OrcadReadTitleBlock(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 12-byte trailer.
ORCAD_BUS_ENTRY OrcadReadBusEntry(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &)
ORCAD_GRAPHIC_INST OrcadReadGraphicInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Common body of Port/Global/OffPageConnector/TitleBlock/ERCObject/Graphic*Inst.
std::optional< size_t > OrcadLongPrefixCount(int aTypeId)
Registered number of long prefixes for a modern framed structure type.
ORCAD_NET_GROUP OrcadReadT0x35Raw(ORCAD_STREAM &aStream)
T0x35 = the T0x34 raw layout followed by u16 n and 4 * n bytes.
ORCAD_WIRE OrcadReadWire(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Types 20 (wire) and 21 (bus); isBus is set from the prefix type.
ORCAD_PLACED_INSTANCE OrcadReadPlacedInstance(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_GRAPHIC_INST OrcadReadPort(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 9-byte trailer.
ORCAD_PIN_INST OrcadReadPinInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_DISPLAY_PROP OrcadReadDisplayProp(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Body readers start after the prefixes.
ORCAD_GRAPHIC_INST OrcadReadErcObject(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by 3 lzt strings.
ORCAD_GRAPHIC_INST OrcadReadTitleBlock(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 12-byte trailer.
ORCAD_GRAPHIC_INST OrcadReadGraphicInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Common body of Port/Global/OffPageConnector/TitleBlock/ERCObject/Graphic*Inst.
ORCAD_BUS_ENTRY OrcadReadBusEntry(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_ALIAS OrcadReadAlias(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
std::optional< size_t > OrcadLongPrefixCount(int aTypeId)
Registered number of long prefixes for a modern framed structure type.
The owning wire defines the connection.
std::string name
int rotation
0..3 quarter turns
int y1
int color
int x2
int y2
int x1
Display positions use symbol coordinates; rotFont combines the font index and quarter turns.
int fontIdx
1-based into ORCAD_LIBRARY_INFO::fonts; 0 = default
int rotation
0..3 quarter turns
std::string name
resolved property name (empty when index invalid)
Free graphics use nested primitive coordinates.
std::unique_ptr< ORCAD_SYMBOL_DEF > nested
SthInPages0 body, else nullptr.
std::map< std::string, std::string > props
int rotation
0..3 quarter turns
std::string name
cache symbol name
std::vector< ORCAD_DISPLAY_PROP > displayProps
std::string logicalName
ports: resolved net/port name
int typeId
ORCAD_ST value.
std::vector< uint32_t > members
std::string name
Pin positions are absolute page connection points.
The placed box includes displayed text.
std::string sourcePackage
package base name
std::vector< ORCAD_DISPLAY_PROP > displayProps
ORCAD_BBOX bbox
placed box, page DBU
int rotation
0..3 quarter turns
uint16_t unitIndex
zero-based package device index
std::map< std::string, std::string > props
short-prefix property pairs
bool mirror
orientation bit 2
std::string sourceLibrary
source library path from the placed-instance header
std::string value
resolved Part Value
std::vector< ORCAD_PIN_INST > pins
successfully parsed T0x10 records
Prefix lengths supply structure bounds.
std::vector< size_t > stops
< (from the outermost long prefix); < 0 when unknown
int typeId
ORCAD_ST value (u8 in the stream)
size_t bodyStart
offset right after the preamble trail
std::vector< std::pair< uint32_t, uint32_t > > props
short prefix (nameIdx, valueIdx) pairs
std::vector< uint32_t > bodyLens
one per long prefix, outermost first
size_t end
offset right after the whole structure
size_t start
stream offset where the chain began
ORCAD_RECORD_VARIANT record
The bounding box occupies the final eight bytes before the next prefix stop.
The wire ID refers to the page net table.
uint32_t id
uint32_t dbId
bool isBus
true for structure type 21
std::vector< ORCAD_ALIAS > aliases
KIBIS_PIN * pin
wxString result
Test unit parsing edge cases and error handling.