Compare commits

...
Sign in to create a new pull request.

33 commits

Author SHA1 Message Date
4cfe64067d fixed crash on AppImage
All checks were successful
Java CI / test (push) Successful in 1m38s
2025-05-04 01:28:57 +02:00
4f786226bd added check if loaded file is iso
All checks were successful
Java CI / test (push) Successful in 1m38s
2025-05-03 23:17:52 +02:00
75fdd45938 minor fixes
All checks were successful
Java CI / test (push) Successful in 1m31s
2025-05-03 20:59:30 +02:00
b69cac606a added different installation methods
All checks were successful
Java CI / test (push) Successful in 1m27s
2025-05-03 20:44:27 +02:00
0479843d47 minor changes
Some checks failed
Java CI / test (push) Failing after 12s
2025-05-03 17:27:21 +02:00
dc89d32164 added logging
Some checks failed
Java CI / test (push) Failing after 8s
2025-05-03 17:19:17 +02:00
7f01a92677 added version check
Some checks failed
Java CI / test (push) Failing after 7s
2025-05-03 16:58:25 +02:00
ee23983551 updated README.md
Some checks failed
Java CI / test (push) Failing after 1m19s
2025-05-03 16:56:35 +02:00
c1c4f89622 versioned release workflow
All checks were successful
Java CI / test (push) Successful in 1m34s
2025-05-03 16:49:57 +02:00
c08316e222 versioning added
Some checks failed
Java CI / test (push) Has been cancelled
2025-05-03 16:48:27 +02:00
e562d4a0ad Merge remote-tracking branch 'origin/master'
All checks were successful
Java CI / test (push) Successful in 2m2s
2025-05-03 16:32:31 +02:00
d32c17dc1c Setup Improved 2025-05-03 16:32:22 +02:00
ecc4728e5e .forgejo/workflows/dotnet.yaml aktualisiert
All checks were successful
Java CI / test (push) Successful in 1m33s
2025-05-01 17:35:42 +00:00
951f93b1b3 added AppImage Building
All checks were successful
Java CI / test (push) Successful in 2m2s
2025-05-01 15:16:39 +02:00
a9bfb5c706 added files for AppImage
Some checks failed
Java CI / test (push) Failing after 1s
2025-05-01 15:10:46 +02:00
bc0ac93f3f fixed some minor issues with CDs
All checks were successful
Java CI / test (push) Successful in 1m25s
2025-04-27 21:48:23 +02:00
1eaf8c2580 Finished ConvertGameWindow.axaml
All checks were successful
Java CI / test (push) Successful in 1m25s
2025-04-27 21:13:51 +02:00
4eb2d47adf added a bin to iso converter
All checks were successful
Java CI / test (push) Successful in 1m29s
2025-04-27 20:20:51 +02:00
312afabfdc Merge remote-tracking branch 'origin/master'
All checks were successful
Java CI / test (push) Successful in 1m24s
2025-04-27 17:40:46 +02:00
86da04442c fix 2025-04-27 17:40:43 +02:00
1ae4690d0d displays difference between dvds and cds 2025-04-27 17:40:00 +02:00
2f3effc087 README.md aktualisiert
All checks were successful
Java CI / test (push) Successful in 1m21s
2025-04-27 14:33:40 +00:00
55adc6c2a9 updated README.md
Some checks failed
Java CI / test (push) Has been cancelled
2025-04-27 16:33:04 +02:00
8d7a45ce5c added disc icons for Game List
All checks were successful
Java CI / test (push) Successful in 1m30s
2025-04-27 16:05:00 +02:00
cc2eee27c2 minor fixes
All checks were successful
Java CI / test (push) Successful in 1m46s
2025-04-27 04:02:17 +02:00
492d3c71f2 added support for configs and vmcs
All checks were successful
Java CI / test (push) Successful in 1m33s
2025-04-27 03:48:53 +02:00
d6671ad2f8 Dateien nach „PS2_Manager/Images“ hochladen
All checks were successful
Java CI / test (push) Successful in 1m25s
2025-04-26 22:25:07 +00:00
af4e7848ae updated screenshots
All checks were successful
Java CI / test (push) Successful in 1m27s
2025-04-26 20:11:05 +02:00
8965f2c5cc added assembly icon
All checks were successful
Java CI / test (push) Successful in 1m23s
2025-04-26 19:28:55 +02:00
3c18a4b942 removed unused files
All checks were successful
Java CI / test (push) Successful in 1m28s
2025-04-26 18:18:13 +02:00
7b3e52595e UI rework done
Some checks failed
Java CI / test (push) Has been cancelled
2025-04-26 18:17:24 +02:00
d7479b9fec Merge branch 'experimental' 2025-04-26 18:16:55 +02:00
1f4d68461f .forgejo/workflows/dotnet.yaml aktualisiert
Some checks failed
Java CI / test (push) Has been cancelled
2025-04-26 10:23:19 +00:00
37 changed files with 947 additions and 272 deletions

View file

@ -18,6 +18,22 @@ jobs:
- name: Checkout code
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)
run: |
dotnet publish ./PS2_Manager/PS2_Manager.csproj \
@ -38,6 +54,27 @@ jobs:
-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
run: |
mkdir -p ./release
@ -46,21 +83,12 @@ jobs:
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
run: |
git tag ${{ steps.generate_tag.outputs.tag_name }}
git push origin ${{ steps.generate_tag.outputs.tag_name }}
git config user.name "WeeXnes"
git config user.email "somtrigi@gmail.com"
git tag v${{ steps.get_version.outputs.version }}
git push origin v${{ steps.get_version.outputs.version }}
- name: Upload to Forgejo
uses: actions/forgejo-release@v2.6.0
@ -69,6 +97,6 @@ jobs:
url: https://git.weexnes.dev/
repo: WeeXnes/ps2_manager
token: ${{ secrets.RELEASE_TOKEN }}
tag: ${{ steps.generate_tag.outputs.tag_name }}
tag: v${{ steps.get_version.outputs.version }}
release-dir: release
release-notes: "Automated release from CI"
release-notes: "Automated release for version ${{ steps.get_version.outputs.version }}"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View file

@ -3,32 +3,19 @@
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"
Height="349"
Height="389"
Width="598"
CanResize="False"
x:Class="PS2_Manager.AddGameWindow"
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"
PointerPressed="CoverImage_OnPointerPressed">
<Image Name="CoverImage" Source="Images/missing.png" Stretch="UniformToFill"/>
<Image Name="CoverImage" Source="Assets/missing.png" Stretch="UniformToFill"/>
</Border>
<!-- Spacer -->
@ -52,6 +39,10 @@
<TextBlock Text="ISO Path"/>
<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"
Background="#aa4de8"
Foreground="Black"
@ -60,6 +51,4 @@
</StackPanel>
</Grid>
</Grid>
</Grid>
</Window>

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
@ -22,6 +23,9 @@ public partial class AddGameWindow : Window
{
this.newGame = new Game(filePath);
InitializeComponent();
InstallationMethodBox.Items.Add("Move");
InstallationMethodBox.Items.Add("Copy");
InstallationMethodBox.SelectedItem = settings.preferred_installation_method.GetValue<string>() ?? "Move";
}
private void RefreshPreview()
@ -57,6 +61,7 @@ public partial class AddGameWindow : Window
{
InstallButton.IsEnabled = false;
GameNameBox.IsEnabled = false;
InstallationMethodBox.IsEnabled = false;
InstallButton.Content = "Installing...";
newGame.Install();
newGame.InstallProgress.ValueChanged += () =>
@ -100,4 +105,9 @@ public partial class AddGameWindow : Window
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,7 +51,6 @@ public partial class App : Application
setupWindow.Closed += (_, _) =>
{
// Replace MainWindow after setup finishes
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var mainWindow = new MainWindow();

View file

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

BIN
PS2_Manager/Assets/bin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

BIN
PS2_Manager/Assets/cd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 KiB

BIN
PS2_Manager/Assets/dvd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 KiB

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
PS2_Manager/Assets/vmc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 KiB

View file

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

@ -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

@ -0,0 +1,23 @@
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);
}
}

118
PS2_Manager/Core/Config.cs Normal file
View file

@ -0,0 +1,118 @@
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;
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())
return default(T);

View file

@ -0,0 +1,35 @@
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,6 +12,7 @@ using Avalonia.Threading;
using Microsoft.VisualBasic.CompilerServices;
using Nocksoft.IO.ConfigFiles;
namespace PS2_Manager.Core;
public class Game
@ -22,6 +23,8 @@ public class Game
public Bitmap? ArtworkFront { get; set; }
public Bitmap? ArtworkBack { get; set; }
public Bitmap? ArtworkDVD { get; set; }
public Config? Config { get; set; }
public DiscIcon Icon { get; set; }
public EventHandler? InstallationFinished { get; set; }
public UpdateVar<double> InstallProgress { get; private set; }
@ -29,6 +32,16 @@ public class Game
{
this.GamePath = 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)
{
this.Name = this.GetGameTitle();
@ -45,6 +58,8 @@ public class Game
}
}
public void ChangeName(string newName)
{
Console.Info("Changing name of " + this.Name + " to " + newName);
@ -104,6 +119,9 @@ public class Game
{
this.InstallProgress = new UpdateVar<double>();
await this.CopyIsoWithProgressAsync();
string installationMethod = settings.preferred_installation_method.GetValue<string>() ?? "Move";
if(installationMethod == "Move")
this.Uninstall();
}
private Bitmap DownloadCover(Artwork.Type type)
@ -152,11 +170,14 @@ public class Game
public async Task CopyIsoWithProgressAsync()
{
Console.Info("Copying ISO file for " + this + "...");
string targetDirectory = settings.library_path.GetValue<string>();
Util.CheckDir(Path.Combine(targetDirectory, "DVD"));
string targetDirectory = "";
if (this.Icon.type == DiscType.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 destPath = Path.Combine(Path.Combine(targetDirectory, "DVD"), newFileName);
string destPath = Path.Combine(targetDirectory, newFileName);
const int bufferSize = 1024 * 1024;
byte[] buffer = new byte[bufferSize];
@ -185,10 +206,6 @@ public class Game
MainWindow.RefreshGamesListTrigger?.Invoke(this, EventArgs.Empty);
}
public Bitmap? LoadCover(Artwork.Type artworkType)
{
Console.Info("Loading " + artworkType + " Artwork for " + this.GameID);
@ -249,115 +266,32 @@ public class Game
{
return this.Name + " -> " + this.GameID;
}
private string GetConfigPath()
{
return Path.Combine(Path.Combine(settings.library_path.GetValue<string>(), "CFG"), this.GameID + ".cfg");
}
public class GameConfig
private string GetArtworkPath(Artwork.Type artworkType)
{
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()
string targetDirectory = settings.library_path.GetValue<string>();
string modifier = "";
switch (artworkType)
{
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 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)
{
var line = rawLine.Trim();
// Skip empty or comment lines
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);
case Artwork.Type.Front:
modifier = "_COV.png";
break;
case "$VMC_0":
this.MemoryCard1 = value;
case Artwork.Type.Back:
modifier = "_COV2.png";
break;
case "$VMC_1":
this.MemoryCard2 = value;
break;
case "$ConfigSource":
// Optional: You can store/use this if needed
case Artwork.Type.Disc:
modifier = "_ICO.png";
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,6 +4,7 @@ using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Microsoft.VisualBasic.CompilerServices;
namespace PS2_Manager.Core;
@ -23,7 +24,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")
{
@ -34,7 +35,8 @@ public static class Globals
public enum settings
{
library_path
library_path,
preferred_installation_method
}
public class UpdateVar<T>

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

@ -31,9 +31,17 @@ public static class Util
public static void CheckDir(string path)
{
//Console.Info("Checking directory: " + path);
if (!Directory.Exists(path))
{
Console.Error("Directory " + path + " wasn't found, creating now.");
Directory.CreateDirectory(path);
}
else
{
Console.Success("Directory was found: " + path);
}
}
public static string FormatFileSize(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB", "TB" };

View file

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

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

@ -10,7 +10,7 @@
Width="990"
Height="520"
MinHeight="490"
MinWidth="600"
MinWidth="875"
WindowStartupLocation="CenterScreen"
Loaded="Control_OnLoaded"
Foreground="White">
@ -25,11 +25,16 @@
<Border Background="Transparent" Padding="10">
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="Add New Game" Click="OpenFileButton_Clicked"/>
<MenuItem Header="Remove Game" Click="DeleteButton"/>
<MenuItem Header="Show Details"/>
</ContextMenu>
</Border.ContextMenu>
<TextBlock Foreground="White" Text="{Binding Name}"/>
<Grid ColumnDefinitions="30, 5,*">
<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>
</DataTemplate>
</ListBox.ItemTemplate>
@ -64,7 +69,8 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Spacing="10">
<TextBlock Text="Welcome to the PS2 Games Manager"
<TextBlock Text=""
Name="WelcomeTextTop"
HorizontalAlignment="Center"
TextAlignment="Center"
FontSize="18"
@ -92,7 +98,31 @@
<StackPanel Orientation="Vertical" Margin="10">
<TextBlock Foreground="White" Text="Display Name:" HorizontalAlignment="Center" Padding="0,10"/>
<TextBox Foreground="White" Name="NameTextBox_Edit"/>
<Separator/>
<Separator Margin="0,10"/>
<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>
<Border Background="#35313d" CornerRadius="5" Padding="10" Margin="0,5" IsVisible="False" Name="ChecksumArea">
<StackPanel>
@ -127,7 +157,7 @@
<Border Grid.Column="1" Width="205" Height="292" Background="Transparent" CornerRadius="5" HorizontalAlignment="Center" VerticalAlignment="Center"
PointerPressed="CoverImage_OnPointerPressed" Name="CoverContainer">
<Grid>
<Image Name="CoverImage" Source="Images/missing.png" Stretch="UniformToFill"/>
<Image Name="CoverImage" Source="Assets/missing.png" Stretch="UniformToFill"/>
<TextBlock Name="CoverTextHint" HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="False"/>
</Grid>
</Border>

View file

@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
@ -11,6 +12,7 @@ using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using DiscUtils;
using PS2_Manager.Core;
namespace PS2_Manager;
@ -22,6 +24,7 @@ public partial class MainWindow : Window
public UpdateVar<Artwork.Type> ArtworkType { get; set; } = new UpdateVar<Artwork.Type>();
public UpdateVar<string> MD5Hash { get; set; } = new UpdateVar<string>();
public UpdateVar<string> SHA1Hash { get; set; } = new UpdateVar<string>();
public MainWindow()
{
InitializeComponent();
@ -88,21 +91,16 @@ public partial class MainWindow : Window
{
ChecksumArea.IsVisible = false;
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)
{
@ -121,8 +119,17 @@ public partial class MainWindow : Window
if (files.Count >= 1)
{
Console.Info("AddGameWindow was called for " + files[0].Path.LocalPath);
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
{
Console.Error("OpenFilePicker was called but Canceled or no Files selected");
@ -131,6 +138,26 @@ public partial class MainWindow : Window
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();
}
@ -139,17 +166,53 @@ public partial class MainWindow : Window
SwitchView(true);
Console.Info("Fetching games from library...");
List<Game> Games = new List<Game>();
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "DVD"));
string[] files = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "DVD"));
foreach (var file in files)
string[] filesDVDDir = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "DVD"));
foreach (var file in filesDVDDir)
{
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);
}
}
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();
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;
}
@ -340,4 +403,70 @@ public partial class MainWindow : Window
{
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,9 +3,12 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ApplicationIcon>icon.ico</ApplicationIcon>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<AssemblyVersion>1.0</AssemblyVersion>
<FileVersion>1.4</FileVersion>
</PropertyGroup>
<ItemGroup>
@ -23,6 +26,14 @@
<ItemGroup>
<None Remove="Images\missing.png" />
<AvaloniaResource Include="Images\missing.png" />
<AvaloniaResource Include="Assets\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>
</Project>

View file

@ -5,22 +5,13 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="PS2_Manager.Setup"
WindowStartupLocation="CenterScreen"
SystemDecorations="None"
Title="Setup"
Title="Setup PS2 Manager"
Height="349"
Width="598"
CanResize="False"
Background="#201c29"
Closing="Window_OnClosing">
<Grid RowDefinitions="20, *">
<Grid Grid.Row="0">
<Border Background="#35313d"
PointerPressed="WindowDrag">
<Grid ColumnDefinitions="*, 20">
<TextBlock Name="WindowTitle" FontSize="12" Text="Setup PS2 Manager" Padding="8,0,0,0" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
<Grid Grid.Row="1" Margin="20">
<Grid Margin="20">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Name="InfoText1" Text="Welcome to PS2 Manager" HorizontalAlignment="Center"/>
<Separator/>
@ -29,5 +20,4 @@
Click="OpenLibraryButton_OnClick"/>
</StackPanel>
</Grid>
</Grid>
</Window>

View file

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

View file

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

@ -1,16 +0,0 @@
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();
}
}

BIN
PS2_Manager/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View file

@ -1,6 +1,5 @@
# PS2 Game Manager for OPL
ARTWORK API IS NOT PUBLIC YET.
## Overview
@ -9,6 +8,10 @@ PS2 Game Manager for OPL is a modern, open-source alternative to OPL Manager des
### Key Features:
- **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.
- **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
@ -41,6 +44,11 @@ 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.
- **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
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.
@ -48,3 +56,4 @@ 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!