Compare commits

..

No commits in common. "master" and "experimental" have entirely different histories.

37 changed files with 272 additions and 947 deletions

View file

@ -18,22 +18,6 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Extract FileVersion from .csproj
id: get_version
run: |
version=$(grep -oPm1 "(?<=<FileVersion>)[^<]+" PS2_Manager/PS2_Manager.csproj)
echo "PS2Manager version: $version"
echo "version=$version" >> $GITHUB_OUTPUT
- name: Check if release tag already exists
run: |
tag="v${{ steps.get_version.outputs.version }}"
if git ls-remote --tags origin | grep -q "refs/tags/$tag"; then
echo "Release tag $tag already exists. Cancelling workflow."
exit 1
fi
- name: Build the project (Linux x64) - name: Build the project (Linux x64)
run: | run: |
dotnet publish ./PS2_Manager/PS2_Manager.csproj \ dotnet publish ./PS2_Manager/PS2_Manager.csproj \
@ -54,27 +38,6 @@ jobs:
-o ./output_win -o ./output_win
- name: Download appimagetool
run: |
curl -L -o appimagetool-x86_64.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
- name: Build AppImage
run: |
mkdir -p PS2_Manager.AppDir/usr/bin
cp -r ./output_linux/* PS2_Manager.AppDir/usr/bin/
cp PS2_Manager/Assets/AppRun PS2_Manager.AppDir/
cp PS2_Manager/Assets/ps2manager.desktop PS2_Manager.AppDir/
cp PS2_Manager/Assets/ps2manager.png PS2_Manager.AppDir/
chmod +x PS2_Manager.AppDir/AppRun
./appimagetool-x86_64.AppImage PS2_Manager.AppDir
mkdir -p release
mv PS2_Manager-x86_64.AppImage release/PS2Manager_Linux_x64.AppImage
- name: Pack Releases into Zips - name: Pack Releases into Zips
run: | run: |
mkdir -p ./release mkdir -p ./release
@ -83,12 +46,21 @@ jobs:
rm -rf ./output_linux ./output_win rm -rf ./output_linux ./output_win
- name: Generate tag name based on current date and time
id: generate_tag
run: |
# Get current date and time, format as 'YYYY-MM-DD-HHMMSS'
current_date=$(date +"%Y-%m-%d-%H%M%S")
echo "Generated tag name: $current_date"
echo "::set-output name=tag_name::$current_date"
- name: Create Git tag - name: Create Git tag
run: | run: |
git config user.name "WeeXnes" git tag ${{ steps.generate_tag.outputs.tag_name }}
git config user.email "somtrigi@gmail.com" git push origin ${{ steps.generate_tag.outputs.tag_name }}
git tag v${{ steps.get_version.outputs.version }}
git push origin v${{ steps.get_version.outputs.version }}
- name: Upload to Forgejo - name: Upload to Forgejo
uses: actions/forgejo-release@v2.6.0 uses: actions/forgejo-release@v2.6.0
@ -97,6 +69,6 @@ jobs:
url: https://git.weexnes.dev/ url: https://git.weexnes.dev/
repo: WeeXnes/ps2_manager repo: WeeXnes/ps2_manager
token: ${{ secrets.RELEASE_TOKEN }} token: ${{ secrets.RELEASE_TOKEN }}
tag: v${{ steps.get_version.outputs.version }} tag: ${{ steps.generate_tag.outputs.tag_name }}
release-dir: release release-dir: release
release-notes: "Automated release for version ${{ steps.get_version.outputs.version }}" release-notes: "Automated release from CI"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 223 KiB

View file

@ -3,19 +3,32 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Height="389" Height="349"
Width="598" Width="598"
CanResize="False" CanResize="False"
x:Class="PS2_Manager.AddGameWindow" x:Class="PS2_Manager.AddGameWindow"
Title="Install Game" Title="Install Game"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Loaded="Control_OnLoaded" Loaded="Control_OnLoaded"
Background="#201c29"> 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>
<Grid Grid.Row="1" ColumnDefinitions="Auto,Auto,*" Margin="20"> <Grid Grid.Row="1" ColumnDefinitions="Auto,Auto,*" Margin="20">
<!-- PS2 Cover --> <!-- PS2 Cover -->
<Border Width="205" Height="292" Background="Black" CornerRadius="5" HorizontalAlignment="Left" <Border Width="205" Height="292" Background="Black" CornerRadius="5" HorizontalAlignment="Left"
PointerPressed="CoverImage_OnPointerPressed"> PointerPressed="CoverImage_OnPointerPressed">
<Image Name="CoverImage" Source="Assets/missing.png" Stretch="UniformToFill"/> <Image Name="CoverImage" Source="Images/missing.png" Stretch="UniformToFill"/>
</Border> </Border>
<!-- Spacer --> <!-- Spacer -->
@ -39,10 +52,6 @@
<TextBlock Text="ISO Path"/> <TextBlock Text="ISO Path"/>
<TextBox Name="IsoPathBox" IsEnabled="False"/> <TextBox Name="IsoPathBox" IsEnabled="False"/>
<TextBlock Text="Installation Method"/>
<ComboBox Name="InstallationMethodBox" Margin="5,0" HorizontalAlignment="Stretch" SelectionChanged="InstallationMethodBox_OnSelectionChanged">
</ComboBox>
<Button Name="InstallButton" Content="Install Game" HorizontalAlignment="Center" <Button Name="InstallButton" Content="Install Game" HorizontalAlignment="Center"
Background="#aa4de8" Background="#aa4de8"
Foreground="Black" Foreground="Black"
@ -51,4 +60,6 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid> </Grid>
</Grid>
</Window> </Window>

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
@ -23,9 +22,6 @@ public partial class AddGameWindow : Window
{ {
this.newGame = new Game(filePath); this.newGame = new Game(filePath);
InitializeComponent(); InitializeComponent();
InstallationMethodBox.Items.Add("Move");
InstallationMethodBox.Items.Add("Copy");
InstallationMethodBox.SelectedItem = settings.preferred_installation_method.GetValue<string>() ?? "Move";
} }
private void RefreshPreview() private void RefreshPreview()
@ -61,7 +57,6 @@ public partial class AddGameWindow : Window
{ {
InstallButton.IsEnabled = false; InstallButton.IsEnabled = false;
GameNameBox.IsEnabled = false; GameNameBox.IsEnabled = false;
InstallationMethodBox.IsEnabled = false;
InstallButton.Content = "Installing..."; InstallButton.Content = "Installing...";
newGame.Install(); newGame.Install();
newGame.InstallProgress.ValueChanged += () => newGame.InstallProgress.ValueChanged += () =>
@ -105,9 +100,4 @@ public partial class AddGameWindow : Window
Console.Error("OpenFilePicker was called but Canceled or no Files selected"); Console.Error("OpenFilePicker was called but Canceled or no Files selected");
} }
} }
private void InstallationMethodBox_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
settings.preferred_installation_method.SetValue(InstallationMethodBox.SelectionBoxItem?.ToString());
}
} }

View file

@ -51,6 +51,7 @@ public partial class App : Application
setupWindow.Closed += (_, _) => setupWindow.Closed += (_, _) =>
{ {
// Replace MainWindow after setup finishes
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
var mainWindow = new MainWindow(); var mainWindow = new MainWindow();

View file

@ -1,4 +0,0 @@
#!/bin/bash
HERE="$(dirname "$(readlink -f "$0")")"
exec "$HERE/usr/bin/PS2_Manager" "$@"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 KiB

View file

@ -1,6 +0,0 @@
[Desktop Entry]
Type=Application
Name=PS2 Manager
Exec=PS2_Manager
Icon=ps2manager
Categories=Utility;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 KiB

View file

@ -1,33 +0,0 @@
<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="260"
Width="398"
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="100,*,100">
<Border Grid.Column="0" Background="#201c29" Margin="10" CornerRadius="7">
<Image Margin="10" RenderOptions.BitmapInterpolationMode="HighQuality" Source="Assets/bin.png"/>
</Border>
<TextBlock Grid.Column="1" FontSize="25" Text="→" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border Grid.Column="2" Background="#201c29" Margin="10" CornerRadius="7">
<Image Margin="10" RenderOptions.BitmapInterpolationMode="HighQuality" Source="Assets/cd.png"/>
</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

@ -1,69 +0,0 @@
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

@ -1,23 +0,0 @@
using System;
namespace PS2_Manager.Core;
public static class Artwork
{
public enum Type
{
Front,
Back,
Disc
}
public static Type NextType(Type _type)
{
return (Type)(((int)_type + 1) % Enum.GetValues(typeof(Type)).Length);
}
public static Type PrevType(Type _type)
{
return (Type)(((int)_type - 1 + Enum.GetValues(typeof(Type)).Length) % Enum.GetValues(typeof(Type)).Length);
}
}

View file

@ -1,118 +0,0 @@
using System.Collections.Generic;
using System.IO;
namespace PS2_Manager.Core;
public class Config
{
private string path { get; set; }
public string MemoryCard1 { get; set; }
public string MemoryCard2 { get; set; }
public bool Mode1 { get; set; }
public bool Mode2 { get; set; }
public bool Mode3 { get; set; }
public bool Mode4 { get; set; }
public bool Mode5 { get; set; }
public bool Mode6 { get; set; }
public Config(string path)
{
this.path = path;
this.ParseConfig(path);
}
public override string ToString()
{
return $"VMCs: {MemoryCard1} - {MemoryCard2}\n" +
$"Mode 1: {Mode1}\n" +
$"Mode 2: {Mode2}\n" +
$"Mode 3: {Mode3}\n" +
$"Mode 4: {Mode4}\n" +
$"Mode 5: {Mode5}\n" +
$"Mode 6: {Mode6}\n";
}
private void FromCompatibility(int value)
{
Mode1 = (value & (1 << 0)) != 0;
Mode2 = (value & (1 << 1)) != 0;
Mode3 = (value & (1 << 2)) != 0;
Mode4 = (value & (1 << 3)) != 0;
Mode5 = (value & (1 << 4)) != 0;
Mode6 = (value & (1 << 5)) != 0;
}
private int ToCompatibility()
{
int value = 0;
if (Mode1) value |= (1 << 0);
if (Mode2) value |= (1 << 1);
if (Mode3) value |= (1 << 2);
if (Mode4) value |= (1 << 3);
if (Mode5) value |= (1 << 4);
if (Mode6) value |= (1 << 5);
return value;
}
public void SaveConfig()
{
var lines = new List<string>();
if (!string.IsNullOrEmpty(MemoryCard1))
lines.Add($"$VMC_0={MemoryCard1}");
if (!string.IsNullOrEmpty(MemoryCard2))
lines.Add($"$VMC_1={MemoryCard2}");
lines.Add($"$Compatibility={ToCompatibility()}");
lines.Add($"$ConfigSource=1");
File.WriteAllLines(path, lines);
}
private void ParseConfig(string path)
{
if (!File.Exists(path))
return;
var lines = File.ReadAllLines(path);
foreach (var rawLine in lines)
{
var line = rawLine.Trim();
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#") || line.StartsWith("//"))
continue;
var parts = line.Split('=', 2);
if (parts.Length != 2)
continue;
var key = parts[0].Trim();
var value = parts[1].Trim();
switch (key)
{
case "$Compatibility":
if (int.TryParse(value, out int compat))
this.FromCompatibility(compat);
break;
case "$VMC_0":
this.MemoryCard1 = value;
break;
case "$VMC_1":
this.MemoryCard2 = value;
break;
case "$ConfigSource":
// Optional: You can store/use this if needed
break;
}
}
}
}

View file

@ -21,7 +21,7 @@ public static class ConfigUtils
return; return;
config.SetValue(getStrType(_type), getStrName(_type), _value.ToString()); config.SetValue(getStrType(_type), getStrName(_type), _value.ToString());
} }
public static T? GetValue<T>(this Enum _type) public static T GetValue<T>(this Enum _type)
{ {
if (!checkIfInitialized()) if (!checkIfInitialized())
return default(T); return default(T);

View file

@ -1,35 +0,0 @@
using System;
using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
namespace PS2_Manager.Core;
public class DiscIcon
{
public bool ShowDVD { get; set; }
public bool ShowCD { get; set; }
public DiscType type { get; set; }
public DiscIcon(DiscType _type)
{
this.type = _type;
if (type == DiscType.CD)
{
this.ShowCD = true;
this.ShowDVD = false;
}else if (type == DiscType.DVD)
{
this.ShowCD = false;
this.ShowDVD = true;
}
}
}
public enum DiscType
{
DVD,
CD
}

View file

@ -12,7 +12,6 @@ using Avalonia.Threading;
using Microsoft.VisualBasic.CompilerServices; using Microsoft.VisualBasic.CompilerServices;
using Nocksoft.IO.ConfigFiles; using Nocksoft.IO.ConfigFiles;
namespace PS2_Manager.Core; namespace PS2_Manager.Core;
public class Game public class Game
@ -23,8 +22,6 @@ public class Game
public Bitmap? ArtworkFront { get; set; } public Bitmap? ArtworkFront { get; set; }
public Bitmap? ArtworkBack { get; set; } public Bitmap? ArtworkBack { get; set; }
public Bitmap? ArtworkDVD { get; set; } public Bitmap? ArtworkDVD { get; set; }
public Config? Config { get; set; }
public DiscIcon Icon { get; set; }
public EventHandler? InstallationFinished { get; set; } public EventHandler? InstallationFinished { get; set; }
public UpdateVar<double> InstallProgress { get; private set; } public UpdateVar<double> InstallProgress { get; private set; }
@ -32,16 +29,6 @@ public class Game
{ {
this.GamePath = isoPath; this.GamePath = isoPath;
this.GameID = ISO.GetSerial(isoPath); this.GameID = ISO.GetSerial(isoPath);
FileInfo fileInfo = new FileInfo(isoPath);
if (fileInfo.Length < 1_000_000_000)
{
this.Icon = new DiscIcon(DiscType.CD);
}
else
{
this.Icon = new DiscIcon(DiscType.DVD);
}
this.Config = new Config(this.GetConfigPath());
if (!installed) if (!installed)
{ {
this.Name = this.GetGameTitle(); this.Name = this.GetGameTitle();
@ -58,8 +45,6 @@ public class Game
} }
} }
public void ChangeName(string newName) public void ChangeName(string newName)
{ {
Console.Info("Changing name of " + this.Name + " to " + newName); Console.Info("Changing name of " + this.Name + " to " + newName);
@ -119,9 +104,6 @@ public class Game
{ {
this.InstallProgress = new UpdateVar<double>(); this.InstallProgress = new UpdateVar<double>();
await this.CopyIsoWithProgressAsync(); await this.CopyIsoWithProgressAsync();
string installationMethod = settings.preferred_installation_method.GetValue<string>() ?? "Move";
if(installationMethod == "Move")
this.Uninstall();
} }
private Bitmap DownloadCover(Artwork.Type type) private Bitmap DownloadCover(Artwork.Type type)
@ -170,14 +152,11 @@ public class Game
public async Task CopyIsoWithProgressAsync() public async Task CopyIsoWithProgressAsync()
{ {
Console.Info("Copying ISO file for " + this + "..."); Console.Info("Copying ISO file for " + this + "...");
string targetDirectory = ""; string targetDirectory = settings.library_path.GetValue<string>();
if (this.Icon.type == DiscType.DVD) Util.CheckDir(Path.Combine(targetDirectory, "DVD"));
targetDirectory = Path.Combine(settings.library_path.GetValue<string>(), "DVD");
if (this.Icon.type == DiscType.CD)
targetDirectory = Path.Combine(settings.library_path.GetValue<string>(), "CD");
string newFileName = $"{this.GameID}.{this.Name}.iso"; string newFileName = $"{this.GameID}.{this.Name}.iso";
string destPath = Path.Combine(targetDirectory, newFileName); string destPath = Path.Combine(Path.Combine(targetDirectory, "DVD"), newFileName);
const int bufferSize = 1024 * 1024; const int bufferSize = 1024 * 1024;
byte[] buffer = new byte[bufferSize]; byte[] buffer = new byte[bufferSize];
@ -206,6 +185,10 @@ public class Game
MainWindow.RefreshGamesListTrigger?.Invoke(this, EventArgs.Empty); MainWindow.RefreshGamesListTrigger?.Invoke(this, EventArgs.Empty);
} }
public Bitmap? LoadCover(Artwork.Type artworkType) public Bitmap? LoadCover(Artwork.Type artworkType)
{ {
Console.Info("Loading " + artworkType + " Artwork for " + this.GameID); Console.Info("Loading " + artworkType + " Artwork for " + this.GameID);
@ -266,32 +249,115 @@ public class Game
{ {
return this.Name + " -> " + this.GameID; return this.Name + " -> " + this.GameID;
} }
}
private string GetConfigPath() public class GameConfig
{
public string MemoryCard1 { get; set; }
public string MemoryCard2 { get; set; }
public bool Mode1 { get; set; }
public bool Mode2 { get; set; }
public bool Mode3 { get; set; }
public bool Mode4 { get; set; }
public bool Mode5 { get; set; }
public bool Mode6 { get; set; }
public override string ToString()
{ {
return Path.Combine(Path.Combine(settings.library_path.GetValue<string>(), "CFG"), this.GameID + ".cfg"); return $"VMCs: {MemoryCard1} - {MemoryCard2}\n" +
$"Mode 1: {Mode1}\n" +
$"Mode 2: {Mode2}\n" +
$"Mode 3: {Mode3}\n" +
$"Mode 4: {Mode4}\n" +
$"Mode 5: {Mode5}\n" +
$"Mode 6: {Mode6}\n";
} }
private string GetArtworkPath(Artwork.Type artworkType)
private void FromCompatibility(int value)
{ {
string targetDirectory = settings.library_path.GetValue<string>(); Mode1 = (value & (1 << 0)) != 0;
string modifier = ""; Mode2 = (value & (1 << 1)) != 0;
switch (artworkType) Mode3 = (value & (1 << 2)) != 0;
Mode4 = (value & (1 << 3)) != 0;
Mode5 = (value & (1 << 4)) != 0;
Mode6 = (value & (1 << 5)) != 0;
}
private int ToCompatibility()
{
int value = 0;
if (Mode1) value |= (1 << 0);
if (Mode2) value |= (1 << 1);
if (Mode3) value |= (1 << 2);
if (Mode4) value |= (1 << 3);
if (Mode5) value |= (1 << 4);
if (Mode6) value |= (1 << 5);
return value;
}
public void ParseConfig(string path)
{
if (!File.Exists(path))
throw new FileNotFoundException("Config file not found.", path);
var lines = File.ReadAllLines(path);
foreach (var rawLine in lines)
{ {
case Artwork.Type.Front: var line = rawLine.Trim();
modifier = "_COV.png";
break; // Skip empty or comment lines
case Artwork.Type.Back: if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#") || line.StartsWith("//"))
modifier = "_COV2.png"; continue;
break;
case Artwork.Type.Disc: var parts = line.Split('=', 2);
modifier = "_ICO.png"; if (parts.Length != 2)
break; continue;
var key = parts[0].Trim();
var value = parts[1].Trim();
switch (key)
{
case "$Compatibility":
if (int.TryParse(value, out int compat))
this.FromCompatibility(compat);
break;
case "$VMC_0":
this.MemoryCard1 = value;
break;
case "$VMC_1":
this.MemoryCard2 = value;
break;
case "$ConfigSource":
// Optional: You can store/use this if needed
break;
}
} }
return Path.Combine(Path.Combine(targetDirectory, "ART"), this.GameID + modifier);
} }
} }
public static class Artwork
{
public enum Type
{
Front,
Back,
Disc
}
public static Type NextType(Type _type)
{
return (Type)(((int)_type + 1) % Enum.GetValues(typeof(Type)).Length);
}
public static Type PrevType(Type _type)
{
return (Type)(((int)_type - 1 + Enum.GetValues(typeof(Type)).Length) % Enum.GetValues(typeof(Type)).Length);
}
}

View file

@ -4,7 +4,6 @@ using System.Threading.Tasks;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Microsoft.VisualBasic.CompilerServices;
namespace PS2_Manager.Core; namespace PS2_Manager.Core;
@ -24,7 +23,7 @@ public static class Globals
{ {
public static FilePickerFileType PS2Game { get; } = new("PS2 Game") public static FilePickerFileType PS2Game { get; } = new("PS2 Game")
{ {
Patterns = new[] { "*.iso", "*.bin" } Patterns = new[] { "*.iso" }
}; };
public static FilePickerFileType PS2Cover { get; } = new("PS2 Cover") public static FilePickerFileType PS2Cover { get; } = new("PS2 Cover")
{ {
@ -35,8 +34,7 @@ public static class Globals
public enum settings public enum settings
{ {
library_path, library_path
preferred_installation_method
} }
public class UpdateVar<T> public class UpdateVar<T>

View file

@ -1,310 +0,0 @@
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

@ -31,16 +31,8 @@ public static class Util
public static void CheckDir(string path) public static void CheckDir(string path)
{ {
//Console.Info("Checking directory: " + path); if(!Directory.Exists(path))
if (!Directory.Exists(path))
{
Console.Error("Directory " + path + " wasn't found, creating now.");
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
}
else
{
Console.Success("Directory was found: " + path);
}
} }
public static string FormatFileSize(long bytes) public static string FormatFileSize(long bytes)
{ {

View file

@ -0,0 +1,8 @@
<UserControl 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"
x:Class="PS2_Manager.GameInfo">
</UserControl>

View file

@ -0,0 +1,29 @@
using System;
using System.IO;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using PS2_Manager.Core;
namespace PS2_Manager;
public partial class GameInfo : UserControl
{
public Game game { get; set; }
public GameInfo(Game _game)
{
InitializeComponent();
this.game = _game;
}
}

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -10,7 +10,7 @@
Width="990" Width="990"
Height="520" Height="520"
MinHeight="490" MinHeight="490"
MinWidth="875" MinWidth="600"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Loaded="Control_OnLoaded" Loaded="Control_OnLoaded"
Foreground="White"> Foreground="White">
@ -25,16 +25,11 @@
<Border Background="Transparent" Padding="10"> <Border Background="Transparent" Padding="10">
<Border.ContextMenu> <Border.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="Add New Game" Click="OpenFileButton_Clicked"/>
<MenuItem Header="Remove Game" Click="DeleteButton"/> <MenuItem Header="Remove Game" Click="DeleteButton"/>
<MenuItem Header="Show Details"/> <MenuItem Header="Show Details"/>
</ContextMenu> </ContextMenu>
</Border.ContextMenu> </Border.ContextMenu>
<Grid ColumnDefinitions="30, 5,*"> <TextBlock Foreground="White" Text="{Binding Name}"/>
<Image IsVisible="{Binding Icon.ShowDVD}" Grid.Column="0" RenderOptions.BitmapInterpolationMode="HighQuality" Source="Assets/dvd.png"/>
<Image IsVisible="{Binding Icon.ShowCD}" Grid.Column="0" RenderOptions.BitmapInterpolationMode="HighQuality" Source="Assets/cd.png"/>
<TextBlock Grid.Column="2" Foreground="White" Text="{Binding Name}" VerticalAlignment="Center"/>
</Grid>
</Border> </Border>
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
@ -69,8 +64,7 @@
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Center" VerticalAlignment="Center"
Spacing="10"> Spacing="10">
<TextBlock Text="" <TextBlock Text="Welcome to the PS2 Games Manager"
Name="WelcomeTextTop"
HorizontalAlignment="Center" HorizontalAlignment="Center"
TextAlignment="Center" TextAlignment="Center"
FontSize="18" FontSize="18"
@ -98,31 +92,7 @@
<StackPanel Orientation="Vertical" Margin="10"> <StackPanel Orientation="Vertical" Margin="10">
<TextBlock Foreground="White" Text="Display Name:" HorizontalAlignment="Center" Padding="0,10"/> <TextBlock Foreground="White" Text="Display Name:" HorizontalAlignment="Center" Padding="0,10"/>
<TextBox Foreground="White" Name="NameTextBox_Edit"/> <TextBox Foreground="White" Name="NameTextBox_Edit"/>
<Separator Margin="0,10"/> <Separator/>
<Grid Grid.ColumnDefinitions="*,120,*,120,*">
<Border Grid.Column="1" Background="#35313d" Padding="0,5" CornerRadius="5">
<StackPanel>
<Image RenderOptions.BitmapInterpolationMode="HighQuality" Source="Assets/vmc.png"/>
<ComboBox Name="VMC_1" Margin="5,0" HorizontalAlignment="Stretch" SelectionChanged="VMC_1_OnSelectionChanged"/>
</StackPanel>
</Border>
<Border Grid.Column="3" Background="#35313d" Padding="0,5" CornerRadius="5">
<StackPanel>
<Image RenderOptions.BitmapInterpolationMode="HighQuality" Source="Assets/vmc.png"/>
<ComboBox Name="VMC_2" Margin="5,0" HorizontalAlignment="Stretch" SelectionChanged="VMC_2_OnSelectionChanged"/>
</StackPanel>
</Border>
</Grid>
<Separator Margin="0,10"/>
<Grid Grid.RowDefinitions="*,*,*" Grid.ColumnDefinitions="*,120,*,120,*">
<ToggleSwitch Name="toggle_mode1" Content="Mode 1" Grid.Row="0" Grid.Column="1" IsCheckedChanged="Toggle_mode_OnIsCheckedChanged"/>
<ToggleSwitch Name="toggle_mode2" Content="Mode 2" Grid.Row="1" Grid.Column="1" IsCheckedChanged="Toggle_mode_OnIsCheckedChanged"/>
<ToggleSwitch Name="toggle_mode3" Content="Mode 3" Grid.Row="2" Grid.Column="1" IsCheckedChanged="Toggle_mode_OnIsCheckedChanged"/>
<ToggleSwitch Name="toggle_mode4" Content="Mode 4" Grid.Row="0" Grid.Column="3" IsCheckedChanged="Toggle_mode_OnIsCheckedChanged"/>
<ToggleSwitch Name="toggle_mode5" Content="Mode 5" Grid.Row="1" Grid.Column="3" IsCheckedChanged="Toggle_mode_OnIsCheckedChanged"/>
<ToggleSwitch Name="toggle_mode6" Content="Mode 6" Grid.Row="2" Grid.Column="3" IsCheckedChanged="Toggle_mode_OnIsCheckedChanged"/>
</Grid>
<Separator Margin="0,10"/>
<Button Foreground="White" Content="Calculate Checksums" Click="ChecksumButtonOnClick" HorizontalAlignment="Stretch"></Button> <Button Foreground="White" Content="Calculate Checksums" Click="ChecksumButtonOnClick" HorizontalAlignment="Stretch"></Button>
<Border Background="#35313d" CornerRadius="5" Padding="10" Margin="0,5" IsVisible="False" Name="ChecksumArea"> <Border Background="#35313d" CornerRadius="5" Padding="10" Margin="0,5" IsVisible="False" Name="ChecksumArea">
<StackPanel> <StackPanel>
@ -157,7 +127,7 @@
<Border Grid.Column="1" Width="205" Height="292" Background="Transparent" CornerRadius="5" HorizontalAlignment="Center" VerticalAlignment="Center" <Border Grid.Column="1" Width="205" Height="292" Background="Transparent" CornerRadius="5" HorizontalAlignment="Center" VerticalAlignment="Center"
PointerPressed="CoverImage_OnPointerPressed" Name="CoverContainer"> PointerPressed="CoverImage_OnPointerPressed" Name="CoverContainer">
<Grid> <Grid>
<Image Name="CoverImage" Source="Assets/missing.png" Stretch="UniformToFill"/> <Image Name="CoverImage" Source="Images/missing.png" Stretch="UniformToFill"/>
<TextBlock Name="CoverTextHint" HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="False"/> <TextBlock Name="CoverTextHint" HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="False"/>
</Grid> </Grid>
</Border> </Border>

View file

@ -4,7 +4,6 @@ using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
@ -12,7 +11,6 @@ using Avalonia.Media;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using DiscUtils;
using PS2_Manager.Core; using PS2_Manager.Core;
namespace PS2_Manager; namespace PS2_Manager;
@ -24,7 +22,6 @@ public partial class MainWindow : Window
public UpdateVar<Artwork.Type> ArtworkType { get; set; } = new UpdateVar<Artwork.Type>(); public UpdateVar<Artwork.Type> ArtworkType { get; set; } = new UpdateVar<Artwork.Type>();
public UpdateVar<string> MD5Hash { get; set; } = new UpdateVar<string>(); public UpdateVar<string> MD5Hash { get; set; } = new UpdateVar<string>();
public UpdateVar<string> SHA1Hash { get; set; } = new UpdateVar<string>(); public UpdateVar<string> SHA1Hash { get; set; } = new UpdateVar<string>();
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
@ -91,16 +88,21 @@ public partial class MainWindow : Window
{ {
ChecksumArea.IsVisible = false; ChecksumArea.IsVisible = false;
NameTextBox_Edit.Text = selectedGame.Name; NameTextBox_Edit.Text = selectedGame.Name;
VMC_1.SelectedItem = selectedGame.Config?.MemoryCard1;
VMC_2.SelectedItem = selectedGame.Config?.MemoryCard2;
toggle_mode1.IsChecked = selectedGame.Config?.Mode1;
toggle_mode2.IsChecked = selectedGame.Config?.Mode2;
toggle_mode3.IsChecked = selectedGame.Config?.Mode3;
toggle_mode4.IsChecked = selectedGame.Config?.Mode4;
toggle_mode5.IsChecked = selectedGame.Config?.Mode5;
toggle_mode6.IsChecked = selectedGame.Config?.Mode6;
} }
} }
private void WindowDrag(object? sender, PointerPressedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
BeginMoveDrag(e);
}
}
private void WindowClose(object? sender, PointerPressedEventArgs e)
{
Console.Success("Window closing");
this.Close();
}
private async void OpenFileButton_Clicked(object sender, RoutedEventArgs args) private async void OpenFileButton_Clicked(object sender, RoutedEventArgs args)
{ {
@ -119,16 +121,7 @@ public partial class MainWindow : Window
if (files.Count >= 1) if (files.Count >= 1)
{ {
Console.Info("AddGameWindow was called for " + files[0].Path.LocalPath); Console.Info("AddGameWindow was called for " + files[0].Path.LocalPath);
string ext = Path.GetExtension(files[0].Path.LocalPath); new AddGameWindow(files[0].Path.LocalPath).Show();
if (ext == ".bin")
{
new ConvertGameWindow(files[0].Path.LocalPath).Show();
}
else if (ext == ".iso")
{
new AddGameWindow(files[0].Path.LocalPath).Show();
}
} }
else else
{ {
@ -138,26 +131,6 @@ public partial class MainWindow : Window
private async void Control_OnLoaded(object? sender, RoutedEventArgs e) private async void Control_OnLoaded(object? sender, RoutedEventArgs e)
{ {
string welcomeText = "";
try
{
welcomeText = FileVersionInfo
.GetVersionInfo(Assembly.GetExecutingAssembly().Location)
.FileVersion ?? "Unknown";
welcomeText = "Welcome to the PS2 Games Manager v" + welcomeText;
}
catch (Exception ex)
{
welcomeText = "Welcome to the PS2 Games Manager";
}
WelcomeTextTop.Text = welcomeText;
Util.CheckDir(settings.library_path.GetValue<string>());
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "DVD"));
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "CD"));
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "CFG"));
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "ART"));
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "VMC"));
FetchGamesFromLibrary(); FetchGamesFromLibrary();
} }
@ -166,53 +139,17 @@ public partial class MainWindow : Window
SwitchView(true); SwitchView(true);
Console.Info("Fetching games from library..."); Console.Info("Fetching games from library...");
List<Game> Games = new List<Game>(); List<Game> Games = new List<Game>();
string[] filesDVDDir = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "DVD")); Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "DVD"));
foreach (var file in filesDVDDir) string[] files = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "DVD"));
foreach (var file in files)
{ {
if (Path.GetExtension(file).ToLower() == ".iso") Game newGame =
{ new Game(file, true);
Game newGame = Games.Add(newGame);
new Game(file, true); Console.Success("Successfully fetched " + newGame);
Games.Add(newGame);
Console.Success("Successfully fetched " + newGame);
}
else
{
Console.WriteLine("Skipped non-ISO file: " + file);
}
}
string[] filesCDDir = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "CD"));
foreach (var file in filesCDDir)
{
if (Path.GetExtension(file).ToLower() == ".iso")
{
Game newGame =
new Game(file, true);
Games.Add(newGame);
Console.Success("Successfully fetched " + newGame);
}
else
{
Console.WriteLine("Skipped non-ISO file: " + file);
}
} }
Games = Games.OrderBy(game => game.Name).ToList(); Games = Games.OrderBy(game => game.Name).ToList();
GamesList.ItemsSource = Games; GamesList.ItemsSource = Games;
FetchVMCs();
}
private void FetchVMCs()
{
List<string> VMCs = new List<string>();
string[] files = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "VMC"));
VMCs.Add("");
foreach (var file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file);
VMCs.Add(fileName);
}
VMC_1.ItemsSource = VMCs;
VMC_2.ItemsSource = VMCs;
} }
@ -403,70 +340,4 @@ public partial class MainWindow : Window
{ {
this.ArtworkType.Value = Artwork.PrevType(this.ArtworkType.Value); this.ArtworkType.Value = Artwork.PrevType(this.ArtworkType.Value);
} }
private void VMC_1_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (GamesList.SelectedItem is Game selectedGame)
{
if (VMC_1.SelectedItem is string selectedVMC)
{
Console.Warning("Setting " + selectedVMC + " as VMC1 for " + selectedGame.GameID);
selectedGame.Config.MemoryCard1 = selectedVMC;
selectedGame.Config.SaveConfig();
}
}
}
private void VMC_2_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (GamesList.SelectedItem is Game selectedGame)
{
if (VMC_2.SelectedItem is string selectedVMC)
{
Console.Warning("Setting " + selectedVMC + " as VMC2 for " + selectedGame.GameID);
selectedGame.Config.MemoryCard2 = selectedVMC;
selectedGame.Config.SaveConfig();
}
}
}
private void Toggle_mode_OnIsCheckedChanged(object sender, RoutedEventArgs e)
{
if (GamesList.SelectedItem is Game selectedGame)
{
if (sender is ToggleSwitch toggle)
{
switch (toggle.Name)
{
case "toggle_mode1":
selectedGame.Config.Mode1 = toggle_mode1.IsChecked.Value;
Console.Warning("Toggled Mode 1 for " + selectedGame.GameID + " to " + selectedGame.Config.Mode1);
break;
case "toggle_mode2":
selectedGame.Config.Mode2 = toggle_mode2.IsChecked.Value;
Console.Warning("Toggled Mode 2 for " + selectedGame.GameID + " to " + selectedGame.Config.Mode2);
break;
case "toggle_mode3":
selectedGame.Config.Mode3 = toggle_mode3.IsChecked.Value;
Console.Warning("Toggled Mode 3 for " + selectedGame.GameID + " to " + selectedGame.Config.Mode3);
break;
case "toggle_mode4":
selectedGame.Config.Mode4 = toggle_mode4.IsChecked.Value;
Console.Warning("Toggled Mode 4 for " + selectedGame.GameID + " to " + selectedGame.Config.Mode4);
break;
case "toggle_mode5":
selectedGame.Config.Mode5 = toggle_mode5.IsChecked.Value;
Console.Warning("Toggled Mode 5 for " + selectedGame.GameID + " to " + selectedGame.Config.Mode5);
break;
case "toggle_mode6":
selectedGame.Config.Mode6 = toggle_mode6.IsChecked.Value;
Console.Warning("Toggled Mode 6 for " + selectedGame.GameID + " to " + selectedGame.Config.Mode6);
break;
}
}
selectedGame.Config.SaveConfig();
}
}
} }

View file

@ -3,12 +3,9 @@
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ApplicationIcon>icon.ico</ApplicationIcon>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest> <ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<AssemblyVersion>1.0</AssemblyVersion>
<FileVersion>1.4</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -26,14 +23,6 @@
<ItemGroup> <ItemGroup>
<None Remove="Images\missing.png" /> <None Remove="Images\missing.png" />
<AvaloniaResource Include="Assets\missing.png" /> <AvaloniaResource Include="Images\missing.png" />
<None Remove="Images\vmc.png" />
<AvaloniaResource Include="Assets\vmc.png" />
<None Remove="Images\cd.png" />
<AvaloniaResource Include="Assets\cd.png" />
<None Remove="Images\dvd.png" />
<AvaloniaResource Include="Assets\dvd.png" />
<None Remove="Assets\bin.png" />
<AvaloniaResource Include="Assets\bin.png" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -5,19 +5,29 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="PS2_Manager.Setup" x:Class="PS2_Manager.Setup"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Title="Setup PS2 Manager" SystemDecorations="None"
Title="Setup"
Height="349" Height="349"
Width="598" Width="598"
CanResize="False"
Background="#201c29" Background="#201c29"
Closing="Window_OnClosing"> Closing="Window_OnClosing">
<Grid Margin="20"> <Grid RowDefinitions="20, *">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid Grid.Row="0">
<TextBlock Name="InfoText1" Text="Welcome to PS2 Manager" HorizontalAlignment="Center"/> <Border Background="#35313d"
<Separator/> PointerPressed="WindowDrag">
<TextBlock Name="InfoText2" Text="First of all please select the path to your PS2 Game Library" HorizontalAlignment="Center"/> <Grid ColumnDefinitions="*, 20">
<Button Name="OpenLibraryButton" Content="Select Folder" HorizontalAlignment="Center" Margin="0,10" <TextBlock Name="WindowTitle" FontSize="12" Text="Setup PS2 Manager" Padding="8,0,0,0" VerticalAlignment="Center"/>
Click="OpenLibraryButton_OnClick"/> </Grid>
</StackPanel> </Border>
</Grid>
<Grid Grid.Row="1" Margin="20">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Name="InfoText1" Text="Welcome to PS2 Manager" HorizontalAlignment="Center"/>
<Separator/>
<TextBlock Name="InfoText2" Text="First of all please select the path to your PS2 Game Library" HorizontalAlignment="Center"/>
<Button Name="OpenLibraryButton" Content="Select Folder" HorizontalAlignment="Center" Margin="0,10"
Click="OpenLibraryButton_OnClick"/>
</StackPanel>
</Grid>
</Grid> </Grid>
</Window> </Window>

View file

@ -43,30 +43,29 @@ public partial class Setup : Window
{ {
Console.Info("Open Library Button Clicked"); Console.Info("Open Library Button Clicked");
settings.library_path.SetValue(""); settings.library_path.SetValue("");
var topLevel = TopLevel.GetTopLevel(this); while (String.IsNullOrEmpty(settings.library_path.GetValue<string>()))
var path = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = "Open Game Library", var topLevel = TopLevel.GetTopLevel(this);
AllowMultiple = false var path = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
});
try
{
if (!String.IsNullOrEmpty(path[0].Path.LocalPath))
{ {
settings.library_path.SetValue(path[0].Path.LocalPath); Title = "Open Game Library",
FinishSetup(); AllowMultiple = false
});
try
{
if (!String.IsNullOrEmpty(path[0].Path.LocalPath))
settings.library_path.SetValue(path[0].Path.LocalPath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
} }
} }
catch (Exception ex) FinishSetup();
{
Console.WriteLine(ex.Message);
}
} }
private void Window_OnClosing(object? sender, WindowClosingEventArgs e) private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{ {
if(!this.SetupFinished) Environment.Exit(0); if(!this.SetupFinished) e.Cancel = true;
} }
} }

10
PS2_Manager/Welcome.axaml Normal file
View file

@ -0,0 +1,10 @@
<UserControl 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"
x:Class="PS2_Manager.Welcome">
<StackPanel >
</StackPanel>
</UserControl>

View file

@ -0,0 +1,16 @@
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace PS2_Manager;
public partial class Welcome : UserControl
{
public Welcome()
{
InitializeComponent();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

View file

@ -1,5 +1,6 @@
# PS2 Game Manager for OPL # PS2 Game Manager for OPL
ARTWORK API IS NOT PUBLIC YET.
## Overview ## Overview
@ -8,10 +9,6 @@ PS2 Game Manager for OPL is a modern, open-source alternative to OPL Manager des
### Key Features: ### Key Features:
- **Modern and Intuitive Interface**: A redesigned UI focused on ease of use, making managing PS2 games a smooth and enjoyable experience. - **Modern and Intuitive Interface**: A redesigned UI focused on ease of use, making managing PS2 games a smooth and enjoyable experience.
- **Open-Source**: PS2 Game Manager for OPL is completely open-source and free to use. Contributions are welcome, and the community plays a key role in its development. - **Open-Source**: PS2 Game Manager for OPL is completely open-source and free to use. Contributions are welcome, and the community plays a key role in its development.
- **CD/DVD Support**: PS2-Manager supports DVDs in ISO format and CDs in BIN/CUE format with its included BIN to ISO converter
- **Virtual Memory Cards Support**: Configure and manage virtual memory cards to store your game saves. (VMC's need to be created via OPL right now tho)
- **Mode Toggles**
## Screenshots ## Screenshots
@ -44,11 +41,6 @@ PS2 Game Manager for OPL was built with **modern design principles** in mind. We
- **Responsive Design**: The program adapts well to different screen sizes and resolutions, providing an optimal experience regardless of your device. - **Responsive Design**: The program adapts well to different screen sizes and resolutions, providing an optimal experience regardless of your device.
- **Optimized Performance**: With faster loading times and smooth transitions, the program ensures a seamless experience even with large game libraries. - **Optimized Performance**: With faster loading times and smooth transitions, the program ensures a seamless experience even with large game libraries.
## Disclaimer
This project does **NOT** support piracy in any form. Please ensure that all game images you use are legally obtained. We encourage users to only use game images that they have personally dumped from their own legally owned discs. The developers of this tool do not condone or support the use of illegally obtained game images.
## Open Source ## Open Source
This project is **open-source**, and contributions are highly encouraged! If you're passionate about improving the PS2 gaming experience or if you have suggestions or improvements, feel free to contribute to the project. This project is **open-source**, and contributions are highly encouraged! If you're passionate about improving the PS2 gaming experience or if you have suggestions or improvements, feel free to contribute to the project.
@ -56,4 +48,3 @@ This project is **open-source**, and contributions are highly encouraged! If you
We welcome **issues**, **pull requests**, and **feature suggestions** from the community. Help us make this tool even better for PS2 gamers! We welcome **issues**, **pull requests**, and **feature suggestions** from the community. Help us make this tool even better for PS2 gamers!