Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
Li | 2ef6e0c65d | |
Li | 58b6de3d00 | |
Li | dd3431c312 | |
Li | 97c5959caf | |
Li | fb8c379751 | |
Li | b433e30fcc | |
Li | 1c1711d844 | |
Li | 2b1154a140 | |
Li | fec8c58ae5 | |
Li | dad692f9dd | |
Li | 434c3304b7 | |
Li | 1779f2f7c2 | |
Li | c837fddb9f | |
Li | f087076653 | |
Li | c15e345b30 | |
Li | 5aa34528ea |
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>ChovySign_CLI</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_LastSelectedProfileId>C:\Users\Li\Documents\git\Chovy-Sign-v2\ChovySign-CLI\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||
<_LastSelectedProfileId>C:\Users\Li\Desktop\git\chovy-sign\ChovySign-CLI\Properties\PublishProfiles\Linux64.pubxml</_LastSelectedProfileId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -4,6 +4,9 @@ using GameBuilder.Psp;
|
|||
using LibChovy;
|
||||
using LibChovy.VersionKey;
|
||||
using System.Text;
|
||||
using Vita.ContentManager;
|
||||
using PspCrypto;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ChovySign_CLI
|
||||
{
|
||||
|
@ -11,19 +14,29 @@ namespace ChovySign_CLI
|
|||
{
|
||||
private static ArgumentParsingMode mode = ArgumentParsingMode.ARG;
|
||||
private static List<string> parameters = new List<string>();
|
||||
private static string[] discs;
|
||||
private static string[] discs = new string[] { };
|
||||
private static bool pspCompress = false;
|
||||
private static bool devKit = false;
|
||||
private static string? popsDiscName;
|
||||
private static string? popsIcon0File;
|
||||
private static string? popsPic0File;
|
||||
private static byte[]? popsIcon0File;
|
||||
private static byte[]? popsPic0File;
|
||||
private static PbpMode? pbpMode = null;
|
||||
private static NpDrmRif? rifFile = null;
|
||||
private static NpDrmInfo? drmInfo = null;
|
||||
|
||||
// cma
|
||||
private static bool devKit = false;
|
||||
private static bool packagePsvImg = true;
|
||||
private static string? outputFolder = null;
|
||||
|
||||
// --vkey-gen
|
||||
private static byte[]? actDat = null;
|
||||
private static byte[]? idps = null;
|
||||
private static string? rifFolder = null;
|
||||
|
||||
// --pops-eboot-sign
|
||||
private static byte[]? ebootElf = null;
|
||||
private static byte[]? configBin = null;
|
||||
|
||||
enum PbpMode
|
||||
{
|
||||
PSP = 0,
|
||||
|
@ -33,15 +46,23 @@ namespace ChovySign_CLI
|
|||
}
|
||||
enum ArgumentParsingMode
|
||||
{
|
||||
ARG = 0,
|
||||
POPS_DISC = 1,
|
||||
PSP_UMD = 2,
|
||||
VERSIONKEY = 3,
|
||||
VERSIONKEY_EXTRACT = 4,
|
||||
VERSIONKEY_GENERATOR = 5,
|
||||
POPS_INFO = 6,
|
||||
KEYS_TXT_GEN = 7,
|
||||
RIF = 8
|
||||
ARG,
|
||||
POPS_DISC,
|
||||
PSP_UMD,
|
||||
|
||||
VERSIONKEY,
|
||||
VERSIONKEY_EXTRACT,
|
||||
VERSIONKEY_GENERATOR,
|
||||
|
||||
CMA_DEVKIT,
|
||||
CMA_OUTPUT_FOLDER,
|
||||
CMA_PACKAGE_PSVIMG,
|
||||
|
||||
POPS_INFO,
|
||||
POPS_EBOOT,
|
||||
|
||||
KEYS_TXT_GEN,
|
||||
RIF
|
||||
}
|
||||
public static int Error(string errorMsg, int ret)
|
||||
{
|
||||
|
@ -85,6 +106,7 @@ namespace ChovySign_CLI
|
|||
|
||||
if(rif.AccountId != accountId) { Error(rif.ContentId + " account id does not match: " + accountId.ToString("X") + " (was " + rif.AccountId.ToString("X") + ")", 10); continue; }
|
||||
string[] keys = new string[4];
|
||||
|
||||
for (int i = 0; i < keys.Length; i++)
|
||||
keys[i] = BitConverter.ToString(ActRifMethod.GetVersionKey(actDat, rif.Rif, idps, i).VersionKey).Replace("-", "");
|
||||
|
||||
|
@ -92,7 +114,7 @@ namespace ChovySign_CLI
|
|||
string keysTxt = String.Join(' ', keysTxtLine);
|
||||
|
||||
addKeys.AppendLine(keysTxt);
|
||||
Console.WriteLine(keysTxt);
|
||||
//Console.WriteLine(keysTxt);
|
||||
}
|
||||
File.AppendAllText("KEYS.TXT", addKeys.ToString());
|
||||
}
|
||||
|
@ -102,13 +124,13 @@ namespace ChovySign_CLI
|
|||
switch (mode)
|
||||
{
|
||||
case ArgumentParsingMode.POPS_DISC:
|
||||
if (parameters.Count > 5) return Error("--pops: no more than 5 disc images allowed in a single game (sony's rules, not mine)", 5);
|
||||
if (parameters.Count < 1) return Error("--pops: at least 1 disc image file is required.", 5);
|
||||
if (parameters.Count > 5) return Error("--pops: no more than 5 disc images allowed in a single game (sony's rules, not mine)", 4);
|
||||
if (parameters.Count < 1) return Error("--pops: at least 1 disc image file is required.", 4);
|
||||
discs = parameters.ToArray();
|
||||
break;
|
||||
case ArgumentParsingMode.PSP_UMD:
|
||||
if (parameters.Count < 1) return Error("--psp: a path to a disc image is required", 5);
|
||||
if (parameters.Count > 2) return Error("--psp: no more than 2 arguments. ("+parameters.Count+" given)", 5);
|
||||
if (parameters.Count < 1) return Error("--psp: a path to a disc image is required", 4);
|
||||
if (parameters.Count > 2) return Error("--psp: no more than 2 arguments. ("+parameters.Count+" given)", 4);
|
||||
discs = new string[1];
|
||||
discs[0] = parameters[0];
|
||||
|
||||
|
@ -123,8 +145,8 @@ namespace ChovySign_CLI
|
|||
drmInfo = new NpDrmInfo(StringToByteArray(parameters[0]), parameters[1], int.Parse(parameters[2]));
|
||||
break;
|
||||
case ArgumentParsingMode.VERSIONKEY_EXTRACT:
|
||||
if (parameters.Count != 1) return Error("--vkey-extract: expect 1 arguments. ("+parameters.Count+" given)", 4);
|
||||
drmInfo = EbootPbpMethod.GetVersionKey(File.OpenRead(parameters[0]));
|
||||
if (parameters.Count != 2) return Error("--vkey-extract: expect 2 arguments. ("+parameters.Count+" given)", 4);
|
||||
drmInfo = EbootPbpMethod.GetVersionKey(File.OpenRead(parameters[0]), int.Parse(parameters[1]));
|
||||
break;
|
||||
case ArgumentParsingMode.VERSIONKEY_GENERATOR:
|
||||
if(parameters.Count != 4) return Error("--vkey-gen: expect 4 arguments. ("+parameters.Count+" given)", 4);
|
||||
|
@ -134,10 +156,10 @@ namespace ChovySign_CLI
|
|||
if (parameters.Count < 2) return Error("--pops-info takes at least 1 arguments ("+parameters.Count+" given)", 4);
|
||||
if (parameters.Count > 3) return Error("--pops-info takes no more than 3 arguments("+parameters.Count+" given)", 4);
|
||||
popsDiscName = parameters[0];
|
||||
if (parameters.Count > 1)
|
||||
popsIcon0File = parameters[1];
|
||||
if (parameters.Count > 2)
|
||||
popsPic0File = parameters[2];
|
||||
if (parameters.Count > 1 && File.Exists(parameters[1]))
|
||||
popsIcon0File = File.ReadAllBytes(parameters[1]);
|
||||
if (parameters.Count > 2 && File.Exists(parameters[2]))
|
||||
popsPic0File = File.ReadAllBytes(parameters[2]);
|
||||
break;
|
||||
case ArgumentParsingMode.KEYS_TXT_GEN:
|
||||
if (parameters.Count != 3) return Error("--keys-txt-gen takes 3 arguments, (" + parameters.Count + " given)", 4);
|
||||
|
@ -145,6 +167,23 @@ namespace ChovySign_CLI
|
|||
idps = StringToByteArray(parameters[1]);
|
||||
rifFolder = parameters[2];
|
||||
break;
|
||||
case ArgumentParsingMode.POPS_EBOOT:
|
||||
if (parameters.Count < 1) return Error("--pops-eboot-sign expects at most 1 arguments", 4);
|
||||
if (!File.Exists(parameters[0])) return Error("--pops-eboot-sign: file not found", 4);
|
||||
ebootElf = File.ReadAllBytes(parameters[0]);
|
||||
|
||||
if (parameters.Count >= 2 && File.Exists(parameters[1]))
|
||||
configBin = File.ReadAllBytes(parameters[1]);
|
||||
else
|
||||
configBin = GameBuilder.Resources.DATAPSPSDCFG;
|
||||
|
||||
break;
|
||||
case ArgumentParsingMode.CMA_OUTPUT_FOLDER:
|
||||
if (parameters.Count < 1) return Error("--output-folder expects 1 output", 4);
|
||||
if (!Directory.Exists(parameters[0])) return Error("--output-folder: directory not found", 4);
|
||||
|
||||
SettingsReader.BackupsFolder = parameters[0];
|
||||
break;
|
||||
case ArgumentParsingMode.RIF:
|
||||
if (parameters.Count != 1) return Error("--rif expects only 1 argument,", 4);
|
||||
rifFile = new NpDrmRif(File.ReadAllBytes(parameters[0]));
|
||||
|
@ -155,20 +194,77 @@ namespace ChovySign_CLI
|
|||
parameters.Clear();
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
public static void generateRif(byte[] idps, byte[] actBuf, byte[] versionKey, int versionKeyType, ulong accountId, string contentId)
|
||||
{
|
||||
byte[] vkey2 = new byte[versionKey.Length];
|
||||
Array.Copy(versionKey, vkey2, versionKey.Length);
|
||||
|
||||
byte[] rkey = Rng.RandomBytes(0x10);
|
||||
int keyId = 0x10; // (Int32)(Rng.RandomUInt() % 0x80);
|
||||
Array.ConstrainedCopy(BitConverter.GetBytes(keyId).Reverse().ToArray(), 0, rkey, 0xC, 0x4);
|
||||
|
||||
byte[] encKey1 = new byte[0x10];
|
||||
AesHelper.AesEncrypt(rkey, encKey1, KeyVault.drmRifKey);
|
||||
|
||||
// get the act key
|
||||
byte[] actKey = new byte[0x10];
|
||||
|
||||
SceNpDrm.SetPSID(idps);
|
||||
SceNpDrm.Aid = accountId;
|
||||
|
||||
Act act = MemoryMarshal.AsRef<Act>(actBuf);
|
||||
GetActKey(actKey, act.PrimKeyTable[(keyId * 0x10)..], 1);
|
||||
|
||||
// reverse version key back to main version key
|
||||
sceNpDrmTransformVersionKey(vkey2, versionKeyType, 0);
|
||||
|
||||
byte[] encKey2 = new byte[0x10];
|
||||
AesHelper.AesEncrypt(vkey2, encKey2, actKey);
|
||||
|
||||
using (MemoryStream rifStream = new MemoryStream())
|
||||
{
|
||||
StreamUtil rifUtil = new StreamUtil(rifStream);
|
||||
|
||||
rifUtil.WriteInt16(0x0);
|
||||
rifUtil.WriteInt16(0x1);
|
||||
|
||||
rifUtil.WriteInt32(0x2);
|
||||
rifUtil.WriteUInt64(accountId);
|
||||
|
||||
rifUtil.WriteStrWithPadding(contentId, 0x00, 0x30);
|
||||
|
||||
rifUtil.WriteBytes(encKey1); // enckey1
|
||||
rifUtil.WriteBytes(encKey2); // enckey2
|
||||
|
||||
rifUtil.WriteUInt64(SceRtc.ksceRtcGetCurrentSecureTick());
|
||||
rifUtil.WriteUInt64(0x00); // expiry
|
||||
|
||||
rifUtil.WritePadding(0xFF, 0x28);
|
||||
}
|
||||
}
|
||||
*/
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("Chovy-Sign v2 (CLI)");
|
||||
Console.WriteLine("--pops [disc1.cue] [disc2.cue] [disc3.cue] ... (up to 5)");
|
||||
Console.WriteLine("--pops-info [game title] [icon0.png] (optional) [pic1.png] (optional)");
|
||||
Console.WriteLine("--pops-eboot [eboot.elf] [config.bin] (optional)");
|
||||
|
||||
Console.WriteLine("--psp [umd.iso] [compress; true/false] (optional)");
|
||||
|
||||
Console.WriteLine("--rif [GAME.RIF]");
|
||||
|
||||
Console.WriteLine("--devkit (Use 000000000000 account id)");
|
||||
Console.WriteLine("--no-psvimg (Disable creating a .psvimg file)");
|
||||
Console.WriteLine("--output-folder [output_folder]");
|
||||
|
||||
Console.WriteLine("--vkey [versionkey] [contentid] [key_index]");
|
||||
Console.WriteLine("--vkey-extract [eboot.pbp]");
|
||||
Console.WriteLine("--vkey-extract [eboot.pbp] [key_index]");
|
||||
Console.WriteLine("--vkey-gen [act.dat] [license.rif] [console_id] [key_index]");
|
||||
|
||||
Console.WriteLine("--keys-txt-gen [act.dat] [console_id] [psp_license_folder]");
|
||||
}
|
||||
|
||||
|
@ -236,6 +332,17 @@ namespace ChovySign_CLI
|
|||
return Error("rif is already set", 3);
|
||||
|
||||
break;
|
||||
case "--pops-eboot":
|
||||
mode = ArgumentParsingMode.POPS_EBOOT;
|
||||
break;
|
||||
case "--output-folder":
|
||||
mode = ArgumentParsingMode.CMA_OUTPUT_FOLDER;
|
||||
break;
|
||||
|
||||
case "--no-psvimg":
|
||||
packagePsvImg = false;
|
||||
break;
|
||||
|
||||
case "--devkit":
|
||||
devKit = true;
|
||||
break;
|
||||
|
@ -248,6 +355,7 @@ namespace ChovySign_CLI
|
|||
case ArgumentParsingMode.VERSIONKEY_EXTRACT:
|
||||
case ArgumentParsingMode.PSP_UMD:
|
||||
case ArgumentParsingMode.POPS_DISC:
|
||||
case ArgumentParsingMode.POPS_EBOOT:
|
||||
case ArgumentParsingMode.POPS_INFO:
|
||||
case ArgumentParsingMode.RIF:
|
||||
default:
|
||||
|
@ -261,20 +369,17 @@ namespace ChovySign_CLI
|
|||
generateKeysTxt();
|
||||
|
||||
if (drmInfo is null) return Error("no versionkey was found, exiting", 6);
|
||||
|
||||
//Console.WriteLine("Version Key: " + BitConverter.ToString(drmInfo.VersionKey).Replace("-", "") + ", " + drmInfo.KeyIndex);
|
||||
|
||||
if (pbpMode is null) return Error("no pbp mode was set, exiting", 7);
|
||||
|
||||
if (pbpMode == PbpMode.PSP && drmInfo.KeyIndex != 2)
|
||||
return Error("KeyType is "+drmInfo.KeyIndex+", but PBP mode is PSP, you cant do that .. please use a type 1 versionkey.", 8);
|
||||
int targetKeyIndex = (pbpMode == PbpMode.PSP) ? 2 : 1;
|
||||
if (drmInfo.KeyIndex != targetKeyIndex)
|
||||
{
|
||||
SceNpDrm.sceNpDrmTransformVersionKey(drmInfo.VersionKey, drmInfo.KeyIndex, 2);
|
||||
drmInfo.KeyIndex = targetKeyIndex;
|
||||
}
|
||||
|
||||
if (pbpMode == PbpMode.POPS && drmInfo.KeyIndex != 1)
|
||||
return Error("KeyType is " + drmInfo.KeyIndex + ", but PBP mode is POPS, you cant do that .. please use a type 1 versionkey.", 8);
|
||||
if (rifFile is null) return Error("Rif is not set, use --rif to specify base game RIF", 8);
|
||||
|
||||
if (rifFile is null)
|
||||
return Error("Rif is not set, use --rif to specify base game RIF", 8);
|
||||
//if (pbpMode == PbpMode.POPS && (popsDiscName is null || popsIcon0File is null)) return Error("pbp mode is POPS, but you have not specified a disc title or icon file using --pops-info.", 9);
|
||||
ChovySign csign = new ChovySign();
|
||||
csign.RegisterCallback(onProgress);
|
||||
if (pbpMode == PbpMode.POPS)
|
||||
|
@ -287,11 +392,17 @@ namespace ChovySign_CLI
|
|||
if(popsDiscName is not null)
|
||||
popsParameters.Name = popsDiscName;
|
||||
|
||||
if(File.Exists(popsIcon0File))
|
||||
popsParameters.Icon0 = File.ReadAllBytes(popsIcon0File);
|
||||
if(popsIcon0File is not null)
|
||||
popsParameters.Icon0 = popsIcon0File;
|
||||
|
||||
|
||||
popsParameters.CreatePsvImg = packagePsvImg;
|
||||
popsParameters.Account.Devkit = devKit;
|
||||
|
||||
// Allow for custom eboot.elf and configs
|
||||
popsParameters.ConfigBinOverride = configBin;
|
||||
popsParameters.EbootElfOverride = ebootElf;
|
||||
|
||||
csign.Go(popsParameters);
|
||||
|
||||
}
|
||||
|
@ -299,6 +410,8 @@ namespace ChovySign_CLI
|
|||
{
|
||||
PspParameters pspParameters = new PspParameters(drmInfo, rifFile);
|
||||
pspParameters.Account.Devkit = devKit;
|
||||
pspParameters.CreatePsvImg = packagePsvImg;
|
||||
|
||||
pspParameters.Compress = pspCompress;
|
||||
pspParameters.Umd = new UmdInfo(discs.First());
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<History>True|2023-04-26T03:20:05.7988009Z;True|2023-04-24T08:18:55.4774877+12:00;True|2023-04-20T08:33:00.3404616+12:00;False|2023-04-20T08:29:02.1306599+12:00;True|2023-04-19T21:53:45.1116925+12:00;True|2023-04-19T20:46:20.2756012+12:00;True|2023-04-19T19:58:40.3825010+12:00;True|2023-04-18T00:00:51.4131559+12:00;True|2023-04-17T09:56:35.5065135+12:00;True|2023-04-17T09:22:54.8607008+12:00;True|2023-04-17T08:27:16.5281469+12:00;True|2023-04-17T08:22:02.0531219+12:00;</History>
|
||||
<LastFailureDetails />
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\Linux</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -6,10 +6,10 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\</PublishDir>
|
||||
<PublishDir>bin\Release\Windows</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
|
@ -1,153 +1,123 @@
|
|||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="ChovySign_GUI.App">
|
||||
x:Class="ChovySign_GUI.App"
|
||||
RequestedThemeVariant="Dark">
|
||||
<Application.Styles>
|
||||
<FluentTheme Mode="Light"/>
|
||||
<FluentTheme/>
|
||||
|
||||
<!-- Checkbox Styling -->
|
||||
<Style Selector="CheckBox:checked /template/ ContentPresenter">
|
||||
<Setter Property="TextBlock.Foreground">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
<!-- checked -->
|
||||
<Style Selector="CheckBox:checked">
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox:checked /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>#3f3f3f</Setter.Value>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
<Setter Property="Background" Value="#3f3f3f" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox:pointerover /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>#1f1f1f</Setter.Value>
|
||||
</Setter>
|
||||
<!-- unchecked -->
|
||||
|
||||
<Style Selector="CheckBox:unchecked">
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>#3f3f3f</Setter.Value>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
<Setter Property="Background" Value="#3f3f3f" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="TextBlock.Foreground">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
<!-- pointerover -->
|
||||
|
||||
<Style Selector="CheckBox:pointerover">
|
||||
<Setter Property="BorderBrush" Value="Green" />
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Foreground" Value="Green" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush" Value="Green" />
|
||||
<Setter Property="Background" Value="#1f1f1f" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="CheckBox">
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
|
||||
<!-- Button styles -->
|
||||
<Style Selector="Button:disabled /template/ ContentPresenter">
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>Black</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>DarkRed</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="TextBlock.Foreground">
|
||||
<Setter.Value>DarkRed</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
<!-- disabled -->
|
||||
<Style Selector="Button:disabled">
|
||||
<Style Selector="^:disabled /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="Black" />
|
||||
<Setter Property="BorderBrush" Value="DarkRed" />
|
||||
<Setter Property="Foreground" Value="DarkRed" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Button:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>Red</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>DarkRed</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="TextBlock.Foreground">
|
||||
<Setter.Value>Black</Setter.Value>
|
||||
</Setter>
|
||||
<!-- pointerover -->
|
||||
<Style Selector="Button:pointerover">
|
||||
<Style Selector="^:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="Red" />
|
||||
<Setter Property="BorderBrush" Value="DarkRed" />
|
||||
<Setter Property="Foreground" Value="Black" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<!-- regular -->
|
||||
<Style Selector="Button">
|
||||
<Setter Property="BorderThickness">
|
||||
<Setter.Value>1</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>Red</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>Red</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>Black</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Background" Value="Black" />
|
||||
<Setter Property="BorderBrush" Value="Red" />
|
||||
<Setter Property="Foreground" Value="Red" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
</Style>
|
||||
|
||||
<!-- Textbox Styling -->
|
||||
|
||||
<Style Selector="TextBox:focus">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
|
||||
<Style Selector="^ /template/ TextBlock">
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBox:focus /template/ TextBlock">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border">
|
||||
<Setter Property="Background" Value="#3f3f3f" />
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
</Style>
|
||||
<Style Selector="TextBox:focus /template/ Border">
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>#3f3f3f</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="TextBox:pointerover">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="Green" />
|
||||
|
||||
<Style Selector="^ /template/ TextBlock">
|
||||
<Setter Property="Foreground" Value="Green" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBox:pointerover /template/ TextBlock">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border">
|
||||
<Setter Property="Background" Value="#1f1f1f" />
|
||||
<Setter Property="BorderBrush" Value="Green" />
|
||||
</Style>
|
||||
<Style Selector="TextBox:pointerover /template/ Border">
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>#1f1f1f</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBox">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>#3f3f3f</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderBrush">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="LightGreen" />
|
||||
<Setter Property="Background" Value="#3f3f3f" />
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
</Style>
|
||||
|
||||
<!-- ComboBox -->
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
|
@ -16,8 +16,6 @@
|
|||
<None Remove="Icon.png" />
|
||||
<None Remove="Popup\Global\KeySelector\ACTRIFMETHOD.PNG" />
|
||||
<None Remove="Popup\Global\KeySelector\EBOOTMETHOD.PNG" />
|
||||
<None Remove="Popup\Global\KeySelector\EBOOTMETHOD1.png" />
|
||||
<None Remove="Popup\Global\KeySelector\EBOOTMETHOD2.png" />
|
||||
<None Remove="Popup\Global\KeySelector\KEYSTXTMETHOD.PNG" />
|
||||
<None Remove="PS1CD.PNG" />
|
||||
<None Remove="UMD.png" />
|
||||
|
@ -25,8 +23,7 @@
|
|||
<ItemGroup>
|
||||
<AvaloniaResource Include="ICON.PNG" />
|
||||
<AvaloniaResource Include="Popup\Global\KeySelector\ACTRIFMETHOD.PNG" />
|
||||
<AvaloniaResource Include="Popup\Global\KeySelector\EBOOTMETHOD1.PNG" />
|
||||
<AvaloniaResource Include="Popup\Global\KeySelector\EBOOTMETHOD2.PNG" />
|
||||
<AvaloniaResource Include="Popup\Global\KeySelector\EBOOTMETHOD.PNG" />
|
||||
<AvaloniaResource Include="Popup\Global\KeySelector\KEYSTXTMETHOD.PNG" />
|
||||
<AvaloniaResource Include="Ps1\PS1CD.PNG" />
|
||||
<AvaloniaResource Include="Psp\UMD.PNG">
|
||||
|
@ -42,11 +39,11 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.10.19" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.19" />
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-beta1" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.1.0-beta1" />
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.19" />
|
||||
<PackageReference Include="XamlNameReferenceGenerator" Version="1.6.1" />
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.0-beta1" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.0-beta1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -176,19 +176,28 @@ namespace ChovySign_GUI.Global
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public BrowseButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.filePath.KeyUp += onKeyPress;
|
||||
this.filePath.PropertyChanged += onPropertyChanged;
|
||||
|
||||
this.extension = "";
|
||||
this.fileTypeName = "All Files";
|
||||
}
|
||||
|
||||
private void onKeyPress(object? sender, KeyEventArgs e)
|
||||
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;
|
||||
if (!ContainsFile) return;
|
||||
OnFileChanged(new EventArgs());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,19 +153,19 @@ namespace ChovySign_GUI.Global
|
|||
break;
|
||||
case VersionKeyMethod.EBOOT_PBP_METHOD:
|
||||
CmaBackupPicker ebootBackupSelector = new CmaBackupPicker();
|
||||
ebootBackupSelector.BackupType = ((keyIndex == 1) ? "PSGAME" : "PGAME");
|
||||
ebootBackupSelector.BackupType = new string[] { "PGAME", "PSGAME" };
|
||||
|
||||
string? gameBackupFolder = await ebootBackupSelector.ShowDialog<string>(currentWindow);
|
||||
string accountId = ebootBackupSelector.AccountId;
|
||||
if (gameBackupFolder is null) break;
|
||||
if (accountId == "") break;
|
||||
|
||||
key = CMAVersionKeyHelper.GetKeyFromGamePsvimg(gameBackupFolder, accountId);
|
||||
key = CMAVersionKeyHelper.GetKeyFromGamePsvimg(gameBackupFolder, accountId, this.keyIndex);
|
||||
rif = CMAVersionKeyHelper.GetRifFromLicensePsvimg(gameBackupFolder, accountId);
|
||||
break;
|
||||
case VersionKeyMethod.KEYS_TXT_METHOD:
|
||||
CmaBackupPicker pspLicenseBackupSelector = new CmaBackupPicker();
|
||||
pspLicenseBackupSelector.BackupType = "PGAME";
|
||||
pspLicenseBackupSelector.BackupType = new string[] { "PGAME", "PSGAME" };
|
||||
pspLicenseBackupSelector.Filter = KeysTxtMethod.TitleIds;
|
||||
|
||||
gameBackupFolder = await pspLicenseBackupSelector.ShowDialog<string>(currentWindow);
|
||||
|
@ -186,10 +186,8 @@ namespace ChovySign_GUI.Global
|
|||
if (key is not null)
|
||||
{
|
||||
if (key.KeyIndex != this.keyIndex)
|
||||
{
|
||||
await MessageBox.Show(currentWindow, "VersionKey obtained, but had keyindex: " + key.KeyIndex + " however keyindex " + this.keyIndex + " was required.", "KeyIndex mismatch!", MessageBoxButtons.Ok);
|
||||
return;
|
||||
}
|
||||
sceNpDrmTransformVersionKey(key.VersionKey, key.KeyIndex, this.keyIndex);
|
||||
// its a revoolution~
|
||||
|
||||
VersionKey = key.VersionKey;
|
||||
}
|
||||
|
|
|
@ -54,13 +54,13 @@ namespace ChovySign_GUI.Global
|
|||
{
|
||||
get
|
||||
{
|
||||
string[]? strings = this.comboBox.Items as string[];
|
||||
string[]? strings = this.comboBox.ItemsSource as string[];
|
||||
if (strings is null) return new string[0];
|
||||
return strings;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.comboBox.Items = value;
|
||||
this.comboBox.ItemsSource = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using ChovySign_GUI.Popup.Global;
|
||||
using ChovySign_GUI.Settings;
|
||||
using Li.Progress;
|
||||
using LibChovy;
|
||||
using System;
|
||||
|
@ -13,6 +14,8 @@ namespace ChovySign_GUI.Global
|
|||
public partial class ProgressStatus : UserControl
|
||||
{
|
||||
public ChovySignParameters? Parameters = null;
|
||||
public event EventHandler<EventArgs>? Finished;
|
||||
public event EventHandler<EventArgs>? BeforeStart;
|
||||
private ChovySign chovySign;
|
||||
public ProgressStatus()
|
||||
{
|
||||
|
@ -21,14 +24,13 @@ namespace ChovySign_GUI.Global
|
|||
chovySign = new ChovySign();
|
||||
chovySign.RegisterCallback(onProgress);
|
||||
}
|
||||
public event EventHandler<EventArgs>? BeforeStart;
|
||||
protected virtual void OnBeforeStart(EventArgs e)
|
||||
{
|
||||
if (BeforeStart is not null)
|
||||
BeforeStart(this, e);
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs>? Finished;
|
||||
|
||||
protected virtual void OnFinished(EventArgs e)
|
||||
{
|
||||
if (Finished is not null)
|
||||
|
@ -44,13 +46,23 @@ namespace ChovySign_GUI.Global
|
|||
this.goButton.IsEnabled = false;
|
||||
|
||||
OnBeforeStart(new EventArgs());
|
||||
|
||||
// sanity check it
|
||||
if(Parameters is null) { await MessageBox.Show(currentWindow, "ChovySignParameters was null, cannot start!", "Invalid Parameters", MessageBoxButtons.Ok); return; }
|
||||
// apply settings that are global to all signs
|
||||
if(SettingsTab.Settings is not null) Parameters.BuildStreamType = SettingsTab.Settings.BuildStreamType;
|
||||
|
||||
await Task.Run(() => { chovySign.Go(Parameters); });
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Run(() => {
|
||||
chovySign.Go(Parameters);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await MessageBox.Show(currentWindow, "Error building: " + ex.Message + "\n\nSTACKTRACE: " + ex.StackTrace, "ERROR", MessageBoxButtons.Ok);
|
||||
return;
|
||||
}
|
||||
OnFinished(new EventArgs());
|
||||
|
||||
this.goButton.IsEnabled = true;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace ChovySign_GUI
|
||||
|
|
|
@ -3,7 +3,8 @@ using Avalonia.Interactivity;
|
|||
using ChovySign_GUI.Global;
|
||||
using GameBuilder.Psp;
|
||||
using LibChovy.Config;
|
||||
using Org.BouncyCastle.Utilities.Bzip2;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -16,7 +17,7 @@ namespace ChovySign_GUI.Popup.Global
|
|||
|
||||
private const string lookingInLabelText = "Looking in: ";
|
||||
private string[]? gameDirectories;
|
||||
private string backupSubFolder = "";
|
||||
private string[] backupSubFolders;
|
||||
|
||||
private string[]? filter;
|
||||
|
||||
|
@ -69,50 +70,80 @@ namespace ChovySign_GUI.Popup.Global
|
|||
}
|
||||
}
|
||||
|
||||
private string accountIdSearchFolder
|
||||
private string[] accountIdSearchFolders
|
||||
{
|
||||
get
|
||||
{
|
||||
string searchIn = Path.Combine(BackupDir, this.BackupType);
|
||||
string[] searchIn = new string[this.BackupType.Length];
|
||||
for (int i = 0; i < this.BackupType.Length; i++)
|
||||
{
|
||||
searchIn[i] = Path.Combine(BackupDir, this.BackupType[i]);
|
||||
}
|
||||
|
||||
return searchIn;
|
||||
}
|
||||
}
|
||||
private string backupSearchFolder
|
||||
private string[] backupSearchFolders
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AccountId == "") return accountIdSearchFolder;
|
||||
return Path.Combine(accountIdSearchFolder, AccountId);
|
||||
string[] backupFolders = new string[this.BackupType.Length];
|
||||
string[] searchFolders = this.accountIdSearchFolders;
|
||||
for (int i = 0; i < this.BackupType.Length; i++)
|
||||
{
|
||||
if (this.AccountId == "") backupFolders[i] = searchFolders[i];
|
||||
backupFolders[i] = Path.Combine(searchFolders[i], this.AccountId);
|
||||
}
|
||||
return backupFolders;
|
||||
}
|
||||
}
|
||||
public string BackupType
|
||||
public string[] BackupType
|
||||
{
|
||||
get
|
||||
{
|
||||
return backupSubFolder;
|
||||
return backupSubFolders;
|
||||
}
|
||||
set
|
||||
{
|
||||
backupSubFolder = value;
|
||||
lookingInLbl.Content = lookingInLabelText + backupSubFolder;
|
||||
backupSubFolders = value;
|
||||
lookingInLbl.Content = lookingInLabelText + String.Join(", ", backupSubFolders);
|
||||
|
||||
reloadAccountIdsList();
|
||||
reloadBackupsList();
|
||||
}
|
||||
}
|
||||
|
||||
private string[] GetAllDriectories(string[] dirList)
|
||||
{
|
||||
List<string> foundDir = new List<string>();
|
||||
|
||||
foreach(string dirSearch in dirList)
|
||||
{
|
||||
if (!Directory.Exists(dirSearch)) continue;
|
||||
foreach(string dir in Directory.GetDirectories(dirSearch))
|
||||
{
|
||||
if (!foundDir.Contains(dir))
|
||||
{
|
||||
foundDir.Add(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return foundDir.ToArray();
|
||||
}
|
||||
|
||||
private void reloadAccountIdsList()
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] usedAccountIds = Directory.GetDirectories(accountIdSearchFolder);
|
||||
string[] usedAccountIds = GetAllDriectories(accountIdSearchFolders);
|
||||
List<string> accountIdLst = new List<string>();
|
||||
foreach (string accountId in usedAccountIds)
|
||||
{
|
||||
string aid = Path.GetFileName(accountId);
|
||||
if (accountIdLst.Contains(aid)) continue;
|
||||
if (aid.Length != 16) continue;
|
||||
accountIdLst.Add(aid);
|
||||
|
||||
}
|
||||
|
||||
this.accId.Items = accountIdLst.ToArray();
|
||||
|
@ -139,11 +170,11 @@ namespace ChovySign_GUI.Popup.Global
|
|||
private void reloadBackupsList()
|
||||
{
|
||||
this.selectBtn.IsEnabled = false;
|
||||
this.backupList.Items = new string[0];
|
||||
this.backupList.ItemsSource = new string[0];
|
||||
try
|
||||
{
|
||||
if(!Directory.Exists(backupSearchFolder)) { return; }
|
||||
string[] gameBackupDirectories = Directory.GetDirectories(backupSearchFolder);
|
||||
string[] gameBackupDirectories = GetAllDriectories(backupSearchFolders);
|
||||
|
||||
List<string> filteredGameDirectories = new List<string>();
|
||||
List<string> gameList = new List<string>();
|
||||
foreach (string gameDirectory in gameBackupDirectories)
|
||||
|
@ -171,7 +202,7 @@ namespace ChovySign_GUI.Popup.Global
|
|||
}
|
||||
|
||||
this.gameDirectories = filteredGameDirectories.ToArray();
|
||||
this.backupList.Items = gameList;
|
||||
this.backupList.ItemsSource = gameList;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
@ -180,7 +211,7 @@ namespace ChovySign_GUI.Popup.Global
|
|||
{
|
||||
InitializeComponent();
|
||||
this.cmaDir.FilePath = BackupDir;
|
||||
this.backupSubFolder = "APP";
|
||||
this.backupSubFolders = new string[] { "APP" };
|
||||
this.accId.SelectionChanged += onAccountSelectionChanged;
|
||||
this.cmaDir.FileChanged += onCmaDirChanged;
|
||||
this.backupList.SelectionChanged += onSelectedBackupChanged;
|
||||
|
@ -191,6 +222,7 @@ namespace ChovySign_GUI.Popup.Global
|
|||
private void onSelectedBackupChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
ListBox? lstBox = sender as ListBox;
|
||||
if (lstBox is null) return;
|
||||
if (lstBox.SelectedIndex == -1) selectBtn.IsEnabled = false;
|
||||
else selectBtn.IsEnabled = true;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
|
@ -21,8 +21,7 @@
|
|||
<Button Content="IDPS+RIF+ACT Method" Click="actRifMethodClick" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<Button Content="KEYS.TXT Method" Click="keysTxtMethodClick" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
|
||||
<Image Name="ebootMethodPs1Graphic" Source="/Popup/Global/KeySelector/EBOOTMETHOD1.PNG" Grid.Row="1" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
|
||||
<Image Name="ebootMethodPspGraphic" Source="/Popup/Global/KeySelector/EBOOTMETHOD2.PNG" Grid.Row="1" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
|
||||
<Image Name="ebootMethodGraphic" Source="/Popup/Global/KeySelector/EBOOTMETHOD.PNG" Grid.Row="1" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
|
||||
<Image Name="actRifMethodGraphic" Source="/Popup/Global/KeySelector/ACTRIFMETHOD.PNG" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
|
||||
<Image Name="keysTxtMethodGraphic" Source="/Popup/Global/KeySelector/KEYSTXTMETHOD.PNG" Grid.Row="1" Grid.Column="2" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
|
||||
</Grid>
|
||||
|
|
|
@ -20,8 +20,6 @@ namespace ChovySign_GUI.Popup.Global.KeySelector
|
|||
set
|
||||
{
|
||||
keyIndex = value;
|
||||
if (keyIndex == 1) { ebootMethodPspGraphic.IsVisible = false; ebootMethodPs1Graphic.IsVisible = true; }
|
||||
else { ebootMethodPspGraphic.IsVisible = true; ebootMethodPs1Graphic.IsVisible = false; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,11 +99,19 @@ namespace ChovySign_GUI.Ps1
|
|||
Title = disc.DiscName;
|
||||
DiscId = disc.DiscId;
|
||||
|
||||
if (!File.Exists(this.iconFile.FilePath))
|
||||
{
|
||||
byte[] newCover = await Downloader.DownloadCover(disc);
|
||||
loadIcon(newCover);
|
||||
iconCache = newCover;
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
catch (Exception e) {
|
||||
Window? currentWindow = this.VisualRoot as Window;
|
||||
if (currentWindow is not Window) throw new Exception("could not find current window");
|
||||
|
||||
await MessageBox.Show(currentWindow, "unable to read cue sheet: " + Path.GetFileName(cueFile) + "\n" + e.Message + "\n\nSTACKTRACE: " + e.StackTrace, "cannot load cue sheet", MessageBox.MessageBoxButtons.Ok);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<byte[]?> doLoad(BrowseButton imgFile, int width, int height)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
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;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Vita.ContentManager;
|
||||
|
@ -70,8 +68,10 @@ namespace ChovySign_GUI.Ps1
|
|||
|
||||
// read settings from settings tab.
|
||||
if (SettingsTab.Settings.DevkitMode) popsParameters.Account = new Account(0);
|
||||
|
||||
popsParameters.CrackMethod = SettingsTab.Settings.LibcryptMode;
|
||||
SettingsReader.BackupsFolder = SettingsTab.Settings.CmaDirectory;
|
||||
popsParameters.CreatePsvImg = SettingsTab.Settings.PackagePsvimg;
|
||||
|
||||
progressStatus.Parameters = popsParameters;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace ChovySign_GUI.Psp
|
|||
{
|
||||
keySelector.IsEnabled = true;
|
||||
isoSelector.IsEnabled = true;
|
||||
SettingsTab.Settings.IsEnabled = false;
|
||||
SettingsTab.Settings.IsEnabled = true;
|
||||
|
||||
Window? currentWindow = this.VisualRoot as Window;
|
||||
if (currentWindow is not Window) throw new Exception("could not find current window");
|
||||
|
@ -67,8 +67,9 @@ namespace ChovySign_GUI.Psp
|
|||
pspParameters.Compress = isoSelector.Compress;
|
||||
|
||||
// read settings from settings tab.
|
||||
if (SettingsTab.Settings.DevkitMode) pspParameters.Account = new Account(0);
|
||||
pspParameters.Account.Devkit = SettingsTab.Settings.DevkitMode;
|
||||
SettingsReader.BackupsFolder = SettingsTab.Settings.CmaDirectory;
|
||||
pspParameters.CreatePsvImg = SettingsTab.Settings.PackagePsvimg;
|
||||
|
||||
progressStatus.Parameters = pspParameters;
|
||||
}
|
||||
|
|
|
@ -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="80"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="85"
|
||||
x:Class="ChovySign_GUI.Settings.ConfigDropDown">
|
||||
<Grid>
|
||||
<Global:LabeledComboBox Name="configComboBox" Label="Label"/>
|
||||
|
|
|
@ -13,12 +13,30 @@ namespace ChovySign_GUI.Settings
|
|||
|
||||
internal bool disableEvents = false;
|
||||
private string? promptMsg = null;
|
||||
|
||||
private bool defaultSetting = false;
|
||||
internal override void init()
|
||||
{
|
||||
bool? isToggleChecked = ChovyConfig.CurrentConfig.GetBool(ConfigKey);
|
||||
if (isToggleChecked is null) isToggleChecked = false;
|
||||
if(isToggleChecked is null) isToggleChecked = defaultSetting;
|
||||
|
||||
this.disableEvents = true;
|
||||
configCheckbox.IsChecked = isToggleChecked;
|
||||
this.disableEvents = false;
|
||||
}
|
||||
|
||||
public bool Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultSetting;
|
||||
}
|
||||
set
|
||||
{
|
||||
defaultSetting = value;
|
||||
|
||||
if (ChovyConfig.CurrentConfig.GetBool(ConfigKey) is null)
|
||||
this.IsToggled = defaultSetting;
|
||||
}
|
||||
}
|
||||
public string Label
|
||||
{
|
||||
|
@ -67,6 +85,9 @@ namespace ChovySign_GUI.Settings
|
|||
else
|
||||
IsToggled = false;
|
||||
}
|
||||
else{
|
||||
IsToggled = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,42 @@
|
|||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<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)"
|
||||
<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
Which is how it is on Devkit, Testkit and IDU Firmware
Enabling this if you have a retail firmware will result in the games just *not* showing up

If you DON'T know what this means, DON'T enable this.
do you want to continue?"
|
||||
HorizontalAlignment="Stretch" Grid.Row="0"/>
|
||||
HorizontalAlignment="Stretch"
|
||||
Default="false"
|
||||
Grid.Row="0"/>
|
||||
|
||||
<Settings:ConfigPath Name="cmaDirectory" ConfigKey="USE_CMA_DIRECTORY" IsDirectory="True" Label="Output Folder:" HorizontalAlignment="Stretch" Grid.Row="1"/>
|
||||
<Settings:ConfigToggle Name="packagePsvimg"
|
||||
ConfigKey="USE_CMA_PSVIMG"
|
||||
Label="Use Content Manager (Package to PSVIMG)"
|
||||
Default="true"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Row="1"/>
|
||||
|
||||
<Settings:ConfigDropDown Name="libCryptMode" ConfigKey="USE_LIBCRYPT_METHOD" Label="LibCrypt Method:" HorizontalAlignment="Stretch" Grid.Row="2"/>
|
||||
<Settings:ConfigPath Name="cmaDirectory"
|
||||
ConfigKey="USE_CMA_DIRECTORY"
|
||||
IsDirectory="true"
|
||||
Label="Output Folder:"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Row="2"/>
|
||||
|
||||
<Settings:ConfigDropDown Name="libCryptMode"
|
||||
ConfigKey="USE_LIBCRYPT_METHOD"
|
||||
Label="LibCrypt Method:"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Row="3"/>
|
||||
|
||||
<Settings:ConfigDropDown Name="streamType"
|
||||
ConfigKey="USE_STREAM_TYPE"
|
||||
Label="Build Stream Type:"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Row="4"/>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Avalonia.Controls;
|
||||
using GameBuilder.Pops.LibCrypt;
|
||||
using GameBuilder;
|
||||
using System.IO;
|
||||
using Vita.ContentManager;
|
||||
|
||||
|
@ -7,7 +8,15 @@ namespace ChovySign_GUI.Settings
|
|||
{
|
||||
public partial class SettingsTab : UserControl
|
||||
{
|
||||
public static SettingsTab Settings;
|
||||
public static SettingsTab? Settings;
|
||||
|
||||
public StreamType BuildStreamType
|
||||
{
|
||||
get
|
||||
{
|
||||
return (StreamType) this.streamType.SelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public LibCryptMethod LibcryptMode
|
||||
{
|
||||
|
@ -37,6 +46,13 @@ namespace ChovySign_GUI.Settings
|
|||
return devkitAccount.IsToggled;
|
||||
}
|
||||
}
|
||||
public bool PackagePsvimg
|
||||
{
|
||||
get
|
||||
{
|
||||
return packagePsvimg.IsToggled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SettingsTab()
|
||||
|
@ -44,10 +60,12 @@ namespace ChovySign_GUI.Settings
|
|||
InitializeComponent();
|
||||
|
||||
libCryptMode.Items = new string[2] { "Magic Word in ISO Header", "Sub Channel PGD" };
|
||||
streamType.Items = new string[2] { "MemoryStream - Create EBOOT in memory, faster, but high memory usage", "FileStream - Create EBOOT with temporary files, slower, but less memory usage" };
|
||||
|
||||
if (!Directory.Exists(this.CmaDirectory))
|
||||
cmaDirectory.Value = SettingsReader.BackupsFolder;
|
||||
|
||||
|
||||
Settings = this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -3,6 +3,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -12,6 +13,9 @@ namespace GameBuilder.Atrac3
|
|||
{
|
||||
public class Atrac3ToolEncoder : IAtracEncoderBase
|
||||
{
|
||||
[DllImport("libc")]
|
||||
private static extern int setenv(string name, string value, bool overwrite);
|
||||
|
||||
private static Random rng = new Random();
|
||||
private static string TOOLS_DIRECTORY = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "tools");
|
||||
|
||||
|
@ -19,6 +23,7 @@ namespace GameBuilder.Atrac3
|
|||
private static string AT3TOOL_LINUX = Path.Combine(TOOLS_DIRECTORY, "at3tool.elf");
|
||||
|
||||
private static string TEMP_DIRECTORY = Path.Combine(Path.GetTempPath(), "at3tool_tmp");
|
||||
private static string LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
|
||||
|
||||
// random name so that can generate multiple at once if wanted ..
|
||||
private string TEMP_WAV;
|
||||
|
@ -45,10 +50,24 @@ namespace GameBuilder.Atrac3
|
|||
}
|
||||
}
|
||||
|
||||
private string setupLibaryPath()
|
||||
{
|
||||
string? libaryPath = Environment.GetEnvironmentVariable(LD_LIBRARY_PATH);
|
||||
if (libaryPath is null) libaryPath = TOOLS_DIRECTORY;
|
||||
else libaryPath += ";" + TOOLS_DIRECTORY;
|
||||
|
||||
Environment.SetEnvironmentVariable(libaryPath, libaryPath);
|
||||
setenv(LD_LIBRARY_PATH, libaryPath, true);
|
||||
|
||||
return libaryPath;
|
||||
}
|
||||
private void runAtrac3Tool()
|
||||
{
|
||||
using(Process proc = new Process())
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
proc.StartInfo.Environment.Add(LD_LIBRARY_PATH, setupLibaryPath());
|
||||
|
||||
proc.StartInfo.FileName = AT3TOOL_LOCATION;
|
||||
proc.StartInfo.Arguments = "-br 132 -e \"" + TEMP_WAV + "\" \"" + TEMP_AT3 + "\"";
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
using DiscUtils.Streams;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder
|
||||
{
|
||||
public class BuildStream : Stream
|
||||
{
|
||||
public static StreamType BuildUsingStreamType = StreamType.TYPE_MEMORY_STREAM;
|
||||
private Stream underylingStream;
|
||||
|
||||
private StreamType uStreamType;
|
||||
private string? filename = null;
|
||||
|
||||
private void init()
|
||||
{
|
||||
this.uStreamType = BuildUsingStreamType;
|
||||
if (this.uStreamType == StreamType.TYPE_MEMORY_STREAM)
|
||||
{
|
||||
this.underylingStream = new MemoryStream();
|
||||
}
|
||||
else if (this.uStreamType == StreamType.TYPE_FILE_STREAM)
|
||||
{
|
||||
string tmpFolder = Path.Combine(Path.GetTempPath(), "chovysign2");
|
||||
Directory.CreateDirectory(tmpFolder);
|
||||
|
||||
this.filename = Path.Combine(tmpFolder, Guid.NewGuid().ToString());
|
||||
this.underylingStream = File.Create(this.filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("unknown stream type");
|
||||
}
|
||||
}
|
||||
|
||||
public BuildStream(byte[] data)
|
||||
{
|
||||
init();
|
||||
this.Write(data, 0, data.Length);
|
||||
this.Seek(0x00, SeekOrigin.Begin);
|
||||
}
|
||||
public BuildStream()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
public override bool CanRead {
|
||||
get {
|
||||
return underylingStream.CanRead;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get {
|
||||
return underylingStream.CanSeek;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get {
|
||||
return underylingStream.CanWrite;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get {
|
||||
return underylingStream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get {
|
||||
return underylingStream.Position;
|
||||
}
|
||||
set {
|
||||
underylingStream.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
this.underylingStream.Close();
|
||||
|
||||
if(this.uStreamType == StreamType.TYPE_FILE_STREAM && this.filename is not null)
|
||||
File.Delete(this.filename);
|
||||
|
||||
base.Close();
|
||||
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
underylingStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return underylingStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return underylingStream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
underylingStream.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
underylingStream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
public byte[] ToArray()
|
||||
{
|
||||
long oldLocation = this.Position;
|
||||
|
||||
this.Seek(0x00, SeekOrigin.Begin);
|
||||
|
||||
byte[] rdData = new byte[this.Length];
|
||||
this.Read(rdData, 0x00, rdData.Length);
|
||||
|
||||
this.Seek(oldLocation, SeekOrigin.Begin);
|
||||
|
||||
return rdData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -269,7 +269,7 @@ namespace GameBuilder.Cue
|
|||
|
||||
public byte[] CreateToc()
|
||||
{
|
||||
using (MemoryStream toc = new MemoryStream())
|
||||
using (BuildStream toc = new BuildStream())
|
||||
{
|
||||
StreamUtil tocUtil = new StreamUtil(toc);
|
||||
tocUtil.WriteBytes(createDummyTracks());
|
||||
|
@ -300,6 +300,19 @@ namespace GameBuilder.Cue
|
|||
openTracks.Clear();
|
||||
}
|
||||
|
||||
private string getFilename(string str)
|
||||
{
|
||||
if (!str.Contains(' ')) throw new Exception("cue specifies no bin file.");
|
||||
if (!str.Contains('"')) return str.Split(' ')[1];
|
||||
|
||||
int start = str.IndexOf('"');
|
||||
str = str.Substring(start + 1);
|
||||
|
||||
|
||||
int end = str.IndexOf('"');
|
||||
str = str.Substring(0, end);
|
||||
return str;
|
||||
}
|
||||
public CueReader(string cueFile)
|
||||
{
|
||||
openTracks = new Dictionary<int, CueStream>();
|
||||
|
@ -310,10 +323,11 @@ namespace GameBuilder.Cue
|
|||
CueTrack? curTrack = null;
|
||||
|
||||
for (string? cueData = cueReader.ReadLine();
|
||||
cueData != null;
|
||||
cueData is not null;
|
||||
cueData = cueReader.ReadLine())
|
||||
{
|
||||
string[] cueLn = cueData.Trim().Replace("\r", "").Replace("\n", "").Split(' ');
|
||||
cueData = cueData.Trim().Replace("\r", "").Replace("\n", "");
|
||||
string[] cueLn = cueData.Split(' ');
|
||||
|
||||
if (cueLn[0] == "INDEX")
|
||||
{
|
||||
|
@ -350,17 +364,17 @@ namespace GameBuilder.Cue
|
|||
if (curTrack != null) setTrackNumber(curTrack.TrackNo, ref curTrack);
|
||||
|
||||
// parse out filename..
|
||||
string[] cueFnameParts = new string[cueLn.Length - 2];
|
||||
Array.ConstrainedCopy(cueLn, 1, cueFnameParts, 0, cueFnameParts.Length);
|
||||
string cueFname = String.Join(' ', cueFnameParts);
|
||||
|
||||
// open file ..
|
||||
string binFileName = cueFname.Substring(1, cueFname.Length - 2);
|
||||
string binFileName = getFilename(cueData);
|
||||
string? folderContainingCue = Path.GetDirectoryName(cueFile);
|
||||
|
||||
if (folderContainingCue != null)
|
||||
binFileName = Path.Combine(folderContainingCue, binFileName);
|
||||
|
||||
if(!File.Exists(binFileName))
|
||||
binFileName = Path.ChangeExtension(cueFile, ".bin");
|
||||
|
||||
if (!File.Exists(binFileName)) throw new FileNotFoundException("unable to find bin file.");
|
||||
|
||||
curTrack = new CueTrack(binFileName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -26,8 +26,8 @@ namespace GameBuilder.Pops
|
|||
this.disc = disc;
|
||||
this.cue = new CueReader(disc.CueFile);
|
||||
|
||||
this.IsoHeader = new MemoryStream();
|
||||
this.CompressedIso = new MemoryStream();
|
||||
this.IsoHeader = new BuildStream();
|
||||
this.CompressedIso = new BuildStream();
|
||||
|
||||
this.isoHeaderUtil = new StreamUtil(IsoHeader);
|
||||
this.atrac3Encoder = encoder;
|
||||
|
@ -189,9 +189,9 @@ namespace GameBuilder.Pops
|
|||
|
||||
writeCDAEntry(Convert.ToInt32(CompressedIso.Position), atracData.Length, key);
|
||||
|
||||
using (MemoryStream atracStream = new MemoryStream(atracData))
|
||||
using (BuildStream atracStream = new BuildStream(atracData))
|
||||
{
|
||||
using (MemoryStream encryptedAtracStream = new MemoryStream())
|
||||
using (BuildStream encryptedAtracStream = new BuildStream())
|
||||
{
|
||||
AtracCrypto.ScrambleAtracData(atracStream, encryptedAtracStream, key);
|
||||
encryptedAtracStream.Seek(0x00, SeekOrigin.Begin);
|
||||
|
@ -241,8 +241,8 @@ namespace GameBuilder.Pops
|
|||
private CueReader cue;
|
||||
private PopsImg srcImg;
|
||||
|
||||
public MemoryStream IsoHeader;
|
||||
public MemoryStream CompressedIso;
|
||||
public BuildStream IsoHeader;
|
||||
public BuildStream CompressedIso;
|
||||
|
||||
private StreamUtil isoHeaderUtil;
|
||||
private IAtracEncoderBase atrac3Encoder;
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace GameBuilder.Pops.LibCrypt
|
|||
{
|
||||
public static byte[] CreateSubchannelDat(int magicWord)
|
||||
{
|
||||
using(MemoryStream subChannels = new MemoryStream())
|
||||
using(BuildStream subChannels = new BuildStream())
|
||||
{
|
||||
StreamUtil subChannelsUtil = new StreamUtil(subChannels);
|
||||
// this header seems to mark the start of the sub channel data.
|
||||
|
|
|
@ -17,13 +17,16 @@ namespace GameBuilder.Pops
|
|||
|
||||
public PopsImg(NpDrmInfo versionKey) : base(versionKey)
|
||||
{
|
||||
simple = new MemoryStream();
|
||||
simple = new BuildStream();
|
||||
simpleUtil = new StreamUtil(simple);
|
||||
|
||||
this.StartDat = NpDrmPsar.CreateStartDat(Resources.STARTDATPOPS);
|
||||
this.createSimpleDat();
|
||||
this.SimplePgd = CreatePgd(simple.ToArray());
|
||||
|
||||
this.EbootElf = Resources.DATAPSPSD;
|
||||
this.ConfigBin = Resources.DATAPSPSDCFG;
|
||||
this.PatchEboot = true;
|
||||
}
|
||||
internal void createSimpleDat()
|
||||
{
|
||||
|
@ -55,8 +58,10 @@ namespace GameBuilder.Pops
|
|||
{
|
||||
Span<byte> loaderEnc = new byte[0x9B13];
|
||||
|
||||
byte[] dataPspElf = Resources.DATAPSPSD;
|
||||
//byte[] dataPspElf = Resources.DATAPSPSD;
|
||||
|
||||
if (this.PatchEboot)
|
||||
{
|
||||
// calculate size low and high part ..
|
||||
uint szLow = Convert.ToUInt32(Psar.Length) >> 16;
|
||||
uint szHigh = Convert.ToUInt32(Psar.Length) & 0xFFFF;
|
||||
|
@ -66,16 +71,28 @@ namespace GameBuilder.Pops
|
|||
byte[] highBits = BitConverter.GetBytes(Convert.ToUInt16(szHigh)).ToArray();
|
||||
|
||||
// overwrite data.psar size check ..
|
||||
Array.ConstrainedCopy(lowBits, 0, dataPspElf, 0x68C, 0x2);
|
||||
Array.ConstrainedCopy(highBits, 0, dataPspElf, 0x694, 0x2);
|
||||
Array.ConstrainedCopy(lowBits, 0, this.EbootElf, 0x68C, 0x2);
|
||||
Array.ConstrainedCopy(highBits, 0, this.EbootElf, 0x694, 0x2);
|
||||
}
|
||||
|
||||
SceMesgLed.Encrypt(loaderEnc, dataPspElf, 0x0DAA06F0, SceExecFileDecryptMode.DECRYPT_MODE_POPS_EXEC, DrmInfo.VersionKey, DrmInfo.ContentId, Resources.DATAPSPSDCFG);
|
||||
SceMesgLed.Encrypt(
|
||||
loaderEnc,
|
||||
this.EbootElf,
|
||||
0x0DAA06F0,
|
||||
SceExecFileDecryptMode.DECRYPT_MODE_POPS_EXEC,
|
||||
DrmInfo.VersionKey,
|
||||
DrmInfo.ContentId,
|
||||
this.ConfigBin);
|
||||
return loaderEnc.ToArray();
|
||||
}
|
||||
|
||||
private MemoryStream simple;
|
||||
private BuildStream simple;
|
||||
private StreamUtil simpleUtil;
|
||||
|
||||
public byte[] EbootElf;
|
||||
public byte[] ConfigBin;
|
||||
public bool PatchEboot;
|
||||
|
||||
public byte[] StartDat;
|
||||
public byte[] SimplePgd;
|
||||
|
||||
|
|
|
@ -50,10 +50,10 @@ namespace GameBuilder.Pops
|
|||
}
|
||||
|
||||
|
||||
isoMap = new MemoryStream();
|
||||
isoMap = new BuildStream();
|
||||
isoMapUtil = new StreamUtil(isoMap);
|
||||
|
||||
isoPart = new MemoryStream();
|
||||
isoPart = new BuildStream();
|
||||
isoPartUtil = new StreamUtil(isoPart);
|
||||
|
||||
|
||||
|
@ -174,10 +174,10 @@ namespace GameBuilder.Pops
|
|||
private PSInfo[] discs;
|
||||
private DiscCompressor[] compressors;
|
||||
|
||||
private MemoryStream isoPart;
|
||||
private BuildStream isoPart;
|
||||
private StreamUtil isoPartUtil;
|
||||
|
||||
private MemoryStream isoMap;
|
||||
private BuildStream isoMap;
|
||||
private StreamUtil isoMapUtil;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,19 +17,19 @@ namespace GameBuilder.Psp
|
|||
{
|
||||
DrmInfo = npDrmInfo;
|
||||
|
||||
Psar = new MemoryStream();
|
||||
Psar = new BuildStream();
|
||||
psarUtil = new StreamUtil(Psar);
|
||||
|
||||
}
|
||||
|
||||
public NpDrmInfo DrmInfo;
|
||||
public MemoryStream Psar;
|
||||
public BuildStream Psar;
|
||||
internal StreamUtil psarUtil;
|
||||
public abstract void CreatePsar();
|
||||
public abstract byte[] GenerateDataPsp();
|
||||
public static byte[] CreateStartDat(byte[] image)
|
||||
{
|
||||
using(MemoryStream startDatStream = new MemoryStream())
|
||||
using(BuildStream startDatStream = new BuildStream())
|
||||
{
|
||||
StreamUtil startDatUtil = new StreamUtil(startDatStream);
|
||||
|
||||
|
|
|
@ -21,16 +21,16 @@ namespace GameBuilder.Psp
|
|||
{
|
||||
this.compress = compress;
|
||||
|
||||
this.npHdr = new MemoryStream();
|
||||
this.npHdr = new BuildStream();
|
||||
this.npHdrUtil = new StreamUtil(npHdr);
|
||||
|
||||
this.npHdrBody = new MemoryStream();
|
||||
this.npHdrBody = new BuildStream();
|
||||
this.npHdrBodyUtil = new StreamUtil(npHdrBody);
|
||||
|
||||
this.npTbl = new MemoryStream();
|
||||
this.npTbl = new BuildStream();
|
||||
this.npTblUtil = new StreamUtil(npTbl);
|
||||
|
||||
this.isoData = new MemoryStream();
|
||||
this.isoData = new BuildStream();
|
||||
this.isoDataUtil = new StreamUtil(isoData);
|
||||
|
||||
this.headerKey = Rng.RandomBytes(0x10);
|
||||
|
@ -43,7 +43,7 @@ namespace GameBuilder.Psp
|
|||
public void PatchSfo()
|
||||
{
|
||||
Sfo sfoKeys = Sfo.ReadSfo(umdImage.DataFiles["PARAM.SFO"]);
|
||||
if ((sfoKeys["CATEGORY"] as String) == "UG") // "UMD Game"
|
||||
//if ((sfoKeys["CATEGORY"] as String) == "UG") // "UMD Game"
|
||||
sfoKeys["CATEGORY"] = "EG"; // set it to "Eboot Game"
|
||||
umdImage.DataFiles["PARAM.SFO"] = sfoKeys.WriteSfo();
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ namespace GameBuilder.Psp
|
|||
public override byte[] GenerateDataPsp()
|
||||
{
|
||||
byte[] startDat = CreateStartDat(umdImage.Minis ? Resources.STARTDATMINIS : Resources.STARTDATPSP);
|
||||
using (MemoryStream dataPsp = new MemoryStream())
|
||||
using (BuildStream dataPsp = new BuildStream())
|
||||
{
|
||||
StreamUtil dataPspUtil = new StreamUtil(dataPsp);
|
||||
byte[] signature = signParamSfo(umdImage.DataFiles["PARAM.SFO"]);
|
||||
|
@ -288,16 +288,16 @@ namespace GameBuilder.Psp
|
|||
private byte[] dataKey;
|
||||
|
||||
|
||||
private MemoryStream npHdr;
|
||||
private BuildStream npHdr;
|
||||
private StreamUtil npHdrUtil;
|
||||
|
||||
private MemoryStream npHdrBody;
|
||||
private BuildStream npHdrBody;
|
||||
private StreamUtil npHdrBodyUtil;
|
||||
|
||||
private MemoryStream isoData;
|
||||
private BuildStream isoData;
|
||||
private StreamUtil isoDataUtil;
|
||||
|
||||
private MemoryStream npTbl;
|
||||
private BuildStream npTbl;
|
||||
private StreamUtil npTblUtil;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace GameBuilder.Psp
|
|||
private byte[]? snd0At3;
|
||||
private NpDrmPsar psar;
|
||||
private short pbpVersion;
|
||||
private MemoryStream pbpStream;
|
||||
private BuildStream pbpStream;
|
||||
|
||||
public PbpBuilder(byte[] paramSfo, byte[] icon0Png, byte[]? icon1Pmf,
|
||||
byte[]? pic0Png, byte[]? pic1Png, byte[]? snd0At3,
|
||||
|
@ -33,11 +33,11 @@ namespace GameBuilder.Psp
|
|||
this.psar = dataPsar;
|
||||
this.pbpVersion = version;
|
||||
|
||||
pbpStream = new MemoryStream();
|
||||
pbpStream = new BuildStream();
|
||||
psar.RegisterCallback(onProgress);
|
||||
}
|
||||
|
||||
public MemoryStream PbpStream
|
||||
public BuildStream PbpStream
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -12,12 +12,12 @@ namespace GameBuilder.Psp
|
|||
{
|
||||
private string[] filesList = new string[]
|
||||
{
|
||||
"PSP_GAME\\ICON0.PNG",
|
||||
"PSP_GAME\\ICON1.PMF",
|
||||
"PSP_GAME\\PARAM.SFO",
|
||||
"PSP_GAME\\PIC0.PNG",
|
||||
"PSP_GAME\\PIC1.PNG",
|
||||
"PSP_GAME\\SND0.AT3"
|
||||
Path.Combine("PSP_GAME","ICON0.PNG"),
|
||||
Path.Combine("PSP_GAME","ICON1.PMF"),
|
||||
Path.Combine("PSP_GAME","PARAM.SFO"),
|
||||
Path.Combine("PSP_GAME","PIC0.PNG"),
|
||||
Path.Combine("PSP_GAME","PIC1.PNG"),
|
||||
Path.Combine("PSP_GAME","SND0.AT3")
|
||||
};
|
||||
|
||||
public Dictionary<string, byte[]?> DataFiles = new Dictionary<string, byte[]?>();
|
||||
|
@ -27,12 +27,12 @@ namespace GameBuilder.Psp
|
|||
this.IsoStream = File.OpenRead(isoFile);
|
||||
using (CDReader cdReader = new CDReader(this.IsoStream, true, true))
|
||||
{
|
||||
foreach (string file in filesList)
|
||||
foreach (string file in this.filesList)
|
||||
{
|
||||
string fname = Path.GetFileName(file).ToUpperInvariant();
|
||||
if (cdReader.FileExists(file))
|
||||
if (cdReader.FileExists(file.Replace('/', '\\')))
|
||||
{
|
||||
using (SparseStream s = cdReader.OpenFile(file, FileMode.Open))
|
||||
using (SparseStream s = cdReader.OpenFile(file.Replace('/', '\\'), FileMode.Open))
|
||||
{
|
||||
byte[] data = new byte[s.Length];
|
||||
|
||||
|
@ -48,11 +48,14 @@ namespace GameBuilder.Psp
|
|||
}
|
||||
}
|
||||
|
||||
byte[]? paramFile = DataFiles["PARAM.SFO"];
|
||||
if (paramFile is null) throw new Exception("ISO contains no PARAM.SFO file, so this is not a valid PSP game.");
|
||||
|
||||
if (DataFiles["PARAM.SFO"] is null) throw new Exception("ISO contains no PARAM.SFO file, so this is not a valid PSP game.");
|
||||
Sfo sfo = Sfo.ReadSfo(paramFile);
|
||||
string? discId = sfo["DISC_ID"] as String;
|
||||
if (discId is null) throw new Exception("PARAM.SFO does not contain \"DISC_ID\"");
|
||||
|
||||
Sfo sfo = Sfo.ReadSfo(DataFiles["PARAM.SFO"]);
|
||||
this.DiscId = sfo["DISC_ID"] as String;
|
||||
this.DiscId = discId;
|
||||
|
||||
// check minis
|
||||
if (sfo["ATTRIBUTE"] is UInt32)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder
|
||||
{
|
||||
public enum StreamType : uint
|
||||
{
|
||||
TYPE_MEMORY_STREAM,
|
||||
TYPE_FILE_STREAM
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -117,6 +117,10 @@ namespace Li.Utilities
|
|||
{
|
||||
WriteBytesWithPadding(Encoding.UTF8.GetBytes(str), b, len);
|
||||
}
|
||||
public void WriteUInt64(UInt64 v)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(v));
|
||||
}
|
||||
public void WriteInt64(Int64 v)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(v));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using GameBuilder.Pops;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -30,7 +31,7 @@ namespace LibChovy.Art
|
|||
using (Image psnBorder = Image.Load(Resources.ICON0))
|
||||
{
|
||||
|
||||
coverImage.Mutate(x => x.Crop(new Rectangle(80, 0, coverImage.Width - 80, coverImage.Height)));
|
||||
//coverImage.Mutate(x => x.Crop(new Rectangle(80, 0, coverImage.Width - 80, coverImage.Height)));
|
||||
coverImage.Mutate(x => x.Resize(58, 58));
|
||||
psnBorder.Mutate(x => x.DrawImage(coverImage, new Point(13, 11), 1.0f));
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using GameBuilder.Pops;
|
||||
using GameBuilder;
|
||||
using GameBuilder.Pops;
|
||||
using GameBuilder.Psp;
|
||||
using Li.Progress;
|
||||
using PspCrypto;
|
||||
|
@ -62,6 +63,17 @@ namespace LibChovy
|
|||
else
|
||||
img = new PsIsoImg(parameters.DrmInfo, parameters.FirstDisc);
|
||||
|
||||
// apply eboot elf overrides
|
||||
if(parameters.EbootElfOverride is not null)
|
||||
{
|
||||
img.EbootElf = parameters.EbootElfOverride;
|
||||
img.PatchEboot = false;
|
||||
}
|
||||
if (parameters.ConfigBinOverride is not null)
|
||||
{
|
||||
img.ConfigBin = parameters.ConfigBinOverride;
|
||||
}
|
||||
|
||||
using (PbpBuilder pbpBuilder = new PbpBuilder(sfo, parameters.Icon0, null, parameters.Pic0, parameters.Pic1, null, img, 0))
|
||||
{
|
||||
pbpBuilder.RegisterCallback(onProgress);
|
||||
|
@ -138,6 +150,8 @@ namespace LibChovy
|
|||
|
||||
SceNpDrm.Aid = parameters.DrmRif.AccountId;
|
||||
|
||||
BuildStream.BuildUsingStreamType = parameters.BuildStreamType;
|
||||
|
||||
if (!Directory.Exists(parameters.OutputFolder))
|
||||
Directory.CreateDirectory(parameters.OutputFolder);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using GameBuilder.Psp;
|
||||
using GameBuilder;
|
||||
using GameBuilder.Psp;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -19,6 +20,7 @@ namespace LibChovy
|
|||
this.Account = new Account(DrmRif.AccountId);
|
||||
this.CreatePsvImg = true;
|
||||
this.FirmwareVersion = 0x3600000;
|
||||
this.BuildStreamType = StreamType.TYPE_MEMORY_STREAM;
|
||||
}
|
||||
|
||||
public int FirmwareVersion;
|
||||
|
@ -28,6 +30,7 @@ namespace LibChovy
|
|||
public Account Account;
|
||||
public ChovyTypes Type;
|
||||
|
||||
public StreamType BuildStreamType;
|
||||
|
||||
protected string? outputFolderOverride;
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
using DiscUtils.Streams;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LiLib
|
||||
{
|
||||
public class ChovyStream : Stream
|
||||
{
|
||||
private Stream underylingStream;
|
||||
|
||||
public ChovyStream()
|
||||
{
|
||||
underylingStream = new MemoryStream();
|
||||
}
|
||||
|
||||
public override bool CanRead {
|
||||
get {
|
||||
return underylingStream.CanRead;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get {
|
||||
return underylingStream.CanSeek;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get {
|
||||
return underylingStream.CanWrite;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get {
|
||||
return underylingStream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get {
|
||||
return underylingStream.Position;
|
||||
}
|
||||
set {
|
||||
underylingStream.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
underylingStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return underylingStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return underylingStream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
underylingStream.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
underylingStream.Write(buffer, offset, count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace LibChovy
|
|||
Type = ChovyTypes.POPS;
|
||||
discList = new List<PSInfo>();
|
||||
|
||||
EbootElfOverride = null;
|
||||
ConfigBinOverride = null;
|
||||
|
||||
discIdOverride = null;
|
||||
nameOverride = null;
|
||||
libCryptMethod = LibCryptMethod.METHOD_MAGIC_WORD;
|
||||
|
@ -32,6 +35,10 @@ namespace LibChovy
|
|||
private byte[]? pic1;
|
||||
private byte[]? icon0;
|
||||
|
||||
|
||||
public byte[]? EbootElfOverride;
|
||||
public byte[]? ConfigBinOverride;
|
||||
|
||||
public PSInfo FirstDisc
|
||||
{
|
||||
get
|
||||
|
|
|
@ -137,3 +137,17 @@ EP9000-UCES01242_00-PRESELLADDONPCK0 FE1E0A3B419BB9376D084ABEC54A526B DBD40050D8
|
|||
EP9000-UCES01242_00-PRESELLADDONPCK1 45331A2B5F214CD4E1297227126FAE95 FC1310D9604F5DC4FFF1015299A33524 A46821B0D75A1EA5932A9C6E6CC41E9B 70C67F9198F5105DFE70AA867679E0D3
|
||||
EP9000-UCES01242_00-PRESELLADDONPCK3 3C67064205AF3B6F5516E1008F7E9578 3DA0A4525880F6E65D921B406291D0E0 FDB5E4B9E8FE2EBED8BE487F8B585ED9 C07F639AC4C4E5E3E3DED4054F600514
|
||||
EP9000-UCES01242_00-PRESELLADDONPCK2 211625C7ACF3AD87FB80C088B5A816D0 731870DDA5D2B6A454FC32B196B39BB4 034B72CB73F41ECE183E17C5F1F5DB2F 01BDE1B45251E03597DE2D00F745E0E0
|
||||
EP0001-NPEH00029_00-GPCASSASSINPGO02 3256531B6287569F75A12C24DB1D92F5 779E4C9FA20A2DC30DBBFDC05B6F8CE9 0E446F48989AF17569671B0BC24EE951 CBFD89B5ED02344EC13485B31E32DAB1
|
||||
EP0006-NPEW00073_00-TPCFIFA11P000001 266993E225B9FE02F6784CF706624989 F19D7EDF0BDC5889A96DACB9B8D1AC68 C12E67459716BACCC208707B65793E1D 5C2104AB3DDB9974E444259EA0C75C2A
|
||||
EP1004-ULES00502_00-GPCGRANDTH000001 0E39CF82632FFF40CB6431ED3D612C55 80C952D1EAE9B0486080B9A34E0F7C26 FD1233140909948C810391716D4730C9 9A1B891F7885430FBF0E2AD3B1AA15EE
|
||||
EP1063-NPEH00101_00-PRAM001122334455 30CDDC33A4E18D8C9335278B7E05BB9B 4A1FBE67782A0324E4C7756F3854FE2B 60C5698A260CD64F8EF4ABFC936A354F D46F9CFBC83E2BCAE3C0AEB44D678756
|
||||
EP1063-NPEH00101_00-TICKET0011223344 891C6358BCD5FA5822125170C9CFDC88 67128C1321601EB91F7FCF0D643A5A83 C0713C15C91ABF06278CC0A9437F1F27 53FAB2836B5DC5C89A2CC9D68CE5C23E
|
||||
EP4293-ULES01515_00-GBPSPGAMERG00100 2CD73C4EFC809558543F1B3E3C272AB9 64794493FD2B4B960FB73AD6B1E140F7 766898B4E6BD91A138C242B4D56B1EE1 E849705F7C20FA3E4A963A01A632B8AA
|
||||
EP9000-NPEG90013_00-DPCRESISTA000001 D9621D80C5BEF35B42DC2A18E8C1C1F2 D27AC3D28A9D564F8EE713B1C485C1B7 9BBB0AD3A6BDA78720ADBC73E30018BD 4EEE59B99F8DD06D97DFF7E196B317C0
|
||||
EP9000-NPEG90019_00-LBPPSPEPSN000001 C0F7AD7D7012202CF27BBE670265BF05 1DCF8692689FB9CC0E010DE98EF77C23 8957E078A33C249D6CFEBF4A69CD21EE 6ADCB170B8A861E2035BAA20CB5BAA2C
|
||||
EP9000-NPEW00068_00-TPCPSPGOPR000001 C3602E7EE9CA1B5D4600C5AA54BB1055 B53C53352F887C2DA84E5BDE29EB72AF 8CFA5E61BE013AFCFE418126CEF4D809 36644FDB1346637D6AF6C21426692FB8
|
||||
EP9000-UCED90042_00-DPCSOCOMFTDEMO01 47D6208DF789C4ECD86692CF4D60A322 ECA7BAEC11B35B8F54280FE0D389B3B6 78DA407B23310875D52648802F7E4974 1878AC0652D24B8AEFB286358D2B5E60
|
||||
EP9000-UCES00422_00-RIDGERACER2DEMO1 D5041BB4CBFBDFD6470F9F9EE6FE5A12 8A9833DB42B4848FEA6BF46E0CCCBB6D F09D093506D205CAE121D641C0AAB354 33B9BB2EE725BF8AD6AED826447C6BE9
|
||||
EP9000-UCES00694_00-PFXTRMJUSTPSPGO2 0A4368759887952E157998EA5EA27396 71539E955A231AA6AB7044DA6E3D80AD FCCFB57EA5C15E1E5554811ECC7203E3 3041033FCD90D2ABA50545F6227410EB
|
||||
EP9000-UCES01264_00-LBPPSPEFULL00001 297DBC7870E72EF195D85611A10B94E7 A9F0F0D181C264D15CB3AFC553EB63A7 0D905696883327C8F4CE4DC45B185FB8 900132071EB7175615C1CA822C804BA0
|
||||
EP9001-NPEW00051_00-TPCGRANTUR000001 FEA1848910E05C9D45C9FBFA8863C1BE DE374F786E6CBF4E057B1C9EB64B3124 D50C141C8A7B0B840903F60A3796FB5B A346DCD09D173B36E524B29D776066C3
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace LibChovy.VersionKey
|
|||
catch { return null; }
|
||||
}
|
||||
|
||||
public static NpDrmInfo? GetKeyFromGamePsvimg(string gameBackupFolder, string accountId)
|
||||
public static NpDrmInfo? GetKeyFromGamePsvimg(string gameBackupFolder, string accountId, int keyIndex)
|
||||
{
|
||||
string gamePsvimgFile = Path.Combine(gameBackupFolder, "game", "game.psvimg");
|
||||
if (!File.Exists(gamePsvimgFile)) return null;
|
||||
|
@ -36,7 +36,7 @@ namespace LibChovy.VersionKey
|
|||
using (PSVIMGFileStream? pbp = GetFileFromPsvImg(gamePsvimgFile, "/EBOOT.PBP", cmaKey))
|
||||
{
|
||||
if (pbp is null) return null;
|
||||
return EbootPbpMethod.GetVersionKey(pbp);
|
||||
return EbootPbpMethod.GetVersionKey(pbp, keyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace LibChovy.VersionKey
|
|||
AMCTRL.bbmac_getkey(mkey, bbmac, versionKey);
|
||||
return versionKey;
|
||||
}
|
||||
public static NpDrmInfo GetVersionKey(Stream ebootStream)
|
||||
public static NpDrmInfo GetVersionKey(Stream ebootStream, int keyIndex)
|
||||
{
|
||||
using (ebootStream)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace LibChovy.VersionKey
|
|||
switch (psarMagic)
|
||||
{
|
||||
case "NPUMDIMG":
|
||||
int keyType = ebootUtil.ReadInt32();
|
||||
int orginalKeyIndex = ebootUtil.ReadInt32();
|
||||
string contentId = ebootUtil.ReadStringAt(dataPsarLocation + 0x10);
|
||||
|
||||
byte[] npUmdHdr = ebootUtil.ReadBytesAt(dataPsarLocation, 0xC0);
|
||||
|
@ -47,24 +47,27 @@ namespace LibChovy.VersionKey
|
|||
|
||||
byte[] versionkey = getKey(npUmdHeaderHash, npUmdHdr);
|
||||
|
||||
return new NpDrmInfo(versionkey, contentId, keyType);
|
||||
SceNpDrm.sceNpDrmTransformVersionKey(versionkey, orginalKeyIndex, keyIndex);
|
||||
return new NpDrmInfo(versionkey, contentId, keyIndex);
|
||||
case "PSISOIMG":
|
||||
using (DNASStream dnas = new DNASStream(ebootStream, dataPsarLocation + 0x400))
|
||||
{
|
||||
contentId = ebootUtil.ReadStringAt(dataPspLocation + 0x560);
|
||||
keyType = dnas.KeyIndex;
|
||||
orginalKeyIndex = dnas.KeyIndex;
|
||||
versionkey = dnas.VersionKey;
|
||||
|
||||
return new NpDrmInfo(versionkey, contentId, keyType);
|
||||
SceNpDrm.sceNpDrmTransformVersionKey(versionkey, orginalKeyIndex, keyIndex);
|
||||
return new NpDrmInfo(versionkey, contentId, keyIndex);
|
||||
}
|
||||
case "PSTITLEI":
|
||||
using (DNASStream dnas = new DNASStream(ebootStream, dataPsarLocation + 0x200))
|
||||
{
|
||||
contentId = ebootUtil.ReadStringAt(dataPspLocation + 0x560);
|
||||
keyType = dnas.KeyIndex;
|
||||
orginalKeyIndex = dnas.KeyIndex;
|
||||
versionkey = dnas.VersionKey;
|
||||
|
||||
return new NpDrmInfo(versionkey, contentId, keyType);
|
||||
SceNpDrm.sceNpDrmTransformVersionKey(versionkey, orginalKeyIndex, keyIndex);
|
||||
return new NpDrmInfo(versionkey, contentId, keyIndex);
|
||||
}
|
||||
default:
|
||||
throw new Exception("Cannot obtain versionkey from this EBOOT.PBP (magic:" + psarMagic + ")");
|
||||
|
|
BIN
Methods.png
BIN
Methods.png
Binary file not shown.
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 96 KiB |
|
@ -2,12 +2,12 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.1.0" />
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -6,10 +6,10 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\net6.0\publish\win-x64\</PublishDir>
|
||||
<PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
|
|
|
@ -197,6 +197,7 @@ namespace PspCrypto
|
|||
var encData = encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
|
||||
encData.AsSpan().CopyTo(oubput);
|
||||
}
|
||||
|
||||
#if false
|
||||
public static byte[] AesDecrypt(Aes aes, byte[] data, int offset, int length)
|
||||
{
|
||||
|
|
|
@ -1080,7 +1080,7 @@ namespace PspCrypto
|
|||
|
||||
unsafe
|
||||
{
|
||||
var ecdsa = ECDsaHelper.Create(curve, sig.public_key.x, sig.public_key.y);
|
||||
ECDsa ecdsa = ECDsaHelper.Create(curve, sig.public_key.x, sig.public_key.y);
|
||||
|
||||
if (ecdsa.VerifyHash(sig.message_hash, sig.signature.sig))
|
||||
{
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />
|
||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -3,6 +3,7 @@ using System;
|
|||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
@ -433,6 +434,14 @@ namespace PspCrypto
|
|||
}
|
||||
|
||||
}
|
||||
public static int sceNpDrmTransformVersionKey(Span<byte> versionKey, int srcKeyType, int dstKeyType)
|
||||
{
|
||||
// reverse the previous "GenVersionKey" step ..
|
||||
int ret = ReverseGenVersionKey(versionKey, srcKeyType);
|
||||
if (ret >= 0)
|
||||
ret = GenVersionKey(versionKey, dstKeyType); // generate a new version key of this type
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int sceNpDrmGetIDps(Span<byte> idps)
|
||||
{
|
||||
|
@ -444,7 +453,7 @@ namespace PspCrypto
|
|||
return -0x7faaf6ff;
|
||||
}
|
||||
|
||||
private static int GetActKey(Span<byte> key, ReadOnlySpan<byte> keyTable, int count)
|
||||
public static int GetActKey(Span<byte> key, ReadOnlySpan<byte> keyTable, int count)
|
||||
{
|
||||
Span<byte> idps = stackalloc byte[16];
|
||||
Span<byte> decKey = stackalloc byte[16];
|
||||
|
@ -525,6 +534,22 @@ namespace PspCrypto
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private static int ReverseGenVersionKey(Span<byte> versionkey, int type)
|
||||
{
|
||||
type &= 0xffffff;
|
||||
int ret = 0;
|
||||
if (type != 0)
|
||||
{
|
||||
ret = unchecked((int)0x80550901);
|
||||
if (type < 4)
|
||||
{
|
||||
ret = AesHelper.AesDecrypt(versionkey, versionkey, KeyVault.drmVersionKeyKey.AsSpan().Slice(type * 0x10, 0x10));
|
||||
ret = ret == 16 ? 0 : unchecked((int)0x80550902);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private static int GenVersionKey(Span<byte> versionKey, int type)
|
||||
{
|
||||
type &= 0xffffff;
|
||||
|
|
107
README.md
107
README.md
|
@ -1,65 +1,83 @@
|
|||
#ChovyProject v2
|
||||
Now with PS1 Support !
|
||||
|
||||
\- chovy-sign is an application to allow you to convert PSP and PS1 ISO's to be playable on unmodified PSVita's
|
||||
**chovy-sign is an application to allow you to convert PSP and PS1 ISO's to be playable on unmodified PSVita***
|
||||
|
||||
Setups:
|
||||
You need a valid (offical) PSP or PS1 license,
|
||||
You need an (offical) PSP or PS1 license;
|
||||
|
||||
i recommend getting; Petz Saddle Club, LocoRoco Midnight Carnival, or Ape Quest Starter Pack
|
||||
atleast one of these are free in *most* regions;
|
||||
because atleast one of these are free in *most* regions;
|
||||
|
||||
however failing that, you can also use a PSP DLC license-
|
||||
|
||||
-- if you don't have a hacked PSVita:
|
||||
Note: If the game you are using to do this with any games besides PETZ SADDLE CLUB, LOCOROCO MIDNIGHT CARNIVAL or APE QUEST STARTER PACK;
|
||||
you will be limited to the same game type as the license is for,
|
||||
i.e a PS1 game will only be usable to create a PS1 game,
|
||||
and a PSP game will only be usable to create a PSP game
|
||||
(this is different' if you use the henkaku method)
|
||||
----
|
||||
**-- If you don't have a modded PSVita:**
|
||||
|
||||
Copy the game to your PC using Content Manager,
|
||||
open chovy-sign2 and click the "Get Keys" button
|
||||
-- if you are using "APE QUEST, LOCOROCO MIDNIGHT CARNIVAL, or PETZ SADDLE CLUB, and want to make a PS1 game select "KEYS.TXT" instead-)
|
||||
select "EBOOT.PBP" method, click on the game
|
||||
(note: there may be some issues if you try this while having DLC for the game installed ...)
|
||||
*you will need:*
|
||||
- Any PS1 or PSP game (or demo) from the PS Store. (Petz Saddle Club, LocoRoco Midnight Carnival, etc..)
|
||||
- Ability to connect PSVita to PC Content Manager (USB or WiFi)
|
||||
|
||||
you should see the RIF and KEY fields populate, and your good to go!
|
||||
*obtaining keys:*
|
||||
- Copy an offical PS1 or PSP game to your PC using Content Manager,
|
||||
- open chovy-sign2
|
||||
- select either PSP or PS1 and click the "Get Keys" button
|
||||
- click "EBOOT.PBP method",
|
||||
- select the offical PS1 or PSP game you copied;
|
||||
- click on select "Content Manager" backup
|
||||
|
||||
-- If you have a hacked PSVita:
|
||||
note: you can still use the unhacked vita method if you would like
|
||||
(i.e if your only wanting to make PSP games, or are using PETZ SADDLE CLUB, LOCOROCO MIDNIGHT CARNIVAL or APE QUEST STARTER PACK)
|
||||
- you should see the RIF and KEY fields populate,
|
||||
|
||||
note2: bubbles created using the hacked vita method will still *work* on any unhacked vita,
|
||||
using the same PSN Account; however it requires a hacked vita to *obtain* some of the files,
|
||||
that are required for this method;
|
||||
*chovy-sign2 will remember this information for later so you only have to do this part one time;*
|
||||
|
||||
the main advantage to doing it this way is you can use any psp license to create both ps1 and psp bubbles;
|
||||
*getting psp or ps1 games:*
|
||||
- select either a PS1 BIN/CUE image or a UMD ISO image.
|
||||
- click "go"
|
||||
- once it finishes, you should be able to find the game availible to be copied over from Content Manager.
|
||||
|
||||
you will need:
|
||||
note: *there may be some issues if you try this while having DLC for the game installed .*
|
||||
|
||||
----
|
||||
**-- If you have a modded PSVita:**
|
||||
|
||||
note: *you can still use the unmodified vita method on a hacked vita; if you would like *
|
||||
|
||||
note2: *bubbles created using the hacked vita method will still *work* on any unmodified vita, *
|
||||
*using the same PSN Account; however it requires a hacked vita to *obtain* some of the files, *
|
||||
*that are required for this method;*
|
||||
|
||||
*you will need:*
|
||||
- Your ConsoleID/IDPS, Yoti has a tool to dump this availible [here](https://github.com/Yoti/psv_idpsdump/releases/)
|
||||
- Your Consoles activation data file (located at tm0:/npdrm/act.dat)
|
||||
- Any PSP/PS1 License file for your account (located at ux0:/pspemu/PSP/LICENSE/*.rif, or ux0:/bgdl/t/XXXXXX/temp.dat if you have a pending download)
|
||||
- Your Consoles activation data file (located at ``tm0:/npdrm/act.dat``)
|
||||
- Any offical PSP/PS1 License file for your account (located at ``ux0:/pspemu/PSP/LICENSE/*.rif``, or ``ux0:/bgdl/t/XXXXXX/temp.dat`` for downloads)
|
||||
*you can also use PocketStation license or a PSP DLC license*
|
||||
|
||||
YOUTUBERS: if you are planning on making a youtube tutorial on this, please note that your consoles IDPS is
|
||||
also used to identify your console on the playstation network,
|
||||
and sharing it would allow anyone to impersonate your console on the PSN!,
|
||||
do not just blindly give this out to people.
|
||||
(this would not give them access to your PSN Account however)
|
||||
note: *your IDPS is unique to your PSVita and is used to identify your console on the PSN, so do not share it with other people*
|
||||
|
||||
Open the CHOVY-SIGN2 application, under PSP click GET KEYS
|
||||
put in your IDPS into the ConsoleID/IDPS field; in hex (if you used yotis tool, its in ux0:/data/idps.txt)
|
||||
browse to your act.dat file, and rif file, and click Generate.
|
||||
this will populate the key and rif field;
|
||||
now do the same thing for the PS1 Option, using the same license and activation file as before.
|
||||
*obtaining keys:*
|
||||
- open chovy-sign2
|
||||
- select either PSP or PS1 and click the "Get Keys" button
|
||||
- select "IDPS+RIF+ACT Method",
|
||||
- copy in your IDPS
|
||||
- browse for your license rif file
|
||||
- browse for our act.dat file
|
||||
- click generate keys
|
||||
|
||||
*chovy-sign2 will remember this information for later so you only have to do this part one time;*
|
||||
|
||||
*getting psp or ps1 games:*
|
||||
- select either a PS1 BIN/CUE image or a UMD ISO image.
|
||||
- click "go"
|
||||
- once it finishes, you should be able to find the game availible to be copied over from Content Manager.
|
||||
- alternatively, you can disable the "Use CMA" option in settings, and then copy the resulting **TITLEID** folder to ``ux0:/pspemu/PSP/GAME``, then delete ``ux0:/id.dat``, and reboot to trigger an app database update.
|
||||
|
||||
a diagram explaining the 3 key obtaining methods is below:
|
||||
-----
|
||||
|
||||
so overall there are 3 methods to obtain keys,
|
||||
![image](https://silica.codes/SilicaAndPina/chovy-sign/raw/branch/master/Methods.png)
|
||||
|
||||
--
|
||||
note: *keys.txt is basically pointless now, in the bast it wasn't known how to use psp eboot to create ps1 games*
|
||||
|
||||
----
|
||||
|
||||
Credits:
|
||||
SquallATF (for "PspCrypto" and "PBPResigner", and making PS1 Game signing possible,
|
||||
|
@ -72,7 +90,6 @@ Writing the PS1 Disc Compresison algorithm, making it possible to use custom ISO
|
|||
Writing C# Implementation of PSVIMGTOOLS,
|
||||
Being transgender)
|
||||
|
||||
|
||||
dots-tb (for [chovy-gen](https://github.com/dots-tb/chovy-gen) (\_\_sce_ebootpbp signing)
|
||||
|
||||
Sony Computer Enterainment: (For at3tool)
|
||||
|
@ -82,16 +99,14 @@ yifanlu & xyz for the original [psvimgtools](https://github.com/yifanlu/psvimgto
|
|||
Mathieulh (Found psp signing keys?)
|
||||
|
||||
Motoharu (For helping dots with \_\_sce_ebootpbp)
|
||||
|
||||
Davee (For finding the PS1 Signing Key)
|
||||
|
||||
xlenore (For [PS1 Cover Art](https://github.com/xlenore/psx-covers))
|
||||
|
||||
RupertAvery (For their fork of DiscUtils to add PS1 Support)
|
||||
|
||||
|
||||
SquallATF's PBPResigner and PSPCrypto were derived from :
|
||||
xdotnano ([PSXTract](https://github.com/xdotnano/PSXtract))
|
||||
swarzesherz ([sign_np](https://github.com/swarzesherz/sign_np))
|
||||
tpunix ([kirk_engine](https://github.com/tpunix/kirk_engine))
|
||||
|
||||
xdotnano ([PSXTract](https://github.com/xdotnano/PSXtract))
|
||||
|
||||
swarzesherz ([sign_np](https://github.com/swarzesherz/sign_np))
|
||||
|
||||
tpunix ([kirk_engine](https://github.com/tpunix/kirk_engine))
|
||||
|
|
|
@ -78,6 +78,49 @@ namespace Vita.ContentManager
|
|||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "PS Vita");
|
||||
}
|
||||
|
||||
private static string getQcmaConfFile()
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "codestation", "qcma.conf");
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Preferences", "com.codestation.qcma.plist");
|
||||
else
|
||||
throw new PlatformNotSupportedException("cannot open qcma config as i dont know where it is.");
|
||||
}
|
||||
private static string? getQcmaConfigSetting(string file, string key)
|
||||
{
|
||||
if (!File.Exists(file)) return null;
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
using (TextReader confFile = File.OpenText(file))
|
||||
{
|
||||
for (string? ln = confFile.ReadLine();
|
||||
ln is not null;
|
||||
ln = confFile.ReadLine())
|
||||
{
|
||||
ln = ln.Trim();
|
||||
if (ln.StartsWith("[")) continue;
|
||||
|
||||
string[] kvp = ln.Split('=');
|
||||
if (kvp.Length < 2) continue;
|
||||
|
||||
string settingKey = kvp[0].Trim();
|
||||
string settingValue = kvp[1].Trim();
|
||||
|
||||
|
||||
if (settingKey == key)
|
||||
return settingValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
throw new PlatformNotSupportedException("TODO: Implement reading bplist file from mac os");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string? getRegistryKey(string registryPath, string keyName)
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
|
@ -115,16 +158,13 @@ namespace Vita.ContentManager
|
|||
private static string? getQcmaPSVitaFolder()
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
using(RegistryKey? qcmaKey = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma"))
|
||||
{
|
||||
return getRegistryKey(@"Software\codestation\qcma", "appsPath");
|
||||
}
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
string qcmaConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "codestation", "qcma.conf");
|
||||
// TODO: read file
|
||||
string qcmaConf = getQcmaConfFile();
|
||||
return getQcmaConfigSetting(qcmaConf, "appsPath");
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.0" />
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />
|
||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Loading…
Reference in New Issue