diff --git a/OpenRA.FileFormats/Graphics/Dune2ShpReader.cs b/OpenRA.FileFormats/Graphics/Dune2ShpReader.cs deleted file mode 100644 index 3951a50458..0000000000 --- a/OpenRA.FileFormats/Graphics/Dune2ShpReader.cs +++ /dev/null @@ -1,144 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.IO; - -namespace OpenRA.FileFormats -{ - public enum Dune2ImageFlags : int - { - F80_F2 = 0, - F2 = 2, - L16_F80_F2_1 = 1, - L16_F80_F2_2 = 3, - Ln_F80_F2 = 5 - } - - public class Dune2ImageHeader - { - public readonly Dune2ImageFlags Flags; - public readonly int Width; - public readonly int Height; - public readonly int Slices; - public readonly int FileSize; - public readonly int DataSize; - - public readonly byte[] LookupTable; - public byte[] Image; - - public Dune2ImageHeader(Stream s) - { - Flags = (Dune2ImageFlags)s.ReadUInt16(); - Slices = s.ReadUInt8(); - Width = s.ReadUInt16(); - Height = s.ReadUInt8(); - FileSize = s.ReadUInt16(); - DataSize = s.ReadUInt16(); - - if (Flags == Dune2ImageFlags.L16_F80_F2_1 || - Flags == Dune2ImageFlags.L16_F80_F2_2 || - Flags == Dune2ImageFlags.Ln_F80_F2) - { - int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16; - LookupTable = new byte[n]; - for (int i = 0; i < n; i++) - LookupTable[i] = s.ReadUInt8(); - } - else - { - LookupTable = new byte[256]; - for (int i = 0; i < 256; i++) - LookupTable[i] = (byte)i; - LookupTable[1] = 0x7f; - LookupTable[2] = 0x7e; - LookupTable[3] = 0x7d; - LookupTable[4] = 0x7c; - } - } - - public Size Size - { - get { return new Size(Width, Height); } - } - } - - public class Dune2ShpReader : IEnumerable - { - public readonly int ImageCount; - - List headers = new List(); - - public Dune2ShpReader(Stream s) - { - ImageCount = s.ReadUInt16(); - - //Last offset is pointer to end of file. - uint[] offsets = new uint[ImageCount + 1]; - - uint temp = s.ReadUInt32(); - - //If fourth byte in file is non-zero, the offsets are two bytes each. - bool twoByteOffsets = (temp & 0xFF0000) > 0; - if (twoByteOffsets) - { - offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes - offsets[1] = (temp & 0xFFFF) + 2; - } - else - offsets[0] = temp + 2; - - for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++) - offsets[i] = (twoByteOffsets ? s.ReadUInt16() : s.ReadUInt32()) + 2; - - for (int i = 0; i < ImageCount; i++) - { - s.Seek(offsets[i], SeekOrigin.Begin); - Dune2ImageHeader header = new Dune2ImageHeader(s); - byte[] imgData = s.ReadBytes(header.FileSize); - header.Image = new byte[header.Height * header.Width]; - - //Decode image data - if (header.Flags != Dune2ImageFlags.F2) - { - byte[] tempData = new byte[header.DataSize]; - Format80.DecodeInto(imgData, tempData); - Format2.DecodeInto(tempData, header.Image); - } - else - Format2.DecodeInto(imgData, header.Image); - - //Lookup values in lookup table - if (header.LookupTable != null) - for (int j = 0; j < header.Image.Length; j++) - header.Image[j] = header.LookupTable[header.Image[j]]; - - headers.Add(header); - } - } - - public Dune2ImageHeader this[int index] - { - get { return headers[index]; } - } - - public IEnumerator GetEnumerator() - { - return headers.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/OpenRA.FileFormats/Graphics/ShpD2Reader.cs b/OpenRA.FileFormats/Graphics/ShpD2Reader.cs new file mode 100644 index 0000000000..622d7d8d47 --- /dev/null +++ b/OpenRA.FileFormats/Graphics/ShpD2Reader.cs @@ -0,0 +1,114 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; + +namespace OpenRA.FileFormats +{ + enum Dune2ImageFlags : int + { + F80_F2 = 0, + F2 = 2, + L16_F80_F2_1 = 1, + L16_F80_F2_2 = 3, + Ln_F80_F2 = 5 + } + + class Frame : ISpriteFrame + { + public Size Size { get; private set; } + public Size FrameSize { get { return Size; } } + public float2 Offset { get { return float2.Zero; } } + public byte[] Data { get; set; } + + public Frame(Stream s) + { + var flags = (Dune2ImageFlags)s.ReadUInt16(); + s.Position += 1; + var width = s.ReadUInt16(); + var height = s.ReadUInt8(); + Size = new Size(width, height); + + var frameSize = s.ReadUInt16(); + var dataSize = s.ReadUInt16(); + + byte[] table; + if (flags == Dune2ImageFlags.L16_F80_F2_1 || + flags == Dune2ImageFlags.L16_F80_F2_2 || + flags == Dune2ImageFlags.Ln_F80_F2) + { + var n = flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16; + table = new byte[n]; + for (var i = 0; i < n; i++) + table[i] = s.ReadUInt8(); + } + else + { + table = new byte[256]; + for (var i = 0; i < 256; i++) + table[i] = (byte)i; + table[1] = 0x7f; + table[2] = 0x7e; + table[3] = 0x7d; + table[4] = 0x7c; + } + + // Subtract header size + var imgData = s.ReadBytes(frameSize - 10); + Data = new byte[width * height]; + + // Decode image data + if (flags != Dune2ImageFlags.F2) + { + var tempData = new byte[dataSize]; + Format80.DecodeInto(imgData, tempData); + Format2.DecodeInto(tempData, Data); + } + else + Format2.DecodeInto(imgData, Data); + + // Lookup values in lookup table + for (var j = 0; j < Data.Length; j++) + Data[j] = table[Data[j]]; + } + } + + public class ShpD2Reader : ISpriteSource + { + List headers = new List(); + public IEnumerable Frames { get { return headers.Cast(); } } + + public ShpD2Reader(Stream s) + { + var imageCount = s.ReadUInt16(); + + // Last offset is pointer to end of file. + var offsets = new uint[imageCount + 1]; + var temp = s.ReadUInt32(); + + // If fourth byte in file is non-zero, the offsets are two bytes each. + var twoByteOffset = (temp & 0xFF0000) > 0; + s.Position = 2; + + for (var i = 0; i < imageCount + 1; i++) + offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2; + + for (var i = 0; i < imageCount; i++) + { + s.Position = offsets[i]; + headers.Add(new Frame(s)); + } + } + } +} diff --git a/OpenRA.FileFormats/Graphics/SpriteSource.cs b/OpenRA.FileFormats/Graphics/SpriteSource.cs index a3edbec43f..b1af05257d 100644 --- a/OpenRA.FileFormats/Graphics/SpriteSource.cs +++ b/OpenRA.FileFormats/Graphics/SpriteSource.cs @@ -28,7 +28,7 @@ namespace OpenRA.FileFormats IEnumerable Frames { get; } } - public enum SpriteType { Unknown, ShpTD, ShpTS, TmpTD, TmpRA, R8 } + public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, R8 } public static class SpriteSource { static bool IsTmpRA(Stream s) @@ -129,6 +129,44 @@ namespace OpenRA.FileFormats return b == 0x20 || b == 0x40 || b == 0x80; } + static bool IsShpD2(Stream s) + { + var start = s.Position; + + // First word is the image count + var imageCount = s.ReadUInt16(); + if (imageCount == 0) + { + s.Position = start; + return false; + } + + // Test for two vs four byte offset + var testOffset = s.ReadUInt32(); + var offsetSize = (testOffset & 0xFF0000) > 0 ? 2 : 4; + + // Last offset should point to the end of file + var finalOffset = start + 2 + offsetSize * imageCount; + if (finalOffset > s.Length) + { + s.Position = start; + return false; + } + + s.Position = finalOffset; + var eof = offsetSize == 2 ? s.ReadUInt16() : s.ReadUInt32(); + if (eof + 2 != s.Length) + { + s.Position = start; + return false; + } + + // Check the format flag on the first frame + var b = s.ReadUInt16(); + s.Position = start; + return b == 5 || b <= 3; + } + static bool IsR8(Stream s) { var start = s.Position; @@ -165,6 +203,9 @@ namespace OpenRA.FileFormats if (IsTmpTD(s)) return SpriteType.TmpTD; + if (IsShpD2(s)) + return SpriteType.ShpD2; + return SpriteType.Unknown; } @@ -183,6 +224,8 @@ namespace OpenRA.FileFormats return new TmpRAReader(s); case SpriteType.TmpTD: return new TmpTDReader(s); + case SpriteType.ShpD2: + return new ShpD2Reader(s); case SpriteType.Unknown: default: throw new InvalidDataException(filename + " is not a valid sprite file"); diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 938ad857b8..ada09fc867 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -90,7 +90,6 @@ - @@ -154,6 +153,7 @@ + diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index 0a2fc742a2..ba60a2e740 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -136,25 +136,6 @@ namespace OpenRA.Utility Console.WriteLine("Saved {0}-[0..{1}].png", prefix, count - 1); } - public static void ConvertFormat2ToFormat80(string[] args) - { - var src = args[1]; - var dest = args[2]; - - Dune2ShpReader srcImage = null; - using (var s = File.OpenRead(src)) - srcImage = new Dune2ShpReader(s); - - var size = srcImage.First().Size; - - if (!srcImage.All(im => im.Size == size)) - throw new InvalidOperationException("All the frames must be the same size to convert from Dune2 to RA"); - - using (var destStream = File.Create(dest)) - ShpReader.Write(destStream, size.Width, size.Height, - srcImage.Select(im => im.Image)); - } - public static void ExtractFiles(string[] args) { var mod = args[1]; diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index 37ef9407d5..aea3b5b1c6 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -23,7 +23,6 @@ namespace OpenRA.Utility { "--settings-value", Command.Settings }, { "--shp", Command.ConvertPngToShp }, { "--png", Command.ConvertShpToPng }, - { "--fromd2", Command.ConvertFormat2ToFormat80 }, { "--extract", Command.ExtractFiles }, { "--remap", Command.RemapShp }, { "--transpose", Command.TransposeShp }, @@ -58,7 +57,6 @@ namespace OpenRA.Utility Console.WriteLine(" --settings-value KEY Get value of KEY from settings.yaml"); Console.WriteLine(" --shp PNGFILE [PNGFILE ...] Combine a list of PNG images into a SHP"); Console.WriteLine(" --png SPRITEFILE PALETTE [--noshadow] [--nopadding] Convert a shp/tmp/R8 to a series of PNGs, optionally removing shadow"); - Console.WriteLine(" --fromd2 DUNE2SHP C&CSHP Convert a Dune II SHP (C&C mouse cursor) to C&C SHP format."); Console.WriteLine(" --extract MOD[,MOD]* FILES [--userdir] Extract files from mod packages to the current (or user) directory"); Console.WriteLine(" --remap SRCMOD:PAL DESTMOD:PAL SRCSHP DESTSHP Remap SHPs to another palette"); Console.WriteLine(" --transpose SRCSHP DESTSHP START N M [START N M ...] Transpose the N*M block of frames starting at START.");