diff --git a/ArcFormats/Cyberworks/ArcDAT.cs b/ArcFormats/Cyberworks/ArcDAT.cs index 481e16f7..bd0ab453 100644 --- a/ArcFormats/Cyberworks/ArcDAT.cs +++ b/ArcFormats/Cyberworks/ArcDAT.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 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)