chovy-sign/CHOVY-SIGN/CHOVYPspBuilder.cs

635 lines
23 KiB
C#

using CHOVY_SIGN.Properties;
using Ionic.Zlib;
using Microsoft.Win32;
using ParamSfo;
using PSVIMGTOOLS;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Media;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace CHOVY_SIGN
{
public partial class CHOVYPspBuilder : Form
{
bool MutedAudio = false;
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
public byte[] ReadFileFromISO(string ISOFile, string FilePath)
{
try
{
FileStream ISO = File.OpenRead(ISOFile);
DiscUtils.Iso9660.CDReader cdr = new DiscUtils.Iso9660.CDReader(ISO, false);
Stream FileStr = cdr.OpenFile(FilePath, FileMode.Open, FileAccess.Read);
byte[] FileBytes = new byte[FileStr.Length];
FileStr.Read(FileBytes, 0x00, (int)FileStr.Length);
ISO.Close();
return FileBytes;
}
catch(Exception)
{
return new byte[0x00];
}
}
public static string GetTitleID(string ISOFile)
{
FileStream ISO = File.OpenRead(ISOFile);
DiscUtils.Iso9660.CDReader cdr = new DiscUtils.Iso9660.CDReader(ISO, false);
Stream ParamSfo = cdr.OpenFile(@"PSP_GAME\PARAM.SFO", FileMode.Open, FileAccess.Read);
Dictionary<string,object> SfoKeys = Sfo.ReadSfo(ParamSfo);
string TitleID = (string)SfoKeys["DISC_ID"];
ISO.Close();
return TitleID;
}
public static bool isMini(string ISOFile)
{
FileStream ISO = File.OpenRead(ISOFile);
DiscUtils.Iso9660.CDReader cdr = new DiscUtils.Iso9660.CDReader(ISO, false);
Stream Icon0 = cdr.OpenFile(@"PSP_GAME\ICON0.PNG", FileMode.Open, FileAccess.Read);
Bitmap bmp = new Bitmap(Icon0);
bool isMini = (bmp.Width == 80 && bmp.Height == 80);
bmp.Dispose();
ISO.Close();
return isMini;
}
public string ReadSetting(string Setting)
{
string Value = "";
try
{
RegistryKey key;
key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVYProject\Chovy-Sign");
Value = key.GetValue(Setting).ToString();
key.Close();
}
catch (Exception) { return ""; }
return Value;
}
public void WriteSetting(string Setting,string Value)
{
try
{
RegistryKey key;
key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVYProject\Chovy-Sign");
key.SetValue(Setting, Value);
key.Close();
}
catch (Exception) { }
}
public bool IsDexAidSet()
{
string isDex = ReadSetting("DexAid");
if (isDex == "0")
{
return false;
}
else if(isDex == "1")
{
return true;
}
else
{
return false;
}
}
public CHOVYPspBuilder()
{
InitializeComponent();
}
private void CHOVY_Load(object sender, EventArgs e)
{
if (ReadSetting("MuteAudio") == "1")
{
MutedAudio = true;
}
Versionkey.Text = ReadSetting("VersionKey");
RifPath.Text = ReadSetting("RifPath");
}
private void FREEDOM_EnabledChanged(object sender, EventArgs e)
{
Color red = Color.FromArgb(192, 0, 0);
Color black = Color.Black;
bool enabled = this.FREEDOM.Enabled;
this.FREEDOM.ForeColor = enabled ? red : black;
this.FREEDOM.BackColor = enabled ? black : red;
}
private void FREEDOM_Click(object sender, EventArgs e)
{
Action enable = () => {
this.FREEDOM.Enabled = true;
this.Ps1Menu.Enabled = true;
this.FindFromCMA.Enabled = true;
this.RifPath.ReadOnly = false;
this.Versionkey.ReadOnly = false;
this.ISOPath.ReadOnly = false;
this.CompressPBP.Enabled = true;
this.BrowseButton.Enabled = true;
};
Action disable = () => {
this.FREEDOM.Enabled = false;
this.Ps1Menu.Enabled = false;
this.FindFromCMA.Enabled = false;
this.RifPath.ReadOnly = true;
this.Versionkey.ReadOnly = true;
this.ISOPath.ReadOnly = true;
this.CompressPBP.Enabled = false;
this.BrowseButton.Enabled = false;
};
disable();
bool isZrif = false;
if(RifPath.Text == "" || !File.Exists(RifPath.Text))
{
// Check if valid 'zRIF'
try
{
ZlibStream.UncompressBuffer(Convert.FromBase64String(RifPath.Text));
isZrif = true;
}
catch(Exception)
{
MessageBox.Show("INVALID RIF!\nPlease try \"Find from CMA\"", "RIF ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
enable();
return;
}
}
if(Versionkey.Text.Length != 32)
{
MessageBox.Show("INVALID VERSION KEY!\nPlease try \"Find from CMA\"", "VERKEY ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
enable();
return;
}
if(ISOPath.Text == "" || !File.Exists(ISOPath.Text))
{
MessageBox.Show("INVALID ISO PATH!", "ISO ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
enable();
return;
}
this.FREEDOM.Enabled = false;
string CmaDir = ReadSetting("CmaDir");
if(CmaDir == "")
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.Description = "Select CMA Backups Directory";
fbd.ShowDialog();
CmaDir = fbd.SelectedPath;
}
string TitleID = GetTitleID(ISOPath.Text);
string TmpDir = Path.Combine(Application.StartupPath, "_tmp");
string GameWorkDir = Path.Combine(TmpDir, TitleID);
string EbootFile = Path.Combine(GameWorkDir, "EBOOT.PBP");
string EbootSignature = Path.Combine(GameWorkDir, "__sce_ebootpbp");
Directory.CreateDirectory(TmpDir);
Directory.CreateDirectory(GameWorkDir);
//Read RIF data
byte[] ContentId = new byte[0x24];
byte[] RifAid = new byte[0x08];
Stream rif = null;
if (!isZrif)
rif = File.OpenRead(RifPath.Text);
else
rif = new MemoryStream(ZlibStream.UncompressBuffer(Convert.FromBase64String(RifPath.Text)));
rif.Seek(0x10, SeekOrigin.Begin);
rif.Read(ContentId, 0x00, 0x24);
rif.Seek(0x08, SeekOrigin.Begin);
rif.Read(RifAid, 0x00, 0x08);
string ContentID = Encoding.UTF8.GetString(ContentId);
string AidStr = BitConverter.ToString(RifAid).Replace("-", "").ToLower();
if(IsDexAidSet())
{
AidStr = "0000000000000000";
}
string BackupWorkDir = Path.Combine(CmaDir, "PGAME", AidStr, TitleID);
TotalProgress.Maximum = 100;
Status.Text = "Overthrowing The PSPEMU Monarchy 0%";
Thread BuildPbpThread = new Thread(() =>
{
// Try New System
try
{
FileStream EbootStream = File.OpenWrite(EbootFile);
FileStream IsoStream = File.OpenRead(ISOPath.Text);
Bitmap BootupImage;
if (isMini(ISOPath.Text))
BootupImage = Resources.MINIS;
else
BootupImage = Resources.ChovyLogo;
byte[] Sfo = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\PARAM.SFO");
byte[] Icon0Png = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\ICON0.PNG");
byte[] Icon1 = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\ICON1.PMF");
byte[] Pic0 = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\PIC0.PNG");
byte[] Pic1 = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\PIC1.PNG");
byte[] Snd0 = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\SND0.AT3");
Pbp.BuildPbp(EbootStream, IsoStream, CompressPBP.Checked, FromHex(Versionkey.Text), BootupImage, ContentID, Sfo, Icon0Png, Icon1, Pic0, Pic1, Snd0);
IsoStream.Close();
EbootStream.Close();
}
catch (Exception exp)
{
MessageBox.Show(exp.Message, "Error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
});
BuildPbpThread.Start();
while(BuildPbpThread.IsAlive)
{
if (Pbp.DoEvents)
{
TotalProgress.Maximum = Pbp.NumberOfSectors;
TotalProgress.Value = Pbp.SectorsDone;
if (Pbp.SectorsDone != 0 && Pbp.NumberOfSectors != 0)
{
decimal progress = Math.Floor(((decimal)Pbp.SectorsDone / (decimal)Pbp.NumberOfSectors) * 100);
Status.Text = "Overthrowing The PSPEMU Monarchy " + progress.ToString() + "%";
}
else
Status.Text = "Overthrowing The PSPEMU Monarchy 0%";
Application.DoEvents();
}
}
TotalProgress.Value = 0;
Status.Text = "Signing the Declaration of Independance 0%";
UInt64 IntAid = BitConverter.ToUInt64(RifAid,0x00);
Thread ChovyGenThread = new Thread(() =>
{
int ChovyGenRes = Pbp.gen__sce_ebootpbp(EbootFile, IntAid, EbootSignature);
});
ChovyGenThread.Start();
while(ChovyGenThread.IsAlive)
{
Application.DoEvents();
}
/*
* BUILD PSVIMG FILE
*/
// Pacakge GAME
byte[] CmaKey;
if (IsDexAidSet())
{
CmaKey = CmaKeys.GenerateKey(new byte[0x8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
}
else
{
CmaKey = CmaKeys.GenerateKey(RifAid);
}
string[] entrys = Directory.GetFileSystemEntries(GameWorkDir, "*", SearchOption.AllDirectories);
long noEntrys = entrys.LongLength;
string parentPath = "ux0:pspemu/temp/game/PSP/GAME/" + TitleID;
int noBlocks = 0;
foreach (string fileName in Directory.GetFiles(GameWorkDir,"*",SearchOption.AllDirectories))
{
noBlocks += Convert.ToInt32(new FileInfo(fileName).Length / PSVIMGConstants.PSVIMG_BLOCK_SIZE);
}
TotalProgress.Maximum = noBlocks;
string BackupDir = Path.Combine(BackupWorkDir, "game");
Directory.CreateDirectory(BackupDir);
string psvimgFilepath = Path.Combine(BackupDir, "game.psvimg");
FileStream gamePsvimg = File.OpenWrite(psvimgFilepath);
gamePsvimg.SetLength(0);
PSVIMGBuilder builder = new PSVIMGBuilder(gamePsvimg, CmaKey);
foreach (string entry in entrys)
{
string relativePath = entry.Remove(0, GameWorkDir.Length);
relativePath = relativePath.Replace('\\', '/');
bool isDir = File.GetAttributes(entry).HasFlag(FileAttributes.Directory);
if (isDir)
{
builder.AddDir(entry, parentPath, relativePath);
}
else
{
builder.AddFileAsync(entry, parentPath, relativePath);
while(!builder.HasFinished)
{
try
{
int tBlocks = builder.BlocksWritten;
TotalProgress.Value = tBlocks;
decimal progress = Math.Floor(((decimal)tBlocks / (decimal)noBlocks) * 100);
Status.Text = "Signing the Declaration of Independance " + progress.ToString() + "%";
}
catch (Exception) { }
Application.DoEvents();
}
}
}
long ContentSize = builder.Finish();
gamePsvimg = File.OpenRead(psvimgFilepath);
FileStream gamePsvmd = File.OpenWrite(Path.Combine(BackupDir, "game.psvmd"));
PSVMDBuilder.CreatePsvmd(gamePsvmd, gamePsvimg, ContentSize, "game", CmaKey);
gamePsvmd.Close();
gamePsvimg.Close();
// Package LICENSE
BackupDir = Path.Combine(BackupWorkDir, "license");
psvimgFilepath = Path.Combine(BackupDir, "license.psvimg");
Directory.CreateDirectory(BackupDir);
FileStream licensePsvimg = File.OpenWrite(psvimgFilepath);
licensePsvimg.SetLength(0);
builder = new PSVIMGBuilder(licensePsvimg, CmaKey);
if (!isZrif)
{
builder.AddFile(RifPath.Text, "ux0:pspemu/temp/game/PSP/LICENSE", "/" + ContentID + ".rif");
}
else
{
rif.Seek(0x00, SeekOrigin.Begin);
builder.AddFileFromStream(rif, "ux0:pspemu/temp/game/PSP/LICENSE", "/" + ContentID + ".rif");
}
rif.Close();
ContentSize = builder.Finish();
licensePsvimg = File.OpenRead(psvimgFilepath);
FileStream licensePsvmd = File.OpenWrite(Path.Combine(BackupDir, "license.psvmd"));
PSVMDBuilder.CreatePsvmd(licensePsvmd, licensePsvimg, ContentSize, "license", CmaKey);
licensePsvmd.Close();
licensePsvimg.Close();
// Write PARAM.SFO & ICON0.PNG
string SceSysWorkDir = Path.Combine(BackupWorkDir, "sce_sys");
Directory.CreateDirectory(SceSysWorkDir);
byte[] ParamSfo = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\PARAM.SFO");
byte[] Icon0 = ReadFileFromISO(ISOPath.Text, @"PSP_GAME\ICON0.PNG");
File.WriteAllBytes(Path.Combine(SceSysWorkDir, "param.sfo"), ParamSfo);
File.WriteAllBytes(Path.Combine(SceSysWorkDir, "icon0.png"), Icon0);
Status.Text = "YOU HAVE MADE A SOCIAL CONTRACT WITH FREEDOM!";
TotalProgress.Value = 0;
try
{
Directory.Delete(TmpDir, true);
}
catch (Exception) { };
if (!MutedAudio)
{
Stream str = Resources.Murica;
SoundPlayer snd = new SoundPlayer(str);
snd.Play();
}
enable();
MessageBox.Show("YOU HAVE MADE A SOCIAL CONTRACT WITH FREEDOM!", "FREEDOM!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void FindFromCMA_Click(object sender, EventArgs e)
{
this.Hide();
string cmaDir = "";
string accountId = "0000000000000000";
try
{
//try qcma
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("appsPath").ToString();
accountId = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("lastAccountId").ToString();
}
catch (Exception)
{
try
{
//try sony cma
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\Sony Corporation\Content Manager Assistant\Settings").GetValue("ApplicationHomePath").ToString();
}
catch (Exception)
{
try
{
//try devkit cma
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\SCE\PSP2\Services\Content Manager Assistant for PlayStation(R)Vita DevKit\Settings").GetValue("ApplicationHomePath").ToString();
}
catch (Exception)
{
try
{
string DefaultDir = Path.Combine(Environment.GetEnvironmentVariable("HOMEDRIVE"), Environment.GetEnvironmentVariable("HOMEPATH"), "Documents", "PS Vita");
if (Directory.Exists(DefaultDir))
{
cmaDir = DefaultDir;
}
}
catch (Exception)
{
//Do nothing
}
}
}
}
CHOVYCmaSelector ccs = new CHOVYCmaSelector(cmaDir, accountId);
ccs.FormClosing += Ccs_FormClosing;
ccs.ShowDialog();
}
private void Ccs_FormClosing(object sender, FormClosingEventArgs e)
{
CHOVYCmaSelector ccs = (CHOVYCmaSelector)sender;
string CmaDir = ccs.GetCmaDir();
string CmaAid = ccs.GetCmaAid();
string Backup = ccs.GetSelectedBackup();
WriteSetting("CmaDir", CmaDir);
if (Backup == "")
{
return;
}
string BackupPath = Path.Combine(CmaDir, "PGAME", CmaAid, Backup, "game", "game.psvimg");
if(!File.Exists(BackupPath))
{
MessageBox.Show("Could not find \n" + BackupPath + "\n Perhaps backup failed?", "License Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
ccs.Hide();
this.Show();
this.Focus();
return;
}
byte[] AID = BitConverter.GetBytes(Convert.ToInt64(CmaAid, 16));
Array.Reverse(AID);
byte[] Key = CmaKeys.GenerateKey(AID);
PSVIMGStream GamePsvimg = new PSVIMGStream(File.OpenRead(BackupPath), Key);
BackupPath = Path.Combine(CmaDir, "PGAME", CmaAid, Backup, "license", "license.psvimg");
if (!File.Exists(BackupPath))
{
MessageBox.Show("Could not find \n"+BackupPath+"\n Perhaps backup failed?","License Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
ccs.Hide();
this.Show();
this.Focus();
return;
}
PSVIMGStream LicensePsvimg = new PSVIMGStream(File.OpenRead(BackupPath), Key);
PSVIMGFileStream EbootPbp = new PSVIMGFileStream(GamePsvimg, "/EBOOT.PBP");
byte[] VersionKey = Pbp.GetVersionKey(EbootPbp);
string VerKey = BitConverter.ToString(VersionKey).Replace("-", "");
WriteSetting("VersionKey", VerKey);
string ContentID = Pbp.GetContentId(EbootPbp);
PSVIMGFileStream LicenseRif = new PSVIMGFileStream(LicensePsvimg, "/"+ ContentID+ ".rif");
byte[] LicenseRifBytes = new byte[LicenseRif.Length];
LicenseRif.Read(LicenseRifBytes, 0x00, LicenseRifBytes.Length);
LicenseRif.Close();
LicensePsvimg.Close();
EbootPbp.Close();
GamePsvimg.Close();
byte[] zRifBytes = ZlibStream.CompressBuffer(LicenseRifBytes);
string Rif = Convert.ToBase64String(zRifBytes);
WriteSetting("RifPath", Rif);
Versionkey.Text = VerKey;
RifPath.Text = Rif;
ccs.Hide();
this.Show();
this.Focus();
MessageBox.Show("KEYS HAVE BEEN EXTRACTED FROM CMA, YOU MAY NOW LIBERATE YOURSELF", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void BrowseButton_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Select PSP UMD image *.iso";
ofd.Filter = "ISO9660 Image Files (*.iso)|*.iso";
ofd.ShowDialog();
ISOPath.Text = ofd.FileName;
}
private void CHOVY_FormClosing(object sender, FormClosingEventArgs e)
{
Environment.Exit(0);
}
private void PsmChan_Click(object sender, EventArgs e)
{
if(!MutedAudio)
{
MutedAudio = true;
WriteSetting("MuteAudio", "1");
}
else
{
MutedAudio = false;
WriteSetting("MuteAudio", "0");
}
}
private void DexAidEnabler_Click(object sender, EventArgs e)
{
if (!IsDexAidSet())
{
WriteSetting("DexAid", "1");
MessageBox.Show("Enabled DEX Aid\n(0x0000000000000000) will be used for CMA Backups.", "Dex Aid", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
WriteSetting("DexAid", "0");
MessageBox.Show("Enabled Retail Aid,\nAid From RIF Will be used for CMA Backups.", "Dex Aid", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void Ps1Menu_Click(object sender, EventArgs e)
{
if (!MutedAudio)
{
Stream str = Resources.POPS;
SoundPlayer snd = new SoundPlayer(str);
snd.Play();
}
CHOVYPopsBuilder pops = new CHOVYPopsBuilder();
this.Hide();
pops.Show();
pops.FormClosing += Pops_FormClosing;
}
private void Pops_FormClosing(object sender, FormClosingEventArgs e)
{
this.Show();
}
}
}