mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-27 05:35:57 -04:00
Finished data load logic for DCC files.
This commit is contained in:
parent
20bacbbb14
commit
2f1f15c7b5
@ -47,13 +47,21 @@ namespace OpenDiablo2.Common.Models
|
|||||||
|
|
||||||
private int MakeSigned(int value, int bits)
|
private int MakeSigned(int value, int bits)
|
||||||
{
|
{
|
||||||
var msbSet = ((value & (1 << (bits - 1))) != 0);
|
if (bits == 1)
|
||||||
if (msbSet)
|
return -value;
|
||||||
|
|
||||||
|
if ((value & (1 << (bits - 1))) == 0)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
var result = UInt32.MaxValue;
|
||||||
|
for (byte i = 0; i < bits; i++)
|
||||||
{
|
{
|
||||||
value = ~value + 1;
|
if (((value >> i) & 1) == 0)
|
||||||
|
result -= (UInt32)(1 << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
var newResult = (int)result;
|
||||||
|
return newResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ namespace OpenDiablo2.Common.Models
|
|||||||
{
|
{
|
||||||
public sealed class MPQDCC
|
public sealed class MPQDCC
|
||||||
{
|
{
|
||||||
public struct PixelBufferEntry
|
public class PixelBufferEntry
|
||||||
{
|
{
|
||||||
public byte[] Value;
|
public byte[] Value;
|
||||||
public int Frame;
|
public int Frame;
|
||||||
@ -62,23 +62,25 @@ namespace OpenDiablo2.Common.Models
|
|||||||
public void MakeCells(MPQDCCDirection direction)
|
public void MakeCells(MPQDCCDirection direction)
|
||||||
{
|
{
|
||||||
var w = 4 - ((Box.Left - direction.Box.Left) % 4); // Width of the first column (in pixels)
|
var w = 4 - ((Box.Left - direction.Box.Left) % 4); // Width of the first column (in pixels)
|
||||||
if ((Box.Width - w) <= 1)
|
if ((Width - w) <= 1)
|
||||||
HorizontalCellCount = 1;
|
HorizontalCellCount = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HorizontalCellCount = 2 + ((Box.Width - w - 1) / 4);
|
var tmp = Width - w - 1;
|
||||||
if (((Box.Width - w - 1) % 4) == 0)
|
HorizontalCellCount = 2 + (tmp / 4);
|
||||||
|
if ((tmp % 4) == 0)
|
||||||
HorizontalCellCount--;
|
HorizontalCellCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var h = 4 - ((Box.Top - direction.Box.Top) % 4); // Height of the first column (in pixels)
|
var h = 4 - ((Box.Top - direction.Box.Top) % 4); // Height of the first column (in pixels)
|
||||||
if ((Box.Height - h) <= 1)
|
if ((Height - h) <= 1)
|
||||||
VerticalCellCount = 1;
|
VerticalCellCount = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VerticalCellCount = 2 + ((Box.Height - h - 1) / 4);
|
var tmp = Height - h - 1;
|
||||||
if (((Box.Height - h - 1) % 4) == 0)
|
VerticalCellCount = 2 + (tmp / 4);
|
||||||
|
if ((tmp % 4) == 0)
|
||||||
VerticalCellCount--;
|
VerticalCellCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,24 +89,24 @@ namespace OpenDiablo2.Common.Models
|
|||||||
// Calculate the cell widths and heights
|
// Calculate the cell widths and heights
|
||||||
var cellWidths = new int[HorizontalCellCount];
|
var cellWidths = new int[HorizontalCellCount];
|
||||||
if (HorizontalCellCount == 1)
|
if (HorizontalCellCount == 1)
|
||||||
cellWidths[0] = Box.Width;
|
cellWidths[0] = Width;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cellWidths[0] = w;
|
cellWidths[0] = w;
|
||||||
for (var i = 1; i < (HorizontalCellCount - 1); i++)
|
for (var i = 1; i < (HorizontalCellCount - 1); i++)
|
||||||
cellWidths[i] = 4;
|
cellWidths[i] = 4;
|
||||||
cellWidths[HorizontalCellCount - 1] = Box.Width - w - (4 * (HorizontalCellCount - 2));
|
cellWidths[HorizontalCellCount - 1] = Width - w - (4 * (HorizontalCellCount - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
var cellHeights = new int[VerticalCellCount];
|
var cellHeights = new int[VerticalCellCount];
|
||||||
if (VerticalCellCount == 1)
|
if (VerticalCellCount == 1)
|
||||||
cellHeights[0] = Box.Height;
|
cellHeights[0] = Height;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cellHeights[0] = h;
|
cellHeights[0] = h;
|
||||||
for (var i = 1; i < (VerticalCellCount - 1); i++)
|
for (var i = 1; i < (VerticalCellCount - 1); i++)
|
||||||
cellHeights[i] = 4;
|
cellHeights[i] = 4;
|
||||||
cellHeights[VerticalCellCount - 1] = Box.Height - h - (4 * (VerticalCellCount - 2));
|
cellHeights[VerticalCellCount - 1] = Height - h - (4 * (VerticalCellCount - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
Cells = new Cell[HorizontalCellCount * VerticalCellCount];
|
Cells = new Cell[HorizontalCellCount * VerticalCellCount];
|
||||||
@ -129,6 +131,7 @@ namespace OpenDiablo2.Common.Models
|
|||||||
}
|
}
|
||||||
public sealed class MPQDCCDirection
|
public sealed class MPQDCCDirection
|
||||||
{
|
{
|
||||||
|
const int DCC_MAX_PB_ENTRY = 85000; // But why is this the magic number?
|
||||||
public int OutSizeCoded { get; private set; }
|
public int OutSizeCoded { get; private set; }
|
||||||
public int CompressionFlags { get; private set; }
|
public int CompressionFlags { get; private set; }
|
||||||
public int Variable0Bits { get; private set; }
|
public int Variable0Bits { get; private set; }
|
||||||
@ -148,7 +151,7 @@ namespace OpenDiablo2.Common.Models
|
|||||||
public Cell[] Cells { get; private set; }
|
public Cell[] Cells { get; private set; }
|
||||||
public int HorizontalCellCount { get; private set; }
|
public int HorizontalCellCount { get; private set; }
|
||||||
public int VerticalCellCount { get; private set; }
|
public int VerticalCellCount { get; private set; }
|
||||||
public List<PixelBufferEntry> PixelBuffer { get; private set; }
|
public PixelBufferEntry[] PixelBuffer { get; private set; }
|
||||||
|
|
||||||
private static readonly byte[] crazyBitTable = { 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32 };
|
private static readonly byte[] crazyBitTable = { 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32 };
|
||||||
public MPQDCCDirection(BitMuncher bm, MPQDCC file)
|
public MPQDCCDirection(BitMuncher bm, MPQDCC file)
|
||||||
@ -165,9 +168,6 @@ namespace OpenDiablo2.Common.Models
|
|||||||
|
|
||||||
Frames = new MPQDCCDirectionFrame[file.NumberOfFrames];
|
Frames = new MPQDCCDirectionFrame[file.NumberOfFrames];
|
||||||
|
|
||||||
if (Variable0Bits != 0)
|
|
||||||
throw new ApplicationException("Variable0Bits is not 0. This is not ok.");
|
|
||||||
|
|
||||||
// Load the frame headers
|
// Load the frame headers
|
||||||
for (var frameIdx = 0; frameIdx < file.NumberOfFrames; frameIdx++)
|
for (var frameIdx = 0; frameIdx < file.NumberOfFrames; frameIdx++)
|
||||||
Frames[frameIdx] = new MPQDCCDirectionFrame(bm, this);
|
Frames[frameIdx] = new MPQDCCDirectionFrame(bm, this);
|
||||||
@ -253,30 +253,32 @@ namespace OpenDiablo2.Common.Models
|
|||||||
private void FillPixelBuffer(BitMuncher pcd, BitMuncher ec, BitMuncher pm, BitMuncher et, BitMuncher rp)
|
private void FillPixelBuffer(BitMuncher pcd, BitMuncher ec, BitMuncher pm, BitMuncher et, BitMuncher rp)
|
||||||
{
|
{
|
||||||
UInt32 lastPixel = 0;
|
UInt32 lastPixel = 0;
|
||||||
var cellBuffer = new int[HorizontalCellCount * VerticalCellCount]; // Store the offset to the cell buffer
|
|
||||||
for (var i = 0; i < cellBuffer.Length; i++)
|
PixelBuffer = new PixelBufferEntry[DCC_MAX_PB_ENTRY];
|
||||||
cellBuffer[i] = -1;
|
for (var i = 0; i < DCC_MAX_PB_ENTRY; i++)
|
||||||
|
PixelBuffer[i] = new PixelBufferEntry { Frame = -1, FrameCellIndex = -1, Value = new byte[4] };
|
||||||
|
|
||||||
PixelBuffer = new List<PixelBufferEntry>();
|
var cellBuffer = new PixelBufferEntry[Cells.Length];
|
||||||
|
|
||||||
var frameIndex = -1;
|
var frameIndex = -1;
|
||||||
|
var pbIndex = -1;
|
||||||
UInt32 pixelMask = 0x00;
|
UInt32 pixelMask = 0x00;
|
||||||
foreach (var frame in Frames)
|
foreach (var frame in Frames)
|
||||||
{
|
{
|
||||||
frameIndex++;
|
frameIndex++;
|
||||||
var originCellX = (frame.Box.Left - Box.Left) / 4;
|
var originCellX = (frame.Box.Left - Box.Left) / 4;
|
||||||
var originCellY = (frame.Box.Top - Box.Top) / 4;
|
var originCellY = (frame.Box.Top - Box.Top) / 4;
|
||||||
|
var frameCellIndex = 0;
|
||||||
for (var cellY = 0; cellY < frame.VerticalCellCount; cellY++)
|
for (var cellY = 0; cellY < frame.VerticalCellCount; cellY++)
|
||||||
{
|
{
|
||||||
var currentCellY = cellY + originCellY;
|
var currentCellY = cellY + originCellY;
|
||||||
for (var cellX = 0; cellX < frame.HorizontalCellCount; cellX++)
|
for (var cellX = 0; cellX < frame.HorizontalCellCount; cellX++, frameCellIndex++)
|
||||||
{
|
{
|
||||||
var currentCell = (originCellX + cellX) + (currentCellY * HorizontalCellCount);
|
var currentCell = (originCellX + cellX) + (currentCellY * frame.HorizontalCellCount);
|
||||||
var nextCell = false;
|
var nextCell = false;
|
||||||
if (cellBuffer[currentCell] != -1)
|
var tmp = 0;
|
||||||
|
if (cellBuffer[currentCell] != null)
|
||||||
{
|
{
|
||||||
var tmp = 0;
|
|
||||||
if (EqualCellsBitstreamSize > 0)
|
if (EqualCellsBitstreamSize > 0)
|
||||||
tmp = ec.GetBit();
|
tmp = ec.GetBit();
|
||||||
|
|
||||||
@ -287,65 +289,67 @@ namespace OpenDiablo2.Common.Models
|
|||||||
}
|
}
|
||||||
else pixelMask = 0x0F;
|
else pixelMask = 0x0F;
|
||||||
|
|
||||||
|
if (nextCell)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (nextCell == false)
|
// Decode the pixels
|
||||||
|
var pixelStack = new UInt32[4];
|
||||||
|
lastPixel = 0;
|
||||||
|
int numberOfPixelBits = pixelMaskLookup[pixelMask];
|
||||||
|
var encodingType = ((numberOfPixelBits != 0) && (EncodingTypeBitsreamSize > 0))
|
||||||
|
? et.GetBit()
|
||||||
|
: 0;
|
||||||
|
int decodedPixel = 0;
|
||||||
|
for (int i = 0; i < numberOfPixelBits; i++)
|
||||||
{
|
{
|
||||||
// Decode the pixels
|
if (encodingType != 0)
|
||||||
UInt32[] pixelStack = new UInt32[4];
|
|
||||||
int numberOfPixelBits = pixelMaskLookup[pixelMask];
|
|
||||||
var encodingType = ((numberOfPixelBits != 0) && (EncodingTypeBitsreamSize > 0))
|
|
||||||
? et.GetBit()
|
|
||||||
: 0;
|
|
||||||
int decodedPixel = 0;
|
|
||||||
for (int i = 0; i < numberOfPixelBits; i++)
|
|
||||||
{
|
{
|
||||||
if (encodingType != 0)
|
pixelStack[i] = (UInt32)rp.GetBits(8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixelStack[i] = lastPixel;
|
||||||
|
var pixelDisplacement = pcd.GetBits(4);
|
||||||
|
pixelStack[i] += (UInt32)pixelDisplacement;
|
||||||
|
while (pixelDisplacement == 15)
|
||||||
{
|
{
|
||||||
pixelStack[i] = (UInt32)rp.GetBits(8);
|
pixelDisplacement = pcd.GetBits(4);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixelStack[i] = lastPixel;
|
|
||||||
var pixelDisplacement = pcd.GetBits(4);
|
|
||||||
pixelStack[i] += (UInt32)pixelDisplacement;
|
pixelStack[i] += (UInt32)pixelDisplacement;
|
||||||
while (pixelDisplacement == 15)
|
|
||||||
{
|
|
||||||
pixelDisplacement = pcd.GetBits(4);
|
|
||||||
pixelStack[i] += (UInt32)pixelDisplacement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pixelStack[i] == lastPixel)
|
|
||||||
{
|
|
||||||
pixelStack[i] = 0;
|
|
||||||
i = numberOfPixelBits; // Just break here....
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastPixel = pixelStack[i];
|
|
||||||
decodedPixel++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pixelStack[i] == lastPixel)
|
||||||
var oldEntry = cellBuffer[currentCell];
|
|
||||||
var curIdx = decodedPixel - 1;
|
|
||||||
var newEntry = new PixelBufferEntry { Value = new byte[4] };
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
{
|
||||||
if ((pixelMask * (1 << i)) != 0)
|
pixelStack[i] = 0;
|
||||||
{
|
i = numberOfPixelBits; // Just break here....
|
||||||
if (curIdx >= 0)
|
}
|
||||||
newEntry.Value[i] = (byte)pixelStack[curIdx--];
|
else
|
||||||
else
|
{
|
||||||
newEntry.Value[i] = 0;
|
lastPixel = pixelStack[i];
|
||||||
}
|
decodedPixel++;
|
||||||
else
|
|
||||||
newEntry.Value[i] = PixelBuffer[oldEntry].Value[i];
|
|
||||||
}
|
}
|
||||||
newEntry.Frame = frameIndex;
|
|
||||||
newEntry.FrameCellIndex = XOffsetBits + (cellY * HorizontalCellCount);
|
|
||||||
PixelBuffer.Add(newEntry);
|
|
||||||
cellBuffer[currentCell] = PixelBuffer.Count() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oldEntry = cellBuffer[currentCell];
|
||||||
|
pbIndex++;
|
||||||
|
var newEntry = PixelBuffer[pbIndex];
|
||||||
|
var curIdx = decodedPixel - 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if ((pixelMask & (1 << i)) != 0)
|
||||||
|
{
|
||||||
|
if (curIdx >= 0)
|
||||||
|
newEntry.Value[i] = (byte)pixelStack[curIdx--];
|
||||||
|
else
|
||||||
|
newEntry.Value[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newEntry.Value[i] = oldEntry.Value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
cellBuffer[currentCell] = newEntry;
|
||||||
|
newEntry.Frame = frameIndex;
|
||||||
|
newEntry.FrameCellIndex = cellX + (cellY * HorizontalCellCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user