97/pcb/php-parser/Class_OrCad21.php
2025-02-22 18:50:46 +03:00

487 lines
16 KiB
PHP

<?
class orcad21
{
const HDR_SIZE = 48;
public $Error;
public $LastErrorStr;
public $ParseIndex;
public $FileName;
public $FileSize;
public $BUF = array();
public $HDR = array();
public $COMP = array();
public $TXT = array();
public $BRDPOI = array();
public $NETPOI = array();
public $VIA_STYLE = array();
public $PAD_STYLE = array();
public $TXT_STYLE = array();
public $PATTERN_STYLE = array();
public $MinPosX;
public $MinPosY;
public $MaxPosX;
public $MaxPosY;
// constructor
function __construct($fn = "")
{
$this->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;
}
}
}
}