Worms4Editor/LibW4M/PS2/PsuFile.cs

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);
}
}
}
}