Revamp of BIOS handling (#423)

Many of the platforms are similar enough to other platforms that they'll
share the same BIOS files.

The current storage method stores BIOS files per platform, meaning that
files can be duplicated multiple times to satisfy the requirements of
each platform.

This change stores the files as their hash with a .bios extension
(example: `85ad74194e87c08904327de1a9443b7a.bios`) in a flat directory
structure. This allows BIOS files that are used by multiple platforms to
be shared without duplication.
This commit is contained in:
Michael Green
2024-09-15 03:35:36 -07:00
committed by GitHub
parent 070589f718
commit c8140d7178
5 changed files with 77 additions and 41 deletions

View File

@@ -11,6 +11,33 @@ namespace gaseous_server.Classes
} }
public static void MigrateToNewFolderStructure()
{
// migrate from old BIOS file structure which had each bios file inside a folder named for the platform to the new structure which has each file in a subdirectory named after the MD5 hash
if (Directory.Exists(Config.LibraryConfiguration.LibraryBIOSDirectory))
{
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
{
if (platformMapping.Bios != null)
{
foreach (Models.PlatformMapping.PlatformMapItem.EmulatorBiosItem emulatorBiosItem in platformMapping.Bios)
{
string oldBiosPath = Path.Combine(Config.LibraryConfiguration.LibraryBIOSDirectory, platformMapping.IGDBSlug.ToString(), emulatorBiosItem.filename);
string newBiosPath = Path.Combine(Config.LibraryConfiguration.LibraryFirmwareDirectory, emulatorBiosItem.hash + ".bios");
if (File.Exists(oldBiosPath))
{
File.Copy(oldBiosPath, newBiosPath, true);
}
}
}
}
// remove old BIOS folder structure
Directory.Delete(Config.LibraryConfiguration.LibraryBIOSDirectory, true);
}
}
public static Models.PlatformMapping.PlatformMapItem? BiosHashSignatureLookup(string MD5) public static Models.PlatformMapping.PlatformMapItem? BiosHashSignatureLookup(string MD5)
{ {
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap) foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
@@ -96,10 +123,11 @@ namespace gaseous_server.Classes
{ {
get get
{ {
return Path.Combine(Config.LibraryConfiguration.LibraryBIOSDirectory, platformslug, base.filename); return Path.Combine(Config.LibraryConfiguration.LibraryFirmwareDirectory, hash + ".bios");
} }
} }
public bool Available { public bool Available
{
get get
{ {
bool fileExists = File.Exists(biosPath); bool fileExists = File.Exists(biosPath);

View File

@@ -575,6 +575,14 @@ namespace gaseous_server.Classes
} }
} }
public string LibraryFirmwareDirectory
{
get
{
return Path.Combine(LibraryRootDirectory, "Firmware");
}
}
public string LibraryUploadDirectory public string LibraryUploadDirectory
{ {
get get
@@ -656,7 +664,8 @@ namespace gaseous_server.Classes
{ {
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(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); } // if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
if (!Directory.Exists(LibraryFirmwareDirectory)) { Directory.CreateDirectory(LibraryFirmwareDirectory); }
if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); } if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); }
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); } if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
if (!Directory.Exists(LibraryTempDirectory)) { Directory.CreateDirectory(LibraryTempDirectory); } if (!Directory.Exists(LibraryTempDirectory)) { Directory.CreateDirectory(LibraryTempDirectory); }

View File

@@ -151,11 +151,8 @@ namespace gaseous_server.Classes
{ {
if (biosItem.hash == hash.md5hash) if (biosItem.hash == hash.md5hash)
{ {
string biosPath = biosItem.biosPath.Replace(biosItem.filename, ""); string biosPath = Path.Combine(Config.LibraryConfiguration.LibraryFirmwareDirectory, biosItem.hash + ".bios");
if (!Directory.Exists(biosPath)) Logging.Log(Logging.LogType.Information, "Import Game", " " + GameFileImportPath + " is a BIOS file - moving to " + biosPath);
{
Directory.CreateDirectory(biosPath);
}
File.Move(GameFileImportPath, biosItem.biosPath, true); File.Move(GameFileImportPath, biosItem.biosPath, true);

View File

@@ -10,6 +10,8 @@ using Asp.Versioning;
using Authentication; using Authentication;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using gaseous_server.Models; using gaseous_server.Models;
using IGDB.Models;
using gaseous_server.Classes.Metadata;
namespace gaseous_server.Controllers namespace gaseous_server.Controllers
{ {
@@ -62,25 +64,15 @@ namespace gaseous_server.Controllers
{ {
try try
{ {
Platform platform = Platforms.GetPlatform(PlatformId);
PlatformMapping.PlatformMapItem platformMap = PlatformMapping.GetPlatformMap(PlatformId);
List<string> biosHashes = new List<string>();
if (GameId == -1 || filtered == false) if (GameId == -1 || filtered == false)
{ {
IGDB.Models.Platform platform = Classes.Metadata.Platforms.GetPlatform(PlatformId); // get all bios files for selected platform
biosHashes.AddRange(platformMap.EnabledBIOSHashes);
string biosPath = Path.Combine(Config.LibraryConfiguration.LibraryBIOSDirectory, platform.Slug);
string tempFile = Path.GetTempFileName();
using (FileStream zipFile = System.IO.File.Create(tempFile))
using (var zipArchive = new ZipArchive(zipFile, ZipArchiveMode.Create))
{
foreach (string file in Directory.GetFiles(biosPath))
{
zipArchive.CreateEntryFromFile(file, Path.GetFileName(file));
}
}
var stream = new FileStream(tempFile, FileMode.Open);
return File(stream, "application/zip", platform.Slug + ".zip");
} }
else else
{ {
@@ -90,24 +82,31 @@ namespace gaseous_server.Controllers
PlatformMapping platformMapping = new PlatformMapping(); PlatformMapping platformMapping = new PlatformMapping();
PlatformMapping.PlatformMapItem userPlatformMap = platformMapping.GetUserPlatformMap(user.Id, PlatformId, GameId); PlatformMapping.PlatformMapItem userPlatformMap = platformMapping.GetUserPlatformMap(user.Id, PlatformId, GameId);
biosHashes.AddRange(userPlatformMap.EnabledBIOSHashes);
}
// build zip file // build zip file
string tempFile = Path.GetTempFileName(); string tempFile = Path.GetTempFileName();
using (FileStream zipFile = System.IO.File.Create(tempFile)) using (FileStream zipFile = System.IO.File.Create(tempFile))
using (var zipArchive = new ZipArchive(zipFile, ZipArchiveMode.Create)) using (var zipArchive = new ZipArchive(zipFile, ZipArchiveMode.Create))
{ {
foreach (Bios.BiosItem bios in GetBios(PlatformId, true)) foreach (string hash in biosHashes)
{ {
if (userPlatformMap.EnabledBIOSHashes.Contains(bios.hash)) // get the bios data for the hash
foreach (PlatformMapping.PlatformMapItem.EmulatorBiosItem bios in platformMap.Bios)
{ {
zipArchive.CreateEntryFromFile(bios.biosPath, bios.filename); if (bios.hash == hash)
{
// add the bios file to the zip
zipArchive.CreateEntryFromFile(Path.Combine(Config.LibraryConfiguration.LibraryFirmwareDirectory, hash + ".bios"), bios.filename);
}
} }
} }
} }
var stream = new FileStream(tempFile, FileMode.Open); var stream = new FileStream(tempFile, FileMode.Open);
return File(stream, "application/zip", userPlatformMap.IGDBSlug + ".zip"); return File(stream, "application/zip", platform.Slug + ".zip");
}
} }
catch catch
{ {

View File

@@ -338,6 +338,9 @@ gaseous_server.Classes.Metadata.Platforms.AssignAllPlatformsToGameIdZero();
// extract platform map if not present // extract platform map if not present
PlatformMapping.ExtractPlatformMap(); PlatformMapping.ExtractPlatformMap();
// migrate old firmware directory structure to new style
Bios.MigrateToNewFolderStructure();
// add background tasks // add background tasks
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem( ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.SignatureIngestor) ProcessQueue.QueueItemType.SignatureIngestor)