mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 03:44:13 +08:00
implemented AMI archive creation.
This commit is contained in:
parent
cb8dbb229c
commit
6005016a07
@ -26,12 +26,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
|
using System.Globalization;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using ZLibNet;
|
using ZLibNet;
|
||||||
|
using GameRes.Formats.Strings;
|
||||||
|
|
||||||
namespace GameRes.Formats
|
namespace GameRes.Formats
|
||||||
{
|
{
|
||||||
@ -62,6 +65,7 @@ namespace GameRes.Formats
|
|||||||
public override string Description { get { return Strings.arcStrings.AMIDescription; } }
|
public override string Description { get { return Strings.arcStrings.AMIDescription; } }
|
||||||
public override uint Signature { get { return 0x00494d41; } }
|
public override uint Signature { get { return 0x00494d41; } }
|
||||||
public override bool IsHierarchic { get { return false; } }
|
public override bool IsHierarchic { get { return false; } }
|
||||||
|
public override bool CanCreate { get { return true; } }
|
||||||
|
|
||||||
public AmiOpener ()
|
public AmiOpener ()
|
||||||
{
|
{
|
||||||
@ -124,6 +128,125 @@ namespace GameRes.Formats
|
|||||||
else
|
else
|
||||||
return new ZLibStream (input, CompressionMode.Decompress);
|
return new ZLibStream (input, CompressionMode.Decompress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Create (Stream output, IEnumerable<Entry> list, ResourceOptions options,
|
||||||
|
EntryCallback callback)
|
||||||
|
{
|
||||||
|
IDictionary<uint, PackedEntry> file_table = BuildFileTable (list);
|
||||||
|
uint file_count = (uint)file_table.Count;
|
||||||
|
if (0 == file_count)
|
||||||
|
throw new InvalidFormatException (arcStrings.AMINoFiles);
|
||||||
|
if (null != callback)
|
||||||
|
callback ((int)file_count+1, null, null);
|
||||||
|
|
||||||
|
int callback_count = 0;
|
||||||
|
long start_offset = output.Position;
|
||||||
|
uint data_offset = file_count * 16 + 16;
|
||||||
|
output.Seek (data_offset, SeekOrigin.Current);
|
||||||
|
foreach (var entry in file_table)
|
||||||
|
{
|
||||||
|
if (null != callback)
|
||||||
|
callback (callback_count++, entry.Value, arcStrings.MsgAddingFile);
|
||||||
|
long current_offset = output.Position;
|
||||||
|
if (current_offset > uint.MaxValue)
|
||||||
|
throw new FileSizeException();
|
||||||
|
entry.Value.Offset = (uint)current_offset;
|
||||||
|
entry.Value.Size = WriteAmiEntry (entry.Value, output);
|
||||||
|
}
|
||||||
|
if (null != callback)
|
||||||
|
callback (callback_count++, null, arcStrings.MsgWritingIndex);
|
||||||
|
output.Position = start_offset;
|
||||||
|
using (var header = new BinaryWriter (output, Encoding.ASCII, true))
|
||||||
|
{
|
||||||
|
header.Write (Signature);
|
||||||
|
header.Write (file_count);
|
||||||
|
header.Write (data_offset);
|
||||||
|
header.Write ((uint)0);
|
||||||
|
foreach (var entry in file_table)
|
||||||
|
{
|
||||||
|
header.Write (entry.Key);
|
||||||
|
header.Write ((uint)entry.Value.Offset);
|
||||||
|
header.Write ((uint)entry.Value.UnpackedSize);
|
||||||
|
header.Write ((uint)entry.Value.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IDictionary<uint, PackedEntry> BuildFileTable (IEnumerable<Entry> list)
|
||||||
|
{
|
||||||
|
var table = new SortedDictionary<uint, PackedEntry>();
|
||||||
|
foreach (var entry in list)
|
||||||
|
{
|
||||||
|
string ext = Path.GetExtension (entry.Name).ToLower();
|
||||||
|
if (entry.Type != "image" && ext != ".scr")
|
||||||
|
continue;
|
||||||
|
uint id;
|
||||||
|
if (!uint.TryParse (Path.GetFileNameWithoutExtension (entry.Name), NumberStyles.HexNumber,
|
||||||
|
CultureInfo.InvariantCulture, out id))
|
||||||
|
continue;
|
||||||
|
PackedEntry existing;
|
||||||
|
if (table.TryGetValue (id, out existing))
|
||||||
|
{
|
||||||
|
var file_new = new FileInfo (entry.Name);
|
||||||
|
var file_old = new FileInfo (existing.Name);
|
||||||
|
if (file_new.LastWriteTime <= file_old.LastWriteTime)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
table[id] = new PackedEntry
|
||||||
|
{
|
||||||
|
Name = entry.Name,
|
||||||
|
Type = entry.Type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint WriteAmiEntry (PackedEntry entry, Stream output)
|
||||||
|
{
|
||||||
|
uint packed_size = 0;
|
||||||
|
using (var input = File.OpenRead (entry.Name))
|
||||||
|
{
|
||||||
|
long file_size = input.Length;
|
||||||
|
if (file_size > uint.MaxValue)
|
||||||
|
throw new FileSizeException();
|
||||||
|
entry.UnpackedSize = (uint)file_size;
|
||||||
|
if ("image" == entry.Type)
|
||||||
|
{
|
||||||
|
packed_size = WriteImageEntry (entry, input, output);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input.CopyTo (output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packed_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint WriteImageEntry (PackedEntry entry, Stream input, Stream output)
|
||||||
|
{
|
||||||
|
var grp = FormatCatalog.Instance.LookupTag<GrpFormat> ("GRP").FirstOrDefault();
|
||||||
|
if (null == grp) // probably never happens
|
||||||
|
throw new FileFormatException ("GRP image encoder not available");
|
||||||
|
bool is_grp = grp.Signature == FormatCatalog.ReadSignature (input);
|
||||||
|
input.Position = 0;
|
||||||
|
using (var zstream = new ZLibStream (output, CompressionMode.Compress, true))
|
||||||
|
{
|
||||||
|
if (is_grp)
|
||||||
|
{
|
||||||
|
input.CopyTo (zstream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var image = ImageFormat.Read (input);
|
||||||
|
if (null == image)
|
||||||
|
throw new InvalidFormatException (string.Format (arcStrings.MsgInvalidImageFormat, entry.Name));
|
||||||
|
grp.Write (zstream, image);
|
||||||
|
entry.UnpackedSize = (uint)zstream.TotalIn;
|
||||||
|
}
|
||||||
|
zstream.Flush();
|
||||||
|
return (uint)zstream.TotalOut;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Export(typeof(ImageFormat))]
|
[Export(typeof(ImageFormat))]
|
||||||
|
18
ArcFormats/Strings/arcStrings.Designer.cs
generated
18
ArcFormats/Strings/arcStrings.Designer.cs
generated
@ -69,6 +69,15 @@ namespace GameRes.Formats.Strings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to No files suitable for AMI archive found..
|
||||||
|
/// </summary>
|
||||||
|
public static string AMINoFiles {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AMINoFiles", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Archive content is encrypted.
|
/// Looks up a localized string similar to Archive content is encrypted.
|
||||||
///Choose appropriate encryption scheme..
|
///Choose appropriate encryption scheme..
|
||||||
@ -216,6 +225,15 @@ namespace GameRes.Formats.Strings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to {0}: image format not recognized..
|
||||||
|
/// </summary>
|
||||||
|
public static string MsgInvalidImageFormat {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("MsgInvalidImageFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Updating index....
|
/// Looks up a localized string similar to Updating index....
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -120,6 +120,9 @@
|
|||||||
<data name="AMIDescription" xml:space="preserve">
|
<data name="AMIDescription" xml:space="preserve">
|
||||||
<value>Amaterasu Translations Muv-Luv archive</value>
|
<value>Amaterasu Translations Muv-Luv archive</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AMINoFiles" xml:space="preserve">
|
||||||
|
<value>No files suitable for AMI archive found.</value>
|
||||||
|
</data>
|
||||||
<data name="ArcEncryptedNotice" xml:space="preserve">
|
<data name="ArcEncryptedNotice" xml:space="preserve">
|
||||||
<value>Archive content is encrypted.
|
<value>Archive content is encrypted.
|
||||||
Choose appropriate encryption scheme.</value>
|
Choose appropriate encryption scheme.</value>
|
||||||
@ -171,6 +174,9 @@ predefined encryption scheme.</value>
|
|||||||
<data name="MsgIllegalCharacters" xml:space="preserve">
|
<data name="MsgIllegalCharacters" xml:space="preserve">
|
||||||
<value>File name contains illegal characters</value>
|
<value>File name contains illegal characters</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MsgInvalidImageFormat" xml:space="preserve">
|
||||||
|
<value>{0}: image format not recognized.</value>
|
||||||
|
</data>
|
||||||
<data name="MsgUpdatingIndex" xml:space="preserve">
|
<data name="MsgUpdatingIndex" xml:space="preserve">
|
||||||
<value>Updating index...</value>
|
<value>Updating index...</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -117,6 +117,9 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="AMINoFiles" xml:space="preserve">
|
||||||
|
<value>Не найдено файлов, подходящих для архива AMI.</value>
|
||||||
|
</data>
|
||||||
<data name="ArcEncryptedNotice" xml:space="preserve">
|
<data name="ArcEncryptedNotice" xml:space="preserve">
|
||||||
<value>Содержимое архива зашифровано.
|
<value>Содержимое архива зашифровано.
|
||||||
Выберите алгоритм шифрования.</value>
|
Выберите алгоритм шифрования.</value>
|
||||||
@ -156,6 +159,9 @@
|
|||||||
<data name="MsgIllegalCharacters" xml:space="preserve">
|
<data name="MsgIllegalCharacters" xml:space="preserve">
|
||||||
<value>Имя файла содержит недопустимые символы</value>
|
<value>Имя файла содержит недопустимые символы</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MsgInvalidImageFormat" xml:space="preserve">
|
||||||
|
<value>{0}: не удалось распознать формат изображения.</value>
|
||||||
|
</data>
|
||||||
<data name="MsgUpdatingIndex" xml:space="preserve">
|
<data name="MsgUpdatingIndex" xml:space="preserve">
|
||||||
<value>Обновляется оглавление...</value>
|
<value>Обновляется оглавление...</value>
|
||||||
</data>
|
</data>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user