Attempt to locate `.cue` for PSX `.bin` before synthesising one

see #4146
This commit is contained in:
YoshiRulz 2025-01-05 22:10:32 +10:00
parent 04955ea228
commit ddd14d5274
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
3 changed files with 84 additions and 0 deletions

View File

@ -486,6 +486,21 @@ namespace BizHawk.Client.Common
}
break;
case VSystemID.Raw.PSX when ext is ".bin":
if (TryLoadSiblingCue(
nextComm,
binFilePath: file.Name,
forcedCoreName: forcedCoreName,
out var nextEmulator1,
out var game1,
out cancel))
{
nextEmulator = nextEmulator1;
rom = null;
game = game1;
return;
}
if (cancel) break; //TODO return? the cancel earlier in this method doesn't
const string FILE_EXT_CUE = ".cue";
var crc32Digest = CRC32Checksum.ComputeDigestHex(file.GetStream().ReadAllBytes()); // slow!
var cuePath = Path.Combine(Path.GetTempPath(), $"synthesised for {crc32Digest}{FILE_EXT_CUE}");
@ -534,6 +549,70 @@ namespace BizHawk.Client.Common
nextEmulator = MakeCoreFromCoreInventory(cip, forcedCoreName);
}
private bool TryLoadSiblingCue(
CoreComm nextComm,
string binFilePath,
string forcedCoreName,
out IEmulator nextEmulator,
out GameInfo game,
out bool cancel)
{
nextEmulator = null;
game = null;
cancel = false;
const string FILE_EXT_CUE = ".cue";
const string FMT_STR_ASK = "Found \"{0}\".\nLoad that instead? Select \"No\" to synthesise a new .cue file for this game.";
HawkFile/*?*/ hfChosen = null;
//TODO can probably express this logic flow in a better way
HawkFile hfMatching = new(binFilePath.RemoveSuffix(".bin") + ".cue");
if (hfMatching.Exists)
{
var result = nextComm.Question(string.Format(FMT_STR_ASK, hfMatching.Name));
if (result is null)
{
cancel = true;
return false;
}
if (result is true)
{
hfChosen = hfMatching;
}
}
if (hfChosen is null)
{
var soleCueSiblingPath = Directory.EnumerateFiles(Path.GetDirectoryName(binFilePath))
.Where(static s => s.EndsWithOrdinal(FILE_EXT_CUE))
.Except([ hfMatching.Name ]) // seen but denied by user; don't prompt for the same file again
.SingleOrDefault();
HawkFile hfSoleSibling = soleCueSiblingPath is null ? null : new(soleCueSiblingPath);
if (hfSoleSibling is { Exists: true })
{
var result = nextComm.Question(string.Format(FMT_STR_ASK, hfSoleSibling.Name));
if (result is null)
{
cancel = true;
return false;
}
if (result is true)
{
hfChosen = hfSoleSibling;
}
}
}
if (hfChosen is null) return false;
return LoadDisc(
path: hfChosen.Name,
nextComm,
file: hfChosen,
ext: FILE_EXT_CUE,
forcedCoreName: forcedCoreName,
out nextEmulator,
out game);
}
private void LoadPSF(string path, CoreComm nextComm, HawkFile file, out IEmulator nextEmulator, out RomGame rom, out GameInfo game)
{
// TODO: Why does the PSF loader need CbDeflater provided? Surely this is a matter internal to it.

View File

@ -258,6 +258,7 @@ namespace BizHawk.Client.EmuHawk
return new CoreComm(
message => this.ModalMessageBox(message, "Warning", EMsgBoxIcon.Warning),
AddOnScreenMessage,
text => this.ModalMessageBox3(icon: EMsgBoxIcon.Question, caption: "ROM loader", text: text),
cfp,
prefs,
new OpenGLProvider());

View File

@ -8,9 +8,12 @@ namespace BizHawk.Emulation.Common
/// </summary>
public class CoreComm
{
public readonly Func<string, bool?> Question;
public CoreComm(
Action<string> showMessage,
Action<string, int?> notifyMessage,
Func<string, bool?> question,
ICoreFileProvider coreFileProvider,
CorePreferencesFlags prefs,
IOpenGLProvider oglProvider
@ -18,6 +21,7 @@ namespace BizHawk.Emulation.Common
{
ShowMessage = showMessage;
Notify = notifyMessage;
Question = question;
CoreFileProvider = coreFileProvider;
CorePreferences = prefs;
OpenGLProvider = oglProvider;