FileName = $fn; $this->Load($this->FileName); $this->MinPosX = 1000000; $this->MinPosY = 1000000; $this->MaxPosX = 0; $this->MaxPosY = 0; } // private private function hex($int) { $h = dechex($int); if (strlen($h)%2 != 0) { $h = str_pad($h, strlen($h) + 1, '0', STR_PAD_LEFT); } return strtoupper($h)."h"; } private function GetStr($strl, $descr = "") { $result['ofs'] = $this->ParseIndex; for ($i=0; $i<$strl; $i++) { if ($i > 0) $result['buf'] .= " "; $result['buf'] .= $this->hex(ord($this->BUF[$this->ParseIndex + $i])); if ((ord($this->BUF[$this->ParseIndex + $i]) > 31) and (ord($this->BUF[$this->ParseIndex + $i]) < 128)) { $result['v'] .= $this->BUF[$this->ParseIndex + $i]; } } $result['descr'] = $descr; $this->ParseIndex += $strl; return $result; } private function GetByte($descr = "") { $result['ofs'] = $this->ParseIndex; $result['buf'] = $this->hex(ord($this->BUF[$this->ParseIndex])); $result['v'] = ord($this->BUF[$this->ParseIndex]); $result['descr'] = $descr; $this->ParseIndex++; return $result; } private function GetWord($descr = "") { $result['ofs'] = $this->ParseIndex; $result['buf'] = $this->hex(ord($this->BUF[$this->ParseIndex])) . " " . $this->hex(ord($this->BUF[$this->ParseIndex + 1])); $result['v'] = ord($this->BUF[$this->ParseIndex]) + 256 * ord($this->BUF[$this->ParseIndex + 1]); $result['descr'] = $descr; $this->ParseIndex += 2; return $result; } private function ParseHeader() { $this->Error = 0; $this->LastErrorStr = ""; $this->ParseIndex = 0; $this->HDR['file_name'] = $this->GetStr(8); $this->HDR['file_name']['v'] = trim($this->HDR['file_name']['v']); $this->HDR['unk1'] = $this->GetWord(); $this->HDR['comp_count'] = $this->GetWord(); $this->HDR['unk3'] = $this->GetWord(); $this->HDR['unk4'] = $this->GetWord(); $this->HDR['unk5'] = $this->GetWord(); $this->HDR['unk6'] = $this->GetWord(); $this->HDR['unk7'] = $this->GetWord(); $this->HDR['unk8'] = $this->GetWord(); $this->HDR['unk9'] = $this->GetWord(); $this->HDR['unk10'] = $this->GetWord(); $this->HDR['unk11'] = $this->GetWord(); $this->HDR['texts_ofs'] = $this->GetWord(); $this->HDR['texts_ofs_real']['v'] = $this->HDR['texts_ofs']['v'] * 2 + self::HDR_SIZE; $this->HDR['texts_size'] = $this->GetWord(); $this->HDR['brd_points_count'] = $this->GetWord(); $this->HDR['net_points_count'] = $this->GetWord(); $this->HDR['unk16'] = $this->GetWord(); $this->HDR['unk17'] = $this->GetWord(); $this->HDR['unk18'] = $this->GetWord(); $this->HDR['file_ext'] = $this->GetStr(4); $this->HDR['file_ext']['v'] = trim($this->HDR['file_ext']['v']); // check range if ($this->ParseIndex > $this->FileSize) { $this->Error = 1; $this->LastErrorStr = "ParseIndex is out of FileSize during ParseHeader()"; return false; } return true; } private function ParseComponent($i) { $this->COMP[$i]['ofs'] = $this->ParseIndex; $this->COMP[$i]['timestamp'] = $this->GetStr(8); $this->COMP[$i]['unk1'] = $this->GetByte(); $this->COMP[$i]['rotate'] = $this->GetByte("0-0, 1-90, 2-180, 3-270"); $this->COMP[$i]['layer'] = $this->GetByte("0-bot, 1-top"); $this->COMP[$i]['unk3'] = $this->GetByte(); $this->COMP[$i]['unk4'] = $this->GetWord(); $this->COMP[$i]['unk5'] = $this->GetWord(); $this->COMP[$i]['unk6'] = $this->GetWord(); $this->COMP[$i]['unk7'] = $this->GetWord(); $this->COMP[$i]['pos_y'] = $this->GetWord(); $this->COMP[$i]['pos_x'] = $this->GetWord(); $this->COMP[$i]['unk10'] = $this->GetWord(); $this->COMP[$i]['unk11'] = $this->GetWord(); $this->COMP[$i]['lines_ofs'] = $this->GetWord(); $this->COMP[$i]['names_ofs'] = $this->GetWord(); $this->COMP[$i]['pads_ofs'] = $this->GetWord(); $this->COMP[$i]['next_ofs1'] = $this->GetWord(); $this->COMP[$i]['next_ofs2'] = $this->GetWord(); $this->COMP[$i]['pattern'] = $this->GetStr(8); $this->COMP[$i]['pattern']['v'] = trim($this->COMP[$i]['pattern']['v']); $this->COMP[$i]['next_ofs3'] = $this->GetWord(); $this->COMP[$i]['lines_count']['v'] = ($this->COMP[$i]['names_ofs']['v'] - $this->COMP[$i]['lines_ofs']['v']) / 6; $this->COMP[$i]['names_count']['v'] = ($this->COMP[$i]['pads_ofs']['v'] - $this->COMP[$i]['names_ofs']['v']) / 24; $this->COMP[$i]['pads_count']['v'] = ($this->COMP[$i]['next_ofs1']['v'] - $this->COMP[$i]['pads_ofs']['v']) / 24; // lines for($j=1; $j<=$this->COMP[$i]['lines_count']['v']; $j++) { $this->COMP[$i]['line'.$j.'_flags'] = $this->GetWord(); $this->COMP[$i]['line'.$j.'_pos_y'] = $this->GetWord(); $this->COMP[$i]['line'.$j.'_pos_x'] = $this->GetWord(); } // names for($j=1; $j<=$this->COMP[$i]['names_count']['v']; $j++) { $this->COMP[$i]['name'.$j.'_unk1'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_unk2'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_str'] = $this->GetStr(8); $this->COMP[$i]['name'.$j.'_str']['v'] = trim($this->COMP[$i]['name'.$j.'_str']['v']); $this->COMP[$i]['name'.$j.'_unk4'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_unk5'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_unk6'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_unk7'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_pos_y'] = $this->GetWord(); $this->COMP[$i]['name'.$j.'_pos_x'] = $this->GetWord(); } // pads for($j=1; $j<=$this->COMP[$i]['pads_count']['v']; $j++) { $this->COMP[$i]['pad'.$j.'_ofs_real']['v'] = $this->ParseIndex; $this->COMP[$i]['pad'.$j.'_ofs']['v'] = round($this->ParseIndex / 2) - 24; $this->COMP[$i]['pad'.$j.'_des'] = $this->GetStr(4); $this->COMP[$i]['pad'.$j.'_des']['v'] = trim($this->COMP[$i]['pad'.$j.'_des']['v']); $this->COMP[$i]['pad'.$j.'_net'] = $this->GetStr(8); $this->COMP[$i]['pad'.$j.'_net']['v'] = trim($this->COMP[$i]['pad'.$j.'_net']['v']); $this->COMP[$i]['pad'.$j.'_shape'] = $this->GetByte("1-circ, 2-rect"); $this->COMP[$i]['pad'.$j.'_width'] = $this->GetWord(); $this->COMP[$i]['pad'.$j.'_height'] = $this->GetWord(); $this->COMP[$i]['pad'.$j.'_rotate'] = $this->GetByte("0-0, 1-90, 2-180, 3-270"); $this->COMP[$i]['pad'.$j.'_flags'] = $this->GetByte("1-smd, 3-plated"); $this->COMP[$i]['pad'.$j.'_hole_dia'] = $this->GetByte(); $this->COMP[$i]['pad'.$j.'_pos_y'] = $this->GetWord(); $this->COMP[$i]['pad'.$j.'_pos_x'] = $this->GetWord(); } } private function ParseComponents() { $this->Error = 0; $this->LastErrorStr = ""; // 'comp_count' = 'comp_count_real' + 1, // so needs check 'ParseIndex' does not over 'texts_ofs_real' for($i=1; $i<=$this->HDR['comp_count']['v']; $i++) { $this->ParseComponent($i); // check components size if($this->ParseIndex >= $this->HDR['texts_ofs_real']['v']) { $this->HDR['comp_count_real']['v'] = $i; return true; } // check range if ($this->ParseIndex > $this->FileSize) { $this->Error = 1; $this->LastErrorStr = "ParseIndex is out of FileSize during ParseComponents(), i=" . $i; return false; } } return false; } private function ParseTexts() { $this->Error = 0; $this->LastErrorStr = ""; $i = 1; while (1) { $this->TXT[$i]['ofs'] = $this->ParseIndex; $this->TXT[$i]['unk1'] = $this->GetWord(); $this->TXT[$i]['unk2'] = $this->GetWord(); $this->TXT[$i]['unk3'] = $this->GetWord(); $this->TXT[$i]['unk4'] = $this->GetWord(); $this->TXT[$i]['unk5'] = $this->GetWord(); $this->TXT[$i]['unk6'] = $this->GetWord(); $this->TXT[$i]['len'] = $this->GetByte(); $this->TXT[$i]['size_h'] = $this->GetWord(); $this->TXT[$i]['size_v'] = $this->GetWord(); $this->TXT[$i]['rotate'] = $this->GetByte("0-0, 1-90, 2-180, 3-270"); $this->TXT[$i]['layer'] = $this->GetByte("0-bot, 1-top"); $this->TXT[$i]['flags'] = $this->GetByte("(HL), H-mirrored(0-yes)"); $this->TXT[$i]['pos_y'] = $this->GetWord(); $this->TXT[$i]['pos_x'] = $this->GetWord(); $this->TXT[$i]['str'] = $this->GetStr($this->TXT[$i]['len']['v']); // check texts size if ($this->ParseIndex >= ($this->HDR['texts_ofs_real']['v'] + $this->HDR['texts_size']['v'])) break; // check range if ($this->ParseIndex > $this->FileSize) { $this->Error = 1; $this->LastErrorStr = "ParseIndex is out of FileSize during ParseTexts(), i=" . $i; return false; } $i++; } $this->HDR['texts_count']['v'] = $i; return true; } private function ParseBoardPoints() { $this->Error = 0; $this->LastErrorStr = ""; for($i=1; $i<=$this->HDR['brd_points_count']['v']; $i++) { $this->BRDPOI[$i]['ofs'] = $this->ParseIndex; $this->BRDPOI[$i]['flags'] = $this->GetByte(); $this->BRDPOI[$i]['unk2'] = $this->GetByte(); $this->BRDPOI[$i]['pos_y'] = $this->GetWord(); $this->BRDPOI[$i]['pos_x'] = $this->GetWord(); $this->BRDPOI[$i]['unk5'] = $this->GetByte(); $this->BRDPOI[$i]['unk6'] = $this->GetByte(); if ($this->BRDPOI[$i]['pos_x']['v'] < $this->MinPosX) $this->MinPosX = $this->BRDPOI[$i]['pos_x']['v']; if ($this->BRDPOI[$i]['pos_y']['v'] < $this->MinPosY) $this->MinPosY = $this->BRDPOI[$i]['pos_y']['v']; if ($this->BRDPOI[$i]['pos_x']['v'] > $this->MaxPosX) $this->MaxPosX = $this->BRDPOI[$i]['pos_x']['v']; if ($this->BRDPOI[$i]['pos_y']['v'] > $this->MaxPosY) $this->MaxPosY = $this->BRDPOI[$i]['pos_y']['v']; // check range if ($this->ParseIndex > $this->FileSize) { $this->Error = 1; $this->LastErrorStr = "ParseIndex is out of FileSize during ParseBoardPoints(), i=" . $i; return false; } } return true; } private function ParseNetPoints() { $this->Error = 0; $this->LastErrorStr = ""; for($i=1; $i<=$this->HDR['net_points_count']['v']; $i++) { $this->NETPOI[$i]['ofs'] = $this->ParseIndex; $this->NETPOI[$i]['flags'] = $this->GetByte("(1x)h-layer, (x1)h-head"); $this->NETPOI[$i]['size'] = $this->GetByte(); $this->NETPOI[$i]['pos_y'] = $this->GetWord(); $this->NETPOI[$i]['pos_x'] = $this->GetWord(); $this->NETPOI[$i]['net_id'] = $this->GetWord(); // check range if ($this->ParseIndex > $this->FileSize) { $this->Error = 1; $this->LastErrorStr = "ParseIndex is out of FileSize during ParseNetPoints(), i=" . $i; return false; } } return true; } // public public function Load() { $this->ParseIndex = 0; $this->BUF = file_get_contents($this->FileName); $this->FileSize = filesize($this->FileName); if (!$this->FileSize) { $this->FileSize = 0; } } public function Parse() { $this->ParseHeader(); $this->ParseComponents(); $this->ParseTexts(); $this->ParseBoardPoints(); $this->ParseNetPoints(); if ($this->FileSize == $this->ParseIndex) return true; return false; } public function ChangePos($dx, $dy, $reverse_x, $reverse_y, $swap = 0) { // component for($i=1; $i<=sizeof($this->COMP); $i++) { if (!$this->COMP[$i]['ofs']) continue; $this->COMP[$i]['pos_x']['v'] += $dx; $this->COMP[$i]['pos_y']['v'] += $dy; if ($reverse_x) $this->COMP[$i]['pos_x']['v'] = $reverse_x - $this->COMP[$i]['pos_x']['v']; if ($reverse_y) $this->COMP[$i]['pos_y']['v'] = $reverse_y - $this->COMP[$i]['pos_y']['v']; if ($swap) { $tmp = $this->COMP[$i]['pos_x']['v']; $this->COMP[$i]['pos_x']['v'] = $this->COMP[$i]['pos_y']['v']; $this->COMP[$i]['pos_y']['v'] = $tmp; } // lines for($j=1; $j<=$this->COMP[$i]['lines_count']['v']; $j++) { $this->COMP[$i]['line'.$j.'_pos_y']['v'] += $dy; $this->COMP[$i]['line'.$j.'_pos_x']['v'] += $dx; if ($reverse_x) $this->COMP[$i]['line'.$j.'_pos_x']['v'] = $reverse_x - $this->COMP[$i]['line'.$j.'_pos_x']['v']; if ($reverse_y) $this->COMP[$i]['line'.$j.'_pos_y']['v'] = $reverse_y - $this->COMP[$i]['line'.$j.'_pos_y']['v']; if ($swap) { $tmp = $this->COMP[$i]['line'.$j.'_pos_x']['v']; $this->COMP[$i]['line'.$j.'_pos_x']['v'] = $this->COMP[$i]['line'.$j.'_pos_y']['v']; $this->COMP[$i]['line'.$j.'_pos_y']['v'] = $tmp; } } // names for($j=1; $j<=$this->COMP[$i]['names_count']['v']; $j++) { $this->COMP[$i]['name'.$j.'_pos_y']['v'] += $dy; $this->COMP[$i]['name'.$j.'_pos_x']['v'] += $dx; if ($reverse_x) $this->COMP[$i]['name'.$j.'_pos_x']['v'] = $reverse_x - $this->COMP[$i]['name'.$j.'_pos_x']['v']; if ($reverse_y) $this->COMP[$i]['name'.$j.'_pos_y']['v'] = $reverse_y - $this->COMP[$i]['name'.$j.'_pos_y']['v']; if ($swap) { $tmp = $this->COMP[$i]['name'.$j.'_pos_x']['v']; $this->COMP[$i]['name'.$j.'_pos_x']['v'] = $this->COMP[$i]['name'.$j.'_pos_y']['v']; $this->COMP[$i]['name'.$j.'_pos_y']['v'] = $tmp; } } // pads for($j=1; $j<=$this->COMP[$i]['pads_count']['v']; $j++) { $this->COMP[$i]['pad'.$j.'_pos_y']['v'] += $dy; $this->COMP[$i]['pad'.$j.'_pos_x']['v'] += $dx; if ($reverse_x) $this->COMP[$i]['pad'.$j.'_pos_x']['v'] = $reverse_x - $this->COMP[$i]['pad'.$j.'_pos_x']['v']; if ($reverse_y) $this->COMP[$i]['pad'.$j.'_pos_y']['v'] = $reverse_y - $this->COMP[$i]['pad'.$j.'_pos_y']['v']; if ($swap) { $tmp = $this->COMP[$i]['pad'.$j.'_pos_x']['v']; $this->COMP[$i]['pad'.$j.'_pos_x']['v'] = $this->COMP[$i]['pad'.$j.'_pos_y']['v']; $this->COMP[$i]['pad'.$j.'_pos_y']['v'] = $tmp; $tmp = $this->COMP[$i]['pad'.$j.'_width']['v']; $this->COMP[$i]['pad'.$j.'_width']['v'] = $this->COMP[$i]['pad'.$j.'_height']['v']; $this->COMP[$i]['pad'.$j.'_height']['v'] = $tmp; } } } // text for($i=1; $i<=sizeof($this->TXT); $i++) { $this->TXT[$i]['pos_y']['v'] += $dy; $this->TXT[$i]['pos_x']['v'] += $dx; if ($reverse_x) $this->TXT[$i]['pos_x']['v'] = $reverse_x - $this->TXT[$i]['pos_x']['v']; if ($reverse_y) $this->TXT[$i]['pos_y']['v'] = $reverse_y - $this->TXT[$i]['pos_y']['v']; if ($swap) { $tmp = $this->TXT[$i]['pos_x']['v']; $this->TXT[$i]['pos_x']['v'] = $this->TXT[$i]['pos_y']['v']; $this->TXT[$i]['pos_y']['v'] = $tmp; } } // board points for($i=1; $i<=$this->HDR['brd_points_count']['v']; $i++) { $this->BRDPOI[$i]['pos_y']['v'] += $dy; $this->BRDPOI[$i]['pos_x']['v'] += $dx; if ($reverse_x) $this->BRDPOI[$i]['pos_x']['v'] = $reverse_x - $this->BRDPOI[$i]['pos_x']['v']; if ($reverse_y) $this->BRDPOI[$i]['pos_y']['v'] = $reverse_y - $this->BRDPOI[$i]['pos_y']['v']; if ($swap) { $tmp = $this->BRDPOI[$i]['pos_y']['v']; $this->BRDPOI[$i]['pos_y']['v'] = $this->BRDPOI[$i]['pos_x']['v']; $this->BRDPOI[$i]['pos_x']['v'] = $tmp; } } // net pointes for($i=1; $i<=$this->HDR['net_points_count']['v']; $i++) { $this->NETPOI[$i]['pos_y']['v'] += $dy; $this->NETPOI[$i]['pos_x']['v'] += $dx; if ($reverse_x) $this->NETPOI[$i]['pos_x']['v'] = $reverse_x - $this->NETPOI[$i]['pos_x']['v']; if ($reverse_y) $this->NETPOI[$i]['pos_y']['v'] = $reverse_y - $this->NETPOI[$i]['pos_y']['v']; if ($swap) { $tmp = $this->NETPOI[$i]['pos_x']['v']; $this->NETPOI[$i]['pos_x']['v'] = $this->NETPOI[$i]['pos_y']['v']; $this->NETPOI[$i]['pos_y']['v'] = $tmp; } } } }