177 lines
5.7 KiB
C#
177 lines
5.7 KiB
C#
using LibXom.Streams;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Reflection.PortableExecutable;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace LibW4M.PS2
|
|
{
|
|
public class PsuFile
|
|
{
|
|
public PsuFile()
|
|
{
|
|
entries = new List<PsuFileEntry>();
|
|
}
|
|
|
|
private List<PsuFileEntry> entries;
|
|
|
|
|
|
public PsuFileEntry[] Entires
|
|
{
|
|
get
|
|
{
|
|
return entries.ToArray();
|
|
}
|
|
}
|
|
|
|
public PsuFileEntry[] Files
|
|
{
|
|
get
|
|
{
|
|
List<PsuFileEntry> tmpList = new List<PsuFileEntry>();
|
|
|
|
foreach (PsuFileEntry entry in entries)
|
|
{
|
|
if (entry.EntryType == PsuEntryType.FILE_ENTRY || entry.EntryType == PsuEntryType.SYSTEM_ENTRY)
|
|
{
|
|
tmpList.Add(entry);
|
|
}
|
|
}
|
|
|
|
return tmpList.ToArray();
|
|
}
|
|
}
|
|
public PsuFileEntry[] Directorys
|
|
{
|
|
get
|
|
{
|
|
List<PsuFileEntry> tmpList = new List<PsuFileEntry>();
|
|
|
|
foreach (PsuFileEntry entry in entries)
|
|
{
|
|
if (entry.EntryType == PsuEntryType.DIRECTORY_ENTRY)
|
|
{
|
|
tmpList.Add(entry);
|
|
}
|
|
}
|
|
|
|
return tmpList.ToArray();
|
|
}
|
|
}
|
|
|
|
public void CreateDirectory(string directoryName)
|
|
{
|
|
this.entries.Add(new PsuFileEntry(PsuEntryType.DIRECTORY_ENTRY, 0x00, DateTime.Now, 0, DateTime.Now, directoryName, null));
|
|
this.entries[0].directoryEntries = this.entries.Count - 1;
|
|
}
|
|
|
|
public void CreateFile(string fileName, byte[] data)
|
|
{
|
|
this.entries.Add(new PsuFileEntry(PsuEntryType.FILE_ENTRY, data.Length, DateTime.Now, 0, DateTime.Now, fileName, data));
|
|
this.entries[0].directoryEntries = this.entries.Count - 1;
|
|
}
|
|
|
|
public void CreateSystemFile(string fileName, byte[] data)
|
|
{
|
|
this.entries.Add(new PsuFileEntry(PsuEntryType.SYSTEM_ENTRY, data.Length, DateTime.Now, 0, DateTime.Now, fileName, data));
|
|
this.entries[0].directoryEntries = this.entries.Count - 1;
|
|
}
|
|
|
|
public void InitalizePSU(string titleId)
|
|
{
|
|
this.entries.Clear();
|
|
CreateDirectory(titleId);
|
|
CreateDirectory(".");
|
|
CreateDirectory("..");
|
|
}
|
|
|
|
public PsuFileEntry GetFileByName(string filename)
|
|
{
|
|
foreach(PsuFileEntry entry in this.Files)
|
|
{
|
|
if(entry.Filename.Equals(filename, StringComparison.InvariantCulture))
|
|
{
|
|
return entry;
|
|
}
|
|
}
|
|
|
|
throw new FileNotFoundException("Cannot find any file named \""+filename+"\" in the PSU.");
|
|
}
|
|
|
|
public static PsuFile ReadPSU(string psuFilePath)
|
|
{
|
|
PsuFile psuFile = new PsuFile();
|
|
psuFile.ReadPSU(File.OpenRead(psuFilePath));
|
|
return psuFile;
|
|
}
|
|
|
|
public void WritePSU(Stream psuStream)
|
|
{
|
|
using (XomStreamWriter writer = new XomStreamWriter(psuStream))
|
|
{
|
|
|
|
foreach (PsuFileEntry fileEntry in this.Entires)
|
|
{
|
|
writer.WriteUInt16((ushort)fileEntry.EntryType);
|
|
writer.Skip(0x02);
|
|
writer.WriteInt32(fileEntry.Filesize);
|
|
writer.Skip(0x01);
|
|
writer.WriteDateTime(fileEntry.CreationDate);
|
|
writer.WriteUInt16(fileEntry.Sector);
|
|
writer.Skip(0x07);
|
|
writer.WriteDateTime(fileEntry.ModifiedDate);
|
|
writer.Skip(0x20);
|
|
writer.WriteStrLen(fileEntry.Filename, 0x1C0);
|
|
|
|
if(fileEntry.FileData != Stream.Null)
|
|
{
|
|
fileEntry.FileData.Seek(0, SeekOrigin.Begin);
|
|
fileEntry.FileData.CopyTo(psuStream);
|
|
writer.WritePadding(0xFF, 0x400 - (fileEntry.Filesize % 0x400));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void ReadPSU(Stream psuStream)
|
|
{
|
|
using (XomStreamReader reader = new XomStreamReader(psuStream))
|
|
{
|
|
do
|
|
{
|
|
// read header
|
|
PsuEntryType type = (PsuEntryType)reader.ReadUInt16();
|
|
reader.Skip(0x02);
|
|
int size = reader.ReadInt32();
|
|
reader.Skip(0x01);
|
|
DateTime creationDate = reader.ReadDateTime();
|
|
ushort sector = reader.ReadUInt16();
|
|
reader.Skip(0x07);
|
|
DateTime modifiedDate = reader.ReadDateTime();
|
|
reader.Skip(0x20);
|
|
string filename = reader.ReadStrLen(0x1C0);
|
|
|
|
if (type == PsuEntryType.FILE_ENTRY || type == PsuEntryType.SYSTEM_ENTRY)
|
|
{
|
|
byte[] fileData = reader.ReadBytes(size);
|
|
|
|
reader.Skip(0x400 - (size % 0x400));
|
|
this.entries.Add(new PsuFileEntry(type, size, creationDate, sector, modifiedDate, filename, fileData));
|
|
}
|
|
else
|
|
{
|
|
this.entries.Add(new PsuFileEntry(type, size, creationDate, sector, modifiedDate, filename, null));
|
|
}
|
|
}
|
|
while (psuStream.Position < psuStream.Length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|