diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index e4a716ef..ed19f7ec 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -131,7 +131,9 @@
+
+
WidgetDXA.xaml
diff --git a/ArcFormats/DigitalWorks/ArcPACsingle.cs b/ArcFormats/DigitalWorks/ArcPACsingle.cs
new file mode 100644
index 00000000..310823c1
--- /dev/null
+++ b/ArcFormats/DigitalWorks/ArcPACsingle.cs
@@ -0,0 +1,88 @@
+//! \file ArcPACPS2.cs
+//! \date 2018 Sep 18
+//! \brief Digital Works PS2 resource archive.
+//
+// Copyright (C) 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
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//
+
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.IO;
+using GameRes.Compression;
+
+namespace GameRes.Formats.DigitalWorks
+{
+ [Export(typeof(ArchiveFormat))]
+ public class PacSingleOpener : ArchiveFormat
+ {
+ public override string Tag { get { return "PAC/LZS-TIM2"; } }
+ public override string Description { get { return "LZS-TIM2 Image archive"; } }
+ public override uint Signature { get { return 0x535A4C; } } // 'LZS'
+ public override bool IsHierarchic { get { return false; } }
+ public override bool CanWrite { get { return false; } }
+
+ /**
+ Target games:
+ Cafe Little Wish SLPM-65294
+ F Fanatic SLPM-65296
+ */
+
+ public override ArcFile TryOpen (ArcView file)
+ {
+ if (!file.View.AsciiEqual(9, "TIM2"))
+ return null;
+ var dir = new List (1);
+ var entry = FormatCatalog.Instance.Create (file.Name);
+ entry.Offset = 0L;
+ entry.Size = (uint)file.MaxOffset;
+ if (!entry.CheckPlacement (file.MaxOffset))
+ return null;
+ dir.Add (entry);
+
+ return new ArcFile (file, this, dir);
+ }
+
+ public override Stream OpenEntry (ArcFile arc, Entry entry)
+ {
+ var pent = entry as PackedEntry;
+ if (null == pent)
+ return base.OpenEntry (arc, entry);
+ if (!pent.IsPacked)
+ {
+ if (!arc.File.View.AsciiEqual (entry.Offset, "LZS\0"))
+ return base.OpenEntry (arc, entry);
+ pent.IsPacked = true;
+ pent.UnpackedSize = arc.File.View.ReadUInt32 (entry.Offset+4);
+ }
+ var input = arc.File.CreateStream (entry.Offset+8, entry.Size-8);
+ bool embedded_lzs = (input.Signature & ~0xF0u) == 0x535A4C0F; // 'LZS'
+ var lzs = new LzssStream (input);
+ if (embedded_lzs)
+ {
+ var header = new byte[8];
+ lzs.Read (header, 0, 8);
+ pent.UnpackedSize = header.ToUInt32 (4);
+ lzs = new LzssStream (lzs);
+ }
+ return lzs;
+ }
+ }
+}
diff --git a/ArcFormats/DigitalWorks/ImageTM2.cs b/ArcFormats/DigitalWorks/ImageTM2.cs
index 2c3a6afc..0be8eab1 100644
--- a/ArcFormats/DigitalWorks/ImageTM2.cs
+++ b/ArcFormats/DigitalWorks/ImageTM2.cs
@@ -23,6 +23,7 @@
// IN THE SOFTWARE.
//
+using GameRes.Formats.Strings;
using System;
using System.ComponentModel.Composition;
using System.IO;
@@ -36,6 +37,7 @@ internal class Tim2MetaData : ImageMetaData
public int PaletteSize;
public int HeaderSize;
public int Colors;
+ public byte Alpha;
}
[Export(typeof(ImageFormat))]
@@ -48,8 +50,16 @@ public class Tim2Format : ImageFormat
public Tim2Format ()
{
Extensions = new string[] { "tm2", "ext" };
+ Settings = new[] { AlphaFormat };
}
+ FixedSetSetting AlphaFormat = new FixedSetSetting(Properties.Settings.Default)
+ {
+ Name = "TIM2AlphaFormat",
+ Text = arcStrings.Tim2AlphaFormat,
+ ValuesSet = new[] { "No Alpha", "RGBX", "RGBA" },
+ };
+
public override ImageMetaData ReadMetaData (IBinaryStream file)
{
var header = file.ReadHeader (0x40);
@@ -62,6 +72,14 @@ public override ImageMetaData ReadMetaData (IBinaryStream file)
case 5: bpp = 8; break;
default: return null;
}
+ byte alpha;
+ switch (AlphaFormat.Get())
+ {
+ case "No Alpha": alpha = 0; break;
+ case "RGBX": alpha = 7; break;
+ case "RGBA":
+ default: alpha = 8; break;
+ }
return new Tim2MetaData {
Width = header.ToUInt16 (0x24),
Height = header.ToUInt16 (0x26),
@@ -69,6 +87,7 @@ public override ImageMetaData ReadMetaData (IBinaryStream file)
PaletteSize = header.ToInt32 (0x14),
HeaderSize = header.ToUInt16 (0x1C),
Colors = header.ToUInt16 (0x1E),
+ Alpha = alpha, //header.ToUInt16(0x30) == 0?// not so sure, there will be omissions
};
}
@@ -113,9 +132,9 @@ public byte[] Unpack ()
int image_size = (int)m_info.Width * (int)m_info.Height * pixel_size;
var output = m_input.ReadBytes (image_size);
if (pixel_size <= 8 && m_info.Colors > 0)
- Palette = ReadPalette (m_info.Colors);
+ Palette = ReadPalette (m_info.Colors, m_info.Alpha);
- if (pixel_size >= 3)
+ if (pixel_size == 3 || pixel_size == 4 && m_info.Alpha == 8)
{
for (int i = 0; i < image_size; i += pixel_size)
{
@@ -124,12 +143,36 @@ public byte[] Unpack ()
output[i+2] = r;
}
}
+ if (pixel_size == 4 && m_info.Alpha == 7)
+ {
+ for (int i = 0; i < image_size; i += 4)
+ {
+ byte r = output[i];
+ output[i] = output[i + 2];
+ output[i + 2] = r;
+ if (output[i + 3] >= byte.MaxValue / 2)
+ output[i + 3] = byte.MaxValue;
+ else
+ output[i + 3] = (byte)(output[i + 3] << 1);
+ }
+ }
+ if (pixel_size == 4 && m_info.Alpha == 0)
+ {
+ for (int i = 0; i < image_size; i += 4)
+ {
+ byte r = output[i];
+ output[i] = output[i + 2];
+ output[i + 2] = r;
+ output[i + 3] = byte.MaxValue;
+ }
+ }
return output;
}
- BitmapPalette ReadPalette (int color_num)
+ BitmapPalette ReadPalette (int color_num, byte X_A = 8)
{
- var source = ImageFormat.ReadColorMap (m_input.AsStream, color_num, PaletteFormat.RgbA);
+ var source = ImageFormat.ReadColorMap (m_input.AsStream,
+ color_num, X_A == 7 ? PaletteFormat.RgbA7 : X_A == 0 ? PaletteFormat.RgbX : PaletteFormat.RgbA);
var color_map = new Color[color_num];
int parts = color_num / 32;
diff --git a/ArcFormats/DigitalWorks/ImageTM2arc.cs b/ArcFormats/DigitalWorks/ImageTM2arc.cs
new file mode 100644
index 00000000..f7be9250
--- /dev/null
+++ b/ArcFormats/DigitalWorks/ImageTM2arc.cs
@@ -0,0 +1,53 @@
+using GameRes.Compression;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.IO;
+
+namespace GameRes.Formats.DigitalWorks
+{
+ [Export(typeof(ImageFormat))]
+ public class TM2ArkFormat : Tim2Format
+ {
+ public override string Tag { get { return "TIM2/PS2 compressed"; } }
+ public override string Description { get { return "PlayStation/2 image format with LZSS compress"; } }
+ public override uint Signature { get { return 0x535A4C; } } // 'LZS'
+ public TM2ArkFormat()
+ {
+ Extensions = new string[] { "tm2" };
+ Settings = null;
+ }
+
+ public override ImageMetaData ReadMetaData(IBinaryStream stream)
+ {
+ stream.Position = 9;
+ uint real_sign = stream.ReadUInt32();
+ //Tim2Format tm2raw = new Tim2Format();
+ if (real_sign != base.Signature)
+ {
+ return null;
+ }
+ stream.Position = 4;
+ uint unpacked_size = stream.ReadUInt32();
+ if (unpacked_size <= 0x20 || unpacked_size > 0x5000000) // ~83MB
+ return null;
+ stream.Position = 8;
+ using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
+ using (var input = new SeekableStream(lzss))
+ using (var tm2 = new BinaryStream(input, stream.Name))
+ return base.ReadMetaData(tm2);
+ }
+ public override ImageData Read(IBinaryStream stream, ImageMetaData info)
+ {
+ stream.Position = 8;
+ using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
+ using (var input = new SeekableStream(lzss))
+ using (var tm2 = new BinaryStream(input, stream.Name))
+ return base.Read(tm2, info);
+ }
+ public override void Write(Stream file, ImageData image)
+ {
+ throw new System.NotImplementedException("TM2ArkFormat.Write not implemented");
+ }
+ }
+}
diff --git a/ArcFormats/MAGES/ArcARC20.cs b/ArcFormats/MAGES/ArcARC20.cs
index a8c3f1cd..9c7a16c5 100644
--- a/ArcFormats/MAGES/ArcARC20.cs
+++ b/ArcFormats/MAGES/ArcARC20.cs
@@ -11,7 +11,7 @@ public class ARC20Opener : ArchiveFormat
public override string Tag { get { return "ARC/Princess Soft ARC20"; } }
public override string Description { get { return "Princess Soft PS2 resource archive"; } }
public override uint Signature { get { return 0x20435241; } } // 'ARC\x20'
- public override bool IsHierarchic { get { return false; } }
+ public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
diff --git a/ArcFormats/Properties/Settings.Designer.cs b/ArcFormats/Properties/Settings.Designer.cs
index f22c61a8..4bad779b 100644
--- a/ArcFormats/Properties/Settings.Designer.cs
+++ b/ArcFormats/Properties/Settings.Designer.cs
@@ -837,5 +837,17 @@ public int NexasEncodingCP {
this["NexasEncodingCP"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("RGBA")]
+ public string TIM2AlphaFormat {
+ get {
+ return ((string)(this["TIM2AlphaFormat"]));
+ }
+ set {
+ this["TIM2AlphaFormat"] = value;
+ }
+ }
}
}
diff --git a/ArcFormats/Properties/Settings.settings b/ArcFormats/Properties/Settings.settings
index a6aa5543..50457412 100644
--- a/ArcFormats/Properties/Settings.settings
+++ b/ArcFormats/Properties/Settings.settings
@@ -206,5 +206,8 @@
932
+
+ RGBA
+
\ No newline at end of file
diff --git a/ArcFormats/Strings/arcStrings.Designer.cs b/ArcFormats/Strings/arcStrings.Designer.cs
index c42b4340..accb3959 100644
--- a/ArcFormats/Strings/arcStrings.Designer.cs
+++ b/ArcFormats/Strings/arcStrings.Designer.cs
@@ -752,6 +752,16 @@ public static string SGLabelEncoding {
}
}
+ ///
+ /// Looks up a localized string similar to Choose Tim2 image alpha format.
+ /// It can't be read correctly from the file.
+ ///
+ public static string Tim2AlphaFormat {
+ get {
+ return ResourceManager.GetString("Tim2AlphaFormat", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Hex number.
///
diff --git a/ArcFormats/Strings/arcStrings.ja-JP.resx b/ArcFormats/Strings/arcStrings.ja-JP.resx
index 09cb1f5f..ea90ba37 100644
--- a/ArcFormats/Strings/arcStrings.ja-JP.resx
+++ b/ArcFormats/Strings/arcStrings.ja-JP.resx
@@ -501,4 +501,8 @@ Choose encryption scheme or enter a passphrase.
Default audio sampling rate
+
+ Tim2画像のAlpha形式を選択してください。
+ファイルから正しく読み取ることができません。
+
\ No newline at end of file
diff --git a/ArcFormats/Strings/arcStrings.resx b/ArcFormats/Strings/arcStrings.resx
index 435a145e..8543086c 100644
--- a/ArcFormats/Strings/arcStrings.resx
+++ b/ArcFormats/Strings/arcStrings.resx
@@ -401,4 +401,8 @@ Choose encryption scheme or enter a passphrase.
Default audio sampling rate
+
+ Choose Tim2 image alpha format.
+It can't be read correctly from the file.
+
\ No newline at end of file
diff --git a/ArcFormats/Strings/arcStrings.zh-Hans.resx b/ArcFormats/Strings/arcStrings.zh-Hans.resx
index 97a8a221..056eb3ec 100644
--- a/ArcFormats/Strings/arcStrings.zh-Hans.resx
+++ b/ArcFormats/Strings/arcStrings.zh-Hans.resx
@@ -399,4 +399,8 @@
默认音频采样率
+
+ 选择Tim2图片透明度格式。
+这无法从文件中正确获取。
+
\ No newline at end of file
diff --git a/ArcFormats/app.config b/ArcFormats/app.config
index eb7f9ea8..ef1cc161 100644
--- a/ArcFormats/app.config
+++ b/ArcFormats/app.config
@@ -208,6 +208,9 @@
932
+
+ RGBA
+