Skip to content

Commit f556ca9

Browse files
authored
Merge pull request #190 from YeLikesss/master
[CatSystem2] 封包支持
2 parents d487074 + be3bf61 commit f556ca9

3 files changed

Lines changed: 284 additions & 0 deletions

File tree

ArcFormats/ArcFormats.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@
176176
<Compile Include="aNCHOR\ArcFPD.cs" />
177177
<Compile Include="aNCHOR\AudioFCD.cs" />
178178
<Compile Include="aNCHOR\Blowfish.cs" />
179+
<Compile Include="CatSystem\ArcBinV1.cs" />
180+
<Compile Include="CatSystem\ArcPidaV1.cs" />
179181
<Compile Include="FrontierWorks\ArcPCARC.cs" />
180182
<Compile Include="Artemis\ImageNekoPNG.cs" />
181183
<Compile Include="CsWare\AudioWAV.cs" />

ArcFormats/CatSystem/ArcBinV1.cs

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.Composition;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
8+
namespace GameRes.Formats.CatSystem
9+
{
10+
internal class BinEntryV1 : Entry
11+
{
12+
public long Size64 { get; set; }
13+
}
14+
15+
internal class BinStreamV1 : Stream
16+
{
17+
private Stream mBaseStream;
18+
private readonly long mOffset;
19+
private readonly long mLength;
20+
private long mPosition = 0L;
21+
private bool mDisposed = false;
22+
23+
public BinStreamV1(Stream stream, long offset, long length)
24+
{
25+
this.mBaseStream = stream;
26+
this.mOffset = offset;
27+
this.mLength = length;
28+
}
29+
30+
public override bool CanRead => !this.mDisposed;
31+
public override bool CanSeek => !this.mDisposed;
32+
public override bool CanWrite => false;
33+
public override long Length => this.mLength;
34+
public override long Position
35+
{
36+
get
37+
{
38+
return this.mPosition;
39+
}
40+
set
41+
{
42+
if (value < 0)
43+
{
44+
throw new ArgumentOutOfRangeException();
45+
}
46+
if (value > this.mLength)
47+
{
48+
throw new ArgumentOutOfRangeException();
49+
}
50+
this.mPosition = value;
51+
}
52+
}
53+
54+
public override void Flush()
55+
{
56+
}
57+
public override int Read(byte[] buffer, int offset, int count)
58+
{
59+
Stream stream = this.mBaseStream;
60+
61+
stream.Position = this.mOffset + this.mPosition;
62+
int bytesRead = stream.Read(buffer, offset, (int)Math.Min(this.mLength - this.mPosition, count));
63+
64+
this.Decrypt(buffer, offset, bytesRead, this.mOffset, this.mPosition);
65+
this.mPosition += bytesRead;
66+
67+
return bytesRead;
68+
}
69+
public override long Seek(long offset, SeekOrigin origin)
70+
{
71+
long pos = 0L;
72+
switch (origin)
73+
{
74+
case SeekOrigin.Begin:
75+
{
76+
pos = offset;
77+
break;
78+
}
79+
case SeekOrigin.Current:
80+
{
81+
pos = this.mPosition + offset;
82+
break;
83+
}
84+
case SeekOrigin.End:
85+
{
86+
pos = this.mLength + offset;
87+
break;
88+
}
89+
}
90+
91+
if (pos < 0)
92+
{
93+
throw new ArgumentOutOfRangeException();
94+
}
95+
if (pos > this.mLength)
96+
{
97+
throw new ArgumentOutOfRangeException();
98+
}
99+
100+
this.mPosition = pos;
101+
return pos;
102+
}
103+
public override void SetLength(long value)
104+
{
105+
throw new NotSupportedException();
106+
}
107+
public override void Write(byte[] buffer, int offset, int count)
108+
{
109+
throw new NotSupportedException();
110+
}
111+
protected override void Dispose(bool disposing)
112+
{
113+
if (!this.mDisposed)
114+
{
115+
if (disposing)
116+
{
117+
this.mBaseStream.Dispose();
118+
this.mBaseStream = Stream.Null;
119+
}
120+
this.mDisposed = true;
121+
base.Dispose(disposing);
122+
}
123+
}
124+
125+
protected virtual void Decrypt(byte[] buffer, long offset, int count, long fileOffset, long arcOffset)
126+
{
127+
for(int i = 0; i < count; ++i)
128+
{
129+
byte key = (byte)((fileOffset + arcOffset + i) * 0x9D + (arcOffset + i) * 0x773);
130+
buffer[offset + i] -= key;
131+
}
132+
}
133+
}
134+
135+
[Export(typeof(ArchiveFormat))]
136+
public class BinOpenerV1 : ArchiveFormat
137+
{
138+
public override string Tag => "BinV1/CSPACK";
139+
public override string Description => "CatSystem2 resource archive";
140+
public override uint Signature => 0x40674461u;
141+
public override bool IsHierarchic => true;
142+
public override bool CanWrite => false;
143+
144+
public override ArcFile TryOpen(ArcView file)
145+
{
146+
using (ArcViewStream stream = file.CreateStream())
147+
{
148+
using (BinaryReader br = new BinaryReader(stream, Encoding.Unicode, true))
149+
{
150+
stream.Position = 8L;
151+
152+
List<BinEntryV1> entries = new List<BinEntryV1>();
153+
{
154+
string fn = br.ReadString();
155+
while (!string.IsNullOrEmpty(fn))
156+
{
157+
BinEntryV1 e = Create<BinEntryV1>(fn);
158+
e.Offset = br.ReadUInt32();
159+
e.Size64 = 0L;
160+
161+
entries.Add(e);
162+
163+
fn = br.ReadString();
164+
}
165+
}
166+
167+
if (entries.Any())
168+
{
169+
{
170+
BinEntryV1 last = entries.Last();
171+
last.Size64 = stream.Length - last.Offset;
172+
last.Size = (uint)last.Size64;
173+
}
174+
for (int i = 0; i < entries.Count - 1; ++i)
175+
{
176+
BinEntryV1 curr = entries[i + 0];
177+
BinEntryV1 next = entries[i + 1];
178+
curr.Size64 = next.Offset - curr.Offset;
179+
curr.Size = (uint)curr.Size64;
180+
}
181+
}
182+
183+
return new ArcFile(file, this, entries.Cast<Entry>().ToList());
184+
}
185+
}
186+
}
187+
public override Stream OpenEntry(ArcFile arc, Entry entry)
188+
{
189+
if(!(entry is BinEntryV1 e))
190+
{
191+
return base.OpenEntry(arc, entry);
192+
}
193+
return new BinStreamV1(arc.File.CreateStream(), e.Offset, e.Size64);
194+
}
195+
}
196+
}

ArcFormats/CatSystem/ArcPidaV1.cs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.Composition;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
8+
namespace GameRes.Formats.CatSystem
9+
{
10+
internal class PidaEntryV1 : Entry
11+
{
12+
public ushort Width;
13+
public ushort Height;
14+
public short OffsetX;
15+
public short OffsetY;
16+
}
17+
18+
[Export(typeof(ArchiveFormat))]
19+
public class PidaOpenerV1 : ArchiveFormat
20+
{
21+
public override string Tag => "PidaV1";
22+
public override string Description => "CatSystem2 engine multi-image";
23+
public override uint Signature => 0x6DF22373u;
24+
public override bool IsHierarchic => true;
25+
public override bool CanWrite => false;
26+
27+
public PidaOpenerV1()
28+
{
29+
ContainedFormats = new[] { "PNG" };
30+
}
31+
32+
public override ArcFile TryOpen(ArcView file)
33+
{
34+
using (ArcViewStream stream = file.CreateStream())
35+
{
36+
using (BinaryReader br = new BinaryReader(stream, Encoding.Unicode, true))
37+
{
38+
stream.Position = 8L;
39+
40+
List<PidaEntryV1> entries = new List<PidaEntryV1>();
41+
{
42+
string fn = br.ReadString();
43+
while (!string.IsNullOrEmpty(fn))
44+
{
45+
PidaEntryV1 e = Create<PidaEntryV1>(fn);
46+
e.Offset = br.ReadUInt32();
47+
e.Size = 0u;
48+
49+
e.Width = br.ReadUInt16();
50+
e.Height = br.ReadUInt16();
51+
e.OffsetX = br.ReadInt16();
52+
e.OffsetY = br.ReadInt16();
53+
54+
e.Type = "image";
55+
entries.Add(e);
56+
57+
fn = br.ReadString();
58+
}
59+
}
60+
61+
if (entries.Any())
62+
{
63+
long imageDataOffset = stream.Position;
64+
65+
foreach (PidaEntryV1 e in entries)
66+
{
67+
e.Offset += imageDataOffset;
68+
}
69+
{
70+
PidaEntryV1 last = entries.Last();
71+
last.Size = (uint)(stream.Length - last.Offset);
72+
}
73+
for (int i = 0; i < entries.Count - 1; ++i)
74+
{
75+
PidaEntryV1 curr = entries[i + 0];
76+
PidaEntryV1 next = entries[i + 1];
77+
curr.Size = (uint)(next.Offset - curr.Offset);
78+
}
79+
}
80+
81+
return new ArcFile(file, this, entries.Cast<Entry>().ToList());
82+
}
83+
}
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)