KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pads_binary_parser.h
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 (C) 2026 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include <string>
23#include <vector>
24#include <map>
25#include <cstdint>
26
27#include <wx/string.h>
28
29#include "pads_parser.h"
30
31namespace PADS_IO
32{
33
51{
52public:
55
56 void Parse( const wxString& aFileName );
57
62 static bool IsBinaryPadsFile( const wxString& aFileName );
63
64 const PARAMETERS& GetParameters() const { return m_parameters; }
65 const std::vector<PART>& GetParts() const { return m_parts; }
66 const std::vector<NET>& GetNets() const { return m_nets; }
67 const std::vector<ROUTE>& GetRoutes() const { return m_routes; }
68 const std::vector<TEXT>& GetTexts() const { return m_texts; }
69 const std::vector<POUR>& GetPours() const { return m_pours; }
70 const std::vector<POLYLINE>& GetBoardOutlines() const { return m_boardOutlines; }
71 const std::map<std::string, PART_DECAL>& GetPartDecals() const { return m_decals; }
72 int GetLayerCount() const { return m_parameters.layer_count; }
73 bool IsBasicUnits() const { return true; }
74
75 std::vector<LAYER_INFO> GetLayerInfos() const;
76
77private:
78 static constexpr uint16_t MAGIC = 0xFF00;
79 static constexpr int HEADER_SIZE = 10;
80 static constexpr int FOOTER_SIZE = 46;
81 static constexpr int DIR_ENTRY_SIZE = 16;
82 static constexpr int32_t ANGLE_SCALE = 1800000;
83
84 struct DirEntry
85 {
86 int index = 0;
87 uint32_t count = 0;
88 uint32_t totalBytes = 0;
89 uint32_t dataOffset = 0;
90 uint32_t perItem = 0;
91 };
92
93 // Version helpers
94 bool isOldFormat() const { return m_version == 0x2021; }
95 int dirEntryCount() const;
96
97 // Low-level readers
98 uint8_t readU8( size_t aOffset ) const;
99 uint16_t readU16( size_t aOffset ) const;
100 uint32_t readU32( size_t aOffset ) const;
101 int32_t readI32( size_t aOffset ) const;
102 std::string readFixedString( size_t aOffset, size_t aMaxLen ) const;
103
104 // File structure parsing
105 void parseHeader();
106 void parseFooter();
107 void parseDirectory();
108
109 // Section data accessors
110 const uint8_t* sectionData( int aIndex ) const;
111 uint32_t sectionSize( int aIndex ) const;
112 const DirEntry* getSection( int aIndex ) const;
113
114 // Section parsers
115 void parseBoardSetup();
116 void parseStringPool();
117 void parsePartPlacements();
118 void parseSection19Parts();
119 void parsePadStacks();
120 void parsePartDecals();
121 void parseFootprintDefs();
122 void parseLineVertices();
123 void parseBoardOutline();
124 void parseNetNames();
125 void parseMetadataRegion();
126 void parseDftConfig( size_t aStart, size_t aEnd );
127 void parseRouteVertices();
128 void parseTextRecords();
129 void parseCopperPours();
130
131 // DFT format parsers
132 std::map<std::string, std::string> parseDftDotPadded( size_t aPos, size_t aEnd ) const;
133 std::map<std::string, std::string> parseDftNullSeparated( size_t aPos, size_t aEnd ) const;
134
135 // Net name helpers
136 std::string extractNetName( const uint8_t* aData, size_t aOffset ) const;
137 bool isValidNetName( const std::string& aName ) const;
138
139 // String pool resolver
140 std::string resolveString( uint32_t aByteOffset ) const;
141
142 // Coordinate conversion from binary absolute to PADS_IO design-relative units
143 double toBasicCoordX( int32_t aRawValue ) const;
144 double toBasicCoordY( int32_t aRawValue ) const;
145 double toBasicAngle( int32_t aRawAngle ) const;
146
147 // File data
148 std::vector<uint8_t> m_data;
149 uint16_t m_version = 0;
151
152 // Directory
153 std::vector<DirEntry> m_dirEntries;
154
155 // String pool (section 57)
156 std::vector<uint8_t> m_stringPoolBytes;
157
158 // Line vertex pool (section 12)
160 {
161 int32_t x = 0;
162 int32_t y = 0;
163 uint32_t extra = 0;
164 };
165 std::vector<LineVertex> m_lineVertices;
166
167 // Coordinate origin from DFT_CONFIGURATION
168 int32_t m_originX = 0;
169 int32_t m_originY = 0;
170 bool m_originFound = false;
171
172 // Pad stack cache indexed by section 4 record number
173 std::map<int, std::vector<PAD_STACK_LAYER>> m_padStackCache;
174
175 // Footprint type name -> decal name mapping from section 17
176 std::map<std::string, std::string> m_fpTypeToDecal;
177
178 // Route segment from section 24 linking to section 60 vertices
180 {
181 int32_t x1 = 0;
182 int32_t y1 = 0;
183 int32_t x2 = 0;
184 int32_t y2 = 0;
185 int32_t width = 0;
186 };
187 std::vector<RouteSegment> m_routeSegments;
188
189 // Via locations from section 59 (pin connection endpoints)
191 {
192 int32_t x = 0;
193 int32_t y = 0;
194 };
195 std::vector<ViaLocation> m_viaLocations;
196
197 // Output data (same structs as ASCII parser)
199 std::vector<PART> m_parts;
200 std::vector<NET> m_nets;
201 std::vector<ROUTE> m_routes;
202 std::vector<TEXT> m_texts;
203 std::vector<POUR> m_pours;
204 std::vector<POLYLINE> m_boardOutlines;
205 std::map<std::string, PART_DECAL> m_decals;
206};
207
208} // namespace PADS_IO
std::map< std::string, std::string > parseDftNullSeparated(size_t aPos, size_t aEnd) const
uint8_t readU8(size_t aOffset) const
double toBasicCoordY(int32_t aRawValue) const
const std::map< std::string, PART_DECAL > & GetPartDecals() const
std::vector< uint8_t > m_stringPoolBytes
std::vector< NET > m_nets
const std::vector< POLYLINE > & GetBoardOutlines() const
std::string readFixedString(size_t aOffset, size_t aMaxLen) const
bool isValidNetName(const std::string &aName) const
static constexpr int FOOTER_SIZE
std::vector< PART > m_parts
uint32_t readU32(size_t aOffset) const
const std::vector< POUR > & GetPours() const
std::map< std::string, std::string > parseDftDotPadded(size_t aPos, size_t aEnd) const
std::map< int, std::vector< PAD_STACK_LAYER > > m_padStackCache
const DirEntry * getSection(int aIndex) const
static constexpr int32_t ANGLE_SCALE
std::vector< POUR > m_pours
static bool IsBinaryPadsFile(const wxString &aFileName)
Check if a file appears to be a PADS binary PCB file.
std::map< std::string, PART_DECAL > m_decals
static constexpr int HEADER_SIZE
std::vector< uint8_t > m_data
std::vector< POLYLINE > m_boardOutlines
std::string resolveString(uint32_t aByteOffset) const
uint16_t readU16(size_t aOffset) const
uint32_t sectionSize(int aIndex) const
void parseDftConfig(size_t aStart, size_t aEnd)
const std::vector< TEXT > & GetTexts() const
const PARAMETERS & GetParameters() const
std::string extractNetName(const uint8_t *aData, size_t aOffset) const
void Parse(const wxString &aFileName)
const std::vector< PART > & GetParts() const
double toBasicCoordX(int32_t aRawValue) const
const uint8_t * sectionData(int aIndex) const
static constexpr int DIR_ENTRY_SIZE
std::vector< RouteSegment > m_routeSegments
const std::vector< NET > & GetNets() const
static constexpr uint16_t MAGIC
std::map< std::string, std::string > m_fpTypeToDecal
std::vector< ViaLocation > m_viaLocations
std::vector< DirEntry > m_dirEntries
const std::vector< ROUTE > & GetRoutes() const
std::vector< ROUTE > m_routes
std::vector< LineVertex > m_lineVertices
std::vector< TEXT > m_texts
int32_t readI32(size_t aOffset) const
double toBasicAngle(int32_t aRawAngle) const
std::vector< LAYER_INFO > GetLayerInfos() const