Add settings menu, libcrypt from database, etc

This commit is contained in:
Li 2023-05-02 05:52:34 +12:00
parent de65c71d2c
commit 36a088e256
34 changed files with 999 additions and 179 deletions

View File

@ -55,10 +55,12 @@
</ItemGroup>
<ItemGroup>
<UpToDateCheckInput Remove="Global\DevkitToggle.axaml" />
</ItemGroup>
<ItemGroup>
<Compile Update="Settings\ConfigPath.axaml.cs">
<DependentUpon>ConfigPath.axaml</DependentUpon>
</Compile>
<Compile Update="Settings\ConfigToggle.axaml.cs">
<DependentUpon>ConfigToggle.axaml</DependentUpon>
</Compile>
<Compile Update="Resource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>

View File

@ -1,86 +0,0 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using ChovySign_GUI.Popup.Global;
using LibChovy.Config;
using System;
using System.Collections.Generic;
using static ChovySign_GUI.Popup.Global.MessageBox;
namespace ChovySign_GUI.Global
{
public partial class DevkitToggle : UserControl
{
private static List<DevkitToggle> instances = new List<DevkitToggle>();
private const string useDevkitModeConfigKey = "USE_DEVKIT_ACCOUNT_ID";
internal bool disableEvents = false;
private async void onDevkitModeChecked(object? sender, RoutedEventArgs e)
{
if (disableEvents) return;
CheckBox? checkBox = sender as CheckBox;
if (checkBox is null) return;
bool? devMode = checkBox.IsChecked;
if (devMode is null) devMode = false;
Window? currentWindow = this.VisualRoot as Window;
if (currentWindow is not Window) throw new Exception("could not find current window");
MessageBoxResult res = await MessageBox.Show(currentWindow, "This option will force the CMA Account ID to be all 0's\nWhich is how it is on Devkit, Testkit and IDU Firmware\nEnabling this if you have a retail firmware will result in the games just *not* showing up\n\nIf you DON'T know what this means, DON'T enable this.\ndo you want to continue?", "Are you sure?", MessageBoxButtons.YesNo);
if (res == MessageBoxResult.Yes)
{
IsDevkitMode = true;
}
else
{
IsDevkitMode = false;
}
}
private void onDevkitModeUnchecked(object? sender, RoutedEventArgs e)
{
if (disableEvents) return;
CheckBox? checkBox = sender as CheckBox;
if (checkBox is null) return;
bool? devMode = checkBox.IsChecked;
if (devMode is null) devMode = false;
IsDevkitMode = (bool)devMode;
}
public bool IsDevkitMode
{
get
{
if (this.devkitCheckbox.IsChecked is null) return false;
return (bool)this.devkitCheckbox.IsChecked;
}
set
{
foreach (DevkitToggle instance in instances)
{
instance.disableEvents = true;
instance.devkitCheckbox.IsChecked = value;
instance.disableEvents = false;
}
ChovyConfig.CurrentConfig.SetBool(useDevkitModeConfigKey, value);
}
}
public DevkitToggle()
{
InitializeComponent();
bool? isDevkitMode = ChovyConfig.CurrentConfig.GetBool(useDevkitModeConfigKey);
if (isDevkitMode is null) isDevkitMode = false;
devkitCheckbox.IsChecked = isDevkitMode;
devkitCheckbox.Unchecked += onDevkitModeUnchecked;
devkitCheckbox.Checked += onDevkitModeChecked;
instances.Add(this);
}
}
}

View File

@ -83,10 +83,24 @@ namespace ChovySign_GUI.Global
public FilteredTextBox()
{
InitializeComponent();
this.txtBox.PastingFromClipboard += onPaste;
this.txtBox.PropertyChanged += onPropertyChanged;
this.txtBox.AddHandler(TextInputEvent, onTxtInput, RoutingStrategies.Tunnel);
}
private void onPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
TextBox? txt = sender as TextBox;
if (txt is null) return;
if (e.Property.Name == "Text")
{
if (txt.Text is null) return;
txt.Text = filter(txt.Text);
OnTextChanged(new EventArgs());
}
}
private string filter(string original)
{
@ -104,36 +118,6 @@ namespace ChovySign_GUI.Global
}
return original;
}
private async Task<bool> setClipboardText(string text)
{
if (Application.Current is null) return false;
if (Application.Current.Clipboard is null) return false;
await Application.Current.Clipboard.SetTextAsync(text);
return true;
}
private async Task<string> getClipboardText()
{
if (Application.Current is null) return "";
if (Application.Current.Clipboard is null) return "";
string? clipboard = await Application.Current.Clipboard.GetTextAsync();
if (clipboard is null) return "";
return clipboard;
}
private async void onPaste(object? sender, RoutedEventArgs e)
{
TextBox? txt = sender as TextBox;
if (txt is null) return;
string clipboard = getClipboardText().Result;
clipboard = filter(clipboard);
_ = setClipboardText(clipboard).Result;
// annoyingly, the text being pasted isnt actually in the textbox yet
// and it wont trigger a textInput event when pasting; t-this really is the best can do
await Task.Delay(100);
OnTextChanged(new EventArgs());
}
private void onTxtInput(object? sender, TextInputEventArgs e)
{

View File

@ -52,6 +52,12 @@ namespace ChovySign_GUI.Global
public string[] Items
{
get
{
string[]? strings = this.comboBox.Items as string[];
if (strings is null) return new string[0];
return strings;
}
set
{
this.comboBox.Items = value;

View File

@ -4,7 +4,9 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Ps1="clr-namespace:ChovySign_GUI.Ps1"
xmlns:Psp="clr-namespace:ChovySign_GUI.Psp"
mc:Ignorable="d" d:DesignWidth="850" d:DesignHeight="950"
xmlns:Settings="clr-namespace:ChovySign_GUI.Settings"
mc:Ignorable="d" d:DesignWidth="850" d:DesignHeight="760"
MinHeight="760"
x:Class="ChovySign_GUI.MainWindow"
Title="Chovy Sign V2" Icon="/ICON.PNG">
@ -13,9 +15,12 @@
<TabItem Header="PlayStation Portable">
<Psp:PspTab Name="pspTab"/>
</TabItem>
<TabItem Header="PlayStation 1">
<TabItem Header="PlayStation One">
<Ps1:Ps1Tab Name="ps1Tab"/>
</TabItem>
<TabItem Header="Settings">
<Settings:SettingsTab Name="settingsTab"/>
</TabItem>
</TabControl>
</Grid>

View File

@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="300"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="280"
x:Class="ChovySign_GUI.Ps1.CueSelector">
<!-- Bin/Cue Image selector -->
<Border Padding="5 5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">

View File

@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="250"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="280"
x:Class="ChovySign_GUI.Ps1.GameInfoSelector">
<Border Padding="5 5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid>
@ -18,11 +18,13 @@
<RowDefinition Height="52"/>
<RowDefinition Height="52"/>
<RowDefinition Height="52"/>
<RowDefinition Height="52"/>
</Grid.RowDefinitions>
<Global:LabeledTextBox HorizontalAlignment="Stretch" Name="gameTitle" Label="Title:" Watermark="The BEST PlayStation 1 Game" MaxLength="128" Grid.Row="0"/>
<Global:BrowseButton HorizontalAlignment="Stretch" Name="iconFile" Extension="png" FileTypeName="Portable Network Graphics" Watermark="(Default)" Label="icon0.png:" Grid.Row="1"/>
<Global:BrowseButton HorizontalAlignment="Stretch" Name="pic0File" Extension="png" FileTypeName="Portable Network Graphics" Watermark="(Default)" Label="pic0.png:" Grid.Row="2"/>
<Global:BrowseButton HorizontalAlignment="Stretch" Name="pic1File" Extension="png" FileTypeName="Portable Network Graphics" Watermark="(Default)" Label="pic1.png:" Grid.Row="3"/>
<Global:LabeledTextBox HorizontalAlignment="Stretch" Name="discId" AllowedChars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" Label="Disc ID:" Watermark="SLUS00001" MaxLength="9" Grid.Row="4"/>
</Grid>
</Grid>
</Border>

View File

@ -19,7 +19,18 @@ namespace ChovySign_GUI.Ps1
private byte[] iconCache;
private byte[] pic0Cache;
private byte[] pic1Cache;
public string DiscId
{
get
{
if (this.discId.Text is null) return "";
return this.discId.Text;
}
set
{
this.discId.Text = value;
}
}
public string Title
{
get
@ -86,6 +97,7 @@ namespace ChovySign_GUI.Ps1
{
PSInfo disc = new PSInfo(cueFile);
Title = disc.DiscName;
DiscId = disc.DiscId;
byte[] newCover = await Downloader.DownloadCover(disc);
loadIcon(newCover);
@ -147,6 +159,13 @@ namespace ChovySign_GUI.Ps1
if (TitleChanged is not null)
TitleChanged(this, e);
}
public event EventHandler<EventArgs>? DiscIdChanged;
protected virtual void OnDiscIdChanged(EventArgs e)
{
if (DiscIdChanged is not null)
DiscIdChanged(this, e);
}
public GameInfoSelector()
{
InitializeComponent();
@ -161,6 +180,13 @@ namespace ChovySign_GUI.Ps1
this.pic1File.FileChanged += onPic1Change;
this.gameTitle.TextChanged += onTitleChange;
this.discId.TextChanged += onDiscIdChange;
}
private void onDiscIdChange(object? sender, EventArgs e)
{
OnDiscIdChanged(new EventArgs());
}
private void onTitleChange(object? sender, EventArgs e)

View File

@ -10,9 +10,9 @@
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="1.5*" />
<RowDefinition Height="1.3*" />
<RowDefinition Height="0.6*" />
<RowDefinition Height="280" />
<RowDefinition Height="280" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
@ -22,14 +22,13 @@
<Global:KeySelector Name="keySelector" KeyIndex="1" Grid.Row="0" Grid.Column="1"/>
<Ps1:CueSelector Name="discSelector" Grid.Row="1" Grid.Column="1"/>
<Ps1:GameInfoSelector Name="gameInfo" Grid.Row="2" Grid.Column="1"/>
<Ps1:CueSelector Name="discSelector" Height="280" Grid.Row="1" Grid.Column="1"/>
<Ps1:GameInfoSelector Name="gameInfo" Height="280" Grid.Row="2" Grid.Column="1"/>
<Global:ProgressStatus VerticalAlignment="Center" Name="progressStatus" Grid.Row="3" Grid.Column="1"/>
</Grid>
<!-- Credits -->
<Global:DevkitToggle Name="devkitAccount" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<Label Content="Li, Dots TB, SquallATF, Motoharu, Davee" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
</Grid>
</UserControl>

View File

@ -2,6 +2,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using ChovySign_GUI.Global;
using ChovySign_GUI.Popup.Global;
using ChovySign_GUI.Settings;
using GameBuilder.Psp;
using LibChovy;
using LibChovy.Config;
@ -21,6 +22,7 @@ namespace ChovySign_GUI.Ps1
discSelector.DiscsSelected += onDiscSelected;
keySelector.ValidStateChanged += onKeyValidityChanged;
gameInfo.TitleChanged += onTitleChanged;
gameInfo.DiscIdChanged += onDiscIdChanged;
progressStatus.BeforeStart += onProcessStarting;
progressStatus.Finished += onProcessFinished;
@ -28,13 +30,12 @@ namespace ChovySign_GUI.Ps1
}
private async void onProcessFinished(object? sender, EventArgs e)
{
keySelector.IsEnabled = true;
discSelector.IsEnabled = true;
devkitAccount.IsEnabled = true;
gameInfo.IsEnabled = true;
SettingsTab.Settings.IsEnabled = true;
Window? currentWindow = this.VisualRoot as Window;
if (currentWindow is not Window) throw new Exception("could not find current window");
@ -47,34 +48,41 @@ namespace ChovySign_GUI.Ps1
{
keySelector.IsEnabled = false;
discSelector.IsEnabled = false;
devkitAccount.IsEnabled = false;
gameInfo.IsEnabled = false;
SettingsTab.Settings.IsEnabled = false;
if (keySelector.Rif is null) return;
if (keySelector.VersionKey is null) return;
NpDrmRif rifInfo = new NpDrmRif(keySelector.Rif);
NpDrmInfo drmInfo = new NpDrmInfo(keySelector.VersionKey, rifInfo.ContentId, keySelector.KeyIndex);
PspParameters pspParameters = new PspParameters(drmInfo, rifInfo);
PopsParameters popsParameters = new PopsParameters(drmInfo, rifInfo);
foreach (string disc in discSelector.Discs)
popsParameters.AddCd(disc);
popsParameters.Name = gameInfo.Title;
popsParameters.Icon0 = gameInfo.Icon0;
popsParameters.Pic0 = gameInfo.Pic0;
popsParameters.Pic1 = gameInfo.Pic1;
popsParameters.Name = gameInfo.Title;
popsParameters.DiscId = gameInfo.DiscId;
popsParameters.Icon0 = gameInfo.Icon0;
popsParameters.Pic0 = gameInfo.Pic0;
popsParameters.Pic1 = gameInfo.Pic1;
if (devkitAccount.IsDevkitMode)
popsParameters.Account = new Account(0);
// read settings from settings tab.
if (SettingsTab.Settings.DevkitMode) popsParameters.Account = new Account(0);
popsParameters.CrackMethod = SettingsTab.Settings.LibcryptMode;
SettingsReader.BackupsFolder = SettingsTab.Settings.CmaDirectory;
progressStatus.Parameters = popsParameters;
}
private void onDiscIdChanged(object? sender, EventArgs e)
{
check();
}
private void onTitleChanged(object? sender, EventArgs e)
{
check();
@ -82,7 +90,7 @@ namespace ChovySign_GUI.Ps1
private void check()
{
this.progressStatus.IsEnabled = (discSelector.AnyDiscsSelected && keySelector.IsValid && gameInfo.Title != "");
this.progressStatus.IsEnabled = (discSelector.AnyDiscsSelected && keySelector.IsValid && gameInfo.Title != "" && gameInfo.DiscId.Length == 9);
}
private void onKeyValidityChanged(object? sender, EventArgs e)
{

View File

@ -26,7 +26,6 @@
</Grid>
<!-- Credits -->
<Global:DevkitToggle Name="devkitAccount" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<Label Content="Li, Dots TB, SquallATF, Motoharu, Davee" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
</Grid>
</UserControl>

View File

@ -1,11 +1,13 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using ChovySign_GUI.Popup.Global;
using ChovySign_GUI.Settings;
using GameBuilder.Psp;
using LibChovy;
using LibChovy.Config;
using System;
using System.Media;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Vita.ContentManager;
using static ChovySign_GUI.Popup.Global.MessageBox;
@ -36,7 +38,7 @@ namespace ChovySign_GUI.Psp
{
keySelector.IsEnabled = true;
isoSelector.IsEnabled = true;
devkitAccount.IsEnabled = true;
SettingsTab.Settings.IsEnabled = false;
Window? currentWindow = this.VisualRoot as Window;
if (currentWindow is not Window) throw new Exception("could not find current window");
@ -48,8 +50,9 @@ namespace ChovySign_GUI.Psp
private void onProcessStarting(object? sender, EventArgs e)
{
keySelector.IsEnabled = false;
devkitAccount.IsEnabled = false;
isoSelector.IsEnabled = false;
SettingsTab.Settings.IsEnabled = false;
if (keySelector.Rif is null) return;
if (keySelector.VersionKey is null) return;
@ -63,8 +66,9 @@ namespace ChovySign_GUI.Psp
pspParameters.Umd = umd;
pspParameters.Compress = isoSelector.Compress;
if (devkitAccount.IsDevkitMode)
pspParameters.Account = new Account(0);
// read settings from settings tab.
if (SettingsTab.Settings.DevkitMode) pspParameters.Account = new Account(0);
SettingsReader.BackupsFolder = SettingsTab.Settings.CmaDirectory;
progressStatus.Parameters = pspParameters;
}

View File

@ -0,0 +1,30 @@
using Avalonia.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ChovySign_GUI.Settings
{
public abstract class ConfigControl : UserControl
{
private string? configKey = null;
public string ConfigKey
{
get
{
if (configKey is null) return "";
return configKey;
}
set
{
configKey = value;
init();
}
}
internal abstract void init();
}
}

View File

@ -0,0 +1,11 @@
<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"
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="80"
x:Class="ChovySign_GUI.Settings.ConfigDropDown">
<Grid>
<Global:LabeledComboBox Name="configComboBox" Label="Label"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,71 @@
using Avalonia.Controls;
using ChovySign_GUI.Global;
using LibChovy.Config;
using System;
namespace ChovySign_GUI.Settings
{
public partial class ConfigDropDown : ConfigControl
{
internal override void init()
{
int? cfgInt = ChovyConfig.CurrentConfig.GetInt(ConfigKey);
if (cfgInt is null) cfgInt = 0;
this.configComboBox.SelectedIndex = (int)cfgInt;
}
public string Label
{
get
{
return this.configComboBox.Label;
}
set
{
this.configComboBox.Label = value;
}
}
public int SelectedIndex
{
get
{
return this.configComboBox.SelectedIndex;
}
set
{
this.configComboBox.SelectedIndex = value;
if (this.configComboBox.SelectedIndex < 0) return;
ChovyConfig.CurrentConfig.SetInt(ConfigKey, this.configComboBox.SelectedIndex);
}
}
public string[] Items
{
get
{
return this.configComboBox.Items;
}
set
{
this.configComboBox.Items = value;
init();
}
}
public ConfigDropDown()
{
InitializeComponent();
init();
this.configComboBox.SelectionChanged += onSelectionChange;
}
private void onSelectionChange(object? sender, EventArgs e)
{
LabeledComboBox? comboBox = sender as LabeledComboBox;
if (comboBox is null) return;
if (comboBox.SelectedIndex < 0) return;
ChovyConfig.CurrentConfig.SetInt(ConfigKey, comboBox.SelectedIndex);
}
}
}

View File

@ -0,0 +1,11 @@
<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"
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="80"
x:Class="ChovySign_GUI.Settings.ConfigPath">
<Grid>
<Global:BrowseButton Name="configPath" Label="Label"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,92 @@
using Avalonia.Controls;
using ChovySign_GUI.Global;
using LibChovy.Config;
using System;
namespace ChovySign_GUI.Settings
{
public partial class ConfigPath : ConfigControl
{
internal override void init()
{
string? cfgText = ChovyConfig.CurrentConfig.GetString(ConfigKey);
if (cfgText is null) cfgText = "";
configPath.FilePath = cfgText;
}
public string Label
{
get
{
return configPath.Label;
}
set
{
configPath.Label = value;
}
}
public string Value
{
get
{
return this.configPath.FilePath;
}
set
{
this.configPath.FilePath = value;
if(configPath.ContainsFile)
ChovyConfig.CurrentConfig.SetString(ConfigKey, this.configPath.FilePath);
}
}
public bool IsDirectory
{
get
{
return this.configPath.IsDirectory;
}
set
{
this.configPath.IsDirectory = value;
}
}
public string Extension
{
get
{
return this.configPath.Extension;
}
set
{
this.configPath.Extension = value;
}
}
public string FileTypeName
{
get
{
return this.configPath.FileTypeName;
}
set
{
this.configPath.FileTypeName = value;
}
}
public ConfigPath()
{
InitializeComponent();
init();
this.configPath.FileChanged += onFileChange;
}
private void onFileChange(object? sender, EventArgs e)
{
BrowseButton? browseBtn = sender as BrowseButton;
if (browseBtn is null) return;
if (!browseBtn.ContainsFile) return;
ChovyConfig.CurrentConfig.SetString(ConfigKey, browseBtn.FilePath);
}
}
}

View File

@ -0,0 +1,11 @@
<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"
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="80"
x:Class="ChovySign_GUI.Settings.ConfigText">
<Grid>
<Global:LabeledTextBox Name="configText" Label="Label"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,58 @@
using Avalonia.Controls;
using ChovySign_GUI.Global;
using LibChovy.Config;
using System;
namespace ChovySign_GUI.Settings
{
public partial class ConfigText : ConfigControl
{
internal override void init()
{
string? cfgText = ChovyConfig.CurrentConfig.GetString(ConfigKey);
if (cfgText is null) cfgText = "";
configText.Text = cfgText;
}
public string Label
{
get
{
return configText.Label;
}
set
{
configText.Label = value;
}
}
public string Value
{
get
{
if (this.configText.Text is null) return "";
return (string)this.configText.Text;
}
set
{
this.configText.Text = value;
ChovyConfig.CurrentConfig.SetString(ConfigKey, value);
}
}
public ConfigText()
{
InitializeComponent();
init();
this.configText.TextChanged += onTextChange;
}
private void onTextChange(object? sender, EventArgs e)
{
LabeledTextBox? txtBox = sender as LabeledTextBox;
if (txtBox is null) return;
if (txtBox.Text is null) return;
ChovyConfig.CurrentConfig.SetString(ConfigKey, txtBox.Text);
}
}
}

View File

@ -3,8 +3,8 @@
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="80"
x:Class="ChovySign_GUI.Global.DevkitToggle">
x:Class="ChovySign_GUI.Settings.ConfigToggle">
<Grid>
<CheckBox Name="devkitCheckbox" Content="I have a DevKit, TestKit or IDU Vita"/>
<CheckBox Name="configCheckbox" Content="Label"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,112 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using ChovySign_GUI.Popup.Global;
using LibChovy.Config;
using System;
using System.Collections.Generic;
using static ChovySign_GUI.Popup.Global.MessageBox;
namespace ChovySign_GUI.Settings
{
public partial class ConfigToggle : ConfigControl
{
internal bool disableEvents = false;
private string? promptMsg = null;
internal override void init()
{
bool? isToggleChecked = ChovyConfig.CurrentConfig.GetBool(ConfigKey);
if (isToggleChecked is null) isToggleChecked = false;
configCheckbox.IsChecked = isToggleChecked;
}
public string Label
{
get
{
string? content = configCheckbox.Content as string;
if (content is null) return "";
return content;
}
set
{
configCheckbox.Content = value;
}
}
public string Prompt
{
get
{
if (promptMsg is null) return "";
return promptMsg;
}
set
{
promptMsg = value;
}
}
private async void onToggleChecked(object? sender, RoutedEventArgs e)
{
if (disableEvents) return;
CheckBox? checkBox = sender as CheckBox;
if (checkBox is null) return;
bool? toggled = checkBox.IsChecked;
if (toggled is null) toggled = false;
if (promptMsg is not null)
{
Window? currentWindow = this.VisualRoot as Window;
if (currentWindow is not Window) throw new Exception("could not find current window");
MessageBoxResult res = await MessageBox.Show(currentWindow, Prompt, "Are you sure?", MessageBoxButtons.YesNo);
if (res == MessageBoxResult.Yes)
IsToggled = true;
else
IsToggled = false;
}
}
private void onToggleUnchecked(object? sender, RoutedEventArgs e)
{
if (disableEvents) return;
CheckBox? checkBox = sender as CheckBox;
if (checkBox is null) return;
bool? toggle = checkBox.IsChecked;
if (toggle is null) toggle = false;
IsToggled = (bool)toggle;
}
public bool IsToggled
{
get
{
if (this.configCheckbox.IsChecked is null) return false;
return (bool)this.configCheckbox.IsChecked;
}
set
{
this.disableEvents = true;
this.configCheckbox.IsChecked = value;
this.disableEvents = false;
ChovyConfig.CurrentConfig.SetBool(ConfigKey, value);
}
}
public ConfigToggle()
{
InitializeComponent();
init();
configCheckbox.Unchecked += onToggleUnchecked;
configCheckbox.Checked += onToggleChecked;
}
}
}

View File

@ -0,0 +1,31 @@
<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"
xmlns:Settings="clr-namespace:ChovySign_GUI.Settings"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ChovySign_GUI.Settings.SettingsTab">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Settings:ConfigToggle Name="devkitAccount" ConfigKey="USE_DEVKIT_ACCOUNT_ID" Label="Devkit Mode (Use 0x0000000000000000 Account ID)"
Prompt="This option will force the CMA Account ID to be all 0's&#x0a;Which is how it is on Devkit, Testkit and IDU Firmware&#x0a;Enabling this if you have a retail firmware will result in the games just *not* showing up&#x0a;&#x0a;If you DON'T know what this means, DON'T enable this.&#x0a;do you want to continue?"
HorizontalAlignment="Stretch" Grid.Row="0"/>
<Settings:ConfigPath Name="cmaDirectory" ConfigKey="USE_CMA_DIRECTORY" IsDirectory="True" Label="Output Folder:" HorizontalAlignment="Stretch" Grid.Row="1"/>
<Settings:ConfigDropDown Name="libCryptMode" ConfigKey="USE_LIBCRYPT_METHOD" Label="LibCrypt Method:" HorizontalAlignment="Stretch" Grid.Row="2"/>
</Grid>
</Grid>
</UserControl>

View File

@ -0,0 +1,54 @@
using Avalonia.Controls;
using GameBuilder.Pops.LibCrypt;
using System.IO;
using Vita.ContentManager;
namespace ChovySign_GUI.Settings
{
public partial class SettingsTab : UserControl
{
public static SettingsTab Settings;
public LibCryptMethod LibcryptMode
{
get
{
if (this.libCryptMode.SelectedIndex == 0) return LibCryptMethod.METHOD_MAGIC_WORD;
else return LibCryptMethod.METHOD_SUB_CHANNEL;
}
}
public string CmaDirectory
{
get
{
return cmaDirectory.Value;
}
set
{
cmaDirectory.Value = value;
}
}
public bool DevkitMode
{
get
{
return devkitAccount.IsToggled;
}
}
public SettingsTab()
{
InitializeComponent();
libCryptMode.Items = new string[2] { "Magic Word in ISO Header", "Sub Channel PGD" };
if (!Directory.Exists(this.CmaDirectory))
cmaDirectory.Value = SettingsReader.BackupsFolder;
Settings = this;
}
}
}

View File

@ -239,7 +239,6 @@ namespace GameBuilder.Pops
private PSInfo disc;
private CueReader cue;
private SbiReader sbi;
private PopsImg srcImg;
public MemoryStream IsoHeader;

View File

@ -0,0 +1,27 @@
using GameBuilder.Cue;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder.Pops.LibCrypt
{
public class DbLibCrypt : LibCryptInfo
{
private string discId;
public override int MagicWord
{
get
{
return LibCrypt.MagicWord.LookupMagicWord(discId);
}
}
public DbLibCrypt(string discId, LibCryptMethod method)
{
this.discId = discId;
this.Method = method;
}
}
}

View File

@ -1,52 +1,43 @@
using GameBuilder.Cue;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static GameBuilder.Pops.LibCrypt.MagicWord;
using static GameBuilder.Pops.LibCrypt.SubChannel;
namespace GameBuilder.Pops.LibCrypt
{
public class LibCryptInfo
public abstract class LibCryptInfo
{
public LibCryptMethod Method;
private SbiReader? sbiReader;
public int MagicWord
private LibCryptMethod method;
public virtual LibCryptMethod Method
{
get
{
if (sbiReader is null) return 0;
return GenerateMagicWord(sbiReader.Entries);
return method;
}
set
{
if (MagicWord == 0) return;
method = value;
}
}
public abstract int MagicWord { get; }
public int ObfuscatedMagicWord
public virtual int ObfuscatedMagicWord
{
get
{
if (Method == LibCryptMethod.METHOD_SUB_CHANNEL) return 0;
return ObfuscateMagicWord(this.MagicWord);
return LibCrypt.MagicWord.ObfuscateMagicWord(this.MagicWord);
}
}
public byte[] Subchannels
public virtual byte[] Subchannels
{
get
{
if (sbiReader is null) throw new Exception("Cannot create subchannels, if there is no SBI data.");
return CreateSubchannelDat(MagicWord);
return LibCrypt.SubChannel.CreateSubchannelDat(this.MagicWord);
}
}
public LibCryptInfo(SbiReader? sbi, LibCryptMethod method)
{
this.sbiReader = sbi;
if (sbi is null) Method = LibCryptMethod.METHOD_MAGIC_WORD;
else Method = method;
}
}
}

View File

@ -1,6 +1,7 @@
using GameBuilder.Cue;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -13,6 +14,25 @@ namespace GameBuilder.Pops.LibCrypt
{
return magicWord ^ Constants.MAGIC_WORD_KEY;
}
public static int LookupMagicWord(string discId)
{
using (TextReader magicWords = new StringReader(Resources.MAGICWORDS))
{
for(string? line = magicWords.ReadLine();
line is not null;
line = magicWords.ReadLine())
{
string[] split = line.Split(' ');
if (split[0].Equals(discId, StringComparison.InvariantCultureIgnoreCase))
{
return Int32.Parse(split[1], NumberStyles.HexNumber);
}
}
return 0;
}
}
public static int GenerateMagicWord(SbiEntry[] sbiEntries)
{
bool[] bits = new bool[16];

View File

@ -0,0 +1,27 @@
using GameBuilder.Cue;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder.Pops.LibCrypt
{
public class SbiLibCrypt : LibCryptInfo
{
private SbiReader sbiReader;
public override int MagicWord
{
get
{
return LibCrypt.MagicWord.GenerateMagicWord(sbiReader.Entries);
}
}
public SbiLibCrypt(SbiReader sbi, LibCryptMethod method)
{
this.sbiReader = sbi;
this.Method = method;
}
}
}

View File

@ -69,6 +69,10 @@ namespace GameBuilder.Pops
{
return discId.Replace("-", "").Replace("_", "").ToUpperInvariant().PadRight(9, '0').Substring(0, 9).ToUpperInvariant();
}
set
{
this.discId = value.Replace("-", "").Replace("_", "").ToUpperInvariant().PadRight(9, '0').Substring(0, 9).ToUpperInvariant();
}
}
public PSInfo(string cueFile)
@ -112,9 +116,10 @@ namespace GameBuilder.Pops
if (discId is null) discId = "SLUS00001";
if (this.SbiFile is not null)
this.lc = new LibCryptInfo(new SbiReader(this.SbiFile), LibCryptMethod.METHOD_MAGIC_WORD);
this.lc = new SbiLibCrypt(new SbiReader(this.SbiFile), LibCryptMethod.METHOD_MAGIC_WORD);
else
this.lc = new LibCryptInfo(null, LibCryptMethod.METHOD_MAGIC_WORD);
this.lc = new DbLibCrypt(discId, LibCryptMethod.METHOD_MAGIC_WORD);
}
}
}

View File

@ -80,6 +80,47 @@ namespace GameBuilder {
}
}
/// <summary>
/// Looks up a localized string similar to SCES00311 87AA
///SCES01431 6547
///SCES01444 BD44
///SCES01492 D16A
///SCES01493 197A
///SCES01494 AAA6
///SCES01495 0E57
///SCES01516 44F6
///SCES01517 AE85
///SCES01518 9C27
///SCES01519 364B
///SCES01564 CEC1
///SCES01695 89EA
///SCES01700 4717
///SCES01701 C49E
///SCES01702 672A
///SCES01703 883F
///SCES01704 CE32
///SCES01763 096F
///SCES01882 B364
///SCES01909 E788
///SCES01979 0D9D
///SCES02004 C437
///SCES02005 9137
///SCES02006 7554
///SCES02007 E686
///SCES02028 9AD4
///SCES02029 26B6
///SCES02030 23D9
///SCES02031 D325
///SCES02080 9DE0
///SCES02104 744B
/// [rest of string was truncated]&quot;;.
/// </summary>
public static string MAGICWORDS {
get {
return ResourceManager.GetString("MAGICWORDS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>

View File

@ -124,6 +124,9 @@
<data name="DATAPSPSDCFG" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\DATAPSPSDCFG.BIN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="MAGICWORDS" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\MagicWords.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="SIMPLE" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\SIMPLE.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>

View File

@ -0,0 +1,227 @@
SCES00311 87AA
SCES01431 6547
SCES01444 BD44
SCES01492 D16A
SCES01493 197A
SCES01494 AAA6
SCES01495 0E57
SCES01516 44F6
SCES01517 AE85
SCES01518 9C27
SCES01519 364B
SCES01564 CEC1
SCES01695 89EA
SCES01700 4717
SCES01701 C49E
SCES01702 672A
SCES01703 883F
SCES01704 CE32
SCES01763 096F
SCES01882 B364
SCES01909 E788
SCES01979 0D9D
SCES02004 C437
SCES02005 9137
SCES02006 7554
SCES02007 E686
SCES02028 9AD4
SCES02029 26B6
SCES02030 23D9
SCES02031 D325
SCES02080 9DE0
SCES02104 744B
SCES02105 A371
SCES02181 7D84
SCES02182 A8CD
SCES02184 1E5C
SCES02185 74E4
SCES02222 A4F8
SCES02264 0E3E
SCES02290 12D7
SCES02365 1CDC
SCES02366 D6C8
SCES02367 96A6
SCES02368 5C27
SCES02369 DC25
SCES02430 B159
SCES02431 7872
SCES02432 13AE
SCES02433 B50B
SCES02487 7AD0
SCES02488 898F
SCES02489 25EA
SCES02490 0F6C
SCES02491 F01B
SCES02544 3A17
SCES02545 A96C
SCES02546 378A
SCES02834 E728
SCES02835 369A
SCES02977 B88D
SCES03189 4BCC
SCES03190 710F
SCES03191 6A95
SCES12080 9DE0
SCES22080 9DE0
SCES32080 9DE0
SLES00017 E2B8
SLES00995 8BB1
SLES01041 6317
SLES01226 03E7
SLES01241 E313
SLES01301 B722
SLES01362 6CA6
SLES01545 A54E
SLES01715 A4F4
SLES01733 B06D
SLES01906 14ED
SLES01907 C0EE
SLES01943 7067
SLES02024 1B71
SLES02025 CA4E
SLES02026 116F
SLES02027 3A63
SLES02061 8AB5
SLES02071 2735
SLES02080 9DE0
SLES02081 6837
SLES02082 698B
SLES02083 94CD
SLES02084 44BD
SLES02086 16F4
SLES02112 AF44
SLES02113 5897
SLES02118 6DB0
SLES02207 3A6C
SLES02208 71A9
SLES02209 26D6
SLES02210 632D
SLES02211 1A57
SLES02292 86F2
SLES02293 BA85
SLES02328 3F22
SLES02329 9D38
SLES02330 E03D
SLES02354 64E9
SLES02355 4AE6
SLES02395 AAA9
SLES02396 A56A
SLES02402 AA3A
SLES02529 AD70
SLES02530 7C23
SLES02531 ACB8
SLES02532 1C3D
SLES02533 EA8A
SLES02538 6353
SLES02558 D5E0
SLES02559 5715
SLES02560 DB28
SLES02561 EA85
SLES02562 3D94
SLES02563 4B63
SLES02572 395C
SLES02573 5563
SLES02681 1CC7
SLES02688 7368
SLES02689 E1D2
SLES02698 1C9D
SLES02700 27D8
SLES02704 711E
SLES02705 4AAD
SLES02706 1EB1
SLES02707 AD31
SLES02708 5EC4
SLES02722 B68A
SLES02723 0FF0
SLES02724 CE94
SLES02733 B60D
SLES02754 1FC1
SLES02755 5917
SLES02756 E076
SLES02763 78A6
SLES02766 984F
SLES02767 AB45
SLES02768 9D68
SLES02769 30DE
SLES02824 B385
SLES02830 62BC
SLES02831 05DE
SLES02839 CB19
SLES02857 5F0A
SLES02858 3E1A
SLES02859 255E
SLES02860 A792
SLES02861 C8DC
SLES02862 C3D1
SLES02965 B6C8
SLES02966 CEA1
SLES02967 725A
SLES02968 E516
SLES02969 EC61
SLES02975 7A91
SLES02976 6547
SLES02978 5B13
SLES02979 2F4A
SLES03061 0C7E
SLES03062 B0CD
SLES03241 7B82
SLES03242 A768
SLES03243 2771
SLES03244 1597
SLES03245 05D7
SLES03324 CD31
SLES03489 90AF
SLES03519 BB14
SLES03520 9678
SLES03521 FB20
SLES03522 CB0E
SLES03523 30FC
SLES03530 93F0
SLES03603 5AC9
SLES03604 196E
SLES03605 F152
SLES03606 C5D4
SLES03607 8A3B
SLES03626 4F23
SLES03648 6939
SLES12080 9DE0
SLES12081 6837
SLES12082 698B
SLES12083 94CD
SLES12084 44BD
SLES12328 4AEC
SLES12329 9D38
SLES12330 DE03
SLES12558 D5E0
SLES12559 5715
SLES12560 DB28
SLES12561 EA85
SLES12562 3D94
SLES12965 A1D3
SLES12966 9731
SLES12967 D916
SLES12968 544F
SLES12969 645B
SLES22080 9DE0
SLES22081 6837
SLES22082 698B
SLES22083 94CD
SLES22084 44BD
SLES22328 70D3
SLES22329 9D38
SLES22330 236B
SLES22965 6DC2
SLES22966 C873
SLES22967 19B5
SLES22968 41CF
SLES22969 6636
SLES32080 9DE0
SLES32081 6837
SLES32082 698B
SLES32083 94CD
SLES32084 44BD
SLES32965 1EC5
SLES32966 35D1
SLES32967 54CD
SLES32968 C61D
SLES32969 E8C3

View File

@ -1,4 +1,5 @@
using GameBuilder.Pops;
using GameBuilder.Pops.LibCrypt;
using GameBuilder.Psp;
using LibChovy.Art;
using System;
@ -17,9 +18,15 @@ namespace LibChovy
{
Type = ChovyTypes.POPS;
discList = new List<PSInfo>();
discIdOverride = null;
nameOverride = null;
libCryptMethod = LibCryptMethod.METHOD_MAGIC_WORD;
}
private string? discIdOverride;
private string? nameOverride;
private List<PSInfo> discList;
private LibCryptMethod libCryptMethod;
private byte[]? pic0;
private byte[]? pic1;
@ -102,8 +109,12 @@ namespace LibChovy
public void AddCd(string cd)
{
PSInfo disc = new PSInfo(cd);
if (nameOverride is not null) disc.DiscName = nameOverride;
else discList.Add(disc);
if (nameOverride is not null) disc.DiscName = this.nameOverride;
if (discIdOverride is not null) disc.DiscId = this.discIdOverride;
if (disc.SbiFile is not null) disc.LibCrypt.Method = this.CrackMethod;
discList.Add(disc);
}
public void RemoveCd(string cd)
{
@ -123,6 +134,24 @@ namespace LibChovy
return discList.ToArray();
}
}
public string DiscId
{
get
{
if (discIdOverride is not null && discIdOverride.Length == 9) return discIdOverride;
return FirstDisc.DiscId;
}
set
{
if (value.Equals(FirstDisc.DiscId, StringComparison.InvariantCultureIgnoreCase)) { discIdOverride = null; return; };
if (value.Length != 9) { discIdOverride = null; return; };
for (int i = 0; i < discList.Count; i++)
discList[i].DiscId = value;
discIdOverride = value;
}
}
public string Name
{
get
@ -143,6 +172,20 @@ namespace LibChovy
}
}
public LibCryptMethod CrackMethod
{
get
{
return libCryptMethod;
}
set
{
libCryptMethod = value;
for (int i = 0; i < discList.Count; i++)
discList[i].LibCrypt.Method = value;
}
}
public bool MultiDisc
{
get

View File

@ -9,6 +9,7 @@ namespace Vita.ContentManager
{
public class SettingsReader
{
private static string? overrideBackupsFolder = null;
public static string AppFolder
{
get
@ -56,6 +57,8 @@ namespace Vita.ContentManager
{
get
{
if (overrideBackupsFolder is not null) return overrideBackupsFolder;
string? cmaFolder = getQcmaPSVitaFolder();
if (cmaFolder is not null) return cmaFolder;
cmaFolder = getDevkitCmaPSVitaFolder();
@ -64,6 +67,10 @@ namespace Vita.ContentManager
if (cmaFolder is not null) return cmaFolder;
return getDefaultCmaPSVitaFolder();
}
set
{
overrideBackupsFolder = value;
}
}
private static string getDefaultCmaPSVitaFolder()