diff --git a/OpenRA.FileFormats/FileFormats/Format2.cs b/OpenRA.FileFormats/FileFormats/Format2.cs index a043755c18..b584d3b9a3 100644 --- a/OpenRA.FileFormats/FileFormats/Format2.cs +++ b/OpenRA.FileFormats/FileFormats/Format2.cs @@ -12,25 +12,22 @@ namespace OpenRA.FileFormats { public static class Format2 { - public static int DecodeInto(byte[] src, byte[] dest) + public static void DecodeInto(byte[] src, byte[] dest, int destIndex) { - FastByteReader r = new FastByteReader(src); + var r = new FastByteReader(src); - int i = 0; while (!r.Done()) { - byte cmd = r.ReadByte(); + var cmd = r.ReadByte(); if (cmd == 0) { - byte count = r.ReadByte(); + var count = r.ReadByte(); while (count-- > 0) - dest[i++] = 0; + dest[destIndex++] = 0; } else - dest[i++] = cmd; + dest[destIndex++] = cmd; } - - return i; } } } diff --git a/OpenRA.FileFormats/FileFormats/Format80.cs b/OpenRA.FileFormats/FileFormats/Format80.cs index ad2b97b6d8..4780ec8f69 100644 --- a/OpenRA.FileFormats/FileFormats/Format80.cs +++ b/OpenRA.FileFormats/FileFormats/Format80.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -27,7 +27,7 @@ namespace OpenRA.FileFormats public byte ReadByte() { return src[offset++]; } public int ReadWord() { - int x = ReadByte(); + var x = ReadByte(); return x | (ReadByte() << 8); } @@ -42,84 +42,84 @@ namespace OpenRA.FileFormats public static class Format80 { - static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count ) + static void ReplicatePrevious(byte[] dest, int destIndex, int srcIndex, int count) { - if( srcIndex > destIndex ) + if (srcIndex > destIndex) throw new NotImplementedException("srcIndex > destIndex {0} {1}".F(srcIndex, destIndex)); - if( destIndex - srcIndex == 1 ) + if (destIndex - srcIndex == 1) { - for( int i = 0 ; i < count ; i++ ) - dest[ destIndex + i ] = dest[ destIndex - 1 ]; + for (var i = 0; i < count; i++) + dest[destIndex + i] = dest[destIndex - 1]; } else { - for( int i = 0 ; i < count ; i++ ) - dest[ destIndex + i ] = dest[ srcIndex + i ]; + for (var i = 0; i < count; i++) + dest[destIndex + i] = dest[srcIndex + i]; } } - public static int DecodeInto( byte[] src, byte[] dest ) + public static int DecodeInto(byte[] src, byte[] dest) { var ctx = new FastByteReader(src); - int destIndex = 0; + var destIndex = 0; - while( true ) + while (true) { - byte i = ctx.ReadByte(); - if( ( i & 0x80 ) == 0 ) + var i = ctx.ReadByte(); + if ((i & 0x80) == 0) { // case 2 - byte secondByte = ctx.ReadByte(); - int count = ( ( i & 0x70 ) >> 4 ) + 3; - int rpos = ( ( i & 0xf ) << 8 ) + secondByte; + var secondByte = ctx.ReadByte(); + var count = ((i & 0x70) >> 4) + 3; + var rpos = ((i & 0xf) << 8) + secondByte; - ReplicatePrevious( dest, destIndex, destIndex - rpos, count ); + ReplicatePrevious(dest, destIndex, destIndex - rpos, count); destIndex += count; } - else if( ( i & 0x40 ) == 0 ) + else if ((i & 0x40) == 0) { // case 1 - int count = i & 0x3F; - if( count == 0 ) + var count = i & 0x3F; + if (count == 0) return destIndex; - ctx.CopyTo( dest, destIndex, count ); + ctx.CopyTo(dest, destIndex, count); destIndex += count; } else { - int count3 = i & 0x3F; - if( count3 == 0x3E ) + var count3 = i & 0x3F; + if (count3 == 0x3E) { // case 4 - int count = ctx.ReadWord(); - byte color = ctx.ReadByte(); + var count = ctx.ReadWord(); + var color = ctx.ReadByte(); - for( int end = destIndex + count ; destIndex < end ; destIndex++ ) - dest[ destIndex ] = color; + for (var end = destIndex + count; destIndex < end; destIndex++) + dest[destIndex] = color; } - else if( count3 == 0x3F ) + else if (count3 == 0x3F) { // case 5 - int count = ctx.ReadWord(); - int srcIndex = ctx.ReadWord(); - if( srcIndex >= destIndex ) + var count = ctx.ReadWord(); + var srcIndex = ctx.ReadWord(); + if (srcIndex >= destIndex) throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex)); - for( int end = destIndex + count ; destIndex < end ; destIndex++ ) - dest[ destIndex ] = dest[ srcIndex++ ]; + for (var end = destIndex + count; destIndex < end; destIndex++) + dest[destIndex] = dest[srcIndex++]; } else { // case 3 - int count = count3 + 3; - int srcIndex = ctx.ReadWord(); - if( srcIndex >= destIndex ) + var count = count3 + 3; + var srcIndex = ctx.ReadWord(); + if (srcIndex >= destIndex) throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex)); - for( int end = destIndex + count ; destIndex < end ; destIndex++ ) - dest[ destIndex ] = dest[ srcIndex++ ]; + for (var end = destIndex + count; destIndex < end; destIndex++) + dest[destIndex] = dest[srcIndex++]; } } } diff --git a/OpenRA.FileFormats/Graphics/ShpD2Reader.cs b/OpenRA.FileFormats/Graphics/ShpD2Reader.cs index aa21efc521..eebf97f4eb 100644 --- a/OpenRA.FileFormats/Graphics/ShpD2Reader.cs +++ b/OpenRA.FileFormats/Graphics/ShpD2Reader.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections; using System.Collections.Generic; using System.Drawing; @@ -16,13 +17,11 @@ using System.Linq; namespace OpenRA.FileFormats { - enum Dune2ImageFlags : int + [Flags] enum FormatFlags : int { - F80_F2 = 0, - F2 = 2, - L16_F80_F2_1 = 1, - L16_F80_F2_2 = 3, - Ln_F80_F2 = 5 + PaletteTable = 1, + SkipFormat80 = 2, + VariableLengthTable = 4 } class Frame : ISpriteFrame @@ -34,24 +33,25 @@ namespace OpenRA.FileFormats public Frame(Stream s) { - var flags = (Dune2ImageFlags)s.ReadUInt16(); + var flags = (FormatFlags)s.ReadUInt16(); s.Position += 1; var width = s.ReadUInt16(); var height = s.ReadUInt8(); Size = new Size(width, height); - var frameSize = s.ReadUInt16(); + // Subtract header size + var dataLeft = s.ReadUInt16() - 10; var dataSize = s.ReadUInt16(); byte[] table; - if (flags == Dune2ImageFlags.L16_F80_F2_1 || - flags == Dune2ImageFlags.L16_F80_F2_2 || - flags == Dune2ImageFlags.Ln_F80_F2) + if ((flags & FormatFlags.PaletteTable) != 0) { - var n = flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16; + var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16; table = new byte[n]; for (var i = 0; i < n; i++) table[i] = s.ReadUInt8(); + + dataLeft -= n; } else { @@ -64,19 +64,18 @@ namespace OpenRA.FileFormats 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 compressed = s.ReadBytes(dataLeft); + if ((flags & FormatFlags.SkipFormat80) == 0) { - var tempData = new byte[dataSize]; - Format80.DecodeInto(imgData, tempData); - Format2.DecodeInto(tempData, Data); + var temp = new byte[dataSize]; + Format80.DecodeInto(compressed, temp); + compressed = temp; } - else - Format2.DecodeInto(imgData, Data); + + Format2.DecodeInto(compressed, Data, 0); // Lookup values in lookup table for (var j = 0; j < Data.Length; j++) diff --git a/OpenRA.FileFormats/Graphics/ShpReader.cs b/OpenRA.FileFormats/Graphics/ShpReader.cs index b211b94751..a6e05e3546 100644 --- a/OpenRA.FileFormats/Graphics/ShpReader.cs +++ b/OpenRA.FileFormats/Graphics/ShpReader.cs @@ -108,6 +108,10 @@ namespace OpenRA.FileFormats void Decompress(Stream stream, ImageHeader h) { + // No extra work is required for empty frames + if (h.Size.Width == 0 || h.Size.Height == 0) + return; + if (recurseDepth > imageCount) throw new InvalidDataException("Format20/40 headers contain infinite loop"); diff --git a/OpenRA.FileFormats/Graphics/ShpTSReader.cs b/OpenRA.FileFormats/Graphics/ShpTSReader.cs index 90c45aa85a..5c2f3c15db 100644 --- a/OpenRA.FileFormats/Graphics/ShpTSReader.cs +++ b/OpenRA.FileFormats/Graphics/ShpTSReader.cs @@ -89,21 +89,8 @@ namespace OpenRA.FileFormats for (var j = 0; j < f.Size.Height; j++) { - var k = j * f.Size.Width; var length = stream.ReadUInt16() - 2; - while (length > 0) - { - var b = stream.ReadUInt8(); - length--; - - if (b == 0) - { - k += stream.ReadUInt8(); - length--; - } - else - f.Data[k++] = b; - } + Format2.DecodeInto(stream.ReadBytes(length), f.Data, j * f.Size.Width); } } }