mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 20:04:13 +08:00
(VFF): recognize multi-part archives.
This commit is contained in:
parent
111481c4ac
commit
48d741c37c
@ -2,7 +2,7 @@
|
||||
//! \date Wed Jun 08 00:27:36 2016
|
||||
//! \brief LiveMaker resource archive.
|
||||
//
|
||||
// Copyright (C) 2016 by morkt
|
||||
// Copyright (C) 2016-2018 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
|
||||
@ -51,13 +51,14 @@ namespace GameRes.Formats.LiveMaker
|
||||
{
|
||||
uint base_offset = 0;
|
||||
ArcView index_file = file;
|
||||
ArcView extra_file = null;
|
||||
try
|
||||
{
|
||||
// possible filesystem structure:
|
||||
// game.dat -- main archive body
|
||||
// game.001 -- [optional] extra part
|
||||
// game.ext -- [optional] separate index (could be included into the main body)
|
||||
// game.001 -- [optional] extra parts
|
||||
// game.002
|
||||
// ...
|
||||
|
||||
uint signature = index_file.View.ReadUInt32 (0);
|
||||
if (file.Name.HasExtension (".exe")
|
||||
@ -88,37 +89,30 @@ namespace GameRes.Formats.LiveMaker
|
||||
if (null == dir)
|
||||
return null;
|
||||
long max_offset = file.MaxOffset;
|
||||
for (int i = 0; i < dir.Count; ++i)
|
||||
var parts = new List<ArcView>();
|
||||
try
|
||||
{
|
||||
if (!dir[i].CheckPlacement (max_offset))
|
||||
for (int i = 1; i < 100; ++i)
|
||||
{
|
||||
if (extra_file != null)
|
||||
{
|
||||
// remove entries that don't fit into game.dat+game.001
|
||||
int discard = dir.Count - i;
|
||||
Trace.WriteLine (string.Format ("{0} entries didn't fit and were discarded", discard), "[vff]");
|
||||
dir.RemoveRange (i, discard);
|
||||
var ext = string.Format (".{0:D3}", i);
|
||||
var part_filename = Path.ChangeExtension (file.Name, ext);
|
||||
if (!VFS.FileExists (part_filename))
|
||||
break;
|
||||
var arc_file = VFS.OpenView (part_filename);
|
||||
max_offset += arc_file.MaxOffset;
|
||||
parts.Add (arc_file);
|
||||
}
|
||||
var extra_filename = Path.ChangeExtension (file.Name, ".001");
|
||||
if (!VFS.FileExists (extra_filename))
|
||||
return null;
|
||||
extra_file = VFS.OpenView (extra_filename);
|
||||
max_offset += extra_file.MaxOffset;
|
||||
if (!dir[i].CheckPlacement (max_offset))
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (null == extra_file)
|
||||
return new ArcFile (file, this, dir);
|
||||
return new VffArchive (file, this, dir, extra_file);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (extra_file != null)
|
||||
extra_file.Dispose();
|
||||
foreach (var part in parts)
|
||||
part.Dispose();
|
||||
throw;
|
||||
}
|
||||
if (0 == parts.Count)
|
||||
return new ArcFile (file, this, dir);
|
||||
return new MultiFileArchive (file, this, dir, parts);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (index_file != file)
|
||||
@ -128,7 +122,7 @@ namespace GameRes.Formats.LiveMaker
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var vff = arc as VffArchive;
|
||||
var vff = arc as MultiFileArchive;
|
||||
Stream input = null;
|
||||
if (vff != null)
|
||||
input = vff.OpenStream (entry);
|
||||
@ -218,43 +212,4 @@ namespace GameRes.Formats.LiveMaker
|
||||
m_current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal class VffArchive : ArcFile
|
||||
{
|
||||
readonly ArcView ExtraFile;
|
||||
|
||||
public VffArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, ArcView extra_file)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
ExtraFile = extra_file;
|
||||
}
|
||||
|
||||
internal Stream OpenStream (Entry entry)
|
||||
{
|
||||
if (entry.Offset < File.MaxOffset && entry.Offset+entry.Size > File.MaxOffset)
|
||||
{
|
||||
var first_part = File.View.ReadBytes (entry.Offset, entry.Size);
|
||||
var second_part = ExtraFile.CreateStream (0, entry.Size - (uint)first_part.Length);
|
||||
return new PrefixStream (first_part, second_part);
|
||||
}
|
||||
else if (entry.Offset >= File.MaxOffset)
|
||||
{
|
||||
return ExtraFile.CreateStream (entry.Offset, entry.Size);
|
||||
}
|
||||
else
|
||||
return File.CreateStream (entry.Offset, entry.Size);
|
||||
}
|
||||
|
||||
bool _vff_disposed = false;
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (!_vff_disposed)
|
||||
{
|
||||
if (disposing && ExtraFile != null)
|
||||
ExtraFile.Dispose();
|
||||
_vff_disposed = true;
|
||||
}
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user