Merge pull request #190 from YeLikesss/master

[CatSystem2] 封包支持
This commit is contained in:
Crsky
2026-04-28 23:40:40 +08:00
committed by GitHub
3 changed files with 284 additions and 0 deletions

View File

@@ -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" />

View File

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

View File

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