Compare commits

..

7 Commits

Author SHA1 Message Date
Michael Green
9081b0bed9 Merge pull request #26 from gaseous-project/dependabot/nuget/Microsoft.VisualStudio.Web.CodeGeneration.Design-7.0.8
chore(deps): bump Microsoft.VisualStudio.Web.CodeGeneration.Design from 7.0.7 to 7.0.8
2023-07-19 13:27:40 +10:00
Michael Green
d64877543a Merge branch 'main' into dependabot/nuget/Microsoft.VisualStudio.Web.CodeGeneration.Design-7.0.8 2023-07-19 13:27:29 +10:00
Michael Green
649fba1bfa Merge pull request #27 from gaseous-project/dependabot/nuget/Microsoft.AspNetCore.OpenApi-7.0.9
chore(deps): bump Microsoft.AspNetCore.OpenApi from 7.0.8 to 7.0.9
2023-07-19 13:27:09 +10:00
Michael Green
7dfb97608f Merge branch 'main' into dependabot/nuget/Microsoft.AspNetCore.OpenApi-7.0.9 2023-07-19 13:26:46 +10:00
Michael Green
35bb2f18d9 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
2023-07-19 13:18:39 +10:00
dependabot[bot]
ad84f5ae58 chore(deps): bump Microsoft.AspNetCore.OpenApi from 7.0.8 to 7.0.9
Bumps [Microsoft.AspNetCore.OpenApi](https://github.com/dotnet/aspnetcore) from 7.0.8 to 7.0.9.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v7.0.8...v7.0.9)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.OpenApi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 04:33:32 +00:00
dependabot[bot]
922c429716 chore(deps): bump Microsoft.VisualStudio.Web.CodeGeneration.Design
Bumps [Microsoft.VisualStudio.Web.CodeGeneration.Design](https://github.com/dotnet/Scaffolding) from 7.0.7 to 7.0.8.
- [Release notes](https://github.com/dotnet/Scaffolding/releases)
- [Commits](https://github.com/dotnet/Scaffolding/commits)

---
updated-dependencies:
- dependency-name: Microsoft.VisualStudio.Web.CodeGeneration.Design
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 04:33:26 +00:00
26 changed files with 674 additions and 83 deletions

BIN
.DS_Store vendored

Binary file not shown.

4
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "gaseous-server/wwwroot/EmulatorJS"]
path = gaseous-server/wwwroot/EmulatorJS
[submodule "gaseous-server/wwwroot/emulators/EmulatorJS"]
path = gaseous-server/wwwroot/emulators/EmulatorJS
url = https://github.com/EmulatorJS/EmulatorJS.git

View File

@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Dockerfile = Dockerfile
README.MD = README.MD
LICENSE = LICENSE
.gitignore = .gitignore
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "screenshots", "screenshots", "{F1A847C7-57BC-4DA9-8F83-CD060A7F5122}"

Binary file not shown.

View File

@@ -0,0 +1,120 @@
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using gaseous_tools;
namespace gaseous_server.Classes
{
public class Bios
{
public Bios()
{
}
public static Models.PlatformMapping.PlatformMapItem? BiosHashSignatureLookup(string MD5)
{
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
{
if (platformMapping.WebEmulator != null)
{
if (platformMapping.WebEmulator.Bios != null)
{
foreach (Models.PlatformMapping.PlatformMapItem.WebEmulatorItem.EmulatorBiosItem emulatorBiosItem in platformMapping.WebEmulator.Bios)
{
if (emulatorBiosItem.hash.ToLower() == MD5.ToLower())
{
return platformMapping;
}
}
}
}
}
return null;
}
public static List<BiosItem> GetBios()
{
return BuildBiosList();
}
public static List<BiosItem> GetBios(long PlatformId, bool HideUnavailable)
{
List<BiosItem> biosItems = new List<BiosItem>();
foreach (BiosItem biosItem in BuildBiosList())
{
if (biosItem.platformid == PlatformId)
{
if (HideUnavailable == true)
{
if (biosItem.Available == true)
{
biosItems.Add(biosItem);
}
}
else
{
biosItems.Add(biosItem);
}
}
}
return biosItems;
}
private static List<BiosItem> BuildBiosList()
{
List<BiosItem> biosItems = new List<BiosItem>();
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
{
if (platformMapping.WebEmulator != null)
{
if (platformMapping.WebEmulator.Bios != null)
{
IGDB.Models.Platform platform = Metadata.Platforms.GetPlatform(platformMapping.IGDBId);
foreach (Models.PlatformMapping.PlatformMapItem.WebEmulatorItem.EmulatorBiosItem emulatorBios in platformMapping.WebEmulator.Bios)
{
BiosItem biosItem = new BiosItem
{
platformid = platformMapping.IGDBId,
platformslug = platform.Slug,
platformname = platform.Name,
description = emulatorBios.description,
filename = emulatorBios.filename,
region = emulatorBios.region,
hash = emulatorBios.hash
};
biosItems.Add(biosItem);
}
}
}
}
return biosItems;
}
public class BiosItem : Models.PlatformMapping.PlatformMapItem.WebEmulatorItem.EmulatorBiosItem
{
public long platformid { get; set; }
public string platformslug { get; set; }
public string platformname { get; set; }
public string biosPath
{
get
{
return Path.Combine(Config.LibraryConfiguration.LibraryBIOSDirectory, platformslug, base.filename);
}
}
public bool Available {
get
{
bool fileExists = File.Exists(biosPath);
return fileExists;
}
}
}
}
}

View File

@@ -58,36 +58,64 @@ namespace gaseous_server.Classes
FileInfo fi = new FileInfo(GameFileImportPath);
Common.hashObject hash = new Common.hashObject(GameFileImportPath);
// check to make sure we don't already have this file imported
sql = "SELECT COUNT(Id) AS count FROM Games_Roms WHERE MD5=@md5 AND SHA1=@sha1";
dbDict.Add("md5", hash.md5hash);
dbDict.Add("sha1", hash.sha1hash);
DataTable importDB = db.ExecuteCMD(sql, dbDict);
if ((Int64)importDB.Rows[0]["count"] > 0)
{
if (!GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryImportDirectory))
{
Logging.Log(Logging.LogType.Warning, "Import Game", " " + GameFileImportPath + " already in database - skipping");
}
}
else
{
Logging.Log(Logging.LogType.Information, "Import Game", " " + GameFileImportPath + " not in database - processing");
Models.PlatformMapping.PlatformMapItem? IsBios = Classes.Bios.BiosHashSignatureLookup(hash.md5hash);
// process as a single file
Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
if (IsBios == null)
{
// file is a rom
// check to make sure we don't already have this file imported
sql = "SELECT COUNT(Id) AS count FROM Games_Roms WHERE MD5=@md5 AND SHA1=@sha1";
dbDict.Add("md5", hash.md5hash);
dbDict.Add("sha1", hash.sha1hash);
DataTable importDB = db.ExecuteCMD(sql, dbDict);
if ((Int64)importDB.Rows[0]["count"] > 0)
{
if (!GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryImportDirectory))
{
Logging.Log(Logging.LogType.Warning, "Import Game", " " + GameFileImportPath + " already in database - skipping");
}
}
else
{
Logging.Log(Logging.LogType.Information, "Import Game", " " + GameFileImportPath + " not in database - processing");
// get discovered platform
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(discoveredSignature.Flags.IGDBPlatformId);
if (determinedPlatform == null)
{
determinedPlatform = new IGDB.Models.Platform();
}
// process as a single file
Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
// get discovered platform
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(discoveredSignature.Flags.IGDBPlatformId);
if (determinedPlatform == null)
{
determinedPlatform = new IGDB.Models.Platform();
}
// add to database
StoreROM(hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
// add to database
StoreROM(hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
}
}
else
{
// file is a bios
if (IsBios.WebEmulator != null)
{
foreach (Classes.Bios.BiosItem biosItem in Classes.Bios.GetBios())
{
if (biosItem.Available == false && biosItem.hash == hash.md5hash)
{
string biosPath = biosItem.biosPath.Replace(biosItem.filename, "");
if (!Directory.Exists(biosPath))
{
Directory.CreateDirectory(biosPath);
}
File.Move(GameFileImportPath, biosItem.biosPath, true);
break;
}
}
}
}
}
}

View File

@@ -128,8 +128,9 @@ namespace gaseous_server.Classes
public long Id { get; set; }
public long PlatformId { get; set; }
public IGDB.Models.Platform Platform { get; set; }
public Dictionary<string, string>? Emulator { get; set; }
public long GameId { get; set; }
//public Dictionary<string, object>? Emulator { get; set; }
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
public long GameId { get; set; }
public string? Name { get; set; }
public long Size { get; set; }
public string? CRC { get; set; }

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace gaseous_server.Controllers
{
[ApiController]
[Route("api/v1/[controller]")]
public class BiosController : Controller
{
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<Classes.Bios.BiosItem> GetBios()
{
return Classes.Bios.GetBios();
}
[HttpGet]
[Route("{PlatformId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<Classes.Bios.BiosItem> GetBios(long PlatformId, bool AvailableOnly = true)
{
return Classes.Bios.GetBios(PlatformId, AvailableOnly);
}
[HttpGet]
[HttpHead]
[Route("{PlatformId}/{BiosName}")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult BiosFile(long PlatformId, string BiosName)
{
try
{
foreach (Classes.Bios.BiosItem biosItem in Classes.Bios.GetBios(PlatformId, true))
{
if (biosItem.filename == BiosName)
{
if (System.IO.File.Exists(biosItem.biosPath))
{
string filename = Path.GetFileName(biosItem.biosPath);
string filepath = biosItem.biosPath;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = "application/octet-stream";
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = false,
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("Cache-Control", "public, max-age=604800");
return File(filedata, contentType);
}
else
{
return NotFound();
}
}
}
return NotFound();
}
catch
{
return NotFound();
}
}
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Reflection;
using System.Text.Json.Serialization;
using gaseous_server.Classes;
namespace gaseous_server.Models
{
@@ -10,23 +12,21 @@ namespace gaseous_server.Models
}
private static List<PlatformMapItem> _PlatformMaps = new List<PlatformMapItem>();
//private static List<PlatformMapItem> _PlatformMaps = new List<PlatformMapItem>();
public static List<PlatformMapItem> PlatformMap
{
get
{
if (_PlatformMaps.Count == 0)
// load platform maps from: gaseous_server.Support.PlatformMap.json
List<PlatformMapItem> _PlatformMaps = new List<PlatformMapItem>();
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "gaseous_server.Support.PlatformMap.json";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
// load platform maps from: gaseous_server.Support.PlatformMap.json
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "gaseous_server.Support.PlatformMap.json";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string rawJson = reader.ReadToEnd();
_PlatformMaps.Clear();
_PlatformMaps = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson);
}
string rawJson = reader.ReadToEnd();
_PlatformMaps.Clear();
_PlatformMaps = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson);
}
return _PlatformMaps;
@@ -73,13 +73,28 @@ namespace gaseous_server.Models
}
public class PlatformMapItem
{
{
public int IGDBId { get; set; }
public string IGDBName { get; set; }
public List<string> AlternateNames { get; set; } = new List<string>();
public List<string> KnownFileExtensions { get; set; } = new List<string>();
public Dictionary<string, string>? WebEmulator { get; set; }
//public Dictionary<string, object>? WebEmulator { get; set; }
public WebEmulatorItem? WebEmulator { get; set; }
public class WebEmulatorItem
{
public string Type { get; set; }
public string Core { get; set; }
public List<EmulatorBiosItem> Bios { get; set; }
public class EmulatorBiosItem
{
public string hash { get; set; }
public string description { get; set; }
public string filename { get; set; }
public string region { get; set; }
}
}
}
}
}

View File

@@ -236,7 +236,7 @@ namespace gaseous_server.Models
public class SignatureFlags
{
public int IGDBPlatformId { get; set; }
public long IGDBPlatformId { get; set; }
public string IGDBPlatformName { get; set; }
}
}

View File

@@ -20,6 +20,11 @@ if (Config.ReadSetting("API Key", "Test API Key") == "Test API Key")
Logging.Log(Logging.LogType.Information, "Startup", "Setting initial API key");
Config.SetSetting("API Key", APIKey.ToString());
}
if (Config.ReadSetting("Emulator: Default BIOS Region", "Default Value") == "Default Value")
{
Logging.Log(Logging.LogType.Information, "Startup", "Setting default BIOS region to US");
Config.SetSetting("Emulator: Default BIOS Region", "US");
}
// set up server
var builder = WebApplication.CreateBuilder(args);
@@ -32,6 +37,9 @@ builder.Services.AddControllers().AddJsonOptions(x =>
// suppress nulls
x.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
// set max depth
x.JsonSerializerOptions.MaxDepth = 64;
});
builder.Services.AddResponseCaching();
builder.Services.AddControllers(options =>

View File

@@ -44,7 +44,31 @@
],
"KnownFileExtensions": [
".SMS"
]
],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "segaMS",
"Bios": [
{
"hash": "840481177270d5642a14ca71ee72844c",
"description": "MasterSystem EU BIOS",
"filename": "bios_E.sms",
"region": "EU"
},
{
"hash": "840481177270d5642a14ca71ee72844c",
"description": "MasterSystem US BIOS",
"filename": "bios_U.sms",
"region": "US"
},
{
"hash": "24a519c53f67b00640d0048ef7089105",
"description": "MasterSystem JP BIOS",
"filename": "bios_J.sms",
"region": "JP"
}
]
}
},
{
"IGDBId": 29,
@@ -101,5 +125,67 @@
"Type": "EmulatorJS",
"Core": "nes"
}
},
{
"IGDBId": 19,
"IGDBName": "Super Nintendo Entertainment System",
"AlternateNames": [
"Nintendo Super Famicom & Super Entertainment System",
"Super Nintendo Entertainment System",
"Super Nintendo",
"SNES"
],
"KnownFileExtensions": [],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "snes"
}
},
{
"IGDBId": 7,
"IGDBName": "PlayStation",
"AlternateNames": [
"Sony PlayStation",
"PS1",
"PSX",
"PSOne",
"PS"
],
"KnownFileExtensions": [],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "psx",
"Bios": [
{
"hash": "8dd7d5296a650fac7319bce665a6a53c",
"description": "PS1 JP BIOS - Required for JP games",
"filename": "scph5500.bin",
"region": "JP"
},
{
"hash": "490f666e1afb15b7362b406ed1cea246",
"description": "PS1 US BIOS - Required for US games",
"filename": "scph5501.bin",
"region": "US"
},
{
"hash": "32736f17079d0b2b7024407c39bd3050",
"description": "PS1 EU BIOS - Required for EU games",
"filename": "scph5502.bin",
"region": "EU"
}
]
}
},
{
"IGDBId": 52,
"IGDBName": "Arcade",
"AlternateNames": [],
"KnownFileExtensions": [],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "arcade",
"Bios": []
}
}
]

View File

@@ -14,9 +14,9 @@
<DocumentationFile>bin\Debug\net7.0\gaseous-server.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.8" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.7" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.8" />
<PackageReference Include="IGDB" Version="2.3.2" />
</ItemGroup>
@@ -105,6 +105,7 @@
<Folder Include="Assets\Ratings\CLASS_IND\" />
<Folder Include="wwwroot\fonts\" />
<Folder Include="wwwroot\pages\dialogs\" />
<Folder Include="wwwroot\pages\settings\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj">
@@ -119,6 +120,7 @@
</ItemGroup>
<ItemGroup>
<Content Remove="Support\PlatformMap.json" />
<Content Remove="wwwroot\pages\settings\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">

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;
}

View File

@@ -335,6 +335,14 @@ namespace gaseous_tools
}
}
public string LibraryBIOSDirectory
{
get
{
return Path.Combine(LibraryRootDirectory, "BIOS");
}
}
public string LibraryMetadataDirectory
{
get
@@ -385,6 +393,7 @@ namespace gaseous_tools
if (!Directory.Exists(LibraryRootDirectory)) { Directory.CreateDirectory(LibraryRootDirectory); }
if (!Directory.Exists(LibraryImportDirectory)) { Directory.CreateDirectory(LibraryImportDirectory); }
if (!Directory.Exists(LibraryDataDirectory)) { Directory.CreateDirectory(LibraryDataDirectory); }
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
if (!Directory.Exists(LibrarySignatureImportDirectory)) { Directory.CreateDirectory(LibrarySignatureImportDirectory); }
if (!Directory.Exists(LibrarySignatureImportDirectory_TOSEC)) { Directory.CreateDirectory(LibrarySignatureImportDirectory_TOSEC); }