EmulatorJS - First Version (#23)

* feat: added EmulatorJS support for Mega Drive, NES, and N64 (see: #15)

* doc: updated attribution in README.MD to include EmulatorJS

* ci: updated action to include submodules
This commit is contained in:
Michael Green
2023-07-13 13:31:38 +10:00
committed by GitHub
parent b010f9742b
commit 7a8e445471
17 changed files with 140 additions and 6 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -12,6 +12,8 @@ jobs:
-
name: Checkout
uses: actions/checkout@v3
with:
submodules: 'true'
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2

3
.gitmodules vendored
View File

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

View File

@@ -16,6 +16,7 @@ The following projects are used by Gaseous
* https://github.com/JamesNK/Newtonsoft.Json
* https://www.nuget.org/packages/MySql.Data/8.0.32.1
* https://github.com/kamranayub/igdb-dotnet
* https://github.com/EmulatorJS/EmulatorJS
## 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).

Binary file not shown.

View File

@@ -107,6 +107,19 @@ namespace gaseous_server.Classes
Path = (string)romDR["path"],
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;
}
@@ -115,6 +128,7 @@ 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 string? Name { get; set; }
public long Size { get; set; }

View File

@@ -749,6 +749,7 @@ namespace gaseous_server.Controllers
}
[HttpGet]
[HttpHead]
[Route("{GameId}/roms/{RomId}/file")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]

View File

@@ -78,6 +78,8 @@ namespace gaseous_server.Models
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; }
}
}
}

View File

@@ -76,7 +76,11 @@ app.UseResponseCaching();
app.UseAuthorization();
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();

View File

@@ -60,7 +60,11 @@
".MD",
".SG",
".SMD"
]
],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "segaMD"
}
},
{
"IGDBId": 4,
@@ -71,7 +75,11 @@
],
"KnownFileExtensions": [
".Z64"
]
],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "n64"
}
},
{
"IGDBId": 18,
@@ -88,6 +96,10 @@
".SFC",
".SMC",
".SWC"
]
],
"WebEmulator": {
"Type": "EmulatorJS",
"Core": "nes"
}
}
]

View File

@@ -119,6 +119,10 @@
</ItemGroup>
<ItemGroup>
<Content Remove="Support\PlatformMap.json" />
<Content Remove="wwwroot\styles\select2.min.css" />
<Content Remove="wwwroot\scripts\select2.min.js" />
<Content Remove="wwwroot\scripts\moment.js" />
<Content Remove="wwwroot\scripts\jquery-3.6.0.min.js" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">
@@ -165,4 +169,9 @@
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Ten.svg" />
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Twelve.svg" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\EmulatorJS\data\old\sega-old-wasm.data">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

Binary file not shown.

View 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 = ''; // example: https://dl.dropboxusercontent.com/s/[random-code]/bios.bin
// URL to Game rom
EJS_gameUrl = decodeURIComponent(urlParams.get('rompath'));
// Path to the data directory
EJS_pathtodata = '/EmulatorJS/data/';
EJS_DEBUG_XX = false;
</script>
<script src='/EmulatorJS/data/loader.js'></script>

View File

@@ -0,0 +1,48 @@
<div id="bgImage">
<div id="bgImage_Opacity"></div>
</div>
<div id="emulator"></div>
<script type="text/javascript">
const urlParams = new URLSearchParams(window.location.search);
var gameId = urlParams.get('gameid');
var gameData;
var artworks = null;
var artworksPosition = 0;
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);');
}
}
});
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);');
}
}
switch (urlParams.get('engine')) {
case 'EmulatorJS':
$('#emulator').load('/pages/EmulatorJS.html');
break;
}
</script>

View File

@@ -304,7 +304,7 @@
var newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, ['Name', 'Size', 'Media', '', '']));
newTable.appendChild(createTableRow(true, ['Name', 'Size', 'Media', '', '', '']));
var lastPlatform = '';
for (var i = 0; i < result.length; i++) {
@@ -318,11 +318,17 @@
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 + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/file') + '" class="romlink">Start</a>';
}
var newRow = [
'<a href="/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/file" class="romlink">' + result[i].name + '</a>',
formatBytes(result[i].size, 2),
result[i].romTypeMedia,
result[i].mediaLabel,
launchButton,
'<span class="romlink" onclick="showDialog(\'rominfo\', ' + result[i].id + ');">...</span>'
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));

View File

@@ -579,3 +579,9 @@ button:disabled {
.redbutton:disabled {
background-color: #555;
}
#emulator {
margin: 0 auto;
width: 640px;
padding-top: 100px;
}