mirror of
https://github.com/holub/mame
synced 2025-04-28 19:14:55 +03:00
455 lines
12 KiB
JavaScript
455 lines
12 KiB
JavaScript
// 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);
|
|
|
|
|
|
function update_cmd_preview()
|
|
{
|
|
var result = '';
|
|
var first = true;
|
|
|
|
var sysbios = document.getElementById('select-system-bios');
|
|
if (sysbios && (sysbios.selectedOptions[0].getAttribute('data-isdefault') != 'yes'))
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
result += ' ';
|
|
result += '-bios ' + sysbios.value;
|
|
}
|
|
|
|
var slotslist = document.getElementById('list-slot-options');
|
|
if (slotslist)
|
|
{
|
|
for (var item = slotslist.firstChild; item; item = item.nextSibling)
|
|
{
|
|
if (item.nodeName == 'DT')
|
|
{
|
|
var selection = item.lastChild.selectedOptions[0];
|
|
var biospopup = document.getElementById(('select-slot-bios-' + item.getAttribute('data-slotname')).replace(/:/g, '-'));
|
|
var defcard = selection.getAttribute('data-isdefault') == 'yes';
|
|
var defbios = !biospopup || (biospopup.selectedOptions[0].getAttribute('data-isdefault') == 'yes');
|
|
if (!defcard || !defbios)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
result += ' ';
|
|
var card = selection.value;
|
|
if (card == '')
|
|
card = '""';
|
|
result += '-' + item.getAttribute('data-slotname') + ' ' + card;
|
|
if (!defbios)
|
|
result += ',bios=' + biospopup.value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
document.getElementById('para-cmd-preview').textContent = result;
|
|
}
|
|
|
|
|
|
function set_default_system_bios()
|
|
{
|
|
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')
|
|
{
|
|
sysbios.selectedIndex = i;
|
|
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/' + 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/' + 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();
|
|
}
|
|
};
|
|
})();
|
|
|
|
|
|
function add_flag_rows(table, device)
|
|
{
|
|
var len, i, row, cell;
|
|
|
|
var sorted_features = Object.keys(machine_flags[device].features).sort();
|
|
var imperfect = [], unemulated = [];
|
|
len = sorted_features.length;
|
|
for (i = 0; i < len; i++)
|
|
((machine_flags[device].features[sorted_features[i]].overall == 'unemulated') ? unemulated : imperfect).push(sorted_features[i]);
|
|
|
|
len = unemulated.length;
|
|
if (len > 0)
|
|
{
|
|
row = document.createElement('tr');
|
|
row.appendChild(document.createElement('th')).textContent = 'Unemulated features:';
|
|
cell = row.appendChild(document.createElement('td'));
|
|
cell.textContent = unemulated[0];
|
|
for (i = 1; i < len; i++)
|
|
cell.textContent += ', ' + unemulated[i];
|
|
if (tbl.lastChild.getAttribute('class') == 'devbios')
|
|
tbl.insertBefore(row, tbl.lastChild);
|
|
else
|
|
tbl.appendChild(row)
|
|
}
|
|
|
|
len = imperfect.length;
|
|
if (len > 0)
|
|
{
|
|
row = document.createElement('tr');
|
|
row.appendChild(document.createElement('th')).textContent = 'Imperfect features:';
|
|
cell = row.appendChild(document.createElement('td'));
|
|
cell.textContent = imperfect[0];
|
|
for (i = 1; i < len; i++)
|
|
cell.textContent += ', ' + unemulated[i];
|
|
if (tbl.lastChild.getAttribute('class') == 'devbios')
|
|
tbl.insertBefore(row, tbl.lastChild);
|
|
else
|
|
tbl.appendChild(row)
|
|
}
|
|
}
|
|
|
|
|
|
function add_bios_row(slot, table, device)
|
|
{
|
|
var sorted_sets = Object.keys(bios_sets[device]).sort();
|
|
var len = sorted_sets.length;
|
|
if (len > 0)
|
|
{
|
|
var row = document.createElement('tr');
|
|
row.setAttribute('class', 'devbios');
|
|
row.appendChild(document.createElement('th')).textContent = 'BIOS:';
|
|
var popup = document.createElement('select');
|
|
popup.setAttribute('id', ('select-slot-bios-' + slot).replace(/:/g, '-'));
|
|
popup.onchange = slot_bios_change_handler;
|
|
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;
|
|
}
|
|
row.appendChild(document.createElement('td')).appendChild(popup);
|
|
table.appendChild(row);
|
|
update_cmd_preview();
|
|
}
|
|
}
|
|
|
|
|
|
function make_slot_term(name, slot, defaults)
|
|
{
|
|
var len, i;
|
|
|
|
var defcard = '';
|
|
len = defaults.length;
|
|
for (i = 0; (i < len) && (defcard == ''); i++)
|
|
{
|
|
if (Object.prototype.hasOwnProperty.call(defaults[i], name))
|
|
defcard = defaults[i][name];
|
|
}
|
|
|
|
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', ('select-slot-choice-' + name).replace(/:/g, '-'));
|
|
term.appendChild(popup);
|
|
var option = document.createElement('option');
|
|
option.setAttribute('value', '');
|
|
option.setAttribute('data-isdefault', ('' == defcard) ? 'yes' : 'no');
|
|
option.textContent = '-';
|
|
popup.appendChild(option);
|
|
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);
|
|
}
|
|
popup.selectedIndex = 0;
|
|
popup.onchange = make_slot_change_handler(name, slot, defaults);
|
|
return term;
|
|
}
|
|
|
|
|
|
function add_slot_items(root, device, defaults, slotslist, pos)
|
|
{
|
|
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;
|
|
|
|
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);
|
|
}
|
|
|
|
for (var j = 0; j < defcnt; j++)
|
|
{
|
|
if (Object.prototype.hasOwnProperty.call(defaults[j], slotabs))
|
|
{
|
|
var card = defaults[j][slotabs];
|
|
var sel = term.lastChild;
|
|
var found = false;
|
|
var choice;
|
|
for (choice in sel.options)
|
|
{
|
|
if (sel.options[choice].value == card)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (found)
|
|
{
|
|
sel.selectedIndex = choice;
|
|
sel.dispatchEvent(new Event('change'));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
update_cmd_preview();
|
|
}
|
|
|
|
|
|
function make_slot_change_handler(name, slot, defaults)
|
|
{
|
|
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];
|
|
|
|
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);
|
|
}
|
|
|
|
if (selection === null)
|
|
{
|
|
event.target.parentNode.setAttribute('data-slotcard', '');
|
|
if (def.firstChild)
|
|
def.removeChild(def.firstChild);
|
|
}
|
|
else
|
|
{
|
|
event.target.parentNode.setAttribute('data-slotcard', selection.device);
|
|
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/' + selection.device);
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(machine_flags, selection.device))
|
|
fetch_machine_flags(selection.device);
|
|
else
|
|
add_flag_rows(tbl, selection.device);
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(bios_sets, selection.device))
|
|
fetch_bios_sets(selection.device);
|
|
else
|
|
add_bios_row(slotname, tbl, selection.device);
|
|
|
|
if (def.firstChild)
|
|
def.replaceChild(tbl, def.firstChild);
|
|
else
|
|
def.appendChild(tbl);
|
|
|
|
add_slot_items(slotname + ':' + choice, selection.device, defaults, slotslist, def.nextSibling);
|
|
}
|
|
update_cmd_preview();
|
|
};
|
|
}
|
|
|
|
|
|
function slot_bios_change_handler(event)
|
|
{
|
|
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/' + 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);
|
|
}
|