Update to use LibChovy

This commit is contained in:
Li 2023-04-19 21:58:07 +12:00
parent 537b1b1229
commit e15f1897a7
24 changed files with 632 additions and 133 deletions

View File

@ -9,7 +9,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\GameBuilder\GameBuilder.csproj" />
<ProjectReference Include="..\LibChovy\LibChovy.csproj" />
</ItemGroup>

View File

@ -3,6 +3,7 @@ using GameBuilder.Pops;
using GameBuilder.Psp;
using GameBuilder.VersionKey;
using PspCrypto;
using LibChovy;
namespace ChovySign_CLI
{
@ -12,10 +13,12 @@ namespace ChovySign_CLI
private static List<string> parameters = new List<string>();
private static string[] discs;
private static bool pspCompress = false;
private static bool devKit = false;
private static string? popsDiscName;
private static string? popsIcon0File;
private static string? popsPic0File;
private static PbpMode? pbpMode = null;
private static NpDrmRif? rifFile = null;
private static NpDrmInfo? drmInfo = null;
enum PbpMode
{
@ -32,7 +35,8 @@ namespace ChovySign_CLI
VERSIONKEY = 3,
VERSIONKEY_EXTRACT = 4,
VERSIONKEY_GENERATOR = 5,
POPS_INFO = 6
POPS_INFO = 6,
RIF = 7
}
public static int Error(string errorMsg, int ret)
{
@ -92,13 +96,18 @@ namespace ChovySign_CLI
drmInfo = ActRifMethod.GetVersionKey(File.ReadAllBytes(parameters[0]), File.ReadAllBytes(parameters[1]), StringToByteArray(parameters[2]), int.Parse(parameters[3]));
break;
case ArgumentParsingMode.POPS_INFO:
if (parameters.Count < 2) return Error("--pops-info takes at least 2 arguments ("+parameters.Count+" given)", 4);
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];
popsIcon0File = parameters[1];
if (parameters.Count > 1)
popsIcon0File = parameters[1];
if (parameters.Count > 2)
popsPic0File = parameters[2];
break;
case ArgumentParsingMode.RIF:
if (parameters.Count != 1) return Error("--rif expects only 1 argument,", 4);
rifFile = new NpDrmRif(File.ReadAllBytes(parameters[0]));
break;
}
mode = ArgumentParsingMode.ARG;
@ -112,8 +121,10 @@ namespace ChovySign_CLI
{
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] [pic1.png] (optional)");
Console.WriteLine("--pops-info [game title] [icon0.png] (optional) [pic1.png] (optional)");
Console.WriteLine("--psp [umd.iso] [compress; true/false] (optional)");
Console.WriteLine("--rif [GAME.RIF]");
Console.WriteLine("--devkit (Use 000000000000 account id)");
Console.WriteLine("--vkey [versionkey] [contentid] [key_index]");
Console.WriteLine("--vkey-extract [eboot.pbp]");
Console.WriteLine("--vkey-gen [act.dat] [license.rif] [console_id] [key_index]");
@ -169,6 +180,16 @@ namespace ChovySign_CLI
if (drmInfo is not null)
return Error("versionkey is already set", 3);
break;
case "--rif":
mode = ArgumentParsingMode.RIF;
if (rifFile is not null)
return Error("rif is already set", 3);
break;
case "--devkit":
devKit = true;
break;
default:
return Error("Unknown argument: " + arg, 1);
@ -180,6 +201,7 @@ namespace ChovySign_CLI
case ArgumentParsingMode.PSP_UMD:
case ArgumentParsingMode.POPS_DISC:
case ArgumentParsingMode.POPS_INFO:
case ArgumentParsingMode.RIF:
default:
parameters.Add(arg);
break;
@ -199,73 +221,38 @@ namespace ChovySign_CLI
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 (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);
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)
{
PopsParameters popsParameters = new PopsParameters(drmInfo, rifFile);
foreach (string disc in discs)
popsParameters.AddCd(disc);
if(popsDiscName is not null)
popsParameters.Name = popsDiscName;
if(File.Exists(popsIcon0File))
popsParameters.Icon0 = File.ReadAllBytes(popsIcon0File);
DiscInfo[] discInfs = new DiscInfo[discs.Length];
for (int i = 0; i < discInfs.Length; i++)
discInfs[i] = new DiscInfo(discs[i], popsDiscName);
popsParameters.Account.Devkit = devKit;
Sfo psfo = new Sfo();
psfo.AddKey("BOOTABLE", 1, 4);
psfo.AddKey("CATEGORY", "ME", 4);
psfo.AddKey("DISC_ID", discInfs.First().DiscId, 16);
psfo.AddKey("DISC_VERSION", "1.00", 8);
psfo.AddKey("LICENSE", "Chovy-Sign is licensed under the GPLv3, POPS stuff was done by Li and SquallATF.", 512);
psfo.AddKey("PARENTAL_LEVEL", 0, 4);
psfo.AddKey("PSP_SYSTEM_VER", "6.60", 8);
psfo.AddKey("REGION", 32768, 4);
psfo.AddKey("TITLE", popsDiscName, 128);
byte[] sfo = psfo.WriteSfo();
if (discs.Length == 1)
{
using (PbpBuilder pbpBuilder = new PbpBuilder(sfo, File.ReadAllBytes(popsIcon0File), null, (popsPic0File is not null) ? File.ReadAllBytes(popsPic0File) : null, LibChovy.Resources.PIC1, null, new PsIsoImg(drmInfo, discInfs.First()), 0))
{
pbpBuilder.RegisterCallback(onProgress);
pbpBuilder.CreatePsarAndPbp();
pbpBuilder.PbpStream.Seek(0x00, SeekOrigin.Begin);
byte[] ebootsig = new byte[0x200];
SceNpDrm.KsceNpDrmEbootSigGenPs1(pbpBuilder.PbpStream, ebootsig, 0x3674000);
File.WriteAllBytes("__sce_ebootpbp", ebootsig.ToArray());
pbpBuilder.WritePbpToFile("EBOOT.PBP");
}
}
else
{
using (PbpBuilder pbpBuilder = new PbpBuilder(sfo, File.ReadAllBytes(popsIcon0File), null, (popsPic0File is not null) ? File.ReadAllBytes(popsPic0File) : null, Resources.PIC1, null, new PsTitleImg(drmInfo, discInfs), 0))
{
pbpBuilder.RegisterCallback(onProgress);
pbpBuilder.CreatePsarAndPbp();
pbpBuilder.PbpStream.Seek(0x00, SeekOrigin.Begin);
byte[] ebootsig = new byte[0x200];
pbpBuilder.WritePbpToFile("EBOOT.PBP");
SceNpDrm.KsceNpDrmEbootSigGenPs1(pbpBuilder.PbpStream, ebootsig, 0x3674000);
File.WriteAllBytes("__sce_ebootpbp", ebootsig.ToArray());
}
}
csign.Go(popsParameters);
}
else if(pbpMode == PbpMode.PSP)
{
using (UmdInfo umd = new UmdInfo(discs.First()))
{
using (PbpBuilder pbpBuilder = new PbpBuilder(umd.DataFiles["PARAM.SFO"], umd.DataFiles["ICON0.PNG"], umd.DataFiles["ICON1.PMF"], umd.DataFiles["PIC0.PNG"], umd.DataFiles["PIC1.PNG"], umd.DataFiles["SND0.AT3"], new NpUmdImg(drmInfo, umd, pspCompress), 1))
{
pbpBuilder.RegisterCallback(onProgress);
pbpBuilder.CreatePsarAndPbp();
pbpBuilder.PbpStream.Seek(0x00, SeekOrigin.Begin);
byte[] ebootsig = new byte[0x200];
SceNpDrm.KsceNpDrmEbootSigGenPsp(pbpBuilder.PbpStream, ebootsig, 0x3674000);
File.WriteAllBytes("__sce_ebootpbp", ebootsig.ToArray());
pbpBuilder.WritePbpToFile("EBOOT.PBP");
}
}
PspParameters pspParameters = new PspParameters(drmInfo, rifFile);
pspParameters.Account.Devkit = devKit;
pspParameters.Compress = pspCompress;
pspParameters.Umd = new UmdInfo(discs.First());
csign.Go(pspParameters);
}
return 0;
}

View File

@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<History>True|2023-04-17T12:00:51.4131559Z;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>
<History>True|2023-04-19T09:53:45.1116925Z;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>

View File

@ -93,7 +93,7 @@ namespace GameBuilder.Cue
int fileSectorSz = Convert.ToInt32(track.binFileSz / track.SectorSz);
int endSector = Convert.ToInt32(startSector + fileSectorSz);
// check if another track begins (thus ending this one)
// find first track to start after this one ..
for (int i = 0; i < tracks.Length; i++)
{
CueTrack? cTrack = tracks[i];

View File

@ -1,6 +1,7 @@
using DiscUtils.Iso9660Ps1;
using DiscUtils.Streams;
using GameBuilder.Cue;
using Li.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
@ -12,8 +13,8 @@ namespace GameBuilder.Pops
public class DiscInfo
{
private string cueFile;
private string discName;
private string discId;
private string? discName;
private string? discId;
public string CueFile
{
@ -34,7 +35,12 @@ namespace GameBuilder.Pops
{
get
{
return discName;
if (discName is null) return "";
else return discName;
}
set
{
discName = value;
}
}
@ -46,16 +52,18 @@ namespace GameBuilder.Pops
}
}
public DiscInfo(string cueFile, string discName)
public DiscInfo(string cueFile)
{
this.cueFile = cueFile;
this.discName = discName;
using(CueReader cue = new CueReader(cueFile))
{
using (CueStream cueStream = cue.OpenTrack(cue.FirstDataTrackNo))
using (CueStream binStream = cue.OpenTrack(cue.FirstDataTrackNo))
{
using (CDReader cdReader = new CDReader(cueStream, false, true, cue.GetTrackNumber(cue.FirstDataTrackNo).SectorSz))
StreamUtil binUtil = new StreamUtil(binStream);
// Get disc id from SYSTEM.CNF
using (CDReader cdReader = new CDReader(binStream, false, true, cue.GetTrackNumber(cue.FirstDataTrackNo).SectorSz))
{
using (SparseStream systemCnfStream = cdReader.OpenFile("SYSTEM.CNF", FileMode.Open))
{
@ -74,7 +82,11 @@ namespace GameBuilder.Pops
}
}
}
}
binStream.Seek(0x9340, SeekOrigin.Begin);
discName = binUtil.ReadCDStr(0x20);
}
}

View File

@ -30,6 +30,12 @@ namespace GameBuilder.Pops
this.compressors = new DiscCompressor[MAX_DISCS];
this.discs = discs;
// ensure disc name is the same for all discs..
string discName = discs.First().DiscName;
for (int i = 0; i < discs.Length; i++)
discs[i].DiscName = discName;
// create compressor objects.
for (int i = 0; i < compressors.Length; i++)
{
if (i > (discs.Length - 1))

View File

@ -0,0 +1,50 @@
using Ionic.Zlib;
using Org.BouncyCastle.Asn1.Mozilla;
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder.Psp
{
public class NpDrmRif
{
public NpDrmRif(string zRif)
{
Rif = ZlibStream.UncompressBuffer(Convert.FromBase64String(zRif));
}
public NpDrmRif(byte[] rifData)
{
Rif = rifData;
}
public byte[] Rif;
public string ZRif
{
get
{
return Convert.ToBase64String(ZlibStream.CompressBuffer(Rif));
}
}
public UInt64 AccountId
{
get
{
return BitConverter.ToUInt64(Rif, 0x8);
}
}
public string ContentId
{
get
{
return Encoding.UTF8.GetString(Rif, 0x10, 0x24);
}
}
}
}

View File

@ -42,7 +42,7 @@ namespace GameBuilder.Psp
}
private void patchSfo()
public void PatchSfo()
{
Sfo sfoKeys = Sfo.ReadSfo(umdImage.DataFiles["PARAM.SFO"]);
if ((sfoKeys["CATEGORY"] as String) == "UG") // "UMD Game"
@ -74,7 +74,7 @@ namespace GameBuilder.Psp
public override void CreatePsar()
{
patchSfo();
PatchSfo();
createNpUmdTbl();
byte[] tbl = encryptTable();
this.dataKey = hashBlock(tbl);
@ -89,7 +89,7 @@ namespace GameBuilder.Psp
isoData.CopyTo(Psar);
}
public byte[] signParamSfo(byte[] paramSfo)
private byte[] signParamSfo(byte[] paramSfo)
{
int paramSfoLen = paramSfo.Length;
byte[] contentIdBytes = Encoding.UTF8.GetBytes(DrmInfo.ContentId);

View File

@ -17,6 +17,10 @@ namespace Li.Utilities
{
return Encoding.UTF8.GetString(ReadBytes(len));
}
public string ReadCDStr(int len)
{
return ReadStrLen(len).Trim(' ');
}
public string ReadCStr()
{
using (MemoryStream ms = new MemoryStream())

50
LibChovy/ArtDownloader.cs Normal file
View File

@ -0,0 +1,50 @@
using GameBuilder.Pops;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibChovy
{
internal class ArtDownloader
{
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)
{
string discIdDash = game.DiscId.Substring(0, 4) + "-" + game.DiscId.Substring(4, 5);
return await DownloadCover(discIdDash);
}
public static async Task<byte[]> DownloadCover(string gameId)
{
try
{
byte[] data = await httpClient.GetByteArrayAsync(coverApi + gameId + ".jpg");
using (Image coverImage = Image.Load(data))
{
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.Resize(58, 58));
psnBorder.Mutate(x => x.DrawImage(coverImage, new Point(13, 11), 1.0f));
using (MemoryStream png = new MemoryStream())
{
await psnBorder.SaveAsPngAsync(png);
return png.ToArray();
}
}
}
}
catch (Exception e) { Console.Error.WriteLine(e.Message); Console.Error.WriteLine(e.StackTrace); return Resources.ICON0; }
}
}
}

View File

@ -1,30 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GameBuilder.Pops;
using GameBuilder.Psp;
using Li.Progress;
using PspCrypto;
using Vita.PsvImgTools;
namespace LibChovy
{
public class ChovySign
public class ChovySign : ProgressTracker
{
public void createPOPS()
private void onProgress(ProgressInfo inf)
{
updateProgress(inf.Done, inf.Remain, inf.CurrentProcess);
}
private void createPSP(PspParameters parameters)
{
using(NpUmdImg img = new NpUmdImg(parameters.DrmInfo, parameters.Umd, parameters.Compress))
{
img.PatchSfo();
using (PbpBuilder pbpBuilder = new PbpBuilder(parameters.Umd.DataFiles["PARAM.SFO"], parameters.Umd.DataFiles["ICON0.PNG"], parameters.Umd.DataFiles["ICON1.PMF"], parameters.Umd.DataFiles["PIC0.PNG"], parameters.Umd.DataFiles["PIC1.PNG"], parameters.Umd.DataFiles["SND0.AT3"], img, 1))
{
pbpBuilder.RegisterCallback(onProgress);
pbpBuilder.CreatePsarAndPbp();
pbpBuilder.PbpStream.Seek(0x00, SeekOrigin.Begin);
byte[] ebootsig = new byte[0x200];
SceNpDrm.KsceNpDrmEbootSigGenPsp(pbpBuilder.PbpStream, ebootsig, parameters.FirmwareVersion);
if (!parameters.CreatePsvImg)
{
File.WriteAllBytes(Path.Combine(parameters.OutputFolder, "__sce_ebootpbp"), ebootsig.ToArray());
pbpBuilder.WritePbpToFile(Path.Combine(parameters.OutputFolder, "EBOOT.PBP"));
}
else
{
createPsvImg(parameters.OutputFolder, parameters.Umd.DiscId, parameters.Umd.DataFiles["PARAM.SFO"], parameters.Umd.DataFiles["ICON0.PNG"], pbpBuilder, parameters.DrmRif, ebootsig, parameters.Account.CmaKey);
}
}
}
}
private void createPOPS(PopsParameters parameters)
{
}
public void createPOPSMultiDisc()
{
Sfo psfo = new Sfo();
psfo.AddKey("BOOTABLE", 1, 4);
psfo.AddKey("CATEGORY", "ME", 4);
psfo.AddKey("DISC_ID", parameters.FirstDisc.DiscId, 16);
psfo.AddKey("DISC_VERSION", "1.00", 8);
psfo.AddKey("LICENSE", "Chovy-Sign is licensed under the GPLv3, And was made possible by SquallATF and Li.", 512);
psfo.AddKey("PARENTAL_LEVEL", 0, 4);
psfo.AddKey("PSP_SYSTEM_VER", "6.61", 8);
psfo.AddKey("REGION", 32768, 4);
psfo.AddKey("TITLE", parameters.Name, 128);
byte[] sfo = psfo.WriteSfo();
PopsImg img;
if (parameters.MultiDisc)
img = new PsTitleImg(parameters.DrmInfo, parameters.Discs);
else
img = new PsIsoImg(parameters.DrmInfo, parameters.FirstDisc);
using (PbpBuilder pbpBuilder = new PbpBuilder(sfo, parameters.Icon0, null, parameters.Pic0, parameters.Pic1, null, img, 0))
{
pbpBuilder.RegisterCallback(onProgress);
pbpBuilder.CreatePsarAndPbp();
pbpBuilder.PbpStream.Seek(0x00, SeekOrigin.Begin);
byte[] ebootsig = new byte[0x200];
SceNpDrm.KsceNpDrmEbootSigGenPs1(pbpBuilder.PbpStream, ebootsig, parameters.FirmwareVersion);
if (!parameters.CreatePsvImg)
{
File.WriteAllBytes(Path.Combine(parameters.OutputFolder, "__sce_ebootpbp"), ebootsig.ToArray());
pbpBuilder.WritePbpToFile(Path.Combine(parameters.OutputFolder, "EBOOT.PBP"));
}
else
{
createPsvImg(parameters.OutputFolder, parameters.FirstDisc.DiscId, sfo, parameters.Icon0, pbpBuilder, parameters.DrmRif, ebootsig, parameters.Account.CmaKey);
}
}
}
public void createPSP()
private void createPsvImg(string outputFolder, string discId,
byte[] sfo, byte[] icon0,
PbpBuilder pbp, NpDrmRif license, byte[] sig,
byte[] cmaKey)
{
// create GAME.PSVIMG
pbp.PbpStream.Seek(0x00, SeekOrigin.Begin);
string gameFolder = Path.Combine(outputFolder, "game");
string licenseFolder = Path.Combine(outputFolder, "license");
string sceSysFolder = Path.Combine(outputFolder, "sce_sys");
if (!Directory.Exists(gameFolder)) Directory.CreateDirectory(gameFolder);
if (!Directory.Exists(licenseFolder)) Directory.CreateDirectory(licenseFolder);
if (!Directory.Exists(sceSysFolder)) Directory.CreateDirectory(sceSysFolder);
using (FileStream gamePsvimg = File.Open(Path.Combine(gameFolder, "game.psvimg"), FileMode.Create, FileAccess.ReadWrite))
{
PSVIMGBuilder psvImg = new PSVIMGBuilder(gamePsvimg, cmaKey);
psvImg.RegisterCallback(onProgress);
psvImg.AddFile(pbp.PbpStream, "ux0:pspemu/temp/game/PSP/GAME/" + discId, "/EBOOT.PBP");
psvImg.AddFile(sig, "ux0:pspemu/temp/game/PSP/GAME/" + discId, "/__sce_ebootpbp");
long contentSize = psvImg.Finish();
// create GAME.PSVMD
using (FileStream gamePsvmd = File.Open(Path.Combine(gameFolder, "game.psvmd"), FileMode.Create, FileAccess.ReadWrite))
PSVMDBuilder.CreatePsvmd(gamePsvmd, gamePsvimg, contentSize, "game", cmaKey);
}
// create LICENSE.PSVIMG
using (FileStream gamePsvimg = File.Open(Path.Combine(licenseFolder, "license.psvimg"), FileMode.Create, FileAccess.ReadWrite))
{
PSVIMGBuilder psvImg = new PSVIMGBuilder(gamePsvimg, cmaKey);
psvImg.RegisterCallback(onProgress);
psvImg.AddFile(license.Rif, "ux0:pspemu/temp/game/PSP/LICENSE", "/" + license.ContentId + ".rif");
long contentSize = psvImg.Finish();
// create LICENSE.PSVMD
using (FileStream gamePsvmd = File.Open(Path.Combine(licenseFolder, "license.psvmd"), FileMode.Create, FileAccess.ReadWrite))
PSVMDBuilder.CreatePsvmd(gamePsvmd, gamePsvimg, contentSize, "license", cmaKey);
}
// write SCE_SYS
File.WriteAllBytes(Path.Combine(sceSysFolder, "param.sfo"), sfo);
File.WriteAllBytes(Path.Combine(sceSysFolder, "icon0.png"), icon0);
}
public void Go()
public void Go(ChovySignParameters parameters)
{
SceNpDrm.Aid = parameters.DrmRif.AccountId;
if (!Directory.Exists(parameters.OutputFolder))
Directory.CreateDirectory(parameters.OutputFolder);
if (parameters.Type == ChovyTypes.PSP)
createPSP((PspParameters)parameters);
else
createPOPS((PopsParameters)parameters);
}
}
}

View File

@ -1,16 +1,48 @@
using System;
using GameBuilder.Psp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Vita.ContentManager;
namespace LibChovy
{
public abstract class ChovySignParameters
{
public ChovySignParameters(NpDrmInfo drmInfo, NpDrmRif rif)
{
this.DrmInfo = drmInfo;
this.DrmRif = rif;
this.Account = new Account(DrmRif.AccountId);
this.CreatePsvImg = true;
this.FirmwareVersion = 0x3600000;
}
public int FirmwareVersion;
public bool CreatePsvImg;
public NpDrmInfo DrmInfo;
public NpDrmRif DrmRif;
public Account Account;
public ChovyTypes Type;
public bool MakePSVIMG;
public bool ForceDevkitAid;
protected string? outputFolderOverride;
protected virtual string outputFolder
{
get
{
if (outputFolderOverride is null) return Path.Combine(SettingsReader.PspFolder, Account.AccountIdStr);
return outputFolderOverride;
}
set
{
outputFolderOverride = value;
}
}
public abstract string OutputFolder { get; }
}
}

View File

@ -1,14 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GameBuilder\GameBuilder.csproj" />
<ProjectReference Include="..\Vita\Vita.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -1,27 +1,148 @@
using System;
using GameBuilder.Pops;
using GameBuilder.Psp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Vita.ContentManager;
namespace LibChovy
{
public class PopsParameters : ChovySignParameters
{
public PopsParameters(NpDrmInfo drmInfo, NpDrmRif rif) : base(drmInfo, rif)
{
Type = ChovyTypes.POPS;
discList = new List<DiscInfo>();
}
private string? nameOverride;
private List<DiscInfo> discList;
//public int SetSDKVersion
public string[] DiscList;
public string DiscName;
public Bitmap? Icon0Override;
public Bitmap? Pic0Override;
public Bitmap? Pic1Override;
private byte[]? pic0;
private byte[]? pic1;
private byte[]? icon0;
public DiscInfo FirstDisc
{
get
{
return Discs.First();
}
}
protected override string outputFolder
{
get
{
if (outputFolderOverride is null) return Path.Combine(SettingsReader.Ps1Folder, Account.AccountIdStr);
return outputFolderOverride;
}
set
{
outputFolderOverride = value;
}
}
public override string OutputFolder
{
get
{
return Path.Combine(outputFolder, FirstDisc.DiscId);
}
}
public byte[] Pic0
{
get
{
if (pic0 is null) return Resources.PIC0;
else return pic0;
}
set
{
pic0 = value;
}
}
public byte[] Icon0
{
get
{
if (icon0 is null)
{
byte[] coverImg = ArtDownloader.DownloadCover(FirstDisc).Result;
icon0 = coverImg;
return coverImg;
}
else
{
return icon0;
}
}
set
{
icon0 = value;
}
}
public byte[] Pic1
{
get
{
if (pic1 is null) return Resources.PIC1;
else return pic1;
}
}
public void AddCd(string cd)
{
DiscInfo disc = new DiscInfo(cd);
if (nameOverride is not null) disc.DiscName = nameOverride;
else discList.Add(disc);
}
public void RemoveCd(string cd)
{
for (int i = 0; i < discList.Count; i++)
{
if (discList[i].CueFile == cd)
{
discList.RemoveAt(i);
break;
}
}
}
public DiscInfo[] Discs
{
get
{
return discList.ToArray();
}
}
public string Name
{
get
{
if (nameOverride is null)
{
if (FirstDisc.DiscName == "") return FirstDisc.DiscId;
else return FirstDisc.DiscName;
}
else return nameOverride;
}
set
{
for (int i = 0; i < discList.Count; i++)
discList[i].DiscName = value;
nameOverride = value;
}
}
public bool MultiDisc
{
get
{
return DiscList.Length > 1;
return Discs.Length > 1;
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using GameBuilder.Psp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -8,9 +9,19 @@ namespace LibChovy
{
public class PspParameters : ChovySignParameters
{
public PspParameters()
public PspParameters(NpDrmInfo drmInfo, NpDrmRif rif) : base(drmInfo, rif)
{
Type = ChovyTypes.PSP;
}
public bool Compress;
public UmdInfo Umd;
public override string OutputFolder
{
get
{
return Path.Combine(outputFolder, Umd.DiscId);
}
}
}
}

View File

@ -61,22 +61,32 @@ namespace LibChovy {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static System.Drawing.Bitmap PIC0 {
public static byte[] ICON0 {
get {
object obj = ResourceManager.GetObject("PIC0", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
object obj = ResourceManager.GetObject("ICON0", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static System.Drawing.Bitmap PIC1 {
public static byte[] PIC0 {
get {
object obj = ResourceManager.GetObject("PIC0", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] PIC1 {
get {
object obj = ResourceManager.GetObject("PIC1", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
return ((byte[])(obj));
}
}
}

View File

@ -118,10 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="ICON0" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\ICON0.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="PIC0" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\PIC0.PNG;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<value>Resources\PIC0.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="PIC1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\PIC1.PNG;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<value>Resources\PIC1.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,9 +1,6 @@
using CommunityToolkit.HighPerformance;
using Ionic.Zlib;
using GameBuilder.Pops;
using GameBuilder.Psp;
using PspCrypto;
using PsvImage;
using System;
using System.Buffers.Binary;
using System.IO;
@ -12,6 +9,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using Vita.ContentManager;
namespace PbpResign
{
@ -1185,7 +1183,7 @@ namespace PbpResign
}
var aidData = Convert.FromHexString(aid);
SceNpDrm.Aid = BitConverter.ToUInt64(aidData);
var cmaKey = CmaKeys.GenerateKey(aid);
var cmaKey = KeyGenerator.GenerateKey(aidData);
Console.WriteLine(Convert.ToHexString(cmaKey));
var srcPbp = args[2];

View File

@ -1039,7 +1039,7 @@ namespace PspCrypto
return -0x7f78ffff;
}
Span<byte> secureTick = stackalloc byte[8] { 0xD4, 0x7A, 0x2C, 0x13, 0x64, 0x59, 0xE2, 0x00 };
Span<byte> secureTick = BitConverter.GetBytes(ksceRtcGetCurrentSecureTick()); //stackalloc byte[8] { 0xD4, 0x7A, 0x2C, 0x13, 0x64, 0x59, 0xE2, 0x00 };
//RandomNumberGenerator.Fill(secureTick);
ebootSig.Fill(0);
@ -1283,6 +1283,14 @@ namespace PspCrypto
return 0;
}
private static ulong ksceRtcGetCurrentSecureTick()
{
DateTime epoch = new DateTime(1, 1, 1, 0, 0, 0);
DateTime now = DateTime.UtcNow;
TimeSpan ts = now.Subtract(epoch);
return Convert.ToUInt64(Math.Floor(ts.TotalMilliseconds)) * 1000;
}
private static int SceSblGcAuthMgrDrmBBForDriver_4B506BE7(ReadOnlySpan<byte> digest, ReadOnlySpan<byte> sig, int keyType)
{
byte[] pubx;

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Vita.ContentManager
{
public class Account
{
public Account(UInt64 accountId)
{
this.accountId = accountId;
}
private UInt64 accountId;
public bool Devkit;
public byte[] AccountId
{
get
{
if (Devkit) return new byte[8];
return BitConverter.GetBytes(accountId);
}
}
public string AccountIdStr
{
get
{
return BitConverter.ToString(AccountId).Replace("-", "").ToLowerInvariant();
}
}
public string CmaKeyStr
{
get
{
return KeyGenerator.GenerateKeyStr(AccountIdStr);
}
}
public byte[] CmaKey
{
get
{
return KeyGenerator.GenerateKey(AccountId);
}
}
}
}

View File

@ -5,7 +5,7 @@ using System.Text;
namespace Vita.ContentManager
{
class KeyGenerator
public class KeyGenerator
{
static Byte[] Passphrase = Encoding.ASCII.GetBytes("Sri Jayewardenepura Kotte");
static Byte[] Key = { 0xA9, 0xFA, 0x5A, 0x62, 0x79, 0x9F, 0xCC, 0x4C, 0x72, 0x6B, 0x4E, 0x2C, 0xE3, 0x50, 0x6D, 0x38 };
@ -19,7 +19,7 @@ namespace Vita.ContentManager
byte[] AidBytes = BitConverter.GetBytes(longlong);
Array.Reverse(AidBytes);
byte[] DerivedKey = CmaKeys.GenerateKey(AidBytes);
byte[] DerivedKey = GenerateKey(AidBytes);
return BitConverter.ToString(DerivedKey).Replace("-", "");
@ -46,8 +46,7 @@ namespace Vita.ContentManager
return DerviedKey;
}
private static byte[] Decrypt(byte[] cipherData,
byte[] Key)
private static byte[] Decrypt(byte[] cipherData, byte[] Key)
{
MemoryStream ms = new MemoryStream();
Aes alg = Aes.Create();

View File

@ -1,17 +1,14 @@
using Li.Progress;
using Org.BouncyCastle.Crypto.Digests;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using static Vita.PsvImgTools.SceIoStat;
namespace Vita.PsvImgTools
{
public class PSVIMGBuilder : ProgressTracker
{
private const Int64 BUFFER_SZ = 0x33554432;
private const Int64 BUFFER_SZ = 0x10000;
private byte[] IV = new byte[0x10];
private byte[] KEY;
private Random rnd = new Random();
@ -151,7 +148,30 @@ namespace Vita.PsvImgTools
sdt.Microsecond = Convert.ToUInt32(dt.Millisecond * 1000);
return sdt;
}
internal virtual SceIoStat sceIoStat()
{
SceIoStat stats = new SceIoStat();
stats.Mode |= Modes.Directory;
// set size..
stats.Size = 0;
// fake the rest--
stats.Mode |= Modes.GroupRead;
stats.Mode |= Modes.GroupWrite;
stats.Mode |= Modes.OthersRead;
stats.Mode |= Modes.OthersWrite;
stats.Mode |= Modes.UserRead;
stats.Mode |= Modes.UserWrite;
stats.CreationTime = dateTimeToSceDateTime(DateTime.Now);
stats.AccessTime = dateTimeToSceDateTime(DateTime.Now);
stats.ModificaionTime = dateTimeToSceDateTime(DateTime.Now);
return stats;
}
internal virtual SceIoStat sceIoStat(Stream str)
{
SceIoStat stats = new SceIoStat();
@ -423,7 +443,7 @@ namespace Vita.PsvImgTools
}
}
internal virtual void writeStream(Stream dst)
internal virtual void writeStream(Stream dst, string file)
{
while(dst.Position < dst.Length)
{
@ -436,7 +456,7 @@ namespace Vita.PsvImgTools
dst.Read(work_buf, 0x00, work_buf.Length);
writeBlock(work_buf, true);
updateProgress(Convert.ToInt32(dst.Position), Convert.ToInt32(dst.Length), "PSVIMG Creation");
updateProgress(Convert.ToInt32(dst.Position), Convert.ToInt32(dst.Length), "PSVIMG Package File: " + Path.GetFileName(file));
}
}
@ -454,12 +474,19 @@ namespace Vita.PsvImgTools
}
}
public void AddFile(byte[] sData, string ParentPath, string PathRel)
{
using (MemoryStream ms = new MemoryStream(sData))
{
AddFile(ms, ParentPath, PathRel);
}
}
public void AddFile(Stream sData, string ParentPath, string PathRel)
{
SceIoStat stat = sceIoStat(sData);
long sz = Convert.ToInt64(stat.Size);
writeBlock(getHeader(stat, ParentPath, PathRel));
writeStream(sData);
writeStream(sData, PathRel);
writeBlock(getPadding(sz));
writeBlock(getTailer());
contentSize += sz;
@ -471,13 +498,18 @@ namespace Vita.PsvImgTools
long sz = Convert.ToInt64(sceIoStat(FilePath).Size);
writeBlock(getHeader(FilePath, ParentPath, PathRel));
using (FileStream fs = File.OpenRead(FilePath))
writeStream(fs);
writeStream(fs, PathRel);
writeBlock(getPadding(sz));
writeBlock(getTailer());
contentSize += sz;
finished = true;
}
public void AddDir(string ParentPath, string PathRel)
{
writeBlock(getHeader(sceIoStat(), ParentPath, PathRel));
writeBlock(getPadding(0));
writeBlock(getTailer());
}
public void AddDir(string DirPath, string ParentPath, string PathRel)
{
writeBlock(getHeader(DirPath, ParentPath, PathRel));
@ -491,7 +523,7 @@ namespace Vita.PsvImgTools
mainStream.Write(footer, 0x00, footer.Length);
blockStream.Dispose();
mainStream.Dispose();
//mainStream.Dispose();
return contentSize;
}

View File

@ -5,7 +5,7 @@ using System.Security.Cryptography;
using System.Text;
namespace Vita.PsvImgTools
{
class PSVMDBuilder
public class PSVMDBuilder
{
private static void memset(byte[] buf, byte content, long length)
{