added a bin to iso converter
All checks were successful
Java CI / test (push) Successful in 1m29s

This commit is contained in:
WeeXnes 2025-04-27 20:20:51 +02:00
parent 312afabfdc
commit 4eb2d47adf
6 changed files with 422 additions and 18 deletions

View file

@ -10,20 +10,7 @@
Title="Install Game"
WindowStartupLocation="CenterScreen"
Loaded="Control_OnLoaded"
Background="#201c29"
SystemDecorations="None">
<Grid RowDefinitions="20, *">
<Grid Grid.Row="0">
<Border Background="#35313d"
PointerPressed="WindowDrag">
<Grid ColumnDefinitions="*, 20">
<TextBlock Name="WindowTitle" FontSize="12" Text="Install Game" Padding="8,0,0,0" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="#4b4753" PointerPressed="WindowClose">
<TextBlock FontSize="12" Text="×" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</Grid>
</Border>
</Grid>
Background="#201c29">
<Grid Grid.Row="1" ColumnDefinitions="Auto,Auto,*" Margin="20">
<!-- PS2 Cover -->
<Border Width="205" Height="292" Background="Black" CornerRadius="5" HorizontalAlignment="Left"
@ -60,6 +47,4 @@
</StackPanel>
</Grid>
</Grid>
</Grid>
</Window>

View file

@ -0,0 +1,31 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="PS2_Manager.ConvertGameWindow"
Title="Convert BIN to ISO"
Height="349"
Width="598"
CanResize="False"
WindowStartupLocation="CenterScreen"
Background="#201c29"
Loaded="Control_OnLoaded"
Closing="Window_OnClosing">
<Grid RowDefinitions="80, *, 80">
<TextBlock Name="Label_1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border Grid.Row="1" CornerRadius="10" Background="#35313d" Margin="10, 0">
<Grid ColumnDefinitions="*,*,*">
<Border Grid.Column="0" Background="#201c29" Margin="10" CornerRadius="7">
</Border>
<Border Grid.Column="2" Background="#201c29" Margin="10" CornerRadius="7">
</Border>
</Grid>
</Border>
<Button Click="ConvertButton_OnClick" Name="ConvertButton" Grid.Row="2" Content="Convert" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0"/>
</Grid>
</Window>

View file

@ -0,0 +1,69 @@
using System.ComponentModel;
using System.IO;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using PS2_Manager.Core.IO.DiscImage;
using PS2_Manager.Core.IO.DiscImage.Type;
namespace PS2_Manager;
public partial class ConvertGameWindow : Window
{
public bool PreventClose { get; set; } = false;
public string binPath { get; set; }
public string isoPath { get; set; }
public BackgroundWorker Worker { get; set; }
public ConvertGameWindow(string path)
{
this.binPath = path;
this.isoPath = Path.ChangeExtension(path, ".iso");
InitializeComponent();
Worker = new BackgroundWorker();
Worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted;
Worker.DoWork += WorkerOnDoWork;
}
private void WorkerOnDoWork(object? sender, DoWorkEventArgs e)
{
Console.Info("Worker has started");
Iso9660Conv conv = new Iso9660Conv();
conv.DiscImage = new BinType(this.binPath);
conv.Convert(this.isoPath);
}
private void WorkerOnRunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e)
{
Console.Info("File Converted");
OpenInstallWindow();
}
public void OpenInstallWindow()
{
Console.Success("Converted Successfully");
this.PreventClose = false;
new AddGameWindow(this.isoPath).Show();
this.Close();
}
private void Control_OnLoaded(object? sender, RoutedEventArgs e)
{
this.Label_1.Text = Path.GetFileName(this.binPath) + " needs to be converted into a ISO file";
}
private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{
if(this.PreventClose)
e.Cancel = true;
}
private void ConvertButton_OnClick(object? sender, RoutedEventArgs e)
{
this.PreventClose = true;
ConvertButton.Content = "Converting...";
Console.Warning("Converting " + this.binPath + " to ISO");
Worker.RunWorkerAsync();
}
}

View file

@ -23,7 +23,7 @@ public static class Globals
{
public static FilePickerFileType PS2Game { get; } = new("PS2 Game")
{
Patterns = new[] { "*.iso" }
Patterns = new[] { "*.iso", "*.bin" }
};
public static FilePickerFileType PS2Cover { get; } = new("PS2 Cover")
{

View file

@ -0,0 +1,310 @@
using System;
using System.IO;
#nullable disable
namespace PS2_Manager.Core.IO.DiscImage.Type
{
public class BinType : IDiscImage
{
private SectorStructure _sector;
private string _imagePath;
public string ImagePath => this._imagePath;
public BinType(string imagePath)
{
this._imagePath = imagePath;
this._sector = new SectorStructure();
}
public long FirstDumpSector() => 0;
public SectorStructure GetSectorStucture()
{
this._sector = new SectorStructure();
FileStream input = (FileStream) null;
BinaryReader binaryReader = (BinaryReader) null;
try
{
input = new FileStream(this._imagePath, FileMode.Open, FileAccess.Read, FileShare.Read);
binaryReader = new BinaryReader((Stream) input);
byte[] numArray = new byte[16];
binaryReader.Read(numArray, 0, numArray.Length);
if (BytesHelper.CompareBytesArray(BytesHelper.CopyRange(numArray, 0, Iso9660Conv.SYNC_HEADER.Length), Iso9660Conv.SYNC_HEADER))
{
switch (numArray[15])
{
case 1:
this._sector.sectorLength = 2352;
this._sector.userDataOffset = 16;
break;
case 2:
this._sector.sectorLength = 2352;
this._sector.userDataOffset = 24;
break;
}
}
else
{
this._sector.sectorLength = 2336;
this._sector.userDataOffset = 8;
}
}
catch (Exception ex)
{
}
finally
{
binaryReader?.Close();
if (input != null)
{
input.Close();
input.Dispose();
}
}
return this._sector;
}
}
}
namespace PS2_Manager.Core.IO.DiscImage
{
public interface IDiscImage
{
string ImagePath { get; }
long FirstDumpSector();
SectorStructure GetSectorStucture();
}
}
namespace PS2_Manager.Core.IO.DiscImage
{
public struct SectorStructure(int length, int dataOffset)
{
public int sectorLength = length;
public int userDataOffset = dataOffset;
}
}
#nullable disable
namespace PS2_Manager.Core.IO.DiscImage
{
public class Iso9660Conv
{
private const int ISO_SECTOR_SIZE = 2048;
private const int BUFFER_LENGTH_FACTOR = 64;
private const uint FAT32_DISK_LIMIT = 4294967295;
private SectorStructure _sectorStruct;
private long _startFirstSector;
private IDiscImage _discImage;
private FileStream _fsSrc = (FileStream) null;
private FileStream _fsDst = (FileStream) null;
private BinaryReader _brSrc = (BinaryReader) null;
private BinaryWriter _wrDst = (BinaryWriter) null;
internal static byte[] SYNC_HEADER = new byte[12]
{
(byte) 0,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
byte.MaxValue,
(byte) 0
};
public event EventHandler<Iso9660CreatorEventArgs> Progression;
public event EventHandler Terminate;
public IDiscImage DiscImage
{
get => this._discImage;
set
{
this._discImage = value;
this.SetDiscImage();
}
}
public Iso9660Conv()
{
}
public Iso9660Conv(IDiscImage converter)
{
this._discImage = converter;
this.SetDiscImage();
}
public void Close()
{
if (this._brSrc != null)
this._brSrc.Close();
if (this._wrDst != null)
this._wrDst.Close();
if (this._fsSrc != null)
{
this._fsSrc.Close();
this._fsSrc.Dispose();
}
if (this._fsDst == null)
return;
this._fsDst.Close();
this._fsDst.Dispose();
}
public void Convert(IDiscImage discImage, string isoDestination)
{
this._discImage = discImage != null ? discImage : throw new ArgumentNullException(nameof (discImage), "The IDiscImage interface is null.");
this.SetDiscImage();
this.Convert(isoDestination);
}
public void Convert(string isoDestination)
{
if (this._discImage == null)
throw new ArgumentNullException("The IDiscImage interface is null. You can specified an instance from DiscImage propertie.");
if (isoDestination == string.Empty)
throw new ArgumentNullException("output", "The output file path must not be null.");
if (this._sectorStruct.sectorLength == 0)
throw new IOException("The source image file format is unknown.");
if (!File.Exists(this._discImage.ImagePath))
throw new FileNotFoundException("The souce image file does not exists.");
DriveInfo driveInfo = new DriveInfo(Path.GetPathRoot(isoDestination));
long num1 = new FileInfo(this._discImage.ImagePath).Length / (long) this._sectorStruct.sectorLength * 2048L - this._startFirstSector;
if (driveInfo.DriveFormat.Equals("FAT32") && num1 > (long) uint.MaxValue)
throw new IOException("Not enough space on FAT32 destination drive.");
if (driveInfo.TotalSize < num1)
throw new IOException("Not enough space on the destination drive.");
try
{
this._fsSrc = new FileStream(this._discImage.ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read);
this._brSrc = new BinaryReader((Stream) this._fsSrc);
this._fsDst = new FileStream(isoDestination, FileMode.Create, FileAccess.Write, FileShare.None);
this._wrDst = new BinaryWriter((Stream) this._fsDst);
this._brSrc.BaseStream.Seek(this._startFirstSector, SeekOrigin.Begin);
byte[] numArray = new byte[this._sectorStruct.sectorLength * 64];
int num2;
do
{
num2 = this._brSrc.Read(numArray, 0, numArray.Length);
if (num2 == this._sectorStruct.sectorLength * 64)
this._wrDst.Write(this.CleanUserDataBuffer(numArray, 131072U));
else if (num2 > 0)
{
uint uint32 = System.Convert.ToUInt32(num2 / this._sectorStruct.sectorLength * 2048);
this._wrDst.Write(this.CleanUserDataBuffer(numArray, uint32));
}
if (this.Progression != null)
this.Progression((object) null, new Iso9660CreatorEventArgs(this._wrDst.BaseStream.Position, this._brSrc.BaseStream.Length));
}
while (num2 > 0 && this._wrDst.BaseStream.Position != num1);
if (this.Terminate == null)
return;
this.Terminate((object) null, EventArgs.Empty);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
this.Close();
}
}
private byte[] CleanUserDataBuffer(byte[] source, uint dataSize)
{
byte[] dst = new byte[(int) dataSize];
int num = 0;
for (int index = 0; (long) index < (long) dataSize; index += 2048)
{
if ((long) dataSize - (long) index >= 2048L)
{
Buffer.BlockCopy((Array) source, num * this._sectorStruct.sectorLength + this._sectorStruct.userDataOffset, (Array) dst, num * 2048, 2048);
++num;
}
else
Buffer.BlockCopy((Array) source, this._sectorStruct.sectorLength * num + this._sectorStruct.userDataOffset, (Array) dst, num * 2048, (int) ((long) dataSize - (long) index));
}
return dst;
}
private void SetDiscImage()
{
this._sectorStruct = this._discImage.GetSectorStucture();
this._startFirstSector = this._discImage.FirstDumpSector();
}
}
}
#nullable disable
namespace PS2_Manager.Core
{
internal static class BytesHelper
{
public static bool CompareBytesArray(byte[] a, byte[] b)
{
if (a == null || b == null || a.Length != b.Length)
return false;
for (int index = 0; index < a.Length; ++index)
{
if ((int) a[index] != (int) b[index])
return false;
}
return true;
}
public static byte[] CopyRange(byte[] source, int srcOffset, int length)
{
byte[] dst = new byte[length];
if (source.Length < length)
return (byte[]) null;
Buffer.BlockCopy((Array) source, srcOffset, (Array) dst, 0, dst.Length);
return dst;
}
}
}
#nullable disable
namespace PS2_Manager.Core.IO.DiscImage
{
public class Iso9660CreatorEventArgs : EventArgs
{
private long _bytesWritted;
private long _discLength;
public long DiscLength => this._discLength;
public long BytesWritted => this._bytesWritted;
public Iso9660CreatorEventArgs()
{
}
public Iso9660CreatorEventArgs(long writted, long discLength)
{
this._bytesWritted = writted;
this._discLength = discLength;
}
}
}

View file

@ -117,7 +117,16 @@ public partial class MainWindow : Window
if (files.Count >= 1)
{
Console.Info("AddGameWindow was called for " + files[0].Path.LocalPath);
new AddGameWindow(files[0].Path.LocalPath).Show();
string ext = Path.GetExtension(files[0].Path.LocalPath);
if (ext == ".bin")
{
new ConvertGameWindow(files[0].Path.LocalPath).Show();
}
else if (ext == ".iso")
{
new AddGameWindow(files[0].Path.LocalPath).Show();
}
}
else
{