added support for configs and vmcs
All checks were successful
Java CI / test (push) Successful in 1m33s

This commit is contained in:
WeeXnes 2025-04-27 03:48:53 +02:00
parent d6671ad2f8
commit 492d3c71f2
8 changed files with 276 additions and 113 deletions

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

@ -22,6 +22,7 @@ public class Game
public Bitmap? ArtworkFront { get; set; }
public Bitmap? ArtworkBack { get; set; }
public Bitmap? ArtworkDVD { get; set; }
public Config? Config { get; set; }
public EventHandler? InstallationFinished { get; set; }
public UpdateVar<double> InstallProgress { get; private set; }
@ -29,6 +30,7 @@ public class Game
{
this.GamePath = isoPath;
this.GameID = ISO.GetSerial(isoPath);
this.Config = new Config(this.GetConfigPath());
if (!installed)
{
this.Name = this.GetGameTitle();
@ -45,6 +47,8 @@ public class Game
}
}
public void ChangeName(string newName)
{
Console.Info("Changing name of " + this.Name + " to " + newName);
@ -249,115 +253,32 @@ public class Game
{
return this.Name + " -> " + this.GameID;
}
}
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()
private string GetConfigPath()
{
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";
return Path.Combine(Path.Combine(settings.library_path.GetValue<string>(), "CFG"), this.GameID + ".cfg");
}
private void FromCompatibility(int value)
private string GetArtworkPath(Artwork.Type artworkType)
{
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)
string targetDirectory = settings.library_path.GetValue<string>();
string modifier = "";
switch (artworkType)
{
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);
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;
}
case Artwork.Type.Front:
modifier = "_COV.png";
break;
case Artwork.Type.Back:
modifier = "_COV2.png";
break;
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);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

BIN
PS2_Manager/Images/vmc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 KiB

View file

@ -10,7 +10,8 @@
Width="990"
Height="520"
MinHeight="490"
MinWidth="600"
MinWidth="875"
Resized="WindowBase_OnResized"
WindowStartupLocation="CenterScreen"
Loaded="Control_OnLoaded"
Foreground="White">
@ -100,6 +101,28 @@
<TextBlock Foreground="White" FontSize="10" Name="SHATextBlock"/>
</StackPanel>
</Border>
<Grid Grid.ColumnDefinitions="*,120,*,120,*" Margin="0,20">
<Border Grid.Column="1" Background="#35313d" Padding="0,5" CornerRadius="5">
<StackPanel>
<Image RenderOptions.BitmapInterpolationMode="HighQuality" Source="Images/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="Images/vmc.png"/>
<ComboBox Name="VMC_2" Margin="5,0" HorizontalAlignment="Stretch" SelectionChanged="VMC_2_OnSelectionChanged"/>
</StackPanel>
</Border>
</Grid>
<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>
</StackPanel>
</ScrollViewer>
<Grid Grid.Row="1" ColumnDefinitions="*,*">

View file

@ -22,6 +22,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 +89,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)
{
@ -150,6 +146,21 @@ public partial class MainWindow : Window
}
Games = Games.OrderBy(game => game.Name).ToList();
GamesList.ItemsSource = Games;
FetchVMCs();
}
private void FetchVMCs()
{
List<string> VMCs = new List<string>();
Util.CheckDir(Path.Combine(settings.library_path.GetValue<string>(), "VMC"));
string[] files = Directory.GetFiles(Path.Combine(settings.library_path.GetValue<string>(), "VMC"));
foreach (var file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file);
VMCs.Add(fileName);
}
VMC_1.ItemsSource = VMCs;
VMC_2.ItemsSource = VMCs;
}
@ -340,4 +351,69 @@ public partial class MainWindow : Window
{
this.ArtworkType.Value = Artwork.PrevType(this.ArtworkType.Value);
}
private void WindowBase_OnResized(object? sender, WindowResizedEventArgs e)
{
VanillaConsole.WriteLine(e.ClientSize);
}
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;
break;
case "toggle_mode2":
selectedGame.Config.Mode2 = toggle_mode2.IsChecked.Value;
break;
case "toggle_mode3":
selectedGame.Config.Mode3 = toggle_mode3.IsChecked.Value;
break;
case "toggle_mode4":
selectedGame.Config.Mode4 = toggle_mode4.IsChecked.Value;
break;
case "toggle_mode5":
selectedGame.Config.Mode5 = toggle_mode5.IsChecked.Value;
break;
case "toggle_mode6":
selectedGame.Config.Mode6 = toggle_mode6.IsChecked.Value;
break;
}
}
selectedGame.Config.SaveConfig();
}
}
}

View file

@ -25,5 +25,7 @@
<ItemGroup>
<None Remove="Images\missing.png" />
<AvaloniaResource Include="Images\missing.png" />
<None Remove="Images\vmc.png" />
<AvaloniaResource Include="Images\vmc.png" />
</ItemGroup>
</Project>