Add support for adding EmulatorJS firmware (#28)

* feat: EmulatorJS support - importing of BIOS files #15

* feat: added Bios controller to make Bios files available to the emulator, also resolved SNES identification issues (see: #25)

* feat: added firmware selector to emulator screen

* refactor: moved EmulatorJS to a subfolder

* feat: added firmware image availability page
This commit is contained in:
Michael Green
2023-07-19 13:18:39 +10:00
committed by GitHub
parent a2d634d96f
commit 35bb2f18d9
26 changed files with 672 additions and 81 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 KiB

View File

@@ -23,7 +23,7 @@
<div id="banner_header">
<div id="banner_header_label">Gaseous Games</div>
</div>
<div id="banner_cog" onclick="window.location.href = '/index.html?page=system';">
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';">
<img src="/images/cog.jpg" alt="System" id="banner_system_image" />
</div>

View File

@@ -12,14 +12,14 @@
EJS_lightgun = false; // can be true or false
// URL to BIOS file
EJS_biosUrl = ''; // example: https://dl.dropboxusercontent.com/s/[random-code]/bios.bin
EJS_biosUrl = emuBios;
// URL to Game rom
EJS_gameUrl = decodeURIComponent(urlParams.get('rompath'));
// Path to the data directory
EJS_pathtodata = '/EmulatorJS/data/';
EJS_pathtodata = '/emulators/EmulatorJS/data/';
EJS_DEBUG_XX = false;
EJS_DEBUG_XX = true;
</script>
<script src='/EmulatorJS/data/loader.js'></script>
<script src='/emulators/EmulatorJS/data/loader.js'></script>

View File

@@ -4,14 +4,27 @@
<div id="emulator"></div>
<div id="emulatorbios">
<table style="width: 100%;">
<tr>
<td>Firmware:</td>
<td><select id="emulatorbiosselector" onchange="loadEmulator();"></select></td>
</tr>
</table>
</div>
<script type="text/javascript">
const urlParams = new URLSearchParams(window.location.search);
var gameId = urlParams.get('gameid');
var platformId = urlParams.get('platformid');
var gameData;
var artworks = null;
var artworksPosition = 0;
var emuBios = '';
var availableEmuBios = [];
ajaxCall('/api/v1/Games/' + gameId, 'GET', function (result) {
gameData = result;
@@ -29,6 +42,36 @@
}
});
ajaxCall('/api/v1/Bios/' + platformId, 'GET', function (result) {
var emulatorbiosDiv = document.getElementById('emulatorbios');
availableEmuBios = result;
if (result.length == 0) {
emuBios = '';
emulatorbiosDiv.setAttribute('style', 'display: none;');
} else {
emuBios = '/api/v1/Bios/' + platformId + '/' + availableEmuBios[0].filename;
var emulatorbiosselect = document.getElementById('emulatorbiosselector');
for (var i = 0; i < availableEmuBios.length; i++) {
var biosOption = document.createElement('option');
biosOption.value = availableEmuBios[i].filename;
biosOption.innerHTML = availableEmuBios[i].description + ' (' + availableEmuBios[i].filename + ')';
if (availableEmuBios[i].region == "US") {
emuBios = '/api/v1/Bios/' + platformId + '/' + availableEmuBios[i].filename;
biosOption.setAttribute('selected', 'selected');
}
emulatorbiosselect.appendChild(biosOption);
}
}
loadEmulator();
});
function rotateBackground() {
if (artworks) {
artworksPosition += 1;
@@ -40,9 +83,18 @@
}
}
switch (urlParams.get('engine')) {
case 'EmulatorJS':
$('#emulator').load('/pages/EmulatorJS.html');
break;
function loadEmulator() {
if (availableEmuBios.length > 0) {
var emulatorbiosselect = document.getElementById('emulatorbiosselector');
emuBios = emulatorbiosselect.value;
} else {
emuBios = '';
}
switch (urlParams.get('engine')) {
case 'EmulatorJS':
$('#emulator').load('/pages/EmulatorJS.html');
break;
}
}
</script>

View File

@@ -312,7 +312,7 @@
lastPlatform = result[i].platform.name;
var platformRow = document.createElement('tr');
var platformHeader = document.createElement('th');
platformHeader.setAttribute('colspan', 4);
platformHeader.setAttribute('colspan', 6);
platformHeader.innerHTML = result[i].platform.name;
platformRow.appendChild(platformHeader);
newTable.appendChild(platformRow);
@@ -320,7 +320,7 @@
var launchButton = '';
if (result[i].emulator) {
launchButton = '<a href="/index.html?page=emulator&engine=' + result[i].emulator.Type + '&core=' + result[i].emulator.Core + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/file') + '" class="romlink">Start</a>';
launchButton = '<a href="/index.html?page=emulator&engine=' + result[i].emulator.type + '&core=' + result[i].emulator.core + '&platformid=' + result[i].platform.id + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/file') + '" class="romstart">Launch</a>';
}
var newRow = [
@@ -329,7 +329,7 @@
result[i].romTypeMedia,
result[i].mediaLabel,
launchButton,
'<span class="romlink" onclick="showDialog(\'rominfo\', ' + result[i].id + ');">...</span>'
'<div class="properties_button" onclick="showDialog(\'rominfo\', ' + result[i].id + ');">i</div>'
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}

View File

@@ -0,0 +1,48 @@
<div id="bgImage" style="background-image: url('/images/SettingsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
<div id="gamepage">
<div id="properties_toc" class="settings_toc">
<div class="filter_header">Settings</div>
<div id="properties_toc_system" name="properties_toc_item" onclick="SelectTab('system');">System</div>
<div id="properties_toc_bios" name="properties_toc_item" onclick="SelectTab('bios');">Firmware</div>
<div id="properties_toc_about" name="properties_toc_item" onclick="SelectTab('about');">About</div>
</div>
<div id="properties_bodypanel">
</div>
</div>
<div id="settings_photocredit">
Wallpaper by <a href="https://unsplash.com/@lorenzoherrera" class="romlink">Lorenzo Herrera</a> / <a href="https://unsplash.com/photos/p0j-mE6mGo4" class="romlink">Unsplash</a>
</div>
<script type="text/javascript">
const urlParams = new URLSearchParams(window.location.search);
var myParam = urlParams.get('sub');
var selectedTab = '';
if (myParam) {
selectedTab = myParam;
} else {
selectedTab = 'system';
}
SelectTab(selectedTab);
function SelectTab(TabName) {
var tocs = document.getElementsByName('properties_toc_item');
for (var i = 0; i < tocs.length; i++) {
if ((tocs[i].id) == ("properties_toc_" + TabName)) {
tocs[i].className = "properties_toc_item_selected";
} else {
tocs[i].className = '';
}
}
$('#properties_bodypanel').load('/pages/settings/' + TabName + '.html');
}
</script>

View File

@@ -0,0 +1,14 @@
<div id="gametitle">
<h1 id="gametitle_label">About Gaseous</h1>
</div>
<table>
<tr>
<th>Home Page</th>
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
</tr>
<tr>
<th>Bugs and Feature Requests</th>
<td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td>
</tr>
</table>

View File

@@ -0,0 +1,53 @@
<div id="gametitle">
<h1 id="gametitle_label">Firmware</h1>
</div>
<h3>Firmware Availablility</h3>
<table id="table_firmware" class="romtable" cellspacing="0">
</table>
<script type="text/javascript">
ajaxCall('/api/v1/Bios', 'GET', function (result) {
result.sort((a, b) => a.platformname.charCodeAt(0) - b.platformname.charCodeAt(0));
var lastPlatform = '';
var newTable = document.getElementById('table_firmware');
newTable.appendChild(createTableRow(true, ['Description', 'File name', 'MD5 Hash', 'Available']));
for (var i = 0; i < result.length; i++) {
if (result[i].platformname != lastPlatform) {
lastPlatform = result[i].platformname;
var platformRow = document.createElement('tr');
var platformHeader = document.createElement('th');
platformHeader.setAttribute('colspan', 4);
platformHeader.innerHTML = result[i].platformname;
platformRow.appendChild(platformHeader);
newTable.appendChild(platformRow);
}
var biosFilename = document.createElement('a');
biosFilename.href = '/api/v1/Bios/' + result[i].platformid + '/' + result[i].filename;
biosFilename.innerHTML = result[i].filename;
biosFilename.className = 'romlink';
var availableText = document.createElement('span');
if (result[i].available == true) {
availableText.innerHTML = 'Available';
availableText.className = 'greentext';
} else {
availableText.innerHTML = 'Unavailable';
availableText.className = 'redtext';
}
var newRow = [
result[i].description,
biosFilename,
result[i].hash,
availableText
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
});
</script>

View File

@@ -1,23 +1,20 @@
<div id="gamepage">
<div id="gametitle">
<h1 id="gametitle_label">System</h1>
</div>
<h3>Background Tasks</h3>
<div id="system_tasks"></div>
<h3>Usage</h3>
<p><strong>Library</strong></p>
<div id="system_disks"></div>
<p><strong>Database</strong></p>
<div id="system_database"></div>
<h3>Signatures</h3>
<div id="system_signatures"></div>
<div id="gametitle">
<h1 id="gametitle_label">System</h1>
</div>
<script type="text/javascript">
function SystemLoadStatus() {
<h3>Background Tasks</h3>
<div id="system_tasks"></div>
<h3>Usage</h3>
<p><strong>Library</strong></p>
<div id="system_disks"></div>
<p><strong>Database</strong></p>
<div id="system_database"></div>
<h3>Signatures</h3>
<div id="system_signatures"></div>
<script type="text/javascript">function SystemLoadStatus() {
ajaxCall('/api/v1/BackgroundTasks', 'GET', function (result) {
var newTable = document.createElement('table');
newTable.className = 'romtable';
@@ -71,7 +68,7 @@
var startButton = '';
if (result[i].itemState != "Running") {
startButton = "<span id='startProcess' class='romlink' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
}
var newRow = [
@@ -111,7 +108,7 @@
formatBytes(spaceUsedByOthers),
formatBytes(result.Paths[i].TotalSpace)
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
var spaceRow = document.createElement('tr');
@@ -202,5 +199,4 @@
SystemLoadSystemStatus();
setInterval(SystemLoadStatus, 60000);
SystemSignaturesStatus();
setInterval(SystemSignaturesStatus, 300000);
</script>
setInterval(SystemSignaturesStatus, 300000);</script>

View File

@@ -168,6 +168,7 @@ h3 {
}
.filter_header {
font-weight: bold;
padding: 10px;
background-color: #2b2b2b;
}
@@ -469,7 +470,7 @@ th {
.romlink {
color: white;
text-decoration: none;
/*text-decoration: none;*/
}
.romlink:hover {
@@ -478,6 +479,56 @@ th {
cursor: pointer;
}
.romstart {
padding-left: 7px;
padding-right: 7px;
padding-top: 3px;
padding-bottom: 3px;
background-color: #02B01B;
color: white;
text-shadow: 2px 2px 6px #003506;
text-decoration: none;
border-radius: 5px 5px 5px 5px;
-webkit-border-radius: 5px 5px 5px 5px;
-moz-border-radius: 5px 5px 5px 5px;
border: 1px solid #19d348;
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
}
.romstart:hover {
background-color: #003506;
border-color: #129834;
cursor: pointer;
}
.properties_button {
width: 15px;
height: 15px;
border-radius: 15px;
font-size: 13px;
font-weight: bold;
color: blue;
line-height: 17px;
text-align: center;
border-color: blue;
border-width: 2px;
border-style: solid;
background-color: white;
outline-color: white;
outline-width: 1px;
outline-style: solid;
}
.properties_button:hover {
cursor: pointer;
color: white;
border-color: white;
background-color: blue;
outline-color: blue;
}
#gamedev_logo {
float: right;
max-height: 48px;
@@ -492,6 +543,8 @@ th {
display: block;
width: 150px;
min-width: 150px;
background-color: #383838;
height: 100%;
}
div[name="properties_toc_item"] {
@@ -518,6 +571,10 @@ div[name="properties_toc_item"]:hover {
padding-left: 10px;
}
.settings_toc {
margin-top: 20px;
}
.select2-container--open .select2-dropdown--below,
.select2-container--open .select2-dropdown--above {
background: #2b2b2b;
@@ -584,4 +641,30 @@ button:disabled {
margin: 0 auto;
width: 640px;
padding-top: 100px;
}
#emulatorbios {
margin: 0 auto;
width: 640px;
padding-top: 20px;
}
.greentext {
color: lightgreen;
}
.redtext {
color: red;
}
#settings_photocredit {
position: fixed;
bottom: 0px;
left: 0px;
right: 0px;
height: 20px;
background-color: rgba(0, 22, 56, 0.8);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
padding: 5px;
}