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

View File

@@ -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++];
}
}
}

View File

@@ -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++)

View File

@@ -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");

View File

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