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;
}
}
}