diff options
Diffstat (limited to 'docs/release/scripts/minimaws/lib/assets')
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/common.js | 149 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/digest.js | 234 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/disclosedown.svg | 4 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/discloseup.svg | 4 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/machine.js | 628 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/romident.js | 641 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/sortasc.png | bin | 0 -> 1157 bytes | |||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/sortasc.svg | 4 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/sortdesc.png | bin | 0 -> 1195 bytes | |||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/sortdesc.svg | 4 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/sortind.png | bin | 0 -> 1247 bytes | |||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/sortind.svg | 5 | ||||
-rw-r--r-- | docs/release/scripts/minimaws/lib/assets/style.css | 18 |
13 files changed, 1691 insertions, 0 deletions
diff --git a/docs/release/scripts/minimaws/lib/assets/common.js b/docs/release/scripts/minimaws/lib/assets/common.js new file mode 100644 index 00000000000..7439aaa5a21 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/common.js @@ -0,0 +1,149 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb + +function make_collapsible(heading, section) +{ + var hidden = false; + var display = section.style.display; + var icon = heading.insertBefore(document.createElement('img'), heading.firstChild); + icon.setAttribute('src', assetsurl + '/disclosedown.svg'); + icon.setAttribute('class', 'disclosure'); + icon.addEventListener( + 'click', + function (event) + { + hidden = !hidden; + if (hidden) + { + icon.setAttribute('src', assetsurl + '/discloseup.svg'); + section.style.display = 'none'; + } + else + { + icon.setAttribute('src', assetsurl + '/disclosedown.svg'); + section.style.display = display; + var headingtop = 0; + for (var element = heading; element !== null; element = element.offsetParent) + headingtop += element.offsetTop; + var sectionbot = section.offsetHeight; + for (var element = section; element !== null; element = element.offsetParent) + sectionbot += element.offsetTop; + if ((window.pageYOffset + window.innerHeight) < sectionbot) + { + if ((sectionbot - headingtop) > window.innerHeight) + heading.scrollIntoView(true); + else + window.scroll(window.pageXOffset, sectionbot - window.innerHeight); + } + } + }); + + return function () + { + hidden = true; + icon.setAttribute('src', assetsurl + '/discloseup.svg'); + section.style.display = 'none'; + }; +} + + +function make_table_sortable(tbl) +{ + var sorticons = new Array(tbl.tHead.rows[0].cells.length); + + function TableSortHelper(i) + { + this.column = i; + this.header = tbl.tHead.rows[0].cells[i]; + this.sorted = false; + this.direction = 1; + + var container = this.header.appendChild(document.createElement('div')); + container.setAttribute('class', 'sorticon'); + + this.icon = container.appendChild(document.createElement('img')); + this.icon.setAttribute('src', assetsurl + '/sortind.svg'); + this.icon.addEventListener('click', this.icon_click.bind(this)); + } + + TableSortHelper.prototype = (function () + { + function set_unsorted(obj) + { + obj.sorted = false; + obj.icon.setAttribute('src', assetsurl + '/sortind.svg'); + } + + function sort_table(obj) + { + var c = obj.header.cellIndex; + var numeric = obj.header.getAttribute('class') == 'numeric'; + var tbody = tbl.tBodies[0]; + var trows; + if (numeric) + { + trows = Array.prototype.slice.call(tbody.rows, 0).sort( + function (x, y) + { + return obj.direction * (parseFloat(x.cells[c].textContent) - parseFloat(y.cells[c].textContent)); + }); + } + else + { + trows = Array.prototype.slice.call(tbody.rows, 0).sort( + function (x, y) + { + return obj.direction * x.cells[c].textContent.localeCompare(y.cells[c].textContent); + }); + } + trows.forEach(function (row) { tbody.appendChild(row); }); + } + + return { + icon_click : function (event) + { + if (this.sorted) + this.direction = -this.direction; + if (this.direction < 0) + this.icon.setAttribute('src', assetsurl + '/sortdesc.svg'); + else + this.icon.setAttribute('src', assetsurl + '/sortasc.svg'); + this.sorted = true; + for (var i = 0; i < sorticons.length; i++) + { + if (i != this.column) + set_unsorted(sorticons[i]); + } + sort_table(this); + } + }; + })(); + + for (var i = 0; i < sorticons.length; i++) + sorticons[i] = new TableSortHelper(i); +} + + +function make_restore_default_handler(popup, index) +{ + return function (event) + { + if (popup.selectedIndex != index) + { + popup.selectedIndex = index; + popup.dispatchEvent(new Event('change')); + } + } +} + + +function make_restore_default_button(title, id, popup, index) +{ + var btn = document.createElement('button'); + btn.setAttribute('id', id); + btn.setAttribute('type', 'button'); + btn.disabled = popup.selectedIndex == index; + btn.textContent = title; + btn.onclick = make_restore_default_handler(popup, index); + return btn; +} diff --git a/docs/release/scripts/minimaws/lib/assets/digest.js b/docs/release/scripts/minimaws/lib/assets/digest.js new file mode 100644 index 00000000000..6739d1440d9 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/digest.js @@ -0,0 +1,234 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb + +function Crc32Digester() +{ + this.crc = 0xffffffff; +} + +Crc32Digester.prototype = (function () + { + var table = new Uint32Array(256); + (function () + { + for (var i = 0; i < 256; i++) + { + var crc = i; + for (var b = 0; b < 8; b++) + crc = (crc >>> 1) ^ ((crc & 1) ? 0xedb88320 : 0x00000000); + table[i] = crc; + } + })(); + + return { + digest: function (data, view) + { + for (var i = 0; i < view.length; i++) + this.crc = (this.crc >>> 8) ^ table[(this.crc & 0x000000ff) ^ view[i]]; + }, + + finalise: function () + { + return this.crc ^ 0xffffffff; + } + }; + })(); + + +function Sha1Digester() +{ + this.st = new Uint32Array(5); + this.st[0] = 0xc3d2e1f0; + this.st[1] = 0x10325476; + this.st[2] = 0x98badcfe; + this.st[3] = 0xefcdab89; + this.st[4] = 0x67452301; + + this.cnt = new Uint32Array(2); + this.cnt[0] = 0; + this.cnt[1] = 0; + + this.buf = new DataView(new ArrayBuffer(64)); +} + +Sha1Digester.prototype = (function () + { + function rol(x, n) + { + return ((x << n) | (x >>> (32 - n))) & 0xffffffff; + } + + function b(data, i) + { + var r = data.getUint32(((i + 13) & 15) << 2, false); + r ^= data.getUint32(((i + 8) & 15) << 2, false); + r ^= data.getUint32(((i + 2) & 15) << 2, false); + r ^= data.getUint32((i & 15) << 2, false); + r = rol(r, 1); + data.setUint32((i & 15) << 2, r, false); + return r; + } + + function r0(data, d, i) + { + d[i % 5] = 0xffffffff & (d[i % 5] + ((d[(i + 3) % 5] & (d[(i + 2) % 5] ^ d[(i + 1) % 5])) ^ d[(i + 1) % 5]) + data.getUint32(i << 2, false) + 0x5a827999 + rol(d[(i + 4) % 5], 5)); + d[(i + 3) % 5] = rol(d[(i + 3) % 5], 30); + } + + function r1(data, d, i) + { + d[i % 5] = 0xffffffff & (d[i % 5] + ((d[(i + 3) % 5] & (d[(i + 2) % 5] ^ d[(i + 1) % 5])) ^ d[(i + 1) % 5])+ b(data, i) + 0x5a827999 + rol(d[(i + 4) % 5], 5)); + d[(i + 3) % 5] = rol(d[(i + 3) % 5], 30); + } + + function r2(data, d, i) + { + d[i % 5] = 0xffffffff & (d[i % 5] + (d[(i + 3) % 5] ^ d[(i + 2) % 5] ^ d[(i + 1) % 5]) + b(data, i) + 0x6ed9eba1 + rol(d[(i + 4) % 5], 5)); + d[(i + 3) % 5] = rol(d[(i + 3) % 5], 30); + } + + function r3(data, d, i) + { + d[i % 5] = 0xffffffff & (d[i % 5] + (((d[(i + 3) % 5] | d[(i + 2) % 5]) & d[(i + 1) % 5]) | (d[(i + 3) % 5] & d[(i + 2) % 5])) + b(data, i) + 0x8f1bbcdc + rol(d[(i + 4) % 5], 5)); + d[(i + 3) % 5] = rol(d[(i + 3) % 5], 30); + } + + function r4(data, d, i) + { + d[i % 5] = 0xffffffff & (d[i % 5] + (d[(i + 3) % 5] ^ d[(i + 2) % 5] ^ d[(i + 1) % 5]) + b(data, i) + 0xca62c1d6 + rol(d[(i + 4) % 5], 5)); + d[(i + 3) % 5] = rol(d[(i + 3) % 5], 30); + } + + function process(st, data) + { + var d = new Uint32Array(st); + var i = 0; + while (i < 16) + r0(data, d, i++); + while (i < 20) + r1(data, d, i++); + while (i < 40) + r2(data, d, i++); + while (i < 60) + r3(data, d, i++); + while (i < 80) + r4(data, d, i++); + for (i = 0; i < st.length; i++) + st[i] = (st[i] + d[i]) & 0xffffffff; + } + + return { + digest: function (data, view) + { + var residual = this.cnt[0]; + this.cnt[0] = (this.cnt[0] + (view.length << 3)) & 0xffffffff; + if (residual > this.cnt[0]) + this.cnt[1]++; + this.cnt[1] += (view.length >>> 29); + residual = (residual >>> 3) & 63; + var offset = 0; + if ((residual + view.length) >= 64) + { + if (residual > 0) + { + for (offset = 0; (offset + residual) < 64; offset++) + this.buf.setUint8(offset + residual, view[offset]); + process(this.st, this.buf); + residual = 0; + } + for ( ; (view.length - offset) >= 64; offset += 64) + process(this.st, new DataView(data, offset, 64)); + } + for ( ; offset < view.length; residual++, offset++) + this.buf.setUint8(residual, view[offset]); + }, + + finalise : function () + { + var lenbuf = new ArrayBuffer(8); + var lenview = new DataView(lenbuf); + lenview.setUint32(0, this.cnt[1], false); + lenview.setUint32(4, this.cnt[0], false); + var padbuf = new ArrayBuffer(64 - (63 & ((this.cnt[0] >>> 3) + 8))); + var padview = new Uint8Array(padbuf); + padview[0] = 0x80; + for (var i = 1; i < padview.length; i++) + padview[i] = 0x00; + this.digest(padbuf, padview); + this.digest(lenbuf, new Uint8Array(lenbuf)); + var result = new Array(20); + for (var i = 0; i < 20; i++) + result[i] = (this.st[4 - (i >>> 2)] >> ((3 - (i & 3)) << 3)) & 0x000000ff; + return result.map(x => x.toString(16).padStart(2, '0')).join(''); + } + }; + })(); + + +function StuckBitsDigester(max = 4) +{ + this.offset = 0; + this.state = [ ]; + for (var i = 0; i <= max; i++) + { + var bytes = 1 << i; + this.state.push({ filled: 0, bits: new Uint8Array(bytes), mask: new Uint8Array(bytes) }); + } +} + +StuckBitsDigester.prototype = (function () + { + return { + digest: function (data, view) + { + for (var i = 0; i < view.length; i++) + { + var data = view[i]; + for (var j = 0; j < this.state.length; j++) + { + var detail = this.state[j]; + var bytes = 1 << j; + var o = this.offset % bytes; + var f = o == (bytes - 1); + if (!detail.filled) + { + detail.bits[o] = data; + detail.mask[o] = 0xff; + if (f) + detail.filled = 1; + } + else + { + detail.mask[o] &= ~(data ^ detail.bits[o]); + detail.bits[o] &= detail.mask[o]; + } + if (o == (bytes - 1)) + detail.filled += 1; + } + this.offset = (this.offset + 1) % (1 << (this.state.length - 1)); + } + }, + + finalise: function () + { + var result = [ ]; + var lastresult = null; + for (var i = 0; (i < this.state.length) && (this.state[i].filled >= 4); i++) + { + var detail = this.state[i]; + var bytes = 1 << i; + for (var j = 0; j < bytes; j++) + { + var mask = detail.mask[j]; + if (mask && ((lastresult === null) || (mask != lastresult.mask[j % (1 << (lastresult.mask.length - 1))]))) + { + lastresult = { bits: detail.bits, mask: detail.mask }; + result.push(lastresult); + break; + } + } + } + return result; + } + }; + })(); diff --git a/docs/release/scripts/minimaws/lib/assets/disclosedown.svg b/docs/release/scripts/minimaws/lib/assets/disclosedown.svg new file mode 100644 index 00000000000..bb66c7f5de9 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/disclosedown.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="16" width="16"> + <path d="m 0,5 h 16 l -8,10 z" /> +</svg> diff --git a/docs/release/scripts/minimaws/lib/assets/discloseup.svg b/docs/release/scripts/minimaws/lib/assets/discloseup.svg new file mode 100644 index 00000000000..010065a446b --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/discloseup.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="16" width="16"> + <path d="m 5,0 v 16 l 10,-8 z" /> +</svg> diff --git a/docs/release/scripts/minimaws/lib/assets/machine.js b/docs/release/scripts/minimaws/lib/assets/machine.js new file mode 100644 index 00000000000..b7f600f04d6 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/machine.js @@ -0,0 +1,628 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb + +var slot_info = Object.create(null); +var bios_sets = Object.create(null); +var machine_flags = Object.create(null); +var softwarelist_info = Object.create(null); + + +function make_slot_popup_id(name) { return ('select-slot-choice-' + name).replace(/:/g, '-'); } +function get_slot_popup(name) { return document.getElementById(make_slot_popup_id(name)); } + + +function update_cmd_preview() +{ + var inifmt = document.getElementById('select-options-format').value == 'ini'; + var result = ''; + var first = true; + function add_option(flag, value) + { + if (first) + first = false; + else if (inifmt) + result += '\n'; + else + result += ' '; + + if (inifmt) + { + result += flag + ' '; + if (flag.length < 25) + result += ' '.repeat(25 - flag.length); + result += value; + } + else + { + result += '-' + flag + ' '; + if (value == '') + result += '""'; + else + result += value; + } + } + var elide_defaults = !document.getElementById('check-explicit-defaults').checked; + + // add system BIOS if applicable + var sysbios = document.getElementById('select-system-bios'); + if (sysbios && (!elide_defaults || (sysbios.selectedOptions[0].getAttribute('data-isdefault') != 'yes'))) + add_option('bios', sysbios.value); + + // add RAM option if applicable + var ramopt = document.getElementById('select-ram-option'); + if (ramopt && (!elide_defaults || (ramopt.selectedOptions[0].getAttribute('data-isdefault') != 'yes'))) + add_option('ramsize', ramopt.value); + + var slotslist = document.getElementById('list-slot-options'); + if (slotslist) + { + for (var item = slotslist.firstChild; item; item = item.nextSibling) + { + if (item.nodeName == 'DT') + { + // need to set the slot option if it has non-default card and/or non-default card BIOS + var slotname = item.getAttribute('data-slotname'); + var selection = get_slot_popup(slotname).selectedOptions[0]; + var biospopup = document.getElementById(('select-slot-bios-' + slotname).replace(/:/g, '-')); + var defcard = selection.getAttribute('data-isdefault') == 'yes'; + var defbios = !biospopup || (biospopup.selectedOptions[0].getAttribute('data-isdefault') == 'yes'); + if (!elide_defaults || !defcard || !defbios) + { + var card = selection.value; + add_option(slotname, card + ((biospopup && (!elide_defaults || !defbios)) ? (',bios=' + biospopup.value) : '')); + } + } + } + } + + // replace the preview with appropriate element + var target = document.getElementById('para-cmd-preview'); + var replacement = document.createElement(inifmt ? 'pre' : 'tt'); + replacement.setAttribute('id', 'para-cmd-preview'); + replacement.textContent = result; + target.parentNode.replaceChild(replacement, target); +} + + +function set_default_system_bios() +{ + // search for an explicit default option + var sysbios = document.getElementById('select-system-bios'); + var len = sysbios.options.length; + for (var i = 0; i < len; i++) + { + if (sysbios.options[i].getAttribute('data-isdefault') == 'yes') + { + // select it and add a button for restoring it + sysbios.selectedIndex = i; + var dflt = make_restore_default_button('default', 'btn-def-system-bios', sysbios, i); + sysbios.onchange = make_slot_bios_change_handler(dflt); + sysbios.parentNode.appendChild(document.createTextNode(' ')); + sysbios.parentNode.appendChild(dflt); + break; + } + } + update_cmd_preview(); +} + + +function set_default_ram_option() +{ + // search for an explicit default option + var ramopt = document.getElementById('select-ram-option'); + var len = ramopt.options.length; + for (var i = 0; i < len; i++) + { + if (ramopt.options[i].getAttribute('data-isdefault') == 'yes') + { + // select it and add a button for restoring it + ramopt.selectedIndex = i; + var dflt = make_restore_default_button('default', 'btn-def-ram-option', ramopt, i); + ramopt.onchange = make_slot_bios_change_handler(dflt); + ramopt.parentNode.appendChild(document.createTextNode(' ')); + ramopt.parentNode.appendChild(dflt); + break; + } + } + update_cmd_preview(); +} + + +var fetch_bios_sets = (function () + { + var pending = Object.create(null); + return function (device) + { + if (!Object.prototype.hasOwnProperty.call(bios_sets, device) && !Object.prototype.hasOwnProperty.call(pending, device)) + { + pending[device] = true; + var req = new XMLHttpRequest(); + req.open('GET', appurl + 'rpc/bios/' + encodeURIComponent(device), true); + req.responseType = 'json'; + req.onload = + function () + { + delete pending[device]; + if (req.status == 200) + { + bios_sets[device] = req.response; + var slotslist = document.getElementById('list-slot-options'); + if (slotslist) + { + for (var item = slotslist.firstChild; item; item = item.nextSibling) + { + if ((item.nodeName == 'DT') && (item.getAttribute('data-slotcard') == device)) + add_bios_row(item.getAttribute('data-slotname'), item.nextSibling.firstChild, device); + } + } + } + }; + req.send(); + } + }; + })(); + + +var fetch_machine_flags = (function () + { + var pending = Object.create(null); + return function (device) + { + if (!Object.prototype.hasOwnProperty.call(machine_flags, device) && !Object.prototype.hasOwnProperty.call(pending, device)) + { + pending[device] = true; + var req = new XMLHttpRequest(); + req.open('GET', appurl + 'rpc/flags/' + encodeURIComponent(device), true); + req.responseType = 'json'; + req.onload = + function () + { + delete pending[device]; + if (req.status == 200) + { + machine_flags[device] = req.response; + var slotslist = document.getElementById('list-slot-options'); + if (slotslist) + { + for (var item = slotslist.firstChild; item; item = item.nextSibling) + { + if ((item.nodeName == 'DT') && (item.getAttribute('data-slotcard') == device)) + add_flag_rows(item.nextSibling.firstChild, device); + } + } + } + }; + req.send(); + } + }; + })(); + + +var fetch_softwarelist_info = (function () + { + var pending = Object.create(null); + return function (device) + { + if (!Object.prototype.hasOwnProperty.call(softwarelist_info, device) && !Object.prototype.hasOwnProperty.call(pending, device)) + { + pending[device] = true; + var req = new XMLHttpRequest(); + req.open('GET', appurl + 'rpc/softwarelists/' + encodeURIComponent(device), true); + req.responseType = 'json'; + req.onload = + function () + { + delete pending[device]; + if (req.status == 200) + { + softwarelist_info[device] = req.response; + var slotslist = document.getElementById('list-slot-options'); + if (slotslist) + { + for (var item = slotslist.firstChild; item; item = item.nextSibling) + { + if ((item.nodeName == 'DT') && (item.getAttribute('data-slotcard') == device)) + { + var slotname = item.getAttribute('data-slotname'); + add_softwarelist_rows( + device, + slotname, + document.getElementById('select-slot-choice-' + slotname.replace(/:/g, '-')).value); + } + } + } + } + }; + req.send(); + } + }; + })(); + + +function add_flag_rows(table, device) +{ + var sorted_features = Object.keys(machine_flags[device].features).sort(); + var imperfect = [], unemulated = []; + var len = sorted_features.length; + for (var i = 0; i < len; i++) + ((machine_flags[device].features[sorted_features[i]].overall == 'unemulated') ? unemulated : imperfect).push(sorted_features[i]); + + function add_one(flags, title) + { + var len = flags.length; + if (len > 0) + { + var row = document.createElement('tr'); + row.appendChild(document.createElement('th')).textContent = title; + var cell = row.appendChild(document.createElement('td')); + cell.textContent = flags[0]; + for (i = 1; i < len; i++) + cell.textContent += ', ' + flags[i]; + if (table.lastChild.getAttribute('class') == 'devbios') + table.insertBefore(row, table.lastChild); + else + table.appendChild(row); + } + } + + add_one(unemulated, 'Unemulated features:'); + add_one(imperfect, 'Imperfect features:'); +} + + +function add_softwarelist_rows(device, slot, card) +{ + var sorted_softwarelists = Object.keys(softwarelist_info[device]).sort(); + var cardtag = slot + ':' + card; + if (sorted_softwarelists.length) + { + var table = document.getElementById('tbl-softwarelists').tBodies[0]; + sorted_softwarelists.forEach( + function (tag) + { + var cell, link; + var info = softwarelist_info[device][tag]; + var href = appurl + 'softwarelist/' + encodeURIComponent(info.shortname); + var row = table.appendChild(document.createElement('tr')); + row.setAttribute('id', 'row-softwarelists-' + (cardtag + tag).replace(/:/g, '-')) + row.appendChild(document.createElement('td')).textContent = cardtag; + link = row.appendChild(document.createElement('td')).appendChild(document.createElement('a')); + link.setAttribute('href', href); + link.textContent = info.shortname; + link = row.appendChild(document.createElement('td')).appendChild(document.createElement('a')); + link.setAttribute('href', href); + link.textContent = info.description; + row.appendChild(document.createElement('td')).textContent = info.status; + total = info.total; + cell = row.appendChild(document.createElement('td')); + cell.textContent = total.toString(10); + cell.style.textAlign = 'right'; + if (!total) + total = 1; + cell = row.appendChild(document.createElement('td')); + cell.textContent = (info.supported * 100.0 / total).toFixed(1) + '%'; + cell.style.textAlign = 'right'; + cell = row.appendChild(document.createElement('td')); + cell.textContent = (info.partiallysupported * 100.0 / total).toFixed(1) + '%'; + cell.style.textAlign = 'right'; + cell = row.appendChild(document.createElement('td')); + cell.textContent = (info.unsupported * 100.0 / total).toFixed(1) + '%'; + cell.style.textAlign = 'right'; + }); + document.getElementById('heading-softwarelists').style.removeProperty('display'); + document.getElementById('tbl-softwarelists').style.removeProperty('display'); + } +} + + +function add_bios_row(slot, table, device) +{ + var sorted_sets = Object.keys(bios_sets[device]).sort(); + var len = sorted_sets.length; + if (len > 0) + { + // create table row, add heading + var row = document.createElement('tr'); + row.setAttribute('class', 'devbios'); + row.appendChild(document.createElement('th')).textContent = 'BIOS:'; + var cell = document.createElement('td'); + + // make the BIOS popul itself + var popup = document.createElement('select'); + popup.setAttribute('id', ('select-slot-bios-' + slot).replace(/:/g, '-')); + for (var i = 0; i < len; i++) + { + var set = sorted_sets[i]; + var detail = bios_sets[device][set]; + var option = document.createElement('option'); + option.setAttribute('value', set); + option.setAttribute('data-isdefault', detail.isdefault ? 'yes' : 'no'); + option.textContent = set + ' - ' + detail.description; + popup.appendChild(option); + if (detail.isdefault) + popup.selectedIndex = i; + } + cell.appendChild(popup); + + // make a button to restore the default + var dflt; + if (popup.selectedOptions[0].getAttribute('data-isdefault') == 'yes') + { + dflt = make_restore_default_button('default', ('btn-def-slot-bios-' + slot).replace(/:/g, '-'), popup, popup.selectedIndex); + cell.appendChild(document.createTextNode(' ')) + cell.appendChild(dflt); + } + + // drop the controls into a cell, add it to the table, keep the command line preview up-to-date + popup.onchange = make_slot_bios_change_handler(dflt); + row.appendChild(cell); + table.appendChild(row); + update_cmd_preview(); + } +} + + +function make_slot_term(name, slot, defaults) +{ + var len, i; + + // see if we can find a default, outer layers take precedence + var defcard = ''; + len = defaults.length; + for (i = 0; (i < len) && (defcard == ''); i++) + { + if (Object.prototype.hasOwnProperty.call(defaults[i], name)) + defcard = defaults[i][name]; + } + + // create a container with the slot name and popup + var term = document.createElement('dt'); + term.setAttribute('id', ('item-slot-choice-' + name).replace(/:/g, '-')); + term.setAttribute('data-slotname', name); + term.setAttribute('data-slotcard', ''); + term.textContent = name + ': '; + var popup = document.createElement('select'); + popup.setAttribute('id', make_slot_popup_id(name)); + term.appendChild(popup); + + // add the empty slot option + var option = document.createElement('option'); + option.setAttribute('value', ''); + option.setAttribute('data-isdefault', ('' == defcard) ? 'yes' : 'no'); + option.textContent = '-'; + popup.appendChild(option); + popup.selectedIndex = 0; + + // add options for the cards + var sorted_choices = Object.keys(slot).sort(); + len = sorted_choices.length; + for (i = 0; i < len; i++) + { + var choice = sorted_choices[i]; + var card = slot[choice]; + option = document.createElement('option'); + option.setAttribute('value', choice); + option.setAttribute('data-isdefault', (choice == defcard) ? 'yes' : 'no'); + option.textContent = choice + ' - ' + card.description; + popup.appendChild(option); + if (choice == defcard) + popup.selectedIndex = i + 1; + } + + // make a button for restoring the default and hook up events + var dflt = make_restore_default_button('default', ('btn-def-slot-choice-' + name).replace(/:/g, '-'), popup, popup.selectedIndex); + term.appendChild(document.createTextNode(' ')); + term.appendChild(dflt); + popup.onchange = make_slot_change_handler(name, slot, defaults, dflt); + return term; +} + + +function add_slot_items(root, device, defaults, slotslist, pos) +{ + // add another layer of defaults for this device + var defvals = Object.create(null); + for (var key in slot_info[device].defaults) + defvals[root + key] = slot_info[device].defaults[key]; + defaults = defaults.slice(); + defaults.push(defvals); + var defcnt = defaults.length; + + // add controls for each subslot + var slots = slot_info[device].slots; + var sorted_slots = Object.keys(slots).sort(); + var len = sorted_slots.length; + for (var i = 0; i < len; i++) + { + var slotname = sorted_slots[i]; + var slotabs = root + slotname; + var slot = slots[slotname]; + var term = make_slot_term(slotabs, slot, defaults); + var def = document.createElement('dd'); + def.setAttribute('id', ('item-slot-detail-' + slotabs).replace(/:/g, '-')); + if (pos) + { + slotslist.insertBefore(term, pos); + slotslist.insertBefore(def, pos); + } + else + { + slotslist.appendChild(term); + slotslist.appendChild(def); + } + + // force a change event to populate subslot controls if the default isn't empty + get_slot_popup(slotabs).dispatchEvent(new Event('change')); + } + + update_cmd_preview(); +} + + +function make_slot_change_handler(name, slot, defaults, dfltbtn) +{ + var selection = null; + return function (event) + { + var choice = event.target.value; + var slotslist = event.target.parentNode.parentNode; + var def = event.target.parentNode.nextSibling; + var slotname = event.target.parentNode.getAttribute('data-slotname'); + selection = (choice == '') ? null : slot[choice]; + dfltbtn.disabled = event.target.selectedOptions[0].getAttribute('data-isdefault') == 'yes'; + + // clear out any subslots from previous selection + var prefix = slotname + ':'; + for (var candidate = def.nextSibling; candidate && candidate.getAttribute('data-slotname').startsWith(prefix); ) + { + var next = candidate.nextSibling; + slotslist.removeChild(candidate); + candidate = next.nextSibling; + slotslist.removeChild(next); + } + + // clear out any software lists from previous selection + var softwarelist_rowid_prefix = 'row-softwarelists-' + prefix.replace(/:/g, '-'); + for (var candidate = document.getElementById('tbl-softwarelists').tBodies[0].rows[0]; candidate; ) + { + var next = candidate.nextSibling; + if ((candidate.nodeName == 'TR') && candidate.getAttribute('id').startsWith(softwarelist_rowid_prefix)) + candidate.parentNode.removeChild(candidate); + candidate = next; + } + + if (selection === null) + { + // no selection, remove the slot card details table + event.target.parentNode.setAttribute('data-slotcard', ''); + if (def.firstChild) + def.removeChild(def.firstChild); + } + else + { + // stash the selected device where it's easy to find + event.target.parentNode.setAttribute('data-slotcard', selection.device); + + // create details table and add a link to the device's page + var tbl = document.createElement('table'); + tbl.setAttribute('class', 'sysinfo'); + var row = tbl.appendChild(document.createElement('tr')); + row.appendChild(document.createElement('th')).textContent = 'Short name:'; + var link = row.appendChild(document.createElement('td')).appendChild(document.createElement('a')); + link.textContent = selection.device; + link.setAttribute('href', appurl + 'machine/' + encodeURIComponent(selection.device)); + + // if we have emulation flags, populate now, otherwise fetch asynchronously + if (!Object.prototype.hasOwnProperty.call(machine_flags, selection.device)) + fetch_machine_flags(selection.device); + else + add_flag_rows(tbl, selection.device); + + // if we have BIOS details, populate now, otherwise fetch asynchronously + if (!Object.prototype.hasOwnProperty.call(bios_sets, selection.device)) + fetch_bios_sets(selection.device); + else + add_bios_row(slotname, tbl, selection.device); + + // if we have software list info, populate now, otherweise fetch asynchronously + if (!Object.prototype.hasOwnProperty.call(softwarelist_info, selection.device)) + fetch_softwarelist_info(selection.device); + else + add_softwarelist_rows(selection.device, slotname, choice); + + // drop the details table into the list + if (def.firstChild) + def.replaceChild(tbl, def.firstChild); + else + def.appendChild(tbl); + + // create controls for subslots + add_slot_items(slotname + ':' + choice, selection.device, defaults, slotslist, def.nextSibling); + } + update_cmd_preview(); + }; +} + + +function make_slot_bios_change_handler(dflt) +{ + return function (event) + { + if (dflt) + dflt.disabled = event.target.selectedOptions[0].getAttribute('data-isdefault') == 'yes'; + update_cmd_preview(); + } +} + + +function populate_slots(machine) +{ + var placeholder = document.getElementById('para-slots-placeholder'); + var slotslist = document.createElement('dl'); + slotslist.setAttribute('id', 'list-slot-options'); + placeholder.parentNode.replaceChild(slotslist, placeholder); + add_slot_items('', machine, [], slotslist, null); +} + + +function slot_retrieve_error(device) +{ + var errors; + var placeholder = document.getElementById('para-slots-placeholder'); + if (placeholder) + { + errors = document.createElement('div'); + errors.setAttribute('id', 'div-slots-errors'); + placeholder.parentNode.replaceChild(errors, placeholder); + } + else + { + errors = document.getElementById('div-slots-errors'); + } + var message = document.createElement('p'); + message.textContent = 'Error retrieving slot information for ' + device + '.'; + errors.appendChild(message); +} + + +function fetch_slots(machine) +{ + function make_request(device) + { + var req = new XMLHttpRequest(); + req.open('GET', appurl + 'rpc/slots/' + encodeURIComponent(device), true); + req.responseType = 'json'; + req.onload = + function () + { + if (req.status == 200) + { + slot_info[device] = req.response; + delete pending[device]; + for (var slotname in req.response.slots) + { + var slot = req.response.slots[slotname]; + for (var choice in slot) + { + var card = slot[choice].device + if (!Object.prototype.hasOwnProperty.call(slot_info, card) && !Object.prototype.hasOwnProperty.call(pending, card)) + { + pending[card] = true; + make_request(card); + } + } + } + if (!Object.keys(pending).length) + populate_slots(machine); + } + else + { + slot_retrieve_error(device); + } + }; + req.send(); + } + var pending = Object.create(null); + pending[machine] = true; + make_request(machine); +} diff --git a/docs/release/scripts/minimaws/lib/assets/romident.js b/docs/release/scripts/minimaws/lib/assets/romident.js new file mode 100644 index 00000000000..599b0674007 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/romident.js @@ -0,0 +1,641 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb + +var matched_names = new Array(); +var unmatched_names = new Array(); +var dump_info = Object.create(null); +var machine_info = Object.create(null); +var softwarelist_info = Object.create(null); +var software_info = Object.create(null); + + +function get_chd_sha1(header) +{ + if (header.byteLength < 16) + return null; + if (String.fromCharCode.apply(null, new Uint8Array(header, 0, 8)) != 'MComprHD') + return null; + var view = new DataView(header); + var headerlen = view.getUint32(8, false); + var version = view.getUint32(12, false); + var sha1offs; + if (version == 3) + { + if (headerlen != 120) + return null; + sha1offs = 80; + } + else if (version == 4) + { + if (headerlen != 108) + return null; + sha1offs = 48; + } + else if (version == 5) + { + if (headerlen != 124) + return null; + sha1offs = 84; + } + else + { + return null; + } + if (header.byteLength < (sha1offs + 20)) + return null; + return Array.from(new Uint8Array(header, sha1offs, 20)).map(x => x.toString(16).padStart(2, '0')).join(''); +} + + +function get_sha1_group(sha1) +{ + if (Object.hasOwnProperty.call(dump_info, sha1)) + { + return dump_info[sha1]; + } + else + { + var result = new Object(); + result.crc = Object.create(null); + dump_info[sha1] = result; + return result; + } +} + + +function add_matches(table, names, matches) +{ + for (var i = 0; i < names.length; i++) + { + var row = table.appendChild(document.createElement('tr')); + var name = row.appendChild(document.createElement('th')); + name.textContent = names[i]; + if (matches !== null) + { + name.setAttribute('rowspan', matches.length); + row.appendChild(document.createElement('td')).textContent = matches[0].name; + var bad = row.appendChild(document.createElement('td')); + if (matches[0].bad) + bad.textContent = 'BAD'; + for (var j = 1; j < matches.length; j++) + { + row = table.appendChild(document.createElement('tr')); + row.appendChild(document.createElement('td')).textContent = matches[j].name; + bad = row.appendChild(document.createElement('td')); + if (matches[j].bad) + bad.textContent = 'BAD'; + } + } + } +} + + +function add_software_matches(table, names, part, matches) +{ + for (var i = 0; i < names.length; i++) + { + var row = table.appendChild(document.createElement('tr')); + var name = row.appendChild(document.createElement('th')); + name.textContent = names[i]; + if (matches !== null) + { + name.setAttribute('rowspan', matches.length); + row.appendChild(document.createElement('td')).textContent = part; + row.appendChild(document.createElement('td')).textContent = matches[0].name; + var bad = row.appendChild(document.createElement('td')); + if (matches[0].bad) + bad.textContent = 'BAD'; + for (var j = 1; j < matches.length; j++) + { + row = table.appendChild(document.createElement('tr')); + row.appendChild(document.createElement('td')).textContent = matches[j].name; + bad = row.appendChild(document.createElement('td')); + if (matches[j].bad) + bad.textContent = 'BAD'; + } + } + } +} + + +function add_unmatched(names, crc, sha1) +{ + var table; + if (unmatched_names.length > 0) + { + table = document.getElementById('table-unmatched'); + } + else + { + var div = document.getElementById('div-unmatched'); + var heading = div.appendChild(document.createElement('h2')); + heading.textContent = 'Unmatched'; + table = div.appendChild(document.createElement('table')); + table.setAttribute('id', 'table-unmatched'); + make_collapsible(heading, table); + } + var content; + if (crc === null) + { + content = 'SHA1(' + sha1 + ')'; + } + else + { + if (crc < 0) + crc = 0xffffffff + crc + 1; + content = 'CRC(' + crc.toString(16).padStart(8, '0') + ') SHA1(' + sha1 + ')'; + } + for (var i = 0; i < names.length; i++) + { + var row = table.appendChild(document.createElement('tr')); + row.appendChild(document.createElement('th')).textContent = names[i]; + row.appendChild(document.createElement('td')).textContent = content; + unmatched_names.push(names[i]); + } +} + + +function add_issues(name) +{ + var div = document.getElementById('div-issues'); + var list; + if (!div.hasChildNodes()) + { + var heading = div.appendChild(document.createElement('h2')); + heading.textContent = 'Potential Issues'; + list = div.appendChild(document.createElement('dl')); + make_collapsible(heading, list); + } + else + { + list = div.lastChild; + } + list.appendChild(document.createElement('dt')).textContent = name; + var table = list.appendChild(document.createElement('dd')).appendChild(document.createElement('table')); + table.setAttribute('class', 'sysinfo'); + return table; +} + + +function add_stuck_bits(table, stuck) +{ + function format_stuck_bits(bits, mask) + { + var result = ''; + for (var i = 0; i < bits.length; i++) + { + if (i > 0) + result += ' '; + for (var j = 0; j < 8; j++) + { + if (!((mask[i] >> (7 - j)) & 0x01)) + result += '-'; + else if ((bits[i] >> (7 - j)) & 0x01) + result += '1'; + else + result += '0'; + } + } + var cell = document.createElement('td'); + cell.appendChild(document.createElement('tt')).textContent = result; + return cell; + } + + var row = table.appendChild(document.createElement('tr')); + var header = row.appendChild(document.createElement('th')); + header.textContent = 'Fixed data bits:'; + header.setAttribute('rowspan', stuck.length); + row.appendChild(format_stuck_bits(stuck[0].bits, stuck[0].mask)); + for (var i = 1; i < stuck.length; i++) + { + row = table.appendChild(document.createElement('tr')); + row.appendChild(format_stuck_bits(stuck[i].bits, stuck[i].mask)); + } +} + + +function get_machine_table(shortname, description) +{ + if (Object.hasOwnProperty.call(machine_info, shortname)) + { + return machine_info[shortname]; + } + else + { + var div = document.getElementById('div-machines'); + if (!div.hasChildNodes()) + div.appendChild(document.createElement('h2')).textContent = 'Machines'; + var heading = div.appendChild(document.createElement('h3')); + var link = heading.appendChild(document.createElement('a')); + link.textContent = description; + link.setAttribute('href', appurl + 'machine/' + encodeURIComponent(shortname)); + var table = div.appendChild(document.createElement('table')); + machine_info[shortname] = table; + add_matches(table, matched_names, null); + make_collapsible(heading, table); + return table; + } +} + + +function get_softwarelist_div(shortname, description) +{ + if (Object.hasOwnProperty.call(softwarelist_info, shortname)) + { + return softwarelist_info[shortname]; + } + else + { + software_info[shortname] = Object.create(null) + var div = document.getElementById('div-software'); + if (!div.hasChildNodes()) + div.appendChild(document.createElement('h2')).textContent = 'Software'; + div = div.appendChild(document.createElement('div')); + var heading = div.appendChild(document.createElement('h3')); + var link = heading.appendChild(document.createElement('a')); + link.textContent = description; + link.setAttribute('href', appurl + 'softwarelist/' + encodeURIComponent(shortname)); + softwarelist_info[shortname] = div; + return div; + } +} + + +function get_software_table(softwarelist, shortname, description) +{ + if (Object.hasOwnProperty.call(software_info, softwarelist) && Object.hasOwnProperty.call(software_info[softwarelist], shortname)) + { + return software_info[softwarelist][shortname]; + } + else + { + var div = softwarelist_info[softwarelist]; + var heading = div.appendChild(document.createElement('h4')); + var link = heading.appendChild(document.createElement('a')); + link.textContent = description; + link.setAttribute('href', appurl + 'softwarelist/' + encodeURIComponent(softwarelist) + '/' + encodeURIComponent(shortname)); + var table = div.appendChild(document.createElement('table')); + software_info[softwarelist][shortname] = table; + add_software_matches(table, matched_names, null, null); + return table; + } +} + + +function request_dumps(name, group, crc, sha1, url, progress) +{ + var req = new XMLHttpRequest(); + req.responseType = 'json'; + req.onload = + function () + { + if (req.status == 200) + { + var machines = Object.create(null); + var software = Object.create(null); + var matched = Object.keys(req.response.machines); + var softwarelists = Object.keys(req.response.software); + + if (matched.length > 0) + { + Object.keys(machine_info).forEach( + function (shortname) + { + var machine_table = machine_info[shortname]; + if (Object.hasOwnProperty.call(req.response.machines, shortname)) + { + machines[shortname] = req.response.machines[shortname].matches; + add_matches(machine_table, group.names, req.response.machines[shortname].matches); + } + else + { + add_matches(machine_table, group.names, null); + } + }); + if (softwarelists.length <= 0) + { + Object.keys(software_info).forEach( + function (listname) + { + Object.keys(software_info[listname]).forEach( + function (softwarename) + { + var software_table = software_info[listname][softwarename]; + add_software_matches(software_table, group.names, null, null); + }); + }); + } + matched.forEach( + function (shortname) + { + if (!Object.hasOwnProperty.call(machine_info, shortname)) + { + var machine_details = req.response.machines[shortname]; + var machine_table = get_machine_table(shortname, machine_details.description); + machines[shortname] = req.response.machines[shortname].matches; + add_matches(machine_table, group.names, machine_details.matches); + } + }); + } + + if (softwarelists.length > 0) + { + if (matched.length <= 0) + { + Object.keys(machine_info).forEach( + function (shortname) + { + var machine_table = machine_info[shortname]; + add_matches(machine_table, group.names, null); + }); + } + Object.keys(software_info).forEach( + function (listname) + { + var haslist = Object.hasOwnProperty.call(req.response.software, listname); + Object.keys(software_info[listname]).forEach( + function (softwarename) + { + var software_table = software_info[listname][softwarename]; + if (haslist && Object.hasOwnProperty.call(req.response.software[listname].software, softwarename)) + { + if (!Object.hasOwnProperty.call(software, listname)) + software[listname] = Object.create(null); + if (!Object.hasOwnProperty.call(software[listname], softwarename)) + software[listname][softwarename] = Object.create(null); + var software_details = req.response.software[listname].software[softwarename]; + Object.keys(software_details.parts).forEach( + function (partname) + { + var matches = software_details.parts[partname].matches; + software[listname][softwarename][partname] = matches; + add_software_matches(software_table, group.names, partname, matches); + }); + } + else + { + add_software_matches(software_table, group.names, null, null); + } + }); + }); + softwarelists.forEach( + function (listname) + { + var haslist = Object.hasOwnProperty.call(software_info, listname); + var softwarelist_details = req.response.software[listname]; + var softwarelist_div = get_softwarelist_div(listname, softwarelist_details.description); + Object.keys(softwarelist_details.software).forEach( + function (softwarename) + { + if (!haslist || !Object.hasOwnProperty.call(software_info[listname], softwarename)) + { + if (!Object.hasOwnProperty.call(software, listname)) + software[listname] = Object.create(null); + if (!Object.hasOwnProperty.call(software[listname], softwarename)) + software[listname][softwarename] = Object.create(null); + var software_details = softwarelist_details.software[softwarename]; + var software_table = get_software_table(listname, softwarename, software_details.description); + Object.keys(software_details.parts).forEach( + function (partname) + { + var matches = software_details.parts[partname].matches; + software[listname][softwarename][partname] = matches; + add_software_matches(software_table, group.names, partname, matches); + }); + } + }); + }); + } + + if ((matched.length > 0) | (softwarelists.length > 0)) + { + for (var i = 0; i < group.names.length; i++) + matched_names.push(group.names[i]); + } + else + { + add_unmatched(group.names, crc, sha1); + } + + group.machines = machines; + group.software = software; + progress.parentNode.removeChild(progress); + } + else + { + progress.textContent = 'Error identifying \u201C' + name + '\u201D: HTTP status code ' + req.status.toString(10); + if (crc !== null) + delete dump_info[sha1].crc[crc]; + else + delete dump_info[sha1].disk; + } + }; + req.onerror = + function () + { + progress.textContent = 'Error identifying \u201C' + name + '\u201D'; + if (crc !== null) + delete dump_info[sha1].crc[crc]; + else + delete dump_info[sha1].disk; + }; + req.onabort = + function () + { + progress.textContent = 'Error identifying \u201C' + name + '\u201D: server request aborted'; + if (crc !== null) + delete dump_info[sha1].crc[crc]; + else + delete dump_info[sha1].disk; + }; + req.open('GET', url); + req.send(); +} + + +function add_name(group, name, crc, sha1) +{ + if (group.names.indexOf(name) < 0) + { + group.names.push(name); + + if (group.hasOwnProperty('issues')) + { + var issues = group.issues; + if (issues !== null) + issues.parentNode.parentNode.insertBefore(document.createElement('dt'), issues.parentNode).textContent = name; + } + + if (group.hasOwnProperty('machines')) + { + var machines = group.machines; + var software = group.software; + var names = [ name ]; + if ((Object.keys(machines).length > 0) || (Object.keys(software).length > 0)) + { + Object.keys(machine_info).forEach( + function (shortname) + { + var machine_table = machine_info[shortname]; + if (Object.hasOwnProperty.call(machines, shortname)) + add_matches(machine_table, names, machines[shortname]); + else + add_matches(machine_table, names, null); + }); + + Object.keys(software_info).forEach( + function (listname) + { + var haslist = Object.hasOwnProperty.call(software, listname); + Object.keys(software_info[listname]).forEach( + function (softwarename) + { + var software_table = software_info[listname][softwarename]; + if (haslist && Object.hasOwnProperty.call(software[listname], softwarename)) + { + Object.keys(software[listname][softwarename]).forEach( + function (partname) + { + add_software_matches(software_table, names, partname, software[listname][softwarename][partname]); + }); + } + else + { + add_software_matches(software_table, names, null, null); + } + }); + }); + + matched_names.push(name); + } + else + { + add_unmatched(names, crc, sha1); + } + } + } +} + + +function identify_file(file, trychd, progress) +{ + var digested = 0; + var crcproc = new Crc32Digester(); + var sha1proc = new Sha1Digester(); + var stuckbitsproc = new StuckBitsDigester(); + + function process_chunk(e) + { + if (e.target.error === null) + { + var data = e.target.result; + if ((digested == 0) && trychd) + { + var chdsha1 = get_chd_sha1(data); + if (chdsha1 !== null) + { + var sha1grp = get_sha1_group(chdsha1); + if (!sha1grp.hasOwnProperty('disk')) + { + var diskgrp = new Object(); + diskgrp.names = [ file.name ]; + sha1grp.disk = diskgrp; + request_dumps(file.name, diskgrp, null, chdsha1, appurl + 'rpc/diskdumps?sha1=' + chdsha1, progress); + } + else + { + add_name(sha1grp.disk, file.name, crc, sha1); + progress.parentNode.removeChild(progress); + } + return; + } + } + var view = new Uint8Array(data); + crcproc.digest(data, view); + sha1proc.digest(data, view); + stuckbitsproc.digest(data, view); + digested += data.byteLength; + if (digested < file.size) + { + read_block(); + } + else + { + var crc = crcproc.finalise(); + var sha1 = sha1proc.finalise(); + var stuckbits = stuckbitsproc.finalise(); + + var sha1grp = get_sha1_group(sha1); + var crcgrp; + if (!Object.hasOwnProperty.call(sha1grp.crc, crc)) + { + crcgrp = new Object(); + crcgrp.names = [ file.name ]; + sha1grp.crc[crc] = crcgrp; + if (stuckbits.length) + { + crcgrp.issues = add_issues(file.name); + add_stuck_bits(crcgrp.issues, stuckbits); + } + else + { + crcgrp.issues = null; + } + var crcstr = ((crc < 0) ? (0xffffffff + crc + 1) : crc).toString(16).padStart(8, '0'); + request_dumps(file.name, crcgrp, crc, sha1, appurl + 'rpc/romdumps?crc=' + crcstr + '&sha1=' + sha1, progress); + } + else + { + crcgrp = sha1grp.crc[crc]; + add_name(crcgrp, file.name, crc, sha1); + progress.parentNode.removeChild(progress); + } + } + } + else + { + progress.textContent = 'Error identifying \u201C' + file.name + '\u201D: ' + e.target.error; + } + } + + function read_block() + { + var remaining = file.size - digested; + var chunk = file.slice(digested, digested + Math.min(remaining, 65536)); + var reader = new FileReader(); + reader.onload = process_chunk; + reader.readAsArrayBuffer(chunk); + }; + + progress.textContent = 'Identifying \u201C' + file.name + '\u201D\u2026'; + read_block(); +} + + +function add_dump_files(files) +{ + var prog = document.getElementById('div-progress'); + for (var i = 0; i < files.length; i++) + { + var name = files[i].name; + var dot = name.lastIndexOf('.'); + var trychd = (dot > 0) && (name.substring(dot + 1).toLowerCase() == 'chd'); + identify_file(files[i], trychd, prog.appendChild(document.createElement('p'))); + } +} + + +function div_dropzone_dragover(e) +{ + e.stopPropagation(); + e.preventDefault(); + e.dataTransfer.dropEffect = 'link'; +} + + +function div_dropzone_drop(e) +{ + e.stopPropagation(); + e.preventDefault(); + add_dump_files(e.dataTransfer.files); +} diff --git a/docs/release/scripts/minimaws/lib/assets/sortasc.png b/docs/release/scripts/minimaws/lib/assets/sortasc.png Binary files differnew file mode 100644 index 00000000000..29b893cdd02 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/sortasc.png diff --git a/docs/release/scripts/minimaws/lib/assets/sortasc.svg b/docs/release/scripts/minimaws/lib/assets/sortasc.svg new file mode 100644 index 00000000000..c2ff41afccb --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/sortasc.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="16" width="30"> + <path d="m 14,16 h 16 l -8,-16 z" /> +</svg> diff --git a/docs/release/scripts/minimaws/lib/assets/sortdesc.png b/docs/release/scripts/minimaws/lib/assets/sortdesc.png Binary files differnew file mode 100644 index 00000000000..63f48fc7213 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/sortdesc.png diff --git a/docs/release/scripts/minimaws/lib/assets/sortdesc.svg b/docs/release/scripts/minimaws/lib/assets/sortdesc.svg new file mode 100644 index 00000000000..4a10b3f6e47 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/sortdesc.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="16" width="30"> + <path d="m 14,0 h 16 l -8,16 z" /> +</svg> diff --git a/docs/release/scripts/minimaws/lib/assets/sortind.png b/docs/release/scripts/minimaws/lib/assets/sortind.png Binary files differnew file mode 100644 index 00000000000..773dd6aec02 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/sortind.png diff --git a/docs/release/scripts/minimaws/lib/assets/sortind.svg b/docs/release/scripts/minimaws/lib/assets/sortind.svg new file mode 100644 index 00000000000..6e351b6a6fb --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/sortind.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="16" width="30"> + <path d="m 0,16 h 16 l -8,-16 z" /> + <path d="m 14,0 h 16 l -8,16 z" /> +</svg> diff --git a/docs/release/scripts/minimaws/lib/assets/style.css b/docs/release/scripts/minimaws/lib/assets/style.css new file mode 100644 index 00000000000..9ba6631a783 --- /dev/null +++ b/docs/release/scripts/minimaws/lib/assets/style.css @@ -0,0 +1,18 @@ +/* license:BSD-3-Clause + * copyright-holders:Vas Crabb + */ + +th { text-align: left; background-color: #ddd; padding: 0.25em } +td { padding-left: 0.25em; padding-right: 0.25em } + +img[class=disclosure] { height: 0.7em; margin-right: 0.25em; vertical-align: baseline } + +div[class=sorticon] { float: right; height: 100%; margin-left: 0.5em } +div[class=sorticon] img { height: 0.7em; vertical-align: baseline } + +table[class=sysinfo] th { text-align: right } + +div[class=dropzone] { padding: 0 1em; border-width: 2px; border-radius: 1em; border-style: dashed } + +dl[id=list-slot-options] dt { font-weight: bold; margin-top: 1em } +dl[id=list-slot-options] dd table { margin-top: 0.5em; margin-bottom: 1em } |