mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-25 04:14:13 +08:00
implemented older version of Tinkerbell archives.
This commit is contained in:
parent
17e8c7efca
commit
4585f78074
@ -203,13 +203,11 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
entry_size = pent.UnpackedSize;
|
entry_size = pent.UnpackedSize;
|
||||||
}
|
}
|
||||||
var barc = arc as BellArchive;
|
var barc = arc as BellArchive;
|
||||||
if (null == barc)
|
if (null == barc || entry.Type != "image" || entry_size < 5)
|
||||||
return input;
|
return input;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ("image" == entry.Type && entry_size > 5)
|
|
||||||
return DecryptImage (input, entry_size, barc.Scheme);
|
return DecryptImage (input, entry_size, barc.Scheme);
|
||||||
return input;
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -218,7 +216,7 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream DecryptImage (Stream input, uint entry_size, AImageScheme scheme)
|
protected virtual Stream DecryptImage (Stream input, uint entry_size, AImageScheme scheme)
|
||||||
{
|
{
|
||||||
byte[] header = null;
|
byte[] header = null;
|
||||||
byte type = (byte)input.ReadByte();
|
byte type = (byte)input.ReadByte();
|
||||||
@ -274,7 +272,7 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
AImageScheme QueryScheme (string arc_name)
|
internal AImageScheme QueryScheme (string arc_name)
|
||||||
{
|
{
|
||||||
var title = FormatCatalog.Instance.LookupGame (arc_name);
|
var title = FormatCatalog.Instance.LookupGame (arc_name);
|
||||||
if (!string.IsNullOrEmpty (title) && KnownSchemes.ContainsKey (title))
|
if (!string.IsNullOrEmpty (title) && KnownSchemes.ContainsKey (title))
|
||||||
@ -335,4 +333,148 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
{
|
{
|
||||||
public AImageScheme Scheme;
|
public AImageScheme Scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Export(typeof(ArchiveFormat))]
|
||||||
|
public class OldDatOpener : DatOpener
|
||||||
|
{
|
||||||
|
public override string Tag { get { return "ARC/Csystem"; } }
|
||||||
|
public override string Description { get { return "TinkerBell resource archive"; } }
|
||||||
|
public override uint Signature { get { return 0; } }
|
||||||
|
public override bool IsHierarchic { get { return false; } }
|
||||||
|
public override bool CanWrite { get { return false; } }
|
||||||
|
|
||||||
|
public OldDatOpener ()
|
||||||
|
{
|
||||||
|
Extensions = new string[] { "dat" };
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly Regex s_arcname_re = new Regex (@"^Arc0(?<num>\d)\..*$", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
static readonly IDictionary<int, int> s_arcmap = new Dictionary<int, int>
|
||||||
|
{
|
||||||
|
{ 2, 0 }, { 3, 1 }, { 5, 4 }
|
||||||
|
};
|
||||||
|
|
||||||
|
public override ArcFile TryOpen (ArcView file)
|
||||||
|
{
|
||||||
|
var arc_name = Path.GetFileName (file.Name);
|
||||||
|
var match = s_arcname_re.Match (arc_name);
|
||||||
|
if (!match.Success)
|
||||||
|
return null;
|
||||||
|
int num = match.Groups["num"].Value[0] - '0';
|
||||||
|
int index_num;
|
||||||
|
if (!s_arcmap.TryGetValue (num, out index_num))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var toc_name_builder = new StringBuilder (arc_name);
|
||||||
|
var num_pos = match.Groups["num"].Index;
|
||||||
|
toc_name_builder.Remove (num_pos, match.Groups["num"].Length);
|
||||||
|
toc_name_builder.Insert (num_pos, index_num);
|
||||||
|
|
||||||
|
var toc_name = toc_name_builder.ToString();
|
||||||
|
toc_name = VFS.CombinePath (VFS.GetDirectoryName (file.Name), toc_name);
|
||||||
|
var toc = ReadToc (toc_name);
|
||||||
|
if (null == toc)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
bool has_images = false;
|
||||||
|
var dir = new List<Entry>();
|
||||||
|
using (var toc_stream = new MemoryStream (toc))
|
||||||
|
using (var index = new StreamReader (toc_stream))
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
while ((line = index.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
var fields = line.Split (',');
|
||||||
|
if (fields.Length != 5)
|
||||||
|
return null;
|
||||||
|
var name = Path.ChangeExtension (fields[0], fields[4]);
|
||||||
|
string type = "";
|
||||||
|
if ("b" == fields[4])
|
||||||
|
{
|
||||||
|
type = "image";
|
||||||
|
has_images = true;
|
||||||
|
}
|
||||||
|
else if ("k" == fields[4] || "j" == fields[4])
|
||||||
|
type = "audio";
|
||||||
|
var entry = new PackedEntry
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Type = type,
|
||||||
|
Offset = UInt32.Parse (fields[3]),
|
||||||
|
Size = UInt32.Parse (fields[2]),
|
||||||
|
UnpackedSize = UInt32.Parse (fields[1]),
|
||||||
|
};
|
||||||
|
if (!entry.CheckPlacement (file.MaxOffset))
|
||||||
|
return null;
|
||||||
|
entry.IsPacked = entry.UnpackedSize != entry.Size;
|
||||||
|
dir.Add (entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == dir.Count)
|
||||||
|
return null;
|
||||||
|
if (!has_images)
|
||||||
|
return new ArcFile (file, this, dir);
|
||||||
|
var scheme = QueryScheme (file.Name);
|
||||||
|
return new BellArchive (file, this, dir, scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Stream DecryptImage (Stream input, uint entry_size, AImageScheme scheme)
|
||||||
|
{
|
||||||
|
int id = input.ReadByte();
|
||||||
|
if (id == scheme.Value2)
|
||||||
|
{
|
||||||
|
using (var reader = new AImageReader (input, scheme))
|
||||||
|
{
|
||||||
|
reader.Unpack();
|
||||||
|
return TgaStream.Create (reader.Info, reader.Data, scheme.Flipped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input.CanSeek)
|
||||||
|
{
|
||||||
|
input.Position = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var header = new byte[1] { (byte)id };
|
||||||
|
input = new PrefixStream (header, input);
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] ReadToc (string toc_name)
|
||||||
|
{
|
||||||
|
using (var toc_view = VFS.OpenView (toc_name))
|
||||||
|
{
|
||||||
|
if (toc_view.MaxOffset <= 8)
|
||||||
|
return null;
|
||||||
|
int unpacked_size = DecodeDecimal (toc_view, 0);
|
||||||
|
if (unpacked_size <= 4 || unpacked_size > 0x1000000)
|
||||||
|
return null;
|
||||||
|
int packed_size = DecodeDecimal (toc_view, 4);
|
||||||
|
if (packed_size > toc_view.MaxOffset - 8)
|
||||||
|
return null;
|
||||||
|
using (var toc_s = toc_view.CreateStream (8, (uint)packed_size))
|
||||||
|
using (var lzss = new LzssStream (toc_s))
|
||||||
|
{
|
||||||
|
var toc = new byte[unpacked_size];
|
||||||
|
if (toc.Length != lzss.Read (toc, 0, toc.Length))
|
||||||
|
return null;
|
||||||
|
return toc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DecodeDecimal (ArcView file, long offset)
|
||||||
|
{
|
||||||
|
int v = 0;
|
||||||
|
for (int rank = 1000; rank != 0; rank /= 10)
|
||||||
|
{
|
||||||
|
int b = file.View.ReadByte (offset++);
|
||||||
|
if (b != 0xFF)
|
||||||
|
v += (b ^ 0x7F) * rank;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1088,6 +1088,7 @@ Cartagra<br/>
|
|||||||
Kara no Shoujo 2<br/>
|
Kara no Shoujo 2<br/>
|
||||||
</td></td>
|
</td></td>
|
||||||
<tr><td>data.NN<br/>ArcNN.dat</td><td>-</td><td>No</td><td>Cyberworks</td><td>
|
<tr><td>data.NN<br/>ArcNN.dat</td><td>-</td><td>No</td><td>Cyberworks</td><td>
|
||||||
|
Abunai Kankei<br/>
|
||||||
Aneboku ~Onee-chan wa Bijin 3 Shimai~<br/>
|
Aneboku ~Onee-chan wa Bijin 3 Shimai~<br/>
|
||||||
Aniyome Kyouka-san to Sono Haha Chikako-san<br/>
|
Aniyome Kyouka-san to Sono Haha Chikako-san<br/>
|
||||||
Aru Kazoku no Kankeizu<br/>
|
Aru Kazoku no Kankeizu<br/>
|
||||||
@ -1117,6 +1118,7 @@ Shukubo no Uzuki ~Hitozuma Miboujin no Nareta Karada to Amai Toiki~<br/>
|
|||||||
Volley Coaching!<br/>
|
Volley Coaching!<br/>
|
||||||
Yumekoi Tensei<br/>
|
Yumekoi Tensei<br/>
|
||||||
Zoku Etsuraku no Tane<br/>
|
Zoku Etsuraku no Tane<br/>
|
||||||
|
Zoku Kairaku Izonshou ~Sono Go no Ryouko-san~<br/>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr class="odd"><td>*.bin</td><td><tt>OZ</tt></td><td>No</td><td>Patisserie</td><td>
|
<tr class="odd"><td>*.bin</td><td><tt>OZ</tt></td><td>No</td><td>Patisserie</td><td>
|
||||||
Ore no Tamanokoshi ni Notte Kure<br/>
|
Ore no Tamanokoshi ni Notte Kure<br/>
|
||||||
@ -1215,6 +1217,7 @@ Tsumi no Hikari Rendezvous<br/>
|
|||||||
</td></tr>
|
</td></tr>
|
||||||
<tr class="odd"><td>arc.dat</td><td>-</td><td>No</td><td rowspan="2">AdvSys3</td><td rowspan="2">
|
<tr class="odd"><td>arc.dat</td><td>-</td><td>No</td><td rowspan="2">AdvSys3</td><td rowspan="2">
|
||||||
Okami Tsuma ~Ryokan Baito de no Himitsu~<br/>
|
Okami Tsuma ~Ryokan Baito de no Himitsu~<br/>
|
||||||
|
Tain Shoukougun<br/>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr class="odd last"><td>*.gwd</td><td><tt>GWD</tt></td><td>No</td></tr>
|
<tr class="odd last"><td>*.gwd</td><td><tt>GWD</tt></td><td>No</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user