Broken RUntime
This commit is contained in:
230
Editor/Core/MkpsxisoDownloader.cs
Normal file
230
Editor/Core/MkpsxisoDownloader.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
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, "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 response = await _http.GetAsync(downloadUrl,
|
||||
HttpCompletionOption.ResponseHeadersRead))
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
long? totalBytes = response.Content.Headers.ContentLength;
|
||||
long downloaded = 0;
|
||||
|
||||
using (var fs = File.Create(tempFile))
|
||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||
{
|
||||
byte[] buffer = new byte[81920];
|
||||
int bytesRead;
|
||||
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
await fs.WriteAsync(buffer, 0, bytesRead);
|
||||
downloaded += bytesRead;
|
||||
if (totalBytes.HasValue)
|
||||
{
|
||||
float progress = (float)downloaded / totalBytes.Value;
|
||||
EditorUtility.DisplayProgressBar("Downloading mkpsxiso",
|
||||
$"{downloaded / 1024}/{totalBytes.Value / 1024} KB", progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
FixNestedDirectory(installDir);
|
||||
|
||||
try { File.Delete(tempFile); } catch { }
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
if (IsInstalled())
|
||||
{
|
||||
// Make executable on Linux/Mac
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixNestedDirectory(string dir)
|
||||
{
|
||||
// If extraction created exactly one subdirectory, flatten it
|
||||
var subdirs = Directory.GetDirectories(dir);
|
||||
if (subdirs.Length == 1)
|
||||
{
|
||||
string nested = subdirs[0];
|
||||
foreach (string file in Directory.GetFiles(nested))
|
||||
{
|
||||
string dest = Path.Combine(dir, Path.GetFileName(file));
|
||||
if (!File.Exists(dest)) File.Move(file, dest);
|
||||
}
|
||||
foreach (string sub in Directory.GetDirectories(nested))
|
||||
{
|
||||
string dest = Path.Combine(dir, Path.GetFileName(sub));
|
||||
if (!Directory.Exists(dest)) Directory.Move(sub, dest);
|
||||
}
|
||||
try { Directory.Delete(nested, true); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user