mirror of
https://github.com/crskycode/GARbro.git
synced 2026-06-06 05:38:48 +08:00
Merge pull request #16 from scientificworld/master
Add support for several games
This commit is contained in:
@@ -607,6 +607,7 @@
|
||||
<Compile Include="MD5.cs" />
|
||||
<Compile Include="Moonhir\ArcFPK.cs" />
|
||||
<Compile Include="Morning\ArcTTD.cs" />
|
||||
<Compile Include="Musica\ArcMIP.cs" />
|
||||
<Compile Include="Musica\ArcPAZ.cs" />
|
||||
<Compile Include="Musica\ArcSQZ.cs" />
|
||||
<Compile Include="Musica\WidgetPAZ.xaml.cs">
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace GameRes.Formats.Cyberworks
|
||||
var toc = ReadToc (toc_name, 8);
|
||||
if (null == toc)
|
||||
return null;
|
||||
using (var index = new ArcIndexReader (toc, file, arc_idx, game_name))
|
||||
using (var index = GetIndexReader (toc, file, arc_idx, game_name))
|
||||
{
|
||||
if (!index.Read())
|
||||
return null;
|
||||
@@ -228,6 +228,16 @@ namespace GameRes.Formats.Cyberworks
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual IndexReader GetIndexReader (byte[] toc, ArcView file, int arc_idx, string game_name)
|
||||
{
|
||||
return new ArcIndexReader (toc, file, arc_idx, game_name);
|
||||
}
|
||||
|
||||
internal virtual TocUnpacker GetTocUnpacker (string toc_name)
|
||||
{
|
||||
return new TocUnpacker (toc_name);
|
||||
}
|
||||
|
||||
internal ArcFile ArchiveFromDir (ArcView file, List<Entry> dir, bool has_images)
|
||||
{
|
||||
if (0 == dir.Count)
|
||||
@@ -245,7 +255,7 @@ namespace GameRes.Formats.Cyberworks
|
||||
{
|
||||
if (!VFS.FileExists (meta_arc_name))
|
||||
return null;
|
||||
using (var unpacker = new TocUnpacker (meta_arc_name))
|
||||
using (var unpacker = GetTocUnpacker (meta_arc_name))
|
||||
{
|
||||
if (unpacker.Length > 0x1000)
|
||||
return null;
|
||||
@@ -269,7 +279,7 @@ namespace GameRes.Formats.Cyberworks
|
||||
{
|
||||
if (!VFS.FileExists (toc_name))
|
||||
return null;
|
||||
using (var toc_unpacker = new TocUnpacker (toc_name))
|
||||
using (var toc_unpacker = GetTocUnpacker (toc_name))
|
||||
return toc_unpacker.Unpack (num_length);
|
||||
}
|
||||
|
||||
@@ -403,6 +413,26 @@ namespace GameRes.Formats.Cyberworks
|
||||
public AImageScheme Scheme;
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class DatOpener2024 : DatOpener
|
||||
{
|
||||
public override string Tag { get { return "ARC/Cyberworks/2"; } }
|
||||
public override string Description { get { return "Cyberworks/TinkerBell resource archive"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
public override bool IsHierarchic { get { return false; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
internal override IndexReader GetIndexReader (byte[] toc, ArcView file, int arc_idx, string game_name)
|
||||
{
|
||||
return new ArcIndexReader2 (toc, file, arc_idx, game_name);
|
||||
}
|
||||
|
||||
internal override TocUnpacker GetTocUnpacker (string toc_name)
|
||||
{
|
||||
return new TocUnpacker (toc_name, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class OldDatOpener : DatOpener
|
||||
{
|
||||
@@ -514,19 +544,22 @@ namespace GameRes.Formats.Cyberworks
|
||||
{
|
||||
ArcView m_file;
|
||||
bool m_should_dispose;
|
||||
bool m_reversed_decimal;
|
||||
|
||||
public long Length { get { return m_file.MaxOffset; } }
|
||||
public uint PackedSize { get; private set; }
|
||||
public uint UnpackedSize { get; private set; }
|
||||
|
||||
public TocUnpacker (string toc_name) : this (VFS.OpenView (toc_name), true)
|
||||
public TocUnpacker (string toc_name, bool reversed_decimal = false)
|
||||
: this (VFS.OpenView (toc_name), true, reversed_decimal)
|
||||
{
|
||||
}
|
||||
|
||||
public TocUnpacker (ArcView file, bool should_dispose = false)
|
||||
public TocUnpacker (ArcView file, bool should_dispose = false, bool reversed_decimal = false)
|
||||
{
|
||||
m_file = file;
|
||||
m_should_dispose = should_dispose;
|
||||
m_reversed_decimal = reversed_decimal;
|
||||
}
|
||||
|
||||
public byte[] Unpack (int num_length)
|
||||
@@ -564,7 +597,22 @@ namespace GameRes.Formats.Cyberworks
|
||||
{
|
||||
uint v = 0;
|
||||
uint rank = 1;
|
||||
for (int i = num_length-1; i >= 0; --i, rank *= 10)
|
||||
|
||||
int start, end, step;
|
||||
if (m_reversed_decimal)
|
||||
{
|
||||
start = 0;
|
||||
end = num_length;
|
||||
step = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = num_length-1;
|
||||
end = -1;
|
||||
step = -1;
|
||||
}
|
||||
|
||||
for (int i = start; i != end; i += step, rank *= 10)
|
||||
{
|
||||
uint b = m_file.View.ReadByte (offset+i);
|
||||
if (b != 0xFF)
|
||||
@@ -627,9 +675,9 @@ namespace GameRes.Formats.Cyberworks
|
||||
return true;
|
||||
}
|
||||
|
||||
uint m_fault_id = 100000;
|
||||
protected uint m_fault_id = 100000;
|
||||
|
||||
internal PackedEntry ReadEntryInfo ()
|
||||
internal virtual PackedEntry ReadEntryInfo ()
|
||||
{
|
||||
uint id = m_index.ReadUInt32();
|
||||
if (id > m_fault_id)
|
||||
@@ -707,6 +755,27 @@ namespace GameRes.Formats.Cyberworks
|
||||
}
|
||||
}
|
||||
|
||||
internal class ArcIndexReader2 : ArcIndexReader
|
||||
{
|
||||
public ArcIndexReader2 (byte[] toc, ArcView file, int arc_number, string game_name = null)
|
||||
: base (toc, file, arc_number, game_name)
|
||||
{
|
||||
}
|
||||
|
||||
internal override PackedEntry ReadEntryInfo ()
|
||||
{
|
||||
uint id = m_index.ReadUInt32();
|
||||
if (id > m_fault_id)
|
||||
id = m_fault_id++;
|
||||
var entry = new PackedEntry { Name = id.ToString ("D6") };
|
||||
entry.UnpackedSize = m_index.ReadUInt32();
|
||||
entry.Offset = m_index.ReadUInt32();
|
||||
entry.Size = m_index.ReadUInt32();
|
||||
entry.IsPacked = entry.UnpackedSize != entry.Size && entry.UnpackedSize != 0;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
internal class DatIndexReader : IndexReader
|
||||
{
|
||||
public DatIndexReader (byte[] toc, ArcView file) : base (toc, file)
|
||||
|
||||
@@ -74,12 +74,15 @@ namespace GameRes.Formats.Cyberworks
|
||||
{
|
||||
var arc_name = Path.GetFileName(file.Name);
|
||||
var dir_name = VFS.GetDirectoryName(file.Name);
|
||||
var toc_arc_name = VFS.CombinePath(dir_name, "Data00.dat");
|
||||
if (!VFS.FileExists(toc_arc_name))
|
||||
return null;
|
||||
if ("Data00.dat".Equals(arc_name, StringComparison.OrdinalIgnoreCase))
|
||||
return null;
|
||||
if (!int.TryParse(arc_name.Substring(4, arc_name.IndexOf('.') - 4), out int arc_index))
|
||||
return null;
|
||||
var scheme = QueryScheme(arc_name);
|
||||
var dir = ScanDir(VFS.CombinePath(dir_name, "Data00.dat"), arc_index, scheme);
|
||||
var dir = ScanDir(toc_arc_name, arc_index, scheme);
|
||||
if (null == dir || 0 == dir.Count)
|
||||
return null;
|
||||
|
||||
@@ -151,9 +154,6 @@ namespace GameRes.Formats.Cyberworks
|
||||
|
||||
List<Entry> ScanDir(string toc_arc_name, int arc_index, DataScheme scheme)
|
||||
{
|
||||
if(!VFS.FileExists(toc_arc_name))
|
||||
return null;
|
||||
|
||||
var dir = new List<Entry>();
|
||||
var toc_offset = 0;
|
||||
|
||||
|
||||
@@ -31,6 +31,19 @@ using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.FrontWing
|
||||
{
|
||||
internal class TimeLeapArchive : ArcFile
|
||||
{
|
||||
private bool m_encrypted;
|
||||
|
||||
public bool IsEncrypted { get { return m_encrypted; } }
|
||||
|
||||
public TimeLeapArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, bool encrypted)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
m_encrypted = encrypted;
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class DatOpener : ArchiveFormat
|
||||
{
|
||||
@@ -52,7 +65,17 @@ namespace GameRes.Formats.FrontWing
|
||||
if (file.MaxOffset < index_size + 4)
|
||||
return null;
|
||||
var index = file.View.ReadBytes (file.MaxOffset - 4 - index_size, (uint)index_size);
|
||||
NibbleSwap (index);
|
||||
bool encrypted = false;
|
||||
for (int i = 0; i < 40 && index[i] != 0; i++)
|
||||
{
|
||||
if (index[i] < 0x20 || index[i] >= 0x7f)
|
||||
{
|
||||
encrypted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encrypted)
|
||||
NibbleSwap (index);
|
||||
|
||||
int index_offset = 0;
|
||||
var dir = new List<Entry> (count);
|
||||
@@ -67,7 +90,7 @@ namespace GameRes.Formats.FrontWing
|
||||
index_offset += 0x50;
|
||||
dir.Add (entry);
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
return new TimeLeapArchive (file, this, dir, encrypted);
|
||||
}
|
||||
|
||||
static readonly byte[] keyTable = {
|
||||
@@ -80,16 +103,20 @@ namespace GameRes.Formats.FrontWing
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var data = arc.File.View.ReadBytes (entry.Offset, entry.Size);
|
||||
for (int i = 1; i < data.Length; i += 4)
|
||||
var tarc = arc as TimeLeapArchive;
|
||||
var data = tarc.File.View.ReadBytes (entry.Offset, entry.Size);
|
||||
if (tarc.IsEncrypted)
|
||||
{
|
||||
data[i] = (byte)(-data[i] & 0xff);
|
||||
for (int i = 1; i < data.Length; i += 4)
|
||||
{
|
||||
data[i] = (byte)(-data[i] & 0xff);
|
||||
}
|
||||
for (int i = 0; i < data.Length; i += 3)
|
||||
{
|
||||
data[i] ^= keyTable[i / 5 % 5 + i % 6];
|
||||
}
|
||||
NibbleSwap (data, 2, 6);
|
||||
}
|
||||
for (int i = 0; i < data.Length; i += 3)
|
||||
{
|
||||
data[i] ^= keyTable[i / 5 % 5 + i % 6];
|
||||
}
|
||||
NibbleSwap(data, 2, 6);
|
||||
return new BinMemoryStream (data);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ namespace GameRes.Formats.Lucifen
|
||||
public bool IsEncrypted;
|
||||
public bool PackedEntries;
|
||||
public bool WholeCrypt;
|
||||
public bool IsPatchFile;
|
||||
public uint Key;
|
||||
public byte[] Prefix;
|
||||
}
|
||||
@@ -206,7 +207,7 @@ namespace GameRes.Formats.Lucifen
|
||||
{
|
||||
input.Read (data, 0, data.Length);
|
||||
}
|
||||
if (larc.Info.WholeCrypt)
|
||||
if (larc.Info.WholeCrypt && !(larc.Info.IsPatchFile && lent.Name.HasExtension ("elg")))
|
||||
{
|
||||
larc.Scheme.DecryptContent (data);
|
||||
}
|
||||
@@ -257,15 +258,13 @@ namespace GameRes.Formats.Lucifen
|
||||
IsEncrypted = 0 != (flags & 4),
|
||||
PackedEntries = 0 != (flags & 8),
|
||||
WholeCrypt = 0 != (flags & 0x10),
|
||||
IsPatchFile = 0 != (flags & 0x20),
|
||||
Key = key1
|
||||
};
|
||||
var reader = new IndexReader (lpk_info);
|
||||
var dir = reader.Read (index);
|
||||
if (null == dir)
|
||||
return null;
|
||||
// this condition is fishy, probably patch files have additional bitflag set
|
||||
if (lpk_info.WholeCrypt && Binary.AsciiEqual (basename, "PATCH"))
|
||||
lpk_info.WholeCrypt = false;
|
||||
return new LuciArchive (file, this, dir, scheme, reader.Info);
|
||||
}
|
||||
|
||||
|
||||
655
ArcFormats/Musica/ArcMIP.cs
Normal file
655
ArcFormats/Musica/ArcMIP.cs
Normal file
@@ -0,0 +1,655 @@
|
||||
//! \file ArcMIP.cs
|
||||
//! \date 2026-01-16
|
||||
//! \brief Minori resource archive.
|
||||
//
|
||||
// Copyright (C) 2026 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Musica {
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class MipOpener : ArchiveFormat {
|
||||
public override string Tag { get { return "MIP"; } }
|
||||
public override string Description { get { return "Minori resource archive"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
public override bool IsHierarchic { get { return false; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
// 0x42e100
|
||||
static readonly uint[] resEntrySizeList = {
|
||||
0xDDE,
|
||||
0x1622,
|
||||
0x44F,
|
||||
0xF06,
|
||||
0x1EFEA,
|
||||
0x64B3,
|
||||
0x10684E,
|
||||
0x9288,
|
||||
0x144,
|
||||
0x49993,
|
||||
0x5065C,
|
||||
0x52424,
|
||||
0x4EB4B,
|
||||
0x4EA1F,
|
||||
0x4A334,
|
||||
0x4B8E4,
|
||||
0x55DA6,
|
||||
0x56D7C,
|
||||
0x3A3ED,
|
||||
0x307B3,
|
||||
0x55FB8,
|
||||
0x96D68,
|
||||
0x4B821,
|
||||
0x4C33B,
|
||||
0x54EB3,
|
||||
0x4DBDD,
|
||||
0x52D69,
|
||||
0x50A3F,
|
||||
0x50C0C,
|
||||
0x4975A,
|
||||
0x47E5F,
|
||||
0x37177,
|
||||
0x3E0D4,
|
||||
0x46029,
|
||||
0xC854A,
|
||||
0x4463F,
|
||||
0x44E40,
|
||||
0x40AA5,
|
||||
0x432BF,
|
||||
0x3C0A5,
|
||||
0x29496,
|
||||
0xABC1B,
|
||||
0x88427,
|
||||
0x9F549,
|
||||
0x104EA,
|
||||
0x7C524,
|
||||
0x75CE,
|
||||
0xA419,
|
||||
0x6419,
|
||||
0x9C62,
|
||||
0x6A9C,
|
||||
0xC5862,
|
||||
0x134F2D,
|
||||
0x1271,
|
||||
0x11D6,
|
||||
0x4D1F,
|
||||
0x6134,
|
||||
0x63C1,
|
||||
0x8730,
|
||||
0x6BF9,
|
||||
0x6CDA,
|
||||
0x898A,
|
||||
0x706B,
|
||||
0x696A,
|
||||
0x60AA,
|
||||
0x9007,
|
||||
0x662F,
|
||||
0x72B3,
|
||||
0x55E8,
|
||||
0x6E47,
|
||||
0x9EDA,
|
||||
0x622D,
|
||||
0x5BE4,
|
||||
0x73A9,
|
||||
0x9269,
|
||||
0x5C11,
|
||||
0x553A,
|
||||
0x66EA,
|
||||
0x7174,
|
||||
0x6A8C,
|
||||
0x6AC0,
|
||||
0x6389,
|
||||
0x7167,
|
||||
0x845A,
|
||||
0x900A,
|
||||
0x726E,
|
||||
0x68F3,
|
||||
0x88E4,
|
||||
0x8B70,
|
||||
0x83BB,
|
||||
0x7D1E,
|
||||
0x84CC,
|
||||
0x583C,
|
||||
0x6AD1,
|
||||
0x7981,
|
||||
0x48F0,
|
||||
0x765A,
|
||||
0x763F,
|
||||
0x5ACB,
|
||||
0x5B4E,
|
||||
0x6490,
|
||||
0x7441,
|
||||
0x5D9F,
|
||||
0x5FD9,
|
||||
0x5E9A,
|
||||
0x7330,
|
||||
0x69D1,
|
||||
0x86BE,
|
||||
0x92AC,
|
||||
0x9787,
|
||||
0x972D,
|
||||
0x9963,
|
||||
0x96E3,
|
||||
0x8101,
|
||||
0x707C,
|
||||
0x70DC,
|
||||
0x9105,
|
||||
0x7A06,
|
||||
0x7A8F,
|
||||
0x595F,
|
||||
0x58FA,
|
||||
0x7F95,
|
||||
0x86CB,
|
||||
0x86F7,
|
||||
0x7B3B,
|
||||
0x8971,
|
||||
0x8BFC,
|
||||
0x7FE6,
|
||||
0x77EE,
|
||||
0x83FF,
|
||||
0x606D,
|
||||
0x6125,
|
||||
0x66FB,
|
||||
0x66F9,
|
||||
0x6E76,
|
||||
0x6826,
|
||||
0x67B1,
|
||||
0x76E3,
|
||||
0x7487,
|
||||
0x4E7B,
|
||||
0x4CD34,
|
||||
0x750EF,
|
||||
0x761B6,
|
||||
0xB29F9,
|
||||
0x9CE38,
|
||||
0x95BEF,
|
||||
0x79F4F,
|
||||
0x9BEB6,
|
||||
0xA1C95,
|
||||
0x72147,
|
||||
0x68007,
|
||||
0x59070,
|
||||
0xCADF5,
|
||||
0x71FB4,
|
||||
0x67BF2,
|
||||
0x5C639,
|
||||
0x57FAF,
|
||||
0x63334,
|
||||
0x703D2,
|
||||
0x5DCDB,
|
||||
0xA796B,
|
||||
0x71728,
|
||||
0x7F52D,
|
||||
0x71B7A,
|
||||
0xA024D,
|
||||
0x73670,
|
||||
0x47E4B,
|
||||
0x63AF1,
|
||||
0x83F4F,
|
||||
0x6FFB2,
|
||||
0x82C74,
|
||||
0x708D6,
|
||||
0x79208,
|
||||
0x99011,
|
||||
0x8CFD4,
|
||||
0x7B119,
|
||||
0x65D69,
|
||||
0x982BA,
|
||||
0x86387,
|
||||
0x7F047,
|
||||
0x91A4A,
|
||||
0x9B149,
|
||||
0x65C0F,
|
||||
0x8050B,
|
||||
0x75798,
|
||||
0x369A9,
|
||||
0x39FD1,
|
||||
0x6E791,
|
||||
0x6E31B,
|
||||
0x558B7,
|
||||
0x66149,
|
||||
0x5C5FE,
|
||||
0x6A9CC,
|
||||
0x670E8,
|
||||
0x687DA,
|
||||
0x5F998,
|
||||
0x69569,
|
||||
0x5EF73,
|
||||
0x789BD,
|
||||
0xAE0EC,
|
||||
0xB7733,
|
||||
0x9422C,
|
||||
0xB1BBE,
|
||||
0xAC68D,
|
||||
0x91074,
|
||||
0x65FC9,
|
||||
0x6664C,
|
||||
0xB0867,
|
||||
0x6992C,
|
||||
0x6A4A9,
|
||||
0x5011C,
|
||||
0x5ECBB,
|
||||
0xA4332,
|
||||
0x7411F,
|
||||
0x73E87,
|
||||
0x7322C,
|
||||
0x82260,
|
||||
0x8E294,
|
||||
0x82594,
|
||||
0x6F54E,
|
||||
0x80E86,
|
||||
0x535AF,
|
||||
0x545B0,
|
||||
0x50437,
|
||||
0x503C8,
|
||||
0x56674,
|
||||
0x4E048,
|
||||
0x4D5C8,
|
||||
0x654DD,
|
||||
0x67968,
|
||||
0x5AAAA,
|
||||
0x2F45,
|
||||
0x3098,
|
||||
0x3DF5F,
|
||||
0xE6D49,
|
||||
0xD866D,
|
||||
0x9632C,
|
||||
0xE20BD,
|
||||
0x33061,
|
||||
0x375DF,
|
||||
0x417C2,
|
||||
0x37764,
|
||||
0x37934,
|
||||
0x40807,
|
||||
0xCDA33,
|
||||
0x9FA9C,
|
||||
0x44103,
|
||||
0xDA3E9,
|
||||
0x44E92,
|
||||
0x3C9DB,
|
||||
0x46F57,
|
||||
0x3881A,
|
||||
0x3A9B9,
|
||||
0x3B0A8,
|
||||
0x430A8,
|
||||
0xE2156,
|
||||
0x415F1,
|
||||
0x318EC,
|
||||
0x3AFCC,
|
||||
0x39769,
|
||||
0xDCEA7,
|
||||
0x4E43C,
|
||||
0x3CC83,
|
||||
0xBDF5E,
|
||||
0x33CF8,
|
||||
0x6D250,
|
||||
0x8570A,
|
||||
0x60C21,
|
||||
0x9782C,
|
||||
0x783D0,
|
||||
0x783D0,
|
||||
0x67935,
|
||||
0xAA5A7,
|
||||
0xDCA2E,
|
||||
0x606E9,
|
||||
0xA9047,
|
||||
0x10E5F,
|
||||
0x10E92,
|
||||
0x10E61,
|
||||
0x136E5,
|
||||
0x136EB,
|
||||
0x1371A,
|
||||
0x1368E,
|
||||
0x13818,
|
||||
0x139D4,
|
||||
0x11350,
|
||||
0x11372,
|
||||
0x11372,
|
||||
0x115CD,
|
||||
0x161F1,
|
||||
0x16022,
|
||||
0x16176,
|
||||
0x1503F,
|
||||
0x140CC,
|
||||
0x144D3,
|
||||
0x1433F,
|
||||
0x1365E,
|
||||
0x1388C,
|
||||
0x1365C,
|
||||
0x138FE,
|
||||
0x13616,
|
||||
0x1389D,
|
||||
0x13312,
|
||||
0x134A5,
|
||||
0x18BC8,
|
||||
0x18CD9,
|
||||
0x1785D,
|
||||
0x17A8A,
|
||||
0x176B5,
|
||||
0x17924,
|
||||
0x177F4,
|
||||
0x17A2D,
|
||||
0x1786E,
|
||||
0x17A9D,
|
||||
0x101CA,
|
||||
0x101AE,
|
||||
0x1058B,
|
||||
0x10184,
|
||||
0xD8D3,
|
||||
0xD936,
|
||||
0xD8AB,
|
||||
0xDA4E,
|
||||
0x11968,
|
||||
0x11935,
|
||||
0x11988,
|
||||
0x119D4,
|
||||
0x11938,
|
||||
0x1282A,
|
||||
0x127E9,
|
||||
0x12836,
|
||||
0x12813,
|
||||
0x12803,
|
||||
0xFC09,
|
||||
0xFBF2,
|
||||
0xEFE0,
|
||||
0xF149,
|
||||
0xEECF,
|
||||
0xEFF5,
|
||||
0xF02E,
|
||||
0xE872,
|
||||
0xEA4C,
|
||||
0xE871,
|
||||
0xE778,
|
||||
0xF835,
|
||||
0xFB43,
|
||||
0xF91B,
|
||||
0xFC05,
|
||||
0xE75F,
|
||||
0xE7DC,
|
||||
0x10295,
|
||||
0x102A9,
|
||||
0x102B6,
|
||||
0xD72E,
|
||||
0xD713,
|
||||
0xF21D,
|
||||
0xF51B,
|
||||
0xF26C,
|
||||
0xF55D,
|
||||
0x117B0,
|
||||
0x117B7,
|
||||
0x11783,
|
||||
0x1171E,
|
||||
0x118CD,
|
||||
0x118F0,
|
||||
0x119ED,
|
||||
0x18318,
|
||||
0x18300,
|
||||
0x182EF,
|
||||
0x18710,
|
||||
0x13F5F,
|
||||
0x13E96,
|
||||
0x13E4D,
|
||||
0x13FA9,
|
||||
0x13B17,
|
||||
0x13A41,
|
||||
0x13962,
|
||||
0x13C14,
|
||||
0x1396E,
|
||||
0x13569,
|
||||
0x13830,
|
||||
0xF939,
|
||||
0xF901,
|
||||
0xF925,
|
||||
0xEB9A,
|
||||
0x10C46,
|
||||
0x10B7D,
|
||||
0xEB8E,
|
||||
0x10B3A,
|
||||
0xEB68,
|
||||
0x10B1C,
|
||||
0xEB5F,
|
||||
0x10B5A,
|
||||
0xEC53,
|
||||
0xE494,
|
||||
0xE4B0,
|
||||
0x11A7C,
|
||||
0x1152B,
|
||||
0x11ABA,
|
||||
0x11620,
|
||||
0x11A1A,
|
||||
0x114E0,
|
||||
0x144EE,
|
||||
0x149CF,
|
||||
0x14519,
|
||||
0x10B71,
|
||||
0x10AFA,
|
||||
0x10B04,
|
||||
0xF64E,
|
||||
0xF8B2,
|
||||
0xF65F,
|
||||
0xF90E,
|
||||
0xF5C0,
|
||||
0xF87D,
|
||||
0xF5CC,
|
||||
0xF89A,
|
||||
0xF5A2,
|
||||
0xF883,
|
||||
0xF4CE,
|
||||
0xF7C6,
|
||||
0xF6E2,
|
||||
0xF326,
|
||||
0xF31D,
|
||||
0xFE72,
|
||||
0xFE64,
|
||||
0xFE4B,
|
||||
0x101B2,
|
||||
0xF1FF,
|
||||
0x10D8C,
|
||||
0x101F6,
|
||||
0xF2DD,
|
||||
0x10244,
|
||||
0xF1B6,
|
||||
0x101D9,
|
||||
0xFDC3,
|
||||
0x10363,
|
||||
0xFEB9,
|
||||
0x13450,
|
||||
0x133C1,
|
||||
0x126D1,
|
||||
0x115B8,
|
||||
0x126AD,
|
||||
0x115BC,
|
||||
0x26EA8,
|
||||
0x26E49,
|
||||
0x10A6F,
|
||||
0x10AE4,
|
||||
0x10A3F,
|
||||
0xFEC0,
|
||||
0xFF2F,
|
||||
0xFE55,
|
||||
0x13D6A,
|
||||
0x13DB7,
|
||||
0x13D94,
|
||||
0x13C03,
|
||||
0x123AD,
|
||||
0x121E2,
|
||||
0x12342,
|
||||
0x1252A,
|
||||
0x126A0,
|
||||
0x1285E,
|
||||
0xDD8C,
|
||||
0xDB7C,
|
||||
0xDAA5,
|
||||
0xD2A8,
|
||||
0xD564,
|
||||
0xD2F6,
|
||||
0xD6D1,
|
||||
0xD3F3,
|
||||
0xD775,
|
||||
0xD2F5,
|
||||
0xD8AE,
|
||||
0xD824,
|
||||
0xD8A2,
|
||||
0x1532E,
|
||||
0x151B5,
|
||||
0x12F49,
|
||||
0x141C8,
|
||||
0x12EA7,
|
||||
0x12E57,
|
||||
0x12F0B,
|
||||
0x12EF5,
|
||||
0x13131,
|
||||
0x15066,
|
||||
0x15003,
|
||||
0x150CD,
|
||||
0x10C4B,
|
||||
0x112CE,
|
||||
0x112AD,
|
||||
0x10C21,
|
||||
0x112B3,
|
||||
0x10CDF,
|
||||
0x113AF,
|
||||
0x10CA1,
|
||||
0x1133C,
|
||||
0x10C4B,
|
||||
0x11915,
|
||||
0x11900,
|
||||
0x118CA,
|
||||
0x118AC,
|
||||
0x11985,
|
||||
0x107CC,
|
||||
0x10759,
|
||||
0x1071B,
|
||||
0x4D14,
|
||||
0x4EF7,
|
||||
0x5804,
|
||||
0x5BDA,
|
||||
0x3BB7,
|
||||
0x30BD,
|
||||
0x39E0,
|
||||
0x3A3C,
|
||||
0x3AF2,
|
||||
0x3A3C,
|
||||
0x3969,
|
||||
0x393C,
|
||||
0x3B8C,
|
||||
0x4040,
|
||||
0x37FC,
|
||||
0x3973,
|
||||
0x3856,
|
||||
0x397B,
|
||||
0x3865,
|
||||
0x38DD,
|
||||
0x44C5,
|
||||
0x37C0,
|
||||
0x3BD9,
|
||||
0x3887,
|
||||
0x3C29,
|
||||
0x3BFA,
|
||||
0x3199,
|
||||
0x4848,
|
||||
0x151FD,
|
||||
0xD890,
|
||||
0x24E0A,
|
||||
0xBFAD,
|
||||
0x1531A,
|
||||
0x1B25F
|
||||
};
|
||||
|
||||
// 0x42f1d0
|
||||
static readonly uint[] scEntrySizeList = {
|
||||
0x1D1E7,
|
||||
0x130B4,
|
||||
0xE7AB,
|
||||
0xEC2E,
|
||||
0x1408A,
|
||||
0x96C8,
|
||||
0x1006F,
|
||||
0x109D8,
|
||||
0x1389F,
|
||||
0xEA2E,
|
||||
0xE57C,
|
||||
0xD331,
|
||||
0xD0F1,
|
||||
0x11730,
|
||||
0x12FC4,
|
||||
0xCC50,
|
||||
0xE043,
|
||||
0xD7AB,
|
||||
0x18978,
|
||||
0x2F87,
|
||||
0x4,
|
||||
0x22F3,
|
||||
0x6C2A,
|
||||
0x28BE,
|
||||
0x4080,
|
||||
0x3897
|
||||
};
|
||||
|
||||
public MipOpener() {
|
||||
Extensions = new string[] { "mip" };
|
||||
}
|
||||
|
||||
public override ArcFile TryOpen(ArcView file) {
|
||||
string extension;
|
||||
uint[] sizes;
|
||||
|
||||
string basename = Path.GetFileName(file.Name).ToLower();
|
||||
if (basename == "res.mip") {
|
||||
extension = ".png";
|
||||
sizes = resEntrySizeList;
|
||||
}
|
||||
else if (basename == "sc.mip") {
|
||||
extension = "";
|
||||
sizes = scEntrySizeList;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
|
||||
int count = sizes.Length;
|
||||
var dir = new List<Entry>(count);
|
||||
uint offset = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
var entry = new Entry {
|
||||
Name = i.ToString("D4") + extension,
|
||||
Type = extension == "" ? "script" : "image",
|
||||
Offset = offset,
|
||||
Size = sizes[i]
|
||||
};
|
||||
dir.Add(entry);
|
||||
offset += entry.Size;
|
||||
}
|
||||
|
||||
return new ArcFile(file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry(ArcFile arc, Entry entry) {
|
||||
var s = new XoredStream(arc.File.CreateStream(entry.Offset, entry.Size), 0xFF);
|
||||
if (entry.Name.EndsWith(".png"))
|
||||
return new PrefixStream(PngFormat.HeaderBytes, s);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace GameRes.Formats.Musica
|
||||
Extensions = new string[] { "paz", "dat" };
|
||||
Signatures = new uint[] {
|
||||
0x858F8493, 0x8F889395, 0x6E656465, 0x848F8486, 0x61657453, 0x6873616D, 0x92808483,
|
||||
0x6E697274, 0
|
||||
0x6E697274, 0x5F465342, 0
|
||||
};
|
||||
ContainedFormats = new string[] { "PNG", "ANI/PAZ", "SQZ", "OGG", "WAV", "TXT" };
|
||||
}
|
||||
|
||||
@@ -57,11 +57,13 @@ namespace GameRes.Formats.NitroPlus
|
||||
internal class NpkArchive : ArcFile
|
||||
{
|
||||
public readonly Aes Encryption;
|
||||
public readonly int Version;
|
||||
|
||||
public NpkArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, Aes enc)
|
||||
public NpkArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, Aes enc, int version)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
Encryption = enc;
|
||||
Version = version;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
@@ -100,8 +102,14 @@ namespace GameRes.Formats.NitroPlus
|
||||
set { DefaultScheme = (Npk2Scheme)value; }
|
||||
}
|
||||
|
||||
public NpkOpener ()
|
||||
{
|
||||
Signatures = new uint[] { 0x324B504E, 0x334B504E };
|
||||
}
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
int version = file.View.ReadByte (3) - '0';
|
||||
int count = file.View.ReadInt32 (0x18);
|
||||
if (!IsSaneCount (count))
|
||||
return null;
|
||||
@@ -124,7 +132,7 @@ namespace GameRes.Formats.NitroPlus
|
||||
var dir = ReadIndex (index, count, file.MaxOffset);
|
||||
if (null == dir)
|
||||
return null;
|
||||
var arc = new NpkArchive (file, this, dir, aes);
|
||||
var arc = new NpkArchive (file, this, dir, aes, version);
|
||||
aes = null; // object ownership passed to NpkArchive, don't dispose
|
||||
return arc;
|
||||
}
|
||||
@@ -481,6 +489,7 @@ namespace GameRes.Formats.NitroPlus
|
||||
{
|
||||
ArcView m_file;
|
||||
Aes m_encryption;
|
||||
int m_version;
|
||||
IEnumerator<NpkSegment> m_segment;
|
||||
Stream m_stream;
|
||||
bool m_eof = false;
|
||||
@@ -493,6 +502,7 @@ namespace GameRes.Formats.NitroPlus
|
||||
{
|
||||
m_file = arc.File;
|
||||
m_encryption = arc.Encryption;
|
||||
m_version = arc.Version;
|
||||
m_segment = entry.Segments.GetEnumerator();
|
||||
NextSegment();
|
||||
}
|
||||
@@ -511,7 +521,15 @@ namespace GameRes.Formats.NitroPlus
|
||||
var decryptor = m_encryption.CreateDecryptor();
|
||||
m_stream = new InputCryptoStream (m_stream, decryptor);
|
||||
if (segment.IsCompressed)
|
||||
m_stream = new DeflateStream (m_stream, CompressionMode.Decompress);
|
||||
switch (m_version)
|
||||
{
|
||||
case 2:
|
||||
m_stream = new DeflateStream (m_stream, CompressionMode.Decompress);
|
||||
break;
|
||||
case 3:
|
||||
m_stream = new ZstdNet.DecompressionStream (m_stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
|
||||
Binary file not shown.
96
Legacy/Broccoli/ArcP00.cs
Normal file
96
Legacy/Broccoli/ArcP00.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
//! \file ArcP00.cs
|
||||
//! \date 2026-01-08
|
||||
//! \brief Broccoli resource archive format.
|
||||
//
|
||||
// Copyright (C) 2026 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Broccoli {
|
||||
internal class P00Entry : Entry {
|
||||
public string FileName;
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class P00Opener : ArchiveFormat {
|
||||
public override string Tag { get { return "P00"; } }
|
||||
public override string Description { get { return "Broccoli multipart archive format"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
public override bool IsHierarchic { get { return true; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
public P00Opener() {
|
||||
Extensions = new string[] { "p00" };
|
||||
}
|
||||
|
||||
public override ArcFile TryOpen(ArcView file) {
|
||||
var index_file_name = Path.ChangeExtension(file.Name, "pak");
|
||||
if (!VFS.FileExists(index_file_name))
|
||||
return null;
|
||||
using (var index_file = VFS.OpenView(index_file_name)) {
|
||||
if (!index_file.View.AsciiEqual(0, "IPF "))
|
||||
return null;
|
||||
|
||||
int count = index_file.View.ReadInt32(4);
|
||||
if (!IsSaneCount(count))
|
||||
return null;
|
||||
|
||||
long index_offset = 8;
|
||||
var dir = new List<Entry>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
uint hash = index_file.View.ReadUInt32(index_offset);
|
||||
string name = hash.ToString("X8");
|
||||
var entry = Create<P00Entry>(name);
|
||||
entry.Offset = index_file.View.ReadUInt32(index_offset + 4);
|
||||
entry.Size = index_file.View.ReadUInt32(index_offset + 8);
|
||||
var data_file_name = Path.ChangeExtension(file.Name, string.Format("p{0:00}", entry.Offset >> 28));
|
||||
if (!VFS.FileExists(data_file_name))
|
||||
return null;
|
||||
entry.FileName = data_file_name;
|
||||
dir.Add(entry);
|
||||
index_offset += 12;
|
||||
}
|
||||
|
||||
return new ArcFile(file, this, dir);
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream OpenEntry(ArcFile arc, Entry entry) {
|
||||
var pent = entry as P00Entry;
|
||||
using (var data_file = new ArcView(pent.FileName)) {
|
||||
var input = data_file.CreateStream(pent.Offset & 0xFFFFFFF, pent.Size);
|
||||
if (input.ReadUInt16() == 0x305A) { // 'Z0'
|
||||
input.Seek(10, SeekOrigin.Begin);
|
||||
return new DeflateStream(input, CompressionMode.Decompress);
|
||||
}
|
||||
else {
|
||||
input.Seek(0, SeekOrigin.Begin);
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,7 @@
|
||||
<Compile Include="BlackButterfly\ArcDAT.cs" />
|
||||
<Compile Include="Blucky\Aliases.cs" />
|
||||
<Compile Include="Bom\ImageGRP.cs" />
|
||||
<Compile Include="Broccoli\ArcP00.cs" />
|
||||
<Compile Include="CottonClub\ImageLMG.cs" />
|
||||
<Compile Include="Desire\ArcDSV.cs" />
|
||||
<Compile Include="Desire\ImageDES.cs" />
|
||||
|
||||
Reference in New Issue
Block a user