Add NpUmdImg
This commit is contained in:
parent
7b6830a40b
commit
562016688a
|
@ -3,6 +3,7 @@
|
|||
.vs/*
|
||||
*.7z
|
||||
|
||||
*thumbs.db
|
||||
|
||||
PbpResign/bin/*
|
||||
PbpResign/obj/*
|
||||
|
|
|
@ -533,11 +533,11 @@ namespace PbpResign
|
|||
Span<byte> table = new byte[tablesize];
|
||||
var tp = MemoryMarshal.Cast<byte, uint>(table);
|
||||
input.Read(table);
|
||||
|
||||
// Decrypt Table
|
||||
for (int i = 0; i < totalBlocks; i++)
|
||||
{
|
||||
XorTable(tp[(i * 8)..]);
|
||||
}
|
||||
|
||||
|
||||
var blocks = MemoryMarshal.Cast<byte, NpBlock>(table);
|
||||
for (int i = 0; i < blocks.Length; i++)
|
||||
|
@ -578,9 +578,7 @@ namespace PbpResign
|
|||
|
||||
// Encrypt Table
|
||||
for (int i = 0; i < totalBlocks; i++)
|
||||
{
|
||||
XorTable(tp[(i * 8)..]);
|
||||
}
|
||||
|
||||
output.Seek(entityOff, SeekOrigin.Begin);
|
||||
output.Write(table);
|
||||
|
@ -1073,6 +1071,17 @@ namespace PbpResign
|
|||
return false;
|
||||
}
|
||||
type = 0;
|
||||
|
||||
Console.WriteLine("VersionKey: " + BitConverter.ToString(NewVersionKey.ToArray()));
|
||||
|
||||
NpUmdImg npumd = new NpUmdImg(new NpDrmInfo(NewVersionKey.ToArray(), CId, npHdr.NpFlags),
|
||||
"fft.iso", "ULUS10297", File.ReadAllBytes("TEST\\PARAM.SFO"), false);
|
||||
|
||||
npumd.CreatePsar();
|
||||
byte[] paramFile = File.ReadAllBytes("TEST\\PARAM.SFO");
|
||||
|
||||
PbpBuilder.CreatePbp(paramFile, File.ReadAllBytes("TEST\\ICON0.PNG"), null, File.ReadAllBytes("TEST\\PIC0.PNG"), File.ReadAllBytes("TEST\\PIC1.PNG"), null, npumd, "FFT.PBP");
|
||||
|
||||
return CopyNpUmdImg(input, output, pbpHdr, psarBuff, npHdr);
|
||||
}
|
||||
|
||||
|
@ -1086,7 +1095,7 @@ namespace PbpResign
|
|||
return false;
|
||||
}
|
||||
type = 1;
|
||||
DiscInfo[] discs = new DiscInfo[2];
|
||||
/*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);
|
||||
|
@ -1098,7 +1107,7 @@ namespace PbpResign
|
|||
// 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());
|
||||
//File.WriteAllBytes("TEST.ISOc", i.GetIso());*/
|
||||
|
||||
|
||||
return CopyPsIsoImg(input, output, pbpHdr);
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace PopsBuilder.Pops
|
|||
int headerSize = DNASHelper.CalculateSize(isoHdr.Length, 0x400);
|
||||
byte[] headerEnc = new byte[headerSize];
|
||||
|
||||
int sz = DNASHelper.Encrypt(headerEnc, isoHdr, srcImg.VersionKey, isoHdr.Length, 1, 1, blockSize: 0x400);
|
||||
int sz = DNASHelper.Encrypt(headerEnc, isoHdr, srcImg.DrmInfo.VersionKey, isoHdr.Length, srcImg.DrmInfo.KeyType, 1, blockSize: 0x400);
|
||||
byte[] isoHdrPgd = headerEnc.ToArray();
|
||||
Array.Resize(ref isoHdrPgd, sz);
|
||||
|
||||
|
@ -155,7 +155,6 @@ namespace PopsBuilder.Pops
|
|||
|
||||
private void writeCompressedCDATracks()
|
||||
{
|
||||
Random rng = new Random();
|
||||
|
||||
IsoHeader.Seek(0x800, SeekOrigin.Begin); // CDA Entries
|
||||
|
||||
|
@ -168,7 +167,7 @@ namespace PopsBuilder.Pops
|
|||
|
||||
using (CueStream audioStream = cue.OpenTrack(i))
|
||||
{
|
||||
uint key = Convert.ToUInt32(rng.NextInt64(0, uint.MaxValue));
|
||||
uint key = Rng.RandomUInt();
|
||||
|
||||
Atrac3ToolEncoder enc = new Atrac3ToolEncoder();
|
||||
|
||||
|
@ -202,7 +201,7 @@ namespace PopsBuilder.Pops
|
|||
AMCTRL.sceDrmBBMacInit(mkey, 3);
|
||||
AMCTRL.sceDrmBBMacUpdate(mkey, data, data.Length);
|
||||
Span<byte> checksum = new byte[20 + 0x10];
|
||||
AMCTRL.sceDrmBBMacFinal(mkey, checksum[20..], srcImg.VersionKey);
|
||||
AMCTRL.sceDrmBBMacFinal(mkey, checksum[20..], srcImg.DrmInfo.VersionKey);
|
||||
|
||||
ref var aesHdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(checksum);
|
||||
aesHdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
|
||||
|
|
|
@ -12,27 +12,22 @@ namespace PopsBuilder.Pops
|
|||
{
|
||||
public class PopsImg : NpDrmPsar
|
||||
{
|
||||
public PopsImg(byte[] versionKey, string contentId) : base(versionKey, contentId)
|
||||
public PopsImg(NpDrmInfo versionKey) : base(versionKey)
|
||||
{
|
||||
startDat = new MemoryStream();
|
||||
startDatUtil = new StreamUtil(startDat);
|
||||
|
||||
simple = new MemoryStream();
|
||||
simpleUtil = new StreamUtil(simple);
|
||||
|
||||
createStartDat();
|
||||
StartDat = NpDrmPsar.CreateStartDat(Resources.STARTDATPOPS);
|
||||
createSimpleDat();
|
||||
|
||||
SimplePgd = generateSimplePgd();
|
||||
|
||||
}
|
||||
internal MemoryStream startDat;
|
||||
internal StreamUtil startDatUtil;
|
||||
|
||||
|
||||
private MemoryStream simple;
|
||||
private StreamUtil simpleUtil;
|
||||
public byte[] StartDat;
|
||||
public byte[] SimplePgd;
|
||||
internal Random rng = new Random();
|
||||
private void createSimpleDat()
|
||||
{
|
||||
simpleUtil.WriteStr("SIMPLE ");
|
||||
|
@ -45,20 +40,7 @@ namespace PopsBuilder.Pops
|
|||
simpleUtil.WriteBytes(Resources.SIMPLE);
|
||||
}
|
||||
|
||||
private void createStartDat()
|
||||
{
|
||||
startDatUtil.WriteStr("STARTDAT");
|
||||
startDatUtil.WriteInt32(0x1);
|
||||
startDatUtil.WriteInt32(0x1);
|
||||
startDatUtil.WriteInt32(0x50);
|
||||
startDatUtil.WriteInt32(Resources.STARTDAT.Length);
|
||||
startDatUtil.WriteInt32(0x0);
|
||||
startDatUtil.WriteInt32(0x0);
|
||||
|
||||
startDatUtil.WritePadding(0, 0x30);
|
||||
|
||||
startDatUtil.WriteBytes(Resources.STARTDAT);
|
||||
}
|
||||
|
||||
|
||||
private byte[] generateSimplePgd()
|
||||
{
|
||||
|
@ -69,7 +51,7 @@ namespace PopsBuilder.Pops
|
|||
byte[] simpleEnc = new byte[simpleSz];
|
||||
|
||||
// get pgd
|
||||
int sz = DNASHelper.Encrypt(simpleEnc, simpleData, VersionKey, simpleData.Length, 1, 1, blockSize: 0x400);
|
||||
int sz = DNASHelper.Encrypt(simpleEnc, simpleData, DrmInfo.VersionKey, simpleData.Length, DrmInfo.KeyType, 1, blockSize: 0x400);
|
||||
byte[] pgd = simpleEnc.ToArray();
|
||||
Array.Resize(ref pgd, sz);
|
||||
|
||||
|
@ -77,7 +59,7 @@ namespace PopsBuilder.Pops
|
|||
}
|
||||
|
||||
|
||||
public byte[] GenerateDataPsp()
|
||||
public override byte[] GenerateDataPsp()
|
||||
{
|
||||
Span<byte> loaderEnc = new byte[0x9B13];
|
||||
|
||||
|
@ -95,7 +77,7 @@ namespace PopsBuilder.Pops
|
|||
Array.ConstrainedCopy(lowBits, 0, dataPspElf, 0x68C, 0x2);
|
||||
Array.ConstrainedCopy(highBits, 0, dataPspElf, 0x694, 0x2);
|
||||
|
||||
SceMesgLed.Encrypt(loaderEnc, dataPspElf, 0x0DAA06F0, SceExecFileDecryptMode.DECRYPT_MODE_POPS_EXEC, VersionKey, ContentId, Resources.DATAPSPSDCFG);
|
||||
SceMesgLed.Encrypt(loaderEnc, dataPspElf, 0x0DAA06F0, SceExecFileDecryptMode.DECRYPT_MODE_POPS_EXEC, DrmInfo.VersionKey, DrmInfo.ContentId, Resources.DATAPSPSDCFG);
|
||||
return loaderEnc.ToArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using PopsBuilder.Atrac3;
|
||||
using PopsBuilder.Cue;
|
||||
using PopsBuilder.Psp;
|
||||
using PspCrypto;
|
||||
using System;
|
||||
using System.Net;
|
||||
|
@ -11,24 +12,24 @@ namespace PopsBuilder.Pops
|
|||
{
|
||||
public class PsIsoImg : PopsImg
|
||||
{
|
||||
internal PsIsoImg(byte[] versionkey, string contentId, DiscCompressor discCompressor) : base(versionkey, contentId)
|
||||
internal PsIsoImg(NpDrmInfo versionKey, DiscCompressor discCompressor) : base(versionKey)
|
||||
{
|
||||
this.compressor = discCompressor;
|
||||
}
|
||||
|
||||
public PsIsoImg(byte[] versionkey, string contentId, DiscInfo disc, IAtracEncoderBase encoder) : base(versionkey, contentId)
|
||||
public PsIsoImg(NpDrmInfo versionKey, DiscInfo disc, IAtracEncoderBase encoder) : base(versionKey)
|
||||
{
|
||||
this.compressor = new DiscCompressor(this, disc, encoder);
|
||||
}
|
||||
|
||||
public PsIsoImg(byte[] versionkey, string contentId, DiscInfo disc) : base(versionkey, contentId)
|
||||
public PsIsoImg(NpDrmInfo versionKey, DiscInfo disc) : base(versionKey)
|
||||
{
|
||||
this.compressor = new DiscCompressor(this, disc, new Atrac3ToolEncoder());
|
||||
}
|
||||
public void CreatePsar(bool isPartOfMultiDisc=false)
|
||||
{
|
||||
compressor.GenerateIsoHeaderAndCompress();
|
||||
if (!isPartOfMultiDisc) compressor.WriteSimpleDatLocation((compressor.IsoOffset + compressor.CompressedIso.Length) + startDat.Length);
|
||||
if (!isPartOfMultiDisc) compressor.WriteSimpleDatLocation((compressor.IsoOffset + compressor.CompressedIso.Length) + StartDat.Length);
|
||||
|
||||
psarUtil.WriteStr("PSISOIMG0000");
|
||||
psarUtil.WriteInt64(0x00); // location of STARTDAT
|
||||
|
@ -47,8 +48,7 @@ namespace PopsBuilder.Pops
|
|||
|
||||
// write STARTDAT
|
||||
Int64 startDatLocation = Psar.Position;
|
||||
startDat.Seek(0x00, SeekOrigin.Begin);
|
||||
startDat.CopyTo(Psar);
|
||||
psarUtil.WriteBytes(StartDat);
|
||||
|
||||
// write pgd
|
||||
psarUtil.WriteBytes(this.SimplePgd);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using PopsBuilder.Atrac3;
|
||||
using PopsBuilder.Psp;
|
||||
using PspCrypto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -13,7 +14,7 @@ namespace PopsBuilder.Pops
|
|||
{
|
||||
const int MAX_DISCS = 5;
|
||||
const int PSISO_ALIGN = 0x8000;
|
||||
public PsTitleImg(byte[] versionKey, string contentId, DiscInfo[] discs) : base(versionKey, contentId)
|
||||
public PsTitleImg(NpDrmInfo drmInfo, DiscInfo[] 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];
|
||||
|
@ -42,7 +43,7 @@ namespace PopsBuilder.Pops
|
|||
psarUtil.WriteStr("PSTITLEIMG000000");
|
||||
psarUtil.WriteInt64(PSISO_ALIGN+isoPart.Length); // location of STARTDAT
|
||||
|
||||
psarUtil.WriteRandom(0x10); // dunno what this is
|
||||
psarUtil.WriteBytes(Rng.RandomBytes(0x10)); // dunno what this is
|
||||
psarUtil.WritePadding(0x00, 0x1D8);
|
||||
|
||||
byte[] isoMap = generateIsoMapPgd();
|
||||
|
@ -52,8 +53,7 @@ namespace PopsBuilder.Pops
|
|||
isoPart.Seek(0x00, SeekOrigin.Begin);
|
||||
isoPart.CopyTo(Psar);
|
||||
|
||||
startDat.Seek(0x00, SeekOrigin.Begin);
|
||||
startDat.CopyTo(Psar);
|
||||
psarUtil.WriteBytes(StartDat);
|
||||
|
||||
psarUtil.WriteBytes(SimplePgd);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ namespace PopsBuilder.Pops
|
|||
PspCrypto.AMCTRL.sceDrmBBMacInit(mkey, 3);
|
||||
PspCrypto.AMCTRL.sceDrmBBMacUpdate(mkey, header, header.Length /*0xb3c80*/);
|
||||
Span<byte> newKey = new byte[20 + 0x10];
|
||||
PspCrypto.AMCTRL.sceDrmBBMacFinal(mkey, newKey[20..], VersionKey);
|
||||
PspCrypto.AMCTRL.sceDrmBBMacFinal(mkey, newKey[20..], DrmInfo.VersionKey);
|
||||
ref var aesHdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(newKey);
|
||||
aesHdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
|
||||
aesHdr.keyseed = 0x63;
|
||||
|
@ -86,7 +86,7 @@ namespace PopsBuilder.Pops
|
|||
int encryptedSz = DNASHelper.CalculateSize(isoMapBuf.Length, 1024);
|
||||
var isoMapEnc = new byte[encryptedSz];
|
||||
|
||||
DNASHelper.Encrypt(isoMapEnc, isoMapBuf, VersionKey, isoMapBuf.Length, 1, 1);
|
||||
DNASHelper.Encrypt(isoMapEnc, isoMapBuf, DrmInfo.VersionKey, isoMapBuf.Length, DrmInfo.KeyType, 1);
|
||||
|
||||
return isoMapEnc;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ namespace PopsBuilder.Pops
|
|||
int padLen = Convert.ToInt32(PSISO_ALIGN - (isoPart.Position % PSISO_ALIGN));
|
||||
isoPartUtil.WritePadding(0x00, padLen);
|
||||
|
||||
using (PsIsoImg psIsoImg = new PsIsoImg(this.VersionKey, this.ContentId, compressors[i]))
|
||||
using (PsIsoImg psIsoImg = new PsIsoImg(this.DrmInfo, compressors[i]))
|
||||
{
|
||||
isoMapUtil.WriteUInt32(Convert.ToUInt32(PSISO_ALIGN + isoPart.Position));
|
||||
|
||||
|
@ -127,8 +127,8 @@ namespace PopsBuilder.Pops
|
|||
isoMapUtil.WriteBytes(checksums);
|
||||
isoMapUtil.WriteStrWithPadding(discs.First().DiscIdHdr, 0x00, 0x20);
|
||||
|
||||
isoMapUtil.WriteInt64(Convert.ToInt64(PSISO_ALIGN + isoPart.Length + startDat.Length));
|
||||
isoMapUtil.WriteRandom(0x80);
|
||||
isoMapUtil.WriteInt64(Convert.ToInt64(PSISO_ALIGN + isoPart.Length + StartDat.Length));
|
||||
psarUtil.WriteBytes(Rng.RandomBytes(0x80));
|
||||
isoMapUtil.WriteStrWithPadding(discs.First().DiscName, 0x00, 0x80);
|
||||
isoMapUtil.WriteInt32(MAX_DISCS);
|
||||
isoMapUtil.WritePadding(0x00, 0x70);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PopsBuilder.Psp
|
||||
{
|
||||
public class NpDrmInfo
|
||||
{
|
||||
public string ContentId;
|
||||
public byte[] VersionKey;
|
||||
public int KeyType;
|
||||
|
||||
public NpDrmInfo(byte[] versionKey, string contentId, int keyType)
|
||||
{
|
||||
this.VersionKey = versionKey;
|
||||
this.KeyType = keyType;
|
||||
this.ContentId = contentId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,22 +9,43 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace PopsBuilder.Psp
|
||||
{
|
||||
public class NpDrmPsar : IDisposable
|
||||
public abstract class NpDrmPsar : IDisposable
|
||||
{
|
||||
public NpDrmPsar(byte[] versionKey, string contentId)
|
||||
public NpDrmPsar(NpDrmInfo npDrmInfo)
|
||||
{
|
||||
VersionKey = versionKey;
|
||||
ContentId = contentId;
|
||||
DrmInfo = npDrmInfo;
|
||||
|
||||
Psar = new MemoryStream();
|
||||
psarUtil = new StreamUtil(Psar);
|
||||
}
|
||||
|
||||
public byte[] VersionKey;
|
||||
public string ContentId;
|
||||
public NpDrmInfo DrmInfo;
|
||||
|
||||
public MemoryStream Psar;
|
||||
internal StreamUtil psarUtil;
|
||||
public abstract byte[] GenerateDataPsp();
|
||||
public static byte[] CreateStartDat(byte[] image)
|
||||
{
|
||||
using(MemoryStream startDatStream = new MemoryStream())
|
||||
{
|
||||
StreamUtil startDatUtil = new StreamUtil(startDatStream);
|
||||
|
||||
startDatUtil.WriteStr("STARTDAT");
|
||||
startDatUtil.WriteInt32(0x1);
|
||||
startDatUtil.WriteInt32(0x1);
|
||||
startDatUtil.WriteInt32(0x50);
|
||||
startDatUtil.WriteInt32(image.Length);
|
||||
startDatUtil.WriteInt32(0x0);
|
||||
startDatUtil.WriteInt32(0x0);
|
||||
|
||||
startDatUtil.WritePadding(0, 0x30);
|
||||
|
||||
startDatUtil.WriteBytes(image);
|
||||
|
||||
startDatStream.Seek(0x00, SeekOrigin.Begin);
|
||||
return startDatStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using PopsBuilder.Pops;
|
||||
using PspCrypto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PopsBuilder.Psp
|
||||
{
|
||||
public class NpUmdImg : NpDrmPsar
|
||||
{
|
||||
const int RATIO_LIMIT = 90;
|
||||
const int BLOCK_BASIS = 0x10;
|
||||
const int SECTOR_SZ = 2048;
|
||||
const int BLOCK_SZ = BLOCK_BASIS * SECTOR_SZ;
|
||||
public NpUmdImg(NpDrmInfo drmInfo, string iso, string discId, byte[] paramSfo, bool compress) : base(drmInfo)
|
||||
{
|
||||
this.isoStream = File.OpenRead(iso);
|
||||
this.compress = compress;
|
||||
|
||||
this.npHdr = new MemoryStream();
|
||||
this.npHdrUtil = new StreamUtil(npHdr);
|
||||
|
||||
this.npHdrBody = new MemoryStream();
|
||||
this.npHdrBodyUtil = new StreamUtil(npHdrBody);
|
||||
|
||||
this.npTbl = new MemoryStream();
|
||||
this.npTblUtil = new StreamUtil(npTbl);
|
||||
|
||||
this.isoData = new MemoryStream();
|
||||
this.isoDataUtil = new StreamUtil(isoData);
|
||||
|
||||
this.headerKey = Rng.RandomBytes(0x10);
|
||||
|
||||
this.discId = discId.ToUpperInvariant().Replace("-", "").Replace("_", "");
|
||||
this.paramSfo = paramSfo;
|
||||
|
||||
isoBlocks = Convert.ToInt64((isoStream.Length + BLOCK_SZ - 1) / BLOCK_SZ);
|
||||
|
||||
}
|
||||
|
||||
private void createNpHdr()
|
||||
{
|
||||
npHdrUtil.WriteStr("NPUMDIMG");
|
||||
npHdrUtil.WriteInt32(DrmInfo.KeyType);
|
||||
npHdrUtil.WriteInt32(BLOCK_BASIS);
|
||||
npHdrUtil.WriteStrWithPadding(DrmInfo.ContentId, 0x00, 0x30);
|
||||
|
||||
createNpUmdBody();
|
||||
byte[] npumdDec = npHdrBody.ToArray();
|
||||
byte[] npumdEnc = encryptHeader(npumdDec);
|
||||
|
||||
npHdrUtil.WriteBytes(npumdEnc);
|
||||
npHdrUtil.WriteBytes(this.headerKey);
|
||||
npHdrUtil.WriteBytes(this.dataKey);
|
||||
|
||||
byte[] npumdhdr = npHdr.ToArray();
|
||||
byte[] npumdheaderHash = hashBlock(npumdhdr);
|
||||
|
||||
npHdrUtil.WriteBytes(npumdheaderHash);
|
||||
npHdrUtil.WriteBytes(Rng.RandomBytes(0x8)); // padding
|
||||
npHdrUtil.PadUntil(0x00, 0x100);
|
||||
}
|
||||
|
||||
public void CreatePsar()
|
||||
{
|
||||
createNpUmdTbl();
|
||||
byte[] tbl = encryptTable();
|
||||
this.dataKey = hashBlock(tbl);
|
||||
createNpHdr();
|
||||
|
||||
byte[] npHdrBuf = npHdr.ToArray();
|
||||
ECDsaHelper.SignNpImageHeader(npHdrBuf);
|
||||
psarUtil.WriteBytes(npHdrBuf);
|
||||
psarUtil.WriteBytes(tbl);
|
||||
|
||||
isoData.Seek(0x00, SeekOrigin.Begin);
|
||||
isoData.CopyTo(Psar);
|
||||
}
|
||||
|
||||
public byte[] signParamSfo(byte[] paramSfo)
|
||||
{
|
||||
int paramSfoLen = paramSfo.Length;
|
||||
byte[] contentIdBytes = Encoding.UTF8.GetBytes(DrmInfo.ContentId);
|
||||
Array.Resize(ref paramSfo, paramSfoLen + 0x30);
|
||||
Array.ConstrainedCopy(contentIdBytes, 0, paramSfo, paramSfoLen, contentIdBytes.Length);
|
||||
byte[] signature = new byte[0x30];
|
||||
|
||||
ECDsaHelper.SignParamSfo(paramSfo, signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
public override byte[] GenerateDataPsp()
|
||||
{
|
||||
bool minis = false; // TODO: read minis flag from param.sfo
|
||||
byte[] startDat = CreateStartDat(minis ? Resources.STARTDATMINIS : Resources.STARTDATPSP);
|
||||
using (MemoryStream dataPsp = new MemoryStream())
|
||||
{
|
||||
StreamUtil dataPspUtil = new StreamUtil(dataPsp);
|
||||
byte[] signature = signParamSfo(paramSfo);
|
||||
dataPspUtil.WriteBytes(signature);
|
||||
dataPspUtil.WritePadding(0x00, 0x530);
|
||||
dataPspUtil.WriteStrWithPadding(DrmInfo.ContentId, 0x00, 0x30);
|
||||
dataPspUtil.WriteInt32BE(DrmInfo.KeyType);
|
||||
dataPspUtil.WriteInt32(0);
|
||||
dataPspUtil.WriteInt32(0);
|
||||
dataPspUtil.WriteInt32(0);
|
||||
dataPspUtil.WriteBytes(startDat);
|
||||
return dataPsp.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void createNpUmdTbl()
|
||||
{
|
||||
Int64 tableSz = isoBlocks * 0x20;
|
||||
Int64 isoSz = this.isoStream.Length;
|
||||
int wsize = 0;
|
||||
Int64 isoOffset = 0x100 + tableSz;
|
||||
|
||||
for (int i = 0; i < isoBlocks; i++)
|
||||
{
|
||||
byte[] isoBuf = new byte[BLOCK_SZ];
|
||||
wsize = isoStream.Read(isoBuf, 0x00, BLOCK_SZ);
|
||||
|
||||
byte[] wbuf = isoBuf;
|
||||
|
||||
if (this.compress) // Compress data.
|
||||
{
|
||||
byte[] lzRcBuf = Lz.compress(isoBuf, true);
|
||||
//memset(lzrc_buf + lzrc_size, 0, 16);
|
||||
//
|
||||
|
||||
int ratio = (lzRcBuf.Length * 100) / BLOCK_SZ;
|
||||
|
||||
if (ratio < RATIO_LIMIT)
|
||||
{
|
||||
wbuf = lzRcBuf;
|
||||
|
||||
wsize = (lzRcBuf.Length + 15) & ~15;
|
||||
Array.Resize(ref lzRcBuf, wsize);
|
||||
}
|
||||
}
|
||||
|
||||
int unpaddedSz = wsize;
|
||||
wsize = (wsize + 15) & ~15;
|
||||
Array.Resize(ref wbuf, wsize);
|
||||
encryptBlock(wbuf, Convert.ToInt32(isoOffset));
|
||||
byte[] hash = hashBlock(wbuf);
|
||||
|
||||
npTblUtil.WriteBytes(hash);
|
||||
npTblUtil.WriteUInt32(Convert.ToUInt32(isoOffset));
|
||||
npTblUtil.WriteUInt32(Convert.ToUInt32(unpaddedSz));
|
||||
npTblUtil.WriteInt32(0);
|
||||
npTblUtil.WriteInt32(0);
|
||||
|
||||
|
||||
isoData.Write(wbuf, 0, wsize);
|
||||
|
||||
isoOffset += wsize;
|
||||
|
||||
Console.Write(Convert.ToInt32(Math.Floor((Convert.ToDouble(isoStream.Position) / Convert.ToDouble(isoStream.Length)) * 100.0)) + "%\r");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private byte[] encryptTable()
|
||||
{
|
||||
byte[] table = npTbl.ToArray();
|
||||
|
||||
// Encrypt Table
|
||||
var tp = MemoryMarshal.Cast<byte, uint>(table);
|
||||
|
||||
for (int i = 0; i < (table.Length / 0x20); i++)
|
||||
XorTable(tp[(i * 8)..]);
|
||||
|
||||
var tpbyt = MemoryMarshal.Cast<uint, byte>(tp);
|
||||
|
||||
return tpbyt.ToArray();
|
||||
}
|
||||
private static void XorTable(Span<uint> tp)
|
||||
{
|
||||
tp[4] ^= tp[3] ^ tp[2];
|
||||
tp[5] ^= tp[2] ^ tp[1];
|
||||
tp[6] ^= tp[0] ^ tp[3];
|
||||
tp[7] ^= tp[1] ^ tp[0];
|
||||
}
|
||||
|
||||
|
||||
private byte[] encryptBlock(byte[] blockData, int offset)
|
||||
{
|
||||
AMCTRL.CIPHER_KEY ckey = new AMCTRL.CIPHER_KEY();
|
||||
AMCTRL.sceDrmBBCipherInit(out ckey, 1, DrmInfo.KeyType, headerKey, DrmInfo.VersionKey, offset >> 4);
|
||||
AMCTRL.sceDrmBBCipherUpdate(ref ckey, blockData, blockData.Length);
|
||||
AMCTRL.sceDrmBBCipherFinal(ref ckey);
|
||||
return blockData;
|
||||
}
|
||||
|
||||
private byte[] hashBlock(byte[] blockData)
|
||||
{
|
||||
byte[] hash = new byte[0x10];
|
||||
Span<byte> mkey = stackalloc byte[Marshal.SizeOf<PspCrypto.AMCTRL.MAC_KEY>()];
|
||||
AMCTRL.sceDrmBBMacInit(mkey, 3);
|
||||
AMCTRL.sceDrmBBMacUpdate(mkey, blockData, blockData.Length);
|
||||
AMCTRL.sceDrmBBMacFinal(mkey, hash, DrmInfo.VersionKey);
|
||||
Utils.BuildDrmBBMacFinal2(hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
private void createNpUmdBody()
|
||||
{
|
||||
npHdrBodyUtil.WriteUInt16(SECTOR_SZ); // sector_sz
|
||||
|
||||
if (isoStream.Length > 0x40000000)
|
||||
npHdrBodyUtil.WriteUInt16(0xE001); // unk_2
|
||||
else
|
||||
npHdrBodyUtil.WriteUInt16(0xE000); //unk_2
|
||||
|
||||
npHdrBodyUtil.WriteUInt32(0); // unk_4
|
||||
npHdrBodyUtil.WriteUInt32(0x1010); // unk_8
|
||||
npHdrBodyUtil.WriteUInt32(0); // unk_12
|
||||
npHdrBodyUtil.WriteUInt32(0); // unk_16
|
||||
|
||||
npHdrBodyUtil.WriteUInt32(0x00); // LBA START
|
||||
npHdrBodyUtil.WriteUInt32(0); // unk_24
|
||||
|
||||
|
||||
npHdrBodyUtil.WriteUInt32(Math.Min(Convert.ToUInt32((isoBlocks * BLOCK_BASIS) - 1), 0x6C0BF)); // nsectors
|
||||
npHdrBodyUtil.WriteUInt32(0); // unk_32
|
||||
|
||||
npHdrBodyUtil.WriteUInt32(Convert.ToUInt32((isoBlocks * BLOCK_BASIS) - 1));
|
||||
npHdrBodyUtil.WriteUInt32(0x01003FFE); // unk_40
|
||||
npHdrBodyUtil.WriteUInt32(0x100); // block_entry_offset
|
||||
|
||||
npHdrBodyUtil.WriteStrWithPadding(this.discId.Substring(0, 4) + "-" + this.discId.Substring(4, 5), 0x00, 0x10);
|
||||
|
||||
npHdrBodyUtil.WriteInt32(0); // header_start_offset
|
||||
npHdrBodyUtil.WriteInt32(0); // unk_68
|
||||
|
||||
npHdrBodyUtil.WriteByte(0x00); // unk_72
|
||||
npHdrBodyUtil.WriteByte(0x00); // bbmac param
|
||||
npHdrBodyUtil.WriteByte(0x00); // unk_74
|
||||
npHdrBodyUtil.WriteByte(0x00); // unk_75
|
||||
|
||||
npHdrBodyUtil.WriteInt32(0); // unk_76
|
||||
npHdrBodyUtil.WriteInt32(0); // unk_80
|
||||
npHdrBodyUtil.WriteInt32(0); // unk_84
|
||||
npHdrBodyUtil.WriteInt32(0); // unk_88
|
||||
npHdrBodyUtil.WriteInt32(0); // unk_92
|
||||
|
||||
}
|
||||
|
||||
private byte[] encryptHeader(byte[] headerBytes)
|
||||
{
|
||||
AMCTRL.CIPHER_KEY ckey = new AMCTRL.CIPHER_KEY();
|
||||
AMCTRL.sceDrmBBCipherInit(out ckey, 1, DrmInfo.KeyType, headerKey, DrmInfo.VersionKey, 0);
|
||||
AMCTRL.sceDrmBBCipherUpdate(ref ckey, headerBytes, headerBytes.Length);
|
||||
AMCTRL.sceDrmBBCipherFinal(ref ckey);
|
||||
return headerBytes;
|
||||
}
|
||||
|
||||
private Int64 isoBlocks;
|
||||
private bool compress;
|
||||
|
||||
private string discId;
|
||||
|
||||
private byte[] paramSfo;
|
||||
|
||||
private byte[] headerKey;
|
||||
private byte[] dataKey;
|
||||
|
||||
private FileStream isoStream;
|
||||
|
||||
private MemoryStream npHdr;
|
||||
private StreamUtil npHdrUtil;
|
||||
|
||||
private MemoryStream npHdrBody;
|
||||
private StreamUtil npHdrBodyUtil;
|
||||
|
||||
private MemoryStream isoData;
|
||||
private StreamUtil isoDataUtil;
|
||||
|
||||
private MemoryStream npTbl;
|
||||
private StreamUtil npTblUtil;
|
||||
}
|
||||
}
|
|
@ -10,14 +10,19 @@ namespace PopsBuilder.Psp
|
|||
{
|
||||
public static void CreatePbp(byte[]? paramSfo, byte[]? icon0Png, byte[]? icon1Png,
|
||||
byte[]? pic0Png, byte[]? pic1Png, byte[]? snd0At3,
|
||||
byte[] dataPsp, NpDrmPsar dataPsar, string outputFile)
|
||||
NpDrmPsar dataPsar, string outputFile, short version = 1)
|
||||
{
|
||||
|
||||
using (FileStream pbpStream = File.Open(outputFile, FileMode.Create))
|
||||
{
|
||||
byte[] dataPsp = dataPsar.GenerateDataPsp();
|
||||
int padLen = Convert.ToInt32(0x100 - (dataPsp.Length % 0x100));
|
||||
Array.Resize(ref dataPsp, dataPsp.Length + padLen);
|
||||
|
||||
StreamUtil pbpUtil = new StreamUtil(pbpStream);
|
||||
pbpUtil.WriteByte(0x00);
|
||||
pbpUtil.WriteStrWithPadding("PBP", 0x00, 0x5);
|
||||
pbpUtil.WriteStr("PBP");
|
||||
pbpUtil.WriteInt16(version);
|
||||
pbpUtil.WriteInt16(1);
|
||||
|
||||
// param location
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
using PspCrypto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PopsBuilder.Psp
|
||||
{
|
||||
public static class Rng
|
||||
{
|
||||
public static byte[] RandomBytes(int length)
|
||||
{
|
||||
byte[] randomBytes = new byte[length];
|
||||
KIRKEngine.sceUtilsBufferCopyWithRange(randomBytes, randomBytes.Length, null, 0, KIRKEngine.KIRK_CMD_PRNG);
|
||||
return randomBytes;
|
||||
}
|
||||
public static uint RandomUInt()
|
||||
{
|
||||
byte[] uintBytes = RandomBytes(0x4);
|
||||
return BitConverter.ToUInt32(uintBytes);
|
||||
}
|
||||
public static int RandomInt()
|
||||
{
|
||||
byte[] intBytes = RandomBytes(0x4);
|
||||
return BitConverter.ToInt32(intBytes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ namespace PopsBuilder {
|
|||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace PopsBuilder {
|
|||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PopsBuilder.Resources", typeof(Resources).Assembly);
|
||||
|
@ -51,7 +51,7 @@ namespace PopsBuilder {
|
|||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ namespace PopsBuilder {
|
|||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] DATAPSPSD {
|
||||
public static byte[] DATAPSPSD {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("DATAPSPSD", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
|
@ -73,7 +73,7 @@ namespace PopsBuilder {
|
|||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] DATAPSPSDCFG {
|
||||
public static byte[] DATAPSPSDCFG {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("DATAPSPSDCFG", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
|
@ -83,7 +83,7 @@ namespace PopsBuilder {
|
|||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] SIMPLE {
|
||||
public static byte[] SIMPLE {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("SIMPLE", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
|
@ -93,9 +93,29 @@ namespace PopsBuilder {
|
|||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] STARTDAT {
|
||||
public static byte[] STARTDATMINIS {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("STARTDAT", resourceCulture);
|
||||
object obj = ResourceManager.GetObject("STARTDATMINIS", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] STARTDATPOPS {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("STARTDATPOPS", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] STARTDATPSP {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("STARTDATPSP", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,13 @@
|
|||
<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>
|
||||
<data name="STARTDAT" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\STARTDAT.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<data name="STARTDATMINIS" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\STARTDATMINIS.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="STARTDATPOPS" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\STARTDATPOPS.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="STARTDATPSP" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\STARTDATPSP.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using PspCrypto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
@ -9,11 +10,9 @@ namespace PopsBuilder
|
|||
public class StreamUtil
|
||||
{
|
||||
private Stream s;
|
||||
private Random rng;
|
||||
public StreamUtil(Stream s)
|
||||
{
|
||||
this.s = s;
|
||||
rng = new Random();
|
||||
}
|
||||
|
||||
public void WriteStrWithPadding(string str, byte b, int len)
|
||||
|
@ -30,13 +29,6 @@ namespace PopsBuilder
|
|||
WritePadding(b, (len - sdata.Length));
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteRandom(int len)
|
||||
{
|
||||
byte[] randomBytes = new byte[len];
|
||||
rng.NextBytes(randomBytes);
|
||||
this.WriteBytes(randomBytes);
|
||||
}
|
||||
public byte[] ReadBytes(int len)
|
||||
{
|
||||
byte[] data = new byte[len];
|
||||
|
@ -80,7 +72,10 @@ namespace PopsBuilder
|
|||
{
|
||||
WriteBytes(BitConverter.GetBytes(v));
|
||||
}
|
||||
|
||||
public void WriteInt32BE(Int32 v)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(v).Reverse().ToArray());
|
||||
}
|
||||
public void WriteInt32(Int32 v)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(v));
|
||||
|
@ -98,6 +93,11 @@ namespace PopsBuilder
|
|||
}
|
||||
}
|
||||
|
||||
public void AlignTo(byte padByte, int align)
|
||||
{
|
||||
int padAmt = Convert.ToInt32(align - (s.Position % align));
|
||||
this.WritePadding(padByte, padAmt);
|
||||
}
|
||||
public void PadUntil(byte b, int len)
|
||||
{
|
||||
int remain = Convert.ToInt32(len - s.Length);
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace PspCrypto
|
|||
{
|
||||
public class Lz
|
||||
{
|
||||
public static byte[] compress(byte[] in_buf)
|
||||
public static byte[] compress(byte[] in_buf, bool np9660=false)
|
||||
{
|
||||
//Decoder decoder = new Decoder();
|
||||
//using var inStream = new MemoryStream(@in);
|
||||
|
@ -20,22 +20,21 @@ namespace PspCrypto
|
|||
//decoder.SetDecoderProperties(properties);
|
||||
//decoder.Code(inStream, outStream, insize, size, null);
|
||||
//return 0;
|
||||
var lzrc = new Lzrc();
|
||||
var lzrc = new Lzrc(np9660);
|
||||
|
||||
// create a buffer hopefully big enough to hold compression result
|
||||
byte[] compression_result = new byte[in_buf.Length + 0xffff]; // in worst case (i.e random data),
|
||||
// compression makes the data larger
|
||||
// so have to make sure theres extra space ..
|
||||
// create a buffer big enough to hold compression result
|
||||
byte[] compression_result = new byte[in_buf.Length];
|
||||
// (this could get resized by the compression code, if its too small)
|
||||
|
||||
// compress data, and get the compressed data length
|
||||
int compressed_length = lzrc.lzrc_compress(compression_result, compression_result.Length, in_buf, in_buf.Length);
|
||||
int compressed_length = lzrc.lzrc_compress(ref compression_result, compression_result.Length, in_buf, in_buf.Length);
|
||||
|
||||
// resize array to actual compressed length ...
|
||||
Array.Resize(ref compression_result, compressed_length);
|
||||
|
||||
return compression_result;
|
||||
}
|
||||
public static int decompress(byte[] @out, byte[] @in, int size, int insize)
|
||||
public static int decompress(byte[] @out, byte[] @in, int size, int insize, bool np9660=false)
|
||||
{
|
||||
//Decoder decoder = new Decoder();
|
||||
//using var inStream = new MemoryStream(@in);
|
||||
|
@ -45,7 +44,7 @@ namespace PspCrypto
|
|||
//decoder.SetDecoderProperties(properties);
|
||||
//decoder.Code(inStream, outStream, insize, size, null);
|
||||
//return 0;
|
||||
var lzrc = new Lzrc();
|
||||
var lzrc = new Lzrc(np9660);
|
||||
lzrc.lzrc_decompress(@out, size, @in, insize);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace PspCrypto
|
|||
{
|
||||
public class Lzrc
|
||||
{
|
||||
private bool np9660;
|
||||
|
||||
private byte[] input;
|
||||
private int in_ptr;
|
||||
private int in_len;
|
||||
|
@ -19,11 +21,11 @@ namespace PspCrypto
|
|||
private uint code;
|
||||
private uint out_code;
|
||||
private byte lc;
|
||||
private byte[][] bm_literal = new byte[8][];
|
||||
private byte[][] bm_dist_bits = new byte[8][];
|
||||
private byte[][] bm_dist = new byte[16][];
|
||||
private byte[][] bm_match = new byte[8][];
|
||||
private byte[][] bm_len = new byte[8][];
|
||||
private byte[][] bm_literal;
|
||||
private byte[][] bm_dist_bits;
|
||||
private byte[][] bm_dist;
|
||||
private byte[][] bm_match;
|
||||
private byte[][] bm_len;
|
||||
|
||||
const int max_tbl_sz = 65280;
|
||||
const int tbl_sz = 65536;
|
||||
|
@ -35,6 +37,28 @@ namespace PspCrypto
|
|||
static int[] prev = new int[tbl_sz], next = new int[tbl_sz];
|
||||
static int[] root = new int[tbl_sz];
|
||||
|
||||
public Lzrc(bool np9660 = false)
|
||||
{
|
||||
this.np9660 = np9660;
|
||||
|
||||
if (np9660)
|
||||
{
|
||||
this.bm_literal = new byte[8][];
|
||||
this.bm_dist_bits = new byte[8][];
|
||||
this.bm_dist = new byte[18][];
|
||||
this.bm_match = new byte[8][];
|
||||
this.bm_len = new byte[8][];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bm_literal = new byte[8][];
|
||||
this.bm_dist_bits = new byte[8][];
|
||||
this.bm_dist = new byte[16][];
|
||||
this.bm_match = new byte[8][];
|
||||
this.bm_len = new byte[8][];
|
||||
}
|
||||
}
|
||||
|
||||
static void Init(byte[][] arr, byte value, int length)
|
||||
{
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
|
@ -85,19 +109,23 @@ namespace PspCrypto
|
|||
re_putbyte(lc);
|
||||
|
||||
|
||||
#if NP9660
|
||||
Init(bm_literal, 0x80, 2048);
|
||||
Init(bm_dist_bits, 0x80, 312);
|
||||
Init(bm_dist, 0x80, 144);
|
||||
Init(bm_match, 0x80, 64);
|
||||
Init(bm_len, 0x80, 248);
|
||||
#else
|
||||
Init(bm_literal, 0x80, 256); // 2048 2680 2656
|
||||
Init(bm_dist_bits, 0x80, 23); // 184
|
||||
Init(bm_dist, 0x80, 8); // 128
|
||||
Init(bm_match, 0x80, 8); // 64
|
||||
Init(bm_len, 0x80, 32); // 256
|
||||
#endif
|
||||
if (this.np9660)
|
||||
{
|
||||
Init(bm_literal, 0x80, 256);
|
||||
Init(bm_dist_bits, 0x80, 39);
|
||||
Init(bm_dist, 0x80, 8);
|
||||
Init(bm_match, 0x80, 8);
|
||||
Init(bm_len, 0x80, 31);
|
||||
}
|
||||
else
|
||||
{
|
||||
Init(bm_literal, 0x80, 256); // 2048 2680 2656
|
||||
Init(bm_dist_bits, 0x80, 23); // 184
|
||||
Init(bm_dist, 0x80, 8); // 128
|
||||
Init(bm_match, 0x80, 8); // 64
|
||||
Init(bm_len, 0x80, 32); // 256
|
||||
|
||||
}
|
||||
//memset(re->bm_literal, 0x80, 2048);
|
||||
//memset(re->bm_dist_bits, 0x80, 312);
|
||||
//memset(re->bm_dist, 0x80, 144);
|
||||
|
@ -122,12 +150,25 @@ namespace PspCrypto
|
|||
(rc_getbyte() << 8) |
|
||||
rc_getbyte());
|
||||
out_code = 0xffffffff;
|
||||
|
||||
if (this.np9660)
|
||||
{
|
||||
Init(bm_literal, 0x80, 256);
|
||||
Init(bm_dist_bits, 0x80, 39);
|
||||
Init(bm_dist, 0x80, 8);
|
||||
Init(bm_match, 0x80, 8);
|
||||
Init(bm_len, 0x80, 31);
|
||||
}
|
||||
else
|
||||
{
|
||||
Init(bm_literal, 0x80, 256); // 2048 2680 2656
|
||||
Init(bm_dist_bits, 0x80, 23); // 184
|
||||
Init(bm_dist, 0x80, 8); // 128
|
||||
Init(bm_match, 0x80, 8); // 64
|
||||
Init(bm_len, 0x80, 32); // 256
|
||||
|
||||
}
|
||||
|
||||
Init(bm_literal, 0x80, 256); // 2048 2680 2656
|
||||
Init(bm_dist_bits, 0x80, 23); // 184
|
||||
Init(bm_dist, 0x80, 8); // 128
|
||||
Init(bm_match, 0x80, 8); // 64
|
||||
Init(bm_len, 0x80, 32); // 256
|
||||
}
|
||||
|
||||
void normalize()
|
||||
|
@ -335,16 +376,16 @@ namespace PspCrypto
|
|||
match_len = t_len;
|
||||
match_dist = t_pos;
|
||||
|
||||
if (in_ptr == in_len)
|
||||
if (in_ptr >= in_len)
|
||||
{
|
||||
match_len = 256;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_ptr == (in_len - 1))
|
||||
if (in_ptr >= (in_len - 1))
|
||||
return 0;
|
||||
|
||||
t = text_buf[pos+0];
|
||||
t = text_buf[pos];
|
||||
t = (t << 8) | text_buf[pos+1];
|
||||
if (root[t] == -1)
|
||||
{
|
||||
|
@ -395,6 +436,14 @@ namespace PspCrypto
|
|||
p = next[p];
|
||||
}
|
||||
|
||||
if (this.np9660)
|
||||
{
|
||||
// have we calculated match_dist of 256 when its not the end?
|
||||
if (t_len == 256 && in_ptr < in_len)
|
||||
return 1;
|
||||
}
|
||||
if (t_pos < 0) throw new Exception("t_pos was < 0 :?"); // TODO: figure out why this happens on np9660.
|
||||
|
||||
match_len = t_len;
|
||||
match_dist = t_pos;
|
||||
|
||||
|
@ -447,14 +496,12 @@ namespace PspCrypto
|
|||
|
||||
do
|
||||
{
|
||||
|
||||
tmp = number >> n;
|
||||
bit = (number >> (n - 1)) & 1;
|
||||
re_bit(ref probs, index + tmp, bit);
|
||||
|
||||
n -= 1;
|
||||
} while (n > 0);
|
||||
//number = (res_number - limit);
|
||||
}
|
||||
|
||||
void re_bit(ref byte[] prob, int index, int bit)
|
||||
|
@ -520,7 +567,8 @@ namespace PspCrypto
|
|||
{
|
||||
if (out_ptr == out_len)
|
||||
{
|
||||
throw new Exception("Output overflow!");
|
||||
out_len += 0x100;
|
||||
Array.Resize(ref output, out_len);
|
||||
}
|
||||
|
||||
output[out_ptr++] = out_byte;
|
||||
|
@ -589,7 +637,7 @@ namespace PspCrypto
|
|||
re_putbyte((byte)((code >> 8) & 0xff));
|
||||
re_putbyte((byte)((code >> 0) & 0xff));
|
||||
}
|
||||
public int lzrc_compress(byte[] out_buf, int out_len, byte[] in_buf, int in_len)
|
||||
public int lzrc_compress(ref byte[] out_buf, int out_len, byte[] in_buf, int in_len)
|
||||
{
|
||||
int match_step, re_state, len_state, dist_state;
|
||||
int i, cur_byte, last_byte;
|
||||
|
@ -610,6 +658,8 @@ namespace PspCrypto
|
|||
last_byte = 0;
|
||||
match_len = 0;
|
||||
match_dist = 0;
|
||||
|
||||
bool flg = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -621,19 +671,24 @@ namespace PspCrypto
|
|||
|
||||
if (match_len < 256)
|
||||
{
|
||||
#if NP9660
|
||||
if (match_len < 4 && match_dist > 255)
|
||||
#else
|
||||
if (match_len <= 4 && match_dist > 255)
|
||||
#endif
|
||||
// condition is different if np9660 vs pops
|
||||
if (this.np9660)
|
||||
flg = (match_len < 4 && match_dist > 255);
|
||||
else
|
||||
flg = (match_len <= 4 && match_dist > 255);
|
||||
|
||||
if(flg) // if (condition)
|
||||
match_len = 1;
|
||||
update_tree(match_len);
|
||||
}
|
||||
#if NP9660
|
||||
if ((match_len == 1 || (match_len < 4 && match_dist > 255)))
|
||||
#else
|
||||
if ((match_len == 1 || (match_len <= 4 && match_dist > 255)))
|
||||
#endif
|
||||
|
||||
// condition is different if np9660 vs pops
|
||||
if (this.np9660)
|
||||
flg = (match_len == 1 || (match_len < 4 && match_dist > 255));
|
||||
else
|
||||
flg = (match_len == 1 || (match_len <= 4 && match_dist > 255));
|
||||
|
||||
if (flg)
|
||||
{
|
||||
re_bit(ref bm_match[re_state], match_step, 0);
|
||||
|
||||
|
@ -643,7 +698,7 @@ namespace PspCrypto
|
|||
cur_byte = re_getbyte();
|
||||
re_bittree(ref bm_literal[((last_byte >> lc) & 0x07)], 0, 0x100, cur_byte);
|
||||
|
||||
if (in_ptr == in_len)
|
||||
if (in_ptr >= in_len)
|
||||
{
|
||||
re_normalize();
|
||||
re_flush();
|
||||
|
@ -665,44 +720,51 @@ namespace PspCrypto
|
|||
len_bits += 1;
|
||||
}
|
||||
if (i != 8)
|
||||
{
|
||||
re_bit(ref bm_match[re_state], match_step, 0);
|
||||
}
|
||||
|
||||
if (len_bits > 0)
|
||||
{
|
||||
len_state = ((len_bits - 1) << 2) + ((in_ptr << (len_bits - 1)) & 0x03);
|
||||
re_number(ref bm_len[re_state], len_state, len_bits, (match_len - 1));
|
||||
|
||||
if (in_ptr == in_len)
|
||||
if (this.np9660)
|
||||
flg = (match_len == 256);
|
||||
else
|
||||
flg = (in_ptr >= in_len);
|
||||
|
||||
if (flg)
|
||||
{
|
||||
re_normalize();
|
||||
re_flush();
|
||||
return out_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// determine limit ...
|
||||
dist_state = 0;
|
||||
limit = 8;
|
||||
#if NP9660
|
||||
if ( match_len > 3)
|
||||
#else
|
||||
if( (match_len) > 4 )
|
||||
#endif
|
||||
|
||||
// condition is different if np9660 vs pops
|
||||
if (this.np9660)
|
||||
flg = (match_len > 3);
|
||||
else
|
||||
flg = (match_len > 4);
|
||||
|
||||
|
||||
if (flg) // if (condition)
|
||||
{
|
||||
dist_state += 7;
|
||||
#if NP9660
|
||||
limit = 44;
|
||||
#else
|
||||
limit = 16;
|
||||
#endif
|
||||
|
||||
if (this.np9660)
|
||||
limit = 44;
|
||||
else
|
||||
limit = 16;
|
||||
|
||||
}
|
||||
|
||||
// find total 1s in the match_dist
|
||||
dist_bits = 0;
|
||||
if(match_dist != 0) {
|
||||
if(match_dist > 0) {
|
||||
while ((match_dist >> dist_bits) != 1)
|
||||
dist_bits += 1;
|
||||
}
|
||||
|
@ -714,9 +776,7 @@ namespace PspCrypto
|
|||
re_bittree(ref bm_dist_bits[len_bits], dist_state, limit, dist_bits);
|
||||
|
||||
if (dist_bits > 0)
|
||||
{
|
||||
re_number(ref bm_dist[dist_bits], 0, dist_bits, match_dist);
|
||||
}
|
||||
|
||||
|
||||
in_ptr += match_len;
|
||||
|
@ -736,15 +796,16 @@ namespace PspCrypto
|
|||
int match_src;
|
||||
int round = -1;
|
||||
|
||||
bool flg = false;
|
||||
len_state = 0;
|
||||
|
||||
rc_init(out_buf, out_len, in_buf, in_len);
|
||||
|
||||
if ((lc & 0x80) != 0)
|
||||
/*if ((lc & 0x80) != 0)
|
||||
{
|
||||
Buffer.BlockCopy(in_buf, 5, out_buf, 0, (int)code);
|
||||
return (int)code;
|
||||
}
|
||||
}*/
|
||||
|
||||
rc_state = 0;
|
||||
last_byte = 0;
|
||||
|
@ -758,9 +819,7 @@ namespace PspCrypto
|
|||
if (bit == 0)
|
||||
{
|
||||
if (rc_state > 0)
|
||||
{
|
||||
rc_state -= 1;
|
||||
}
|
||||
|
||||
cur_byte = rc_bittree(bm_literal[(((out_ptr & 7) << 8) + last_byte >> lc) & 0x07], 0, 0x100);
|
||||
|
||||
|
@ -789,29 +848,31 @@ namespace PspCrypto
|
|||
{
|
||||
len_state = ((len_bits - 1) << 2) + ((out_ptr << (len_bits - 1)) & 0x03);
|
||||
match_len = rc_number(bm_len[rc_state], len_state, len_bits);
|
||||
//if ((match_len == 0xFF || match_len == 0xFE) && out_ptr == out_len)
|
||||
//{
|
||||
// return out_ptr;
|
||||
//}
|
||||
if (this.np9660 && match_len == 0xFF)
|
||||
return out_ptr;
|
||||
}
|
||||
|
||||
dist_state = 0;
|
||||
limit = 8;
|
||||
if (match_len > 3)
|
||||
if (this.np9660)
|
||||
flg = (match_len > 2);
|
||||
else
|
||||
flg = (match_len > 3);
|
||||
|
||||
if (flg)
|
||||
{
|
||||
dist_state += 7;
|
||||
limit = 16;
|
||||
if (this.np9660)
|
||||
limit = 44;
|
||||
else
|
||||
limit = 16;
|
||||
}
|
||||
dist_bits = rc_bittree(bm_dist_bits[len_bits], dist_state, limit);
|
||||
|
||||
if (dist_bits > 0)
|
||||
{
|
||||
match_dist = rc_number(bm_dist[dist_bits], 0, dist_bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
match_dist = 1;
|
||||
}
|
||||
|
||||
match_src = out_ptr - match_dist;
|
||||
if (match_dist > out_ptr || match_dist < 0)
|
||||
|
|
Loading…
Reference in New Issue