Compare commits
27 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 | |
Li | 36a088e256 | |
Li | de65c71d2c | |
Li | dd6707d5ef | |
Li | 6647b319a2 | |
Li | b13fa203a8 | |
SquallATF | c96b43031a | |
Li | 299b042dd9 | |
Li | 9001a461cc | |
Li | 73a6c3a0eb | |
Li | 743a2cfc13 | |
Li | 2d34072f91 |
|
@ -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-23T20:18:55.4774877Z;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>
|
|
@ -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\Windows</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -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="^ /template/ Border#NormalRectangle">
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
<Setter Property="Background" Value="#3f3f3f" />
|
||||
</Style>
|
||||
</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>
|
||||
<!-- 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="^ /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>
|
||||
</Style>
|
||||
<!-- pointerover -->
|
||||
|
||||
<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>
|
||||
<Style Selector="CheckBox:pointerover">
|
||||
<Setter Property="BorderBrush" Value="Green" />
|
||||
|
||||
<Style Selector="CheckBox:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="TextBlock.Foreground">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
<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="^ /template/ Border">
|
||||
<Setter Property="Background" Value="#3f3f3f" />
|
||||
<Setter Property="BorderBrush" Value="LightGreen" />
|
||||
</Style>
|
||||
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBox:focus /template/ TextBlock">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>LightGreen</Setter.Value>
|
||||
</Setter>
|
||||
</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>
|
||||
</Style>
|
||||
<Setter Property="Foreground" Value="Green" />
|
||||
|
||||
<Style Selector="TextBox:pointerover /template/ TextBlock">
|
||||
<Setter Property="Foreground">
|
||||
<Setter.Value>Green</Setter.Value>
|
||||
</Setter>
|
||||
</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 Selector="^ /template/ TextBlock">
|
||||
<Setter Property="Foreground" Value="Green" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ Border">
|
||||
<Setter Property="Background" Value="#1f1f1f" />
|
||||
<Setter Property="BorderBrush" Value="Green" />
|
||||
</Style>
|
||||
</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>
|
||||
|
@ -55,10 +52,12 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<UpToDateCheckInput Remove="Global\DevkitToggle.axaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Settings\ConfigPath.axaml.cs">
|
||||
<DependentUpon>ConfigPath.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Settings\ConfigToggle.axaml.cs">
|
||||
<DependentUpon>ConfigToggle.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Resource.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
OnFileChanged(new EventArgs());
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using ChovySign_GUI.Popup.Global;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static ChovySign_GUI.Popup.Global.MessageBox;
|
||||
|
||||
namespace ChovySign_GUI.Global
|
||||
{
|
||||
public partial class DevkitToggle : UserControl
|
||||
{
|
||||
private static List<DevkitToggle> instances = new List<DevkitToggle>();
|
||||
|
||||
private const string useDevkitModeConfigKey = "USE_DEVKIT_ACCOUNT_ID";
|
||||
internal bool disableEvents = false;
|
||||
private async void onDevkitModeChecked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (disableEvents) return;
|
||||
|
||||
CheckBox? checkBox = sender as CheckBox;
|
||||
if (checkBox is null) return;
|
||||
|
||||
bool? devMode = checkBox.IsChecked;
|
||||
if (devMode is null) devMode = false;
|
||||
|
||||
Window? currentWindow = this.VisualRoot as Window;
|
||||
if (currentWindow is not Window) throw new Exception("could not find current window");
|
||||
|
||||
MessageBoxResult res = await MessageBox.Show(currentWindow, "This option will force the CMA Account ID to be all 0's\nWhich is how it is on Devkit, Testkit and IDU Firmware\nEnabling this if you have a retail firmware will result in the games just *not* showing up\n\nIf you DON'T know what this means, DON'T enable this.\ndo you want to continue?", "Are you sure?", MessageBoxButtons.YesNo);
|
||||
if (res == MessageBoxResult.Yes)
|
||||
{
|
||||
IsDevkitMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsDevkitMode = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onDevkitModeUnchecked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (disableEvents) return;
|
||||
|
||||
CheckBox? checkBox = sender as CheckBox;
|
||||
if (checkBox is null) return;
|
||||
|
||||
bool? devMode = checkBox.IsChecked;
|
||||
if (devMode is null) devMode = false;
|
||||
IsDevkitMode = (bool)devMode;
|
||||
}
|
||||
|
||||
public bool IsDevkitMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.devkitCheckbox.IsChecked is null) return false;
|
||||
return (bool)this.devkitCheckbox.IsChecked;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (DevkitToggle instance in instances)
|
||||
{
|
||||
instance.disableEvents = true;
|
||||
instance.devkitCheckbox.IsChecked = value;
|
||||
instance.disableEvents = false;
|
||||
}
|
||||
|
||||
ChovyConfig.CurrentConfig.SetBool(useDevkitModeConfigKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
public DevkitToggle()
|
||||
{
|
||||
InitializeComponent();
|
||||
bool? isDevkitMode = ChovyConfig.CurrentConfig.GetBool(useDevkitModeConfigKey);
|
||||
if (isDevkitMode is null) isDevkitMode = false;
|
||||
devkitCheckbox.IsChecked = isDevkitMode;
|
||||
devkitCheckbox.Unchecked += onDevkitModeUnchecked;
|
||||
devkitCheckbox.Checked += onDevkitModeChecked;
|
||||
|
||||
instances.Add(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,10 +83,24 @@ namespace ChovySign_GUI.Global
|
|||
public FilteredTextBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.txtBox.PastingFromClipboard += onPaste;
|
||||
this.txtBox.PropertyChanged += onPropertyChanged;
|
||||
this.txtBox.AddHandler(TextInputEvent, onTxtInput, RoutingStrategies.Tunnel);
|
||||
}
|
||||
|
||||
private void onPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
TextBox? txt = sender as TextBox;
|
||||
if (txt is null) return;
|
||||
|
||||
if (e.Property.Name == "Text")
|
||||
{
|
||||
if (txt.Text is null) return;
|
||||
txt.Text = filter(txt.Text);
|
||||
|
||||
OnTextChanged(new EventArgs());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string filter(string original)
|
||||
{
|
||||
|
@ -104,36 +118,6 @@ namespace ChovySign_GUI.Global
|
|||
}
|
||||
return original;
|
||||
}
|
||||
private async Task<bool> setClipboardText(string text)
|
||||
{
|
||||
if (Application.Current is null) return false;
|
||||
if (Application.Current.Clipboard is null) return false;
|
||||
await Application.Current.Clipboard.SetTextAsync(text);
|
||||
return true;
|
||||
}
|
||||
private async Task<string> getClipboardText()
|
||||
{
|
||||
if (Application.Current is null) return "";
|
||||
if (Application.Current.Clipboard is null) return "";
|
||||
string? clipboard = await Application.Current.Clipboard.GetTextAsync();
|
||||
if (clipboard is null) return "";
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
private async void onPaste(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
TextBox? txt = sender as TextBox;
|
||||
if (txt is null) return;
|
||||
|
||||
string clipboard = getClipboardText().Result;
|
||||
clipboard = filter(clipboard);
|
||||
_ = setClipboardText(clipboard).Result;
|
||||
|
||||
// annoyingly, the text being pasted isnt actually in the textbox yet
|
||||
// and it wont trigger a textInput event when pasting; t-this really is the best can do
|
||||
await Task.Delay(100);
|
||||
OnTextChanged(new EventArgs());
|
||||
}
|
||||
|
||||
private void onTxtInput(object? sender, TextInputEventArgs e)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -52,9 +52,15 @@ namespace ChovySign_GUI.Global
|
|||
|
||||
public string[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
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;
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Ps1="clr-namespace:ChovySign_GUI.Ps1"
|
||||
xmlns:Psp="clr-namespace:ChovySign_GUI.Psp"
|
||||
mc:Ignorable="d" d:DesignWidth="850" d:DesignHeight="950"
|
||||
xmlns:Settings="clr-namespace:ChovySign_GUI.Settings"
|
||||
mc:Ignorable="d" d:DesignWidth="850" d:DesignHeight="760"
|
||||
MinHeight="760"
|
||||
x:Class="ChovySign_GUI.MainWindow"
|
||||
Title="Chovy Sign V2" Icon="/ICON.PNG">
|
||||
|
||||
|
@ -13,9 +15,12 @@
|
|||
<TabItem Header="PlayStation Portable">
|
||||
<Psp:PspTab Name="pspTab"/>
|
||||
</TabItem>
|
||||
<TabItem Header="PlayStation 1">
|
||||
<TabItem Header="PlayStation One">
|
||||
<Ps1:Ps1Tab Name="ps1Tab"/>
|
||||
</TabItem>
|
||||
<TabItem Header="Settings">
|
||||
<Settings:SettingsTab Name="settingsTab"/>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="300"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="280"
|
||||
x:Class="ChovySign_GUI.Ps1.CueSelector">
|
||||
<!-- Bin/Cue Image selector -->
|
||||
<Border Padding="5 5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="250"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="280"
|
||||
x:Class="ChovySign_GUI.Ps1.GameInfoSelector">
|
||||
<Border Padding="5 5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<Grid>
|
||||
|
@ -18,11 +18,13 @@
|
|||
<RowDefinition Height="52"/>
|
||||
<RowDefinition Height="52"/>
|
||||
<RowDefinition Height="52"/>
|
||||
<RowDefinition Height="52"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Global:LabeledTextBox HorizontalAlignment="Stretch" Name="gameTitle" Label="Title:" Watermark="The BEST PlayStation 1 Game" MaxLength="128" Grid.Row="0"/>
|
||||
<Global:BrowseButton HorizontalAlignment="Stretch" Name="iconFile" Extension="png" FileTypeName="Portable Network Graphics" Watermark="(Default)" Label="icon0.png:" Grid.Row="1"/>
|
||||
<Global:BrowseButton HorizontalAlignment="Stretch" Name="pic0File" Extension="png" FileTypeName="Portable Network Graphics" Watermark="(Default)" Label="pic0.png:" Grid.Row="2"/>
|
||||
<Global:BrowseButton HorizontalAlignment="Stretch" Name="pic1File" Extension="png" FileTypeName="Portable Network Graphics" Watermark="(Default)" Label="pic1.png:" Grid.Row="3"/>
|
||||
<Global:LabeledTextBox HorizontalAlignment="Stretch" Name="discId" AllowedChars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" Label="Disc ID:" Watermark="SLUS00001" MaxLength="9" Grid.Row="4"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
|
|
@ -19,7 +19,18 @@ namespace ChovySign_GUI.Ps1
|
|||
private byte[] iconCache;
|
||||
private byte[] pic0Cache;
|
||||
private byte[] pic1Cache;
|
||||
|
||||
public string DiscId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.discId.Text is null) return "";
|
||||
return this.discId.Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.discId.Text = value;
|
||||
}
|
||||
}
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
|
@ -84,14 +95,23 @@ namespace ChovySign_GUI.Ps1
|
|||
{
|
||||
try
|
||||
{
|
||||
DiscInfo disc = new DiscInfo(cueFile);
|
||||
PSInfo disc = new PSInfo(cueFile);
|
||||
Title = disc.DiscName;
|
||||
DiscId = disc.DiscId;
|
||||
|
||||
byte[] newCover = await Downloader.DownloadCover(disc);
|
||||
loadIcon(newCover);
|
||||
iconCache = newCover;
|
||||
if (!File.Exists(this.iconFile.FilePath))
|
||||
{
|
||||
byte[] newCover = await Downloader.DownloadCover(disc);
|
||||
loadIcon(newCover);
|
||||
iconCache = newCover;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
private async Task<byte[]?> doLoad(BrowseButton imgFile, int width, int height)
|
||||
|
@ -147,6 +167,13 @@ namespace ChovySign_GUI.Ps1
|
|||
if (TitleChanged is not null)
|
||||
TitleChanged(this, e);
|
||||
}
|
||||
public event EventHandler<EventArgs>? DiscIdChanged;
|
||||
protected virtual void OnDiscIdChanged(EventArgs e)
|
||||
{
|
||||
if (DiscIdChanged is not null)
|
||||
DiscIdChanged(this, e);
|
||||
}
|
||||
|
||||
public GameInfoSelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -161,6 +188,13 @@ namespace ChovySign_GUI.Ps1
|
|||
this.pic1File.FileChanged += onPic1Change;
|
||||
|
||||
this.gameTitle.TextChanged += onTitleChange;
|
||||
this.discId.TextChanged += onDiscIdChange;
|
||||
|
||||
}
|
||||
|
||||
private void onDiscIdChange(object? sender, EventArgs e)
|
||||
{
|
||||
OnDiscIdChanged(new EventArgs());
|
||||
}
|
||||
|
||||
private void onTitleChange(object? sender, EventArgs e)
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="40" />
|
||||
<RowDefinition Height="1.5*" />
|
||||
<RowDefinition Height="1.3*" />
|
||||
<RowDefinition Height="0.6*" />
|
||||
<RowDefinition Height="280" />
|
||||
<RowDefinition Height="280" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
|
@ -22,14 +22,13 @@
|
|||
|
||||
<Global:KeySelector Name="keySelector" KeyIndex="1" Grid.Row="0" Grid.Column="1"/>
|
||||
|
||||
<Ps1:CueSelector Name="discSelector" Grid.Row="1" Grid.Column="1"/>
|
||||
<Ps1:GameInfoSelector Name="gameInfo" Grid.Row="2" Grid.Column="1"/>
|
||||
<Ps1:CueSelector Name="discSelector" Height="280" Grid.Row="1" Grid.Column="1"/>
|
||||
<Ps1:GameInfoSelector Name="gameInfo" Height="280" Grid.Row="2" Grid.Column="1"/>
|
||||
|
||||
<Global:ProgressStatus VerticalAlignment="Center" Name="progressStatus" Grid.Row="3" Grid.Column="1"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Credits -->
|
||||
<Global:DevkitToggle Name="devkitAccount" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
|
||||
<Label Content="Li, Dots TB, SquallATF, Motoharu, Davee" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,10 +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;
|
||||
|
@ -21,6 +20,7 @@ namespace ChovySign_GUI.Ps1
|
|||
discSelector.DiscsSelected += onDiscSelected;
|
||||
keySelector.ValidStateChanged += onKeyValidityChanged;
|
||||
gameInfo.TitleChanged += onTitleChanged;
|
||||
gameInfo.DiscIdChanged += onDiscIdChanged;
|
||||
|
||||
progressStatus.BeforeStart += onProcessStarting;
|
||||
progressStatus.Finished += onProcessFinished;
|
||||
|
@ -28,13 +28,12 @@ namespace ChovySign_GUI.Ps1
|
|||
}
|
||||
|
||||
|
||||
|
||||
private async void onProcessFinished(object? sender, EventArgs e)
|
||||
{
|
||||
keySelector.IsEnabled = true;
|
||||
discSelector.IsEnabled = true;
|
||||
devkitAccount.IsEnabled = true;
|
||||
gameInfo.IsEnabled = true;
|
||||
SettingsTab.Settings.IsEnabled = true;
|
||||
|
||||
Window? currentWindow = this.VisualRoot as Window;
|
||||
if (currentWindow is not Window) throw new Exception("could not find current window");
|
||||
|
@ -47,34 +46,43 @@ namespace ChovySign_GUI.Ps1
|
|||
{
|
||||
keySelector.IsEnabled = false;
|
||||
discSelector.IsEnabled = false;
|
||||
devkitAccount.IsEnabled = false;
|
||||
gameInfo.IsEnabled = false;
|
||||
SettingsTab.Settings.IsEnabled = false;
|
||||
|
||||
if (keySelector.Rif is null) return;
|
||||
if (keySelector.VersionKey is null) return;
|
||||
|
||||
NpDrmRif rifInfo = new NpDrmRif(keySelector.Rif);
|
||||
NpDrmInfo drmInfo = new NpDrmInfo(keySelector.VersionKey, rifInfo.ContentId, keySelector.KeyIndex);
|
||||
PspParameters pspParameters = new PspParameters(drmInfo, rifInfo);
|
||||
|
||||
PopsParameters popsParameters = new PopsParameters(drmInfo, rifInfo);
|
||||
|
||||
foreach (string disc in discSelector.Discs)
|
||||
popsParameters.AddCd(disc);
|
||||
|
||||
popsParameters.Name = gameInfo.Title;
|
||||
popsParameters.Icon0 = gameInfo.Icon0;
|
||||
popsParameters.Pic0 = gameInfo.Pic0;
|
||||
popsParameters.Pic1 = gameInfo.Pic1;
|
||||
popsParameters.Name = gameInfo.Title;
|
||||
popsParameters.DiscId = gameInfo.DiscId;
|
||||
popsParameters.Icon0 = gameInfo.Icon0;
|
||||
popsParameters.Pic0 = gameInfo.Pic0;
|
||||
popsParameters.Pic1 = gameInfo.Pic1;
|
||||
|
||||
if (devkitAccount.IsDevkitMode)
|
||||
popsParameters.Account = new Account(0);
|
||||
// read settings from settings tab.
|
||||
if (SettingsTab.Settings.DevkitMode) popsParameters.Account = new Account(0);
|
||||
|
||||
popsParameters.CrackMethod = SettingsTab.Settings.LibcryptMode;
|
||||
SettingsReader.BackupsFolder = SettingsTab.Settings.CmaDirectory;
|
||||
popsParameters.CreatePsvImg = SettingsTab.Settings.PackagePsvimg;
|
||||
|
||||
progressStatus.Parameters = popsParameters;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void onDiscIdChanged(object? sender, EventArgs e)
|
||||
{
|
||||
check();
|
||||
}
|
||||
|
||||
private void onTitleChanged(object? sender, EventArgs e)
|
||||
{
|
||||
check();
|
||||
|
@ -82,7 +90,7 @@ namespace ChovySign_GUI.Ps1
|
|||
|
||||
private void check()
|
||||
{
|
||||
this.progressStatus.IsEnabled = (discSelector.AnyDiscsSelected && keySelector.IsValid && gameInfo.Title != "");
|
||||
this.progressStatus.IsEnabled = (discSelector.AnyDiscsSelected && keySelector.IsValid && gameInfo.Title != "" && gameInfo.DiscId.Length == 9);
|
||||
}
|
||||
private void onKeyValidityChanged(object? sender, EventArgs e)
|
||||
{
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
</Grid>
|
||||
|
||||
<!-- Credits -->
|
||||
<Global:DevkitToggle Name="devkitAccount" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
|
||||
<Label Content="Li, Dots TB, SquallATF, Motoharu, Davee" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using ChovySign_GUI.Popup.Global;
|
||||
using ChovySign_GUI.Settings;
|
||||
using GameBuilder.Psp;
|
||||
using LibChovy;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
using System.Media;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Vita.ContentManager;
|
||||
using static ChovySign_GUI.Popup.Global.MessageBox;
|
||||
|
@ -36,7 +38,7 @@ namespace ChovySign_GUI.Psp
|
|||
{
|
||||
keySelector.IsEnabled = true;
|
||||
isoSelector.IsEnabled = true;
|
||||
devkitAccount.IsEnabled = true;
|
||||
SettingsTab.Settings.IsEnabled = true;
|
||||
|
||||
Window? currentWindow = this.VisualRoot as Window;
|
||||
if (currentWindow is not Window) throw new Exception("could not find current window");
|
||||
|
@ -48,8 +50,9 @@ namespace ChovySign_GUI.Psp
|
|||
private void onProcessStarting(object? sender, EventArgs e)
|
||||
{
|
||||
keySelector.IsEnabled = false;
|
||||
devkitAccount.IsEnabled = false;
|
||||
isoSelector.IsEnabled = false;
|
||||
SettingsTab.Settings.IsEnabled = false;
|
||||
|
||||
if (keySelector.Rif is null) return;
|
||||
if (keySelector.VersionKey is null) return;
|
||||
|
||||
|
@ -63,8 +66,10 @@ namespace ChovySign_GUI.Psp
|
|||
pspParameters.Umd = umd;
|
||||
pspParameters.Compress = isoSelector.Compress;
|
||||
|
||||
if (devkitAccount.IsDevkitMode)
|
||||
pspParameters.Account = new Account(0);
|
||||
// read settings from settings tab.
|
||||
pspParameters.Account.Devkit = SettingsTab.Settings.DevkitMode;
|
||||
SettingsReader.BackupsFolder = SettingsTab.Settings.CmaDirectory;
|
||||
pspParameters.CreatePsvImg = SettingsTab.Settings.PackagePsvimg;
|
||||
|
||||
progressStatus.Parameters = pspParameters;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
using Avalonia.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ChovySign_GUI.Settings
|
||||
{
|
||||
public abstract class ConfigControl : UserControl
|
||||
{
|
||||
private string? configKey = null;
|
||||
public string ConfigKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (configKey is null) return "";
|
||||
return configKey;
|
||||
}
|
||||
set
|
||||
{
|
||||
configKey = value;
|
||||
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract void init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="85"
|
||||
x:Class="ChovySign_GUI.Settings.ConfigDropDown">
|
||||
<Grid>
|
||||
<Global:LabeledComboBox Name="configComboBox" Label="Label"/>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,71 @@
|
|||
using Avalonia.Controls;
|
||||
using ChovySign_GUI.Global;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
|
||||
namespace ChovySign_GUI.Settings
|
||||
{
|
||||
public partial class ConfigDropDown : ConfigControl
|
||||
{
|
||||
internal override void init()
|
||||
{
|
||||
int? cfgInt = ChovyConfig.CurrentConfig.GetInt(ConfigKey);
|
||||
if (cfgInt is null) cfgInt = 0;
|
||||
this.configComboBox.SelectedIndex = (int)cfgInt;
|
||||
}
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configComboBox.Label;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configComboBox.Label = value;
|
||||
}
|
||||
}
|
||||
public int SelectedIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configComboBox.SelectedIndex;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configComboBox.SelectedIndex = value;
|
||||
if (this.configComboBox.SelectedIndex < 0) return;
|
||||
|
||||
ChovyConfig.CurrentConfig.SetInt(ConfigKey, this.configComboBox.SelectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public string[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configComboBox.Items;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configComboBox.Items = value;
|
||||
init();
|
||||
}
|
||||
}
|
||||
public ConfigDropDown()
|
||||
{
|
||||
InitializeComponent();
|
||||
init();
|
||||
|
||||
this.configComboBox.SelectionChanged += onSelectionChange;
|
||||
}
|
||||
|
||||
private void onSelectionChange(object? sender, EventArgs e)
|
||||
{
|
||||
LabeledComboBox? comboBox = sender as LabeledComboBox;
|
||||
if (comboBox is null) return;
|
||||
if (comboBox.SelectedIndex < 0) return;
|
||||
|
||||
ChovyConfig.CurrentConfig.SetInt(ConfigKey, comboBox.SelectedIndex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="80"
|
||||
x:Class="ChovySign_GUI.Settings.ConfigPath">
|
||||
<Grid>
|
||||
<Global:BrowseButton Name="configPath" Label="Label"/>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,92 @@
|
|||
using Avalonia.Controls;
|
||||
using ChovySign_GUI.Global;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
|
||||
namespace ChovySign_GUI.Settings
|
||||
{
|
||||
public partial class ConfigPath : ConfigControl
|
||||
{
|
||||
internal override void init()
|
||||
{
|
||||
string? cfgText = ChovyConfig.CurrentConfig.GetString(ConfigKey);
|
||||
if (cfgText is null) cfgText = "";
|
||||
configPath.FilePath = cfgText;
|
||||
}
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return configPath.Label;
|
||||
}
|
||||
set
|
||||
{
|
||||
configPath.Label = value;
|
||||
}
|
||||
}
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configPath.FilePath;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configPath.FilePath = value;
|
||||
|
||||
if(configPath.ContainsFile)
|
||||
ChovyConfig.CurrentConfig.SetString(ConfigKey, this.configPath.FilePath);
|
||||
}
|
||||
}
|
||||
public bool IsDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configPath.IsDirectory;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configPath.IsDirectory = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Extension
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configPath.Extension;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configPath.Extension = value;
|
||||
}
|
||||
}
|
||||
public string FileTypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.configPath.FileTypeName;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configPath.FileTypeName = value;
|
||||
}
|
||||
}
|
||||
public ConfigPath()
|
||||
{
|
||||
InitializeComponent();
|
||||
init();
|
||||
|
||||
this.configPath.FileChanged += onFileChange;
|
||||
}
|
||||
|
||||
private void onFileChange(object? sender, EventArgs e)
|
||||
{
|
||||
BrowseButton? browseBtn = sender as BrowseButton;
|
||||
if (browseBtn is null) return;
|
||||
if (!browseBtn.ContainsFile) return;
|
||||
|
||||
ChovyConfig.CurrentConfig.SetString(ConfigKey, browseBtn.FilePath);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="80"
|
||||
x:Class="ChovySign_GUI.Settings.ConfigText">
|
||||
<Grid>
|
||||
<Global:LabeledTextBox Name="configText" Label="Label"/>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,58 @@
|
|||
using Avalonia.Controls;
|
||||
using ChovySign_GUI.Global;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
|
||||
namespace ChovySign_GUI.Settings
|
||||
{
|
||||
public partial class ConfigText : ConfigControl
|
||||
{
|
||||
internal override void init()
|
||||
{
|
||||
string? cfgText = ChovyConfig.CurrentConfig.GetString(ConfigKey);
|
||||
if (cfgText is null) cfgText = "";
|
||||
configText.Text = cfgText;
|
||||
}
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return configText.Label;
|
||||
}
|
||||
set
|
||||
{
|
||||
configText.Label = value;
|
||||
}
|
||||
}
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.configText.Text is null) return "";
|
||||
return (string)this.configText.Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.configText.Text = value;
|
||||
|
||||
ChovyConfig.CurrentConfig.SetString(ConfigKey, value);
|
||||
}
|
||||
}
|
||||
public ConfigText()
|
||||
{
|
||||
InitializeComponent();
|
||||
init();
|
||||
|
||||
this.configText.TextChanged += onTextChange;
|
||||
}
|
||||
|
||||
private void onTextChange(object? sender, EventArgs e)
|
||||
{
|
||||
LabeledTextBox? txtBox = sender as LabeledTextBox;
|
||||
if (txtBox is null) return;
|
||||
if (txtBox.Text is null) return;
|
||||
|
||||
ChovyConfig.CurrentConfig.SetString(ConfigKey, txtBox.Text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,8 +3,8 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="80"
|
||||
x:Class="ChovySign_GUI.Global.DevkitToggle">
|
||||
x:Class="ChovySign_GUI.Settings.ConfigToggle">
|
||||
<Grid>
|
||||
<CheckBox Name="devkitCheckbox" Content="I have a DevKit, TestKit or IDU Vita"/>
|
||||
<CheckBox Name="configCheckbox" Content="Label"/>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,133 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using ChovySign_GUI.Popup.Global;
|
||||
using LibChovy.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static ChovySign_GUI.Popup.Global.MessageBox;
|
||||
|
||||
namespace ChovySign_GUI.Settings
|
||||
{
|
||||
public partial class ConfigToggle : ConfigControl
|
||||
{
|
||||
|
||||
internal bool disableEvents = false;
|
||||
private string? promptMsg = null;
|
||||
private bool defaultSetting = false;
|
||||
internal override void init()
|
||||
{
|
||||
bool? isToggleChecked = ChovyConfig.CurrentConfig.GetBool(ConfigKey);
|
||||
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
|
||||
{
|
||||
get
|
||||
{
|
||||
string? content = configCheckbox.Content as string;
|
||||
if (content is null) return "";
|
||||
return content;
|
||||
}
|
||||
set
|
||||
{
|
||||
configCheckbox.Content = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Prompt
|
||||
{
|
||||
get
|
||||
{
|
||||
if (promptMsg is null) return "";
|
||||
return promptMsg;
|
||||
}
|
||||
set
|
||||
{
|
||||
promptMsg = value;
|
||||
}
|
||||
}
|
||||
private async void onToggleChecked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (disableEvents) return;
|
||||
|
||||
CheckBox? checkBox = sender as CheckBox;
|
||||
if (checkBox is null) return;
|
||||
|
||||
bool? toggled = checkBox.IsChecked;
|
||||
if (toggled is null) toggled = false;
|
||||
|
||||
if (promptMsg is not null)
|
||||
{
|
||||
Window? currentWindow = this.VisualRoot as Window;
|
||||
if (currentWindow is not Window) throw new Exception("could not find current window");
|
||||
|
||||
MessageBoxResult res = await MessageBox.Show(currentWindow, Prompt, "Are you sure?", MessageBoxButtons.YesNo);
|
||||
if (res == MessageBoxResult.Yes)
|
||||
IsToggled = true;
|
||||
else
|
||||
IsToggled = false;
|
||||
}
|
||||
else{
|
||||
IsToggled = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onToggleUnchecked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (disableEvents) return;
|
||||
|
||||
CheckBox? checkBox = sender as CheckBox;
|
||||
if (checkBox is null) return;
|
||||
|
||||
bool? toggle = checkBox.IsChecked;
|
||||
if (toggle is null) toggle = false;
|
||||
IsToggled = (bool)toggle;
|
||||
}
|
||||
|
||||
public bool IsToggled
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.configCheckbox.IsChecked is null) return false;
|
||||
return (bool)this.configCheckbox.IsChecked;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.disableEvents = true;
|
||||
this.configCheckbox.IsChecked = value;
|
||||
this.disableEvents = false;
|
||||
|
||||
ChovyConfig.CurrentConfig.SetBool(ConfigKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigToggle()
|
||||
{
|
||||
InitializeComponent();
|
||||
init();
|
||||
|
||||
configCheckbox.Unchecked += onToggleUnchecked;
|
||||
configCheckbox.Checked += onToggleChecked;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Settings="clr-namespace:ChovySign_GUI.Settings"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="ChovySign_GUI.Settings.SettingsTab">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="10*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Settings:ConfigToggle Name="devkitAccount"
|
||||
ConfigKey="USE_DEVKIT_ACCOUNT_ID"
|
||||
Label="Devkit Mode (Use 0x0000000000000000 Account ID)"
|
||||
Prompt="This option will force the CMA Account ID to be all 0's
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"
|
||||
Default="false"
|
||||
Grid.Row="0"/>
|
||||
|
||||
<Settings:ConfigToggle Name="packagePsvimg"
|
||||
ConfigKey="USE_CMA_PSVIMG"
|
||||
Label="Use Content Manager (Package to PSVIMG)"
|
||||
Default="true"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Row="1"/>
|
||||
|
||||
<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>
|
||||
|
||||
</UserControl>
|
|
@ -0,0 +1,72 @@
|
|||
using Avalonia.Controls;
|
||||
using GameBuilder.Pops.LibCrypt;
|
||||
using GameBuilder;
|
||||
using System.IO;
|
||||
using Vita.ContentManager;
|
||||
|
||||
namespace ChovySign_GUI.Settings
|
||||
{
|
||||
public partial class SettingsTab : UserControl
|
||||
{
|
||||
public static SettingsTab? Settings;
|
||||
|
||||
public StreamType BuildStreamType
|
||||
{
|
||||
get
|
||||
{
|
||||
return (StreamType) this.streamType.SelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public LibCryptMethod LibcryptMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.libCryptMode.SelectedIndex == 0) return LibCryptMethod.METHOD_MAGIC_WORD;
|
||||
else return LibCryptMethod.METHOD_SUB_CHANNEL;
|
||||
}
|
||||
}
|
||||
|
||||
public string CmaDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return cmaDirectory.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
cmaDirectory.Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DevkitMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return devkitAccount.IsToggled;
|
||||
}
|
||||
}
|
||||
public bool PackagePsvimg
|
||||
{
|
||||
get
|
||||
{
|
||||
return packagePsvimg.IsToggled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SettingsTab()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,24 +30,28 @@ namespace GameBuilder.Cue
|
|||
return totalTracks;
|
||||
}
|
||||
|
||||
public static byte BinaryDecimalConv(int i)
|
||||
public static byte BinaryDecimalToDecimal(int i)
|
||||
{
|
||||
return Convert.ToByte(Convert.ToInt32(10 * (i - i % 16) / 16 + i % 16));
|
||||
}
|
||||
public static byte DecimalToBinaryDecimal(int i)
|
||||
{
|
||||
return Convert.ToByte(Convert.ToInt32((i % 10) + 16 * ((i / 10) % 10)));
|
||||
}
|
||||
public int IdxToSectorRel(CueIndex index)
|
||||
public static int IdxToSectorRel(DiscIndex index)
|
||||
{
|
||||
int offset = (((index.Mrel * 60) + index.Srel) * 75 + index.Frel);
|
||||
return offset;
|
||||
}
|
||||
public int IdxToSector(CueIndex index)
|
||||
public static int IdxToSector(DiscIndex index)
|
||||
{
|
||||
int offset = (((index.m * 60) + index.s) * 75 + index.f);
|
||||
return offset;
|
||||
}
|
||||
|
||||
public CueIndex SectorToIdx(int sector)
|
||||
public static DiscIndex SectorToIdx(int sector, byte index=1)
|
||||
{
|
||||
CueIndex idx = new CueIndex(1);
|
||||
DiscIndex idx = new DiscIndex(index);
|
||||
|
||||
int x = sector;
|
||||
int f = sector % 75;
|
||||
|
@ -56,11 +60,6 @@ namespace GameBuilder.Cue
|
|||
int s = x % 60;
|
||||
int m = Convert.ToInt32(Math.Floor(Convert.ToDouble(x) / 60.0));
|
||||
|
||||
//idx.Mrel = Convert.ToByte(Convert.ToInt32(((sector / 75) / 60)));
|
||||
//idx.Srel = Convert.ToByte(Convert.ToInt32(((sector / 75) % 60)));
|
||||
//idx.Frel = Convert.ToByte(Convert.ToInt32(((sector % 75))));
|
||||
//idx.Sdelta = 2; // why?
|
||||
|
||||
idx.Mrel = Convert.ToInt16(m);
|
||||
idx.Srel = Convert.ToInt16(s);
|
||||
idx.Frel = Convert.ToInt16(f);
|
||||
|
@ -185,11 +184,11 @@ namespace GameBuilder.Cue
|
|||
byte[] tocA0Entry = new byte[10] { 0x41, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00 };
|
||||
|
||||
// And an A1 track (determines how many tracks there are)
|
||||
byte[] tocA1Entry = new byte[10] { 0x41, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, BinaryDecimalConv(GetTotalTracks()), 0x00, 0x00 };
|
||||
byte[] tocA1Entry = new byte[10] { 0x41, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, DecimalToBinaryDecimal(GetTotalTracks()), 0x00, 0x00 };
|
||||
|
||||
// the A2 track is a bit more complicated ..
|
||||
int totalSectors = getTotalSectorSz();
|
||||
CueIndex idx = SectorToIdx(totalSectors);
|
||||
DiscIndex idx = SectorToIdx(totalSectors);
|
||||
idx.Sdelta = 2;
|
||||
|
||||
byte[] tocA2Entry = new byte[10] { 0x41, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, idx.M, idx.S, idx.F };
|
||||
|
@ -246,7 +245,7 @@ namespace GameBuilder.Cue
|
|||
if (tracks[i] is null) continue;
|
||||
int pos = positions[tracks[i].binFileName];
|
||||
|
||||
CueIndex idx = this.SectorToIdx(pos);
|
||||
DiscIndex idx = SectorToIdx(pos);
|
||||
// pregap not included on first track
|
||||
|
||||
if (tracks[i].TrackNo == 1) tracks[i].TrackIndex[0].Sdelta = 0;
|
||||
|
@ -270,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());
|
||||
|
@ -301,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>();
|
||||
|
@ -311,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")
|
||||
{
|
||||
|
@ -351,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,12 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace GameBuilder.Cue
|
||||
{
|
||||
public class CueTrack
|
||||
public class CueTrack : DiscTrack
|
||||
{
|
||||
|
||||
public const int MODE2_SECTOR_SZ = 2352;
|
||||
public const int CDDA_SECTOR_SZ = 2352;
|
||||
|
||||
public TrackType TrackType;
|
||||
public byte TrackNo;
|
||||
public CueIndex[] TrackIndex;
|
||||
|
||||
public int TrackLength;
|
||||
public int SectorSz
|
||||
{
|
||||
|
@ -30,36 +26,14 @@ namespace GameBuilder.Cue
|
|||
|
||||
internal CueTrack(string binFile)
|
||||
{
|
||||
TrackIndex = new CueIndex[2];
|
||||
for (int i = 0; i < TrackIndex.Length; i++)
|
||||
TrackIndex[i] = new CueIndex(Convert.ToByte(i));
|
||||
|
||||
binFileName = binFile;
|
||||
binFileSz = new FileInfo(binFileName).Length;
|
||||
|
||||
TrackType = TrackType.TRACK_MODE2_2352;
|
||||
TrackNo = 0xFF;
|
||||
this.TrackType = TrackType.TRACK_MODE2_2352;
|
||||
this.TrackNo = 0xFF;
|
||||
}
|
||||
|
||||
public byte[] ToTocEntry()
|
||||
{
|
||||
byte[] tocEntry = new byte[10];
|
||||
|
||||
tocEntry[0] = Convert.ToByte(this.TrackType);
|
||||
tocEntry[1] = 0;
|
||||
tocEntry[2] = CueReader.BinaryDecimalConv(this.TrackNo);
|
||||
|
||||
|
||||
tocEntry[3] = this.TrackIndex[0].M;
|
||||
tocEntry[4] = this.TrackIndex[0].S;
|
||||
tocEntry[5] = this.TrackIndex[0].F;
|
||||
tocEntry[6] = 0;
|
||||
tocEntry[7] = this.TrackIndex[1].M;
|
||||
tocEntry[8] = this.TrackIndex[1].S;
|
||||
tocEntry[9] = this.TrackIndex[1].F;
|
||||
|
||||
return tocEntry;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace GameBuilder.Cue
|
||||
{
|
||||
public class CueIndex
|
||||
public class DiscIndex
|
||||
{
|
||||
public byte IndexNumber;
|
||||
public short Mrel;
|
||||
|
@ -73,7 +73,7 @@ namespace GameBuilder.Cue
|
|||
{
|
||||
get
|
||||
{
|
||||
return CueReader.BinaryDecimalConv(m);
|
||||
return CueReader.DecimalToBinaryDecimal(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ namespace GameBuilder.Cue
|
|||
{
|
||||
get
|
||||
{
|
||||
return CueReader.BinaryDecimalConv(s);
|
||||
return CueReader.DecimalToBinaryDecimal(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,11 +89,11 @@ namespace GameBuilder.Cue
|
|||
{
|
||||
get
|
||||
{
|
||||
return CueReader.BinaryDecimalConv(f);
|
||||
return CueReader.DecimalToBinaryDecimal(f);
|
||||
}
|
||||
}
|
||||
|
||||
internal CueIndex(byte indexNumber)
|
||||
internal DiscIndex(byte indexNumber)
|
||||
{
|
||||
IndexNumber = indexNumber;
|
||||
Mrel = 0;
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Cue
|
||||
{
|
||||
public class DiscTrack
|
||||
{
|
||||
private byte unk1;
|
||||
private byte unk6;
|
||||
public TrackType TrackType;
|
||||
public byte TrackNo;
|
||||
public DiscIndex[] TrackIndex;
|
||||
|
||||
public DiscTrack()
|
||||
{
|
||||
TrackIndex = new DiscIndex[2];
|
||||
for (int i = 0; i < TrackIndex.Length; i++)
|
||||
TrackIndex[i] = new DiscIndex(Convert.ToByte(i));
|
||||
|
||||
unk1 = 0;
|
||||
unk6 = 0;
|
||||
|
||||
}
|
||||
|
||||
public static DiscTrack FromTocEntry(byte[] tocEntry)
|
||||
{
|
||||
if (tocEntry.Length != 0xA) throw new Exception("Invalid TOC Entry.");
|
||||
|
||||
DiscTrack track = new DiscTrack();
|
||||
track.TrackType = (TrackType)tocEntry[0];
|
||||
track.unk1 = tocEntry[1];
|
||||
track.TrackNo = CueReader.BinaryDecimalToDecimal(tocEntry[2]);
|
||||
|
||||
track.TrackIndex[0].Mrel = Convert.ToInt16(CueReader.BinaryDecimalToDecimal(tocEntry[3]) - track.TrackIndex[0].Mdelta);
|
||||
track.TrackIndex[0].Srel = Convert.ToInt16(CueReader.BinaryDecimalToDecimal(tocEntry[4]) - track.TrackIndex[0].Sdelta);
|
||||
track.TrackIndex[0].Frel = Convert.ToInt16(CueReader.BinaryDecimalToDecimal(tocEntry[5]) - track.TrackIndex[0].Fdelta);
|
||||
track.unk6 = tocEntry[6];
|
||||
track.TrackIndex[1].Mrel = Convert.ToInt16(CueReader.BinaryDecimalToDecimal(tocEntry[7]) - track.TrackIndex[1].Mdelta);
|
||||
track.TrackIndex[1].Srel = Convert.ToInt16(CueReader.BinaryDecimalToDecimal(tocEntry[8]) - track.TrackIndex[1].Sdelta);
|
||||
track.TrackIndex[1].Frel = Convert.ToInt16(CueReader.BinaryDecimalToDecimal(tocEntry[9]) - track.TrackIndex[1].Fdelta);
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
public byte[] ToTocEntry()
|
||||
{
|
||||
byte[] tocEntry = new byte[0xA];
|
||||
|
||||
tocEntry[0] = Convert.ToByte(this.TrackType);
|
||||
tocEntry[1] = unk1;
|
||||
tocEntry[2] = CueReader.DecimalToBinaryDecimal(this.TrackNo);
|
||||
|
||||
|
||||
tocEntry[3] = this.TrackIndex[0].M;
|
||||
tocEntry[4] = this.TrackIndex[0].S;
|
||||
tocEntry[5] = this.TrackIndex[0].F;
|
||||
tocEntry[6] = unk6;
|
||||
tocEntry[7] = this.TrackIndex[1].M;
|
||||
tocEntry[8] = this.TrackIndex[1].S;
|
||||
tocEntry[9] = this.TrackIndex[1].F;
|
||||
|
||||
return tocEntry;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Cue
|
||||
{
|
||||
public class SbiEntry
|
||||
{
|
||||
public DiscIndex MSF;
|
||||
public DiscTrack TOC;
|
||||
public int Sector
|
||||
{
|
||||
get
|
||||
{
|
||||
return CueReader.IdxToSector(MSF);
|
||||
}
|
||||
}
|
||||
|
||||
public SbiEntry(DiscIndex Msf, DiscTrack Toc)
|
||||
{
|
||||
MSF = Msf;
|
||||
TOC = Toc;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
using Li.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Cue
|
||||
{
|
||||
public class SbiReader
|
||||
{
|
||||
private StreamUtil sbiUtil;
|
||||
private List<SbiEntry> sbiEntries;
|
||||
public SbiEntry[] Entries
|
||||
{
|
||||
get
|
||||
{
|
||||
return sbiEntries.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private DiscIndex readMsfi()
|
||||
{
|
||||
byte m = CueReader.BinaryDecimalToDecimal(sbiUtil.ReadByte());
|
||||
byte s = CueReader.BinaryDecimalToDecimal(sbiUtil.ReadByte());
|
||||
byte f = CueReader.BinaryDecimalToDecimal(sbiUtil.ReadByte());
|
||||
byte i = CueReader.BinaryDecimalToDecimal(sbiUtil.ReadByte());
|
||||
|
||||
DiscIndex idx = new DiscIndex(i);
|
||||
idx.Mrel = m;
|
||||
idx.Srel = s;
|
||||
idx.Frel = f;
|
||||
return idx;
|
||||
}
|
||||
|
||||
private void init(Stream sbiFile)
|
||||
{
|
||||
sbiEntries = new List<SbiEntry>();
|
||||
sbiUtil = new StreamUtil(sbiFile);
|
||||
string magic = sbiUtil.ReadStrLen(3);
|
||||
if (magic != "SBI")
|
||||
throw new Exception("Invalid SBI Sub Channel file.");
|
||||
sbiUtil.ReadByte();
|
||||
|
||||
do
|
||||
{
|
||||
DiscIndex idx = readMsfi();
|
||||
DiscTrack toc = DiscTrack.FromTocEntry(sbiUtil.ReadBytes(0xA));
|
||||
|
||||
sbiEntries.Add(new SbiEntry(idx, toc));
|
||||
} while (sbiFile.Position < sbiFile.Length);
|
||||
}
|
||||
public SbiReader(string sbiFileName)
|
||||
{
|
||||
using (FileStream fsbi = File.OpenRead(sbiFileName))
|
||||
{
|
||||
init(fsbi);
|
||||
}
|
||||
}
|
||||
public SbiReader(Stream sbiFile)
|
||||
{
|
||||
init(sbiFile);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.Runtime.InteropServices;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Li.Utilities;
|
||||
using GameBuilder.Pops.LibCrypt;
|
||||
|
||||
namespace GameBuilder.Pops
|
||||
{
|
||||
|
@ -19,14 +20,14 @@ namespace GameBuilder.Pops
|
|||
const int DEFAULT_ISO_OFFSET = 0x100000;
|
||||
public int IsoOffset;
|
||||
|
||||
internal DiscCompressor(PopsImg srcImg, DiscInfo disc, IAtracEncoderBase encoder, int offset = DEFAULT_ISO_OFFSET)
|
||||
internal DiscCompressor(PopsImg srcImg, PSInfo disc, IAtracEncoderBase encoder, int offset = DEFAULT_ISO_OFFSET)
|
||||
{
|
||||
this.srcImg = srcImg;
|
||||
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;
|
||||
|
@ -67,23 +68,6 @@ namespace GameBuilder.Pops
|
|||
{
|
||||
isoHeaderUtil.WriteStrWithPadding(disc.DiscIdHdr, 0x00, 0x400);
|
||||
}
|
||||
|
||||
|
||||
public byte[] GenerateIsoPgd()
|
||||
{
|
||||
IsoHeader.Seek(0x0, SeekOrigin.Begin);
|
||||
byte[] isoHdr = IsoHeader.ToArray();
|
||||
|
||||
int headerSize = DNASHelper.CalculateSize(isoHdr.Length, 0x400);
|
||||
byte[] headerEnc = new byte[headerSize];
|
||||
|
||||
int sz = DNASHelper.Encrypt(headerEnc, isoHdr, srcImg.DrmInfo.VersionKey, isoHdr.Length, srcImg.DrmInfo.KeyIndex, 1, blockSize: 0x400);
|
||||
byte[] isoHdrPgd = headerEnc.ToArray();
|
||||
Array.Resize(ref isoHdrPgd, sz);
|
||||
|
||||
return isoHdrPgd;
|
||||
}
|
||||
|
||||
private void writeIsoLocation()
|
||||
{
|
||||
isoHeaderUtil.WriteInt32(0);
|
||||
|
@ -92,7 +76,7 @@ namespace GameBuilder.Pops
|
|||
|
||||
isoHeaderUtil.WriteInt32(IsoOffset); // always 0x100000 on single disc game
|
||||
|
||||
isoHeaderUtil.WritePadding(0x00, 0x620);
|
||||
isoHeaderUtil.WritePadding(0x00, 0x628);
|
||||
}
|
||||
|
||||
private void writeCompressedIso()
|
||||
|
@ -109,42 +93,68 @@ namespace GameBuilder.Pops
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSubChannelPgd()
|
||||
{
|
||||
if(disc.LibCrypt.Method == LibCryptMethod.METHOD_SUB_CHANNEL)
|
||||
{
|
||||
byte[] subChannelsData = disc.LibCrypt.Subchannels;
|
||||
|
||||
int sz = subChannelsData.Length / 0xC;
|
||||
uint location = Convert.ToUInt32(IsoOffset + CompressedIso.Position);
|
||||
writeSubchannelDatLocation(location, sz);
|
||||
|
||||
byte[] pgdData = srcImg.CreatePgd(subChannelsData);
|
||||
|
||||
CompressedIso.Write(pgdData, 0, pgdData.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateIsoHeaderAndCompress()
|
||||
{
|
||||
writeHeader();
|
||||
writeTOC();
|
||||
writeIsoLocation();
|
||||
writeName();
|
||||
writeDiscInfo();
|
||||
writeLibCryptData();
|
||||
|
||||
writeCompressedIso();
|
||||
|
||||
isoHeaderUtil.PadUntil(0x0, 0xb3880);
|
||||
|
||||
// now write CD-Audio data.
|
||||
// write CD Audio data.
|
||||
writeCompressedCDATracks();
|
||||
|
||||
// write subchannels
|
||||
writeSubChannelPgd();
|
||||
}
|
||||
|
||||
public void WriteSimpleDatLocation(Int64 location)
|
||||
private void writeSubchannelDatLocation(uint location, int totalSubchannels)
|
||||
{
|
||||
IsoHeader.Seek(0xE20, SeekOrigin.Begin);
|
||||
isoHeaderUtil.WriteInt64(location);
|
||||
isoHeaderUtil.WriteUInt32At(location, 0xED4);
|
||||
isoHeaderUtil.WriteInt32At(totalSubchannels, 0xED8);
|
||||
}
|
||||
private void writeName()
|
||||
|
||||
public void WriteSimpleDatLocation(uint location)
|
||||
{
|
||||
// copied from crash bandicoot warped
|
||||
isoHeaderUtil.WriteUInt32At(location, 0xE20);
|
||||
}
|
||||
|
||||
isoHeaderUtil.WriteInt64(0x00); // SIMPLE.DAT location
|
||||
|
||||
isoHeaderUtil.WriteInt32(2047); // unk
|
||||
isoHeaderUtil.WriteStrWithPadding(disc.DiscName, 0x00, 0x80);
|
||||
isoHeaderUtil.WriteInt32(3); // unk
|
||||
|
||||
isoHeaderUtil.WriteInt32(0x72d0ee59); // appears to be constant?
|
||||
private void writeLibCryptData()
|
||||
{
|
||||
isoHeaderUtil.WriteInt32(disc.LibCrypt.ObfuscatedMagicWord);
|
||||
isoHeaderUtil.WriteInt32(0);
|
||||
isoHeaderUtil.WriteInt32(0);
|
||||
isoHeaderUtil.WriteInt32(0);
|
||||
|
||||
isoHeaderUtil.WritePadding(0, 0x2D40);
|
||||
|
||||
}
|
||||
private void writeDiscInfo()
|
||||
{
|
||||
isoHeaderUtil.WriteUInt32(Convert.ToUInt32(disc.LibCrypt.Method)); // libcrypt method
|
||||
isoHeaderUtil.WriteStrWithPadding(disc.DiscName, 0x00, 0x80); // disc title
|
||||
isoHeaderUtil.WriteInt32(3); // PARENTAL_LEVEL ?
|
||||
}
|
||||
|
||||
private void writeCDAEntry(int position, int length, uint key)
|
||||
|
@ -179,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);
|
||||
|
@ -227,12 +237,12 @@ namespace GameBuilder.Pops
|
|||
cue.Dispose();
|
||||
}
|
||||
|
||||
private DiscInfo disc;
|
||||
private PSInfo disc;
|
||||
private CueReader cue;
|
||||
private PopsImg srcImg;
|
||||
|
||||
public MemoryStream IsoHeader;
|
||||
public MemoryStream CompressedIso;
|
||||
public BuildStream IsoHeader;
|
||||
public BuildStream CompressedIso;
|
||||
|
||||
private StreamUtil isoHeaderUtil;
|
||||
private IAtracEncoderBase atrac3Encoder;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
public const int MAGIC_WORD_KEY = 0x72D0EE59;
|
||||
|
||||
public static int[][] LIBCRYPT_PAIRS = new int[16][] { new int[2] { 14105, 14110 },
|
||||
new int[2] { 14231, 14236 },
|
||||
new int[2] { 14485, 14490 },
|
||||
new int[2] { 14579, 14584 },
|
||||
new int[2] { 14649, 14654 },
|
||||
new int[2] { 14899, 14904 },
|
||||
new int[2] { 15056, 15061 },
|
||||
new int[2] { 15130, 15135 },
|
||||
new int[2] { 15242, 15247 },
|
||||
new int[2] { 15312, 15317 },
|
||||
new int[2] { 15378, 15383 },
|
||||
new int[2] { 15628, 15633 },
|
||||
new int[2] { 15919, 15924 },
|
||||
new int[2] { 16031, 16036 },
|
||||
new int[2] { 16101, 16106 },
|
||||
new int[2] { 16167, 16172 }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using GameBuilder.Cue;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public class DbLibCrypt : LibCryptInfo
|
||||
{
|
||||
private string discId;
|
||||
public override int MagicWord
|
||||
{
|
||||
get
|
||||
{
|
||||
return LibCrypt.MagicWord.LookupMagicWord(discId);
|
||||
}
|
||||
}
|
||||
|
||||
public DbLibCrypt(string discId, LibCryptMethod method)
|
||||
{
|
||||
this.discId = discId;
|
||||
this.Method = method;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public abstract class LibCryptInfo
|
||||
{
|
||||
private LibCryptMethod method;
|
||||
public virtual LibCryptMethod Method
|
||||
{
|
||||
get
|
||||
{
|
||||
return method;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (MagicWord == 0) return;
|
||||
method = value;
|
||||
}
|
||||
}
|
||||
public abstract int MagicWord { get; }
|
||||
|
||||
public virtual int ObfuscatedMagicWord
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Method == LibCryptMethod.METHOD_SUB_CHANNEL) return 0;
|
||||
return LibCrypt.MagicWord.ObfuscateMagicWord(this.MagicWord);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual byte[] Subchannels
|
||||
{
|
||||
get
|
||||
{
|
||||
return LibCrypt.SubChannel.CreateSubchannelDat(this.MagicWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public enum LibCryptMethod : uint
|
||||
{
|
||||
METHOD_MAGIC_WORD = 0x7ff,
|
||||
METHOD_SUB_CHANNEL = 0x8000,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using GameBuilder.Cue;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public class MagicWord
|
||||
{
|
||||
public static int ObfuscateMagicWord(int magicWord)
|
||||
{
|
||||
return magicWord ^ Constants.MAGIC_WORD_KEY;
|
||||
}
|
||||
|
||||
public static int LookupMagicWord(string discId)
|
||||
{
|
||||
using (TextReader magicWords = new StringReader(Resources.MAGICWORDS))
|
||||
{
|
||||
for(string? line = magicWords.ReadLine();
|
||||
line is not null;
|
||||
line = magicWords.ReadLine())
|
||||
{
|
||||
string[] split = line.Split(' ');
|
||||
|
||||
if (split[0].Equals(discId, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return Int32.Parse(split[1], NumberStyles.HexNumber);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public static int GenerateMagicWord(SbiEntry[] sbiEntries)
|
||||
{
|
||||
bool[] bits = new bool[16];
|
||||
|
||||
HashSet<int> sbiSectors = new HashSet<int>();
|
||||
foreach(SbiEntry sbiEntry in sbiEntries)
|
||||
sbiSectors.Add(sbiEntry.Sector);
|
||||
|
||||
for (int i = 0; i < bits.Length; i++)
|
||||
bits[i] = (sbiSectors.Contains(Constants.LIBCRYPT_PAIRS[i][0]) && sbiSectors.Contains(Constants.LIBCRYPT_PAIRS[i][1]));
|
||||
|
||||
|
||||
int magicWord = 0;
|
||||
|
||||
for (int i = 0; i < bits.Length; i++)
|
||||
{
|
||||
if (bits[i]) magicWord |= 1;
|
||||
|
||||
if(i+1 < bits.Length)
|
||||
magicWord <<= 1;
|
||||
}
|
||||
|
||||
return magicWord;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using GameBuilder.Cue;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public class SbiLibCrypt : LibCryptInfo
|
||||
{
|
||||
private SbiReader sbiReader;
|
||||
public override int MagicWord
|
||||
{
|
||||
get
|
||||
{
|
||||
return LibCrypt.MagicWord.GenerateMagicWord(sbiReader.Entries);
|
||||
}
|
||||
}
|
||||
|
||||
public SbiLibCrypt(SbiReader sbi, LibCryptMethod method)
|
||||
{
|
||||
this.sbiReader = sbi;
|
||||
this.Method = method;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
using GameBuilder.Cue;
|
||||
using Li.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GameBuilder.Pops.LibCrypt
|
||||
{
|
||||
public class SubChannel
|
||||
{
|
||||
public static byte[] CreateSubchannelDat(int magicWord)
|
||||
{
|
||||
using(BuildStream subChannels = new BuildStream())
|
||||
{
|
||||
StreamUtil subChannelsUtil = new StreamUtil(subChannels);
|
||||
// this header seems to mark the start of the sub channel data.
|
||||
subChannelsUtil.WriteUInt32(0xFFFFFFFF);
|
||||
subChannelsUtil.WriteUInt32(0x00000000);
|
||||
subChannelsUtil.WriteUInt32(0xFFFFFFFF);
|
||||
|
||||
|
||||
for (int i = 0; i < Constants.LIBCRYPT_PAIRS.Length; i++)
|
||||
{
|
||||
if ((magicWord & (1 << ((Constants.LIBCRYPT_PAIRS.Length - 1) - i))) != 0)
|
||||
{
|
||||
int[] pair = Constants.LIBCRYPT_PAIRS[i];
|
||||
|
||||
foreach (int lcSector in pair)
|
||||
{
|
||||
DiscIndex sidx = CueReader.SectorToIdx(lcSector, 0);
|
||||
sidx.Sdelta = -2;
|
||||
int adjustedSector = CueReader.IdxToSector(sidx);
|
||||
|
||||
// write sector number offset by 2s
|
||||
subChannelsUtil.WriteInt32(adjustedSector);
|
||||
subChannelsUtil.WriteByte(0x01);
|
||||
subChannelsUtil.WriteByte(0x01);
|
||||
|
||||
sidx.Fdelta = -1;
|
||||
sidx.Sdelta = -2;
|
||||
|
||||
// write sector index 1 but corrupted
|
||||
subChannelsUtil.WriteByte(sidx.M);
|
||||
subChannelsUtil.WriteByte(sidx.S);
|
||||
subChannelsUtil.WriteByte(sidx.F);
|
||||
|
||||
sidx.Sdelta = 0;
|
||||
|
||||
// write sector index 0 but corrupted
|
||||
subChannelsUtil.WriteByte(sidx.M);
|
||||
subChannelsUtil.WriteByte(sidx.S);
|
||||
subChannelsUtil.WriteByte(sidx.F);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// this header seems to mark the end of the sub channel data.
|
||||
subChannelsUtil.WriteUInt32(0xFFFFFFFF);
|
||||
subChannelsUtil.WriteUInt32(0xFFFFFFFF);
|
||||
subChannelsUtil.WriteUInt32(0xFFFFFFFF);
|
||||
|
||||
return subChannels.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
using DiscUtils.Iso9660Ps1;
|
||||
using DiscUtils.Raw;
|
||||
using DiscUtils.Streams;
|
||||
using GameBuilder.Cue;
|
||||
using GameBuilder.Pops.LibCrypt;
|
||||
using Li.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -10,12 +12,29 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace GameBuilder.Pops
|
||||
{
|
||||
public class DiscInfo
|
||||
public class PSInfo
|
||||
{
|
||||
private string cueFile;
|
||||
private string discName;
|
||||
private string discId;
|
||||
private LibCryptInfo lc;
|
||||
|
||||
public LibCryptInfo LibCrypt
|
||||
{
|
||||
get
|
||||
{
|
||||
return lc;
|
||||
}
|
||||
}
|
||||
public string? SbiFile
|
||||
{
|
||||
get
|
||||
{
|
||||
string sbiFileName = Path.ChangeExtension(CueFile, ".sbi");
|
||||
if(File.Exists(sbiFileName)) return sbiFileName;
|
||||
else return null;
|
||||
}
|
||||
}
|
||||
public string CueFile
|
||||
{
|
||||
get
|
||||
|
@ -50,9 +69,13 @@ namespace GameBuilder.Pops
|
|||
{
|
||||
return discId.Replace("-", "").Replace("_", "").ToUpperInvariant().PadRight(9, '0').Substring(0, 9).ToUpperInvariant();
|
||||
}
|
||||
set
|
||||
{
|
||||
this.discId = value.Replace("-", "").Replace("_", "").ToUpperInvariant().PadRight(9, '0').Substring(0, 9).ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
|
||||
public DiscInfo(string cueFile)
|
||||
public PSInfo(string cueFile)
|
||||
{
|
||||
this.cueFile = cueFile;
|
||||
|
||||
|
@ -92,6 +115,11 @@ namespace GameBuilder.Pops
|
|||
if (discName == "") discName = Path.GetFileNameWithoutExtension(cueFile);
|
||||
if (discId is null) discId = "SLUS00001";
|
||||
|
||||
if (this.SbiFile is not null)
|
||||
this.lc = new SbiLibCrypt(new SbiReader(this.SbiFile), LibCryptMethod.METHOD_MAGIC_WORD);
|
||||
else
|
||||
this.lc = new DbLibCrypt(discId, LibCryptMethod.METHOD_MAGIC_WORD);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using GameBuilder;
|
||||
using GameBuilder.Cue;
|
||||
using GameBuilder.Psp;
|
||||
using Li.Utilities;
|
||||
using PspCrypto;
|
||||
|
@ -16,21 +17,18 @@ 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 = generateSimplePgd();
|
||||
this.SimplePgd = CreatePgd(simple.ToArray());
|
||||
|
||||
this.EbootElf = Resources.DATAPSPSD;
|
||||
this.ConfigBin = Resources.DATAPSPSDCFG;
|
||||
this.PatchEboot = true;
|
||||
}
|
||||
|
||||
private MemoryStream simple;
|
||||
private StreamUtil simpleUtil;
|
||||
public byte[] StartDat;
|
||||
public byte[] SimplePgd;
|
||||
|
||||
private void createSimpleDat()
|
||||
internal void createSimpleDat()
|
||||
{
|
||||
simpleUtil.WriteStr("SIMPLE ");
|
||||
simpleUtil.WriteInt32(100);
|
||||
|
@ -41,17 +39,15 @@ namespace GameBuilder.Pops
|
|||
|
||||
simpleUtil.WriteBytes(Resources.SIMPLE);
|
||||
}
|
||||
private byte[] generateSimplePgd()
|
||||
public byte[] CreatePgd(byte[] buffer)
|
||||
{
|
||||
simple.Seek(0x0, SeekOrigin.Begin);
|
||||
byte[] simpleData = simple.ToArray();
|
||||
|
||||
int simpleSz = DNASHelper.CalculateSize(simpleData.Length, 0x400);
|
||||
byte[] simpleEnc = new byte[simpleSz];
|
||||
int bufferSz = DNASHelper.CalculateSize(buffer.Length, 0x400);
|
||||
byte[] bufferEnc = new byte[bufferSz];
|
||||
|
||||
// get pgd
|
||||
int sz = DNASHelper.Encrypt(simpleEnc, simpleData, DrmInfo.VersionKey, simpleData.Length, DrmInfo.KeyIndex, 1, blockSize: 0x400);
|
||||
byte[] pgd = simpleEnc.ToArray();
|
||||
int sz = DNASHelper.Encrypt(bufferEnc, buffer, DrmInfo.VersionKey, buffer.Length, DrmInfo.KeyIndex, 1, blockSize: 0x400);
|
||||
byte[] pgd = bufferEnc.ToArray();
|
||||
Array.Resize(ref pgd, sz);
|
||||
|
||||
return pgd;
|
||||
|
@ -62,25 +58,43 @@ namespace GameBuilder.Pops
|
|||
{
|
||||
Span<byte> loaderEnc = new byte[0x9B13];
|
||||
|
||||
byte[] dataPspElf = Resources.DATAPSPSD;
|
||||
//byte[] dataPspElf = Resources.DATAPSPSD;
|
||||
|
||||
// calculate size low and high part ..
|
||||
uint szLow = Convert.ToUInt32(Psar.Length) >> 16;
|
||||
uint szHigh = Convert.ToUInt32(Psar.Length) & 0xFFFF;
|
||||
if (this.PatchEboot)
|
||||
{
|
||||
// calculate size low and high part ..
|
||||
uint szLow = Convert.ToUInt32(Psar.Length) >> 16;
|
||||
uint szHigh = Convert.ToUInt32(Psar.Length) & 0xFFFF;
|
||||
|
||||
// convert to big endain bytes
|
||||
byte[] lowBits = BitConverter.GetBytes(Convert.ToUInt16(szLow)).ToArray();
|
||||
byte[] highBits = BitConverter.GetBytes(Convert.ToUInt16(szHigh)).ToArray();
|
||||
// convert to big endain bytes
|
||||
byte[] lowBits = BitConverter.GetBytes(Convert.ToUInt16(szLow)).ToArray();
|
||||
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);
|
||||
// overwrite data.psar size check ..
|
||||
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 BuildStream simple;
|
||||
private StreamUtil simpleUtil;
|
||||
|
||||
public byte[] EbootElf;
|
||||
public byte[] ConfigBin;
|
||||
public bool PatchEboot;
|
||||
|
||||
public byte[] StartDat;
|
||||
public byte[] SimplePgd;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@ namespace GameBuilder.Pops
|
|||
this.compressor = discCompressor;
|
||||
}
|
||||
|
||||
public PsIsoImg(NpDrmInfo versionKey, DiscInfo disc, IAtracEncoderBase encoder) : base(versionKey)
|
||||
public PsIsoImg(NpDrmInfo versionKey, PSInfo disc, IAtracEncoderBase encoder) : base(versionKey)
|
||||
{
|
||||
this.compressor = new DiscCompressor(this, disc, encoder);
|
||||
this.compressor.RegisterCallback(onProgress);
|
||||
}
|
||||
|
||||
public PsIsoImg(NpDrmInfo versionKey, DiscInfo disc) : base(versionKey)
|
||||
public PsIsoImg(NpDrmInfo versionKey, PSInfo disc) : base(versionKey)
|
||||
{
|
||||
this.compressor = new DiscCompressor(this, disc, new Atrac3ToolEncoder());
|
||||
this.compressor.RegisterCallback(onProgress);
|
||||
|
@ -34,7 +34,7 @@ namespace GameBuilder.Pops
|
|||
|
||||
psarUtil.WritePadding(0x00, 0x3ec); // Skip forwards
|
||||
|
||||
byte[] isoHdrPgd = compressor.GenerateIsoPgd();
|
||||
byte[] isoHdrPgd = this.CreatePgd(compressor.IsoHeader.ToArray());
|
||||
psarUtil.WriteBytes(isoHdrPgd);
|
||||
psarUtil.PadUntil(0x00, compressor.IsoOffset);
|
||||
}
|
||||
|
@ -45,7 +45,8 @@ namespace GameBuilder.Pops
|
|||
compressor.GenerateIsoHeaderAndCompress();
|
||||
|
||||
// write STARTDAT location
|
||||
compressor.WriteSimpleDatLocation((compressor.IsoOffset + compressor.CompressedIso.Length) + StartDat.Length);
|
||||
UInt32 simpleDatLocation = Convert.ToUInt32((compressor.IsoOffset + compressor.CompressedIso.Length) + StartDat.Length);
|
||||
compressor.WriteSimpleDatLocation(simpleDatLocation);
|
||||
|
||||
// write general PSISO header
|
||||
generatePsIsoHeader();
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace GameBuilder.Pops
|
|||
this.updateProgress(inf.Done, inf.Remain, inf.CurrentProcess + " (disc " + discNumber + ")");
|
||||
}
|
||||
|
||||
public PsTitleImg(NpDrmInfo drmInfo, DiscInfo[] discs) : base(drmInfo)
|
||||
public PsTitleImg(NpDrmInfo drmInfo, PSInfo[] discs) : base(drmInfo)
|
||||
{
|
||||
if (discs.Length > MAX_DISCS) throw new Exception("Sorry, multi disc games only support up to 5 discs... (i dont make the rules)");
|
||||
this.compressors = new DiscCompressor[MAX_DISCS];
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -171,13 +171,13 @@ namespace GameBuilder.Pops
|
|||
base.Dispose();
|
||||
}
|
||||
|
||||
private DiscInfo[] discs;
|
||||
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,8 +43,8 @@ namespace GameBuilder.Psp
|
|||
public void PatchSfo()
|
||||
{
|
||||
Sfo sfoKeys = Sfo.ReadSfo(umdImage.DataFiles["PARAM.SFO"]);
|
||||
if ((sfoKeys["CATEGORY"] as String) == "UG") // "UMD Game"
|
||||
sfoKeys["CATEGORY"] = "EG"; // set it to "Eboot Game"
|
||||
//if ((sfoKeys["CATEGORY"] as String) == "UG") // "UMD Game"
|
||||
sfoKeys["CATEGORY"] = "EG"; // set it to "Eboot Game"
|
||||
umdImage.DataFiles["PARAM.SFO"] = sfoKeys.WriteSfo();
|
||||
}
|
||||
private void createNpHdr()
|
||||
|
@ -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)
|
||||
|
|
|
@ -80,6 +80,47 @@ namespace GameBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to SCES00311 87AA
|
||||
///SCES01431 6547
|
||||
///SCES01444 BD44
|
||||
///SCES01492 D16A
|
||||
///SCES01493 197A
|
||||
///SCES01494 AAA6
|
||||
///SCES01495 0E57
|
||||
///SCES01516 44F6
|
||||
///SCES01517 AE85
|
||||
///SCES01518 9C27
|
||||
///SCES01519 364B
|
||||
///SCES01564 CEC1
|
||||
///SCES01695 89EA
|
||||
///SCES01700 4717
|
||||
///SCES01701 C49E
|
||||
///SCES01702 672A
|
||||
///SCES01703 883F
|
||||
///SCES01704 CE32
|
||||
///SCES01763 096F
|
||||
///SCES01882 B364
|
||||
///SCES01909 E788
|
||||
///SCES01979 0D9D
|
||||
///SCES02004 C437
|
||||
///SCES02005 9137
|
||||
///SCES02006 7554
|
||||
///SCES02007 E686
|
||||
///SCES02028 9AD4
|
||||
///SCES02029 26B6
|
||||
///SCES02030 23D9
|
||||
///SCES02031 D325
|
||||
///SCES02080 9DE0
|
||||
///SCES02104 744B
|
||||
/// [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
public static string MAGICWORDS {
|
||||
get {
|
||||
return ResourceManager.GetString("MAGICWORDS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
|
|
@ -124,6 +124,9 @@
|
|||
<data name="DATAPSPSDCFG" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\DATAPSPSDCFG.BIN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="MAGICWORDS" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\MagicWords.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="SIMPLE" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\SIMPLE.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
SCES00311 87AA
|
||||
SCES01431 6547
|
||||
SCES01444 BD44
|
||||
SCES01492 D16A
|
||||
SCES01493 197A
|
||||
SCES01494 AAA6
|
||||
SCES01495 0E57
|
||||
SCES01516 44F6
|
||||
SCES01517 AE85
|
||||
SCES01518 9C27
|
||||
SCES01519 364B
|
||||
SCES01564 CEC1
|
||||
SCES01695 89EA
|
||||
SCES01700 4717
|
||||
SCES01701 C49E
|
||||
SCES01702 672A
|
||||
SCES01703 883F
|
||||
SCES01704 CE32
|
||||
SCES01763 096F
|
||||
SCES01882 B364
|
||||
SCES01909 E788
|
||||
SCES01979 0D9D
|
||||
SCES02004 C437
|
||||
SCES02005 9137
|
||||
SCES02006 7554
|
||||
SCES02007 E686
|
||||
SCES02028 9AD4
|
||||
SCES02029 26B6
|
||||
SCES02030 23D9
|
||||
SCES02031 D325
|
||||
SCES02080 9DE0
|
||||
SCES02104 744B
|
||||
SCES02105 A371
|
||||
SCES02181 7D84
|
||||
SCES02182 A8CD
|
||||
SCES02184 1E5C
|
||||
SCES02185 74E4
|
||||
SCES02222 A4F8
|
||||
SCES02264 0E3E
|
||||
SCES02290 12D7
|
||||
SCES02365 1CDC
|
||||
SCES02366 D6C8
|
||||
SCES02367 96A6
|
||||
SCES02368 5C27
|
||||
SCES02369 DC25
|
||||
SCES02430 B159
|
||||
SCES02431 7872
|
||||
SCES02432 13AE
|
||||
SCES02433 B50B
|
||||
SCES02487 7AD0
|
||||
SCES02488 898F
|
||||
SCES02489 25EA
|
||||
SCES02490 0F6C
|
||||
SCES02491 F01B
|
||||
SCES02544 3A17
|
||||
SCES02545 A96C
|
||||
SCES02546 378A
|
||||
SCES02834 E728
|
||||
SCES02835 369A
|
||||
SCES02977 B88D
|
||||
SCES03189 4BCC
|
||||
SCES03190 710F
|
||||
SCES03191 6A95
|
||||
SCES12080 9DE0
|
||||
SCES22080 9DE0
|
||||
SCES32080 9DE0
|
||||
SLES00017 E2B8
|
||||
SLES00995 8BB1
|
||||
SLES01041 6317
|
||||
SLES01226 03E7
|
||||
SLES01241 E313
|
||||
SLES01301 B722
|
||||
SLES01362 6CA6
|
||||
SLES01545 A54E
|
||||
SLES01715 A4F4
|
||||
SLES01733 B06D
|
||||
SLES01906 14ED
|
||||
SLES01907 C0EE
|
||||
SLES01943 7067
|
||||
SLES02024 1B71
|
||||
SLES02025 CA4E
|
||||
SLES02026 116F
|
||||
SLES02027 3A63
|
||||
SLES02061 8AB5
|
||||
SLES02071 2735
|
||||
SLES02080 9DE0
|
||||
SLES02081 6837
|
||||
SLES02082 698B
|
||||
SLES02083 94CD
|
||||
SLES02084 44BD
|
||||
SLES02086 16F4
|
||||
SLES02112 AF44
|
||||
SLES02113 5897
|
||||
SLES02118 6DB0
|
||||
SLES02207 3A6C
|
||||
SLES02208 71A9
|
||||
SLES02209 26D6
|
||||
SLES02210 632D
|
||||
SLES02211 1A57
|
||||
SLES02292 86F2
|
||||
SLES02293 BA85
|
||||
SLES02328 3F22
|
||||
SLES02329 9D38
|
||||
SLES02330 E03D
|
||||
SLES02354 64E9
|
||||
SLES02355 4AE6
|
||||
SLES02395 AAA9
|
||||
SLES02396 A56A
|
||||
SLES02402 AA3A
|
||||
SLES02529 AD70
|
||||
SLES02530 7C23
|
||||
SLES02531 ACB8
|
||||
SLES02532 1C3D
|
||||
SLES02533 EA8A
|
||||
SLES02538 6353
|
||||
SLES02558 D5E0
|
||||
SLES02559 5715
|
||||
SLES02560 DB28
|
||||
SLES02561 EA85
|
||||
SLES02562 3D94
|
||||
SLES02563 4B63
|
||||
SLES02572 395C
|
||||
SLES02573 5563
|
||||
SLES02681 1CC7
|
||||
SLES02688 7368
|
||||
SLES02689 E1D2
|
||||
SLES02698 1C9D
|
||||
SLES02700 27D8
|
||||
SLES02704 711E
|
||||
SLES02705 4AAD
|
||||
SLES02706 1EB1
|
||||
SLES02707 AD31
|
||||
SLES02708 5EC4
|
||||
SLES02722 B68A
|
||||
SLES02723 0FF0
|
||||
SLES02724 CE94
|
||||
SLES02733 B60D
|
||||
SLES02754 1FC1
|
||||
SLES02755 5917
|
||||
SLES02756 E076
|
||||
SLES02763 78A6
|
||||
SLES02766 984F
|
||||
SLES02767 AB45
|
||||
SLES02768 9D68
|
||||
SLES02769 30DE
|
||||
SLES02824 B385
|
||||
SLES02830 62BC
|
||||
SLES02831 05DE
|
||||
SLES02839 CB19
|
||||
SLES02857 5F0A
|
||||
SLES02858 3E1A
|
||||
SLES02859 255E
|
||||
SLES02860 A792
|
||||
SLES02861 C8DC
|
||||
SLES02862 C3D1
|
||||
SLES02965 B6C8
|
||||
SLES02966 CEA1
|
||||
SLES02967 725A
|
||||
SLES02968 E516
|
||||
SLES02969 EC61
|
||||
SLES02975 7A91
|
||||
SLES02976 6547
|
||||
SLES02978 5B13
|
||||
SLES02979 2F4A
|
||||
SLES03061 0C7E
|
||||
SLES03062 B0CD
|
||||
SLES03241 7B82
|
||||
SLES03242 A768
|
||||
SLES03243 2771
|
||||
SLES03244 1597
|
||||
SLES03245 05D7
|
||||
SLES03324 CD31
|
||||
SLES03489 90AF
|
||||
SLES03519 BB14
|
||||
SLES03520 9678
|
||||
SLES03521 FB20
|
||||
SLES03522 CB0E
|
||||
SLES03523 30FC
|
||||
SLES03530 93F0
|
||||
SLES03603 5AC9
|
||||
SLES03604 196E
|
||||
SLES03605 F152
|
||||
SLES03606 C5D4
|
||||
SLES03607 8A3B
|
||||
SLES03626 4F23
|
||||
SLES03648 6939
|
||||
SLES12080 9DE0
|
||||
SLES12081 6837
|
||||
SLES12082 698B
|
||||
SLES12083 94CD
|
||||
SLES12084 44BD
|
||||
SLES12328 4AEC
|
||||
SLES12329 9D38
|
||||
SLES12330 DE03
|
||||
SLES12558 D5E0
|
||||
SLES12559 5715
|
||||
SLES12560 DB28
|
||||
SLES12561 EA85
|
||||
SLES12562 3D94
|
||||
SLES12965 A1D3
|
||||
SLES12966 9731
|
||||
SLES12967 D916
|
||||
SLES12968 544F
|
||||
SLES12969 645B
|
||||
SLES22080 9DE0
|
||||
SLES22081 6837
|
||||
SLES22082 698B
|
||||
SLES22083 94CD
|
||||
SLES22084 44BD
|
||||
SLES22328 70D3
|
||||
SLES22329 9D38
|
||||
SLES22330 236B
|
||||
SLES22965 6DC2
|
||||
SLES22966 C873
|
||||
SLES22967 19B5
|
||||
SLES22968 41CF
|
||||
SLES22969 6636
|
||||
SLES32080 9DE0
|
||||
SLES32081 6837
|
||||
SLES32082 698B
|
||||
SLES32083 94CD
|
||||
SLES32084 44BD
|
||||
SLES32965 1EC5
|
||||
SLES32966 35D1
|
||||
SLES32967 54CD
|
||||
SLES32968 C61D
|
||||
SLES32969 E8C3
|
|
@ -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));
|
||||
|
@ -138,6 +142,21 @@ namespace Li.Utilities
|
|||
{
|
||||
WriteBytes(BitConverter.GetBytes(v).Reverse().ToArray());
|
||||
}
|
||||
public void WriteInt32At(Int32 v, long location)
|
||||
{
|
||||
long oldPos = s.Position;
|
||||
s.Seek(location, SeekOrigin.Begin);
|
||||
WriteInt32(v);
|
||||
s.Seek(oldPos, SeekOrigin.Begin);
|
||||
}
|
||||
public void WriteUInt32At(UInt32 v, long location)
|
||||
{
|
||||
long oldPos = s.Position;
|
||||
s.Seek(location, SeekOrigin.Begin);
|
||||
WriteUInt32(v);
|
||||
s.Seek(oldPos, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
public void WriteInt32(Int32 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;
|
||||
|
@ -13,7 +14,7 @@ namespace LibChovy.Art
|
|||
private const string coverApi = "https://raw.githubusercontent.com/xlenore/psx-covers/main/covers/";
|
||||
private static HttpClient httpClient = new HttpClient();
|
||||
|
||||
public static async Task<byte[]> DownloadCover(DiscInfo game)
|
||||
public static async Task<byte[]> DownloadCover(PSInfo game)
|
||||
{
|
||||
string discIdDash = game.DiscId.Substring(0, 4) + "-" + game.DiscId.Substring(4, 5);
|
||||
|
||||
|
@ -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>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using GameBuilder.Pops;
|
||||
using GameBuilder.Pops.LibCrypt;
|
||||
using GameBuilder.Psp;
|
||||
using LibChovy.Art;
|
||||
using System;
|
||||
|
@ -16,16 +17,29 @@ namespace LibChovy
|
|||
public PopsParameters(NpDrmInfo drmInfo, NpDrmRif rif) : base(drmInfo, rif)
|
||||
{
|
||||
Type = ChovyTypes.POPS;
|
||||
discList = new List<DiscInfo>();
|
||||
discList = new List<PSInfo>();
|
||||
|
||||
EbootElfOverride = null;
|
||||
ConfigBinOverride = null;
|
||||
|
||||
discIdOverride = null;
|
||||
nameOverride = null;
|
||||
libCryptMethod = LibCryptMethod.METHOD_MAGIC_WORD;
|
||||
}
|
||||
private string? discIdOverride;
|
||||
private string? nameOverride;
|
||||
private List<DiscInfo> discList;
|
||||
private List<PSInfo> discList;
|
||||
private LibCryptMethod libCryptMethod;
|
||||
|
||||
private byte[]? pic0;
|
||||
private byte[]? pic1;
|
||||
private byte[]? icon0;
|
||||
|
||||
public DiscInfo FirstDisc
|
||||
|
||||
public byte[]? EbootElfOverride;
|
||||
public byte[]? ConfigBinOverride;
|
||||
|
||||
public PSInfo FirstDisc
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -101,9 +115,13 @@ namespace LibChovy
|
|||
|
||||
public void AddCd(string cd)
|
||||
{
|
||||
DiscInfo disc = new DiscInfo(cd);
|
||||
if (nameOverride is not null) disc.DiscName = nameOverride;
|
||||
else discList.Add(disc);
|
||||
PSInfo disc = new PSInfo(cd);
|
||||
|
||||
if (nameOverride is not null) disc.DiscName = this.nameOverride;
|
||||
if (discIdOverride is not null) disc.DiscId = this.discIdOverride;
|
||||
if (disc.SbiFile is not null) disc.LibCrypt.Method = this.CrackMethod;
|
||||
|
||||
discList.Add(disc);
|
||||
}
|
||||
public void RemoveCd(string cd)
|
||||
{
|
||||
|
@ -116,13 +134,31 @@ namespace LibChovy
|
|||
}
|
||||
}
|
||||
}
|
||||
public DiscInfo[] Discs
|
||||
public PSInfo[] Discs
|
||||
{
|
||||
get
|
||||
{
|
||||
return discList.ToArray();
|
||||
}
|
||||
}
|
||||
public string DiscId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (discIdOverride is not null && discIdOverride.Length == 9) return discIdOverride;
|
||||
return FirstDisc.DiscId;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals(FirstDisc.DiscId, StringComparison.InvariantCultureIgnoreCase)) { discIdOverride = null; return; };
|
||||
if (value.Length != 9) { discIdOverride = null; return; };
|
||||
|
||||
for (int i = 0; i < discList.Count; i++)
|
||||
discList[i].DiscId = value;
|
||||
|
||||
discIdOverride = value;
|
||||
}
|
||||
}
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
|
@ -143,6 +179,20 @@ namespace LibChovy
|
|||
}
|
||||
}
|
||||
|
||||
public LibCryptMethod CrackMethod
|
||||
{
|
||||
get
|
||||
{
|
||||
return libCryptMethod;
|
||||
}
|
||||
set
|
||||
{
|
||||
libCryptMethod = value;
|
||||
|
||||
for (int i = 0; i < discList.Count; i++)
|
||||
discList[i].LibCrypt.Method = value;
|
||||
}
|
||||
}
|
||||
public bool MultiDisc
|
||||
{
|
||||
get
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -369,7 +369,7 @@ namespace PbpResign
|
|||
AMCTRL.sceDrmBBCipherInit(out var ckey, 1, 2, npHdr.HeaderKey, vkey, 0);
|
||||
AMCTRL.sceDrmBBCipherUpdate(ref ckey, psarBuff[0x40..], 0x60);
|
||||
AMCTRL.sceDrmBBCipherFinal(ref ckey);
|
||||
npHdr = Utils.AsRef<NpUmdImgHdr>(psarBuff);
|
||||
npHdr = MemoryMarshal.AsRef<NpUmdImgHdr>(psarBuff);
|
||||
|
||||
var lbasize = npHdr.Body.LbaEnd - npHdr.Body.LbaStart + 1;
|
||||
if (npHdr.BlockBasis == 0)
|
||||
|
@ -1059,7 +1059,7 @@ namespace PbpResign
|
|||
return false;
|
||||
}
|
||||
|
||||
ref var npHdr = ref Utils.AsRef<NpUmdImgHdr>(psarBuff);
|
||||
ref var npHdr = ref MemoryMarshal.AsRef<NpUmdImgHdr>(psarBuff);
|
||||
|
||||
if (npHdr.Magic0 == 0x4d55504e && npHdr.Magic1 == 0x474d4944)
|
||||
{
|
||||
|
@ -1070,22 +1070,6 @@ namespace PbpResign
|
|||
return false;
|
||||
}
|
||||
type = 0;
|
||||
/*
|
||||
Console.WriteLine("VersionKey: " + BitConverter.ToString(NewVersionKey.ToArray()));
|
||||
|
||||
UmdInfo disc = new UmdInfo("fft.iso");
|
||||
NpUmdImg npumd = new NpUmdImg(new NpDrmInfo(NewVersionKey.ToArray(), CId, npHdr.NpFlags), disc, false);
|
||||
|
||||
npumd.CreatePsar();
|
||||
|
||||
PbpBuilder.CreatePbp(disc.DataFiles["PARAM.SFO"],
|
||||
disc.DataFiles["ICON0.PNG"],
|
||||
disc.DataFiles["ICON1.PMF"],
|
||||
disc.DataFiles["PIC0.PNG"],
|
||||
disc.DataFiles["PIC1.PNG"],
|
||||
disc.DataFiles["SND0.AT3"],
|
||||
npumd,
|
||||
"FFT.PBP"); */
|
||||
|
||||
return CopyNpUmdImg(input, output, pbpHdr, psarBuff, npHdr);
|
||||
}
|
||||
|
@ -1100,20 +1084,6 @@ namespace PbpResign
|
|||
return false;
|
||||
}
|
||||
type = 1;
|
||||
/*DiscInfo[] discs = new DiscInfo[2];
|
||||
discs[0] = new DiscInfo("ABEE\\D1.CUE", "Oddworld: Abe's Exoddus", "SLES01480");
|
||||
discs[1] = new DiscInfo("ABEE\\D2.CUE", "Oddworld: Abe's Exoddus", "SLES11480");
|
||||
PsTitleImg title = new PsTitleImg(NewVersionKey.ToArray(), CId, discs);
|
||||
title.CreatePsar();
|
||||
PbpBuilder.CreatePbp(File.ReadAllBytes("TEST\\PARAM.SFO"), File.ReadAllBytes("TEST\\ICON0.PNG"), null,
|
||||
File.ReadAllBytes("TEST\\PIC0.PNG"), File.ReadAllBytes("TEST\\PIC1.PNG"), null,
|
||||
title.GenerateDataPsp(), title, "ABE-EBOOT.PBP");
|
||||
//PsIsoImg i = new PsIsoImg("ROLLCAGE\\ROLLCAGE.CUE", "SLUS00800", "ROLLCAGE", CId, NewVersionKey.ToArray(),
|
||||
// File.ReadAllBytes("TEST\\PARAM.SFO"), File.ReadAllBytes("TEST\\ICON0.PNG"), null,
|
||||
// File.ReadAllBytes("TEST\\PIC0.PNG"), File.ReadAllBytes("TEST\\PIC1.PNG"), null);
|
||||
//File.WriteAllBytes("TEST.BIN", i.GetIsoHeader());
|
||||
//File.WriteAllBytes("TEST.ISOc", i.GetIso());*/
|
||||
|
||||
|
||||
return CopyPsIsoImg(input, output, pbpHdr);
|
||||
}
|
||||
|
@ -1208,8 +1178,8 @@ namespace PbpResign
|
|||
|
||||
var srcPath = Path.GetDirectoryName(srcPbp);
|
||||
|
||||
// try
|
||||
// {
|
||||
try
|
||||
{
|
||||
using var input = File.OpenRead(srcPbp);
|
||||
var hdr = new byte[Marshal.SizeOf<PbpHeader>()];
|
||||
var len = input.Read(hdr);
|
||||
|
@ -1219,7 +1189,7 @@ namespace PbpResign
|
|||
return;
|
||||
}
|
||||
|
||||
var pbpHdr = Utils.AsRef<PbpHeader>(hdr);
|
||||
var pbpHdr = MemoryMarshal.AsRef<PbpHeader>(hdr);
|
||||
if (pbpHdr.Sig != 0x50425000)
|
||||
{
|
||||
Console.WriteLine("Wrong pbp sig");
|
||||
|
@ -1374,11 +1344,11 @@ namespace PbpResign
|
|||
//}
|
||||
}
|
||||
|
||||
//}
|
||||
//catch (Exception e)
|
||||
//{
|
||||
// Console.WriteLine(e);
|
||||
//}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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\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>
|
|
@ -67,7 +67,7 @@ namespace PspCrypto
|
|||
static int Kirk4(Span<byte> buf, int size, int type)
|
||||
{
|
||||
int retv;
|
||||
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
hdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
|
||||
hdr.keyseed = type;
|
||||
hdr.data_size = size;
|
||||
|
@ -83,7 +83,7 @@ namespace PspCrypto
|
|||
static int Kirk5(Span<byte> buf, int size)
|
||||
{
|
||||
int retv;
|
||||
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
hdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
|
||||
hdr.keyseed = 0x0100;
|
||||
hdr.data_size = size;
|
||||
|
@ -99,7 +99,7 @@ namespace PspCrypto
|
|||
static int Kirk7(Span<byte> buf, int size, int type)
|
||||
{
|
||||
int retv;
|
||||
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
hdr.mode = KIRKEngine.KIRK_MODE_DECRYPT_CBC;
|
||||
hdr.keyseed = type;
|
||||
hdr.data_size = size;
|
||||
|
@ -115,7 +115,7 @@ namespace PspCrypto
|
|||
static int Kirk8(Span<byte> buf, int size)
|
||||
{
|
||||
int retv;
|
||||
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
|
||||
hdr.mode = KIRKEngine.KIRK_MODE_DECRYPT_CBC;
|
||||
hdr.keyseed = 0x0100;
|
||||
hdr.data_size = size;
|
||||
|
@ -553,7 +553,7 @@ namespace PspCrypto
|
|||
|
||||
public static int sceDrmBBMacFinal2(Span<byte> mkey, ReadOnlySpan<byte> hash, ReadOnlySpan<byte> vkey)
|
||||
{
|
||||
int i, retv, type;
|
||||
int retv, type;
|
||||
byte[] tmp = new byte[16];
|
||||
int kbuf;
|
||||
ref MAC_KEY macKey = ref MemoryMarshal.AsRef<MAC_KEY>(mkey);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace PspCrypto
|
|||
|
||||
data[..dataSize].CopyTo(pgdData[dataOffset..]);
|
||||
|
||||
ref var pgdHdr = ref Utils.AsRef<PgdHeader>(pgdData);
|
||||
ref var pgdHdr = ref MemoryMarshal.AsRef<PgdHeader>(pgdData);
|
||||
pgdHdr.Magic = 0x44475000;
|
||||
pgdHdr.KeyIndex = keyIndex;
|
||||
pgdHdr.DrmType = drmType;
|
||||
|
@ -81,7 +81,7 @@ namespace PspCrypto
|
|||
}
|
||||
|
||||
// Set the decryption parameters in the decrypted header.
|
||||
ref var pgdDesc = ref Utils.AsRef<PgdDesc>(pgdHdr.PgdDesc);
|
||||
ref var pgdDesc = ref MemoryMarshal.AsRef<PgdDesc>(pgdHdr.PgdDesc);
|
||||
pgdDesc.DataSize = dataSize;
|
||||
pgdDesc.BlockSize = blockSize;
|
||||
pgdDesc.DataOffset = dataOffset;
|
||||
|
|
|
@ -169,7 +169,7 @@ namespace PspCrypto
|
|||
{
|
||||
throw new ArgumentException("stream too small", nameof(stream));
|
||||
}
|
||||
var header = Utils.AsRef<PgdHeader>(hdr);
|
||||
var header = MemoryMarshal.AsRef<PgdHeader>(hdr);
|
||||
_keyIndex = header.KeyIndex;
|
||||
if (_keyIndex == 1)
|
||||
{
|
||||
|
@ -234,7 +234,7 @@ namespace PspCrypto
|
|||
throw new IOException("Wrong MAC 0x80");
|
||||
}
|
||||
|
||||
if (!Utils.isEmpty(_versionKey, 0x10))
|
||||
if (!Utils.IsEmpty(_versionKey, 0x10))
|
||||
{
|
||||
ret = CheckBBMac(hdr, 0x70, _versionKey, header.Hash70, macType);
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ namespace PspCrypto
|
|||
{
|
||||
throw new IOException($"Error 0x{ret:X8}");
|
||||
}
|
||||
var desc = Utils.AsRef<PgdDesc>(header.PgdDesc);
|
||||
var desc = MemoryMarshal.AsRef<PgdDesc>(header.PgdDesc);
|
||||
if (desc.Version != 0)
|
||||
{
|
||||
throw new IOException($"Error 0x{8051020:X8}");
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PspCrypto.Security.Cryptography;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using PspCrypto.Security.Cryptography;
|
||||
|
||||
namespace PspCrypto
|
||||
{
|
||||
|
@ -68,17 +65,6 @@ namespace PspCrypto
|
|||
return new ECDsaManaged(par, ebootPbp, type);
|
||||
}
|
||||
|
||||
public static ECDsa CreateNet(ECCurve curve, byte[] privateKey, byte[] pubx, byte[] puby)
|
||||
{
|
||||
var par = new ECParameters
|
||||
{
|
||||
Curve = curve,
|
||||
D = privateKey,
|
||||
Q = { X = pubx, Y = puby }
|
||||
};
|
||||
return ECDsa.Create(par);
|
||||
}
|
||||
|
||||
public static void SignNpImageHeader(Span<byte> npHdr)
|
||||
{
|
||||
var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using ECDsaTest.SafeHandles;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Crypto
|
||||
{
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumDestroy")]
|
||||
internal static extern void BigNumDestroy(IntPtr a);
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumToBinary")]
|
||||
private static extern unsafe int BigNumToBinary(SafeBignumHandle a, byte* to);
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetBigNumBytes")]
|
||||
private static extern int GetBigNumBytes(SafeBignumHandle a);
|
||||
|
||||
|
||||
internal static byte[] ExtractBignum(IntPtr bignum, int targetSize)
|
||||
{
|
||||
// Given that the only reference held to bignum is an IntPtr, create an unowned SafeHandle
|
||||
// to ensure that we don't destroy the key after extraction.
|
||||
using (SafeBignumHandle handle = new SafeBignumHandle(bignum, ownsHandle: false))
|
||||
{
|
||||
return ExtractBignum(handle, targetSize);
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe byte[] ExtractBignum(SafeBignumHandle bignum, int targetSize)
|
||||
{
|
||||
if (bignum == null || bignum.IsInvalid)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int compactSize = GetBigNumBytes(bignum);
|
||||
|
||||
if (targetSize < compactSize)
|
||||
{
|
||||
targetSize = compactSize;
|
||||
}
|
||||
|
||||
// OpenSSL BIGNUM values do not record leading zeroes.
|
||||
// Windows Crypt32 does.
|
||||
//
|
||||
// Since RSACryptoServiceProvider already checks that RSAParameters.DP.Length is
|
||||
// exactly half of RSAParameters.Modulus.Length, we need to left-pad (big-endian)
|
||||
// the array with zeroes.
|
||||
int offset = targetSize - compactSize;
|
||||
|
||||
byte[] buf = new byte[targetSize];
|
||||
|
||||
fixed (byte* to = buf)
|
||||
{
|
||||
byte* start = to + offset;
|
||||
BigNumToBinary(bignum, start);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Crypto
|
||||
{
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrClearError")]
|
||||
internal static extern ulong ErrClearError();
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrGetErrorAlloc")]
|
||||
private static extern ulong ErrGetErrorAlloc([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure);
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrErrorStringN")]
|
||||
private static extern unsafe void ErrErrorStringN(ulong e, byte* buf, int len);
|
||||
|
||||
private static unsafe string ErrErrorStringN(ulong error)
|
||||
{
|
||||
var buffer = new byte[1024];
|
||||
fixed (byte* buf = &buffer[0])
|
||||
{
|
||||
ErrErrorStringN(error, buf, buffer.Length);
|
||||
return Marshal.PtrToStringAnsi((IntPtr)buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal static Exception CreateOpenSslCryptographicException()
|
||||
{
|
||||
// The Windows cryptography library reports error codes through
|
||||
// Marshal.GetLastWin32Error, which has a single value when the
|
||||
// function exits, last writer wins.
|
||||
//
|
||||
// OpenSSL maintains an error queue. Calls to ERR_get_error read
|
||||
// values out of the queue in the order that ERR_set_error wrote
|
||||
// them. Nothing enforces that a single call into an OpenSSL
|
||||
// function will guarantee at-most one error being set.
|
||||
//
|
||||
// In order to maintain parity in how error flows look between the
|
||||
// Windows code and the OpenSSL-calling code, drain the queue
|
||||
// whenever an Exception is desired, and report the exception
|
||||
// related to the last value in the queue.
|
||||
bool isAllocFailure;
|
||||
ulong error = ErrGetErrorAlloc(out isAllocFailure);
|
||||
ulong lastRead = error;
|
||||
bool lastIsAllocFailure = isAllocFailure;
|
||||
|
||||
// 0 (there's no named constant) is only returned when the calls
|
||||
// to ERR_get_error exceed the calls to ERR_set_error.
|
||||
while (lastRead != 0)
|
||||
{
|
||||
error = lastRead;
|
||||
isAllocFailure = lastIsAllocFailure;
|
||||
|
||||
lastRead = ErrGetErrorAlloc(out lastIsAllocFailure);
|
||||
}
|
||||
|
||||
// If we're in an error flow which results in an Exception, but
|
||||
// no calls to ERR_set_error were made, throw the unadorned
|
||||
// CryptographicException.
|
||||
if (error == 0)
|
||||
{
|
||||
return new CryptographicException();
|
||||
}
|
||||
|
||||
if (isAllocFailure)
|
||||
{
|
||||
return new OutOfMemoryException();
|
||||
}
|
||||
|
||||
// Even though ErrGetError returns ulong (C++ unsigned long), we
|
||||
// really only expect error codes in the UInt32 range
|
||||
Debug.Assert(error <= uint.MaxValue, "ErrGetError should only return error codes in the UInt32 range.");
|
||||
|
||||
// If there was an error code, and it wasn't something handled specially,
|
||||
// use the OpenSSL error string as the message to a CryptographicException.
|
||||
return new OpenSslCryptographicException(unchecked((int)error), ErrErrorStringN(error));
|
||||
}
|
||||
|
||||
private sealed class OpenSslCryptographicException : CryptographicException
|
||||
{
|
||||
internal OpenSslCryptographicException(int errorCode, string message)
|
||||
: base(message)
|
||||
{
|
||||
HResult = errorCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ECDsaTest.SafeHandles;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Crypto
|
||||
{
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByExplicitParameters")]
|
||||
internal static extern SafeEcKeyHandle EcKeyCreateByExplicitParameters(
|
||||
ECCurve.ECCurveType curveType,
|
||||
byte[] qx, int qxLength,
|
||||
byte[] qy, int qyLength,
|
||||
byte[] d, int dLength,
|
||||
byte[] p, int pLength,
|
||||
byte[] a, int aLength,
|
||||
byte[] b, int bLength,
|
||||
byte[] gx, int gxLength,
|
||||
byte[] gy, int gyLength,
|
||||
byte[] order, int nLength,
|
||||
byte[] cofactor, int cofactorLength,
|
||||
byte[] seed, int seedLength);
|
||||
|
||||
internal static SafeEcKeyHandle EcKeyCreateByExplicitCurve(ECCurve curve)
|
||||
{
|
||||
byte[] p;
|
||||
if (curve.IsPrime)
|
||||
{
|
||||
p = curve.Prime;
|
||||
}
|
||||
else if (curve.IsCharacteristic2)
|
||||
{
|
||||
p = curve.Polynomial;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException(string.Format("The specified curve '{0}' or its parameters are not valid for this platform.", curve.CurveType.ToString()));
|
||||
}
|
||||
|
||||
SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByExplicitParameters(
|
||||
curve.CurveType,
|
||||
null, 0,
|
||||
null, 0,
|
||||
null, 0,
|
||||
p, p.Length,
|
||||
curve.A, curve.A.Length,
|
||||
curve.B, curve.B.Length,
|
||||
curve.G.X, curve.G.X.Length,
|
||||
curve.G.Y, curve.G.Y.Length,
|
||||
curve.Order, curve.Order.Length,
|
||||
curve.Cofactor, curve.Cofactor.Length,
|
||||
curve.Seed, curve.Seed == null ? 0 : curve.Seed.Length);
|
||||
|
||||
if (key == null || key.IsInvalid)
|
||||
{
|
||||
if (key != null)
|
||||
key.Dispose();
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
|
||||
// EcKeyCreateByExplicitParameters may have polluted the error queue, but key was good in the end.
|
||||
// Clean up the error queue.
|
||||
Interop.Crypto.ErrClearError();
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using ECDsaTest;
|
||||
using ECDsaTest.SafeHandles;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Crypto
|
||||
{
|
||||
internal static bool EcDsaSignEx(ReadOnlySpan<byte> dgst, Span<byte> sig, [In, Out] ref int siglen,
|
||||
ReadOnlySpan<byte> kinv, ReadOnlySpan<byte> rp, SafeEcKeyHandle ecKey) => EcDsaSignEx(
|
||||
ref MemoryMarshal.GetReference(dgst), dgst.Length, ref MemoryMarshal.GetReference(sig), ref siglen,
|
||||
ref MemoryMarshal.GetReference(kinv), kinv.Length, ref MemoryMarshal.GetReference(rp), rp.Length, ecKey);
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSignEx")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool EcDsaSignEx(ref byte dgst, int dlen, ref byte sig, [In, Out] ref int siglen,
|
||||
ref byte kinv, int kinvlen, ref byte rp, int rplen, SafeEcKeyHandle ecKey);
|
||||
|
||||
// returns the maximum length of a DER encoded ECDSA signature created with this key.
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSize")]
|
||||
private static extern int CryptoNative_EcDsaSize(SafeEcKeyHandle ecKey);
|
||||
|
||||
internal static int EcDsaSize(SafeEcKeyHandle ecKey)
|
||||
{
|
||||
int ret = CryptoNative_EcDsaSize(ecKey);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
throw CreateOpenSslCryptographicException();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
internal static PspParameter EcPspParameter(SafeEcKeyHandle key, ReadOnlySpan<byte> sha256, int len)
|
||||
{
|
||||
SafeBignumHandle kinv_bn, rp_bn;
|
||||
int kinvlen, rplen;
|
||||
|
||||
bool refAdded = false;
|
||||
try
|
||||
{
|
||||
key.DangerousAddRef(ref refAdded);
|
||||
var ret = EcPspParameter(key, ref MemoryMarshal.GetReference(sha256), len, out kinv_bn, out kinvlen,
|
||||
out rp_bn, out rplen);
|
||||
if (!ret)
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
|
||||
using (kinv_bn)
|
||||
using (rp_bn)
|
||||
{
|
||||
var par = new PspParameter
|
||||
{
|
||||
Kinv = Crypto.ExtractBignum(kinv_bn, kinvlen),
|
||||
Rp = Crypto.ExtractBignum(rp_bn, rplen)
|
||||
};
|
||||
return par;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (refAdded)
|
||||
key.DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcPspParameter")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool EcPspParameter(SafeEcKeyHandle ecKey, ref byte sha256, int len, out SafeBignumHandle kinv,
|
||||
out int kinvlen, out SafeBignumHandle rp, out int rplen);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Crypto
|
||||
{
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyDestroy")]
|
||||
internal static extern void EcKeyDestroy(IntPtr a);
|
||||
|
||||
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyUpRef")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool EcKeyUpRef(IntPtr r);
|
||||
}
|
||||
}
|
|
@ -762,7 +762,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD0(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size, bool generate_trash)
|
||||
{
|
||||
KIRK_CMD1_HEADER header = Utils.AsRef<KIRK_CMD1_HEADER>(outbuff);
|
||||
KIRK_CMD1_HEADER header = MemoryMarshal.AsRef<KIRK_CMD1_HEADER>(outbuff);
|
||||
// header_keys keys = Utils.AsRef<header_keys>(outbuff);
|
||||
int chk_size;
|
||||
Aes k1;
|
||||
|
@ -817,7 +817,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD1(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
|
||||
{
|
||||
KIRK_CMD1_HEADER header = Utils.AsRef<KIRK_CMD1_HEADER>(inbuff);
|
||||
KIRK_CMD1_HEADER header = MemoryMarshal.AsRef<KIRK_CMD1_HEADER>(inbuff);
|
||||
// header_keys keys; //0-15 AES key, 16-31 CMAC key
|
||||
Aes k1;
|
||||
|
||||
|
@ -831,7 +831,7 @@ namespace PspCrypto
|
|||
|
||||
if (header.ecdsa_hash == 1)
|
||||
{
|
||||
KIRK_CMD1_ECDSA_HEADER eheader = Utils.AsRef<KIRK_CMD1_ECDSA_HEADER>(inbuff);
|
||||
KIRK_CMD1_ECDSA_HEADER eheader = MemoryMarshal.AsRef<KIRK_CMD1_ECDSA_HEADER>(inbuff);
|
||||
var curve = ECDsaHelper.SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b1, KeyVault.ec_N1, KeyVault.Gx1,
|
||||
KeyVault.Gy1);
|
||||
unsafe
|
||||
|
@ -867,7 +867,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD4(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
|
||||
{
|
||||
KIRK_AES128CBC_HEADER header = Utils.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
|
||||
KIRK_AES128CBC_HEADER header = MemoryMarshal.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
|
||||
byte[] key;
|
||||
Aes aes;
|
||||
|
||||
|
@ -892,7 +892,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD7(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
|
||||
{
|
||||
KIRK_AES128CBC_HEADER header = Utils.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
|
||||
KIRK_AES128CBC_HEADER header = MemoryMarshal.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
|
||||
byte[] key;
|
||||
Aes aes;
|
||||
|
||||
|
@ -915,7 +915,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD10(ReadOnlySpan<byte> inbuff, int insize)
|
||||
{
|
||||
KIRK_CMD1_HEADER header = Utils.AsRef<KIRK_CMD1_HEADER>(inbuff);
|
||||
KIRK_CMD1_HEADER header = MemoryMarshal.AsRef<KIRK_CMD1_HEADER>(inbuff);
|
||||
// header_keys keys; //0-15 AES key, 16-31 CMAC key
|
||||
Span<byte> cmac_header_hash = stackalloc byte[16];
|
||||
Span<byte> cmac_data_hash = stackalloc byte[16];
|
||||
|
@ -951,7 +951,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD11(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
|
||||
{
|
||||
KIRK_SHA1_HEADER header = Utils.AsRef<KIRK_SHA1_HEADER>(inbuff);
|
||||
KIRK_SHA1_HEADER header = MemoryMarshal.AsRef<KIRK_SHA1_HEADER>(inbuff);
|
||||
if (!is_kirk_initialized) return KIRK_NOT_INITIALIZED;
|
||||
if (header.data_size == 0 || size == 0) return KIRK_DATA_SIZE_ZERO;
|
||||
|
||||
|
@ -1044,7 +1044,7 @@ namespace PspCrypto
|
|||
static int kirk_CMD16(Span<byte> outbuff, int outsize, ReadOnlySpan<byte> inbuff, int insize)
|
||||
{
|
||||
byte[] dec_private = new byte[0x20];
|
||||
KIRK_CMD16_BUFFER signbuf = Utils.AsRef<KIRK_CMD16_BUFFER>(inbuff);
|
||||
KIRK_CMD16_BUFFER signbuf = MemoryMarshal.AsRef<KIRK_CMD16_BUFFER>(inbuff);
|
||||
//ECDSA_SIG sig = BufferToStruct<ECDSA_SIG>(outbuff);
|
||||
|
||||
if (insize != 0x34) return KIRK_INVALID_SIZE;
|
||||
|
@ -1071,7 +1071,7 @@ namespace PspCrypto
|
|||
|
||||
static int kirk_CMD17(ReadOnlySpan<byte> inbuff, int insize)
|
||||
{
|
||||
KIRK_CMD17_BUFFER sig = Utils.AsRef<KIRK_CMD17_BUFFER>(inbuff);
|
||||
KIRK_CMD17_BUFFER sig = MemoryMarshal.AsRef<KIRK_CMD17_BUFFER>(inbuff);
|
||||
|
||||
if (insize != 0x64) return KIRK_INVALID_SIZE;
|
||||
|
||||
|
@ -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>
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace PspCrypto
|
||||
{
|
||||
public class RijndaelMod : Aes
|
||||
{
|
||||
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
|
||||
{
|
||||
return CreateTransform(rgbKey, encrypting: false);
|
||||
}
|
||||
|
||||
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
|
||||
{
|
||||
return CreateTransform(rgbKey, encrypting: true);
|
||||
}
|
||||
|
||||
public override void GenerateIV()
|
||||
{
|
||||
}
|
||||
|
||||
public override void GenerateKey()
|
||||
{
|
||||
byte[] key = new byte[KeySize / BitsPerByte];
|
||||
RandomNumberGenerator.Fill(key);
|
||||
Key = key;
|
||||
}
|
||||
|
||||
private ICryptoTransform CreateTransform(byte[] rgbKey, bool encrypting)
|
||||
{
|
||||
if (rgbKey == null)
|
||||
throw new ArgumentNullException(nameof(rgbKey));
|
||||
return new RijndaelModTransform(rgbKey, BlockSizeValue, encrypting);
|
||||
}
|
||||
|
||||
private const int BitsPerByte = 8;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue