From beb7a394a26a1ffe428eaa5828d044c103558fa1 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 16:34:48 +1300 Subject: [PATCH] Move ShpD2 sprite loading into Mods.Common. --- OpenRA.Game/Graphics/SpriteSource.cs | 45 +---------- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../SpriteLoaders/ShpD2Loader.cs | 75 ++++++++++++++++--- 4 files changed, 67 insertions(+), 55 deletions(-) rename OpenRA.Game/FileFormats/ShpD2Reader.cs => OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs (63%) diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index 69e1ec67a1..ee5ae9249a 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,52 +15,11 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpD2 } + public enum SpriteType { Unknown } public static class SpriteSource { - 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; - } - public static SpriteType DetectSpriteType(Stream s) { - if (IsShpD2(s)) - return SpriteType.ShpD2; - return SpriteType.Unknown; } @@ -69,8 +28,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - 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.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 15fceb5035..d44495ed83 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -277,7 +277,6 @@ - diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 4d2c16715a..68c487a53d 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -117,6 +117,7 @@ + diff --git a/OpenRA.Game/FileFormats/ShpD2Reader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs similarity index 63% rename from OpenRA.Game/FileFormats/ShpD2Reader.cs rename to OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs index eb90db60ad..c5567cefec 100644 --- a/OpenRA.Game/FileFormats/ShpD2Reader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs @@ -9,13 +9,16 @@ #endregion using System; +using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; +using OpenRA.FileFormats; using OpenRA.Graphics; -namespace OpenRA.FileFormats +namespace OpenRA.Mods.Common.SpriteLoaders { - public class ShpD2Reader : ISpriteSource + public class ShpD2Loader : ISpriteLoader { [Flags] enum FormatFlags : int { @@ -24,7 +27,7 @@ namespace OpenRA.FileFormats VariableLengthTable = 4 } - class Frame : ISpriteFrame + class ShpD2Frame : ISpriteFrame { public Size Size { get; private set; } public Size FrameSize { get { return Size; } } @@ -32,7 +35,7 @@ namespace OpenRA.FileFormats public byte[] Data { get; set; } public bool DisableExportPadding { get { return false; } } - public Frame(Stream s) + public ShpD2Frame(Stream s) { var flags = (FormatFlags)s.ReadUInt16(); s.Position += 1; @@ -84,10 +87,48 @@ namespace OpenRA.FileFormats } } - public IReadOnlyList Frames { get; private set; } - - public ShpD2Reader(Stream s) + 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; + } + + ShpD2Frame[] ParseFrames(Stream s) + { + var start = s.Position; + var imageCount = s.ReadUInt16(); // Last offset is pointer to end of file. @@ -101,13 +142,27 @@ namespace OpenRA.FileFormats for (var i = 0; i < imageCount + 1; i++) offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2; - var frames = new Frame[imageCount]; - Frames = frames.AsReadOnly(); + var frames = new ShpD2Frame[imageCount]; for (var i = 0; i < frames.Length; i++) { s.Position = offsets[i]; - frames[i] = new Frame(s); + frames[i] = new ShpD2Frame(s); } + + s.Position = start; + return frames; + } + + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + { + if (!IsShpD2(s)) + { + frames = null; + return false; + } + + frames = ParseFrames(s); + return true; } } }