diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index 07455422..1920ebc3 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -70,6 +70,9 @@
CreateAMIWidget.xaml
+
+ CreateINTWidget.xaml
+
CreateONSWidget.xaml
@@ -139,6 +142,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/ArcFormats/ArcINT.cs b/ArcFormats/ArcINT.cs
index 0ac68e89..dbdf83c4 100644
--- a/ArcFormats/ArcINT.cs
+++ b/ArcFormats/ArcINT.cs
@@ -48,6 +48,7 @@ namespace GameRes.Formats
}
}
+ [Serializable()]
public class IntEncryptionInfo
{
public uint? Key { get; set; }
@@ -85,6 +86,7 @@ namespace GameRes.Formats
public override string Description { get { return arcStrings.INTDescription; } }
public override uint Signature { get { return 0x0046494b; } }
public override bool IsHierarchic { get { return false; } }
+ public override bool CanCreate { get { return true; } }
public override ArcFile TryOpen (ArcView file)
{
@@ -103,7 +105,7 @@ namespace GameRes.Formats
}
long current_offset = 8;
- var dir = new List();
+ var dir = new List ((int)entry_count);
for (uint i = 0; i < entry_count; ++i)
{
string name = file.View.ReadString (current_offset, 0x40);
@@ -135,7 +137,7 @@ namespace GameRes.Formats
Array.Reverse (blowfish_key);
var blowfish = new Blowfish (blowfish_key);
- var dir = new List();
+ var dir = new List ((int)entry_count-1);
byte[] name_info = new byte[0x40];
for (uint i = 1; i < entry_count; ++i)
{
@@ -332,10 +334,92 @@ namespace GameRes.Formats
return new GUI.WidgetINT ();
}
+ public override object GetCreationWidget ()
+ {
+ return new GUI.CreateINTWidget();
+ }
+
uint? QueryEncryptionInfo ()
{
var options = Query (arcStrings.INTNotice);
return options.EncryptionInfo.GetKey();
}
+
+ public override void Create (Stream output, IEnumerable list, ResourceOptions options,
+ EntryCallback callback)
+ {
+ int file_count = list.Count();
+ if (null != callback)
+ callback (file_count+2, null, null);
+ int callback_count = 0;
+ using (var writer = new BinaryWriter (output, Encoding.ASCII, true))
+ {
+ writer.Write (Signature);
+ writer.Write (file_count);
+ long dir_offset = output.Position;
+
+ var encoding = Encodings.cp932.WithFatalFallback();
+ byte[] name_buf = new byte[0x40];
+ int previous_size = 0;
+
+ if (null != callback)
+ callback (callback_count++, null, arcStrings.MsgWritingIndex);
+
+ // first, write names only
+ foreach (var entry in list)
+ {
+ string name = Path.GetFileName (entry.Name);
+ try
+ {
+ int size = encoding.GetBytes (name, 0, name.Length, name_buf, 0);
+ for (int i = size; i < previous_size; ++i)
+ name_buf[i] = 0;
+ previous_size = size;
+ }
+ catch (EncoderFallbackException X)
+ {
+ throw new InvalidFileName (entry.Name, arcStrings.MsgIllegalCharacters, X);
+ }
+ catch (ArgumentException X)
+ {
+ throw new InvalidFileName (entry.Name, arcStrings.MsgFileNameTooLong, X);
+ }
+ writer.Write (name_buf);
+ writer.BaseStream.Seek (8, SeekOrigin.Current);
+ }
+
+ // now, write files and remember offset/sizes
+ long current_offset = output.Position;
+ foreach (var entry in list)
+ {
+ if (null != callback)
+ callback (callback_count++, entry, arcStrings.MsgAddingFile);
+
+ entry.Offset = current_offset;
+ using (var input = File.OpenRead (entry.Name))
+ {
+ var size = input.Length;
+ if (size > uint.MaxValue || current_offset + size > uint.MaxValue)
+ throw new FileSizeException();
+ current_offset += (uint)size;
+ entry.Size = (uint)size;
+ input.CopyTo (output);
+ }
+ }
+
+ if (null != callback)
+ callback (callback_count++, null, arcStrings.MsgUpdatingIndex);
+
+ // at last, go back to directory and write offset/sizes
+ dir_offset += 0x40;
+ foreach (var entry in list)
+ {
+ writer.BaseStream.Position = dir_offset;
+ writer.Write ((uint)entry.Offset);
+ writer.Write (entry.Size);
+ dir_offset += 0x48;
+ }
+ }
+ }
}
}
diff --git a/ArcFormats/CreateINTWidget.xaml b/ArcFormats/CreateINTWidget.xaml
new file mode 100644
index 00000000..17295086
--- /dev/null
+++ b/ArcFormats/CreateINTWidget.xaml
@@ -0,0 +1,6 @@
+
+
+
diff --git a/ArcFormats/CreateINTWidget.xaml.cs b/ArcFormats/CreateINTWidget.xaml.cs
new file mode 100644
index 00000000..8fe74e57
--- /dev/null
+++ b/ArcFormats/CreateINTWidget.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace GameRes.Formats.GUI
+{
+ ///
+ /// Interaction logic for CreateINTWidget.xaml
+ ///
+ public partial class CreateINTWidget : Grid
+ {
+ public CreateINTWidget ()
+ {
+ InitializeComponent ();
+ }
+ }
+}
diff --git a/ArcFormats/Strings/arcStrings.Designer.cs b/ArcFormats/Strings/arcStrings.Designer.cs
index d1e0d0db..f4e68dca 100644
--- a/ArcFormats/Strings/arcStrings.Designer.cs
+++ b/ArcFormats/Strings/arcStrings.Designer.cs
@@ -142,6 +142,15 @@ namespace GameRes.Formats.Strings {
}
}
+ ///
+ /// Looks up a localized string similar to Encrypted archives creation is not implemented..
+ ///
+ public static string INTCreationNotice {
+ get {
+ return ResourceManager.GetString("INTCreationNotice", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to FrontWing game resource archive.
///
diff --git a/ArcFormats/Strings/arcStrings.resx b/ArcFormats/Strings/arcStrings.resx
index f186a541..5e1be3c9 100644
--- a/ArcFormats/Strings/arcStrings.resx
+++ b/ArcFormats/Strings/arcStrings.resx
@@ -145,6 +145,9 @@ Choose appropriate encryption scheme.
Liar-soft proprietary script format
+
+ Encrypted archives creation is not implemented.
+
FrontWing game resource archive
diff --git a/ArcFormats/Strings/arcStrings.ru-RU.resx b/ArcFormats/Strings/arcStrings.ru-RU.resx
index b8dfe3cd..60868c06 100644
--- a/ArcFormats/Strings/arcStrings.ru-RU.resx
+++ b/ArcFormats/Strings/arcStrings.ru-RU.resx
@@ -136,6 +136,9 @@
без шифрования
+
+ Создание зашифрованных архивов не реализовано.
+
Цифровой ключ должен быть 32-битным шестнадцатиричным числом