Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ArcFormats/ArcFormats.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@
<Compile Include="aNCHOR\ArcFPD.cs" />
<Compile Include="aNCHOR\AudioFCD.cs" />
<Compile Include="aNCHOR\Blowfish.cs" />
<Compile Include="CatSystem\ArcBinV1.cs" />
<Compile Include="CatSystem\ArcPidaV1.cs" />
<Compile Include="FrontierWorks\ArcPCARC.cs" />
<Compile Include="Artemis\ImageNekoPNG.cs" />
<Compile Include="CsWare\AudioWAV.cs" />
Expand Down
196 changes: 196 additions & 0 deletions ArcFormats/CatSystem/ArcBinV1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Text;

namespace GameRes.Formats.CatSystem
{
internal class BinEntryV1 : Entry
{
public long Size64 { get; set; }
}

internal class BinStreamV1 : Stream
{
private Stream mBaseStream;
private readonly long mOffset;
private readonly long mLength;
private long mPosition = 0L;
private bool mDisposed = false;

public BinStreamV1(Stream stream, long offset, long length)
{
this.mBaseStream = stream;
this.mOffset = offset;
this.mLength = length;
}

public override bool CanRead => !this.mDisposed;
public override bool CanSeek => !this.mDisposed;
public override bool CanWrite => false;
public override long Length => this.mLength;
public override long Position
{
get
{
return this.mPosition;
}
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException();
}
if (value > this.mLength)
{
throw new ArgumentOutOfRangeException();
}
this.mPosition = value;
}
}

public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count)
{
Stream stream = this.mBaseStream;

stream.Position = this.mOffset + this.mPosition;
int bytesRead = stream.Read(buffer, offset, (int)Math.Min(this.mLength - this.mPosition, count));

this.Decrypt(buffer, offset, bytesRead, this.mOffset, this.mPosition);
this.mPosition += bytesRead;

return bytesRead;
}
public override long Seek(long offset, SeekOrigin origin)
{
long pos = 0L;
switch (origin)
{
case SeekOrigin.Begin:
{
pos = offset;
break;
}
case SeekOrigin.Current:
{
pos = this.mPosition + offset;
break;
}
case SeekOrigin.End:
{
pos = this.mLength + offset;
break;
}
}

if (pos < 0)
{
throw new ArgumentOutOfRangeException();
}
if (pos > this.mLength)
{
throw new ArgumentOutOfRangeException();
}

this.mPosition = pos;
return pos;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
protected override void Dispose(bool disposing)
{
if (!this.mDisposed)
{
if (disposing)
{
this.mBaseStream.Dispose();
this.mBaseStream = Stream.Null;
}
this.mDisposed = true;
base.Dispose(disposing);
}
}

protected virtual void Decrypt(byte[] buffer, long offset, int count, long fileOffset, long arcOffset)
{
for(int i = 0; i < count; ++i)
{
byte key = (byte)((fileOffset + arcOffset + i) * 0x9D + (arcOffset + i) * 0x773);
buffer[offset + i] -= key;
}
}
}

[Export(typeof(ArchiveFormat))]
public class BinOpenerV1 : ArchiveFormat
{
public override string Tag => "BinV1/CSPACK";
public override string Description => "CatSystem2 resource archive";
public override uint Signature => 0x40674461u;
public override bool IsHierarchic => true;
public override bool CanWrite => false;

public override ArcFile TryOpen(ArcView file)
{
using (ArcViewStream stream = file.CreateStream())
{
using (BinaryReader br = new BinaryReader(stream, Encoding.Unicode, true))
{
stream.Position = 8L;

List<BinEntryV1> entries = new List<BinEntryV1>();
{
string fn = br.ReadString();
while (!string.IsNullOrEmpty(fn))
{
BinEntryV1 e = Create<BinEntryV1>(fn);
e.Offset = br.ReadUInt32();
e.Size64 = 0L;

entries.Add(e);

fn = br.ReadString();
}
}

if (entries.Any())
{
{
BinEntryV1 last = entries.Last();
last.Size64 = stream.Length - last.Offset;
last.Size = (uint)last.Size64;
}
for (int i = 0; i < entries.Count - 1; ++i)
{
BinEntryV1 curr = entries[i + 0];
BinEntryV1 next = entries[i + 1];
curr.Size64 = next.Offset - curr.Offset;
curr.Size = (uint)curr.Size64;
}
}

return new ArcFile(file, this, entries.Cast<Entry>().ToList());
}
}
}
public override Stream OpenEntry(ArcFile arc, Entry entry)
{
if(!(entry is BinEntryV1 e))
{
return base.OpenEntry(arc, entry);
}
return new BinStreamV1(arc.File.CreateStream(), e.Offset, e.Size64);
}
}
}
86 changes: 86 additions & 0 deletions ArcFormats/CatSystem/ArcPidaV1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Text;

namespace GameRes.Formats.CatSystem
{
internal class PidaEntryV1 : Entry
{
public ushort Width;
public ushort Height;
public short OffsetX;
public short OffsetY;
}

[Export(typeof(ArchiveFormat))]
public class PidaOpenerV1 : ArchiveFormat
{
public override string Tag => "PidaV1";
public override string Description => "CatSystem2 engine multi-image";
public override uint Signature => 0x6DF22373u;
public override bool IsHierarchic => true;
public override bool CanWrite => false;

public PidaOpenerV1()
{
ContainedFormats = new[] { "PNG" };
}

public override ArcFile TryOpen(ArcView file)
{
using (ArcViewStream stream = file.CreateStream())
{
using (BinaryReader br = new BinaryReader(stream, Encoding.Unicode, true))
{
stream.Position = 8L;

List<PidaEntryV1> entries = new List<PidaEntryV1>();
{
string fn = br.ReadString();
while (!string.IsNullOrEmpty(fn))
{
PidaEntryV1 e = Create<PidaEntryV1>(fn);
e.Offset = br.ReadUInt32();
e.Size = 0u;

e.Width = br.ReadUInt16();
e.Height = br.ReadUInt16();
e.OffsetX = br.ReadInt16();
e.OffsetY = br.ReadInt16();

e.Type = "image";
entries.Add(e);

fn = br.ReadString();
}
}

if (entries.Any())
{
long imageDataOffset = stream.Position;

foreach (PidaEntryV1 e in entries)
{
e.Offset += imageDataOffset;
}
{
PidaEntryV1 last = entries.Last();
last.Size = (uint)(stream.Length - last.Offset);
}
for (int i = 0; i < entries.Count - 1; ++i)
{
PidaEntryV1 curr = entries[i + 0];
PidaEntryV1 next = entries[i + 1];
curr.Size = (uint)(next.Offset - curr.Offset);
}
}

return new ArcFile(file, this, entries.Cast<Entry>().ToList());
}
}
}
}
}
Loading