Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9081b0bed9 | ||
![]() |
d64877543a | ||
![]() |
649fba1bfa | ||
![]() |
7dfb97608f | ||
![]() |
35bb2f18d9 | ||
![]() |
ad84f5ae58 | ||
![]() |
922c429716 | ||
![]() |
a2d634d96f | ||
![]() |
7a8e445471 | ||
![]() |
b010f9742b | ||
![]() |
afd70e6b02 |
2
.github/workflows/BuildDockerOnTag.yml
vendored
2
.github/workflows/BuildDockerOnTag.yml
vendored
@@ -12,6 +12,8 @@ jobs:
|
|||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
-
|
-
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v2
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "gaseous-server/wwwroot/emulators/EmulatorJS"]
|
||||||
|
path = gaseous-server/wwwroot/emulators/EmulatorJS
|
||||||
|
url = https://github.com/EmulatorJS/EmulatorJS.git
|
||||||
|
@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
Dockerfile = Dockerfile
|
Dockerfile = Dockerfile
|
||||||
README.MD = README.MD
|
README.MD = README.MD
|
||||||
LICENSE = LICENSE
|
LICENSE = LICENSE
|
||||||
|
.gitignore = .gitignore
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "screenshots", "screenshots", "{F1A847C7-57BC-4DA9-8F83-CD060A7F5122}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "screenshots", "screenshots", "{F1A847C7-57BC-4DA9-8F83-CD060A7F5122}"
|
||||||
|
14
README.MD
14
README.MD
@@ -16,6 +16,7 @@ The following projects are used by Gaseous
|
|||||||
* https://github.com/JamesNK/Newtonsoft.Json
|
* https://github.com/JamesNK/Newtonsoft.Json
|
||||||
* https://www.nuget.org/packages/MySql.Data/8.0.32.1
|
* https://www.nuget.org/packages/MySql.Data/8.0.32.1
|
||||||
* https://github.com/kamranayub/igdb-dotnet
|
* https://github.com/kamranayub/igdb-dotnet
|
||||||
|
* https://github.com/EmulatorJS/EmulatorJS
|
||||||
|
|
||||||
## Configuration File
|
## Configuration File
|
||||||
When Gaseous-Server is started for the first time, it creates a configuration file at ~/.gaseous-server/config.json if it doesn't exist. Some values can be filled in using environment variables (such as in the case of using docker).
|
When Gaseous-Server is started for the first time, it creates a configuration file at ~/.gaseous-server/config.json if it doesn't exist. Some values can be filled in using environment variables (such as in the case of using docker).
|
||||||
@@ -57,10 +58,17 @@ When Gaseous-Server is started for the first time, it creates a configuration fi
|
|||||||
|
|
||||||
## Deploy with Docker
|
## Deploy with Docker
|
||||||
Dockerfile and docker-compose.yml files have been provided to make deployment of the server as easy as possible.
|
Dockerfile and docker-compose.yml files have been provided to make deployment of the server as easy as possible.
|
||||||
|
1. Download the docker-compose.yml file
|
||||||
|
2. Open the docker-compose.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
|
||||||
|
3. Run the command "docker-compose up -d"
|
||||||
|
4. Connect to the host on port 5198
|
||||||
|
|
||||||
|
## Build and Deploy with Docker
|
||||||
|
Dockerfile and docker-compose-build.yml files have been provided to make deployment of the server as easy as possible.
|
||||||
1. Clone the repo with "git clone https://github.com/gaseous-project/gaseous-server.git"
|
1. Clone the repo with "git clone https://github.com/gaseous-project/gaseous-server.git"
|
||||||
2. Change into the gaseous-server directory
|
2. Change into the gaseous-server directory
|
||||||
3. Open the docker-compose.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
|
3. Open the docker-compose-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
|
||||||
4. Run the command "docker-compose up -d"
|
4. Run the command "docker-compose up --file docker-compose-build.yml -d"
|
||||||
5. Connect to the host on port 5198
|
5. Connect to the host on port 5198
|
||||||
|
|
||||||
## Adding Content
|
## Adding Content
|
||||||
@@ -98,4 +106,4 @@ Loop through each of the search candidates searching using:
|
|||||||
2. "wherefuzzy" - partial match using wildcards
|
2. "wherefuzzy" - partial match using wildcards
|
||||||
3. "search" - uses a more flexible search method
|
3. "search" - uses a more flexible search method
|
||||||
|
|
||||||
Note: that if more than one result is found, the image will be set as "Unknown" as there is no way for Gaseous to know which title is the correct one.
|
Note: that if more than one result is found, the image will be set as "Unknown" as there is no way for Gaseous to know which title is the correct one.
|
||||||
|
BIN
gaseous-server/.DS_Store
vendored
BIN
gaseous-server/.DS_Store
vendored
Binary file not shown.
120
gaseous-server/Classes/Bios.cs
Normal file
120
gaseous-server/Classes/Bios.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -58,36 +58,64 @@ namespace gaseous_server.Classes
|
|||||||
FileInfo fi = new FileInfo(GameFileImportPath);
|
FileInfo fi = new FileInfo(GameFileImportPath);
|
||||||
Common.hashObject hash = new Common.hashObject(GameFileImportPath);
|
Common.hashObject hash = new Common.hashObject(GameFileImportPath);
|
||||||
|
|
||||||
// check to make sure we don't already have this file imported
|
Models.PlatformMapping.PlatformMapItem? IsBios = Classes.Bios.BiosHashSignatureLookup(hash.md5hash);
|
||||||
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");
|
|
||||||
|
|
||||||
// process as a single file
|
if (IsBios == null)
|
||||||
Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
|
{
|
||||||
|
// 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
|
// process as a single file
|
||||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(discoveredSignature.Flags.IGDBPlatformId);
|
Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
|
||||||
if (determinedPlatform == null)
|
|
||||||
{
|
|
||||||
determinedPlatform = new IGDB.Models.Platform();
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
|
||||||
StoreROM(hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -107,6 +107,19 @@ namespace gaseous_server.Classes
|
|||||||
Path = (string)romDR["path"],
|
Path = (string)romDR["path"],
|
||||||
Source = (GameRomItem.SourceType)(Int32)romDR["metadatasource"]
|
Source = (GameRomItem.SourceType)(Int32)romDR["metadatasource"]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// check for a web emulator and update the romItem
|
||||||
|
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
|
||||||
|
{
|
||||||
|
if (platformMapping.IGDBId == romItem.PlatformId)
|
||||||
|
{
|
||||||
|
if (platformMapping.WebEmulator != null)
|
||||||
|
{
|
||||||
|
romItem.Emulator = platformMapping.WebEmulator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return romItem;
|
return romItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +128,9 @@ namespace gaseous_server.Classes
|
|||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
public long PlatformId { get; set; }
|
public long PlatformId { get; set; }
|
||||||
public IGDB.Models.Platform Platform { get; set; }
|
public IGDB.Models.Platform Platform { 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 string? Name { get; set; }
|
||||||
public long Size { get; set; }
|
public long Size { get; set; }
|
||||||
public string? CRC { get; set; }
|
public string? CRC { get; set; }
|
||||||
|
75
gaseous-server/Controllers/BiosController.cs
Normal file
75
gaseous-server/Controllers/BiosController.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -749,6 +749,7 @@ namespace gaseous_server.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[HttpHead]
|
||||||
[Route("{GameId}/roms/{RomId}/file")]
|
[Route("{GameId}/roms/{RomId}/file")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using gaseous_server.Classes;
|
||||||
|
|
||||||
namespace gaseous_server.Models
|
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
|
public static List<PlatformMapItem> PlatformMap
|
||||||
{
|
{
|
||||||
get
|
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
|
string rawJson = reader.ReadToEnd();
|
||||||
var assembly = Assembly.GetExecutingAssembly();
|
_PlatformMaps.Clear();
|
||||||
var resourceName = "gaseous_server.Support.PlatformMap.json";
|
_PlatformMaps = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _PlatformMaps;
|
return _PlatformMaps;
|
||||||
@@ -73,11 +73,28 @@ namespace gaseous_server.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class PlatformMapItem
|
public class PlatformMapItem
|
||||||
{
|
{
|
||||||
public int IGDBId { get; set; }
|
public int IGDBId { get; set; }
|
||||||
public string IGDBName { get; set; }
|
public string IGDBName { get; set; }
|
||||||
public List<string> AlternateNames { get; set; } = new List<string>();
|
public List<string> AlternateNames { get; set; } = new List<string>();
|
||||||
public List<string> KnownFileExtensions { get; set; } = new List<string>();
|
public List<string> KnownFileExtensions { get; set; } = new List<string>();
|
||||||
|
//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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -236,7 +236,7 @@ namespace gaseous_server.Models
|
|||||||
|
|
||||||
public class SignatureFlags
|
public class SignatureFlags
|
||||||
{
|
{
|
||||||
public int IGDBPlatformId { get; set; }
|
public long IGDBPlatformId { get; set; }
|
||||||
public string IGDBPlatformName { get; set; }
|
public string IGDBPlatformName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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");
|
Logging.Log(Logging.LogType.Information, "Startup", "Setting initial API key");
|
||||||
Config.SetSetting("API Key", APIKey.ToString());
|
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
|
// set up server
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
@@ -32,6 +37,9 @@ builder.Services.AddControllers().AddJsonOptions(x =>
|
|||||||
|
|
||||||
// suppress nulls
|
// suppress nulls
|
||||||
x.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
|
x.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
|
||||||
|
|
||||||
|
// set max depth
|
||||||
|
x.JsonSerializerOptions.MaxDepth = 64;
|
||||||
});
|
});
|
||||||
builder.Services.AddResponseCaching();
|
builder.Services.AddResponseCaching();
|
||||||
builder.Services.AddControllers(options =>
|
builder.Services.AddControllers(options =>
|
||||||
@@ -76,7 +84,11 @@ app.UseResponseCaching();
|
|||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseDefaultFiles();
|
app.UseDefaultFiles();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
ServeUnknownFileTypes = true, //allow unkown file types also to be served
|
||||||
|
DefaultContentType = "plain/text" //content type to returned if fileType is not known.
|
||||||
|
});
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
|
@@ -44,7 +44,31 @@
|
|||||||
],
|
],
|
||||||
"KnownFileExtensions": [
|
"KnownFileExtensions": [
|
||||||
".SMS"
|
".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,
|
"IGDBId": 29,
|
||||||
@@ -60,7 +84,11 @@
|
|||||||
".MD",
|
".MD",
|
||||||
".SG",
|
".SG",
|
||||||
".SMD"
|
".SMD"
|
||||||
]
|
],
|
||||||
|
"WebEmulator": {
|
||||||
|
"Type": "EmulatorJS",
|
||||||
|
"Core": "segaMD"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"IGDBId": 4,
|
"IGDBId": 4,
|
||||||
@@ -71,7 +99,11 @@
|
|||||||
],
|
],
|
||||||
"KnownFileExtensions": [
|
"KnownFileExtensions": [
|
||||||
".Z64"
|
".Z64"
|
||||||
]
|
],
|
||||||
|
"WebEmulator": {
|
||||||
|
"Type": "EmulatorJS",
|
||||||
|
"Core": "n64"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"IGDBId": 18,
|
"IGDBId": 18,
|
||||||
@@ -88,6 +120,72 @@
|
|||||||
".SFC",
|
".SFC",
|
||||||
".SMC",
|
".SMC",
|
||||||
".SWC"
|
".SWC"
|
||||||
]
|
],
|
||||||
|
"WebEmulator": {
|
||||||
|
"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": []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -14,9 +14,9 @@
|
|||||||
<DocumentationFile>bin\Debug\net7.0\gaseous-server.xml</DocumentationFile>
|
<DocumentationFile>bin\Debug\net7.0\gaseous-server.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<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="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" />
|
<PackageReference Include="IGDB" Version="2.3.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -105,6 +105,7 @@
|
|||||||
<Folder Include="Assets\Ratings\CLASS_IND\" />
|
<Folder Include="Assets\Ratings\CLASS_IND\" />
|
||||||
<Folder Include="wwwroot\fonts\" />
|
<Folder Include="wwwroot\fonts\" />
|
||||||
<Folder Include="wwwroot\pages\dialogs\" />
|
<Folder Include="wwwroot\pages\dialogs\" />
|
||||||
|
<Folder Include="wwwroot\pages\settings\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj">
|
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj">
|
||||||
@@ -119,6 +120,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Remove="Support\PlatformMap.json" />
|
<Content Remove="Support\PlatformMap.json" />
|
||||||
|
<Content Remove="wwwroot\pages\settings\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">
|
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">
|
||||||
|
BIN
gaseous-server/wwwroot/.DS_Store
vendored
BIN
gaseous-server/wwwroot/.DS_Store
vendored
Binary file not shown.
1
gaseous-server/wwwroot/emulators/EmulatorJS
Submodule
1
gaseous-server/wwwroot/emulators/EmulatorJS
Submodule
Submodule gaseous-server/wwwroot/emulators/EmulatorJS added at f7fa5d4148
BIN
gaseous-server/wwwroot/images/SettingsWallpaper.jpg
Normal file
BIN
gaseous-server/wwwroot/images/SettingsWallpaper.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 607 KiB |
@@ -3,10 +3,10 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link type="text/css" rel="stylesheet" href="/styles/style.css" />
|
<link type="text/css" rel="stylesheet" href="/styles/style.css" />
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="/scripts/jquery-3.6.0.min.js"></script>
|
||||||
<script src="https://momentjs.com/downloads/moment.js"></script>
|
<script src="/scripts/moment.js"></script>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
<link href="/styles/select2.min.css" rel="stylesheet" />
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
<script src="/scripts/select2.min.js"></script>
|
||||||
<script src="/scripts/main.js" type="text/javascript"></script>
|
<script src="/scripts/main.js" type="text/javascript"></script>
|
||||||
<script src="/scripts/filterformating.js" type="text/javascript"></script>
|
<script src="/scripts/filterformating.js" type="text/javascript"></script>
|
||||||
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
|
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<div id="banner_header">
|
<div id="banner_header">
|
||||||
<div id="banner_header_label">Gaseous Games</div>
|
<div id="banner_header_label">Gaseous Games</div>
|
||||||
</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" />
|
<img src="/images/cog.jpg" alt="System" id="banner_system_image" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
25
gaseous-server/wwwroot/pages/EmulatorJS.html
Normal file
25
gaseous-server/wwwroot/pages/EmulatorJS.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<div style='width:640px;height:480px;max-width:100%'>
|
||||||
|
<div id='game'></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type='text/javascript'>
|
||||||
|
EJS_player = '#game';
|
||||||
|
|
||||||
|
// Can also be fceumm or nestopia
|
||||||
|
EJS_core = urlParams.get('core');
|
||||||
|
|
||||||
|
// Lightgun
|
||||||
|
EJS_lightgun = false; // can be true or false
|
||||||
|
|
||||||
|
// URL to BIOS file
|
||||||
|
EJS_biosUrl = emuBios;
|
||||||
|
|
||||||
|
// URL to Game rom
|
||||||
|
EJS_gameUrl = decodeURIComponent(urlParams.get('rompath'));
|
||||||
|
|
||||||
|
// Path to the data directory
|
||||||
|
EJS_pathtodata = '/emulators/EmulatorJS/data/';
|
||||||
|
|
||||||
|
EJS_DEBUG_XX = true;
|
||||||
|
</script>
|
||||||
|
<script src='/emulators/EmulatorJS/data/loader.js'></script>
|
100
gaseous-server/wwwroot/pages/emulator.html
Normal file
100
gaseous-server/wwwroot/pages/emulator.html
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<div id="bgImage">
|
||||||
|
<div id="bgImage_Opacity"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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;
|
||||||
|
|
||||||
|
// load artwork
|
||||||
|
if (result.artworks) {
|
||||||
|
artworks = result.artworks.ids;
|
||||||
|
var startPos = randomIntFromInterval(0, result.artworks.ids.length);
|
||||||
|
artworksPosition = startPos;
|
||||||
|
rotateBackground();
|
||||||
|
} else {
|
||||||
|
if (result.cover) {
|
||||||
|
var bg = document.getElementById('bgImage');
|
||||||
|
bg.setAttribute('style', 'background-image: url("/api/v1/Games/' + gameId + '/cover/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (artworks[artworksPosition] == null) {
|
||||||
|
artworksPosition = 0;
|
||||||
|
}
|
||||||
|
var bg = document.getElementById('bgImage');
|
||||||
|
bg.setAttribute('style', 'background-image: url("/api/v1/Games/' + gameId + '/artwork/' + artworks[artworksPosition] + '/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
@@ -304,7 +304,7 @@
|
|||||||
var newTable = document.createElement('table');
|
var newTable = document.createElement('table');
|
||||||
newTable.className = 'romtable';
|
newTable.className = 'romtable';
|
||||||
newTable.setAttribute('cellspacing', 0);
|
newTable.setAttribute('cellspacing', 0);
|
||||||
newTable.appendChild(createTableRow(true, ['Name', 'Size', 'Media', '', '']));
|
newTable.appendChild(createTableRow(true, ['Name', 'Size', 'Media', '', '', '']));
|
||||||
|
|
||||||
var lastPlatform = '';
|
var lastPlatform = '';
|
||||||
for (var i = 0; i < result.length; i++) {
|
for (var i = 0; i < result.length; i++) {
|
||||||
@@ -312,18 +312,24 @@
|
|||||||
lastPlatform = result[i].platform.name;
|
lastPlatform = result[i].platform.name;
|
||||||
var platformRow = document.createElement('tr');
|
var platformRow = document.createElement('tr');
|
||||||
var platformHeader = document.createElement('th');
|
var platformHeader = document.createElement('th');
|
||||||
platformHeader.setAttribute('colspan', 4);
|
platformHeader.setAttribute('colspan', 6);
|
||||||
platformHeader.innerHTML = result[i].platform.name;
|
platformHeader.innerHTML = result[i].platform.name;
|
||||||
platformRow.appendChild(platformHeader);
|
platformRow.appendChild(platformHeader);
|
||||||
newTable.appendChild(platformRow);
|
newTable.appendChild(platformRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var launchButton = '';
|
||||||
|
if (result[i].emulator) {
|
||||||
|
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 = [
|
var newRow = [
|
||||||
'<a href="/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/file" class="romlink">' + result[i].name + '</a>',
|
'<a href="/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/file" class="romlink">' + result[i].name + '</a>',
|
||||||
formatBytes(result[i].size, 2),
|
formatBytes(result[i].size, 2),
|
||||||
result[i].romTypeMedia,
|
result[i].romTypeMedia,
|
||||||
result[i].mediaLabel,
|
result[i].mediaLabel,
|
||||||
'<span class="romlink" onclick="showDialog(\'rominfo\', ' + result[i].id + ');">...</span>'
|
launchButton,
|
||||||
|
'<div class="properties_button" onclick="showDialog(\'rominfo\', ' + result[i].id + ');">i</div>'
|
||||||
];
|
];
|
||||||
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
||||||
}
|
}
|
||||||
|
48
gaseous-server/wwwroot/pages/settings.html
Normal file
48
gaseous-server/wwwroot/pages/settings.html
Normal 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>
|
14
gaseous-server/wwwroot/pages/settings/about.html
Normal file
14
gaseous-server/wwwroot/pages/settings/about.html
Normal 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>
|
53
gaseous-server/wwwroot/pages/settings/bios.html
Normal file
53
gaseous-server/wwwroot/pages/settings/bios.html
Normal 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>
|
@@ -1,23 +1,20 @@
|
|||||||
<div id="gamepage">
|
<div id="gametitle">
|
||||||
<div id="gametitle">
|
<h1 id="gametitle_label">System</h1>
|
||||||
<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>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<h3>Background Tasks</h3>
|
||||||
function SystemLoadStatus() {
|
<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) {
|
ajaxCall('/api/v1/BackgroundTasks', 'GET', function (result) {
|
||||||
var newTable = document.createElement('table');
|
var newTable = document.createElement('table');
|
||||||
newTable.className = 'romtable';
|
newTable.className = 'romtable';
|
||||||
@@ -71,7 +68,7 @@
|
|||||||
|
|
||||||
var startButton = '';
|
var startButton = '';
|
||||||
if (result[i].itemState != "Running") {
|
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 = [
|
var newRow = [
|
||||||
@@ -111,7 +108,7 @@
|
|||||||
formatBytes(spaceUsedByOthers),
|
formatBytes(spaceUsedByOthers),
|
||||||
formatBytes(result.Paths[i].TotalSpace)
|
formatBytes(result.Paths[i].TotalSpace)
|
||||||
];
|
];
|
||||||
|
|
||||||
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
||||||
|
|
||||||
var spaceRow = document.createElement('tr');
|
var spaceRow = document.createElement('tr');
|
||||||
@@ -202,5 +199,4 @@
|
|||||||
SystemLoadSystemStatus();
|
SystemLoadSystemStatus();
|
||||||
setInterval(SystemLoadStatus, 60000);
|
setInterval(SystemLoadStatus, 60000);
|
||||||
SystemSignaturesStatus();
|
SystemSignaturesStatus();
|
||||||
setInterval(SystemSignaturesStatus, 300000);
|
setInterval(SystemSignaturesStatus, 300000);</script>
|
||||||
</script>
|
|
2
gaseous-server/wwwroot/scripts/jquery-3.6.0.min.js
vendored
Normal file
2
gaseous-server/wwwroot/scripts/jquery-3.6.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5685
gaseous-server/wwwroot/scripts/moment.js
Normal file
5685
gaseous-server/wwwroot/scripts/moment.js
Normal file
File diff suppressed because it is too large
Load Diff
2
gaseous-server/wwwroot/scripts/select2.min.js
vendored
Normal file
2
gaseous-server/wwwroot/scripts/select2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
gaseous-server/wwwroot/styles/select2.min.css
vendored
Normal file
1
gaseous-server/wwwroot/styles/select2.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -168,6 +168,7 @@ h3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter_header {
|
.filter_header {
|
||||||
|
font-weight: bold;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #2b2b2b;
|
background-color: #2b2b2b;
|
||||||
}
|
}
|
||||||
@@ -469,7 +470,7 @@ th {
|
|||||||
|
|
||||||
.romlink {
|
.romlink {
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
/*text-decoration: none;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.romlink:hover {
|
.romlink:hover {
|
||||||
@@ -478,6 +479,56 @@ th {
|
|||||||
cursor: pointer;
|
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 {
|
#gamedev_logo {
|
||||||
float: right;
|
float: right;
|
||||||
max-height: 48px;
|
max-height: 48px;
|
||||||
@@ -492,6 +543,8 @@ th {
|
|||||||
display: block;
|
display: block;
|
||||||
width: 150px;
|
width: 150px;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
|
background-color: #383838;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[name="properties_toc_item"] {
|
div[name="properties_toc_item"] {
|
||||||
@@ -518,6 +571,10 @@ div[name="properties_toc_item"]:hover {
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings_toc {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.select2-container--open .select2-dropdown--below,
|
.select2-container--open .select2-dropdown--below,
|
||||||
.select2-container--open .select2-dropdown--above {
|
.select2-container--open .select2-dropdown--above {
|
||||||
background: #2b2b2b;
|
background: #2b2b2b;
|
||||||
@@ -578,4 +635,36 @@ button:disabled {
|
|||||||
|
|
||||||
.redbutton:disabled {
|
.redbutton:disabled {
|
||||||
background-color: #555;
|
background-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
#emulator {
|
||||||
|
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;
|
||||||
}
|
}
|
@@ -335,6 +335,14 @@ namespace gaseous_tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string LibraryBIOSDirectory
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(LibraryRootDirectory, "BIOS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string LibraryMetadataDirectory
|
public string LibraryMetadataDirectory
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -385,6 +393,7 @@ namespace gaseous_tools
|
|||||||
if (!Directory.Exists(LibraryRootDirectory)) { Directory.CreateDirectory(LibraryRootDirectory); }
|
if (!Directory.Exists(LibraryRootDirectory)) { Directory.CreateDirectory(LibraryRootDirectory); }
|
||||||
if (!Directory.Exists(LibraryImportDirectory)) { Directory.CreateDirectory(LibraryImportDirectory); }
|
if (!Directory.Exists(LibraryImportDirectory)) { Directory.CreateDirectory(LibraryImportDirectory); }
|
||||||
if (!Directory.Exists(LibraryDataDirectory)) { Directory.CreateDirectory(LibraryDataDirectory); }
|
if (!Directory.Exists(LibraryDataDirectory)) { Directory.CreateDirectory(LibraryDataDirectory); }
|
||||||
|
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
|
||||||
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
|
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
|
||||||
if (!Directory.Exists(LibrarySignatureImportDirectory)) { Directory.CreateDirectory(LibrarySignatureImportDirectory); }
|
if (!Directory.Exists(LibrarySignatureImportDirectory)) { Directory.CreateDirectory(LibrarySignatureImportDirectory); }
|
||||||
if (!Directory.Exists(LibrarySignatureImportDirectory_TOSEC)) { Directory.CreateDirectory(LibrarySignatureImportDirectory_TOSEC); }
|
if (!Directory.Exists(LibrarySignatureImportDirectory_TOSEC)) { Directory.CreateDirectory(LibrarySignatureImportDirectory_TOSEC); }
|
||||||
|
Reference in New Issue
Block a user