Add UMD Reader

This commit is contained in:
Li 2023-04-17 01:07:43 +12:00
parent 50c91e024c
commit 9cb01e4a4b
28 changed files with 478 additions and 74 deletions

View File

@ -11,7 +11,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PopsBuilder\PopsBuilder.csproj" />
<ProjectReference Include="..\PopsBuilder\GameBuilder.csproj" />
<ProjectReference Include="..\PspCrypto\PspCrypto.csproj" />
<ProjectReference Include="..\PsvImage\PsvImage.csproj" />
</ItemGroup>

View File

@ -1,7 +1,7 @@
using CommunityToolkit.HighPerformance;
using Ionic.Zlib;
using PopsBuilder.Pops;
using PopsBuilder.Psp;
using GameBuilder.Pops;
using GameBuilder.Psp;
using PspCrypto;
using PsvImage;
using System;
@ -11,6 +11,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
namespace PbpResign
{
@ -1074,13 +1075,19 @@ namespace PbpResign
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"), true);
UmdDisc disc = new UmdDisc("fft.iso");
NpUmdImg npumd = new NpUmdImg(new NpDrmInfo(NewVersionKey.ToArray(), CId, npHdr.NpFlags), disc, 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");
PbpBuilder.CreatePbp(disc.DataFiles["PARAM.SFO"],
disc.DataFiles["ICON0.PNG"],
disc.DataFiles["ICON1.PMF"],
disc.DataFiles["PIC0.PNG"],
disc.DataFiles["PIC1.PNG"],
disc.DataFiles["SND0.AT3"],
npumd,
"FFT.PBP");
return CopyNpUmdImg(input, output, pbpHdr, psarBuff, npHdr);
}

View File

@ -8,7 +8,7 @@ using System.Threading.Channels;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace PopsBuilder.Atrac3
namespace GameBuilder.Atrac3
{
public class Atrac3ToolEncoder : IAtracEncoderBase
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Atrac3
namespace GameBuilder.Atrac3
{
public interface IAtracEncoderBase
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Cue
namespace GameBuilder.Cue
{
public class CueIndex
{

View File

@ -5,7 +5,7 @@ using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Cue
namespace GameBuilder.Cue
{
public class CueReader : IDisposable
{

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Cue
namespace GameBuilder.Cue
{
public class CueStream : Stream
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Cue
namespace GameBuilder.Cue
{
public class CueTrack
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Cue
namespace GameBuilder.Cue
{
public enum TrackType
{

View File

@ -6,6 +6,11 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DiscUtils.Core" Version="0.16.13" />
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PspCrypto\PspCrypto.csproj" />
</ItemGroup>

26
PopsBuilder/MathUtil.cs Normal file
View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder
{
public static class MathUtil
{
public static int CalculateDifference(int val1, int val2)
{
int smaller = Convert.ToInt32(Math.Min(val1, val2));
int larger = Convert.ToInt32(Math.Max(val1, val2));
return larger - smaller;
}
public static int CalculatePaddingAmount(int total, int alignTo)
{
int remainder = total % alignTo;
int padAmt = alignTo - (remainder);
if ((remainder) == 0) return 0;
return padAmt;
}
}
}

View File

@ -1,6 +1,6 @@
using PopsBuilder.Atrac3;
using PopsBuilder.Cue;
using PopsBuilder.Psp;
using GameBuilder.Atrac3;
using GameBuilder.Cue;
using GameBuilder.Psp;
using PspCrypto;
using System;
using System.Collections.Generic;
@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Pops
namespace GameBuilder.Pops
{
public class DiscCompressor
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Pops
namespace GameBuilder.Pops
{
public class DiscInfo
{

View File

@ -1,11 +1,11 @@
using PopsBuilder.Cue;
using GameBuilder.Cue;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Pops
namespace GameBuilder.Pops
{
public class EccRemoverStream : Stream
{

View File

@ -1,5 +1,5 @@
using Org.BouncyCastle.Crypto.Paddings;
using PopsBuilder.Psp;
using GameBuilder;
using GameBuilder.Psp;
using PspCrypto;
using System;
using System.Collections.Generic;
@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Pops
namespace GameBuilder.Pops
{
public class PopsImg : NpDrmPsar
{

View File

@ -1,14 +1,14 @@
using Org.BouncyCastle.Crypto.Paddings;
using PopsBuilder.Atrac3;
using PopsBuilder.Cue;
using PopsBuilder.Psp;
using GameBuilder.Atrac3;
using GameBuilder.Cue;
using GameBuilder.Psp;
using PspCrypto;
using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
namespace PopsBuilder.Pops
namespace GameBuilder.Pops
{
public class PsIsoImg : PopsImg
{

View File

@ -1,5 +1,5 @@
using PopsBuilder.Atrac3;
using PopsBuilder.Psp;
using GameBuilder.Atrac3;
using GameBuilder.Psp;
using PspCrypto;
using System;
using System.Collections.Generic;
@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Pops
namespace GameBuilder.Pops
{
public class PsTitleImg : PopsImg
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Psp
namespace GameBuilder.Psp
{
public class NpDrmInfo
{

View File

@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Psp
namespace GameBuilder.Psp
{
public abstract class NpDrmPsar : IDisposable
{

View File

@ -1,6 +1,6 @@
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Ocsp;
using PopsBuilder.Pops;
using GameBuilder.Pops;
using PspCrypto;
using System;
using System.Collections.Generic;
@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Psp
namespace GameBuilder.Psp
{
public class NpUmdImg : NpDrmPsar
{
@ -18,9 +18,8 @@ namespace PopsBuilder.Psp
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)
public NpUmdImg(NpDrmInfo drmInfo, UmdDisc umdImage, bool compress) : base(drmInfo)
{
this.isoStream = File.OpenRead(iso);
this.compress = compress;
this.npHdr = new MemoryStream();
@ -37,13 +36,18 @@ namespace PopsBuilder.Psp
this.headerKey = Rng.RandomBytes(0x10);
this.discId = discId.ToUpperInvariant().Replace("-", "").Replace("_", "");
this.paramSfo = paramSfo;
isoBlocks = Convert.ToInt64((isoStream.Length + BLOCK_SZ - 1) / BLOCK_SZ);
this.umdImage = umdImage;
isoBlocks = Convert.ToInt64((umdImage.IsoStream.Length + BLOCK_SZ - 1) / BLOCK_SZ);
}
private void patchSfo()
{
Sfo sfoKeys = Sfo.ReadSfo(umdImage.DataFiles["PARAM.SFO"]);
sfoKeys["DISC_ID"] = DrmInfo.ContentId.Substring(7, 9);
umdImage.DataFiles["PARAM.SFO"] = sfoKeys.WriteSfo();
}
private void createNpHdr()
{
npHdrUtil.WriteStr("NPUMDIMG");
@ -69,6 +73,8 @@ namespace PopsBuilder.Psp
public void CreatePsar()
{
patchSfo();
createNpUmdTbl();
byte[] tbl = encryptTable();
this.dataKey = hashBlock(tbl);
@ -102,7 +108,7 @@ namespace PopsBuilder.Psp
using (MemoryStream dataPsp = new MemoryStream())
{
StreamUtil dataPspUtil = new StreamUtil(dataPsp);
byte[] signature = signParamSfo(paramSfo);
byte[] signature = signParamSfo(umdImage.DataFiles["PARAM.SFO"]);
dataPspUtil.WriteBytes(signature);
dataPspUtil.WritePadding(0x00, 0x530);
dataPspUtil.WriteStrWithPadding(DrmInfo.ContentId, 0x00, 0x30);
@ -118,14 +124,14 @@ namespace PopsBuilder.Psp
private void createNpUmdTbl()
{
Int64 tableSz = isoBlocks * 0x20;
Int64 isoSz = this.isoStream.Length;
Int64 isoSz = umdImage.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);
wsize = umdImage.IsoStream.Read(isoBuf, 0x00, BLOCK_SZ);
byte[] wbuf = isoBuf;
@ -140,13 +146,14 @@ namespace PopsBuilder.Psp
{
wbuf = lzRcBuf;
wsize = (lzRcBuf.Length + 15) & ~15;
wsize = lzRcBuf.Length;
wsize += MathUtil.CalculatePaddingAmount(wsize, 16);
Array.Resize(ref lzRcBuf, wsize);
}
}
int unpaddedSz = wsize;
wsize = (wsize + 15) & ~15;
wsize += MathUtil.CalculatePaddingAmount(wsize, 16);
Array.Resize(ref wbuf, wsize);
encryptBlock(wbuf, Convert.ToInt32(isoOffset));
byte[] hash = hashBlock(wbuf);
@ -162,7 +169,7 @@ namespace PopsBuilder.Psp
isoOffset += wsize;
Console.Write(Convert.ToInt32(Math.Floor((Convert.ToDouble(isoStream.Position) / Convert.ToDouble(isoStream.Length)) * 100.0)) + "%\r");
Console.Write(Convert.ToInt32(Math.Floor((Convert.ToDouble(umdImage.IsoStream.Position) / Convert.ToDouble(umdImage.IsoStream.Length)) * 100.0)) + "%\r");
}
}
@ -215,7 +222,7 @@ namespace PopsBuilder.Psp
{
npHdrBodyUtil.WriteUInt16(SECTOR_SZ); // sector_sz
if (isoStream.Length > 0x40000000)
if (umdImage.IsoStream.Length > 0x40000000)
npHdrBodyUtil.WriteUInt16(0xE001); // unk_2
else
npHdrBodyUtil.WriteUInt16(0xE000); //unk_2
@ -236,7 +243,7 @@ namespace PopsBuilder.Psp
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.WriteStrWithPadding(umdImage.DiscIdSeperated, 0x00, 0x10);
npHdrBodyUtil.WriteInt32(0); // header_start_offset
npHdrBodyUtil.WriteInt32(0); // unk_68
@ -266,14 +273,11 @@ namespace PopsBuilder.Psp
private Int64 isoBlocks;
private bool compress;
private string discId;
private byte[] paramSfo;
UmdDisc umdImage;
private byte[] headerKey;
private byte[] dataKey;
private FileStream isoStream;
private MemoryStream npHdr;
private StreamUtil npHdrUtil;

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Psp
namespace GameBuilder.Psp
{
public static class PbpBuilder
{
@ -16,7 +16,9 @@ namespace PopsBuilder.Psp
using (FileStream pbpStream = File.Open(outputFile, FileMode.Create))
{
byte[] dataPsp = dataPsar.GenerateDataPsp();
int padLen = Convert.ToInt32(0x100 - (dataPsp.Length % 0x100));
int padLen = MathUtil.CalculatePaddingAmount(dataPsp.Length, 0x100);
Array.Resize(ref dataPsp, dataPsp.Length + padLen);
StreamUtil pbpUtil = new StreamUtil(pbpStream);

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder.Psp
namespace GameBuilder.Psp
{
public static class Rng
{

230
PopsBuilder/Psp/Sfo.cs Normal file
View File

@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.IO;
using System.Runtime.CompilerServices;
// A Sfo Parser Written by SilicaAndPina
// Because all the others are overly-complicated for no reason!
// MIT Licensed.
namespace GameBuilder.Psp
{
public class Sfo
{
private struct SfoEntry
{
internal string keyName;
internal byte type;
internal UInt32 valueSize;
internal UInt32 totalSize;
internal byte align;
internal object value;
}
const int SFO_MAGIC = 0x46535000;
const byte PSF_TYPE_BIN = 0;
const byte PSF_TYPE_STR = 2;
const byte PSF_TYPE_VAL = 4;
private Dictionary<string, SfoEntry> sfoEntries;
public Object this[string index]
{
get
{
return sfoEntries[index].value;
}
set
{
SfoEntry sfoEnt = sfoEntries[index];
sfoEnt.value = value;
// update sz
sfoEnt.valueSize = getObjectSz(sfoEnt.value);
if (sfoEnt.valueSize > sfoEnt.totalSize)
sfoEnt.totalSize = Convert.ToUInt32(MathUtil.CalculatePaddingAmount(Convert.ToInt32(sfoEnt.valueSize), sfoEnt.align));
// update type
sfoEnt.type = getPsfType(sfoEnt.value);
sfoEntries[index] = sfoEnt;
}
}
public Sfo()
{
sfoEntries = new Dictionary<string, SfoEntry>();
}
private static UInt32 getObjectSz(Object obj)
{
if (obj is Int32) return 4;
if (obj is UInt32) return 4;
if (obj is String) return Convert.ToUInt32((obj as String).Length+1);
if (obj is Byte[]) return Convert.ToUInt32((obj as Byte[]).Length);
throw new Exception("Object is of unsupported type: " + obj.GetType());
}
private static byte getPsfType(Object obj)
{
if (obj is Int32 || obj is UInt32) return PSF_TYPE_VAL;
if (obj is String) return PSF_TYPE_STR;
if (obj is Byte[]) return PSF_TYPE_BIN;
throw new Exception("Object is of unsupported type: " + obj.GetType());
}
public byte[] WriteSfo(UInt32 version = 0x101, Byte align = 0x4)
{
using (MemoryStream sfoStream = new MemoryStream())
{
WriteSfo(sfoStream, version, align);
byte[] sfoBytes = sfoStream.ToArray();
return sfoBytes;
}
}
public void WriteSfo(Stream SfoStream, UInt32 version=0x101, Byte align=0x4)
{
using(MemoryStream sfoStream = new MemoryStream())
{
StreamUtil sfoUtil = new StreamUtil(sfoStream);
sfoUtil.WriteUInt32(SFO_MAGIC);
sfoUtil.WriteUInt32(version);
sfoUtil.WriteUInt32(0xFFFFFFFF); // key offset
sfoUtil.WriteUInt32(0xFFFFFFFF); // value offset
// (will fill these in after the file is created)
sfoUtil.WriteInt32(sfoEntries.Count);
using (MemoryStream keyTable = new MemoryStream())
{
StreamUtil keyUtils = new StreamUtil(keyTable);
using (MemoryStream valueTable = new MemoryStream())
{
StreamUtil valueUtils = new StreamUtil(valueTable);
foreach (SfoEntry entry in sfoEntries.Values)
{
// write name
sfoUtil.WriteUInt16(Convert.ToUInt16(keyTable.Position));
keyUtils.WriteCStr(entry.keyName);
// write entry
sfoUtil.WriteByte(align); // align
sfoUtil.WriteByte(entry.type); // type
sfoUtil.WriteUInt32(entry.valueSize); // valueSize
sfoUtil.WriteUInt32(entry.totalSize); // totalSize
// write data
sfoUtil.WriteUInt32(Convert.ToUInt32(valueTable.Position)); // dataOffset
switch (entry.type)
{
case PSF_TYPE_VAL:
valueUtils.WriteUInt32(Convert.ToUInt32(entry.value));
valueUtils.WritePadding(0x00, Convert.ToInt32(entry.totalSize - entry.valueSize));
break;
case PSF_TYPE_STR:
valueUtils.WriteStrWithPadding(entry.value as String, 0x00, Convert.ToInt32(entry.totalSize));
break;
case PSF_TYPE_BIN:
valueUtils.WriteBytesWithPadding(entry.value as Byte[], 0x00, Convert.ToInt32(entry.totalSize));
break;
}
}
keyUtils.AlignTo(0x00, align);
UInt32 keyOffset = Convert.ToUInt32(sfoStream.Position);
keyTable.Seek(0x00, SeekOrigin.Begin);
keyTable.CopyTo(sfoStream);
UInt32 valueOffset = Convert.ToUInt32(sfoStream.Position);
valueTable.Seek(0x00, SeekOrigin.Begin);
valueTable.CopyTo(sfoStream);
sfoStream.Seek(0x8, SeekOrigin.Begin);
sfoUtil.WriteUInt32(keyOffset); // key offset
sfoUtil.WriteUInt32(valueOffset); // value offset
}
}
sfoStream.Seek(0x0, SeekOrigin.Begin);
sfoStream.CopyTo(SfoStream);
}
}
public static Sfo ReadSfo(Stream SfoStream)
{
Sfo sfoFile = new Sfo();
StreamUtil DataUtils = new StreamUtil(SfoStream);
// Read Sfo Header
UInt32 magic = DataUtils.ReadUInt32();
UInt32 version = DataUtils.ReadUInt32();
UInt32 keyOffset = DataUtils.ReadUInt32();
UInt32 valueOffset = DataUtils.ReadUInt32();
UInt32 count = DataUtils.ReadUInt32();
if (magic == SFO_MAGIC) //\x00PSF
{
for(int i = 0; i < count; i++)
{
SfoEntry entry = new SfoEntry();
UInt16 nameOffset = DataUtils.ReadUInt16();
entry.align = DataUtils.ReadByte();
entry.type = DataUtils.ReadByte();
entry.valueSize = DataUtils.ReadUInt32();
entry.totalSize = DataUtils.ReadUInt32();
UInt32 dataOffset = DataUtils.ReadUInt32();
int keyLocation = Convert.ToInt32(keyOffset + nameOffset);
entry.keyName = DataUtils.ReadStringAt(keyLocation);
int valueLocation = Convert.ToInt32(valueOffset + dataOffset);
switch (entry.type)
{
case PSF_TYPE_STR:
entry.value = DataUtils.ReadStringAt(valueLocation);
break;
case PSF_TYPE_VAL:
entry.value = DataUtils.ReadUint32At(valueLocation);
break;
case PSF_TYPE_BIN:
entry.value = DataUtils.ReadBytesAt(valueLocation, Convert.ToInt32(entry.valueSize));
break;
}
sfoFile.sfoEntries[entry.keyName] = entry;
}
}
else
{
throw new InvalidDataException("Sfo Magic is Invalid.");
}
return sfoFile;
}
public static Sfo ReadSfo(byte[] Sfo)
{
using (MemoryStream SfoStream = new MemoryStream(Sfo))
{
return ReadSfo(SfoStream);
}
}
}
}

View File

@ -0,0 +1,77 @@
using DiscUtils.Iso9660;
using DiscUtils.Streams;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder.Psp
{
public class UmdDisc : IDisposable
{
private string[] filesList = new string[]
{
"PSP_GAME\\ICON0.PNG",
"PSP_GAME\\ICON1.PMF",
"PSP_GAME\\PARAM.SFO",
"PSP_GAME\\PIC0.PNG",
"PSP_GAME\\PIC1.PNG",
"PSP_GAME\\SND0.AT3"
};
public Dictionary<string, byte[]?> DataFiles = new Dictionary<string, byte[]?>();
public UmdDisc(string isoFile)
{
this.IsoFile = isoFile;
this.IsoStream = File.OpenRead(isoFile);
using (CDReader cdReader = new CDReader(this.IsoStream, true, true))
{
foreach (string file in filesList)
{
string fname = Path.GetFileName(file).ToUpperInvariant();
if (cdReader.FileExists(file))
{
using (SparseStream s = cdReader.OpenFile(file, FileMode.Open))
{
byte[] data = new byte[s.Length];
s.Read(data, 0x00, data.Length);
DataFiles[fname] = data;
}
}
else
{
DataFiles[fname] = null;
}
}
}
if (DataFiles["PARAM.SFO"] is null) throw new Exception("ISO contains no PARAM.SFO file, so this is not a valid PSP game.");
Sfo sfo = Sfo.ReadSfo(DataFiles["PARAM.SFO"]);
this.DiscId = sfo["DISC_ID"] as String;
IsoStream.Seek(0x00, SeekOrigin.Begin);
}
public string IsoFile;
public FileStream IsoStream;
public string DiscId;
public string DiscIdSeperated
{
get
{
return this.DiscId.Substring(0, 4) + "-" + this.DiscId.Substring(4, 5);
}
}
public void Dispose()
{
IsoStream.Dispose();
}
}
}

View File

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace PopsBuilder {
namespace GameBuilder {
using System;
@ -39,7 +39,7 @@ namespace PopsBuilder {
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);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GameBuilder.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder
namespace GameBuilder
{
public class StreamUtil
{
@ -14,21 +14,50 @@ namespace PopsBuilder
{
this.s = s;
}
public void WriteStrWithPadding(string str, byte b, int len)
public string ReadString()
{
byte[] sdata = Encoding.UTF8.GetBytes(str);
if (len < sdata.Length)
using (MemoryStream ms = new MemoryStream())
{
s.Write(sdata, 0, len);
return;
}
else
{
WriteBytes(sdata);
WritePadding(b, (len - sdata.Length));
while (true)
{
byte c = (byte)s.ReadByte();
if (c == 0)
break;
ms.WriteByte(c);
}
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public UInt32 ReadUint32At(int location)
{
long oldPos = s.Position;
s.Seek(location, SeekOrigin.Begin);
UInt32 outp = ReadUInt32();
s.Seek(oldPos, SeekOrigin.Begin);
return outp;
}
public byte[] ReadBytesAt(int location, int length)
{
long oldPos = s.Position;
s.Seek(location, SeekOrigin.Begin);
byte[] work_buf = ReadBytes(length);
s.Seek(oldPos, SeekOrigin.Begin);
return work_buf;
}
public string ReadStringAt(int location)
{
long oldPos = s.Position;
s.Seek(location, SeekOrigin.Begin);
string outp = ReadString();
s.Seek(oldPos, SeekOrigin.Begin);
return outp;
}
public byte ReadByte()
{
return (byte)s.ReadByte();
}
public byte[] ReadBytes(int len)
{
byte[] data = new byte[len];
@ -55,6 +84,23 @@ namespace PopsBuilder
byte[] vbytes = ReadBytes(0x4);
return BitConverter.ToInt32(vbytes);
}
public void WriteBytesWithPadding(byte[] data, byte b, int len)
{
if (len < data.Length)
{
s.Write(data, 0, len);
return;
}
else
{
WriteBytes(data);
WritePadding(b, (len - data.Length));
}
}
public void WriteStrWithPadding(string str, byte b, int len)
{
WriteBytesWithPadding(Encoding.UTF8.GetBytes(str), b, len);
}
public void WriteInt64(Int64 v)
{
WriteBytes(BitConverter.GetBytes(v));
@ -80,6 +126,11 @@ namespace PopsBuilder
{
WriteBytes(BitConverter.GetBytes(v));
}
public void WriteCStr(string str)
{
WriteStr(str);
WriteByte(0x00);
}
public void WriteStr(string str)
{
WriteBytes(Encoding.UTF8.GetBytes(str));
@ -87,6 +138,7 @@ namespace PopsBuilder
public void WritePadding(byte b, int len)
{
if (len < 0) return;
for(int i = 0; i < len; i++)
{
WriteByte(b);
@ -95,7 +147,8 @@ namespace PopsBuilder
public void AlignTo(byte padByte, int align)
{
int padAmt = Convert.ToInt32(align - (s.Position % align));
int padAmt = MathUtil.CalculatePaddingAmount(Convert.ToInt32(s.Position), align);
this.WritePadding(padByte, padAmt);
}
public void PadUntil(byte b, int len)

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PopsBuilder
namespace GameBuilder
{
public class xXEccD3str0yerXx
{
@ -42,7 +42,7 @@ namespace PopsBuilder
}
// extend ISO image to compress block sz
int padLen = COMPRESS_BLOCK_SZ - (Convert.ToInt32(noEccIso.Length) % COMPRESS_BLOCK_SZ);
int padLen = MathUtil.CalculatePaddingAmount(Convert.ToInt32(noEccIso.Length), COMPRESS_BLOCK_SZ);
byte[] padding = new byte[padLen];
noEccIso.Write(padding, 0x00, padding.Length);

View File

@ -9,7 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PbpResign", "PbpResign\PbpR
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PsvImage", "PsvImage\PsvImage.csproj", "{0F4A59D9-FF92-4B4F-BDC4-4BC473F9AA5C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PopsBuilder", "PopsBuilder\PopsBuilder.csproj", "{D1DF66DB-52BE-489C-A292-525BC71F2BB2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameBuilder", "PopsBuilder\GameBuilder.csproj", "{D1DF66DB-52BE-489C-A292-525BC71F2BB2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution