替换原本ole.js为cfb.js
parent
d3e33c2f4a
commit
436d87c64c
113
altium_sch.html
113
altium_sch.html
|
@ -7,6 +7,8 @@
|
||||||
<script type="text/javascript" src="altium_sch_document.js"></script>
|
<script type="text/javascript" src="altium_sch_document.js"></script>
|
||||||
<script type="text/javascript" src="altium_sch_renderer.js"></script>
|
<script type="text/javascript" src="altium_sch_renderer.js"></script>
|
||||||
<script type="text/javascript" src="test_schdoc.js"></script>
|
<script type="text/javascript" src="test_schdoc.js"></script>
|
||||||
|
<script type="text/javascript" src="cfb.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div><input type="file" id="altium-file"></input></div>
|
<div><input type="file" id="altium-file"></input></div>
|
||||||
|
@ -14,10 +16,11 @@
|
||||||
<div><pre id="results"></pre></div>
|
<div><pre id="results"></pre></div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
renderSchematic(getTestFile());
|
// renderSchematic(getTestFile());
|
||||||
|
|
||||||
function readSchematicFile(e)
|
function readSchematicFile(e)
|
||||||
{
|
{
|
||||||
|
console.log(e)
|
||||||
let file = e.target.files[0];
|
let file = e.target.files[0];
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
|
@ -27,20 +30,118 @@ function readSchematicFile(e)
|
||||||
reader.onload = function(e)
|
reader.onload = function(e)
|
||||||
{
|
{
|
||||||
let contents = e.target.result;
|
let contents = e.target.result;
|
||||||
renderSchematic(contents);
|
let cfbs = window.cfb
|
||||||
|
console.log(contents)
|
||||||
|
var dec = new TextDecoder("utf-8");
|
||||||
|
|
||||||
|
let arr = Array.prototype.slice.call(new Uint8Array(contents ));
|
||||||
|
var ss = cfbs.read(arr,{type: 'binary'});
|
||||||
|
console.log(ss)
|
||||||
|
var schdat = cfbs.find(ss, 'FileHeader');
|
||||||
|
var data = schdat.content;
|
||||||
|
let arrayBuffer = new Uint8Array(data).buffer;
|
||||||
|
console.log(dec.decode(arrayBuffer))
|
||||||
|
renderSchematic(arrayBuffer);
|
||||||
};
|
};
|
||||||
reader.readAsArrayBuffer(file);
|
reader.readAsArrayBuffer(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('altium-file').addEventListener('change', readSchematicFile, false);
|
document.getElementById('altium-file').addEventListener('change', readSchematicFile, false);
|
||||||
|
|
||||||
|
// ArrayBuffer转16进制字符串
|
||||||
|
function ab2hex(buffer) {
|
||||||
|
const hexArr = Array.prototype.map.call(
|
||||||
|
new Uint8Array(buffer),
|
||||||
|
function (bit) {
|
||||||
|
return (('00' + bit.toString(16)).slice(-2) + " ")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return hexArr.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
function doSave(value, type, name) {
|
||||||
|
|
||||||
|
var blob;
|
||||||
|
|
||||||
|
if (typeof window.Blob == "function") {
|
||||||
|
|
||||||
|
blob = new Blob([value], {
|
||||||
|
|
||||||
|
type: type
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var BlobBuilder = window.BlobBuilder || window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder;
|
||||||
|
|
||||||
|
var bb = new BlobBuilder();
|
||||||
|
|
||||||
|
bb.append(value);
|
||||||
|
|
||||||
|
blob = bb.getBlob(type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var URL = window.URL || window.webkitURL;
|
||||||
|
|
||||||
|
var bloburl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
var anchor = document.createElement("a");
|
||||||
|
|
||||||
|
if ('download' in anchor) {
|
||||||
|
|
||||||
|
anchor.style.visibility = "hidden";
|
||||||
|
|
||||||
|
anchor.href = bloburl;
|
||||||
|
|
||||||
|
anchor.download = name;
|
||||||
|
|
||||||
|
document.body.appendChild(anchor);
|
||||||
|
|
||||||
|
var evt = document.createEvent("MouseEvents");
|
||||||
|
|
||||||
|
evt.initEvent("click", true, true);
|
||||||
|
|
||||||
|
anchor.dispatchEvent(evt);
|
||||||
|
|
||||||
|
document.body.removeChild(anchor);
|
||||||
|
|
||||||
|
} else if (navigator.msSaveBlob) {
|
||||||
|
|
||||||
|
navigator.msSaveBlob(blob, name);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
location.href = bloburl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrayToAscii(strArray) {
|
||||||
|
return strArray.flatMap(str => {
|
||||||
|
// 將每個字符串轉換為字符數組
|
||||||
|
return Array.from(str, char => {
|
||||||
|
// 取得字符的Unicode編碼
|
||||||
|
const charCode = char.charCodeAt(0);
|
||||||
|
// 判斷是否為ASCII字符(0-127)
|
||||||
|
if (charCode <= 127) {
|
||||||
|
// 如果是ASCII字符,返回對應的ASCII值
|
||||||
|
return charCode;
|
||||||
|
} else {
|
||||||
|
// 如果不是ASCII字符,返回null或undefined(根據需要處理)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderSchematic(data)
|
function renderSchematic(data)
|
||||||
{
|
{
|
||||||
let canvas = document.getElementById("canvas");
|
let canvas = document.getElementById("canvas");
|
||||||
let ole = new OLE(data);
|
// console.log(new TextDecoder('utf-8').decod*****************e(fhData))
|
||||||
let fhEntry = ole.directory_entries.find((de) => de.name == "FileHeader");
|
let altiumDocument = new AltiumDocument(data);
|
||||||
let fhData = fhEntry.read_all();
|
|
||||||
let altiumDocument = new AltiumDocument(fhData);
|
|
||||||
window.altiumDocument = altiumDocument;
|
window.altiumDocument = altiumDocument;
|
||||||
let renderer = new AltiumSchematicRenderer(canvas, altiumDocument);
|
let renderer = new AltiumSchematicRenderer(canvas, altiumDocument);
|
||||||
renderer.render();
|
renderer.render();
|
||||||
|
|
|
@ -45,17 +45,21 @@ class AltiumRecord
|
||||||
constructor(stream, index)
|
constructor(stream, index)
|
||||||
{
|
{
|
||||||
this.record_index = index;
|
this.record_index = index;
|
||||||
this.stream = stream;
|
this.stream = new U8Stream(stream);
|
||||||
this.position = stream.u8stream_position;
|
this.position = stream.u8stream_position;
|
||||||
this.payload_length = stream.read_u16_le();
|
this.payload_length = stream.read_u16_le();
|
||||||
this.padding = stream.read_u8();
|
this.padding = stream.read_u8();
|
||||||
if (this.padding != 0)
|
if (this.padding != 0)
|
||||||
console.warn("Padding byte on record index " + index.toString() + " was non-zero.");
|
console.warn("Padding byte on record index " + index.toString() + " was non-zero.");
|
||||||
this.record_type = stream.read_u8();
|
this.record_type = stream.read_u8();
|
||||||
|
console.warn(this.position)
|
||||||
if (this.record_type != 0)
|
if (this.record_type != 0)
|
||||||
throw new Error("Invalid record type.");
|
throw new Error("Invalid record type.");
|
||||||
this.data = stream.read(this.payload_length);
|
this.data = stream.read(this.payload_length);
|
||||||
this.record_id = -1;
|
this.record_id = -1;
|
||||||
|
console.warn(this.data)
|
||||||
|
console.log(new TextDecoder('utf-8').decode(this.data))
|
||||||
|
|
||||||
if (this.data.length > "|RECORD=255|".length)
|
if (this.data.length > "|RECORD=255|".length)
|
||||||
{
|
{
|
||||||
// check if this starts with |RECORD=
|
// check if this starts with |RECORD=
|
||||||
|
@ -679,11 +683,12 @@ class AltiumImplementationParameterList extends AltiumObject
|
||||||
|
|
||||||
class AltiumDocument
|
class AltiumDocument
|
||||||
{
|
{
|
||||||
constructor(stream)
|
constructor(streams)
|
||||||
{
|
{
|
||||||
this.stream = stream;
|
this.stream = new U8Stream(streams);
|
||||||
this.records = [];
|
this.records = [];
|
||||||
let index = -1; // header comes first, so give it an index of -1
|
let index = -1; // header comes first, so give it an index of -1
|
||||||
|
console.log(this.stream.length)
|
||||||
while (this.stream.u8stream_position < this.stream.length)
|
while (this.stream.u8stream_position < this.stream.length)
|
||||||
{
|
{
|
||||||
this.records.push(new AltiumRecord(this.stream, index));
|
this.records.push(new AltiumRecord(this.stream, index));
|
||||||
|
|
|
@ -150,7 +150,6 @@ class AltiumSchematicRenderer
|
||||||
}
|
}
|
||||||
results.innerText = bom.join("\n");
|
results.innerText = bom.join("\n");
|
||||||
|
|
||||||
|
|
||||||
for (let obj of doc.objects.filter((o) => o instanceof AltiumWire))
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumWire))
|
||||||
{
|
{
|
||||||
if (!this.#shouldShow(obj)) continue;
|
if (!this.#shouldShow(obj)) continue;
|
||||||
|
|
189
ole.js
189
ole.js
|
@ -1,189 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
altium.js OLE parser
|
|
||||||
|
|
||||||
Copyright (c) 2022 Graham Sutherland
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
class OLE
|
|
||||||
{
|
|
||||||
static get ExpectedMagicNumber() { return new Uint8Array([ 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 ]) }
|
|
||||||
static get ExpectedMajorVersion() { return 0x0003; }
|
|
||||||
static get ExpectedMinorVersion() { return 0x003E; }
|
|
||||||
static get ExpectedByteOrder() { return 0xFFFE; }
|
|
||||||
static get ExpectedSectorShift() { return 0x0009; }
|
|
||||||
static get ExpectedMiniSectorShift() { return 0x0006; }
|
|
||||||
static get ExpectedNumberOfDirectorySectors() { return 0; }
|
|
||||||
|
|
||||||
constructor(fileData)
|
|
||||||
{
|
|
||||||
this.stream = new U8Stream(fileData);
|
|
||||||
|
|
||||||
if (fileData.length < 76)
|
|
||||||
{
|
|
||||||
throw new Error("File is too small to be a valid OLE compound document.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.header = {};
|
|
||||||
|
|
||||||
this.header.signature = this.stream.read(8);
|
|
||||||
if (!this.header.signature.compare_to(OLE.ExpectedMagicNumber))
|
|
||||||
{
|
|
||||||
throw new Error("File does not start with the correct OLE header signature.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.header.clsid = this.stream.read(16);
|
|
||||||
if (!this.header.clsid.every((b) => b === 0))
|
|
||||||
{
|
|
||||||
console.warn("OLE header CLSID was not set to all zeroes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.header.minor_version = this.stream.read_u16_le();
|
|
||||||
this.header.major_version = this.stream.read_u16_le();
|
|
||||||
if (this.header.major_version != OLE.ExpectedMajorVersion || this.header.minor_version != OLE.ExpectedMinorVersion)
|
|
||||||
{
|
|
||||||
throw new Error("OLE header does not have expected OLE version number.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.header.byte_order = this.stream.read_u16_le();
|
|
||||||
if (this.header.byte_order != OLE.ExpectedByteOrder)
|
|
||||||
{
|
|
||||||
throw new Error("OLE header does not have expected byte order value.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.header.sector_shift = this.stream.read_u16_le();
|
|
||||||
if (this.header.sector_shift != OLE.ExpectedSectorShift)
|
|
||||||
{
|
|
||||||
throw new Error("OLE header does not have expected sector shift value.");
|
|
||||||
}
|
|
||||||
this.header.sector_size = 1 << this.header.sector_shift;
|
|
||||||
|
|
||||||
this.header.mini_sector_shift = this.stream.read_u16_le();
|
|
||||||
if (this.header.mini_sector_shift != OLE.ExpectedMiniSectorShift)
|
|
||||||
{
|
|
||||||
throw new Error("OLE header does not have expected mini sector shift value.");
|
|
||||||
}
|
|
||||||
this.header.mini_sector_size = 1 << this.header.mini_sector_shift;
|
|
||||||
|
|
||||||
if (!this.stream.read(6).every((b) => b === 0))
|
|
||||||
{
|
|
||||||
console.warn("OLE header reserved field was not set to all zeroes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// directory sectors are unsupported for V3
|
|
||||||
this.header.directory_sector_count = this.stream.read_u32_le();
|
|
||||||
if (this.header.directory_sector_count != OLE.ExpectedNumberOfDirectorySectors)
|
|
||||||
{
|
|
||||||
throw new Error("OLE header does not have expected number of directory sectors.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.header.fat_sector_count = this.stream.read_u32_le();
|
|
||||||
this.header.first_directory_sector_location = this.stream.read_u32_le();
|
|
||||||
this.header.transaction_signature_number = this.stream.read_u32_le();
|
|
||||||
this.header.mini_stream_cutoff_size = this.stream.read_u32_le();
|
|
||||||
this.header.fist_mini_fat_sector_location = this.stream.read_u32_le();
|
|
||||||
this.header.number_of_mini_fat_sectors = this.stream.read_u32_le();
|
|
||||||
this.header.first_difat_sector_location = this.stream.read_u32_le();
|
|
||||||
this.header.number_of_difat_sectors = this.stream.read_u32_le();
|
|
||||||
|
|
||||||
this.header.difat = new Uint32Array(this.stream.read(436, true));
|
|
||||||
this.fat_sectors = [];
|
|
||||||
for (let i = 0; i < 109; i++)
|
|
||||||
{
|
|
||||||
this.fat_sectors[i] = new FATSector(this, this.header.difat[i]);
|
|
||||||
}
|
|
||||||
this.directory_entries = [];
|
|
||||||
this.directory_entries[0] = new DirectoryEntry(this, (this.header.first_directory_sector_location + 1) * this.header.sector_size);
|
|
||||||
this.directory_entries[1] = new DirectoryEntry(this, (this.header.first_directory_sector_location + 1) * this.header.sector_size + 128);
|
|
||||||
this.directory_entries[2] = new DirectoryEntry(this, (this.header.first_directory_sector_location + 1) * this.header.sector_size + 256);
|
|
||||||
this.directory_entries[3] = new DirectoryEntry(this, (this.header.first_directory_sector_location + 1) * this.header.sector_size + 384);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FATSector
|
|
||||||
{
|
|
||||||
constructor(ole, sector_location)
|
|
||||||
{
|
|
||||||
this.ole = ole;
|
|
||||||
this.sector_location = sector_location;
|
|
||||||
const typeMap = [
|
|
||||||
{ value: 0xFFFFFFFC, name: "DIFSECT" },
|
|
||||||
{ value: 0xFFFFFFFD, name: "FATSECT" },
|
|
||||||
{ value: 0xFFFFFFFE, name: "ENDOFCHAIN" },
|
|
||||||
{ value: 0xFFFFFFFF, name: "FREESECT" },
|
|
||||||
];
|
|
||||||
if (this.sector_location >= 0xFFFFFFC)
|
|
||||||
{
|
|
||||||
this.entries = [];
|
|
||||||
this.type = typeMap.find(tm => tm.value == this.sector_location).name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.type = "FAT";
|
|
||||||
ole.stream.seek_to((this.sector_location + 1) * ole.header.sector_size);
|
|
||||||
this.entries = new Uint32Array(ole.stream.read(ole.header.sector_size - 4, true));
|
|
||||||
this.next_difat_sector = ole.stream.read_u32_le();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DirectoryEntry
|
|
||||||
{
|
|
||||||
constructor(ole, position)
|
|
||||||
{
|
|
||||||
this.ole = ole;
|
|
||||||
this.position = position;
|
|
||||||
ole.stream.seek_to(position);
|
|
||||||
|
|
||||||
let name_bytes = ole.stream.read(64);
|
|
||||||
let name_len = ole.stream.read_u16_le();
|
|
||||||
if (name_len > 64)
|
|
||||||
{
|
|
||||||
throw new Error("Name length field exceeded maximum size of 64.");
|
|
||||||
}
|
|
||||||
this.name_field_length = name_len;
|
|
||||||
this.name = new TextDecoder("utf-16").decode(name_bytes.slice(0, name_len));
|
|
||||||
if (this.name.endsWith("\u0000"))
|
|
||||||
this.name = this.name.slice(0, this.name.indexOf("\u0000"));
|
|
||||||
|
|
||||||
this.object_type = ole.stream.read_u8();
|
|
||||||
this.colour_flag = ole.stream.read_u8();
|
|
||||||
this.left_sibling = ole.stream.read_u32_le();
|
|
||||||
this.right_sibling = ole.stream.read_u32_le();
|
|
||||||
this.child_id = ole.stream.read_u32_le();
|
|
||||||
this.clsid = ole.stream.read(16);
|
|
||||||
this.state_bits = ole.stream.read_u32_le();
|
|
||||||
this.creation_time = ole.stream.read_u64_le();
|
|
||||||
this.modified_time = ole.stream.read_u64_le();
|
|
||||||
this.starting_sector_location = ole.stream.read_u32_le();
|
|
||||||
this.stream_size = ole.stream.read_u64_le();
|
|
||||||
}
|
|
||||||
|
|
||||||
read_all()
|
|
||||||
{
|
|
||||||
this.ole.stream.seek_to((this.starting_sector_location + 1) * this.ole.header.sector_size);
|
|
||||||
return new U8Stream(this.ole.stream.read(Number(this.stream_size)));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue