diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index 1fac11fa..db64baa0 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -729,7 +729,6 @@
-
diff --git a/ArcFormats/Cyberworks/ArcP8.cs b/ArcFormats/Cyberworks/ArcP8.cs
index f968e81f..83342d86 100644
--- a/ArcFormats/Cyberworks/ArcP8.cs
+++ b/ArcFormats/Cyberworks/ArcP8.cs
@@ -55,7 +55,7 @@ namespace GameRes.Formats.TinkerBell
var entry = FormatCatalog.Instance.Create (name);
entry.Offset = file.View.ReadUInt32 (index_offset+0x18);
entry.Size = file.View.ReadUInt32 (index_offset+0x10);
- if (!entry.CheckPlacement (file.MaxOffset))
+ if (entry.Offset <= index_offset || !entry.CheckPlacement (file.MaxOffset))
return null;
dir.Add (entry);
}
diff --git a/ArcFormats/ExeFile.cs b/ArcFormats/ExeFile.cs
index 8c73f48f..b57f9b63 100644
--- a/ArcFormats/ExeFile.cs
+++ b/ArcFormats/ExeFile.cs
@@ -40,6 +40,7 @@ namespace GameRes.Formats
Section m_overlay;
uint m_image_base = 0;
List m_section_list;
+ bool? m_is_NE;
public ExeFile (ArcView file)
{
@@ -56,9 +57,18 @@ namespace GameRes.Formats
///
public Section Whole { get; private set; }
+ public bool IsWin16 => m_is_NE ?? (m_is_NE = IsNe()).Value;
+
+ private bool IsNe ()
+ {
+ uint ne_offset = View.ReadUInt32 (0x3C);
+ return ne_offset < m_file.MaxOffset-2 && View.AsciiEqual (ne_offset, "NE");
+ }
+
///
/// Dictionary of executable file sections.
///
+ ///
public IReadOnlyDictionary Sections
{
get
@@ -255,6 +265,11 @@ namespace GameRes.Formats
private void InitSectionTable ()
{
+ if (IsWin16)
+ {
+ InitNe();
+ return;
+ }
long pe_offset = GetHeaderOffset();
int opt_header = View.ReadUInt16 (pe_offset+0x14); // SizeOfOptionalHeader
long section_table = pe_offset+opt_header+0x18;
@@ -294,6 +309,26 @@ namespace GameRes.Formats
m_section_list = list;
}
+ void InitNe ()
+ {
+ uint ne_offset = m_file.View.ReadUInt32 (0x3C);
+ int segment_count = m_file.View.ReadUInt16 (ne_offset + 0x1C);
+ uint seg_table = m_file.View.ReadUInt16 (ne_offset + 0x22) + ne_offset;
+ int shift = m_file.View.ReadUInt16 (ne_offset + 0x32);
+ uint last_seg_end = 0;
+ for (int i = 0; i < segment_count; ++i)
+ {
+ uint offset = (uint)m_file.View.ReadUInt16 (seg_table) << shift;
+ uint size = m_file.View.ReadUInt16 (seg_table+2);
+ if (offset + size > last_seg_end)
+ last_seg_end = offset + size;
+ }
+ m_overlay.Offset = last_seg_end;
+ m_overlay.Size = (uint)(m_file.MaxOffset - last_seg_end);
+ m_section_table = new Dictionary(); // these are empty for 16-bit executables
+ m_section_list = new List(); //
+ }
+
///
/// Helper class for executable file resources access.
///
diff --git a/ArcFormats/ImageMB.cs b/ArcFormats/ImageMB.cs
index 39925bdc..0dd5da9f 100644
--- a/ArcFormats/ImageMB.cs
+++ b/ArcFormats/ImageMB.cs
@@ -38,17 +38,18 @@ namespace GameRes.Formats
public MbImageFormat ()
{
- Extensions = new[] { "bmp", "gra" };
+ Extensions = new[] { "bmp", "gra", "xxx" };
}
public override ImageMetaData ReadMetaData (IBinaryStream stream)
{
int c1 = stream.ReadByte();
int c2 = stream.ReadByte();
+ // MB/MC/MK/CL
switch (c1)
{
case 'M':
- if ('B' != c2 && 'C' != c2)
+ if ('B' != c2 && 'C' != c2 && 'K' != c2)
return null;
break;
case 'C':
diff --git a/ArcFormats/KiriKiri/ArcXP3.cs b/ArcFormats/KiriKiri/ArcXP3.cs
index 29d05082..02114bc3 100644
--- a/ArcFormats/KiriKiri/ArcXP3.cs
+++ b/ArcFormats/KiriKiri/ArcXP3.cs
@@ -88,7 +88,7 @@ namespace GameRes.Formats.KiriKiri
public Xp3Opener ()
{
- Signatures = new uint[] { 0x0d335058, 0 };
+ Signatures = new uint[] { 0x0d335058, 0x00905A4D, 0 };
Extensions = new[] { "XP3", "EXE" };
ContainedFormats = new[] { "TLG", "BMP", "PNG", "JPEG", "OGG", "WAV", "TXT" };
}
diff --git a/ArcFormats/LiveMaker/ArcVF.cs b/ArcFormats/LiveMaker/ArcVF.cs
index ee40f60f..8bb78d2c 100644
--- a/ArcFormats/LiveMaker/ArcVF.cs
+++ b/ArcFormats/LiveMaker/ArcVF.cs
@@ -45,7 +45,7 @@ namespace GameRes.Formats.LiveMaker
public VffOpener ()
{
Extensions = new string[] { "dat", "exe" };
- Signatures = new uint[] { 0x666676, 0 };
+ Signatures = new uint[] { 0x666676, 0x00905A4D, 0 };
}
public override ArcFile TryOpen (ArcView file)
diff --git a/ArcFormats/MAI/ImageMAI.cs b/ArcFormats/MAI/ImageMAI.cs
index 2263d9fb..c636667a 100644
--- a/ArcFormats/MAI/ImageMAI.cs
+++ b/ArcFormats/MAI/ImageMAI.cs
@@ -50,7 +50,7 @@ namespace GameRes.Formats.MAI
public CmFormat ()
{
- Extensions = new string[] { "cm" };
+ Extensions = new string[] { "cmp" };
}
public override void Write (Stream file, ImageData image)
@@ -60,24 +60,22 @@ namespace GameRes.Formats.MAI
public override ImageMetaData ReadMetaData (IBinaryStream stream)
{
- if ('C' != stream.ReadByte() || 'M' != stream.ReadByte())
+ var header = stream.ReadHeader (0x20);
+ if ('C' != header[0] || 'M' != header[1])
return null;
- var header = stream.ReadBytes (0x1e);
- if (header.Length != 0x1e)
+ if (1 != header[0x0E])
return null;
- if (1 != header[0x0c])
- return null;
- uint size = LittleEndian.ToUInt32 (header, 0);
+ uint size = LittleEndian.ToUInt32 (header, 2);
if (size != stream.Length)
return null;
var info = new CmMetaData();
- info.Width = LittleEndian.ToUInt16 (header, 4);
- info.Height = LittleEndian.ToUInt16 (header, 6);
- info.Colors = LittleEndian.ToUInt16 (header, 8);
- info.BPP = header[0x0a];
- info.IsCompressed = 0 != header[0x0b];
- info.DataOffset = LittleEndian.ToUInt32 (header, 0x0e);
- info.DataLength = LittleEndian.ToUInt32 (header, 0x12);
+ info.Width = LittleEndian.ToUInt16 (header, 6);
+ info.Height = LittleEndian.ToUInt16 (header, 8);
+ info.Colors = LittleEndian.ToUInt16 (header, 0x0A);
+ info.BPP = header[0x0C];
+ info.IsCompressed = 0 != header[0x0D];
+ info.DataOffset = LittleEndian.ToUInt32 (header, 0x10);
+ info.DataLength = LittleEndian.ToUInt32 (header, 0x14);
if (info.DataLength > size)
return null;
return info;
@@ -158,7 +156,7 @@ namespace GameRes.Formats.MAI
public AmFormat ()
{
- Extensions = new string[] { "am", "ami" };
+ Extensions = new string[] { "amp", "ami" };
}
public override void Write (Stream file, ImageData image)
@@ -235,6 +233,8 @@ namespace GameRes.Formats.MAI
m_pixels = new byte[m_width*m_height*4];
}
+ static readonly Color Default8bppTransparencyColor = Color.FromRgb (0, 0xFE, 0);
+
public void Unpack ()
{
if (m_info.Colors > 0)
@@ -262,13 +262,23 @@ namespace GameRes.Formats.MAI
m_pixels[dst+3] = alpha;
};
else
+ {
+ const int alphaScale = 0x11;
+ var alphaColor = Color.FromRgb (0, 0xFE, 0);
copy_pixel = (src, dst, alpha) => {
var color = Palette.Colors[m_output[src]];
+ if (Default8bppTransparencyColor == color)
+ alpha = 0;
+ else if (0 == alpha)
+ alpha = 0xFF;
+ else
+ alpha *= alphaScale;
m_pixels[dst] = color.B;
m_pixels[dst+1] = color.G;
m_pixels[dst+2] = color.R;
m_pixels[dst+3] = alpha;
};
+ }
int src_stride = m_width * m_pixel_size;
for (int y = 0; y < m_height; ++y)
{
diff --git a/ArcFormats/Macintosh/ImagePICT.cs b/ArcFormats/Macintosh/ImagePICT.cs
index d332afa1..98d999d9 100644
--- a/ArcFormats/Macintosh/ImagePICT.cs
+++ b/ArcFormats/Macintosh/ImagePICT.cs
@@ -190,6 +190,9 @@ namespace GameRes.Formats.Apple
break;
}
+ case 0x001E: // DefHilite
+ break;
+
case 0x0090:
case 0x0091:
case 0x0098:
diff --git a/ArcFormats/Macromedia/ArcCCT.cs b/ArcFormats/Macromedia/ArcCCT.cs
deleted file mode 100644
index 0f31f25c..00000000
--- a/ArcFormats/Macromedia/ArcCCT.cs
+++ /dev/null
@@ -1,256 +0,0 @@
-//! \file ArcCCT.cs
-//! \date Fri Jun 26 01:15:26 2015
-//! \brief Macromedia Director archive access implementation.
-//
-// Copyright (C) 2015 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;
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.IO;
-using System.Linq;
-using System.Text;
-using GameRes.Compression;
-using GameRes.Utility;
-
-namespace GameRes.Formats.Macromedia
-{
- [Export(typeof(ArchiveFormat))]
- public class CctOpener : ArchiveFormat
- {
- public override string Tag { get { return "CCT"; } }
- public override string Description { get { return "Macromedia Shockwave resource archive"; } }
- public override uint Signature { get { return 0x52494658; } } // 'XFIR'
- public override bool IsHierarchic { get { return false; } }
- public override bool CanWrite { get { return false; } }
-
- public CctOpener ()
- {
- Extensions = new string[] { "cct", "dcr" };
- }
-
- public override ArcFile TryOpen (ArcView file)
- {
- uint id = file.View.ReadUInt32 (8);
- if (id != 0x46474443 && id != 0x4647444D) // 'CDGF' || 'MDGF'
- return null;
-
- var reader = new CctReader (file);
- var dir = reader.ReadIndex();
- if (null != dir)
- {
- var arc = new ArcFile (file, this, dir);
- SetEntryTypes (arc);
- return arc;
- }
- return null;
- }
-
- public override Stream OpenEntry (ArcFile arc, Entry entry)
- {
- var input = arc.File.CreateStream (entry.Offset, entry.Size);
- var packed_entry = entry as PackedEntry;
- if (null == packed_entry || !packed_entry.IsPacked)
- return input;
- else
- return new ZLibStream (input, CompressionMode.Decompress);
- }
-
- private void SetEntryTypes (ArcFile arc)
- {
- foreach (var entry in arc.Dir.OrderBy (x => x.Offset))
- {
- if (entry.Name.EndsWith (".edim"))
- entry.Type = DetectEdimType (arc, entry);
- else if (entry.Name.EndsWith (".bitd"))
- entry.Type = "image";
- }
- }
-
- private string DetectEdimType (ArcFile arc, Entry entry)
- {
- using (var input = OpenEntry (arc, entry))
- {
- uint signature = (uint)input.ReadByte() << 24;
- signature |= (uint)input.ReadByte() << 16;
- signature |= (uint)input.ReadByte() << 8;
- signature |= (byte)input.ReadByte();
- if (0xffd8ffe0 == signature)
- return "image";
- uint real_size = (entry as PackedEntry).UnpackedSize;
- if (signature > 0xffff || signature+4 > real_size)
- return "";
- var header = new byte[signature+0x10];
- if (header.Length != input.Read (header, 0, header.Length))
- return "";
- if (0xff == header[signature])
- return "audio";
- return "";
- }
- }
- }
-
- internal class CctReader
- {
- ArcView m_file;
- long m_offset;
-
- public CctReader (ArcView file)
- {
- m_file = file;
- m_offset = 0x0C;
- }
-
- byte[] m_size_buffer = new byte[10];
-
- public List ReadIndex ()
- {
- uint section_size = ReadSectionSize ("Fver");
- m_offset += section_size;
- section_size = ReadSectionSize ("Fcdr");
- /*
- int Mcdr_size;
- var Mcdr = ZlibUnpack (m_offset, section_size, out Mcdr_size);
- */
- m_offset += section_size;
- uint abmp_size = ReadSectionSize ("ABMP");
- int max_count = m_file.View.Read (m_offset, m_size_buffer, 0, Math.Min (10, abmp_size));
- int size_offset = 0;
- ReadValue (m_size_buffer, ref size_offset, max_count);
- max_count -= size_offset;
-
- int bmp_unpacked_size = (int)ReadValue (m_size_buffer, ref size_offset, max_count);
- m_offset += size_offset;
- abmp_size -= (uint)size_offset;
- int index_size;
- var index = ZlibUnpack (m_offset, abmp_size, out index_size, bmp_unpacked_size);
- m_offset += abmp_size;
- section_size = ReadSectionSize ("FGEI");
- if (0 != section_size)
- throw new NotSupportedException();
-
- int index_offset = 0;
- ReadValue (index, ref index_offset, index_size-index_offset);
- ReadValue (index, ref index_offset, index_size-index_offset);
- int entry_count = (int)ReadValue (index, ref index_offset, index_size-index_offset);
- if (entry_count <= 0 || entry_count > 0xfffff)
- return null;
-
- var type_buf = new char[4];
- var dir = new List (entry_count);
- for (int i = 0; i < entry_count; ++i)
- {
- uint id = ReadValue (index, ref index_offset, index_size-index_offset);
- uint offset = ReadValue (index, ref index_offset, index_size-index_offset);
- uint size = ReadValue (index, ref index_offset, index_size-index_offset);
- uint unpacked_size = ReadValue (index, ref index_offset, index_size-index_offset);
- uint flag = ReadValue (index, ref index_offset, index_size-index_offset);
-
- if (index_size-index_offset < 4)
- return null;
- uint type_id = LittleEndian.ToUInt32 (index, index_offset);
- index_offset += 4;
- if (0 == type_id || uint.MaxValue == offset)
- continue;
-
- Encoding.ASCII.GetChars (index, index_offset-4, 4, type_buf, 0);
- var entry = new PackedEntry
- {
- Name = CreateName (id, type_buf),
- Offset = (long)m_offset + offset,
- Size = size,
- UnpackedSize = unpacked_size,
- IsPacked = 0 == flag,
- };
- if (entry.CheckPlacement (m_file.MaxOffset))
- {
- dir.Add (entry);
- }
- }
- return dir;
- }
-
- string CreateName (uint id, char[] type_buf)
- {
- Array.Reverse (type_buf);
- int t = 3;
- while (t >= 0 && ' ' == type_buf[t])
- t--;
- if (t >= 0)
- {
- string ext = new string (type_buf, 0, t+1);
- return string.Format ("{0:D8}.{1}", id, ext.ToLowerInvariant());
- }
- else
- return id.ToString ("D8");
- }
-
- byte[] ZlibUnpack (long offset, uint size, out int actual_size, int unpacked_size_hint = 0)
- {
- using (var input = m_file.CreateStream (offset, size))
- using (var zstream = new ZLibStream (input, CompressionMode.Decompress))
- using (var mem = new MemoryStream (unpacked_size_hint))
- {
- zstream.CopyTo (mem);
- actual_size = (int)mem.Length;
- return mem.GetBuffer();
- }
- }
-
- uint ReadSectionSize (string id_str)
- {
- uint id = ConvertId (id_str);
- if (id != m_file.View.ReadUInt32 (m_offset))
- throw new InvalidFormatException();
- m_offset += 4;
- if (5 != m_file.View.Read (m_offset, m_size_buffer, 0, 5))
- throw new InvalidFormatException();
- int off_count = 0;
- uint size = ReadValue (m_size_buffer, ref off_count, 5);
- m_offset += off_count;
- return size;
- }
-
- static uint ReadValue (byte[] buffer, ref int offset, int length)
- {
- uint n = 0;
- for (int off_count = 0; off_count < length; ++off_count)
- {
- uint bits = buffer[offset++];
- n = (n << 7) | (bits & 0x7F);
- if (0 == (bits & 0x80))
- return n;
- }
- throw new InvalidFormatException();
- }
-
- static uint ConvertId (string id)
- {
- if (id.Length != 4)
- throw new ArgumentException ("Invalid section id");
- uint n = 0;
- for (int i = 0; i < 4; ++i)
- n = (n << 8) | (byte)id[i];
- return n;
- }
- }
-}
diff --git a/ArcFormats/Macromedia/ArcDXR.cs b/ArcFormats/Macromedia/ArcDXR.cs
index ed6eabc5..31a19e29 100644
--- a/ArcFormats/Macromedia/ArcDXR.cs
+++ b/ArcFormats/Macromedia/ArcDXR.cs
@@ -38,46 +38,58 @@ namespace GameRes.Formats.Macromedia
[Export(typeof(ArchiveFormat))]
public class DxrOpener : ArchiveFormat
{
- public override string Tag { get => "DXR"; }
- public override string Description { get => "Macromedia Director resource archive"; }
- public override uint Signature { get => 0x52494658; } // 'XFIR'
- public override bool IsHierarchic { get => false; }
- public override bool CanWrite { get => false; }
+ public override string Tag => "DXR";
+ public override string Description => "Macromedia Director resource archive";
+ public override uint Signature => SignatureXFIR; // 'XFIR'
+ public override bool IsHierarchic => false;
+ public override bool CanWrite => false;
+
+ public const uint SignatureXFIR = 0x52494658u;
+ public const uint SignatureRIFX = 0x58464952u;
public DxrOpener ()
{
- Extensions = new[] { "dxr", "cxt", "cct", "dcr" };
- Signatures = new[] { 0x52494658u, 0x58464952u };
+ Extensions = new[] { "dxr", "cxt", "cct", "dcr", "exe" };
+ Signatures = new[] { SignatureXFIR, SignatureRIFX, 0x00905A4Du, 0u };
}
internal static readonly HashSet RawChunks = new HashSet {
- "RTE0", "RTE1", "FXmp", "VWFI", "VWSC", "Lscr", "STXT", "XMED", //"snd "
+ "RTE0", "RTE1", "FXmp", "VWFI", "VWSC", "Lscr", "STXT", "XMED", "File"
};
internal bool ConvertText = true;
public override ArcFile TryOpen (ArcView file)
{
+ long base_offset = 0;
+ if (file.View.AsciiEqual (0, "MZ"))
+ base_offset = LookForXfir (file);
+ uint signature = file.View.ReadUInt32 (base_offset);
+ if (signature != SignatureXFIR && signature != SignatureRIFX)
+ return null;
using (var input = file.CreateStream())
{
- ByteOrder ord = input.Signature == 0x52494658u ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
+ ByteOrder ord = signature == SignatureXFIR ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
var reader = new Reader (input, ord);
- reader.Position = 4;
- uint length = reader.ReadU32();
+ reader.Position = base_offset;
var context = new SerializationContext();
var dir_file = new DirectorFile();
if (!dir_file.Deserialize (context, reader))
return null;
var dir = new List ();
- ImportMedia (dir_file, dir);
+ if (dir_file.Codec != "APPL")
+ ImportMedia (dir_file, dir);
foreach (DirectorEntry entry in dir_file.Directory)
{
if (entry.Size != 0 && entry.Offset != -1 && RawChunks.Contains (entry.FourCC))
{
entry.Name = string.Format ("{0:D6}.{1}", entry.Id, entry.FourCC.Trim());
- if ("snd " == entry.FourCC)
- entry.Type = "audio";
+ if ("File" == entry.FourCC)
+ {
+ entry.Offset -= 8;
+ entry.Size += 8;
+ }
dir.Add (entry);
}
}
@@ -155,7 +167,7 @@ namespace GameRes.Formats.Macromedia
entry = ImportBitmap (piece, dir_file, cast);
else if (piece.Type == DataType.Sound)
entry = ImportSound (piece, dir_file);
- if (entry != null)
+ if (entry != null && entry.Size > 0)
dir.Add (entry);
}
}
@@ -381,6 +393,56 @@ namespace GameRes.Formats.Macromedia
zstream.Read (data, 0, data.Length);
return new BinMemoryStream (data, entry.Name);
}
+
+ static readonly byte[] s_xfir = { (byte)'X', (byte)'F', (byte)'I', (byte)'R' };
+
+ long LookForXfir (ArcView file)
+ {
+ var exe = new ExeFile (file);
+ long pos;
+ if (exe.IsWin16)
+ {
+ pos = exe.FindString (exe.Overlay, s_xfir);
+ if (pos < 0)
+ return 0;
+ }
+ else
+ {
+ pos = exe.Overlay.Offset;
+ if (pos >= file.MaxOffset)
+ return 0;
+ if (file.View.AsciiEqual (pos, "10JP"))
+ {
+ pos = file.View.ReadUInt32 (pos+4);
+ }
+ }
+ if (pos >= file.MaxOffset || !file.View.AsciiEqual (pos, "XFIR"))
+ return 0;
+ // TODO threat 'LPPA' archives the normal way, like archives that contain entries.
+ // the problem is, DXR archives contained within 'LPPA' have their offsets relative to executable file,
+ // so have to figure out way to handle it.
+ if (!file.View.AsciiEqual (pos+8, "LPPA"))
+ return pos;
+ var appl = new DirectorFile();
+ var context = new SerializationContext();
+ using (var input = file.CreateStream())
+ {
+ var reader = new Reader (input, ByteOrder.LittleEndian);
+ input.Position = pos + 12;
+ if (!appl.ReadMMap (context, reader))
+ return 0;
+ foreach (var entry in appl.Directory)
+ {
+ // only the first XFIR entry is matched here, but archive may contain multiple sub-archives.
+ if (entry.FourCC == "File")
+ {
+ if (file.View.AsciiEqual (entry.Offset-8, "XFIR"))
+ return entry.Offset-8;
+ }
+ }
+ return 0;
+ }
+ }
}
internal class BitmapEntry : PackedEntry
@@ -409,8 +471,11 @@ namespace GameRes.Formats.Macromedia
Right = reader.ReadI16();
reader.Skip (0x0C);
BitDepth = reader.ReadU16() & 0xFF; // ???
- reader.Skip (2);
- Palette = reader.ReadI16();
+ if (data.Length >= 0x1C)
+ {
+ reader.Skip (2);
+ Palette = reader.ReadI16();
+ }
}
}
}
diff --git a/ArcFormats/Macromedia/AudioEDIM.cs b/ArcFormats/Macromedia/AudioEDIM.cs
index 18925d59..aab5eaca 100644
--- a/ArcFormats/Macromedia/AudioEDIM.cs
+++ b/ArcFormats/Macromedia/AudioEDIM.cs
@@ -1,6 +1,6 @@
//! \file AudioEDIM.cs
//! \date Fri Jun 26 06:52:33 2015
-//! \brief Selen wrapper around MP3 stream.
+//! \brief Macromedia Director wrapper around MP3 stream.
//
// Copyright (C) 2015 by morkt
//
@@ -33,7 +33,7 @@ namespace GameRes.Formats.Selen
public class EdimAudio : Mp3Audio
{
public override string Tag { get { return "EDIM"; } }
- public override string Description { get { return "Selen audio format (MP3)"; } }
+ public override string Description { get { return "Macromedia Director audio format (MP3)"; } }
public override uint Signature { get { return 0x40010000; } }
public override bool CanWrite { get { return false; } }
diff --git a/ArcFormats/Macromedia/DirectorFile.cs b/ArcFormats/Macromedia/DirectorFile.cs
index cca399d5..a1b2232f 100644
--- a/ArcFormats/Macromedia/DirectorFile.cs
+++ b/ArcFormats/Macromedia/DirectorFile.cs
@@ -75,6 +75,9 @@ namespace GameRes.Formats.Macromedia
DirectorConfig m_config = new DirectorConfig();
List m_casts = new List();
Dictionary m_ilsMap = new Dictionary();
+ string m_codec;
+
+ public string Codec => m_codec;
public bool IsAfterBurned { get; private set; }
@@ -96,14 +99,14 @@ namespace GameRes.Formats.Macromedia
public bool Deserialize (SerializationContext context, Reader reader)
{
- reader.Position = 8;
- string codec = reader.ReadFourCC();
- if (codec == "MV93" || codec == "MC95")
+ reader.Skip (8);
+ m_codec = reader.ReadFourCC();
+ if (m_codec == "MV93" || m_codec == "MC95")
{
if (!ReadMMap (context, reader))
return false;
}
- else if (codec == "FGDC" || codec == "FGDM")
+ else if (m_codec == "FGDC" || m_codec == "FGDM")
{
IsAfterBurned = true;
if (!ReadAfterBurner (context, reader))
@@ -111,7 +114,7 @@ namespace GameRes.Formats.Macromedia
}
else
{
- Trace.WriteLine (string.Format ("Unknown codec '{0}'", codec), "DXR");
+ Trace.WriteLine (string.Format ("Unknown m_codec '{0}'", m_codec), "DXR");
return false;
}
return ReadKeyTable (context, reader)
@@ -119,7 +122,7 @@ namespace GameRes.Formats.Macromedia
&& ReadCasts (context, reader);
}
- bool ReadMMap (SerializationContext context, Reader reader)
+ internal bool ReadMMap (SerializationContext context, Reader reader)
{
if (reader.ReadFourCC() != "imap")
return false;
diff --git a/ArcFormats/Macromedia/ImageBITD.cs b/ArcFormats/Macromedia/ImageBITD.cs
index fb571e6a..0e1795a6 100644
--- a/ArcFormats/Macromedia/ImageBITD.cs
+++ b/ArcFormats/Macromedia/ImageBITD.cs
@@ -71,7 +71,7 @@ namespace GameRes.Formats.Macromedia
: info.BPP == 8 ? PixelFormats.Indexed8
: info.BPP == 16 ? PixelFormats.Bgr555
: info.DepthType == 0x87 // i have no clue what this is
- || info.DepthType == 0x8A ? PixelFormats.Bgra32 // depth type 0x87/0x8A
+ || info.DepthType == 0x8A ? PixelFormats.Bgra32 // depth type 0x87/0x8A
: PixelFormats.Bgra32; // depth type 0x82/84/85/86/8C
m_palette = palette;
}
@@ -151,32 +151,7 @@ namespace GameRes.Formats.Macromedia
{
for (int line = 0; line < m_output.Length; line += m_stride)
{
- int x = 0;
- while (x < m_stride)
- {
- int b = m_input.ReadByte();
- if (-1 == b)
- throw new InvalidFormatException ("Unexpected end of file");
- int count = b;
- if (b > 0x7f)
- count = (byte)-(sbyte)b;
- ++count;
- if (x + count > m_stride)
- throw new InvalidFormatException();
- if (b > 0x7f)
- {
- b = m_input.ReadByte();
- if (-1 == b)
- throw new InvalidFormatException ("Unexpected end of file");
- for (int i = 0; i < count; ++i)
- m_output[line + x++] = (byte)b;
- }
- else
- {
- m_input.Read (m_output, line + x, count);
- x += count;
- }
- }
+ UnpackScanLine (m_output, line);
}
return m_output;
}
@@ -186,33 +161,7 @@ namespace GameRes.Formats.Macromedia
var scan_line = new byte[m_stride];
for (int line = 0; line < m_output.Length; line += m_stride)
{
- int x = 0;
- while (x < m_stride)
- {
- int b = m_input.ReadByte();
- if (-1 == b)
- break; // one in 5000 images somehow stumbles here
-// throw new InvalidFormatException ("Unexpected end of file");
- int count = b;
- if (b > 0x7f)
- count = (byte)-(sbyte)b;
- ++count;
- if (x + count > m_stride)
- throw new InvalidFormatException();
- if (b > 0x7f)
- {
- b = m_input.ReadByte();
- if (-1 == b)
- throw new InvalidFormatException ("Unexpected end of file");
- for (int i = 0; i < count; ++i)
- scan_line[x++] = (byte)b;
- }
- else
- {
- m_input.Read (scan_line, x, count);
- x += count;
- }
- }
+ UnpackScanLine (scan_line, 0);
int dst = line;
for (int i = 0; i < m_width; ++i)
{
@@ -222,6 +171,36 @@ namespace GameRes.Formats.Macromedia
}
}
+ void UnpackScanLine (byte[] scan_line, int pos)
+ {
+ int x = 0;
+ while (x < m_stride)
+ {
+ int b = m_input.ReadByte();
+ if (-1 == b)
+ break; // one in 5000 images somehow stumbles here
+ int count = b;
+ if (b > 0x7f)
+ count = (byte)-(sbyte)b;
+ ++count;
+ if (x + count > m_stride)
+ throw new InvalidFormatException();
+ if (b > 0x7f)
+ {
+ b = m_input.ReadByte();
+ if (-1 == b)
+ throw new InvalidFormatException ("Unexpected end of file");
+ for (int i = 0; i < count; ++i)
+ scan_line[pos + x++] = (byte)b;
+ }
+ else
+ {
+ m_input.Read (scan_line, pos+x, count);
+ x += count;
+ }
+ }
+ }
+
#region IDisposable Members
bool m_disposed = false;
diff --git a/ArcFormats/RealLive/ArcSEEN.cs b/ArcFormats/RealLive/ArcSEEN.cs
index 772f1ff6..791c0742 100644
--- a/ArcFormats/RealLive/ArcSEEN.cs
+++ b/ArcFormats/RealLive/ArcSEEN.cs
@@ -111,7 +111,7 @@ namespace GameRes.Formats.RealLive
int offset = input.ReadUInt16();
int count = (offset & 0xF) + 2;
offset >>= 4;
- Binary.CopyOverlapped (output, dst-offset, dst, count);
+ Binary.CopyOverlapped (output, dst-offset-1, dst, count);
dst += count;
}
}
diff --git a/ArcFormats/YuRis/ArcYPF.cs b/ArcFormats/YuRis/ArcYPF.cs
index 36336593..08a2f11e 100644
--- a/ArcFormats/YuRis/ArcYPF.cs
+++ b/ArcFormats/YuRis/ArcYPF.cs
@@ -105,7 +105,7 @@ namespace GameRes.Formats.YuRis
public YpfOpener ()
{
- Signatures = new uint[] { 0x00465059, 0 };
+ Signatures = new uint[] { 0x00465059, 0x00905A4D, 0 };
}
static public Dictionary KnownSchemes { get { return DefaultScheme.KnownSchemes; } }
diff --git a/ArcFormats/Zyx/ImageSPL.cs b/ArcFormats/Zyx/ImageSPL.cs
index bd26100b..3d28aa0a 100644
--- a/ArcFormats/Zyx/ImageSPL.cs
+++ b/ArcFormats/Zyx/ImageSPL.cs
@@ -52,30 +52,37 @@ namespace GameRes.Formats.Zyx
public override ImageMetaData ReadMetaData (IBinaryStream file)
{
int count = file.ReadInt16();
- if (count <= 0)
+ if (count < 0 || count > 0x100)
return null;
- var tiles = new Tile[count];
- for (int i = 0; i < count; ++i)
+ Tile[] tiles = null;
+ if (count > 0)
{
- var tile = new Tile();
- tile.Left = file.ReadInt16();
- tile.Top = file.ReadInt16();
- if (tile.Left < 0 || tile.Top < 0)
- return null;
- tile.Right = file.ReadInt16();
- tile.Bottom = file.ReadInt16();
- if (tile.Right <= tile.Left || tile.Bottom <= tile.Top)
- return null;
- tiles[i] = tile;
+ tiles = new Tile[count];
+ for (int i = 0; i < count; ++i)
+ {
+ var tile = new Tile();
+ tile.Left = file.ReadInt16();
+ tile.Top = file.ReadInt16();
+ if (tile.Left < 0 || tile.Top < 0)
+ return null;
+ tile.Right = file.ReadInt16();
+ tile.Bottom = file.ReadInt16();
+ if (tile.Right <= tile.Left || tile.Bottom <= tile.Top)
+ return null;
+ tiles[i] = tile;
+ }
}
int width = file.ReadInt16();
int height = file.ReadInt16();
if (width <= 0 || height <= 0)
return null;
- foreach (var tile in tiles)
+ if (tiles != null)
{
- if (tile.Right > width || tile.Bottom > height)
- return null;
+ foreach (var tile in tiles)
+ {
+ if (tile.Right > width || tile.Bottom > height)
+ return null;
+ }
}
return new SplMetaData
{