diff --git a/README.md b/README.md
index 3b052b5..a8a6e73 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ Formats of the second generation 2D games are mostly focused right now.
|-------------------|:---------:|:-----------:|:----:|:----:|
| Archive | DIR | W2, WA, WWP | Yes | Yes |
| Image | IMG | W2, WA, WWP | Yes | No |
+| Land Data | LAND.DAT | W2, WA, WWP | Yes | No |
| Mission | DAT | W2 | No | No |
| Mission | WAM | WA, WWP | No | No |
| Monochrome Map | LEV | W2 | No | No |
diff --git a/src/Syroot.Worms.Test/Program.cs b/src/Syroot.Worms.Test/Program.cs
index 264945b..dac17a5 100644
--- a/src/Syroot.Worms.Test/Program.cs
+++ b/src/Syroot.Worms.Test/Program.cs
@@ -18,8 +18,6 @@ namespace Syroot.Worms.Test
private static void Main(string[] args)
{
- Palette palette = new Palette("C:\\Games\\Worms World Party\\graphics\\palettes\\wwp.pal");
-
Console.WriteLine("Done.");
Console.ReadLine();
}
diff --git a/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs b/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs
index b3096a5..3393508 100644
--- a/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs
+++ b/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs
@@ -14,12 +14,9 @@ namespace Syroot.Worms.UnitTest.Common
{
// ---- MEMBERS ------------------------------------------------------------------------------------------------
- private static readonly string[] _gamePaths =
- {
- @"C:\Games\Worms2",
- @"C:\Games\Worms Armageddon 3.7.2.1",
- @"C:\Games\Worms World Party"
- };
+ private static readonly string[] _gamePathsWorms2 = { @"C:\Games\Worms2" };
+ private static readonly string[] _gamePathsWormsArmageddon = { @"C:\Games\Worms Armageddon 3.7.2.1" };
+ private static readonly string[] _gamePathsWormsWorldParty = { @"C:\Games\Worms World Party" };
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
@@ -28,11 +25,13 @@ namespace Syroot.Worms.UnitTest.Common
/// optional array .
///
/// The type of the files to load.
+ /// The games to test.
/// The wildcard to match.
/// Optionally, the files to exclude.
- internal static void LoadFiles(string wildcard, string[] excludedFiles = null) where T : ILoadableFile, new()
+ internal static void LoadFiles(Game games, string wildcard, string[] excludedFiles = null)
+ where T : ILoadableFile, new()
{
- foreach (string fileName in FindFiles(wildcard))
+ foreach (string fileName in FindFiles(games, wildcard))
{
if (excludedFiles?.Contains(Path.GetFileName(fileName), StringComparer.OrdinalIgnoreCase) == true)
{
@@ -47,21 +46,46 @@ namespace Syroot.Worms.UnitTest.Common
}
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
-
- ///
- /// Returns a list of files found in any of the paths provided in the _gamePaths variable which match the
- /// specified .
- ///
- /// The wildcard which files have to match.
- /// A list of files matching the search.
- private static List FindFiles(string wildcard)
+
+ private static List FindFiles(Game games, string wildcard)
{
+ List gamePaths = GetGamePaths(games);
List files = new List();
- foreach (string testPath in _gamePaths)
+ foreach (string testPath in gamePaths)
{
files.AddRange(Directory.GetFiles(testPath, wildcard, SearchOption.AllDirectories));
}
return files;
}
+
+ private static List GetGamePaths(Game game)
+ {
+ List gamePaths = new List();
+ if (game.HasFlag(Game.Worms2))
+ {
+ gamePaths.AddRange(_gamePathsWorms2);
+ }
+ if (game.HasFlag(Game.WormsArmageddon))
+ {
+ gamePaths.AddRange(_gamePathsWormsArmageddon);
+ }
+ if (game.HasFlag(Game.WormsWorldParty))
+ {
+ gamePaths.AddRange(_gamePathsWormsWorldParty);
+ }
+ return gamePaths;
+ }
+ }
+
+ [Flags]
+ internal enum Game
+ {
+ Worms2 = 1 << 0,
+ WormsArmageddon = 1 << 1,
+ WormsWorldParty = 1 << 2,
+
+ Gen2 = Worms2 | WormsArmageddon | WormsWorldParty,
+ Armageddon = WormsArmageddon | WormsWorldParty,
+ All = -1
}
}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs b/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs
index c98bfb7..a2ced52 100644
--- a/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs
+++ b/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs
@@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2
[TestMethod]
public void LoadArchives()
{
- TestHelpers.LoadFiles("*.dir");
+ TestHelpers.LoadFiles(Game.Gen2, "*.dir");
}
}
}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs
new file mode 100644
index 0000000..787d64e
--- /dev/null
+++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs
@@ -0,0 +1,25 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Syroot.Worms.Gen2.Armageddon;
+using Syroot.Worms.UnitTest.Common;
+
+namespace Syroot.Worms.UnitTest.Gen2.Armageddon
+{
+ ///
+ /// Represents a collection of tests for the class.
+ ///
+ [TestCategory("LandData (Armageddon)")]
+ [TestClass]
+ public class LandDataTests
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads all files found in any game directories.
+ ///
+ [TestMethod]
+ public void LoadLandData()
+ {
+ TestHelpers.LoadFiles(Game.Armageddon, "land.dat");
+ }
+ }
+}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs
index b51b0f4..af9d3ec 100644
--- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs
+++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs
@@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon
[TestMethod]
public void LoadSchemes()
{
- TestHelpers.LoadFiles("*.wsc");
+ TestHelpers.LoadFiles(Game.Armageddon, "*.wsc");
}
}
}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs b/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs
index 8e42ad6..4924f63 100644
--- a/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs
+++ b/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs
@@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2
[TestMethod]
public void LoadImages()
{
- TestHelpers.LoadFiles("*.img");
+ TestHelpers.LoadFiles(Game.All, "*.img");
}
}
}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs b/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs
index a727da1..19243d3 100644
--- a/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs
+++ b/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs
@@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2
[TestMethod]
public void LoadPalettes()
{
- TestHelpers.LoadFiles("*.pal", new string[]
+ TestHelpers.LoadFiles(Game.Gen2, "*.pal", new string[]
{
"wwp.pal", // Contains 4 bytes of trash after the data chunk.
"wwpmaped.pal" // Contains 4 bytes of trash after the data chunk.
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs
new file mode 100644
index 0000000..a6b6d2d
--- /dev/null
+++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs
@@ -0,0 +1,25 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Syroot.Worms.Gen2.Worms2;
+using Syroot.Worms.UnitTest.Common;
+
+namespace Syroot.Worms.UnitTest.Gen2.Worms2
+{
+ ///
+ /// Represents a collection of tests for the class.
+ ///
+ [TestCategory("LandData (Worms2)")]
+ [TestClass]
+ public class LandDataTests
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads all files found in any game directories.
+ ///
+ [TestMethod]
+ public void LoadLandData()
+ {
+ TestHelpers.LoadFiles(Game.Worms2, "land.dat");
+ }
+ }
+}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs
index 0ec9db3..fdbab49 100644
--- a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs
+++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs
@@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Worms2
[TestMethod]
public void LoadSchemeOptions()
{
- TestHelpers.LoadFiles("*.opt");
+ TestHelpers.LoadFiles(Game.Worms2, "*.opt");
}
}
}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs
index 704a551..bba5410 100644
--- a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs
+++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs
@@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Worms2
[TestMethod]
public void LoadSchemeWeapons()
{
- TestHelpers.LoadFiles("*.wep");
+ TestHelpers.LoadFiles(Game.Worms2, "*.wep");
}
}
}
diff --git a/src/Syroot.Worms/Core/RiffFile.cs b/src/Syroot.Worms/Core/RiffFile.cs
index 4eadd2a..b907680 100644
--- a/src/Syroot.Worms/Core/RiffFile.cs
+++ b/src/Syroot.Worms/Core/RiffFile.cs
@@ -40,7 +40,7 @@ namespace Syroot.Worms.Core
/// The to load the RIFF data from.
protected void LoadRiff(Stream stream)
{
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the file header.
if (reader.ReadString(_signature.Length) != _signature)
diff --git a/src/Syroot.Worms/Gen2/Archive.cs b/src/Syroot.Worms/Gen2/Archive.cs
index c507d62..6b8e49c 100644
--- a/src/Syroot.Worms/Gen2/Archive.cs
+++ b/src/Syroot.Worms/Gen2/Archive.cs
@@ -65,7 +65,7 @@ namespace Syroot.Worms.Gen2
}
Clear();
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the header.
if (reader.ReadInt32() != _signature)
diff --git a/src/Syroot.Worms/Gen2/Armageddon/LandData.cs b/src/Syroot.Worms/Gen2/Armageddon/LandData.cs
index 3558d43..4817f55 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/LandData.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/LandData.cs
@@ -7,8 +7,8 @@ using Syroot.Worms.Core;
namespace Syroot.Worms.Gen2.Armageddon
{
///
- /// Represents scheme options stored in an OPT file which contains game settings.
- /// S. https://worms2d.info/Options_file.
+ /// Represents map configuration stored by the land generator in LAND.DAT files.
+ /// Used by WA and WWP. S. https://worms2d.info/Land_Data_file.
///
public class LandData : ILoadableFile
{
@@ -18,6 +18,13 @@ namespace Syroot.Worms.Gen2.Armageddon
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public LandData()
+ {
+ }
+
///
/// Initializes a new instance of the class, loading the data from the given
/// .
@@ -92,7 +99,7 @@ namespace Syroot.Worms.Gen2.Armageddon
/// The to load the data from.
public void Load(Stream stream)
{
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the header.
if (reader.ReadInt32() != _signature)
@@ -107,8 +114,8 @@ namespace Syroot.Worms.Gen2.Armageddon
WaterHeight = reader.ReadInt32();
// Read the possible object coordinate array.
+ int badObjectLocations = reader.ReadInt32(); // TODO: Check what this is used for.
ObjectLocations = new Vector2[reader.ReadInt32()];
- int objectLocationCountAgain = reader.ReadInt32(); // TODO: Repetitive or useful?
for (int i = 0; i < ObjectLocations.Length; i++)
{
ObjectLocations[i] = reader.ReadStruct();
diff --git a/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs b/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs
index f75e688..e6bff03 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs
@@ -608,7 +608,7 @@ namespace Syroot.Worms.Gen2.Armageddon
/// The to load the data from.
public void Load(Stream stream)
{
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the header.
if (reader.ReadString(_signature.Length) != _signature)
diff --git a/src/Syroot.Worms/Gen2/Image.cs b/src/Syroot.Worms/Gen2/Image.cs
index 13383db..ef343c2 100644
--- a/src/Syroot.Worms/Gen2/Image.cs
+++ b/src/Syroot.Worms/Gen2/Image.cs
@@ -80,7 +80,7 @@ namespace Syroot.Worms.Gen2
/// The to load the data from.
public void Load(Stream stream)
{
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the header.
if (reader.ReadInt32() != _signature)
@@ -117,10 +117,10 @@ namespace Syroot.Worms.Gen2
}
}
- Size = reader.ReadStruct();
-
- // Read the image data, which might be compressed.
- byte[] data = new byte[Size.X * Size.Y * (BitsPerPixel / 8)];
+ Size = new Vector2(reader.ReadInt16(), reader.ReadInt16());
+
+ // Read the bytes, which might be compressed.
+ byte[] data = new byte[Size.X * Size.Y * BitsPerPixel / 8];
if (flags.HasFlag(Flags.Compressed))
{
Team17Compression.Decompress(reader.BaseStream, ref data);
@@ -129,6 +129,7 @@ namespace Syroot.Worms.Gen2
{
data = reader.ReadBytes(data.Length);
}
+
Data = data;
}
}
diff --git a/src/Syroot.Worms/Gen2/Worms2/LandData.cs b/src/Syroot.Worms/Gen2/Worms2/LandData.cs
new file mode 100644
index 0000000..c72b6d3
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Worms2/LandData.cs
@@ -0,0 +1,147 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Maths;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Worms2
+{
+ ///
+ /// Represents map configuration stored by the land generator in LAND.DAT files.
+ /// Used by W2. S. https://worms2d.info/Land_Data_file.
+ ///
+ public class LandData : ILoadableFile
+ {
+ // ---- CONSTANTS ----------------------------------------------------------------------------------------------
+
+ private const int _signature = 0x1A444E4C; // "LND", 0x1A
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public LandData()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given
+ /// .
+ ///
+ /// The to load the data from.
+ public LandData(Stream stream)
+ {
+ Load(stream);
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public LandData(string fileName)
+ {
+ Load(fileName);
+ }
+
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ ///
+ /// Gets or sets the size of the landscape in pixels.
+ ///
+ public Vector2 Size { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether an indestructible top border will be enabled.
+ ///
+ public bool TopBorder { get; set; }
+
+ ///
+ /// Gets or sets an array of coordinates at which objects can be placed.
+ ///
+ public Vector2[] ObjectLocations { get; set; }
+
+ ///
+ /// Gets or sets the visual foreground image.
+ ///
+ public Image Foreground { get; set; }
+
+ ///
+ /// Gets or sets the collision mask of the landscape.
+ ///
+ public Image CollisionMask { get; set; }
+
+ ///
+ /// Gets or sets the visual background image.
+ ///
+ public Image Background { get; set; }
+
+ ///
+ /// Gets or sets an image of unknown use.
+ ///
+ public Image UnknownImage { get; set; }
+
+ ///
+ /// Gets or sets the path to the land image file.
+ ///
+ public string LandTexturePath { get; set; }
+
+ ///
+ /// Gets or sets the path to the Water.dir file.
+ ///
+ public string WaterDirPath { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ // Read the header.
+ if (reader.ReadInt32() != _signature)
+ {
+ throw new InvalidDataException("Invalid LND file signature.");
+ }
+ int fileLength = reader.ReadInt32();
+
+ // Read the data.
+ Size = reader.ReadStruct();
+ TopBorder = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+
+ // Read the possible object coordinate array.
+ ObjectLocations = new Vector2[reader.ReadInt32()];
+ for (int i = 0; i < ObjectLocations.Length; i++)
+ {
+ ObjectLocations[i] = reader.ReadStruct();
+ }
+ int unknown = reader.ReadInt32(); // Seems 0.
+
+ // Read the image data.
+ Foreground = new Image(stream);
+ CollisionMask = new Image(stream);
+ Background = new Image(stream);
+ UnknownImage = new Image(stream);
+
+ // Read the file paths.
+ LandTexturePath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
+ WaterDirPath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
+ }
+ }
+
+ ///
+ /// Loads the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public void Load(string fileName)
+ {
+ using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ Load(stream);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Worms2/SchemeOptions.cs b/src/Syroot.Worms/Gen2/Worms2/SchemeOptions.cs
index a259c04..225da7d 100644
--- a/src/Syroot.Worms/Gen2/Worms2/SchemeOptions.cs
+++ b/src/Syroot.Worms/Gen2/Worms2/SchemeOptions.cs
@@ -7,7 +7,7 @@ namespace Syroot.Worms.Gen2.Worms2
{
///
/// Represents scheme options stored in an OPT file which contains game settings.
- /// S. https://worms2d.info/Options_file.
+ /// Used by W2. S. https://worms2d.info/Options_file.
///
public class SchemeOptions : ILoadableFile, ISaveableFile
{
@@ -221,7 +221,7 @@ namespace Syroot.Worms.Gen2.Worms2
/// The to load the data from.
public void Load(Stream stream)
{
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the header.
if (reader.ReadString(_signature.Length) != _signature)
diff --git a/src/Syroot.Worms/Gen2/Worms2/SchemeWeapons.cs b/src/Syroot.Worms/Gen2/Worms2/SchemeWeapons.cs
index 912e15e..8c6e795 100644
--- a/src/Syroot.Worms/Gen2/Worms2/SchemeWeapons.cs
+++ b/src/Syroot.Worms/Gen2/Worms2/SchemeWeapons.cs
@@ -7,7 +7,7 @@ namespace Syroot.Worms.Gen2.Worms2
{
///
/// Represents scheme weapons stored in an WEP file which contains armory configuration.
- /// S. https://worms2d.info/Weapons_file.
+ /// Used by W2. S. https://worms2d.info/Weapons_file.
///
public class SchemeWeapons : ILoadableFile, ISaveableFile
{
@@ -62,7 +62,7 @@ namespace Syroot.Worms.Gen2.Worms2
/// The to load the data from.
public void Load(Stream stream)
{
- using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII))
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
// Read the header.
reader.Seek(_trashLength);