From 78ee66bdfbe742d0a970faa404e70b9f1f841f59 Mon Sep 17 00:00:00 2001 From: Tim Sarbin Date: Sat, 24 Nov 2018 11:45:10 -0500 Subject: [PATCH] Fixed signed/unsigned ds/dt issue. Cleaned up load logic --- OpenDiablo2.Common/Models/MPQDS1.cs | 60 ++++++------- OpenDiablo2.Common/Models/MPQDT1.cs | 135 ++++++++++++++++------------ 2 files changed, 107 insertions(+), 88 deletions(-) diff --git a/OpenDiablo2.Common/Models/MPQDS1.cs b/OpenDiablo2.Common/Models/MPQDS1.cs index 0f2777d0..c9fbf80e 100644 --- a/OpenDiablo2.Common/Models/MPQDS1.cs +++ b/OpenDiablo2.Common/Models/MPQDS1.cs @@ -43,27 +43,27 @@ namespace OpenDiablo2.Common.Models public sealed class MPQDS1Object { - public UInt32 Type { get; internal set; } - public UInt32 Id { get; internal set; } - public UInt32 X { get; internal set; } - public UInt32 Y { get; internal set; } - public UInt32 DS1Flags { get; internal set; } + public Int32 Type { get; internal set; } + public Int32 Id { get; internal set; } + public Int32 X { get; internal set; } + public Int32 Y { get; internal set; } + public Int32 DS1Flags { get; internal set; } } public sealed class MPQDS1 { static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public UInt32 Version { get; internal set; } - public UInt32 Width { get; internal set; } - public UInt32 Height { get; internal set; } - public UInt32 Act { get; internal set; } // ??? - public UInt32 TagType { get; internal set; } // ??? - public UInt32 FileCount { get; internal set; } - public UInt32 NumberOfWalls { get; internal set; } - public UInt32 NumberOfFloors { get; internal set; } - public UInt32 NumberOfObjects { get; internal set; } - public UInt32 NumberOfNPCs { get; internal set; } + public Int32 Version { get; internal set; } + public Int32 Width { get; internal set; } + public Int32 Height { get; internal set; } + public Int32 Act { get; internal set; } // ??? + public Int32 TagType { get; internal set; } // ??? + public Int32 FileCount { get; internal set; } + public Int32 NumberOfWalls { get; internal set; } + public Int32 NumberOfFloors { get; internal set; } + public Int32 NumberOfObjects { get; internal set; } + public Int32 NumberOfNPCs { get; internal set; } public MPQDT1[] DT1s = new MPQDT1[32]; @@ -78,12 +78,12 @@ namespace OpenDiablo2.Common.Models { log.Debug($"Loading {fileName} (Act {act}) Def {definition}"); var br = new BinaryReader(stream); - Version = br.ReadUInt32(); - Width = br.ReadUInt32() + 1; - Height = br.ReadUInt32() + 1; - Act = br.ReadUInt32(); - TagType = br.ReadUInt32(); - FileCount = br.ReadUInt32(); + Version = br.ReadInt32(); + Width = br.ReadInt32() + 1; + Height = br.ReadInt32() + 1; + Act = br.ReadInt32(); + TagType = br.ReadInt32(); + FileCount = br.ReadInt32(); @@ -105,8 +105,8 @@ namespace OpenDiablo2.Common.Models FileNames.Add(fn); } - NumberOfWalls = br.ReadUInt32(); - NumberOfFloors = br.ReadUInt32(); + NumberOfWalls = br.ReadInt32(); + NumberOfFloors = br.ReadInt32(); for (int i = 0; i < NumberOfWalls; i++) { @@ -186,22 +186,22 @@ namespace OpenDiablo2.Common.Models // TODO: Tag layer goes here (tag = 1) - NumberOfObjects = br.ReadUInt32(); + NumberOfObjects = br.ReadInt32(); for (int i = 0; i < NumberOfObjects; i++) { Objects.Add(new MPQDS1Object { - Type = br.ReadUInt32(), - Id = br.ReadUInt32(), - X = br.ReadUInt32(), - Y = br.ReadUInt32(), - DS1Flags = br.ReadUInt32() + Type = br.ReadInt32(), + Id = br.ReadInt32(), + X = br.ReadInt32(), + Y = br.ReadInt32(), + DS1Flags = br.ReadInt32() }); } // TODO: Option groups go here (tag = 1) - NumberOfNPCs = br.ReadUInt32(); + NumberOfNPCs = br.ReadInt32(); // TODO: WalkPaths diff --git a/OpenDiablo2.Common/Models/MPQDT1.cs b/OpenDiablo2.Common/Models/MPQDT1.cs index ea6fb798..e19673f8 100644 --- a/OpenDiablo2.Common/Models/MPQDT1.cs +++ b/OpenDiablo2.Common/Models/MPQDT1.cs @@ -9,100 +9,119 @@ namespace OpenDiablo2.Common.Models { public sealed class MPQDT1Block { - public UInt16 PositionX { get; internal set; } - public UInt16 PositionY { get; internal set; } + public Int16 PositionX { get; internal set; } + public Int16 PositionY { get; internal set; } public byte GridX { get; internal set; } public byte GridY { get; internal set; } - public UInt16 Format { get; internal set; } - public UInt32 Length { get; internal set; } - public UInt32 FileOffset { get; internal set; } + public Int16 Format { get; internal set; } + public Int32 Length { get; internal set; } + public Int32 FileOffset { get; internal set; } public Int16[] PixelData { get; internal set; } } public sealed class MPQDT1Tile { - public UInt32 Direction { get; internal set; } - public UInt16 RoofHeight { get; internal set; } + public Int32 Direction { get; internal set; } + public Int16 RoofHeight { get; internal set; } public byte SoundIndex { get; internal set; } public bool Animated { get; internal set; } public int Height { get; internal set; } public int Width { get; internal set; } - public UInt32 Orientation { get; internal set; } - public UInt32 MainIndex { get; internal set; } - public UInt32 SubIndex { get; internal set; } - public UInt32 RarityOrFrameIndex { get; internal set; }// Frame index if animated floor tile + public Int32 Orientation { get; internal set; } + public Int32 MainIndex { get; internal set; } + public Int32 SubIndex { get; internal set; } + public Int32 RarityOrFrameIndex { get; internal set; }// Frame index if animated floor tile public byte[] SubTileFlags { get; internal set; } = new byte[25]; - public UInt32 BlockHeadersPointer { get; internal set; } // Pointer to block headers for this tile - public UInt32 BlockDataLength { get; internal set; } // Block headers + block data of this tile - public UInt32 NumberOfBlocks { get; internal set; } + public Int32 BlockHeadersPointer { get; internal set; } // Pointer to block headers for this tile + public Int32 BlockDataLength { get; internal set; } // Block headers + block data of this tile + public Int32 NumberOfBlocks { get; internal set; } public MPQDT1Block[] Blocks { get; internal set; } } public sealed class MPQDT1 { - public UInt32 NumberOfTiles { get; private set; } + public Int32 NumberOfTiles { get; private set; } public MPQDT1Tile[] Tiles { get; private set; } + private Int32 tileHeaderOffset; public MPQDT1(Stream stream) { var br = new BinaryReader(stream); stream.Seek(268, SeekOrigin.Begin); // Skip useless header info - NumberOfTiles = br.ReadUInt32(); - var tileHeaderOffset = br.ReadUInt32(); - stream.Seek(tileHeaderOffset, SeekOrigin.Begin); + NumberOfTiles = br.ReadInt32(); + tileHeaderOffset = br.ReadInt32(); + + ReadTiles(br); + ReadBlockHeaders(br); + ReadBlockGraphics(br); + + } + private void ReadTiles(BinaryReader br) + { Tiles = new MPQDT1Tile[NumberOfTiles]; - for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++) { - stream.Seek(tileHeaderOffset + (96 * tileIndex), SeekOrigin.Begin); Tiles[tileIndex] = new MPQDT1Tile(); var tile = Tiles[tileIndex]; - tile.Direction = br.ReadUInt32(); - tile.RoofHeight = br.ReadUInt16(); + tile.Direction = br.ReadInt32(); + tile.RoofHeight = br.ReadInt16(); tile.SoundIndex = br.ReadByte(); tile.Animated = br.ReadByte() == 1; tile.Height = br.ReadInt32(); tile.Width = br.ReadInt32(); br.ReadBytes(4); - tile.Orientation = br.ReadUInt32(); - tile.MainIndex = br.ReadUInt32(); - tile.SubIndex = br.ReadUInt32(); - tile.RarityOrFrameIndex = br.ReadUInt32(); + tile.Orientation = br.ReadInt32(); + tile.MainIndex = br.ReadInt32(); + tile.SubIndex = br.ReadInt32(); + tile.RarityOrFrameIndex = br.ReadInt32(); br.ReadBytes(4); for (int i = 0; i < 25; i++) tile.SubTileFlags[i] = br.ReadByte(); br.ReadBytes(7); - tile.BlockHeadersPointer = br.ReadUInt32(); - tile.BlockDataLength = br.ReadUInt32(); - tile.NumberOfBlocks = br.ReadUInt32(); + tile.BlockHeadersPointer = br.ReadInt32(); + tile.BlockDataLength = br.ReadInt32(); + tile.NumberOfBlocks = br.ReadInt32(); br.ReadBytes(12); + } + } - if (tile.BlockHeadersPointer == 0 || tile.Width == 0 || tile.Height == 0) - { - tile.Blocks = new MPQDT1Block[0]; - continue; - } + private void ReadBlockHeaders(BinaryReader br) + { + for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++) + { + var tile = Tiles[tileIndex]; + br.BaseStream.Seek(tile.BlockHeadersPointer, SeekOrigin.Begin); tile.Blocks = new MPQDT1Block[tile.NumberOfBlocks]; + for (int blockIndex = 0; blockIndex < tile.NumberOfBlocks; blockIndex++) { - stream.Seek(tile.BlockHeadersPointer + (20 * blockIndex), SeekOrigin.Begin); tile.Blocks[blockIndex] = new MPQDT1Block(); var block = tile.Blocks[blockIndex]; - block.PositionX = br.ReadUInt16(); - block.PositionY = br.ReadUInt16(); + block.PositionX = br.ReadInt16(); + block.PositionY = br.ReadInt16(); br.ReadBytes(2); block.GridX = br.ReadByte(); block.GridX = br.ReadByte(); - block.Format = br.ReadUInt16(); - block.Length = br.ReadUInt32(); + block.Format = br.ReadInt16(); + block.Length = br.ReadInt32(); br.ReadBytes(2); - block.FileOffset = br.ReadUInt32(); - - stream.Seek(tile.BlockHeadersPointer + block.FileOffset, SeekOrigin.Begin); + block.FileOffset = br.ReadInt32(); + } + } + } + + private void ReadBlockGraphics(BinaryReader br) + { + for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++) + { + for (int blockIndex = 0; blockIndex < Tiles[tileIndex].NumberOfBlocks; blockIndex++) + { + var block = Tiles[tileIndex].Blocks[blockIndex]; + br.BaseStream.Seek(Tiles[tileIndex].BlockHeadersPointer + block.FileOffset, SeekOrigin.Begin); if (block.Format == 1) { @@ -132,10 +151,10 @@ namespace OpenDiablo2.Common.Models } } - else + else { // RLE block - /* TODO: BROKEN + /* var length = block.Length; byte b1; byte b2; @@ -143,28 +162,27 @@ namespace OpenDiablo2.Common.Models int y = 0; int width = (block.Format >> 8); int height = (block.Format & 0xFF); - block.PixelData = new Int16[width * height]; + block.PixelData = new Int16[256 * 256]; while (length > 0) { b1 = br.ReadByte(); b2 = br.ReadByte(); length -= 2; - if (b1 != 0 || b2 != 0) - { - x += b1; - length -= b2; - while (b2 > 0) - { - block.PixelData[x + (y * 32)] = br.ReadByte(); - br.ReadByte(); - x++; - b2--; - } - } - else + if (b1 + b2 == 0) { x = 0; y++; + continue; + } + + x += b1; + length -= b2; + while (b2 > 0) + { + block.PixelData[x + (y * 32)] = br.ReadByte(); + br.ReadByte(); + x++; + b2--; } } */ @@ -172,5 +190,6 @@ namespace OpenDiablo2.Common.Models } } } + } }