Merge pull request #4208 from pchote/sprite-fix

SpriteReader fixes
This commit is contained in:
Matthias Mailänder
2013-12-02 12:33:05 -08:00
5 changed files with 69 additions and 82 deletions

View File

@@ -12,25 +12,22 @@ namespace OpenRA.FileFormats
{ {
public static class Format2 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()) while (!r.Done())
{ {
byte cmd = r.ReadByte(); var cmd = r.ReadByte();
if (cmd == 0) if (cmd == 0)
{ {
byte count = r.ReadByte(); var count = r.ReadByte();
while (count-- > 0) while (count-- > 0)
dest[i++] = 0; dest[destIndex++] = 0;
} }
else else
dest[i++] = cmd; dest[destIndex++] = cmd;
} }
return i;
} }
} }
} }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information #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 * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
@@ -27,7 +27,7 @@ namespace OpenRA.FileFormats
public byte ReadByte() { return src[offset++]; } public byte ReadByte() { return src[offset++]; }
public int ReadWord() public int ReadWord()
{ {
int x = ReadByte(); var x = ReadByte();
return x | (ReadByte() << 8); return x | (ReadByte() << 8);
} }
@@ -42,84 +42,84 @@ namespace OpenRA.FileFormats
public static class Format80 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)); 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++ ) for (var i = 0; i < count; i++)
dest[ destIndex + i ] = dest[ destIndex - 1 ]; dest[destIndex + i] = dest[destIndex - 1];
} }
else else
{ {
for( int i = 0 ; i < count ; i++ ) for (var i = 0; i < count; i++)
dest[ destIndex + i ] = dest[ srcIndex + 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); var ctx = new FastByteReader(src);
int destIndex = 0; var destIndex = 0;
while( true ) while (true)
{ {
byte i = ctx.ReadByte(); var i = ctx.ReadByte();
if( ( i & 0x80 ) == 0 ) if ((i & 0x80) == 0)
{ {
// case 2 // case 2
byte secondByte = ctx.ReadByte(); var secondByte = ctx.ReadByte();
int count = ( ( i & 0x70 ) >> 4 ) + 3; var count = ((i & 0x70) >> 4) + 3;
int rpos = ( ( i & 0xf ) << 8 ) + secondByte; var rpos = ((i & 0xf) << 8) + secondByte;
ReplicatePrevious( dest, destIndex, destIndex - rpos, count ); ReplicatePrevious(dest, destIndex, destIndex - rpos, count);
destIndex += count; destIndex += count;
} }
else if( ( i & 0x40 ) == 0 ) else if ((i & 0x40) == 0)
{ {
// case 1 // case 1
int count = i & 0x3F; var count = i & 0x3F;
if( count == 0 ) if (count == 0)
return destIndex; return destIndex;
ctx.CopyTo( dest, destIndex, count ); ctx.CopyTo(dest, destIndex, count);
destIndex += count; destIndex += count;
} }
else else
{ {
int count3 = i & 0x3F; var count3 = i & 0x3F;
if( count3 == 0x3E ) if (count3 == 0x3E)
{ {
// case 4 // case 4
int count = ctx.ReadWord(); var count = ctx.ReadWord();
byte color = ctx.ReadByte(); var color = ctx.ReadByte();
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for (var end = destIndex + count; destIndex < end; destIndex++)
dest[ destIndex ] = color; dest[destIndex] = color;
} }
else if( count3 == 0x3F ) else if (count3 == 0x3F)
{ {
// case 5 // case 5
int count = ctx.ReadWord(); var count = ctx.ReadWord();
int srcIndex = ctx.ReadWord(); var srcIndex = ctx.ReadWord();
if( srcIndex >= destIndex ) if (srcIndex >= destIndex)
throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex)); throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex));
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for (var end = destIndex + count; destIndex < end; destIndex++)
dest[ destIndex ] = dest[ srcIndex++ ]; dest[destIndex] = dest[srcIndex++];
} }
else else
{ {
// case 3 // case 3
int count = count3 + 3; var count = count3 + 3;
int srcIndex = ctx.ReadWord(); var srcIndex = ctx.ReadWord();
if( srcIndex >= destIndex ) if (srcIndex >= destIndex)
throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex)); throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex));
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for (var end = destIndex + count; destIndex < end; destIndex++)
dest[ destIndex ] = dest[ srcIndex++ ]; dest[destIndex] = dest[srcIndex++];
} }
} }
} }

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
@@ -16,13 +17,11 @@ using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
enum Dune2ImageFlags : int [Flags] enum FormatFlags : int
{ {
F80_F2 = 0, PaletteTable = 1,
F2 = 2, SkipFormat80 = 2,
L16_F80_F2_1 = 1, VariableLengthTable = 4
L16_F80_F2_2 = 3,
Ln_F80_F2 = 5
} }
class Frame : ISpriteFrame class Frame : ISpriteFrame
@@ -34,24 +33,25 @@ namespace OpenRA.FileFormats
public Frame(Stream s) public Frame(Stream s)
{ {
var flags = (Dune2ImageFlags)s.ReadUInt16(); var flags = (FormatFlags)s.ReadUInt16();
s.Position += 1; s.Position += 1;
var width = s.ReadUInt16(); var width = s.ReadUInt16();
var height = s.ReadUInt8(); var height = s.ReadUInt8();
Size = new Size(width, height); Size = new Size(width, height);
var frameSize = s.ReadUInt16(); // Subtract header size
var dataLeft = s.ReadUInt16() - 10;
var dataSize = s.ReadUInt16(); var dataSize = s.ReadUInt16();
byte[] table; byte[] table;
if (flags == Dune2ImageFlags.L16_F80_F2_1 || if ((flags & FormatFlags.PaletteTable) != 0)
flags == Dune2ImageFlags.L16_F80_F2_2 ||
flags == Dune2ImageFlags.Ln_F80_F2)
{ {
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]; table = new byte[n];
for (var i = 0; i < n; i++) for (var i = 0; i < n; i++)
table[i] = s.ReadUInt8(); table[i] = s.ReadUInt8();
dataLeft -= n;
} }
else else
{ {
@@ -64,19 +64,18 @@ namespace OpenRA.FileFormats
table[4] = 0x7c; table[4] = 0x7c;
} }
// Subtract header size
var imgData = s.ReadBytes(frameSize - 10);
Data = new byte[width * height]; Data = new byte[width * height];
// Decode image data // Decode image data
if (flags != Dune2ImageFlags.F2) var compressed = s.ReadBytes(dataLeft);
if ((flags & FormatFlags.SkipFormat80) == 0)
{ {
var tempData = new byte[dataSize]; var temp = new byte[dataSize];
Format80.DecodeInto(imgData, tempData); Format80.DecodeInto(compressed, temp);
Format2.DecodeInto(tempData, Data); compressed = temp;
} }
else
Format2.DecodeInto(imgData, Data); Format2.DecodeInto(compressed, Data, 0);
// Lookup values in lookup table // Lookup values in lookup table
for (var j = 0; j < Data.Length; j++) for (var j = 0; j < Data.Length; j++)

View File

@@ -108,6 +108,10 @@ namespace OpenRA.FileFormats
void Decompress(Stream stream, ImageHeader h) 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) if (recurseDepth > imageCount)
throw new InvalidDataException("Format20/40 headers contain infinite loop"); throw new InvalidDataException("Format20/40 headers contain infinite loop");

View File

@@ -89,21 +89,8 @@ namespace OpenRA.FileFormats
for (var j = 0; j < f.Size.Height; j++) for (var j = 0; j < f.Size.Height; j++)
{ {
var k = j * f.Size.Width;
var length = stream.ReadUInt16() - 2; var length = stream.ReadUInt16() - 2;
while (length > 0) Format2.DecodeInto(stream.ReadBytes(length), f.Data, j * f.Size.Width);
{
var b = stream.ReadUInt8();
length--;
if (b == 0)
{
k += stream.ReadUInt8();
length--;
}
else
f.Data[k++] = b;
}
} }
} }
} }