198 lines
7.4 KiB
C#
198 lines
7.4 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using Debug = UnityEngine.Debug;
|
|
|
|
namespace SplashEdit.EditorCode
|
|
{
|
|
/// <summary>
|
|
/// Downloads and manages mkpsxiso — the tool that builds PlayStation CD images
|
|
/// from an XML catalog. Used for the ISO build target.
|
|
/// https://github.com/Lameguy64/mkpsxiso
|
|
/// </summary>
|
|
public static class MkpsxisoDownloader
|
|
{
|
|
private const string MKPSXISO_VERSION = "2.20";
|
|
private const string MKPSXISO_RELEASE_BASE =
|
|
"https://github.com/Lameguy64/mkpsxiso/releases/download/v" + MKPSXISO_VERSION + "/";
|
|
|
|
private static readonly HttpClient _http = new HttpClient();
|
|
|
|
/// <summary>
|
|
/// Install directory for mkpsxiso inside .tools/
|
|
/// </summary>
|
|
public static string MkpsxisoDir =>
|
|
Path.Combine(SplashBuildPaths.ToolsDir, "mkpsxiso");
|
|
|
|
/// <summary>
|
|
/// Path to the mkpsxiso binary.
|
|
/// </summary>
|
|
public static string MkpsxisoBinary
|
|
{
|
|
get
|
|
{
|
|
if (Application.platform == RuntimePlatform.WindowsEditor)
|
|
return Path.Combine(MkpsxisoDir, "mkpsxiso.exe");
|
|
return Path.Combine(MkpsxisoDir, "bin", "mkpsxiso");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if mkpsxiso is installed and ready to use.
|
|
/// </summary>
|
|
public static bool IsInstalled() => File.Exists(MkpsxisoBinary);
|
|
|
|
/// <summary>
|
|
/// Downloads and installs mkpsxiso from the official GitHub releases.
|
|
/// </summary>
|
|
public static async Task<bool> DownloadAndInstall(Action<string> log = null)
|
|
{
|
|
string archiveName;
|
|
switch (Application.platform)
|
|
{
|
|
case RuntimePlatform.WindowsEditor:
|
|
archiveName = $"mkpsxiso-{MKPSXISO_VERSION}-win64.zip";
|
|
break;
|
|
case RuntimePlatform.LinuxEditor:
|
|
archiveName = $"mkpsxiso-{MKPSXISO_VERSION}-Linux.zip";
|
|
break;
|
|
case RuntimePlatform.OSXEditor:
|
|
archiveName = $"mkpsxiso-{MKPSXISO_VERSION}-Darwin.zip";
|
|
break;
|
|
default:
|
|
log?.Invoke("Unsupported platform for mkpsxiso.");
|
|
return false;
|
|
}
|
|
|
|
string downloadUrl = $"{MKPSXISO_RELEASE_BASE}{archiveName}";
|
|
log?.Invoke($"Downloading mkpsxiso: {downloadUrl}");
|
|
|
|
try
|
|
{
|
|
string tempFile = Path.Combine(Path.GetTempPath(), archiveName);
|
|
EditorUtility.DisplayProgressBar("Downloading mkpsxiso", "Downloading...", 0.1f);
|
|
|
|
using (var client = new System.Net.WebClient())
|
|
{
|
|
client.Headers.Add("User-Agent", "SplashEdit/1.0");
|
|
|
|
client.DownloadProgressChanged += (s, e) =>
|
|
{
|
|
float progress = 0.1f + 0.8f * (e.ProgressPercentage / 100f);
|
|
string sizeMB = $"{e.BytesReceived / (1024 * 1024)}/{e.TotalBytesToReceive / (1024 * 1024)} MB";
|
|
EditorUtility.DisplayProgressBar("Downloading mkpsxiso", $"Downloading... {sizeMB}", progress);
|
|
};
|
|
|
|
await client.DownloadFileTaskAsync(new Uri(downloadUrl), tempFile);
|
|
}
|
|
|
|
log?.Invoke("Extracting...");
|
|
EditorUtility.DisplayProgressBar("Installing mkpsxiso", "Extracting...", 0.9f);
|
|
|
|
string installDir = MkpsxisoDir;
|
|
if (Directory.Exists(installDir))
|
|
Directory.Delete(installDir, true);
|
|
Directory.CreateDirectory(installDir);
|
|
|
|
System.IO.Compression.ZipFile.ExtractToDirectory(tempFile, installDir);
|
|
|
|
// Fix nested directory (archives often have one extra level)
|
|
SplashEdit.RuntimeCode.Utils.FixNestedDirectory(installDir);
|
|
|
|
try { File.Delete(tempFile); } catch { }
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
if (IsInstalled())
|
|
{
|
|
// Make executable on Linux
|
|
if (Application.platform != RuntimePlatform.WindowsEditor)
|
|
{
|
|
var chmod = Process.Start("chmod", $"+x \"{MkpsxisoBinary}\"");
|
|
chmod?.WaitForExit();
|
|
}
|
|
log?.Invoke("mkpsxiso installed successfully!");
|
|
return true;
|
|
}
|
|
|
|
log?.Invoke($"mkpsxiso binary not found at: {MkpsxisoBinary}");
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log?.Invoke($"mkpsxiso download failed: {ex.Message}");
|
|
EditorUtility.ClearProgressBar();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs mkpsxiso with the given XML catalog to produce a BIN/CUE image.
|
|
/// </summary>
|
|
/// <param name="xmlPath">Path to the mkpsxiso XML catalog.</param>
|
|
/// <param name="outputBin">Override output .bin path (optional, uses XML default if null).</param>
|
|
/// <param name="outputCue">Override output .cue path (optional, uses XML default if null).</param>
|
|
/// <param name="log">Logging callback.</param>
|
|
/// <returns>True if mkpsxiso succeeded.</returns>
|
|
public static bool BuildISO(string xmlPath, string outputBin = null,
|
|
string outputCue = null, Action<string> log = null)
|
|
{
|
|
if (!IsInstalled())
|
|
{
|
|
log?.Invoke("mkpsxiso is not installed.");
|
|
return false;
|
|
}
|
|
|
|
// Build arguments
|
|
string args = $"-y \"{xmlPath}\"";
|
|
if (!string.IsNullOrEmpty(outputBin))
|
|
args += $" -o \"{outputBin}\"";
|
|
if (!string.IsNullOrEmpty(outputCue))
|
|
args += $" -c \"{outputCue}\"";
|
|
|
|
log?.Invoke($"Running: mkpsxiso {args}");
|
|
|
|
var psi = new ProcessStartInfo
|
|
{
|
|
FileName = MkpsxisoBinary,
|
|
Arguments = args,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true
|
|
};
|
|
|
|
try
|
|
{
|
|
var process = Process.Start(psi);
|
|
string stdout = process.StandardOutput.ReadToEnd();
|
|
string stderr = process.StandardError.ReadToEnd();
|
|
process.WaitForExit();
|
|
|
|
if (!string.IsNullOrEmpty(stdout))
|
|
log?.Invoke(stdout.Trim());
|
|
|
|
if (process.ExitCode != 0)
|
|
{
|
|
if (!string.IsNullOrEmpty(stderr))
|
|
log?.Invoke($"mkpsxiso error: {stderr.Trim()}");
|
|
log?.Invoke($"mkpsxiso exited with code {process.ExitCode}");
|
|
return false;
|
|
}
|
|
|
|
log?.Invoke("ISO image built successfully.");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log?.Invoke($"mkpsxiso execution failed: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|