diff --git a/Build/Compilers/Nodebuilders/zdbsp.cfg b/Build/Compilers/Nodebuilders/zdbsp.cfg
index 8e981cfdd86d0d07da4001ace3e4f95e57ec9e16..d32329299a5a939a638a7f861803ac6d38f569a1 100644
--- a/Build/Compilers/Nodebuilders/zdbsp.cfg
+++ b/Build/Compilers/Nodebuilders/zdbsp.cfg
@@ -24,7 +24,7 @@ nodebuilders
 {
 	zdbsp_normal
 	{
-		title = "ZDBSP - Normal";
+		title = "ZDBSP - Normal (no reject)";
 		compiler = "zdbsp";
 		parameters = "-c -o%FO %FI";
 		// -c adds comment indices in UDMF format. This is not documented in the ZDBSP usage.
@@ -32,7 +32,7 @@ nodebuilders
 	
 	zdbsp_fast
 	{
-		title = "ZDBSP - Fast (no reject)";
+		title = "ZDBSP - Normal (zero reject)";
 		compiler = "zdbsp";
 		parameters = "-R -o%FO %FI";
 	}
diff --git a/Build/DevIL.dll b/Build/DevIL.dll
new file mode 100644
index 0000000000000000000000000000000000000000..b7a4c0906a33c7cd4a2f0c29d4863b5a048ed055
Binary files /dev/null and b/Build/DevIL.dll differ
diff --git a/Build/Builder.cfg b/Build/GZBuilder.cfg
similarity index 96%
rename from Build/Builder.cfg
rename to Build/GZBuilder.cfg
index 4d5566840917ac4ffc961eca7e2194c07aab542c..fdc2f0c478b35eafd93edef923eb455f634269ee 100644
--- a/Build/Builder.cfg
+++ b/Build/GZBuilder.cfg
@@ -196,6 +196,7 @@ colors
 	color37 = -29696;
 	color38 = -4343957;
 	color39 = -2448096;
+	color40 = -16744256;
 }
 
 
diff --git a/Build/Setup/slimdx.msi b/Build/Setup/slimdx.msi
index 182a233a687c075327065a37b9136860bb798e09..f3b661a73359311e896ae967683864d0aeb3d9af 100644
Binary files a/Build/Setup/slimdx.msi and b/Build/Setup/slimdx.msi differ
diff --git a/Build/SlimDX.dll b/Build/SlimDX.dll
new file mode 100644
index 0000000000000000000000000000000000000000..8715ac49f88431bf61eef5c2a7166c4d51683356
Binary files /dev/null and b/Build/SlimDX.dll differ
diff --git a/Builder.sln b/Builder.sln
index dafafa7abceb8cf547efc9f89b2244478c563c7a..291febe1384c999a284cb0c6fef17c60853c3cad 100644
--- a/Builder.sln
+++ b/Builder.sln
@@ -11,65 +11,108 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommentsPanel", "Source\Plu
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "Source\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpo_dll", "Source\Plugins\vpo_dll\vpo_dll.vcproj", "{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisplaneExplorer", "Source\Plugins\VisplaneExplorer\VisplaneExplorer.csproj", "{CF670175-7099-4090-A330-EE25C7230139}"
+	ProjectSection(ProjectDependencies) = postProject
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE} = {29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|Win32 = Debug|Win32
 		Debug|x86 = Debug|x86
 		Release|Any CPU = Release|Any CPU
 		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|Win32 = Release|Win32
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Win32.ActiveCfg = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.ActiveCfg = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.Build.0 = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Any CPU.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.Build.0 = Release|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Win32.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Win32.ActiveCfg = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.ActiveCfg = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.Build.0 = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Any CPU.ActiveCfg = Release|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.ActiveCfg = Release|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Win32.ActiveCfg = Release|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.ActiveCfg = Release|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.Build.0 = Release|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|Win32.ActiveCfg = Debug|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|x86.ActiveCfg = Debug|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|x86.Build.0 = Debug|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Any CPU.ActiveCfg = Release|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Mixed Platforms.ActiveCfg = Release|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Mixed Platforms.Build.0 = Release|x86
+		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Win32.ActiveCfg = Release|x86
 		{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|x86.ActiveCfg = Release|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Win32.ActiveCfg = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|x86.ActiveCfg = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|x86.Build.0 = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Any CPU.ActiveCfg = Release|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Mixed Platforms.ActiveCfg = Release|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Mixed Platforms.Build.0 = Release|x86
+		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Win32.ActiveCfg = Release|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|x86.ActiveCfg = Release|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|x86.Build.0 = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Win32.ActiveCfg = Debug|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.ActiveCfg = Debug|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.Build.0 = Debug|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Any CPU.ActiveCfg = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.ActiveCfg = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Win32.ActiveCfg = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Debug|Any CPU.ActiveCfg = Debug|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Debug|Win32.ActiveCfg = Debug|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Debug|Win32.Build.0 = Debug|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Debug|x86.ActiveCfg = Debug|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Release|Any CPU.ActiveCfg = Release|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Release|Mixed Platforms.Build.0 = Release|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Release|Win32.ActiveCfg = Release|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Release|Win32.Build.0 = Release|Win32
+		{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}.Release|x86.ActiveCfg = Release|Win32
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Win32.ActiveCfg = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Setup/builder2_setup.iss b/Setup/builder2_setup.iss
index 28036ef48b2aa7e3a888e93e394bc59b87bdd5f2..7aa8b6c8776b2c09728e6b8031b34a7e6a834b32 100644
--- a/Setup/builder2_setup.iss
+++ b/Setup/builder2_setup.iss
@@ -39,9 +39,11 @@ Source: Setup\slimdx.msi; DestDir: {tmp}; Flags: dontcopy
 Source: Builder.exe; DestDir: {app}; Flags: ignoreversion
 Source: Builder.cfg; DestDir: {app}; Flags: ignoreversion
 Source: Refmanual.chm; DestDir: {app}; Flags: ignoreversion
+Source: DevIL.dll; DestDir: {app}; Flags: ignoreversion
 Source: Sharpzip.dll; DestDir: {app}; Flags: ignoreversion
 Source: Scintilla.dll; DestDir: {app}; Flags: ignoreversion
 Source: Trackbar.dll; DestDir: {app}; Flags: ignoreversion
+Source: SlimDX.dll; DestDir: {app}; Flags: ignoreversion
 Source: GPL.txt; DestDir: {app}; Flags: ignoreversion
 Source: Compilers\*; DestDir: {app}\Compilers; Flags: ignoreversion recursesubdirs
 Source: Configurations\*; DestDir: {app}\Configurations; Flags: ignoreversion recursesubdirs
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 7dfd99b4ebbbdb404ca1e017ec725b6c644cd4f8..48bbe368c408ec69505c96864a1f1d4c9a850fac 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -502,7 +502,7 @@
       <HintPath>..\..\Build\Sharpzip.dll</HintPath>
       <Private>False</Private>
     </Reference>
-    <Reference Include="SlimDX, Version=2.0.12.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9, processorArchitecture=x86" />
+    <Reference Include="SlimDX, Version=2.0.13.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9, processorArchitecture=x86" />
     <Reference Include="System" />
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -695,11 +695,13 @@
     <Compile Include="Controls\TransparentPanel.cs">
       <SubType>Component</SubType>
     </Compile>
+    <Compile Include="Data\BitmapImage.cs" />
     <Compile Include="Data\ColorImage.cs" />
     <Compile Include="Data\ColormapImage.cs" />
     <Compile Include="Data\HighResImage.cs" />
     <Compile Include="Data\PK3FileImage.cs" />
     <Compile Include="Data\PK3StructuredReader.cs" />
+    <Compile Include="Data\DynamicBitmapImage.cs" />
     <Compile Include="Editing\CustomThingsFilter.cs" />
     <Compile Include="General\CRC.cs" />
     <Compile Include="General\ErrorItem.cs" />
diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln
index 87f1bad790aa7a9770446c0015cc623722cdd512..d6bbc183a33aac9ab253ba83f43c88aa38f2786c 100644
--- a/Source/Core/Builder.sln
+++ b/Source/Core/Builder.sln
@@ -5,6 +5,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj",
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "..\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuilderModes", "..\Plugins\BuilderModes\BuilderModes.csproj", "{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisplaneExplorer", "..\Plugins\VisplaneExplorer\VisplaneExplorer.csproj", "{CF670175-7099-4090-A330-EE25C7230139}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -35,6 +39,28 @@ Global
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86
 		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Any CPU.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.Build.0 = Release|x86
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug|x86.Build.0 = Debug|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|x86.ActiveCfg = Release|Any CPU
+		{CF670175-7099-4090-A330-EE25C7230139}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Source/Core/Config/ConfigurationInfo.cs b/Source/Core/Config/ConfigurationInfo.cs
index c14f738913aa23b5357cb59c7328e686ca48d51e..8b8d89adb253ee1ad6272597e2ea62663103d784 100644
--- a/Source/Core/Config/ConfigurationInfo.cs
+++ b/Source/Core/Config/ConfigurationInfo.cs
@@ -31,7 +31,7 @@ using System.Collections.Specialized;
 
 namespace CodeImp.DoomBuilder.Config
 {
-	internal class ConfigurationInfo : IComparable<ConfigurationInfo>
+	public class ConfigurationInfo : IComparable<ConfigurationInfo>
 	{
 		#region ================== Constants
 
@@ -69,16 +69,16 @@ namespace CodeImp.DoomBuilder.Config
 		public string Name { get { return name; } }
 		public string Filename { get { return filename; } }
 		public string DefaultLumpName { get { return defaultlumpname; } }
-		public string NodebuilderSave { get { return nodebuildersave; } set { nodebuildersave = value; } }
-		public string NodebuilderTest { get { return nodebuildertest; } set { nodebuildertest = value; } }
-		public DataLocationList Resources { get { return resources; } }
-		public string TestProgram { get { return testprogram; } set { testprogram = value; } }
-		public string TestParameters { get { return testparameters; } set { testparameters = value; } }
-		public bool TestShortPaths { get { return testshortpaths; } set { testshortpaths = value; } }
-		public int TestSkill { get { return testskill; } set { testskill = value; } }
-		public bool CustomParameters { get { return customparameters; } set { customparameters = value; } }
+		public string NodebuilderSave { get { return nodebuildersave; } internal set { nodebuildersave = value; } }
+		public string NodebuilderTest { get { return nodebuildertest; } internal set { nodebuildertest = value; } }
+		internal DataLocationList Resources { get { return resources; } }
+		public string TestProgram { get { return testprogram; } internal set { testprogram = value; } }
+		public string TestParameters { get { return testparameters; } internal set { testparameters = value; } }
+		public bool TestShortPaths { get { return testshortpaths; } internal set { testshortpaths = value; } }
+		public int TestSkill { get { return testskill; } internal set { testskill = value; } }
+		public bool CustomParameters { get { return customparameters; } internal set { customparameters = value; } }
 		internal ICollection<ThingsFilter> ThingsFilters { get { return thingsfilters; } }
-		public List<DefinedTextureSet> TextureSets { get { return texturesets; } }
+		internal List<DefinedTextureSet> TextureSets { get { return texturesets; } }
 		internal Dictionary<string, bool> EditModes { get { return editmodes; } }
 		public string StartMode { get { return startmode; } internal set { startmode = value; } }
 		
@@ -87,7 +87,7 @@ namespace CodeImp.DoomBuilder.Config
 		#region ================== Constructor / Disposer
 
 		// Constructor
-		public ConfigurationInfo(Configuration cfg, string filename)
+		internal ConfigurationInfo(Configuration cfg, string filename)
 		{
 			// Initialize
 			this.filename = filename;
@@ -145,6 +145,14 @@ namespace CodeImp.DoomBuilder.Config
 
 		#region ================== Methods
 
+		/// <summary>
+		/// This returns the resource locations as configured.
+		/// </summary>
+		public DataLocationList GetResources()
+		{
+			return new DataLocationList(resources);
+		}
+
 		// This compares it to other ConfigurationInfo objects
 		public int CompareTo(ConfigurationInfo other)
 		{
@@ -153,7 +161,7 @@ namespace CodeImp.DoomBuilder.Config
 		}
 
 		// This saves the settings to program configuration
-		public void SaveSettings()
+		internal void SaveSettings()
 		{
 			// Write to configuration
 			General.Settings.WriteSetting("configurations." + settingskey + ".nodebuildersave", nodebuildersave);
@@ -203,7 +211,7 @@ namespace CodeImp.DoomBuilder.Config
 		}
 
 		// This clones the object
-		public ConfigurationInfo Clone()
+		internal ConfigurationInfo Clone()
 		{
 			ConfigurationInfo ci = new ConfigurationInfo();
 			ci.name = this.name;
@@ -228,7 +236,7 @@ namespace CodeImp.DoomBuilder.Config
 		}
 		
 		// This applies settings from an object
-		public void Apply(ConfigurationInfo ci)
+		internal void Apply(ConfigurationInfo ci)
 		{
 			this.name = ci.name;
 			this.filename = ci.filename;
@@ -251,7 +259,7 @@ namespace CodeImp.DoomBuilder.Config
 		}
 		
 		// This applies the defaults
-		public void ApplyDefaults(GameConfiguration gameconfig)
+		internal void ApplyDefaults(GameConfiguration gameconfig)
 		{
 			// Some of the defaults can only be applied from game configuration
 			if(gameconfig != null)
diff --git a/Source/Core/Config/ThingTypeInfo.cs b/Source/Core/Config/ThingTypeInfo.cs
index 629b93290d1b521d15e2899275233bc2576c9eef..94375425356aad8309d10adc7e6989229bf10ed0 100644
--- a/Source/Core/Config/ThingTypeInfo.cs
+++ b/Source/Core/Config/ThingTypeInfo.cs
@@ -43,7 +43,7 @@ namespace CodeImp.DoomBuilder.Config
 		public const int THING_BLOCKING_HEIGHT = 2;
 		public const int THING_ERROR_NONE = 0;
 		public const int THING_ERROR_INSIDE = 1;
-		public const int THING_ERROR_INSIDE_STUCKED = 2;
+		public const int THING_ERROR_INSIDE_STUCK = 2;
 		
 		#endregion
 
diff --git a/Source/Core/Controls/ScriptEditorControl.cs b/Source/Core/Controls/ScriptEditorControl.cs
index 0452960f2d57ec9be7c40872260406182e4c006d..32d9c55b10ad474b125a1454d3663c6f9d149e7f 100644
--- a/Source/Core/Controls/ScriptEditorControl.cs
+++ b/Source/Core/Controls/ScriptEditorControl.cs
@@ -364,7 +364,10 @@ namespace CodeImp.DoomBuilder.Controls
 					autocompletelist.Add(k.ToUpperInvariant(), k + "?" + imageindex.ToString(CultureInfo.InvariantCulture));
 				}
 				string words = keywordslist.ToString();
-				scriptedit.KeyWords(keywordsindex, words.ToLowerInvariant());
+				if(scriptconfig.CaseSensitive)
+					scriptedit.KeyWords(keywordsindex, words);
+				else
+					scriptedit.KeyWords(keywordsindex, words.ToLowerInvariant());
 			}
 
 			// Create the constants list and apply it
@@ -380,7 +383,10 @@ namespace CodeImp.DoomBuilder.Controls
 					autocompletelist.Add(c.ToUpperInvariant(), c + "?" + imageindex.ToString(CultureInfo.InvariantCulture));
 				}
 				string words = constantslist.ToString();
-				scriptedit.KeyWords(constantsindex, words.ToLowerInvariant());
+				if(scriptconfig.CaseSensitive)
+					scriptedit.KeyWords(constantsindex, words);
+				else
+					scriptedit.KeyWords(constantsindex, words.ToLowerInvariant());
 			}
 			
 			// Sort the autocomplete list
diff --git a/Source/Core/Data/BitmapImage.cs b/Source/Core/Data/BitmapImage.cs
new file mode 100644
index 0000000000000000000000000000000000000000..da669349b4d289ebfacc82b10a1a05a5d204331f
--- /dev/null
+++ b/Source/Core/Data/BitmapImage.cs
@@ -0,0 +1,86 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Imaging;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.IO;
+using System.IO;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Data
+{
+	public class BitmapImage : ImageData
+	{
+		#region ================== Variables
+
+		// Image source
+		private Bitmap img;
+
+		#endregion
+
+		#region ================== Constructor / Disposer
+
+		// Constructor
+		public BitmapImage(Bitmap img, string name)
+		{
+			// Initialize
+			this.img = img;
+			this.AllowUnload = false;
+			SetName(name);
+
+			// Get width and height from image
+			width = img.Size.Width;
+			height = img.Size.Height;
+			scale.x = 1.0f;
+			scale.y = 1.0f;
+
+			// We have no destructor
+			GC.SuppressFinalize(this);
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// This loads the image
+		protected override void LocalLoadImage()
+		{
+			lock(this)
+			{
+				// No failure checking here. I anything fails here, it is not the user's fault,
+				// because the resources this loads are in the assembly.
+
+				// Get resource from memory
+				bitmap = img;
+
+				// Pass on to base
+				base.LocalLoadImage();
+			}
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index 85fe3f1bc5794553dbdf542750651a9eeb12e10c..c7060c0f2d3745d4c894cbabdadd65a9257b535f 100644
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -1298,7 +1298,7 @@ namespace CodeImp.DoomBuilder.Data
 										if(c.Name.ToLowerInvariant() == catname) cat = c;
 									}
 								}
-								
+
 								// Make the category if needed
 								if(cat == null)
 								{
@@ -1379,7 +1379,7 @@ namespace CodeImp.DoomBuilder.Data
             General.MainWindow.DisplayStatus(StatusType.Busy, "Loading models...");
 
             foreach (Thing t in General.Map.Map.Things)
-                LoadModelForThing(t);
+                t.IsModel = LoadModelForThing(t);
 
             General.MainWindow.RedrawDisplay();
         }
@@ -1550,6 +1550,9 @@ namespace CodeImp.DoomBuilder.Data
             GldefsParser parser = new GldefsParser();
             parser.OnInclude = loadGldefsFromLocation;
 
+            //dbg
+            //GZBuilder.GZGeneral.Trace("Base game is " + General.Map.Config.GameType);
+
             //load default GZDoom gldefs for current game
             if (loadDefaultDefinitions && General.Map.Config.GameType != GameType.UNKNOWN) {
                 string defaultGldefsPath = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)General.Map.Config.GameType].ToLowerInvariant() + ".txt";
@@ -1591,9 +1594,8 @@ namespace CodeImp.DoomBuilder.Data
             }
 
             //dbg
-            GZBuilder.GZGeneral.Trace("******************************************");
+            /*GZBuilder.GZGeneral.Trace("******************************************");
             foreach (KeyValuePair<int, GZDoomLight> group in gldefsEntries) {
-                if (group.Key == 2015) {
                     GZBuilder.GZGeneral.Trace("----------------------------------------");
                     GZBuilder.GZGeneral.Trace("gldefsEntry for id " + group.Key + ":");
                     GZBuilder.GZGeneral.Trace("Color: " + group.Value.Color.Red + "," + group.Value.Color.Green + "," + group.Value.Color.Blue);
@@ -1607,8 +1609,7 @@ namespace CodeImp.DoomBuilder.Data
 
                     GZBuilder.GZGeneral.Trace("Subtractive: " + group.Value.Subtractive);
                     GZBuilder.GZGeneral.Trace("DontLightSelf: " + group.Value.DontLightSelf);
-                }
-            }
+            }*/
         }
 
         //mxd. This loads (Z)MAPINFO
@@ -1667,7 +1668,7 @@ namespace CodeImp.DoomBuilder.Data
 
         // This finds the first IWAD resource
 		// Returns false when not found
-		internal bool FindFirstIWAD(out DataLocation result)
+		public bool FindFirstIWAD(out DataLocation result)
 		{
 			// Go for all data containers
 			foreach(DataReader dr in containers)
diff --git a/Source/Core/Data/DynamicBitmapImage.cs b/Source/Core/Data/DynamicBitmapImage.cs
new file mode 100644
index 0000000000000000000000000000000000000000..26eee10d78a9921728b2504744e6d47a2bf65d10
--- /dev/null
+++ b/Source/Core/Data/DynamicBitmapImage.cs
@@ -0,0 +1,82 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Imaging;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.IO;
+using System.IO;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Data
+{
+	public class DynamicBitmapImage : BitmapImage, ID3DResource
+	{
+		#region ================== Variables
+
+		// Image source
+		private Bitmap img;
+
+		#endregion
+
+		#region ================== Constructor / Disposer
+
+		// Constructor
+		public DynamicBitmapImage(Bitmap img, string name) : base(img, name)
+		{
+			// Initialize
+			this.UseColorCorrection = false;
+			this.dynamictexture = true;
+
+			// This resource is volatile
+			General.Map.Graphics.RegisterResource(this);
+		}
+
+		// Disposer
+		public override void Dispose()
+		{
+			General.Map.Graphics.UnregisterResource(this);
+			base.Dispose();
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// Unload the resource because Direct3D says so
+		public void UnloadResource()
+		{
+			ReleaseTexture();
+		}
+
+		// Reload the resource
+		public void ReloadResource()
+		{
+			CreateTexture();
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Core/Data/ImageData.cs b/Source/Core/Data/ImageData.cs
index a3cb00e601078edc2c64658103cb9efeb9151370..aff902e76a3a870aa2a620b66dedb785f4c3d116 100644
--- a/Source/Core/Data/ImageData.cs
+++ b/Source/Core/Data/ImageData.cs
@@ -24,6 +24,7 @@ using System.Globalization;
 using System.Text;
 using System.Drawing;
 using CodeImp.DoomBuilder.Geometry;
+using SlimDX;
 using SlimDX.Direct3D9;
 using System.Drawing.Imaging;
 using CodeImp.DoomBuilder.Rendering;
@@ -70,6 +71,7 @@ namespace CodeImp.DoomBuilder.Data
 		
 		// Direct3D texture
 		private int mipmaplevels = 0;	// 0 = all mipmaps
+		protected bool dynamictexture;
 		private Texture texture;
 		
 		// Disposing
@@ -235,6 +237,9 @@ namespace CodeImp.DoomBuilder.Data
 					// Bitmap has incorrect format?
 					if(bitmap.PixelFormat != PixelFormat.Format32bppArgb)
 					{
+						if(dynamictexture)
+							throw new Exception("Dynamic images must be in 32 bits ARGB format.");
+						
 						//General.ErrorLogger.Add(ErrorType.Warning, "Image '" + name + "' does not have A8R8G8B8 pixel format. Conversion was needed.");
 						Bitmap oldbitmap = bitmap;
 						try
@@ -296,6 +301,12 @@ namespace CodeImp.DoomBuilder.Data
 					width = bitmap.Size.Width;
 					height = bitmap.Size.Height;
 
+					if(dynamictexture)
+					{
+						if((width != General.NextPowerOf2(width)) || (height != General.NextPowerOf2(height)))
+							throw new Exception("Dynamic images must have a size in powers of 2.");
+					}
+
 					// Do we still have to set a scale?
 					if((scale.x == 0.0f) && (scale.y == 0.0f))
 					{
@@ -334,10 +345,63 @@ namespace CodeImp.DoomBuilder.Data
 					memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096);
 					img.Save(memstream, ImageFormat.Bmp);
 					memstream.Seek(0, SeekOrigin.Begin);
-					texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
-									img.Size.Width, img.Size.Height, mipmaplevels, Usage.None, Format.Unknown,
-									Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
+					if(dynamictexture)
+					{
+						texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
+										img.Size.Width, img.Size.Height, mipmaplevels, Usage.Dynamic, Format.A8R8G8B8,
+										Pool.Default, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
+					}
+					else
+					{
+						texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
+										img.Size.Width, img.Size.Height, mipmaplevels, Usage.None, Format.Unknown,
+										Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
+					}
 					memstream.Dispose();
+					
+					if(dynamictexture)
+					{
+						if((width != texture.GetLevelDescription(0).Width) || (height != texture.GetLevelDescription(0).Height))
+							throw new Exception("Could not create a texture with the same size as the image.");
+					}
+				}
+			}
+		}
+
+		// This updates a dynamic texture
+		public void UpdateTexture()
+		{
+			if(!dynamictexture)
+				throw new Exception("The image must be a dynamic image to support direct updating.");
+			
+			lock(this)
+			{
+				if((texture != null) && !texture.Disposed)
+				{
+					// Lock the bitmap and texture
+					BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+					DataRectangle texdata = texture.LockRectangle(0, LockFlags.Discard);
+
+					// Copy data
+					int* bp = (int*)bmpdata.Scan0.ToPointer();
+					int* tp = (int*)texdata.Data.DataPointer.ToPointer();
+					for(int y = 0; y < bmpdata.Height; y++)
+					{
+						for(int x = 0; x < bmpdata.Width; x++)
+						{
+							*tp = *bp;
+							bp++;
+							tp++;
+						}
+
+						// Skip extra data in texture
+						int extrapitch = (texdata.Pitch >> 2) - bmpdata.Width;
+						tp += extrapitch;
+					}
+
+					// Unlock
+					texture.UnlockRectangle(0);
+					bitmap.UnlockBits(bmpdata);
 				}
 			}
 		}
diff --git a/Source/Core/Data/ImageDataFormat.cs b/Source/Core/Data/ImageDataFormat.cs
index 5bfcc358b8ee819f6b24db29e1be4c16c61fd24b..6587d0645ca5e62da327c15a85ca7ca32cbc59e8 100644
--- a/Source/Core/Data/ImageDataFormat.cs
+++ b/Source/Core/Data/ImageDataFormat.cs
@@ -41,6 +41,7 @@ namespace CodeImp.DoomBuilder.Data
 		private static readonly int[] PNG_SIGNATURE = new int[] { 137, 80, 78, 71, 13, 10, 26, 10 };
 		private static readonly int[] GIF_SIGNATURE = new int[] { 71, 73, 70 };
 		private static readonly int[] BMP_SIGNATURE = new int[] { 66, 77 };
+		private static readonly int[] DDS_SIGNATURE = new int[] { 68, 68, 83, 32 };
 
 		// This check image data and returns the appropriate image reader
 		public static IImageReader GetImageReader(Stream data, int guessformat, Playpal palette)
@@ -59,7 +60,11 @@ namespace CodeImp.DoomBuilder.Data
 				// Check for PNG signature
 				data.Seek(0, SeekOrigin.Begin);
 				if(CheckSignature(data, PNG_SIGNATURE)) return new FileImageReader();
-				
+
+				// Check for DDS signature
+				data.Seek(0, SeekOrigin.Begin);
+				if(CheckSignature(data, DDS_SIGNATURE)) return new FileImageReader();
+
 				// Check for GIF signature
 				data.Seek(0, SeekOrigin.Begin);
 				if(CheckSignature(data, GIF_SIGNATURE)) return new FileImageReader();
diff --git a/Source/Core/Data/ResourceImage.cs b/Source/Core/Data/ResourceImage.cs
index efb71fed08347964611b299c08a62c4c0fc42b9f..47d36d60b00ef7c0b55b49466b68682c4bb01f85 100644
--- a/Source/Core/Data/ResourceImage.cs
+++ b/Source/Core/Data/ResourceImage.cs
@@ -50,6 +50,7 @@ namespace CodeImp.DoomBuilder.Data
 			// Initialize
 			this.assembly = Assembly.GetCallingAssembly();
 			this.resourcename = resourcename;
+			this.AllowUnload = false;
 			SetName(resourcename);
 
 			// Temporarily load resource from memory
diff --git a/Source/Core/GZBuilder/GZDoom/GldefsParser.cs b/Source/Core/GZBuilder/GZDoom/GldefsParser.cs
index 711d8b7bab3233f0b8a268bb92b849ce4fe5bf7a..6273c52b3dbc933e5667f0cc52bd41ea6c95c696 100644
--- a/Source/Core/GZBuilder/GZDoom/GldefsParser.cs
+++ b/Source/Core/GZBuilder/GZDoom/GldefsParser.cs
@@ -154,7 +154,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                                         token = StripTokenQuotes(ReadToken());
                                         if (!ReadSignedFloat(token, ref light.Offset.Z)) {
                                             // Not numeric!
-                                            GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
+                                            GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'");
                                             gotErrors = true;
                                             break;
                                         }
@@ -164,7 +164,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                                         token = StripTokenQuotes(ReadToken());
                                         if (!ReadSignedFloat(token, ref light.Offset.Y)) {
                                             // Not numeric!
-                                            GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
+                                            GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'");
                                             gotErrors = true;
                                             break;
                                         }
@@ -275,7 +275,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                                                 break;
                                             }
 
-                                            if (scale < 0.0f || scale > 1.0f) {
+                                            if (scale > 1.0f) {
                                                 GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + scale);
                                                 gotErrors = true;
                                                 break;
@@ -315,8 +315,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                                             }
 
                                             //offset it slightly to avoid shading glitches
-                                            if (light.Offset.Y == 0)
-                                                light.Offset.Y = 0.1f;
+                                            if (light.Offset.Z == 0.0f)
+                                                light.Offset.Z = 0.1f;
 
                                             if (!gotErrors) {
                                                 if (lightsByName.ContainsKey(lightName)) {
diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs
index e7efe80a2ce3da61d373553a747ddf9bd913e633..c10061af88b71ac9fbdd628822062a4ec65b2e6b 100644
--- a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs
+++ b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs
@@ -40,10 +40,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                         string className = StripTokenQuotes(ReadToken()).ToLowerInvariant();
 
                         if (!string.IsNullOrEmpty(className)) {
-                            if (classNames.IndexOf(className) != -1) {
+                            if (classNames.IndexOf(className) != -1)
                                 continue; //already got this class; continue to next one
-                            }
-                            classNames.Add(className);
 
                             //now find opening brace
                             SkipWhitespace(true);
diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs
index cc161e246bf5c7b5f0b670997dc850325f0958be..40e17ec82b88bf61cd743a8d2b6cfc3e575f9aa4 100644
--- a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs
+++ b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs
@@ -11,7 +11,7 @@ using CodeImp.DoomBuilder.GZBuilder.Data;
 
 namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
     public sealed class ModeldefStructure {
-        private const int MAX_MODELS = 3; //maximum models per modeldef entry, zero-based
+        private const int MAX_MODELS = 4; //maximum models per modeldef entry, zero-based
 
         public ModeldefEntry Parse(ModeldefParser parser) {
             string[] textureNames = new string[4];
@@ -52,7 +52,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                             break;
                         }
 
-                        if (modelIndex > MAX_MODELS) {
+                        if (modelIndex >= MAX_MODELS) {
                             GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " per MODELDEF entry!");
                             break;
                         }
@@ -90,7 +90,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                             break;
                         }
 
-                        if (skinIndex > MAX_MODELS) {
+                        if (skinIndex >= MAX_MODELS) {
                             GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " per MODELDEF entry!");
                             break;
                         }
@@ -217,7 +217,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
                                         break;
                                     }
 
-                                    if (modelIndex > MAX_MODELS) {
+                                    if (modelIndex >= MAX_MODELS) {
                                         GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " per MODELDEF entry!");
                                         gotErrors = true;
                                         break;
diff --git a/Source/Core/GZBuilder/GZGeneral.cs b/Source/Core/GZBuilder/GZGeneral.cs
index d339cb6154231275d8687511487a7c2f34ad69c7..ce94104af20a702a4fb7a4271a03bead70d8fee8 100644
--- a/Source/Core/GZBuilder/GZGeneral.cs
+++ b/Source/Core/GZBuilder/GZGeneral.cs
@@ -76,6 +76,9 @@ namespace CodeImp.DoomBuilder.GZBuilder
         public static void OnMapOpenEnd() {
             UDMF = (General.Map.Config.FormatInterface == "UniversalMapSetIO");
             General.MainWindow.UpdateGZDoomPannel();
+
+            //dbg
+            //GZBuilder.GZGeneral.Trace("GameConfiguration: loaded gametype " + General.Map.Config.GameType);
         }
 
         public static void OnReloadResources() {
diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs
index 39e50b1e274eb03a09801b32a2480b4d8dfb1a4a..8d5ae3447f4cb9ecf4800189ead314fdd3b8af7f 100644
--- a/Source/Core/General/General.cs
+++ b/Source/Core/General/General.cs
@@ -48,6 +48,9 @@ namespace CodeImp.DoomBuilder
 	{
 		#region ================== API Declarations
 
+		[DllImport("devil.dll")]
+		private static extern void ilInit();
+
 		[DllImport("user32.dll")]
 		internal static extern bool LockWindowUpdate(IntPtr hwnd);
 
@@ -602,6 +605,7 @@ namespace CodeImp.DoomBuilder
 
 				// Initialize static classes
 				MapSet.Initialize();
+				ilInit();
 
 				// Create main window
 				General.WriteLogLine("Loading main interface window...");
diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs
index 4ccf015f70e7d519776166ebb638dcb07cec2499..3a2e7d6fb3e13ae648e18d7699ad98ab41bf2fca 100644
--- a/Source/Core/General/MapManager.cs
+++ b/Source/Core/General/MapManager.cs
@@ -107,7 +107,7 @@ namespace CodeImp.DoomBuilder
 		internal Renderer2D CRenderer2D { get { return renderer2d; } }
 		internal Renderer3D CRenderer3D { get { return renderer3d; } }
 		public GameConfiguration Config { get { return config; } }
-		internal ConfigurationInfo ConfigSettings { get { return configinfo; } }
+		public ConfigurationInfo ConfigSettings { get { return configinfo; } }
 		public GridSetup Grid { get { return grid; } }
 		public UndoManager UndoRedo { get { return undoredo; } }
 		internal CopyPasteManager CopyPaste { get { return copypaste; } }
@@ -441,6 +441,14 @@ namespace CodeImp.DoomBuilder
 
 		#region ================== Save
 
+		/// <summary>
+		/// This exports the structures from memory into a WAD file with the current map format.
+		/// </summary>
+		public bool ExportToFile(string filepathname)
+		{
+			return SaveMap(filepathname, SavePurpose.Testing);
+		}
+
 		// Initializes for an existing map
 		internal bool SaveMap(string newfilepathname, SavePurpose purpose)
 		{
diff --git a/Source/Core/IO/FileImageReader.cs b/Source/Core/IO/FileImageReader.cs
index df6dd504bf07e5a682abf0eb2a7053423c15b2a5..85b22abb3d25ecbc0df700553756bb492af19478 100644
--- a/Source/Core/IO/FileImageReader.cs
+++ b/Source/Core/IO/FileImageReader.cs
@@ -20,6 +20,7 @@ using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Globalization;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.IO;
 using CodeImp.DoomBuilder.Map;
@@ -35,6 +36,305 @@ namespace CodeImp.DoomBuilder.IO
 {
 	internal unsafe class FileImageReader : IImageReader
 	{
+		#region ================== APIs
+
+		[DllImport("devil.dll")]
+		private static extern void ilGenImages(int num, IntPtr images);
+
+		[DllImport("devil.dll")]
+		private static extern void ilBindImage(uint image);
+
+		[DllImport("devil.dll")]
+		private static extern void ilDeleteImages(int num, IntPtr images);
+
+		[DllImport("devil.dll")]
+		private static extern bool ilLoadL(uint type, IntPtr lump, uint size);
+
+		[DllImport("devil.dll")]
+		private static extern int ilGetInteger(uint mode);
+
+		[DllImport("devil.dll")]
+		private static extern int ilConvertImage(uint destformat, uint desttype);
+
+		[DllImport("devil.dll")]
+		private static extern uint ilCopyPixels(uint xoff, uint yoff, uint zoff, uint width, uint height, uint depth, uint format, uint type, IntPtr data);
+		
+		//  Matches OpenGL's right now.
+		//! Data formats \link Formats Formats\endlink
+		private const int IL_COLOUR_INDEX     = 0x1900;
+		private const int IL_COLOR_INDEX      = 0x1900;
+		private const int IL_ALPHA			= 0x1906;
+		private const int IL_RGB              = 0x1907;
+		private const int IL_RGBA             = 0x1908;
+		private const int IL_BGR              = 0x80E0;
+		private const int IL_BGRA             = 0x80E1;
+		private const int IL_LUMINANCE        = 0x1909;
+		private const int IL_LUMINANCE_ALPHA  = 0x190A;
+
+		//! Data types \link Types Types\endlink
+		private const int IL_BYTE           = 0x1400;
+		private const int IL_UNSIGNED_BYTE  = 0x1401;
+		private const int IL_SHORT          = 0x1402;
+		private const int IL_UNSIGNED_SHORT = 0x1403;
+		private const int IL_INT            = 0x1404;
+		private const int IL_UNSIGNED_INT   = 0x1405;
+		private const int IL_FLOAT          = 0x1406;
+		private const int IL_DOUBLE         = 0x140A;
+		private const int IL_HALF           = 0x140B;
+		
+		// Image types
+		private const int IL_TYPE_UNKNOWN = 0x0000;
+		private const int IL_BMP          = 0x0420;  //!< Microsoft Windows Bitmap - .bmp extension
+		private const int IL_CUT          = 0x0421;  //!< Dr. Halo - .cut extension
+		private const int IL_DOOM         = 0x0422;  //!< DooM walls - no specific extension
+		private const int IL_DOOM_FLAT    = 0x0423;  //!< DooM flats - no specific extension
+		private const int IL_ICO          = 0x0424;  //!< Microsoft Windows Icons and Cursors - .ico and .cur extensions
+		private const int IL_JPG          = 0x0425;  //!< JPEG - .jpg, .jpe and .jpeg extensions
+		private const int IL_JFIF         = 0x0425;  //!<
+		private const int IL_ILBM         = 0x0426;  //!< Amiga IFF (FORM ILBM) - .iff, .ilbm, .lbm extensions
+		private const int IL_PCD          = 0x0427;  //!< Kodak PhotoCD - .pcd extension
+		private const int IL_PCX          = 0x0428;  //!< ZSoft PCX - .pcx extension
+		private const int IL_PIC          = 0x0429;  //!< PIC - .pic extension
+		private const int IL_PNG          = 0x042A;  //!< Portable Network Graphics - .png extension
+		private const int IL_PNM          = 0x042B;  //!< Portable Any Map - .pbm, .pgm, .ppm and .pnm extensions
+		private const int IL_SGI          = 0x042C;  //!< Silicon Graphics - .sgi, .bw, .rgb and .rgba extensions
+		private const int IL_TGA          = 0x042D;  //!< TrueVision Targa File - .tga, .vda, .icb and .vst extensions
+		private const int IL_TIF          = 0x042E;  //!< Tagged Image File Format - .tif and .tiff extensions
+		private const int IL_CHEAD        = 0x042F;  //!< C-Style Header - .h extension
+		private const int IL_RAW          = 0x0430;  //!< Raw Image Data - any extension
+		private const int IL_MDL          = 0x0431;  //!< Half-Life Model Texture - .mdl extension
+		private const int IL_WAL          = 0x0432;  //!< Quake 2 Texture - .wal extension
+		private const int IL_LIF          = 0x0434;  //!< Homeworld Texture - .lif extension
+		private const int IL_MNG          = 0x0435;  //!< Multiple-image Network Graphics - .mng extension
+		private const int IL_JNG          = 0x0435;  //!< 
+		private const int IL_GIF          = 0x0436;  //!< Graphics Interchange Format - .gif extension
+		private const int IL_DDS          = 0x0437;  //!< DirectDraw Surface - .dds extension
+		private const int IL_DCX          = 0x0438;  //!< ZSoft Multi-PCX - .dcx extension
+		private const int IL_PSD          = 0x0439;  //!< Adobe PhotoShop - .psd extension
+		private const int IL_EXIF         = 0x043A;  //!< 
+		private const int IL_PSP          = 0x043B;  //!< PaintShop Pro - .psp extension
+		private const int IL_PIX          = 0x043C;  //!< PIX - .pix extension
+		private const int IL_PXR          = 0x043D;  //!< Pixar - .pxr extension
+		private const int IL_XPM          = 0x043E;  //!< X Pixel Map - .xpm extension
+		private const int IL_HDR          = 0x043F;  //!< Radiance High Dynamic Range - .hdr extension
+		private const int IL_ICNS			= 0x0440;  //!< Macintosh Icon - .icns extension
+		private const int IL_JP2			= 0x0441;  //!< Jpeg 2000 - .jp2 extension
+		private const int IL_EXR			= 0x0442;  //!< OpenEXR - .exr extension
+		private const int IL_WDP			= 0x0443;  //!< Microsoft HD Photo - .wdp and .hdp extension
+		private const int IL_VTF			= 0x0444;  //!< Valve Texture Format - .vtf extension
+		private const int IL_WBMP			= 0x0445;  //!< Wireless Bitmap - .wbmp extension
+		private const int IL_SUN			= 0x0446;  //!< Sun Raster - .sun, .ras, .rs, .im1, .im8, .im24 and .im32 extensions
+		private const int IL_IFF			= 0x0447;  //!< Interchange File Format - .iff extension
+		private const int IL_TPL			= 0x0448;  //!< Gamecube Texture - .tpl extension
+		private const int IL_FITS			= 0x0449;  //!< Flexible Image Transport System - .fit and .fits extensions
+		private const int IL_DICOM		= 0x044A;  //!< Digital Imaging and Communications in Medicine (DICOM) - .dcm and .dicom extensions
+		private const int IL_IWI			= 0x044B;  //!< Call of Duty Infinity Ward Image - .iwi extension
+		private const int IL_BLP			= 0x044C;  //!< Blizzard Texture Format - .blp extension
+		private const int IL_FTX			= 0x044D;  //!< Heavy Metal: FAKK2 Texture - .ftx extension
+		private const int IL_ROT			= 0x044E;  //!< Homeworld 2 - Relic Texture - .rot extension
+		private const int IL_TEXTURE		= 0x044F;  //!< Medieval II: Total War Texture - .texture extension
+		private const int IL_DPX			= 0x0450;  //!< Digital Picture Exchange - .dpx extension
+		private const int IL_UTX			= 0x0451;  //!< Unreal (and Unreal Tournament) Texture - .utx extension
+		private const int IL_MP3			= 0x0452;  //!< MPEG-1 Audio Layer 3 - .mp3 extension
+
+
+		private const int IL_JASC_PAL     = 0x0475;  //!< PaintShop Pro Palette
+
+
+		// Error Types
+		private const int IL_NO_ERROR             = 0x0000;
+		private const int IL_INVALID_ENUM         = 0x0501;
+		private const int IL_OUT_OF_MEMORY        = 0x0502;
+		private const int IL_FORMAT_NOT_SUPPORTED = 0x0503;
+		private const int IL_INTERNAL_ERROR       = 0x0504;
+		private const int IL_INVALID_VALUE        = 0x0505;
+		private const int IL_ILLEGAL_OPERATION    = 0x0506;
+		private const int IL_ILLEGAL_FILE_VALUE   = 0x0507;
+		private const int IL_INVALID_FILE_HEADER  = 0x0508;
+		private const int IL_INVALID_PARAM        = 0x0509;
+		private const int IL_COULD_NOT_OPEN_FILE  = 0x050A;
+		private const int IL_INVALID_EXTENSION    = 0x050B;
+		private const int IL_FILE_ALREADY_EXISTS  = 0x050C;
+		private const int IL_OUT_FORMAT_SAME      = 0x050D;
+		private const int IL_STACK_OVERFLOW       = 0x050E;
+		private const int IL_STACK_UNDERFLOW      = 0x050F;
+		private const int IL_INVALID_CONVERSION   = 0x0510;
+		private const int IL_BAD_DIMENSIONS       = 0x0511;
+		private const int IL_FILE_READ_ERROR      = 0x0512;  // 05/12/2002: Addition by Sam.
+		private const int IL_FILE_WRITE_ERROR     = 0x0512;
+
+		private const int IL_LIB_GIF_ERROR  = 0x05E1;
+		private const int IL_LIB_JPEG_ERROR = 0x05E2;
+		private const int IL_LIB_PNG_ERROR  = 0x05E3;
+		private const int IL_LIB_TIFF_ERROR = 0x05E4;
+		private const int IL_LIB_MNG_ERROR  = 0x05E5;
+		private const int IL_LIB_JP2_ERROR  = 0x05E6;
+		private const int IL_LIB_EXR_ERROR  = 0x05E7;
+		private const int IL_UNKNOWN_ERROR  = 0x05FF;
+
+
+		// Origin Definitions
+		private const int IL_ORIGIN_SET        = 0x0600;
+		private const int IL_ORIGIN_LOWER_LEFT = 0x0601;
+		private const int IL_ORIGIN_UPPER_LEFT = 0x0602;
+		private const int IL_ORIGIN_MODE       = 0x0603;
+
+
+		// Format and Type Mode Definitions
+		private const int IL_FORMAT_SET  = 0x0610;
+		private const int IL_FORMAT_MODE = 0x0611;
+		private const int IL_TYPE_SET    = 0x0612;
+		private const int IL_TYPE_MODE   = 0x0613;
+
+
+		// File definitions
+		private const int IL_FILE_OVERWRITE	= 0x0620;
+		private const int IL_FILE_MODE		= 0x0621;
+
+
+		// Palette definitions
+		private const int IL_CONV_PAL			= 0x0630;
+
+
+		// Load fail definitions
+		private const int IL_DEFAULT_ON_FAIL	= 0x0632;
+
+
+		// Key colour and alpha definitions
+		private const int IL_USE_KEY_COLOUR	= 0x0635;
+		private const int IL_USE_KEY_COLOR	= 0x0635;
+		private const int IL_BLIT_BLEND		= 0x0636;
+
+
+		// Interlace definitions
+		private const int IL_SAVE_INTERLACED	= 0x0639;
+		private const int IL_INTERLACE_MODE	= 0x063A;
+
+
+		// Quantization definitions
+		private const int IL_QUANTIZATION_MODE = 0x0640;
+		private const int IL_WU_QUANT          = 0x0641;
+		private const int IL_NEU_QUANT         = 0x0642;
+		private const int IL_NEU_QUANT_SAMPLE  = 0x0643;
+		private const int IL_MAX_QUANT_INDEXS  = 0x0644; //XIX : ILint : Maximum number of colors to reduce to, default of 256. and has a range of 2-256
+		private const int IL_MAX_QUANT_INDICES = 0x0644; // Redefined, since the above private const int is misspelled
+
+
+		// Hints
+		private const int IL_FASTEST          = 0x0660;
+		private const int IL_LESS_MEM         = 0x0661;
+		private const int IL_DONT_CARE        = 0x0662;
+		private const int IL_MEM_SPEED_HINT   = 0x0665;
+		private const int IL_USE_COMPRESSION  = 0x0666;
+		private const int IL_NO_COMPRESSION   = 0x0667;
+		private const int IL_COMPRESSION_HINT = 0x0668;
+
+
+		// Compression
+		private const int IL_NVIDIA_COMPRESS	= 0x0670;
+		private const int IL_SQUISH_COMPRESS	= 0x0671;
+
+
+		// Subimage types
+		private const int IL_SUB_NEXT   = 0x0680;
+		private const int IL_SUB_MIPMAP = 0x0681;
+		private const int IL_SUB_LAYER  = 0x0682;
+		
+
+		// Compression definitions
+		private const int IL_COMPRESS_MODE = 0x0700;
+		private const int IL_COMPRESS_NONE = 0x0701;
+		private const int IL_COMPRESS_RLE  = 0x0702;
+		private const int IL_COMPRESS_LZO  = 0x0703;
+		private const int IL_COMPRESS_ZLIB = 0x0704;
+
+
+		// File format-specific values
+		private const int IL_TGA_CREATE_STAMP        = 0x0710;
+		private const int IL_JPG_QUALITY             = 0x0711;
+		private const int IL_PNG_INTERLACE           = 0x0712;
+		private const int IL_TGA_RLE                 = 0x0713;
+		private const int IL_BMP_RLE                 = 0x0714;
+		private const int IL_SGI_RLE                 = 0x0715;
+		private const int IL_TGA_ID_STRING           = 0x0717;
+		private const int IL_TGA_AUTHNAME_STRING     = 0x0718;
+		private const int IL_TGA_AUTHCOMMENT_STRING  = 0x0719;
+		private const int IL_PNG_AUTHNAME_STRING     = 0x071A;
+		private const int IL_PNG_TITLE_STRING        = 0x071B;
+		private const int IL_PNG_DESCRIPTION_STRING  = 0x071C;
+		private const int IL_TIF_DESCRIPTION_STRING  = 0x071D;
+		private const int IL_TIF_HOSTCOMPUTER_STRING = 0x071E;
+		private const int IL_TIF_DOCUMENTNAME_STRING = 0x071F;
+		private const int IL_TIF_AUTHNAME_STRING     = 0x0720;
+		private const int IL_JPG_SAVE_FORMAT         = 0x0721;
+		private const int IL_CHEAD_HEADER_STRING     = 0x0722;
+		private const int IL_PCD_PICNUM              = 0x0723;
+		private const int IL_PNG_ALPHA_INDEX = 0x0724; //XIX : ILint : the color in the palette at this index value (0-255) is considered transparent, -1 for no trasparent color
+		private const int IL_JPG_PROGRESSIVE         = 0x0725;
+		private const int IL_VTF_COMP                = 0x0726;
+
+
+		// DXTC definitions
+		private const int IL_DXTC_FORMAT      = 0x0705;
+		private const int IL_DXT1             = 0x0706;
+		private const int IL_DXT2             = 0x0707;
+		private const int IL_DXT3             = 0x0708;
+		private const int IL_DXT4             = 0x0709;
+		private const int IL_DXT5             = 0x070A;
+		private const int IL_DXT_NO_COMP      = 0x070B;
+		private const int IL_KEEP_DXTC_DATA   = 0x070C;
+		private const int IL_DXTC_DATA_FORMAT = 0x070D;
+		private const int IL_3DC              = 0x070E;
+		private const int IL_RXGB             = 0x070F;
+		private const int IL_ATI1N            = 0x0710;
+		private const int IL_DXT1A            = 0x0711; // Normally the same as IL_DXT1, except for nVidia Texture Tools.
+
+		// Environment map definitions
+		private const int IL_CUBEMAP_POSITIVEX = 0x00000400;
+		private const int IL_CUBEMAP_NEGATIVEX = 0x00000800;
+		private const int IL_CUBEMAP_POSITIVEY = 0x00001000;
+		private const int IL_CUBEMAP_NEGATIVEY = 0x00002000;
+		private const int IL_CUBEMAP_POSITIVEZ = 0x00004000;
+		private const int IL_CUBEMAP_NEGATIVEZ = 0x00008000;
+		private const int IL_SPHEREMAP         = 0x00010000;
+
+
+		// Values
+		private const int IL_VERSION_NUM           = 0x0DE2;
+		private const int IL_IMAGE_WIDTH           = 0x0DE4;
+		private const int IL_IMAGE_HEIGHT          = 0x0DE5;
+		private const int IL_IMAGE_DEPTH           = 0x0DE6;
+		private const int IL_IMAGE_SIZE_OF_DATA    = 0x0DE7;
+		private const int IL_IMAGE_BPP             = 0x0DE8;
+		private const int IL_IMAGE_BYTES_PER_PIXEL = 0x0DE8;
+		private const int IL_IMAGE_BITS_PER_PIXEL  = 0x0DE9;
+		private const int IL_IMAGE_FORMAT          = 0x0DEA;
+		private const int IL_IMAGE_TYPE            = 0x0DEB;
+		private const int IL_PALETTE_TYPE          = 0x0DEC;
+		private const int IL_PALETTE_SIZE          = 0x0DED;
+		private const int IL_PALETTE_BPP           = 0x0DEE;
+		private const int IL_PALETTE_NUM_COLS      = 0x0DEF;
+		private const int IL_PALETTE_BASE_TYPE     = 0x0DF0;
+		private const int IL_NUM_FACES             = 0x0DE1;
+		private const int IL_NUM_IMAGES            = 0x0DF1;
+		private const int IL_NUM_MIPMAPS           = 0x0DF2;
+		private const int IL_NUM_LAYERS            = 0x0DF3;
+		private const int IL_ACTIVE_IMAGE          = 0x0DF4;
+		private const int IL_ACTIVE_MIPMAP         = 0x0DF5;
+		private const int IL_ACTIVE_LAYER          = 0x0DF6;
+		private const int IL_ACTIVE_FACE           = 0x0E00;
+		private const int IL_CUR_IMAGE             = 0x0DF7;
+		private const int IL_IMAGE_DURATION        = 0x0DF8;
+		private const int IL_IMAGE_PLANESIZE       = 0x0DF9;
+		private const int IL_IMAGE_BPC             = 0x0DFA;
+		private const int IL_IMAGE_OFFX            = 0x0DFB;
+		private const int IL_IMAGE_OFFY            = 0x0DFC;
+		private const int IL_IMAGE_CUBEFLAGS       = 0x0DFD;
+		private const int IL_IMAGE_ORIGIN          = 0x0DFE;
+		private const int IL_IMAGE_CHANNELS        = 0x0DFF;
+		
+		#endregion
+
 		#region ================== Constructor / Disposer
 
 		// Constructor
@@ -62,7 +362,39 @@ namespace CodeImp.DoomBuilder.IO
 		{
 			try
 			{
-				return (Bitmap)Bitmap.FromStream(stream);
+				// Create an image in DevIL
+				uint imageid = 0;
+				ilGenImages(1, new IntPtr(&imageid));
+				ilBindImage(imageid);
+				
+				// Read image data from stream
+				byte[] bytes = new byte[stream.Length - stream.Position];
+				stream.Read(bytes, 0, bytes.Length);
+				fixed(byte* bptr = bytes)
+				{
+					if(!ilLoadL(IL_TYPE_UNKNOWN, new IntPtr(bptr), (uint)bytes.Length))
+						throw new BadImageFormatException();
+				}
+				
+				// Get the image properties
+				int width = ilGetInteger(IL_IMAGE_WIDTH);
+				int height = ilGetInteger(IL_IMAGE_HEIGHT);
+				if((width < 1) || (height < 1))
+					throw new BadImageFormatException();
+				
+				// Convert the image to ARGB if needed
+				ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
+
+				// Copy the image pixels to a Bitmap
+				Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
+				BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+				ilCopyPixels(0, 0, 0, (uint)width, (uint)height, 1, IL_BGRA, IL_UNSIGNED_BYTE, bmpdata.Scan0);
+				bmp.UnlockBits(bmpdata);
+
+				// Clean up
+				ilDeleteImages(1, new IntPtr(&imageid));
+
+				return bmp;
 			}
 			catch(Exception e)
 			{
@@ -74,7 +406,7 @@ namespace CodeImp.DoomBuilder.IO
 
 		// This draws the picture to the given pixel color data
 		// Throws exception on failure
-		public unsafe void DrawToPixelData(Stream stream, PixelColor* target, int targetwidth, int targetheight, int x, int y)
+		public void DrawToPixelData(Stream stream, PixelColor* target, int targetwidth, int targetheight, int x, int y)
 		{
 			Bitmap bmp;
 			BitmapData bmpdata;
diff --git a/Source/Core/Map/MapOptions.cs b/Source/Core/Map/MapOptions.cs
index 31524c7c8ec4595f8b29fac95a45f911483e2ae8..80147d77a76fc6a584ae3fbc0bab7e142c6ae9c4 100644
--- a/Source/Core/Map/MapOptions.cs
+++ b/Source/Core/Map/MapOptions.cs
@@ -249,6 +249,14 @@ namespace CodeImp.DoomBuilder.Map
 			return resources.Count - 1;
 		}
 
+		/// <summary>
+		/// This returns the resource locations as configured.
+		/// </summary>
+		public DataLocationList GetResources()
+		{
+			return new DataLocationList(resources);
+		}
+
 		// This clears all reasource
 		internal void ClearResources()
 		{
diff --git a/Source/Core/Properties/AssemblyInfo.cs b/Source/Core/Properties/AssemblyInfo.cs
index e192688af20f50917e7f3c637a87519e83a444a1..c5b7f5500258edf0483ce982c9b07e8a49952b34 100644
--- a/Source/Core/Properties/AssemblyInfo.cs
+++ b/Source/Core/Properties/AssemblyInfo.cs
@@ -29,4 +29,4 @@ using System.Runtime.InteropServices;
 //      Build Number
 //      Revision
 //
-[assembly: AssemblyVersion("2.1.1.0")]
+[assembly: AssemblyVersion("2.1.2.0")]
diff --git a/Source/Core/Properties/Resources.Designer.cs b/Source/Core/Properties/Resources.Designer.cs
index 87f1b48ef57b119d42d36090080ba042ee72dd94..478bf5dd557016230acddd6db98861408f45381c 100644
--- a/Source/Core/Properties/Resources.Designer.cs
+++ b/Source/Core/Properties/Resources.Designer.cs
@@ -1,10 +1,10 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
-//     Этот код создан программой.
-//     Исполняемая версия:2.0.50727.5420
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.269
 //
-//     Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
-//     повторной генерации кода.
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
 // </auto-generated>
 //------------------------------------------------------------------------------
 
@@ -13,13 +13,13 @@ namespace CodeImp.DoomBuilder.Properties {
     
     
     /// <summary>
-    ///   Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
     /// </summary>
-    // Этот класс создан автоматически классом StronglyTypedResourceBuilder
-    // с помощью такого средства, как ResGen или Visual Studio.
-    // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
-    // с параметром /str или перестройте свой проект VS.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
@@ -33,7 +33,7 @@ namespace CodeImp.DoomBuilder.Properties {
         }
         
         /// <summary>
-        ///   Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
+        ///   Returns the cached ResourceManager instance used by this class.
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
         internal static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ namespace CodeImp.DoomBuilder.Properties {
         }
         
         /// <summary>
-        ///   Перезаписывает свойство CurrentUICulture текущего потока для всех
-        ///   обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
         internal static global::System.Globalization.CultureInfo Culture {
diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs
index 34b19030dcbffdeb28cb52c2d2a18594c1e87250..f34f5eb585cc29f35de0fef231123cfc37fcdbf0 100644
--- a/Source/Core/Rendering/Renderer3D.cs
+++ b/Source/Core/Rendering/Renderer3D.cs
@@ -82,10 +82,6 @@ namespace CodeImp.DoomBuilder.Rendering
         private int[] lightOffsets;
         private Dictionary<Texture, List<VisualGeometry>> litGeometry;
         private Dictionary<ModeldefEntry, List<VisualThing>> thingsWithModel;
-        //dbg
-        //int geoSkipped = 0;
-        //int totalGeo = 0;
-        //int totalThings = 0;
 		
 		// Crosshair
 		private FlatVertex[] crosshairverts;
@@ -511,21 +507,12 @@ namespace CodeImp.DoomBuilder.Rendering
             //mxd
             if (General.Settings.GZDrawLights) {
                 thingsWithLight = new List<VisualThing>();
-
-                //dbg
-                //GZBuilder.GZGeneral.ClearTrace();
-                //geoSkipped = 0;
-                //totalGeo = 0;
-                //totalThings = 0;
             }
 		}
 
 		// This ends rendering world geometry
 		public void FinishGeometry()
 		{
-			//dbg
-            //GZBuilder.GZGeneral.ClearTrace();
-            
             //mxd. sort lights
             if (General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0)
                 updateLights();
@@ -652,7 +639,6 @@ namespace CodeImp.DoomBuilder.Rendering
                 if (t.Selected && showselection) {
                     thingColor = General.Colors.Selection3D.ToColorValue();
                 } else {
-                    //thingColor = Color4.Modulate(t.Thing.Color.ToColorValue(), new Color4(t.VertexColor));
                     thingColor = t.Thing.Color.ToColorValue();
                     if (t != highlighted) thingColor.Alpha = 0.6f;
                 }
@@ -1185,8 +1171,10 @@ namespace CodeImp.DoomBuilder.Rendering
                         thingsWithLight.Add(t);
                     }
                 }
+            }
+
             //mxd. gather models
-            } else if (General.Settings.GZDrawModels && (!General.Settings.GZDrawSelectedModelsOnly || t.Selected) && t.Thing.IsModel) {
+            if (General.Settings.GZDrawModels && (!General.Settings.GZDrawSelectedModelsOnly || t.Selected) && t.Thing.IsModel) {
                 ModeldefEntry mde = General.Map.Data.ModeldefEntries[t.Thing.Type];
 
                 if (!isThingOnScreen(t.BoundingBox))
diff --git a/Source/Core/Resources/Splash3_trans.png b/Source/Core/Resources/Splash3_trans.png
index d004897ed2da13bec2d7381798a7128c64953c1d..1cdb5c2be8c8f755a8d80235567cae76f763aa52 100644
Binary files a/Source/Core/Resources/Splash3_trans.png and b/Source/Core/Resources/Splash3_trans.png differ
diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs
index dc4ec9ef3031b694fc024e58ba5ffa1cd5f7197e..1d3ff3ba2a8276753d98b981111f93a6a4e2a4af 100644
--- a/Source/Core/VisualModes/VisualThing.cs
+++ b/Source/Core/VisualModes/VisualThing.cs
@@ -232,7 +232,6 @@ namespace CodeImp.DoomBuilder.VisualModes
 			if(geobuffer != null) geobuffer.Dispose();
 			geobuffer = null;
 			updategeo = true;
-            //checkedIfModel = false;
 		}
 		
 		// This is called resets when the device is reset
@@ -292,7 +291,7 @@ namespace CodeImp.DoomBuilder.VisualModes
 		// This sets the vertices for the thing sprite
 		protected void SetVertices(ICollection<WorldVertex> verts)
 		{
-			// Copy vertices
+            // Copy vertices
 			vertices = new WorldVertex[verts.Count];
 			verts.CopyTo(vertices, 0);
 			triangles = vertices.Length / 3;
@@ -306,15 +305,7 @@ namespace CodeImp.DoomBuilder.VisualModes
             if (updategeo)
 			{
                 //mxd. check if thing is model
-                if (General.Map.Data.ModeldefEntries.ContainsKey(thing.Type)) {
-                    ModeldefEntry mde = General.Map.Data.ModeldefEntries[thing.Type];
-                    if (mde.Model == null)
-                        thing.IsModel = General.Map.Data.LoadModelForThing(thing);
-                    else
-                        thing.IsModel = true;
-                } else {
-                    thing.IsModel = false;
-                }
+                checkModelState();
 
                 // Trash geometry buffer
                 if (geobuffer != null) geobuffer.Dispose();
@@ -334,38 +325,56 @@ namespace CodeImp.DoomBuilder.VisualModes
                 }
 
                 //mxd. Check if thing is light
-                int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type);
-                if (light_id != -1) {
-                    isGldefsLight = false;
-                    lightInterval = -1;
-                    updateLight(light_id);
-                    UpdateBoundingBox(lightRadius, lightRadius * 2);
-
-                //check if we have light from GLDEFS
-                } else if (General.Map.Data.GldefsEntries.ContainsKey(thing.Type)) {
-                    isGldefsLight = true;
-                    updateGldefsLight();
-                    UpdateBoundingBox(lightRadius, lightRadius * 2);
-                } else {
-                    if (thing.IsModel) {
-                        updateBoundingBoxForModel();
-                    } else {
-                        UpdateBoundingBox((int)thing.Size, thingHeight);
-                    }
-                    lightType = -1;
-                    lightRadius = -1;
-                    lightPrimaryRadius = -1;
-                    lightSecondaryRadius = -1;
-                    lightRenderStyle = -1;
-                    lightInterval = -1;
-                    isGldefsLight = false;
-                }
+                checkLightState();
 
 				// Done
 				updategeo = false;
 			}
 		}
 
+        //mxd
+        protected void checkModelState() {
+            if (General.Map.Data.ModeldefEntries.ContainsKey(thing.Type)) {
+                if (General.Map.Data.ModeldefEntries[thing.Type].Model == null)
+                    thing.IsModel = General.Map.Data.LoadModelForThing(thing);
+                else
+                    thing.IsModel = true;
+            } else {
+                thing.IsModel = false;
+            }
+        }
+
+        //mxd
+        protected void checkLightState() {
+            //mxd. Check if thing is light
+            int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type);
+            if (light_id != -1) {
+                isGldefsLight = false;
+                lightInterval = -1;
+                updateLight(light_id);
+                UpdateBoundingBox(lightRadius, lightRadius * 2);
+
+                //check if we have light from GLDEFS
+            } else if (General.Map.Data.GldefsEntries.ContainsKey(thing.Type)) {
+                isGldefsLight = true;
+                updateGldefsLight();
+                UpdateBoundingBox(lightRadius, lightRadius * 2);
+            } else {
+                if (thing.IsModel) {
+                    updateBoundingBoxForModel();
+                } else {
+                    UpdateBoundingBox((int)thing.Size, thingHeight);
+                }
+                lightType = -1;
+                lightRadius = -1;
+                lightPrimaryRadius = -1;
+                lightSecondaryRadius = -1;
+                lightRenderStyle = -1;
+                lightInterval = -1;
+                isGldefsLight = false;
+            }
+        }
+
         //used in ColorPicker to update light 
         public void UpdateLight() {
             int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type);
diff --git a/Source/Core/Windows/ErrorsForm.Designer.cs b/Source/Core/Windows/ErrorsForm.Designer.cs
index 3d5be3acb19e1b81f7a8405e63237579d95840e6..e4aca63f780f98ccee1da1c2ccf5ea463fba6f66 100644
--- a/Source/Core/Windows/ErrorsForm.Designer.cs
+++ b/Source/Core/Windows/ErrorsForm.Designer.cs
@@ -28,146 +28,148 @@ namespace CodeImp.DoomBuilder.Windows
 		/// </summary>
 		private void InitializeComponent()
 		{
-			this.components = new System.ComponentModel.Container();
-			System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
-			this.copyselected = new System.Windows.Forms.Button();
-			this.clearlist = new System.Windows.Forms.Button();
-			this.close = new System.Windows.Forms.Button();
-			this.checkerrors = new System.Windows.Forms.Timer(this.components);
-			this.checkshow = new System.Windows.Forms.CheckBox();
-			this.grid = new System.Windows.Forms.DataGridView();
-			this.iconcolumn = new System.Windows.Forms.DataGridViewImageColumn();
-			this.textcolumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
-			((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
-			this.SuspendLayout();
-			// 
-			// copyselected
-			// 
-			this.copyselected.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-			this.copyselected.Location = new System.Drawing.Point(12, 416);
-			this.copyselected.Name = "copyselected";
-			this.copyselected.Size = new System.Drawing.Size(122, 25);
-			this.copyselected.TabIndex = 1;
-			this.copyselected.Text = "Copy Selection";
-			this.copyselected.UseVisualStyleBackColor = true;
-			this.copyselected.Click += new System.EventHandler(this.copyselected_Click);
-			// 
-			// clearlist
-			// 
-			this.clearlist.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-			this.clearlist.Location = new System.Drawing.Point(150, 416);
-			this.clearlist.Name = "clearlist";
-			this.clearlist.Size = new System.Drawing.Size(122, 25);
-			this.clearlist.TabIndex = 2;
-			this.clearlist.Text = "Clear";
-			this.clearlist.UseVisualStyleBackColor = true;
-			this.clearlist.Click += new System.EventHandler(this.clearlist_Click);
-			// 
-			// close
-			// 
-			this.close.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-			this.close.DialogResult = System.Windows.Forms.DialogResult.Cancel;
-			this.close.Location = new System.Drawing.Point(622, 416);
-			this.close.Name = "close";
-			this.close.Size = new System.Drawing.Size(122, 25);
-			this.close.TabIndex = 4;
-			this.close.Text = "Close";
-			this.close.UseVisualStyleBackColor = true;
-			this.close.Click += new System.EventHandler(this.close_Click);
-			// 
-			// checkerrors
-			// 
-			this.checkerrors.Interval = 1000;
-			this.checkerrors.Tick += new System.EventHandler(this.checkerrors_Tick);
-			// 
-			// checkshow
-			// 
-			this.checkshow.AutoSize = true;
-			this.checkshow.Location = new System.Drawing.Point(301, 420);
-			this.checkshow.Name = "checkshow";
-			this.checkshow.Size = new System.Drawing.Size(213, 18);
-			this.checkshow.TabIndex = 3;
-			this.checkshow.Text = "Show this window when errors occur";
-			this.checkshow.UseVisualStyleBackColor = true;
-			// 
-			// grid
-			// 
-			this.grid.AllowUserToAddRows = false;
-			this.grid.AllowUserToDeleteRows = false;
-			this.grid.AllowUserToResizeColumns = false;
-			this.grid.AllowUserToResizeRows = false;
-			this.grid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.grid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
-			this.grid.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
-			this.grid.BackgroundColor = System.Drawing.SystemColors.Window;
-			this.grid.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
-			this.grid.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None;
-			this.grid.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
-			this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-			this.grid.ColumnHeadersVisible = false;
-			this.grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+            this.components = new System.ComponentModel.Container();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
+            this.copyselected = new System.Windows.Forms.Button();
+            this.clearlist = new System.Windows.Forms.Button();
+            this.close = new System.Windows.Forms.Button();
+            this.checkerrors = new System.Windows.Forms.Timer(this.components);
+            this.checkshow = new System.Windows.Forms.CheckBox();
+            this.grid = new System.Windows.Forms.DataGridView();
+            this.iconcolumn = new System.Windows.Forms.DataGridViewImageColumn();
+            this.textcolumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            ((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // copyselected
+            // 
+            this.copyselected.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.copyselected.Location = new System.Drawing.Point(12, 416);
+            this.copyselected.Name = "copyselected";
+            this.copyselected.Size = new System.Drawing.Size(122, 25);
+            this.copyselected.TabIndex = 1;
+            this.copyselected.Text = "Copy Selection";
+            this.copyselected.UseVisualStyleBackColor = true;
+            this.copyselected.Click += new System.EventHandler(this.copyselected_Click);
+            // 
+            // clearlist
+            // 
+            this.clearlist.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.clearlist.Location = new System.Drawing.Point(150, 416);
+            this.clearlist.Name = "clearlist";
+            this.clearlist.Size = new System.Drawing.Size(122, 25);
+            this.clearlist.TabIndex = 2;
+            this.clearlist.Text = "Clear";
+            this.clearlist.UseVisualStyleBackColor = true;
+            this.clearlist.Click += new System.EventHandler(this.clearlist_Click);
+            // 
+            // close
+            // 
+            this.close.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.close.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.close.Location = new System.Drawing.Point(622, 416);
+            this.close.Name = "close";
+            this.close.Size = new System.Drawing.Size(122, 25);
+            this.close.TabIndex = 4;
+            this.close.Text = "Close";
+            this.close.UseVisualStyleBackColor = true;
+            this.close.Click += new System.EventHandler(this.close_Click);
+            // 
+            // checkerrors
+            // 
+            this.checkerrors.Interval = 1000;
+            this.checkerrors.Tick += new System.EventHandler(this.checkerrors_Tick);
+            // 
+            // checkshow
+            // 
+            this.checkshow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.checkshow.AutoSize = true;
+            this.checkshow.Location = new System.Drawing.Point(301, 420);
+            this.checkshow.Name = "checkshow";
+            this.checkshow.Size = new System.Drawing.Size(213, 18);
+            this.checkshow.TabIndex = 3;
+            this.checkshow.Text = "Show this window when errors occur";
+            this.checkshow.UseVisualStyleBackColor = true;
+            // 
+            // grid
+            // 
+            this.grid.AllowUserToAddRows = false;
+            this.grid.AllowUserToDeleteRows = false;
+            this.grid.AllowUserToResizeColumns = false;
+            this.grid.AllowUserToResizeRows = false;
+            this.grid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.grid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
+            this.grid.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
+            this.grid.BackgroundColor = System.Drawing.SystemColors.Window;
+            this.grid.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.grid.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None;
+            this.grid.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
+            this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.grid.ColumnHeadersVisible = false;
+            this.grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
             this.iconcolumn,
             this.textcolumn});
-			this.grid.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
-			this.grid.Location = new System.Drawing.Point(12, 12);
-			this.grid.Name = "grid";
-			this.grid.ReadOnly = true;
-			this.grid.RowHeadersVisible = false;
-			dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.TopLeft;
-			dataGridViewCellStyle1.Padding = new System.Windows.Forms.Padding(2, 4, 2, 5);
-			this.grid.RowsDefaultCellStyle = dataGridViewCellStyle1;
-			this.grid.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
-			this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
-			this.grid.ShowCellErrors = false;
-			this.grid.ShowCellToolTips = false;
-			this.grid.ShowEditingIcon = false;
-			this.grid.ShowRowErrors = false;
-			this.grid.Size = new System.Drawing.Size(732, 395);
-			this.grid.StandardTab = true;
-			this.grid.TabIndex = 5;
-			// 
-			// iconcolumn
-			// 
-			this.iconcolumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
-			this.iconcolumn.HeaderText = "Icon";
-			this.iconcolumn.MinimumWidth = 20;
-			this.iconcolumn.Name = "iconcolumn";
-			this.iconcolumn.ReadOnly = true;
-			this.iconcolumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
-			this.iconcolumn.Width = 24;
-			// 
-			// textcolumn
-			// 
-			this.textcolumn.HeaderText = "Text";
-			this.textcolumn.Name = "textcolumn";
-			this.textcolumn.ReadOnly = true;
-			// 
-			// ErrorsForm
-			// 
-			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
-			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
-			this.CancelButton = this.close;
-			this.ClientSize = new System.Drawing.Size(756, 453);
-			this.Controls.Add(this.checkshow);
-			this.Controls.Add(this.close);
-			this.Controls.Add(this.clearlist);
-			this.Controls.Add(this.copyselected);
-			this.Controls.Add(this.grid);
-			this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
-			this.MaximizeBox = false;
-			this.MinimizeBox = false;
-			this.Name = "ErrorsForm";
-			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
-			this.Text = "Errors and Warnings";
-			this.Shown += new System.EventHandler(this.ErrorsForm_Shown);
-			this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ErrorsForm_FormClosing);
-			this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.ErrorsForm_HelpRequested);
-			((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
-			this.ResumeLayout(false);
-			this.PerformLayout();
+            this.grid.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
+            this.grid.Location = new System.Drawing.Point(12, 12);
+            this.grid.Name = "grid";
+            this.grid.ReadOnly = true;
+            this.grid.RowHeadersVisible = false;
+            dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.TopLeft;
+            dataGridViewCellStyle1.Padding = new System.Windows.Forms.Padding(2, 4, 2, 5);
+            this.grid.RowsDefaultCellStyle = dataGridViewCellStyle1;
+            this.grid.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+            this.grid.ShowCellErrors = false;
+            this.grid.ShowCellToolTips = false;
+            this.grid.ShowEditingIcon = false;
+            this.grid.ShowRowErrors = false;
+            this.grid.Size = new System.Drawing.Size(732, 395);
+            this.grid.StandardTab = true;
+            this.grid.TabIndex = 5;
+            // 
+            // iconcolumn
+            // 
+            this.iconcolumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
+            this.iconcolumn.HeaderText = "Icon";
+            this.iconcolumn.MinimumWidth = 20;
+            this.iconcolumn.Name = "iconcolumn";
+            this.iconcolumn.ReadOnly = true;
+            this.iconcolumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.iconcolumn.Width = 24;
+            // 
+            // textcolumn
+            // 
+            this.textcolumn.HeaderText = "Text";
+            this.textcolumn.Name = "textcolumn";
+            this.textcolumn.ReadOnly = true;
+            // 
+            // ErrorsForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.CancelButton = this.close;
+            this.ClientSize = new System.Drawing.Size(756, 453);
+            this.Controls.Add(this.checkshow);
+            this.Controls.Add(this.close);
+            this.Controls.Add(this.clearlist);
+            this.Controls.Add(this.copyselected);
+            this.Controls.Add(this.grid);
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.MinimumSize = new System.Drawing.Size(680, 300);
+            this.Name = "ErrorsForm";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "Errors and Warnings";
+            this.Shown += new System.EventHandler(this.ErrorsForm_Shown);
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ErrorsForm_FormClosing);
+            this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.ErrorsForm_HelpRequested);
+            ((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
 
 		}
 
diff --git a/Source/Core/Windows/ErrorsForm.resx b/Source/Core/Windows/ErrorsForm.resx
index b09cbf23f65ff80a33070fb3121a2c895c087a59..0a8746eff8f348174bf26921d3e4f52d739a2185 100644
--- a/Source/Core/Windows/ErrorsForm.resx
+++ b/Source/Core/Windows/ErrorsForm.resx
@@ -141,7 +141,4 @@
   <metadata name="textcolumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
 </root>
\ No newline at end of file
diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index 2089fe8a38374863ef072327d500289f083b1d8c..26cf354f79a5884dbc8ceffa601bd99e6f2c4b2d 100644
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -55,7 +55,7 @@
     <Compile Include="ClassicModes\FindReplaceMode.cs" />
     <Compile Include="ClassicModes\MakeSectorMode.cs" />
     <Compile Include="ErrorChecks\CheckClosedSectors.cs" />
-    <Compile Include="ErrorChecks\CheckStuckedThings.cs" />
+    <Compile Include="ErrorChecks\CheckStuckThings.cs" />
     <Compile Include="ErrorChecks\CheckLineReferences.cs" />
     <Compile Include="ErrorChecks\CheckOverlappingLines.cs" />
     <Compile Include="ErrorChecks\ResultLineOverlapping.cs" />
@@ -64,7 +64,7 @@
     <Compile Include="ErrorChecks\ResultLineMissingFront.cs" />
     <Compile Include="ErrorChecks\ResultLineMissingSides.cs" />
     <Compile Include="ErrorChecks\ResultSectorUnclosed.cs" />
-    <Compile Include="ErrorChecks\ResultStuckedThing.cs" />
+    <Compile Include="ErrorChecks\ResultStuckThingInLine.cs" />
     <Compile Include="ErrorChecks\ErrorResult.cs" />
     <Compile Include="ErrorChecks\ErrorCheckerAttribute.cs" />
     <Compile Include="ErrorChecks\ErrorChecker.cs" />
@@ -240,6 +240,7 @@
     <Compile Include="ErrorChecks\CheckUnknownFlats.cs" />
     <Compile Include="ErrorChecks\CheckUnknownTextures.cs" />
     <Compile Include="ErrorChecks\ResultNoErrors.cs" />
+    <Compile Include="ErrorChecks\ResultStuckThingInThing.cs" />
     <Compile Include="ErrorChecks\ResultTextureMissing.cs" />
     <Compile Include="ErrorChecks\ResultUnknownFlat.cs" />
     <Compile Include="ErrorChecks\ResultUnknownTexture.cs" />
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/CheckStuckedThings.cs b/Source/Plugins/BuilderModes/ErrorChecks/CheckStuckThings.cs
similarity index 62%
rename from Source/Plugins/BuilderModes/ErrorChecks/CheckStuckedThings.cs
rename to Source/Plugins/BuilderModes/ErrorChecks/CheckStuckThings.cs
index e4b608e1ae36e32589f16f5d9cac73c91abb0ada..45acca21bb20d03c3d6c00dd228f8fabfa56e842 100644
--- a/Source/Plugins/BuilderModes/ErrorChecks/CheckStuckedThings.cs
+++ b/Source/Plugins/BuilderModes/ErrorChecks/CheckStuckThings.cs
@@ -41,19 +41,26 @@ using System.Drawing;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[ErrorChecker("Check stuck things", true, 1000)]
-	public class CheckStuckedThings : ErrorChecker
+	public class CheckStuckThings : ErrorChecker
 	{
 		#region ================== Constants
 
 		private const int PROGRESS_STEP = 10;
 		private const float ALLOWED_STUCK_DISTANCE = 6.0f;
 
+		enum StuckType
+		{
+			None = 0,
+			Line,
+			Thing
+		}
+
 		#endregion
 
 		#region ================== Constructor / Destructor
 
 		// Constructor
-		public CheckStuckedThings()
+		public CheckStuckThings()
 		{
 			// Total progress is done when all things are checked
 			SetTotalProgress(General.Map.Map.Things.Count / PROGRESS_STEP);
@@ -69,38 +76,44 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			BlockMap<BlockEntry> blockmap = BuilderPlug.Me.ErrorCheckForm.BlockMap;
 			int progress = 0;
 			int stepprogress = 0;
+
+			// List of things that have been checked for being stuck in other things,
+			// so that they don't show up twice
+			List<Thing> checkedthings = new List<Thing>();
 			
 			// Go for all the things
 			foreach(Thing t in General.Map.Map.Things)
 			{
 				ThingTypeInfo info = General.Map.Data.GetThingInfo(t.Type);
-				bool stucked = false;
-				
-				// Check this thing for getting stucked?
-				if( (info.ErrorCheck == ThingTypeInfo.THING_ERROR_INSIDE_STUCKED) &&
+				bool stuck = false;
+				StuckType stucktype = StuckType.None;
+
+				// Check this thing for getting stuck?
+				if( (info.ErrorCheck == ThingTypeInfo.THING_ERROR_INSIDE_STUCK) &&
 					(info.Blocking > ThingTypeInfo.THING_BLOCKING_NONE))
 				{
 					// Make square coordinates from thing
 					float blockingsize = t.Size - ALLOWED_STUCK_DISTANCE;
-					Vector2D lt = new Vector2D(t.Position.x - blockingsize, t.Position.y - blockingsize);
-					Vector2D rb = new Vector2D(t.Position.x + blockingsize, t.Position.y + blockingsize);
-					
-					// Go for all the lines to see if this thing is stucked
-					List<BlockEntry> blocks = blockmap.GetSquareRange(new RectangleF(lt.x, lt.y, (rb.x - lt.x), (rb.y - lt.y)));
+					Vector2D lt = new Vector2D(t.Position.x - blockingsize, t.Position.y + blockingsize);
+					Vector2D rb = new Vector2D(t.Position.x + blockingsize, t.Position.y - blockingsize);
+
+					// Go for all the lines to see if this thing is stuck
+					List<BlockEntry> blocks = blockmap.GetSquareRange(new RectangleF(lt.x, lt.y, (rb.x - lt.x), (lt.y - rb.y)));
 					Dictionary<Linedef, Linedef> doneblocklines = new Dictionary<Linedef, Linedef>(blocks.Count * 3);
+
 					foreach(BlockEntry b in blocks)
 					{
 						foreach(Linedef l in b.Lines)
 						{
-							// Only test when sinlge-sided and not already checked
-							if((l.Back == null) && !doneblocklines.ContainsKey(l))
+							// Only test when sinlge-sided, two-sided + impassable and not already checked
+							if(((l.Back == null) || l.IsFlagSet(General.Map.Config.ImpassableFlag)) && !doneblocklines.ContainsKey(l))
 							{
 								// Test if line ends are inside the thing
 								if(PointInRect(lt, rb, l.Start.Position) ||
 								   PointInRect(lt, rb, l.End.Position))
 								{
-									// Thing stucked in line!
-									stucked = true;
+									// Thing stuck in line!
+									stuck = true;
 								}
 								// Test if the line intersects the square
 								else if(Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, lt.y, rb.x, lt.y) ||
@@ -108,22 +121,59 @@ namespace CodeImp.DoomBuilder.BuilderModes
 										Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, rb.y, lt.x, rb.y) ||
 										Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, rb.y, lt.x, lt.y))
 								{
-									// Thing stucked in line!
-									stucked = true;
+									// Thing stuck in line!
+									stuck = true;
+									stucktype = StuckType.Line;
 								}
 								
 								// Checked
 								doneblocklines.Add(l, l);
 							}
 						}
+
+						// Check if thing is stuck in other things
+						foreach (Thing ot in b.Things)
+						{
+							// Don't compare the thing with itself
+							if (t.Index == ot.Index) continue;
+
+							// Don't check things that have already been found to be stuck in
+							// other things
+							if (checkedthings.Contains(t)) continue;
+
+							// need to compare the flags
+							Dictionary<string, bool> flags1 = t.GetFlags();
+							Dictionary<string, bool> flags2 = ot.GetFlags();
+
+							// Make square coordinates from the other thing
+							float bsot = ot.Size /* - ALLOWED_STUCK_DISTANCE */;
+							Vector2D ltot = new Vector2D(ot.Position.x - bsot, ot.Position.y + bsot);
+							Vector2D rbot = new Vector2D(ot.Position.x + bsot, ot.Position.y - bsot);
+
+							if (ThingsOverlap(t, ot))
+							{
+								stuck = true;
+								stucktype = StuckType.Thing;
+								checkedthings.Add(ot);
+							}
+						}
 					}
 				}
 				
-				// Stucked?
-				if(stucked)
+				// Stuck?
+				if(stuck)
 				{
 					// Make result
-					SubmitResult(new ResultStuckedThing(t));
+					switch (stucktype)
+					{
+						case StuckType.Line:
+							SubmitResult(new ResultStuckThingInLine(t));
+							break;
+
+						case StuckType.Thing:
+							SubmitResult(new ResultStuckThingInThing(t));
+							break;
+					}
 				}
 				else
 				{
@@ -169,6 +219,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			return (p.x >= lt.x) && (p.x <= rb.x) && (p.y >= lt.y) && (p.y <= rb.y);
 		}
+
+		// Checks if two things overlap
+		private bool ThingsOverlap(Thing t1, Thing t2)
+		{
+			Vector3D p1 = t1.Position;
+			Vector3D p2 = t2.Position;
+
+			// simple bounding box collision detection
+			if (	p1.x + t1.Size < p2.x - t2.Size ||
+					p1.x - t1.Size > p2.x + t2.Size	||
+					p1.y - t1.Size > p2.y + t2.Size ||
+					p1.y + t1.Size < p2.y - t2.Size)
+				return false;
+
+			return true;
+		}
 		
 		#endregion
 	}
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckedThing.cs b/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckThingInLine.cs
similarity index 84%
rename from Source/Plugins/BuilderModes/ErrorChecks/ResultStuckedThing.cs
rename to Source/Plugins/BuilderModes/ErrorChecks/ResultStuckThingInLine.cs
index 8810391f54bb82f8f68a23d3b4d871443b0b23de..7459574cf9180ee18d30c7434a16d7d684435a8c 100644
--- a/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckedThing.cs
+++ b/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckThingInLine.cs
@@ -38,7 +38,7 @@ using CodeImp.DoomBuilder.Config;
 
 namespace CodeImp.DoomBuilder.BuilderModes
 {
-	public class ResultStuckedThing : ErrorResult
+	public class ResultStuckThingInLine : ErrorResult
 	{
 		#region ================== Variables
 
@@ -56,12 +56,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		#region ================== Constructor / Destructor
 		
 		// Constructor
-		public ResultStuckedThing(Thing t)
+		public ResultStuckThingInLine(Thing t)
 		{
 			// Initialize
 			this.thing = t;
 			this.viewobjects.Add(t);
-			this.description = "This thing is stucked in a wall (single-sided line) and will likely not be able to move around.";
+			this.description = "This thing is stuck in a wall (single-sided line) and will likely not be able to move around.";
 		}
 		
 		#endregion
@@ -71,7 +71,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// This must return the string that is displayed in the listbox
 		public override string ToString()
 		{
-			return General.Map.Data.GetThingInfo(thing.Type).Title + " is stucked in a wall at " + thing.Position.x + ", " + thing.Position.y;
+			return General.Map.Data.GetThingInfo(thing.Type).Title + " is stuck in a wall at " + thing.Position.x + ", " + thing.Position.y;
 		}
 
 		// Rendering
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckThingInThing.cs b/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckThingInThing.cs
new file mode 100644
index 0000000000000000000000000000000000000000..11abfa203206fdb887d7ec8bf6c48111728cf20f
--- /dev/null
+++ b/Source/Plugins/BuilderModes/ErrorChecks/ResultStuckThingInThing.cs
@@ -0,0 +1,95 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Reflection;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.IO;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Editing;
+using CodeImp.DoomBuilder.Actions;
+using CodeImp.DoomBuilder.Types;
+using CodeImp.DoomBuilder.Config;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.BuilderModes
+{
+	public class ResultStuckThingInThing : ErrorResult
+	{
+		#region ================== Variables
+
+		private Thing thing;
+
+		#endregion
+
+		#region ================== Properties
+
+		public override int Buttons { get { return 1; } }
+		public override string Button1Text { get { return "Delete Thing"; } }
+
+		#endregion
+
+		#region ================== Constructor / Destructor
+
+		// Constructor
+		public ResultStuckThingInThing(Thing t)
+		{
+			// Initialize
+			this.thing = t;
+			this.viewobjects.Add(t);
+			this.description = "This thing is stuck in another thing. Both will likely not be able to move around.";
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// This must return the string that is displayed in the listbox
+		public override string ToString()
+		{
+			return General.Map.Data.GetThingInfo(thing.Type).Title + " is stuck in another thing at " + thing.Position.x + ", " + thing.Position.y;
+		}
+
+		// Rendering
+		public override void RenderOverlaySelection(IRenderer2D renderer)
+		{
+			renderer.RenderThing(thing, renderer.DetermineThingColor(thing), 1.0f);
+		}
+
+		// This removes the thing
+		public override bool Button1Click()
+		{
+			General.Map.UndoRedo.CreateUndo("Delete thing");
+			thing.Dispose();
+			General.Map.IsChanged = true;
+			General.Map.ThingsFilter.Update();
+			return true;
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs b/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs
index 88f163d1a8ba1777b2933ec5df217f06993a80e8..370dd982be60d0262550e9c7220b3b2d2c18b013 100644
--- a/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs
+++ b/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs
@@ -29,4 +29,4 @@ using System.Runtime.InteropServices;
 //      Build Number
 //      Revision
 //
-[assembly: AssemblyVersion("2.1.1.0")]
+[assembly: AssemblyVersion("2.1.2.0")]
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
index c7d81d3fc3d5030595fbeb563fc70a6a00ae4df0..cfeb1379c1b6773ecce1eb93a7ab7f5ee6715d61 100644
--- a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
+++ b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:2.0.50727.4206
+//     Runtime Version:4.0.30319.269
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -19,7 +19,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
index f458da09b4d159a748fb9b74ec7c89c109d94d4b..d7ac497546c6504fcf321aafeb2a9843c53e939f 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
@@ -203,17 +203,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				}
 			}
 
-            //mxd. check model state
-            if (General.Map.Data.ModeldefEntries.ContainsKey(Thing.Type)) {
-                ModeldefEntry mde = General.Map.Data.ModeldefEntries[Thing.Type];
-                if (mde.Model == null) {
-                    Thing.IsModel = General.Map.Data.LoadModelForThing(Thing);
-                } else {
-                    Thing.IsModel = true;
-                }
-            } else {
-                Thing.IsModel = false;
-            }
+            checkModelState(); //mxd. check model state
+            checkLightState(); //mxd. check gldefs light state
 			
 			// Apply settings
 			SetPosition(pos);
@@ -254,16 +245,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// This forces to rebuild the whole thing
 		public void Rebuild()
 		{
-            // Find thing information //mxd. I think it should be here
-            info = General.Map.Data.GetThingInfo(Thing.Type);
-
-            // Find sprite texture //mxd. and this 
-            if (info.Sprite.Length > 0) {
-                sprite = General.Map.Data.GetSpriteImage(info.Sprite);
-                if (sprite != null) sprite.AddReference();
-            }
-            
-            // Setup visual thing
+			// Find thing information
+			info = General.Map.Data.GetThingInfo(Thing.Type);
+
+			// Find sprite texture
+			if(info.Sprite.Length > 0)
+			{
+				sprite = General.Map.Data.GetSpriteImage(info.Sprite);
+				if(sprite != null) sprite.AddReference();
+			}
+			
+			// Setup visual thing
 			Setup();
 		}
 		
diff --git a/Source/Plugins/CommentsPanel/Properties/Resources.Designer.cs b/Source/Plugins/CommentsPanel/Properties/Resources.Designer.cs
index acd3d5f5c8b05fd2a6245795851587eabc1b6bb5..97760a268990c60f9196f7b54ad991acd3ba870b 100644
--- a/Source/Plugins/CommentsPanel/Properties/Resources.Designer.cs
+++ b/Source/Plugins/CommentsPanel/Properties/Resources.Designer.cs
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:2.0.50727.4206
+//     Runtime Version:4.0.30319.269
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -19,7 +19,7 @@ namespace CodeImp.DoomBuilder.CommentsPanel.Properties {
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
diff --git a/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs b/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs
index 289169a5db19aafe7691cd2a77aa84d37aed922b..878f14fc9696b344e20b54aad3b0589a57e1b148 100644
--- a/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs
+++ b/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:2.0.50727.3615
+//     Runtime Version:4.0.30319.269
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -19,7 +19,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing.Properties {
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs
index ccca9a4a8d337b6a60e5dd8b550acb1137fcd279..8e4d02d75ba9bc487df5a10b5d1ceb1be2b6c48d 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualThing.cs
@@ -239,17 +239,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 				}
 			}
 
-            //mxd. check model state
-            if (General.Map.Data.ModeldefEntries.ContainsKey(Thing.Type)) {
-                ModeldefEntry mde = General.Map.Data.ModeldefEntries[Thing.Type];
-                if (mde.Model == null) {
-                    Thing.IsModel = General.Map.Data.LoadModelForThing(Thing);
-                } else {
-                    Thing.IsModel = true;
-                }
-            } else {
-                Thing.IsModel = false;
-            }
+            checkModelState(); //mxd. check model state
+            checkLightState(); //mxd. check gldefs light state
 			
 			// Apply settings
 			SetPosition(pos);
diff --git a/Source/Plugins/VisplaneExplorer/BuilderPlug.cs b/Source/Plugins/VisplaneExplorer/BuilderPlug.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ca2b1e0813daf24ec719952815f3d63d76ad5c2d
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/BuilderPlug.cs
@@ -0,0 +1,164 @@
+
+#region ================== Copyright (c) 2012 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2012 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.IO;
+using System.Reflection;
+using CodeImp.DoomBuilder.Actions;
+using CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.IO;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.Geometry;
+using System.Drawing;
+using CodeImp.DoomBuilder.Editing;
+using CodeImp.DoomBuilder.Plugins;
+using CodeImp.DoomBuilder.Types;
+using CodeImp.DoomBuilder.Config;
+using CodeImp.DoomBuilder.Data;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	public class BuilderPlug : Plug
+	{
+		#region ================== Variables
+
+		// Objects
+		private static BuilderPlug me;
+		private VPOManager vpo;
+		private InterfaceForm interfaceform;
+
+		// Palettes
+		private Palette[] palettes;
+		
+		#endregion
+
+		#region ================== Properties
+		
+		// Properties
+		public static BuilderPlug Me { get { return me; } }
+		public override string Name { get { return "VisplaneExplorer"; } }
+		internal static VPOManager VPO { get { return me.vpo; } }
+		internal static InterfaceForm InterfaceForm { get { return me.interfaceform; } }
+		internal static Palette[] Palettes { get { return me.palettes; } }
+		public override int MinimumRevision { get { return 1545; } }
+		
+		#endregion
+
+		#region ================== Initialize / Dispose
+
+		// This event is called when the plugin is initialized
+		public override void OnInitialize()
+		{
+			base.OnInitialize();
+			
+			General.Actions.BindMethods(this);
+			
+			// Load interface controls
+			interfaceform = new InterfaceForm();
+
+			// Load VPO manager (manages multithreading and communication with vpo.dll)
+			vpo = new VPOManager();
+
+			// Keep a static reference
+			me = this;
+		}
+
+		// Some things cannot be initialized at plugin start, so we do them here
+		public override void OnMapOpenBegin()
+		{
+			base.OnMapOpenBegin();
+
+			if(palettes == null)
+			{
+				// Load palettes
+				palettes = new Palette[(int)ViewStats.NumStats];
+				palettes[(int)ViewStats.Visplanes] = new Palette(Resources.Visplanes_pal);
+				palettes[(int)ViewStats.Drawsegs] = new Palette(Resources.Drawsegs_pal);
+				palettes[(int)ViewStats.Solidsegs] = new Palette(Resources.Solidsegs_pal);
+				palettes[(int)ViewStats.Openings] = new Palette(Resources.Openings_pal);
+				ApplyUserColors();
+			}
+		}
+
+		// Preferences changed
+		public override void OnClosePreferences(PreferencesController controller)
+		{
+			base.OnClosePreferences(controller);
+
+            if(General.Map != null) //mxd
+			    ApplyUserColors();
+		}
+
+		// This is called when the plugin is terminated
+		public override void Dispose()
+		{
+			// Clean up
+			interfaceform.Dispose();
+			interfaceform = null;
+			vpo.Dispose();
+			vpo = null;
+			General.Actions.UnbindMethods(this);
+			base.Dispose();
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// This applies user-defined appearance colors to the palettes
+		private void ApplyUserColors()
+		{
+			// Override special palette indices with user-defined colors
+            for (int i = 0; i < palettes.Length; i++) {
+                palettes[i].SetColor(Tile.POINT_VOID_B, General.Colors.Background.WithAlpha(0).ToInt());
+            }
+		}
+
+		// This returns a unique temp filename
+		public static string MakeTempFilename(string extension)
+		{
+			string filename;
+			string chars = "abcdefghijklmnopqrstuvwxyz1234567890";
+			Random rnd = new Random();
+			int i;
+
+			do
+			{
+				// Generate a filename
+				filename = "";
+				for(i = 0; i < 8; i++) filename += chars[rnd.Next(chars.Length)];
+				filename = Path.Combine(General.TempPath, filename + extension);
+			}
+			// Continue while file is not unique
+			while(File.Exists(filename) || Directory.Exists(filename));
+
+			// Return the filename
+			return filename;
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/InterfaceForm.Designer.cs b/Source/Plugins/VisplaneExplorer/InterfaceForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..61341ee8473354a3b11be54cd6477ec2f79e332b
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/InterfaceForm.Designer.cs
@@ -0,0 +1,143 @@
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	partial class InterfaceForm
+	{
+		/// <summary>
+		/// Required designer variable.
+		/// </summary>
+		private System.ComponentModel.IContainer components = null;
+
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+		protected override void Dispose(bool disposing)
+		{
+			if(disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Windows Form Designer generated code
+
+		/// <summary>
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.toolstrip = new System.Windows.Forms.ToolStrip();
+			this.statsbutton = new System.Windows.Forms.ToolStripDropDownButton();
+			this.vpstats = new System.Windows.Forms.ToolStripMenuItem();
+			this.dsstats = new System.Windows.Forms.ToolStripMenuItem();
+			this.ssstats = new System.Windows.Forms.ToolStripMenuItem();
+			this.opstats = new System.Windows.Forms.ToolStripMenuItem();
+			this.tooltip = new System.Windows.Forms.ToolTip(this.components);
+			this.toolstrip.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// toolstrip
+			// 
+			this.toolstrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.statsbutton});
+			this.toolstrip.Location = new System.Drawing.Point(0, 0);
+			this.toolstrip.Name = "toolstrip";
+			this.toolstrip.Size = new System.Drawing.Size(465, 25);
+			this.toolstrip.TabIndex = 0;
+			// 
+			// statsbutton
+			// 
+			this.statsbutton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+			this.statsbutton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.vpstats,
+            this.dsstats,
+            this.ssstats,
+            this.opstats});
+			this.statsbutton.Image = global::CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties.Resources.Visplanes;
+			this.statsbutton.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.statsbutton.Name = "statsbutton";
+			this.statsbutton.Size = new System.Drawing.Size(29, 22);
+			this.statsbutton.ToolTipText = "Statistics to view";
+			// 
+			// vpstats
+			// 
+			this.vpstats.Checked = true;
+			this.vpstats.CheckState = System.Windows.Forms.CheckState.Checked;
+			this.vpstats.Image = global::CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties.Resources.Visplanes;
+			this.vpstats.Name = "vpstats";
+			this.vpstats.Size = new System.Drawing.Size(132, 22);
+			this.vpstats.Tag = "0";
+			this.vpstats.Text = "Visplanes";
+			this.vpstats.Click += new System.EventHandler(this.stats_Click);
+			// 
+			// dsstats
+			// 
+			this.dsstats.Image = global::CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties.Resources.Drawsegs;
+			this.dsstats.Name = "dsstats";
+			this.dsstats.Size = new System.Drawing.Size(132, 22);
+			this.dsstats.Tag = "1";
+			this.dsstats.Text = "Drawsegs";
+			this.dsstats.Click += new System.EventHandler(this.stats_Click);
+			// 
+			// ssstats
+			// 
+			this.ssstats.Image = global::CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties.Resources.Solidsegs;
+			this.ssstats.Name = "ssstats";
+			this.ssstats.Size = new System.Drawing.Size(132, 22);
+			this.ssstats.Tag = "2";
+			this.ssstats.Text = "Solidsegs";
+			this.ssstats.Click += new System.EventHandler(this.stats_Click);
+			// 
+			// opstats
+			// 
+			this.opstats.Image = global::CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties.Resources.Openings;
+			this.opstats.Name = "opstats";
+			this.opstats.Size = new System.Drawing.Size(132, 22);
+			this.opstats.Tag = "3";
+			this.opstats.Text = "Openings";
+			this.opstats.Click += new System.EventHandler(this.stats_Click);
+			// 
+			// tooltip
+			// 
+			this.tooltip.AutomaticDelay = 1;
+			this.tooltip.AutoPopDelay = 1000;
+			this.tooltip.InitialDelay = 1;
+			this.tooltip.ReshowDelay = 0;
+			this.tooltip.ShowAlways = true;
+			// 
+			// InterfaceForm
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+			this.ClientSize = new System.Drawing.Size(465, 273);
+			this.Controls.Add(this.toolstrip);
+			this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+			this.MaximizeBox = false;
+			this.MinimizeBox = false;
+			this.Name = "InterfaceForm";
+			this.ShowIcon = false;
+			this.ShowInTaskbar = false;
+			this.Text = "InterfaceForm";
+			this.toolstrip.ResumeLayout(false);
+			this.toolstrip.PerformLayout();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.ToolStrip toolstrip;
+		private System.Windows.Forms.ToolStripDropDownButton statsbutton;
+		private System.Windows.Forms.ToolStripMenuItem vpstats;
+		private System.Windows.Forms.ToolStripMenuItem dsstats;
+		private System.Windows.Forms.ToolStripMenuItem ssstats;
+		private System.Windows.Forms.ToolStripMenuItem opstats;
+		private System.Windows.Forms.ToolTip tooltip;
+
+	}
+}
\ No newline at end of file
diff --git a/Source/Plugins/VisplaneExplorer/InterfaceForm.cs b/Source/Plugins/VisplaneExplorer/InterfaceForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..390fa86d445597bc1138161826afcd9ca2cc17ca
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/InterfaceForm.cs
@@ -0,0 +1,100 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Text;
+using System.ComponentModel;
+using System.Windows.Forms;
+using CodeImp.DoomBuilder.Windows;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	public partial class InterfaceForm : Form
+	{
+		#region ================== Constants
+
+		#endregion
+
+		#region ================== Variables
+
+		private ViewStats viewstats;
+		Point oldttposition;
+
+		#endregion
+
+		#region ================== Properties
+
+		internal ViewStats ViewStats { get { return viewstats; } }
+
+		#endregion
+
+		#region ================== Constructor / Destructor
+
+		// Constructor
+		public InterfaceForm()
+		{
+			InitializeComponent();
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// This adds the buttons to the toolbar
+		public void AddToInterface()
+		{
+			General.Interface.AddButton(statsbutton, ToolbarSection.Custom);
+		}
+
+		// This removes the buttons from the toolbar
+		public void RemoveFromInterface()
+		{
+			General.Interface.RemoveButton(statsbutton);
+		}
+
+		// This shows a tooltip
+		public void ShowTooltip(string text, Point p)
+		{
+			Point sp = General.Interface.Display.PointToScreen(p);
+			Point fp = (General.Interface as Form).Location;
+			Point tp = new Point(sp.X - fp.X, sp.Y - fp.Y);
+
+			if (oldttposition != tp)
+			{
+				tooltip.Show(text, General.Interface, tp);
+				oldttposition = tp;
+			}
+		}
+
+		// This hides the tooltip
+		public void HideTooltip()
+		{
+			tooltip.Hide(General.Interface);
+		}
+
+		#endregion
+
+		#region ================== Events
+
+		// Selecting a type of stats to view
+		private void stats_Click(object sender, EventArgs e)
+		{
+			foreach(ToolStripMenuItem i in statsbutton.DropDownItems)
+				i.Checked = false;
+			
+			ToolStripMenuItem item = (ToolStripMenuItem)sender;
+			viewstats = (ViewStats)int.Parse(item.Tag.ToString(), CultureInfo.InvariantCulture);
+			item.Checked = true;
+			statsbutton.Image = item.Image;
+
+			General.Interface.RedrawDisplay();
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/InterfaceForm.resx b/Source/Plugins/VisplaneExplorer/InterfaceForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..480a5403b4b840732146e6bf4bc7f3a39899ce42
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/InterfaceForm.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolstrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>109, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/VisplaneExplorer/NearestLineBlockmap.cs b/Source/Plugins/VisplaneExplorer/NearestLineBlockmap.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d34239a00c00f29f510695cba1b115bc93fd8102
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/NearestLineBlockmap.cs
@@ -0,0 +1,42 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Text;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Map;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal sealed class NearestLineBlockmap : BlockMap<BlockEntry>
+	{
+		// Constructor
+		public NearestLineBlockmap(RectangleF range) : base(range)
+		{
+			List<Linedef> singlesided = new List<Linedef>(General.Map.Map.Linedefs.Count);
+			foreach(Linedef ld in General.Map.Map.Linedefs)
+				if(ld.Back == null) singlesided.Add(ld);
+			AddLinedefsSet(singlesided);
+
+			// Blocks that do not have any linedefs in them must get the nearest line in them!
+			for(int x = 0; x < size.Width; x++)
+			{
+				for(int y = 0; y < size.Height; y++)
+				{
+					BlockEntry be = blockmap[x, y];
+					if(be.Lines.Count == 0)
+					{
+						Vector2D bc = GetBlockCenter(new Point(x, y));
+						Linedef ld = MapSet.NearestLinedef(singlesided, bc);
+						be.Lines.Add(ld);
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/Palette.cs b/Source/Plugins/VisplaneExplorer/Palette.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2ae3d4e163f3d45977435386d00b84f2ff10d317
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/Palette.cs
@@ -0,0 +1,37 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Text;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal class Palette
+	{
+		// Members
+		private int[] colors;
+
+		// Properties
+		public int[] Colors { get { return colors; } }
+
+		// Constructor
+		public Palette(Bitmap bmp)
+		{
+			// Initialize
+			colors = new int[bmp.Size.Width];
+			for(int x = 0; x < bmp.Size.Width; x++)
+				colors[x] = bmp.GetPixel(x, 1).ToArgb();
+		}
+
+		// This overrides a color
+		public void SetColor(int index, int color)
+		{
+			colors[index] = color;
+		}
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/PointData.cs b/Source/Plugins/VisplaneExplorer/PointData.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b1f0e8fa6e9cf82b412c464785fd88644963e674
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/PointData.cs
@@ -0,0 +1,22 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal struct PointData
+	{
+		public TilePoint point;
+		public PointResult result;
+		public int visplanes;
+		public int drawsegs;
+		public int solidsegs;
+		public int openings;
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/PointResult.cs b/Source/Plugins/VisplaneExplorer/PointResult.cs
new file mode 100644
index 0000000000000000000000000000000000000000..588d1af9cc918f3e641381035ca77ebcc52cd01f
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/PointResult.cs
@@ -0,0 +1,20 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal enum PointResult : int
+	{
+		OK = 0,
+		BadZ = -1,
+		Void = -2,
+		Overflow = -3,
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/Properties/AssemblyInfo.cs b/Source/Plugins/VisplaneExplorer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9f65e7c8675114bb87a49ef54c6ef1a181f2e0e6
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("VisplaneExplorer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("CodeImp")]
+[assembly: AssemblyProduct("Doom Builder")]
+[assembly: AssemblyCopyright("Copyright ©  2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("323a480c-22f6-4bb0-9b3b-20aa547fb1bc")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Plugins/VisplaneExplorer/Properties/Resources.Designer.cs b/Source/Plugins/VisplaneExplorer/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cf89ed593a1a781fd499f8bf95a5449826c4ce87
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/Properties/Resources.Designer.cs
@@ -0,0 +1,119 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.269
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Drawsegs {
+            get {
+                object obj = ResourceManager.GetObject("Drawsegs", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Drawsegs_pal {
+            get {
+                object obj = ResourceManager.GetObject("Drawsegs_pal", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Openings {
+            get {
+                object obj = ResourceManager.GetObject("Openings", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Openings_pal {
+            get {
+                object obj = ResourceManager.GetObject("Openings_pal", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Solidsegs {
+            get {
+                object obj = ResourceManager.GetObject("Solidsegs", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Solidsegs_pal {
+            get {
+                object obj = ResourceManager.GetObject("Solidsegs_pal", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Visplanes {
+            get {
+                object obj = ResourceManager.GetObject("Visplanes", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Visplanes_pal {
+            get {
+                object obj = ResourceManager.GetObject("Visplanes_pal", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/VisplaneExplorer/Properties/Resources.resx b/Source/Plugins/VisplaneExplorer/Properties/Resources.resx
new file mode 100644
index 0000000000000000000000000000000000000000..5c6ee0941038bdc40d089edc24eadbd94b49a30d
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/Properties/Resources.resx
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="Solidsegs" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Solidsegs.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Drawsegs" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Drawsegs.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Visplanes" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Visplanes.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Openings" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Openings.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Drawsegs_pal" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Drawsegs_pal.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Openings_pal" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Openings_pal.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Solidsegs_pal" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Solidsegs_pal.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Visplanes_pal" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Visplanes_pal.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Actions.cfg b/Source/Plugins/VisplaneExplorer/Resources/Actions.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..fab1d89a638747a73481e90331543d05f31a0f2d
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/Resources/Actions.cfg
@@ -0,0 +1,34 @@
+
+//
+// This file defines which actions there are, what description they have and
+// some behaviour options. The Doom Builder core will bind to these actions
+// with delegates (function pointers) where you use the BeginAction and
+// EndAction attributes. This file must be named Actions.cfg and must be
+// included in the plugin project as "Embedded Resource".
+//
+
+//
+// Options:
+//
+// allowkeys:       Allows the user to bind standard keys to this action.
+// allowmouse:      Allows the user to bind mouse buttons to this action.
+// allowscroll:     Allows the user to bind the scrollwheel to this action.
+// disregardshift:  This action will trigger regardless if Shift or Control is used.
+// repeat:          BeginAction will be called for automatic key repetition.
+// default:         Default key is only used when the action is loaded for the first
+//                  time and the default key is not used by any other action.
+//
+// allowkeys and allowmouse are true by default, the others are false by default.
+//
+
+
+visplaneexplorermode
+{
+	title = "Visplane Explorer Mode";
+	category = "modes";
+	description = "Switches to the Visplane Explorer viewing mode.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = false;
+}
+
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Drawsegs.png b/Source/Plugins/VisplaneExplorer/Resources/Drawsegs.png
new file mode 100644
index 0000000000000000000000000000000000000000..1d2cb0f3f006c4102528922d12cfd6bcce6f41f1
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Drawsegs.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Drawsegs_pal.png b/Source/Plugins/VisplaneExplorer/Resources/Drawsegs_pal.png
new file mode 100644
index 0000000000000000000000000000000000000000..69289714f177b44f8576dc68e900a07d7bfc77ac
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Drawsegs_pal.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Gauge.ico b/Source/Plugins/VisplaneExplorer/Resources/Gauge.ico
new file mode 100644
index 0000000000000000000000000000000000000000..508ca5e0a2c3bcc32c101082d3ccfcd413ed5e46
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Gauge.ico differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Gauge.png b/Source/Plugins/VisplaneExplorer/Resources/Gauge.png
new file mode 100644
index 0000000000000000000000000000000000000000..4e286ad9207d5ed92de0ef2f247d8ec78ad9773d
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Gauge.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Gauge_large.ico b/Source/Plugins/VisplaneExplorer/Resources/Gauge_large.ico
new file mode 100644
index 0000000000000000000000000000000000000000..eaa722a4d2803e007c29ccd27f7493563ddd2a64
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Gauge_large.ico differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Openings.png b/Source/Plugins/VisplaneExplorer/Resources/Openings.png
new file mode 100644
index 0000000000000000000000000000000000000000..203d86acc6e3382e200d41cbb5e4e58b71f5dad1
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Openings.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Openings_pal.png b/Source/Plugins/VisplaneExplorer/Resources/Openings_pal.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ea31d714867475eea94002620be0f9c47f61033
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Openings_pal.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Solidsegs.png b/Source/Plugins/VisplaneExplorer/Resources/Solidsegs.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a2c6b6031692d54d745fcd745da9119ffb4e6ef
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Solidsegs.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Solidsegs_pal.png b/Source/Plugins/VisplaneExplorer/Resources/Solidsegs_pal.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e031e000c6d571d1e447440fe635ed456ec1317
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Solidsegs_pal.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Visplanes.png b/Source/Plugins/VisplaneExplorer/Resources/Visplanes.png
new file mode 100644
index 0000000000000000000000000000000000000000..b028752407eba0238da4a41bafb5cf965d63ebc6
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Visplanes.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/Visplanes_pal.png b/Source/Plugins/VisplaneExplorer/Resources/Visplanes_pal.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad85f8edc292a191dcf317e7875e77120451158d
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/Visplanes_pal.png differ
diff --git a/Source/Plugins/VisplaneExplorer/Resources/vpo.dll b/Source/Plugins/VisplaneExplorer/Resources/vpo.dll
new file mode 100644
index 0000000000000000000000000000000000000000..845262b8934fe7378759c2a3c34d71cf0d702556
Binary files /dev/null and b/Source/Plugins/VisplaneExplorer/Resources/vpo.dll differ
diff --git a/Source/Plugins/VisplaneExplorer/Tile.cs b/Source/Plugins/VisplaneExplorer/Tile.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f02f32e96d2cc9ff4f279236fc1eb814d9b2c756
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/Tile.cs
@@ -0,0 +1,180 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Globalization;
+using System.Text;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	// This is a 64x64 tile in map space which holds the point data results.
+	internal class Tile
+	{
+		// Constants
+		public const int TILE_SIZE = 64;
+		public static readonly int[] STATS_COMPRESSOR = new int[] { 1, 2, 1, 160 };
+		public static readonly int[] STATS_LIMITS = new int[] { 128, 256, 32, 320 * 64 };
+		public const uint POINT_MAXRANGE = 254;
+		public const uint POINT_OVERFLOW = 0xFEFEFEFE;
+		public const uint POINT_VOID = 0xFFFFFFFF;
+		public const byte POINT_OVERFLOW_B = 0xFE;
+		public const byte POINT_VOID_B = 0xFF;
+		
+		// Members
+		private Point position;
+		private uint[][] points;
+		private int nextindex;
+		
+		// Properties
+		public Point Position { get { return position; } }
+		public bool IsComplete { get { return nextindex == (TILE_SIZE * TILE_SIZE); } }
+
+		// Constructor
+		public Tile(Point lefttoppos)
+		{
+			// Make the jagged array
+			// I use a jagged array because, allegedly, it performs better than a multidimensional array.
+			points = new uint[TILE_SIZE][];
+			for(int y = 0; y < TILE_SIZE; y++)
+				points[y] = new uint[TILE_SIZE];
+			
+			position = lefttoppos;
+		}
+
+		// This receives a processed point
+		public void StorePointData(PointData pd)
+		{
+			uint t;
+			switch(pd.result)
+			{
+				case PointResult.OK:
+					uint vp = (uint)Math.Min((pd.visplanes + (STATS_COMPRESSOR[(int)ViewStats.Visplanes] - 1)) / STATS_COMPRESSOR[(int)ViewStats.Visplanes], POINT_MAXRANGE);
+					uint ds = (uint)Math.Min((pd.drawsegs + (STATS_COMPRESSOR[(int)ViewStats.Drawsegs] - 1)) / STATS_COMPRESSOR[(int)ViewStats.Drawsegs], POINT_MAXRANGE);
+					uint ss = (uint)Math.Min((pd.solidsegs + (STATS_COMPRESSOR[(int)ViewStats.Solidsegs] - 1)) / STATS_COMPRESSOR[(int)ViewStats.Solidsegs], POINT_MAXRANGE);
+					uint op = (uint)Math.Min((pd.openings + (STATS_COMPRESSOR[(int)ViewStats.Openings] - 1)) / STATS_COMPRESSOR[(int)ViewStats.Openings], POINT_MAXRANGE);
+					t = MakePointValue(vp, ds, ss, op);
+					break;
+
+				case PointResult.BadZ:
+					t = MakePointValue(1, 0, 0, 0);
+					break;
+					
+				case PointResult.Void:
+					t = POINT_VOID;
+					break;
+
+				case PointResult.Overflow:
+				default:
+					t = POINT_OVERFLOW;
+					break;
+			}
+
+			FillPoints(ref pd.point, t);
+		}
+
+		// This fills points with the given tile data over the specified granularity
+		private void FillPoints(ref TilePoint p, uint t)
+		{
+			int xs = p.x - position.X;
+			int ys = p.y - position.Y;
+			int xe = xs + p.granularity;
+			int ye = ys + p.granularity;
+			for(int x = xs; x < xe; x++)
+				for(int y = ys; y < ye; y++)
+					points[y][x] = t;
+		}
+
+		// This composes point values
+		private uint MakePointValue(uint vp, uint ds, uint ss, uint op)
+		{
+			unchecked
+			{
+				return vp + (ds << 8) + (ss << 16) + (op << 24);
+			}
+		}
+
+		// This returns a point value
+		public byte GetPointByte(int x, int y, int stat)
+		{
+			unchecked
+			{
+				uint v = points[y][x];
+				return (byte)((v >> (stat * 8)) & 0xFF);
+			}
+		}
+		
+		// This returns a point value
+		public int GetPointValue(int x, int y, int stat)
+		{
+			byte b = GetPointByte(x, y, stat);
+			return (int)b * STATS_COMPRESSOR[stat];
+		}
+
+		// This returns the next point to process
+		public TilePoint GetNextPoint()
+		{
+			TilePoint p = PointByIndex(nextindex++);
+			p.x += position.X;
+			p.y += position.Y;
+			return p;
+		}
+
+		// Returns a position by index
+		public TilePoint PointByIndex(int index)
+		{
+			#if DEBUG
+			if(index > (TILE_SIZE * TILE_SIZE))
+				throw new IndexOutOfRangeException();
+			#endif
+
+			TilePoint p;
+			
+			// Would be nicer if this could be done without branching or looping...
+			if(index == 0) p.granularity = 64;
+			else if(index < 4) p.granularity = 32;
+			else if(index < 16) p.granularity = 16;
+			else if(index < 64) p.granularity = 8;
+			else if(index < 256) p.granularity = 4;
+			else if(index < 1024) p.granularity = 2;
+			else p.granularity = 1;
+			
+			// this is a "butterfly" style sequence, which begins like:
+			//    ( 0  0)  (32 32)  ( 0 32)  (32  0)
+			//    (16 16)  (48 48)  (16 48)  (48 16)
+			//    ( 0 16)  (32 48)  ( 0 48)  (32 16)
+			//    (16  0)  (48 32)  (16 32)  (48  0)
+			//    ( 8  8)  (40 40)  ( 8 40)  (40  8)
+			//    etc....
+
+			p.x = (index & 1) << 5;
+			p.y = (((index >> 1) ^ index) & 1) << 5;
+
+			index >>= 2;
+			p.x += (index & 1) << 4;
+			p.y += (((index >> 1) ^ index) & 1) << 4;
+
+			index >>= 2;
+			p.x |= (index & 1) << 3;
+			p.y |= (((index >> 1) ^ index) & 1) << 3;
+
+			index >>= 2;
+			p.x |= (index & 1) << 2;
+			p.y |= (((index >> 1) ^ index) & 1) << 2;
+
+			index >>= 2;
+			p.x |= (index & 1) << 1;
+			p.y |= (((index >> 1) ^ index) & 1) << 1;
+
+			index >>= 2;
+			p.x |= index & 1;
+			p.y |= ((index >> 1) ^ index) & 1;
+
+			return p;
+		}
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/TilePoint.cs b/Source/Plugins/VisplaneExplorer/TilePoint.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8a36135187a7f5e68965ccafc9fd942304222501
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/TilePoint.cs
@@ -0,0 +1,19 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal struct TilePoint
+	{
+		public int x;
+		public int y;
+		public byte granularity;
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/VPOManager.cs b/Source/Plugins/VisplaneExplorer/VPOManager.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a36e6b728acabf9d0eb6d725089ca99f7c21019a
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/VPOManager.cs
@@ -0,0 +1,298 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal class VPOManager : IDisposable
+	{
+		#region ================== Constants
+
+		public const int POINTS_PER_ITERATION = 100;
+		private const int EXPECTED_RESULTS_BUFFER = 200000;
+
+		private readonly int[] TEST_ANGLES = new int[] { 0, 90, 180, 270, 45, 135, 225, 315 /*, 22, 67, 112, 157, 202, 247, 292, 337 */ };
+		private const int TEST_HEIGHT = 41 + 8;
+
+		private const int RESULT_OK = 0;
+		private const int RESULT_BAD_Z = -1;
+		private const int RESULT_IN_VOID = -2;
+		private const int RESULT_OVERFLOW = -3;
+		
+		#endregion
+
+		#region ================== APIs
+
+		[DllImport("kernel32.dll")]
+		public static extern IntPtr LoadLibrary(string filename);
+
+		[DllImport("kernel32.dll")]
+		public static extern IntPtr GetProcAddress(IntPtr modulehandle, string procedurename);
+
+		[DllImport("kernel32.dll")]
+		public static extern bool FreeLibrary(IntPtr modulehandle);
+		
+		#endregion
+
+		#region ================== Delegates
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		private delegate string VPO_GetError();
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		private delegate int VPO_LoadWAD(string filename);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		private delegate int VPO_OpenMap(string mapname);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		private delegate void VPO_FreeWAD();
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		private delegate void VPO_CloseMap();
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		private delegate int VPO_TestSpot(int x, int y, int dz, int angle,
+			ref int visplanes, ref int drawsegs, ref int openings, ref int solidsegs);
+
+		#endregion
+
+		#region ================== Variables
+
+		// Main objects
+		private string[] tempfiles;
+		private IntPtr[] dlls;
+		private Thread[] threads;
+
+		// Map to load
+		private string filename;
+		private string mapname;
+
+		// Input and output queue (both require a lock on 'points' !)
+		private Queue<TilePoint> points = new Queue<TilePoint>(EXPECTED_RESULTS_BUFFER);
+		private Queue<PointData> results = new Queue<PointData>(EXPECTED_RESULTS_BUFFER);
+		
+		#endregion
+
+		#region ================== Properties
+
+		public int NumThreads { get { return Environment.ProcessorCount; } }
+
+		#endregion
+
+		#region ================== Constructor / Destructor
+		
+		// Constructor
+		public VPOManager()
+		{
+			// Load a DLL for each thread
+			dlls = new IntPtr[NumThreads];
+			tempfiles = new string[NumThreads];
+			
+			// We must write the DLL file with a unique name for every thread,
+			// because LoadLibrary will share loaded libraries with the same
+			// names and LoadLibraryEx does not have a flag to force loading
+			// it multiple times.
+			Assembly thisasm = Assembly.GetExecutingAssembly();
+			Stream dllstream = thisasm.GetManifestResourceStream("CodeImp.DoomBuilder.Plugins.VisplaneExplorer.Resources.vpo.dll");
+			dllstream.Seek(0, SeekOrigin.Begin);
+			byte[] dllbytes = new byte[dllstream.Length];
+			dllstream.Read(dllbytes, 0, dllbytes.Length);
+			for(int i = 0; i < dlls.Length; i++)
+			{
+				// Write file with unique filename
+				tempfiles[i] = BuilderPlug.MakeTempFilename(".dll");
+				File.WriteAllBytes(tempfiles[i], dllbytes);
+				
+				// Load it
+				dlls[i] = LoadLibrary(tempfiles[i]);
+				if(dlls[i] == IntPtr.Zero) throw new Exception("Unable to load vpo.dll");
+			}
+		}
+
+		// Disposer
+		public void Dispose()
+		{
+			if(threads != null) Stop();
+			
+			if(dlls != null)
+			{
+				for(int i = 0; i < dlls.Length; i++)
+				{
+					FreeLibrary(dlls[i]);
+					File.Delete(tempfiles[i]);
+				}
+				dlls = null;
+			}
+		}
+		
+		#endregion
+
+		#region ================== Processing
+
+		// The thread!
+		private void ProcessingThread(object index)
+		{
+			// Get function pointers
+			VPO_GetError GetError = (VPO_GetError)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dlls[(int)index], "VPO_GetError"), typeof(VPO_GetError));
+			VPO_LoadWAD LoadWAD = (VPO_LoadWAD)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dlls[(int)index], "VPO_LoadWAD"), typeof(VPO_LoadWAD));
+			VPO_OpenMap OpenMap = (VPO_OpenMap)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dlls[(int)index], "VPO_OpenMap"), typeof(VPO_OpenMap));
+			VPO_FreeWAD FreeWAD = (VPO_FreeWAD)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dlls[(int)index], "VPO_FreeWAD"), typeof(VPO_FreeWAD));
+			VPO_CloseMap CloseMap = (VPO_CloseMap)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dlls[(int)index], "VPO_CloseMap"), typeof(VPO_CloseMap));
+			VPO_TestSpot TestSpot = (VPO_TestSpot)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dlls[(int)index], "VPO_TestSpot"), typeof(VPO_TestSpot));
+
+			try
+			{
+				// Load the map
+				if(LoadWAD(filename) != 0) throw new Exception("VPO is unable to read this file.");
+				if(OpenMap(mapname) != 0) throw new Exception("VPO is unable to open this map.");
+
+				// Processing
+				Queue<TilePoint> todo = new Queue<TilePoint>(POINTS_PER_ITERATION);
+				Queue<PointData> done = new Queue<PointData>(POINTS_PER_ITERATION);
+				while(true)
+				{
+					lock(points)
+					{
+						// Flush done points to the results
+						int numdone = done.Count;
+						for(int i = 0; i < numdone; i++)
+							results.Enqueue(done.Dequeue());
+						
+						// Get points from the waiting queue into my todo queue for processing
+						int numtodo = Math.Min(POINTS_PER_ITERATION, points.Count);
+						for(int i = 0; i < numtodo; i++)
+							todo.Enqueue(points.Dequeue());
+					}
+
+					// Don't keep locking!
+					if(todo.Count == 0)
+						Thread.Sleep(31);
+					
+					// Process the points
+					while(todo.Count > 0)
+					{
+						TilePoint p = todo.Dequeue();
+						PointData pd = new PointData();
+						pd.point = p;
+
+						for(int i = 0; i < TEST_ANGLES.Length; i++)
+						{
+							pd.result = (PointResult)TestSpot(p.x, p.y, TEST_HEIGHT, TEST_ANGLES[i],
+								ref pd.visplanes, ref pd.drawsegs, ref pd.openings, ref pd.solidsegs);
+						}
+
+						done.Enqueue(pd);
+					}
+				}
+			}
+			catch(ThreadInterruptedException)
+			{
+			}
+			finally
+			{
+				CloseMap();
+				FreeWAD();
+			}
+		}
+
+		#endregion
+
+		#region ================== Public Methods
+
+		// This loads a map
+		public void Start(string filename, string mapname)
+		{
+			this.filename = filename;
+			this.mapname = mapname;
+			results.Clear();
+			
+			// Start a thread on each core
+			threads = new Thread[dlls.Length];
+			for(int i = 0; i < threads.Length; i++)
+			{
+				threads[i] = new Thread(ProcessingThread);
+				threads[i].Priority = ThreadPriority.BelowNormal;
+				threads[i].Name = "Visplane Explorer " + i;
+				threads[i].Start(i);
+			}
+		}
+
+		// This frees the map
+		public void Stop()
+		{
+			if(threads != null)
+			{
+				lock(points)
+				{
+					// Stop all threads
+					for(int i = 0; i < threads.Length; i++)
+					{
+						threads[i].Interrupt();
+						threads[i].Join();
+					}
+					threads = null;
+					points.Clear();
+					results.Clear();
+				}
+			}
+		}
+
+		// This clears the list of enqueued points
+		public void ClearPoints()
+		{
+			lock(points)
+			{
+				points.Clear();
+			}
+		}
+
+		// This gives points to process and returns the total points left in the buffer
+		public int EnqueuePoints(IEnumerable<TilePoint> newpoints)
+		{
+			lock(points)
+			{
+				foreach(TilePoint p in newpoints)
+					points.Enqueue(p);
+				return points.Count;
+			}
+		}
+
+		// This fetches results (in 'data') and returns the number of points
+		// remaining to be processed.
+		public int DequeueResults(List<PointData> data)
+		{
+			lock(points)
+			{
+				int numresults = results.Count;
+				if(data.Capacity - data.Count < numresults)
+					data.Capacity = data.Count + numresults;
+				for(int i = 0; i < numresults; i++)
+					data.Add(results.Dequeue());
+				return points.Count;
+			}
+		}
+
+		// This returns the number of points left in the buffer
+		public int GetRemainingPoints()
+		{
+			lock(points)
+			{
+				return points.Count;
+			}
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/ViewStats.cs b/Source/Plugins/VisplaneExplorer/ViewStats.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6444637b93bf2ba7c71220bbc6b23c45125bb0ad
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/ViewStats.cs
@@ -0,0 +1,22 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	internal enum ViewStats : int
+	{
+		Visplanes = 0,
+		Drawsegs = 1,
+		Solidsegs = 2,
+		Openings = 3,
+		
+		NumStats = 4
+	}
+}
diff --git a/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj b/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..afd2c58d03439c293d3baf8fb1b0e2aeafdf8463
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{CF670175-7099-4090-A330-EE25C7230139}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>CodeImp.DoomBuilder.Plugins.VisplaneExplorer</RootNamespace>
+    <AssemblyName>VisplaneExplorer</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkSubset>Client</TargetFrameworkSubset>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BuilderPlug.cs" />
+    <Compile Include="InterfaceForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="InterfaceForm.Designer.cs">
+      <DependentUpon>InterfaceForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="NearestLineBlockmap.cs" />
+    <Compile Include="Palette.cs" />
+    <Compile Include="PointData.cs" />
+    <Compile Include="PointResult.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Tile.cs" />
+    <Compile Include="TilePoint.cs" />
+    <Compile Include="ViewStats.cs" />
+    <Compile Include="VisplaneExplorerMode.cs" />
+    <Compile Include="VPOManager.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resources\Actions.cfg" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\Drawsegs.png" />
+    <None Include="Resources\Drawsegs_pal.png" />
+    <Content Include="Resources\Gauge.ico" />
+    <EmbeddedResource Include="InterfaceForm.resx">
+      <DependentUpon>InterfaceForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\Gauge.png" />
+    <Content Include="Resources\Gauge_large.ico" />
+    <EmbeddedResource Include="Resources\vpo.dll" />
+    <None Include="Resources\Solidsegs_pal.png" />
+    <None Include="Resources\Openings_pal.png" />
+    <None Include="Resources\Visplanes_pal.png" />
+    <None Include="Resources\Openings.png" />
+    <None Include="Resources\Solidsegs.png" />
+    <None Include="Resources\Visplanes.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Builder.csproj">
+      <Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project>
+      <Name>Builder</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs b/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs
new file mode 100644
index 0000000000000000000000000000000000000000..475cfac549aec155667fcf49722c4c86233f706a
--- /dev/null
+++ b/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs
@@ -0,0 +1,496 @@
+#region === Copyright (c) 2010 Pascal van der Heiden ===
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Globalization;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+using CodeImp.DoomBuilder.Data;
+using CodeImp.DoomBuilder.Editing;
+using System.Drawing.Imaging;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.Windows;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
+{
+	[EditMode(DisplayName = "Visplane Explorer",
+			  SwitchAction = "visplaneexplorermode",
+			  ButtonImage = "Gauge.png",
+			  ButtonOrder = 300,
+			  ButtonGroup = "002_tools",
+			  Volatile = true,
+			  UseByDefault = true,
+			  AllowCopyPaste = false)]
+	public class VisplaneExplorerMode : ClassicMode
+	{
+		#region ================== Constants
+
+		#endregion
+		
+		#region ================== APIs
+
+		[DllImport("kernel32.dll")]
+		static extern void RtlZeroMemory(IntPtr dst, int length);
+
+		#endregion
+
+		#region ================== Variables
+
+		// The image is the ImageData resource for Doom Builder to work with
+		private DynamicBitmapImage image;
+		
+		// This is the bitmap that we will be drawing on
+		private Bitmap canvas;
+		private ViewStats lastviewstats;
+		
+		// Temporary WAD file written for the vpo.dll library
+		private string tempfile;
+
+		// Rectangle around the map
+		private Rectangle mapbounds;
+
+		// 64x64 tiles in map space. These are discarded when outside view.
+		private Dictionary<Point, Tile> tiles = new Dictionary<Point, Tile>();
+
+		// Time when to do another update
+		private DateTime nextupdate;
+
+		// Are we processing?
+		private bool processingenabled;
+		
+		#endregion
+
+		#region ================== Properties
+
+		#endregion
+
+		#region ================== Constructor / Destructor
+
+		// Constructor
+		public VisplaneExplorerMode()
+		{
+		}
+
+		// Disposer
+		public override void Dispose()
+		{
+			base.Dispose();
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// This cleans up anything we used for this mode
+		private void CleanUp()
+		{
+			BuilderPlug.VPO.Stop();
+
+			if(processingenabled)
+			{
+				General.Interface.DisableProcessing();
+				processingenabled = false;
+			}
+			
+			if(!string.IsNullOrEmpty(tempfile))
+			{
+				File.Delete(tempfile);
+				tempfile = null;
+			}
+
+			if(image != null)
+			{
+				image.Dispose();
+				image = null;
+			}
+
+			if(canvas != null)
+			{
+				canvas.Dispose();
+				canvas = null;
+			}
+
+			tiles.Clear();
+			BuilderPlug.InterfaceForm.HideTooltip();
+			BuilderPlug.InterfaceForm.RemoveFromInterface();
+		}
+
+		// This returns the tile position for the given map coordinate
+		private Point TileForPoint(float x, float y)
+		{
+			return new Point((int)Math.Floor(x / (float)Tile.TILE_SIZE) * Tile.TILE_SIZE, (int)Math.Floor(y / (float)Tile.TILE_SIZE) * Tile.TILE_SIZE);
+		}
+
+		// This draws all tiles on the image
+		// THIS MUST BE FAST! TOP PERFORMANCE REQUIRED!
+		private unsafe void RedrawAllTiles()
+		{
+			if(canvas == null) return;
+
+			// Determine viewport rectangle in map space
+			Vector2D mapleftbot = Renderer.DisplayToMap(new Vector2D(0f, 0f));
+			Vector2D maprighttop = Renderer.DisplayToMap(new Vector2D(General.Interface.Display.ClientSize.Width, General.Interface.Display.ClientSize.Height));
+			Rectangle mapviewrect = new Rectangle((int)mapleftbot.x - Tile.TILE_SIZE, (int)maprighttop.y - Tile.TILE_SIZE, (int)maprighttop.x - (int)mapleftbot.x + Tile.TILE_SIZE, (int)mapleftbot.y - (int)maprighttop.y + Tile.TILE_SIZE);
+
+			int viewstats = (int)BuilderPlug.InterfaceForm.ViewStats;
+			Palette pal = BuilderPlug.Palettes[viewstats];
+			
+			Size canvassize = canvas.Size;
+			BitmapData bd = canvas.LockBits(new Rectangle(0, 0, canvassize.Width, canvassize.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+			RtlZeroMemory(bd.Scan0, bd.Width * bd.Height * 4);
+			int* p = (int*)bd.Scan0.ToPointer();
+
+			foreach(KeyValuePair<Point, Tile> t in tiles)
+			{
+				if(!mapviewrect.Contains(t.Key)) continue;
+				
+				// Map this tile to screen space
+				Vector2D lb = Renderer.MapToDisplay(new Vector2D(t.Value.Position.X, t.Value.Position.Y));
+				Vector2D rt = Renderer.MapToDisplay(new Vector2D(t.Value.Position.X + Tile.TILE_SIZE, t.Value.Position.Y + Tile.TILE_SIZE));
+
+				// Make sure the coordinates are aligned with canvas pixels
+				float x1 = (float)Math.Round(lb.x);
+				float x2 = (float)Math.Round(rt.x);
+				float y1 = (float)Math.Round(rt.y);
+				float y2 = (float)Math.Round(lb.y);
+
+				// Determine width and height of the screen space area for this tile
+				float w = x2 - x1;
+				float h = y2 - y1;
+				float winv = 1f / w;
+				float hinv = 1f / h;
+
+				// Loop ranges. These are relative to the left-top of the tile.
+				float sx = 0f;
+				float sy = 0f;
+				float ex = w;
+				float ey = h;
+				int screenx = (int)x1;
+				int screenystart = (int)y1;
+				
+				// Clipping the loop ranges against canvas boundary.
+				if(x1 < 0f) { sx = -x1; screenx = 0; }
+				if(y1 < 0f) { sy = -y1; screenystart = 0; }
+				if(x2 > bd.Width) ex = w - (x2 - bd.Width);
+				if(y2 > bd.Height) ey = h - (y2 - bd.Height);
+				
+				// Draw all pixels within this tile
+				for(float x = sx; x < ex; x++, screenx++)
+				{
+					int screeny = screenystart;
+					for(float y = sy; y < ey; y++, screeny++)
+					{
+						// Calculate the relative offset in map coordinates for this pixel
+						float ux = x * winv * Tile.TILE_SIZE;
+						float uy = y * hinv * Tile.TILE_SIZE;
+
+						// Get the data and apply the color
+						byte value = t.Value.GetPointByte((int)ux, Tile.TILE_SIZE - 1 - (int)uy, viewstats);
+						p[screeny * bd.Width + screenx] = pal.Colors[value];
+					}
+				}
+			}
+			
+			canvas.UnlockBits(bd);
+			image.UpdateTexture();
+		}
+
+		// This queues points for all current tiles
+		private void QueuePoints(int pointsleft)
+		{
+			// Determine viewport rectangle in map space
+			Vector2D mapleftbot = Renderer.DisplayToMap(new Vector2D(0f, 0f));
+			Vector2D maprighttop = Renderer.DisplayToMap(new Vector2D(General.Interface.Display.ClientSize.Width, General.Interface.Display.ClientSize.Height));
+			Rectangle mapviewrect = new Rectangle((int)mapleftbot.x - Tile.TILE_SIZE, (int)maprighttop.y - Tile.TILE_SIZE, (int)maprighttop.x - (int)mapleftbot.x + Tile.TILE_SIZE, (int)mapleftbot.y - (int)maprighttop.y + Tile.TILE_SIZE);
+			
+			while(pointsleft < (VPOManager.POINTS_PER_ITERATION * BuilderPlug.VPO.NumThreads * 5))
+			{
+				// Collect points from the tiles in the current view
+				List<TilePoint> newpoints = new List<TilePoint>(tiles.Count);
+				foreach(KeyValuePair<Point, Tile> t in tiles)
+					if((!t.Value.IsComplete) && (mapviewrect.Contains(t.Key))) newpoints.Add(t.Value.GetNextPoint());
+				
+				// If the current view is complete, try getting points from all tiles
+				if(newpoints.Count == 0)
+				{
+					foreach(KeyValuePair<Point, Tile> t in tiles)
+						if(!t.Value.IsComplete) newpoints.Add(t.Value.GetNextPoint());
+				}
+				
+				if(newpoints.Count == 0) break;
+				pointsleft = BuilderPlug.VPO.EnqueuePoints(newpoints);
+			}
+		}
+
+		// This updates the overlay
+		private void UpdateOverlay()
+		{
+			// We must redraw the tiles to the canvas when the stats to view has changed
+			if(lastviewstats != BuilderPlug.InterfaceForm.ViewStats)
+			{
+				RedrawAllTiles();
+				lastviewstats = BuilderPlug.InterfaceForm.ViewStats;
+			}
+			
+			// Render the overlay
+			if(renderer.StartOverlay(true))
+			{
+				// Render the canvas to screen
+				RectangleF r = new RectangleF(0, 0, canvas.Width, canvas.Height);
+				renderer.RenderRectangleFilled(r, PixelColor.FromColor(Color.White), false, image);
+
+				// Render any selection
+				if(selecting) RenderMultiSelection();
+
+				// Finish our rendering to this layer.
+				renderer.Finish();
+			}
+		}
+
+		#endregion
+
+		#region ================== Events
+
+		// Mode starts
+		public override void OnEngage()
+		{
+			Cursor.Current = Cursors.WaitCursor;
+			base.OnEngage();
+			General.Interface.DisplayStatus(StatusType.Busy, "Setting up test environment...");
+			
+			CleanUp();
+
+			BuilderPlug.InterfaceForm.AddToInterface();
+			lastviewstats = BuilderPlug.InterfaceForm.ViewStats;
+			
+			// Export the current map to a temporary WAD file
+			tempfile = BuilderPlug.MakeTempFilename(".wad");
+			General.Map.ExportToFile(tempfile);
+			
+			// Load the map in VPO_DLL
+			BuilderPlug.VPO.Start(tempfile, General.Map.Options.LevelName);
+
+			// Determine map boundary
+			mapbounds = Rectangle.Round(MapSet.CreateArea(General.Map.Map.Vertices));
+
+			// Create tiles for all points inside the map
+			Point lt = TileForPoint(mapbounds.Left - Tile.TILE_SIZE, mapbounds.Top - Tile.TILE_SIZE);
+			Point rb = TileForPoint(mapbounds.Right + Tile.TILE_SIZE, mapbounds.Bottom + Tile.TILE_SIZE);
+			Rectangle tilesrect = new Rectangle(lt.X, lt.Y, rb.X - lt.X, rb.Y - lt.Y);
+			NearestLineBlockmap blockmap = new NearestLineBlockmap(tilesrect);
+			for(int x = tilesrect.X; x <= tilesrect.Right; x += Tile.TILE_SIZE)
+			{
+				for(int y = tilesrect.Y; y <= tilesrect.Bottom; y += Tile.TILE_SIZE)
+				{
+					// If the tile is obviously outside the map, don't create it
+					Vector2D pc = new Vector2D(x + (Tile.TILE_SIZE >> 1), y + (Tile.TILE_SIZE >> 1));
+					Linedef ld = MapSet.NearestLinedef(blockmap.GetBlockAt(pc).Lines, pc);
+					float distancesq = ld.DistanceToSq(pc, true);
+					if(distancesq > (Tile.TILE_SIZE * Tile.TILE_SIZE))
+					{
+						float side = ld.SideOfLine(pc);
+						if((side > 0.0f) && (ld.Back == null)) continue;
+					}
+
+					Point tp = new Point(x, y);
+					tiles.Add(tp, new Tile(tp));
+				}
+			}
+
+			QueuePoints(0);
+
+			// Make an image to draw on.
+			// The BitmapImage for Doom Builder's resources must be Format32bppArgb and NOT using color correction,
+			// otherwise DB will make a copy of the bitmap when LoadImage() is called! This is normally not a problem,
+			// but we want to keep drawing to the same bitmap.
+			int width = General.NextPowerOf2(General.Interface.Display.ClientSize.Width);
+			int height = General.NextPowerOf2(General.Interface.Display.ClientSize.Height);
+			canvas = new Bitmap(width, height, PixelFormat.Format32bppArgb);
+			image = new DynamicBitmapImage(canvas, "_CANVAS_");
+			image.UseColorCorrection = false;
+			image.MipMapLevels = 1;
+			image.LoadImage();
+			image.CreateTexture();
+
+			// Make custom presentation
+			CustomPresentation p = new CustomPresentation();
+			p.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Mask, 1f, false));
+			p.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask));
+			p.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1f, true));
+			renderer.SetPresentation(p);
+
+			// Setup processing
+			nextupdate = DateTime.Now + new TimeSpan(0, 0, 0, 0, 100);
+			General.Interface.EnableProcessing();
+			processingenabled = true;
+
+			RedrawAllTiles();
+			Cursor.Current = Cursors.Default;
+			General.Interface.SetCursor(Cursors.Cross);
+			General.Interface.DisplayReady();
+		}
+
+		// Mode ends
+		public override void OnDisengage()
+		{
+			CleanUp();
+			base.OnDisengage();
+		}
+
+		// Cancelled
+		public override void OnCancel()
+		{
+			// Cancel base class
+			base.OnCancel();
+
+			// Return to previous mode
+			General.Editing.ChangeMode(General.Editing.PreviousStableMode.Name);
+		}
+
+		// View position/scale changed!
+		protected override void OnViewChanged()
+		{
+			base.OnViewChanged();
+
+			RedrawAllTiles();
+			
+			// Update the screen sooner
+			nextupdate = DateTime.Now + new TimeSpan(0, 0, 0, 0, 100);
+		}
+
+		// Draw the display
+		public override void OnRedrawDisplay()
+		{
+			base.OnRedrawDisplay();
+			
+			// Render the overlay
+			UpdateOverlay();
+
+			// Render lines and vertices
+			if(renderer.StartPlotter(true))
+			{
+				renderer.PlotLinedefSet(General.Map.Map.Linedefs);
+				renderer.PlotVerticesSet(General.Map.Map.Vertices);
+				renderer.Finish();
+			}
+			renderer.Present();
+		}
+
+		// Processing
+		public override void OnProcess(double deltatime)
+		{
+			base.OnProcess(deltatime);
+			if(DateTime.Now >= nextupdate)
+			{
+				// Get the processed points from the VPO manager
+				List<PointData> points = new List<PointData>();
+				int pointsleft = BuilderPlug.VPO.DequeueResults(points);
+
+				// Queue more points if needed
+				QueuePoints(pointsleft);
+
+				// Apply the points to the tiles
+				foreach(PointData pd in points)
+				{
+					Tile t;
+					Point tp = TileForPoint(pd.point.x, pd.point.y);
+					if(tiles.TryGetValue(tp, out t))
+						t.StorePointData(pd);
+				}
+
+				// Redraw
+				RedrawAllTiles();
+				General.Interface.RedrawDisplay();
+
+				nextupdate = DateTime.Now + new TimeSpan(0, 0, 0, 0, 500);
+			}
+			else
+			{
+				// Queue more points if needed
+				QueuePoints(BuilderPlug.VPO.GetRemainingPoints());
+			}
+		}
+
+		// LMB pressed
+		protected override void OnSelectBegin()
+		{
+			StartMultiSelection();
+			BuilderPlug.InterfaceForm.HideTooltip();
+			base.OnSelectBegin();
+		}
+
+		// Multiselecting
+		protected override void OnUpdateMultiSelection()
+		{
+			base.OnUpdateMultiSelection();
+			
+			UpdateOverlay();
+			renderer.Present();
+		}
+
+		// Multiselect ends
+		protected override void OnEndMultiSelection()
+		{
+			base.OnEndMultiSelection();
+			if((selectionrect.Width < 64f) && (selectionrect.Height < 64f))
+				selectionrect.Inflate(64f, 64f);
+			base.CenterOnArea(selectionrect, 0.1f);
+		}
+
+		// Mouse moves
+		public override void OnMouseMove(MouseEventArgs e)
+		{
+			base.OnMouseMove(e);
+
+			if(!selecting)
+			{
+				int viewstats = (int)BuilderPlug.InterfaceForm.ViewStats;
+				
+				// Get the tile data for the current position
+				Point tp = TileForPoint(mousemappos.x, mousemappos.y);
+				Tile t;
+				if(tiles.TryGetValue(tp, out t))
+				{
+					int x = (int)Math.Floor(mousemappos.x) - t.Position.X;
+					int y = (int)Math.Floor(mousemappos.y) - t.Position.Y;
+					byte b = t.GetPointByte(x, y, viewstats);
+					if(b != Tile.POINT_VOID_B)
+					{
+						// Setup hoverlabel
+						int value = t.GetPointValue(x, y, viewstats);
+						Point p = new Point((int)mousepos.x + 5, (int)mousepos.y + 5);
+						string appendoverflow = (b == Tile.POINT_OVERFLOW_B) ? "+" : "";
+						BuilderPlug.InterfaceForm.ShowTooltip(value + appendoverflow + " / " + Tile.STATS_LIMITS[viewstats], p);
+					}
+					else
+					{
+						// Void
+						BuilderPlug.InterfaceForm.HideTooltip();
+					}
+				}
+				else
+				{
+					BuilderPlug.InterfaceForm.HideTooltip();
+				}
+			}
+		}
+
+		// Mouse leaves
+		public override void OnMouseLeave(EventArgs e)
+		{
+			base.OnMouseLeave(e);
+			BuilderPlug.InterfaceForm.HideTooltip();
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/vpo_dll/doomdata.h b/Source/Plugins/vpo_dll/doomdata.h
new file mode 100644
index 0000000000000000000000000000000000000000..a87ae6c68cf9709fba69d990373f253f6e338932
--- /dev/null
+++ b/Source/Plugins/vpo_dll/doomdata.h
@@ -0,0 +1,221 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//  all external data is defined here
+//  most of the data is loaded into different structures at run time
+//  some internal structures shared by many modules are here
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __DOOMDATA__
+#define __DOOMDATA__
+
+// The most basic types we use, portability.
+#include "doomtype.h"
+
+// Some global defines, that configure the game.
+#include "doomdef.h"
+
+
+
+//
+// Map level types.
+// The following data structures define the persistent format
+// used in the lumps of the WAD files.
+//
+
+// Lump order in a map WAD: each map needs a couple of lumps
+// to provide a complete scene geometry description.
+enum
+{
+  ML_LABEL,		// A separator, name, ExMx or MAPxx
+  ML_THINGS,		// Monsters, items..
+  ML_LINEDEFS,		// LineDefs, from editing
+  ML_SIDEDEFS,		// SideDefs, from editing
+  ML_VERTEXES,		// Vertices, edited and BSP splits generated
+  ML_SEGS,		// LineSegs, from LineDefs split by BSP
+  ML_SSECTORS,		// SubSectors, list of LineSegs
+  ML_NODES,		// BSP nodes
+  ML_SECTORS,		// Sectors, from editing
+  ML_REJECT,		// LUT, sector-sector visibility	
+  ML_BLOCKMAP		// LUT, motion clipping, walls/grid element
+};
+
+
+// A single Vertex.
+typedef struct
+{
+  short		x;
+  short		y;
+} PACKEDATTR mapvertex_t;
+
+
+// A SideDef, defining the visual appearance of a wall,
+// by setting textures and offsets.
+typedef struct
+{
+  short		textureoffset;
+  short		rowoffset;
+  char		toptexture[8];
+  char		bottomtexture[8];
+  char		midtexture[8];
+  // Front sector, towards viewer.
+  short		sector;
+} PACKEDATTR mapsidedef_t;
+
+
+
+// A LineDef, as used for editing, and as input
+// to the BSP builder.
+typedef struct
+{
+  short		v1;
+  short		v2;
+  short		flags;
+  short		special;
+  short		tag;
+  // sidenum[1] will be -1 if one sided
+  short		sidenum[2];		
+} PACKEDATTR maplinedef_t;
+
+
+//
+// LineDef attributes.
+//
+
+// Solid, is an obstacle.
+#define ML_BLOCKING		1
+
+// Blocks monsters only.
+#define ML_BLOCKMONSTERS	2
+
+// Backside will not be present at all
+//  if not two sided.
+#define ML_TWOSIDED		4
+
+// If a texture is pegged, the texture will have
+// the end exposed to air held constant at the
+// top or bottom of the texture (stairs or pulled
+// down things) and will move with a height change
+// of one of the neighbor sectors.
+// Unpegged textures allways have the first row of
+// the texture at the top pixel of the line for both
+// top and bottom textures (use next to windows).
+
+// upper texture unpegged
+#define ML_DONTPEGTOP		8
+
+// lower texture unpegged
+#define ML_DONTPEGBOTTOM	16	
+
+// In AutoMap: don't map as two sided: IT'S A SECRET!
+#define ML_SECRET		32
+
+// Sound rendering: don't let sound cross two of these.
+#define ML_SOUNDBLOCK		64
+
+// Don't draw on the automap at all.
+#define ML_DONTDRAW		128
+
+// Set if already seen, thus drawn in automap.
+#define ML_MAPPED		256
+
+
+
+
+// Sector definition, from editing.
+typedef	struct
+{
+  short		floorheight;
+  short		ceilingheight;
+  char		floorpic[8];
+  char		ceilingpic[8];
+  short		lightlevel;
+  short		special;
+  short		tag;
+} PACKEDATTR mapsector_t;
+
+// SubSector, as generated by BSP.
+typedef struct
+{
+  short		numsegs;
+  // Index of first one, segs are stored sequentially.
+  short		firstseg;	
+} PACKEDATTR mapsubsector_t;
+
+
+// LineSeg, generated by splitting LineDefs
+// using partition lines selected by BSP builder.
+typedef struct
+{
+  short		v1;
+  short		v2;
+  short		angle;		
+  short		linedef;
+  short		side;
+  short		offset;
+} PACKEDATTR mapseg_t;
+
+
+
+// BSP node structure.
+
+// Indicate a leaf.
+#define	NF_SUBSECTOR	0x8000
+
+typedef struct
+{
+  // Partition line from (x,y) to x+dx,y+dy)
+  short		x;
+  short		y;
+  short		dx;
+  short		dy;
+
+  // Bounding box for each child,
+  // clip against view frustum.
+  short		bbox[2][4];
+
+  // If NF_SUBSECTOR its a subsector,
+  // else it's a node of another subtree.
+  unsigned short	children[2];
+
+} PACKEDATTR mapnode_t;
+
+
+
+
+// Thing definition, position, orientation and type,
+// plus skill/visibility flags and attributes.
+typedef struct
+{
+    short		x;
+    short		y;
+    short		angle;
+    short		type;
+    short		options;
+} PACKEDATTR mapthing_t;
+
+
+
+
+
+#endif			// __DOOMDATA__
diff --git a/Source/Plugins/vpo_dll/doomdef.h b/Source/Plugins/vpo_dll/doomdef.h
new file mode 100644
index 0000000000000000000000000000000000000000..abc03041b2ad9141b50e42e25a42e9e26e773795
--- /dev/null
+++ b/Source/Plugins/vpo_dll/doomdef.h
@@ -0,0 +1,258 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//  Internally used data structures for virtually everything,
+//   lots of other stuff.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __DOOMDEF__
+#define __DOOMDEF__
+
+
+// #define macros to provide functions missing in Windows.
+// Outside Windows, we use strings.h for str[n]casecmp.
+
+
+#ifdef _WIN32
+
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+
+#else
+
+#include <strings.h>
+
+#endif
+
+
+//
+// The packed attribute forces structures to be packed into the minimum 
+// space necessary.  If this is not done, the compiler may align structure
+// fields differently to optimize memory access, inflating the overall
+// structure size.  It is important to use the packed attribute on certain
+// structures where alignment is important, particularly data read/written
+// to disk.
+//
+
+#ifdef __GNUC__
+#define PACKEDATTR __attribute__((packed))
+#else
+#define PACKEDATTR
+#endif
+
+//
+// Global parameters/defines.
+//
+// DOOM version
+#define DOOM_VERSION 109
+
+// Version code for cph's longtics hack ("v1.91")
+#define DOOM_191_VERSION 111
+
+
+// Game mode handling - identify IWAD version
+//  to handle IWAD dependend animations etc.
+typedef enum
+{
+  shareware,	// DOOM 1 shareware, E1, M9
+  registered,	// DOOM 1 registered, E3, M27
+  commercial,	// DOOM 2 retail, E1 M34
+  // DOOM 2 german edition not handled
+  retail,	// DOOM 1 retail, E4, M36
+  indetermined	// Well, no IWAD found.
+  
+} GameMode_t;
+
+
+// Mission packs - might be useful for TC stuff?
+typedef enum
+{
+  doom,		// DOOM 1
+  doom2,	// DOOM 2
+  pack_tnt,	// TNT mission pack
+  pack_plut,	// Plutonia pack
+  none
+
+} GameMission_t;
+
+// What version are we emulating?
+
+typedef enum
+{
+    exe_doom_1_9,   // Doom 1.9: used for shareware, registered and commercial
+    exe_hacx,       // Hacx executable (Doom 1.9 with patch applied)
+    exe_ultimate,   // Ultimate Doom (retail)
+    exe_final,      // Final Doom
+    exe_final2,     // Final Doom (alternate exe)
+    exe_chex,       // Chex Quest executable (based on Final Doom)
+} GameVersion_t;
+
+
+// If rangecheck is undefined,
+// most parameter validation debugging code will not be compiled
+#define RANGECHECK
+
+
+
+// Screen width and height.
+
+#define SCREENWIDTH  320
+#define SCREENHEIGHT 200
+
+// Screen width used for "squash" scale functions
+
+#define SCREENWIDTH_4_3 256
+
+// Screen height used for "stretch" scale functions.
+
+#define SCREENHEIGHT_4_3 240
+
+// The maximum number of players, multiplayer/networking.
+#define MAXPLAYERS		4
+
+// State updates, number of tics / second.
+#define TICRATE		35
+
+// The current state of the game: whether we are
+// playing, gazing at the intermission screen,
+// the game final animation, or a demo. 
+typedef enum
+{
+    GS_LEVEL,
+    GS_INTERMISSION,
+    GS_FINALE,
+    GS_DEMOSCREEN,
+} gamestate_t;
+
+//
+// Difficulty/skill settings/filters.
+//
+
+// Skill flags.
+#define	MTF_EASY		1
+#define	MTF_NORMAL		2
+#define	MTF_HARD		4
+
+// Deaf monsters/do not react to sound.
+#define	MTF_AMBUSH		8
+
+typedef enum
+{
+    sk_noitems = -1,        // the "-skill 0" hack
+    sk_baby = 0,
+    sk_easy,
+    sk_medium,
+    sk_hard,
+    sk_nightmare
+} skill_t;
+
+
+
+
+//
+// Key cards.
+//
+typedef enum
+{
+    it_bluecard,
+    it_yellowcard,
+    it_redcard,
+    it_blueskull,
+    it_yellowskull,
+    it_redskull,
+    
+    NUMCARDS
+    
+} card_t;
+
+
+
+// The defined weapons,
+//  including a marker indicating
+//  user has not changed weapon.
+typedef enum
+{
+    wp_fist,
+    wp_pistol,
+    wp_shotgun,
+    wp_chaingun,
+    wp_missile,
+    wp_plasma,
+    wp_bfg,
+    wp_chainsaw,
+    wp_supershotgun,
+
+    NUMWEAPONS,
+    
+    // No pending weapon change.
+    wp_nochange
+
+} weapontype_t;
+
+
+// Ammunition types defined.
+typedef enum
+{
+    am_clip,	// Pistol / chaingun ammo.
+    am_shell,	// Shotgun / double barreled shotgun.
+    am_cell,	// Plasma rifle, BFG.
+    am_misl,	// Missile launcher.
+    NUMAMMO,
+    am_noammo	// Unlimited for chainsaw / fist.	
+
+} ammotype_t;
+
+
+// Power up artifacts.
+typedef enum
+{
+    pw_invulnerability,
+    pw_strength,
+    pw_invisibility,
+    pw_ironfeet,
+    pw_allmap,
+    pw_infrared,
+    NUMPOWERS
+    
+} powertype_t;
+
+
+
+//
+// Power up durations,
+//  how many seconds till expiration,
+//  assuming TICRATE is 35 ticks/second.
+//
+typedef enum
+{
+    INVULNTICS	= (30*TICRATE),
+    INVISTICS	= (60*TICRATE),
+    INFRATICS	= (120*TICRATE),
+    IRONTICS	= (60*TICRATE)
+    
+} powerduration_t;
+
+
+#endif          // __DOOMDEF__
diff --git a/Source/Plugins/vpo_dll/doomtype.h b/Source/Plugins/vpo_dll/doomtype.h
new file mode 100644
index 0000000000000000000000000000000000000000..917f246cdea72f914f5f13c5852227b282a12e0f
--- /dev/null
+++ b/Source/Plugins/vpo_dll/doomtype.h
@@ -0,0 +1,84 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Simple basic typedefs, isolated here to make it easier
+//	 separating modules.
+//    
+//-----------------------------------------------------------------------------
+
+
+#ifndef __DOOMTYPE__
+#define __DOOMTYPE__
+
+// Windows CE is missing some vital ANSI C functions.  We have to
+// use our own replacements.
+
+#ifdef _WIN32_WCE
+#include "libc_wince.h"
+#endif
+
+// C99 integer types; with gcc we just use this.  Other compilers 
+// should add conditional statements that define the C99 types.
+
+// What is really wanted here is stdint.h; however, some old versions
+// of Solaris don't have stdint.h and only have inttypes.h (the 
+// pre-standardisation version).  inttypes.h is also in the C99 
+// standard and defined to include stdint.h, so include this. 
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+
+// Use builtin bool type with C++.
+
+typedef bool boolean;
+
+#else
+
+typedef enum 
+{
+    false, 
+    true
+} boolean;
+
+#endif
+
+typedef uint8_t byte;
+
+#include <limits.h>
+
+#ifdef _WIN32
+
+#define DIR_SEPARATOR '\\'
+#define PATH_SEPARATOR ';'
+
+#else
+
+#define DIR_SEPARATOR '/'
+#define PATH_SEPARATOR ':'
+
+#endif
+
+#define arrlen(array) (sizeof(array) / sizeof(*array))
+
+#endif
+
diff --git a/Source/Plugins/vpo_dll/exports.def b/Source/Plugins/vpo_dll/exports.def
new file mode 100644
index 0000000000000000000000000000000000000000..22f7ad629fd9e5bdd279fd14742ccdb38e6b20f0
--- /dev/null
+++ b/Source/Plugins/vpo_dll/exports.def
@@ -0,0 +1,12 @@
+
+EXPORTS
+	
+	VPO_GetError
+	VPO_LoadWAD
+	VPO_FreeWAD
+	VPO_GetMapName
+	VPO_OpenMap
+	VPO_CloseMap
+	VPO_GetLinedef
+	VPO_TestSpot
+	
\ No newline at end of file
diff --git a/Source/Plugins/vpo_dll/inttypes.h b/Source/Plugins/vpo_dll/inttypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b3828a216298df33899652a1574db70ded3f082
--- /dev/null
+++ b/Source/Plugins/vpo_dll/inttypes.h
@@ -0,0 +1,305 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/Source/Plugins/vpo_dll/m_bbox.cc b/Source/Plugins/vpo_dll/m_bbox.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2bb7d6a6a30f36790f6c48cc045b5b8518611d1b
--- /dev/null
+++ b/Source/Plugins/vpo_dll/m_bbox.cc
@@ -0,0 +1,61 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Main loop menu stuff.
+//	Random number LUT.
+//	Default Config File.
+//	PCX Screenshots.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+void M_ClearBox (fixed_t *box)
+{
+    box[BOXTOP] = box[BOXRIGHT] = INT_MIN;
+    box[BOXBOTTOM] = box[BOXLEFT] = INT_MAX;
+}
+
+void
+M_AddToBox
+( fixed_t*	box,
+  fixed_t	x,
+  fixed_t	y )
+{
+    if (x<box[BOXLEFT])
+	box[BOXLEFT] = x;
+    else if (x>box[BOXRIGHT])
+	box[BOXRIGHT] = x;
+    if (y<box[BOXBOTTOM])
+	box[BOXBOTTOM] = y;
+    else if (y>box[BOXTOP])
+	box[BOXTOP] = y;
+}
+
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/m_bbox.h b/Source/Plugins/vpo_dll/m_bbox.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fb79fd6466140fcfeae4ebc7aaf410475e4dca0
--- /dev/null
+++ b/Source/Plugins/vpo_dll/m_bbox.h
@@ -0,0 +1,55 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//    Nil.
+//    
+//-----------------------------------------------------------------------------
+
+
+#ifndef __M_BBOX__
+#define __M_BBOX__
+
+#include <limits.h>
+
+#include "m_fixed.h"
+
+
+// Bounding box coordinate storage.
+enum
+{
+    BOXTOP,
+    BOXBOTTOM,
+    BOXLEFT,
+    BOXRIGHT
+};	// bbox coordinates
+
+// Bounding box functions.
+void M_ClearBox (fixed_t*	box);
+
+void
+M_AddToBox
+( fixed_t*	box,
+  fixed_t	x,
+  fixed_t	y );
+
+
+#endif
diff --git a/Source/Plugins/vpo_dll/m_fixed.cc b/Source/Plugins/vpo_dll/m_fixed.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a3d3a3c980e38dc2a27bfc004629f1165a57f23d
--- /dev/null
+++ b/Source/Plugins/vpo_dll/m_fixed.cc
@@ -0,0 +1,66 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Fixed point implementation.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+// Fixme. __USE_C_FIXED__ or something.
+
+fixed_t
+FixedMul
+( fixed_t	a,
+  fixed_t	b )
+{
+    return ((int64_t) a * (int64_t) b) >> FRACBITS;
+}
+
+
+
+//
+// FixedDiv, C version.
+//
+
+fixed_t FixedDiv(fixed_t a, fixed_t b)
+{
+    if ((abs(a) >> 14) >= abs(b))
+    {
+	return (a^b) < 0 ? INT_MIN : INT_MAX;
+    }
+    else
+    {
+	int64_t result;
+
+	result = ((int64_t) a << 16) / b;
+
+	return (fixed_t) result;
+    }
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/m_fixed.h b/Source/Plugins/vpo_dll/m_fixed.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a1fa20095acc1c1c4464e2959882e3aa939513d
--- /dev/null
+++ b/Source/Plugins/vpo_dll/m_fixed.h
@@ -0,0 +1,42 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Fixed point arithemtics, implementation.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __M_FIXED__
+#define __M_FIXED__
+
+//
+// Fixed point, 32bit as 16.16.
+//
+#define FRACBITS		16
+#define FRACUNIT		(1<<FRACBITS)
+
+typedef int fixed_t;
+
+fixed_t FixedMul	(fixed_t a, fixed_t b);
+fixed_t FixedDiv	(fixed_t a, fixed_t b);
+
+#endif
diff --git a/Source/Plugins/vpo_dll/p_setup.cc b/Source/Plugins/vpo_dll/p_setup.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0266d3d59ea0849cd41147f9f9a7ccb234180bf8
--- /dev/null
+++ b/Source/Plugins/vpo_dll/p_setup.cc
@@ -0,0 +1,662 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Do all the WAD I/O, get map description,
+//	set up initial state and misc. LUTs.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+//
+// MAP related Lookup tables.
+// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
+//
+int		numvertexes;
+vertex_t*	vertexes;
+
+int		numsegs;
+seg_t*		segs;
+
+int		numsectors;
+sector_t*	sectors;
+
+int		numsubsectors;
+subsector_t*	subsectors;
+
+int		numnodes;
+node_t*		nodes;
+
+int		numlines;
+line_t*		lines;
+
+int		numsides;
+side_t*		sides;
+
+
+static int R_TextureNumForName (const char * name)
+{
+  // "NoTexture" marker.
+  if (name[0] == '-')         
+    return 0;
+
+  return 1;  // dummy value
+}
+
+static int R_FlatNumForName (const char * name)
+{
+  // SKY ?
+  if (name[0] == 'F' && name[1] == '_' && name[2] == 'S' && name[3] == 'K')
+    return skyflatnum;
+
+  return 1;  // dummy value
+}
+
+
+//
+// P_LoadVertexes
+//
+void P_LoadVertexes (int lump)
+{
+    byte*		data;
+    int			i;
+    mapvertex_t*	ml;
+    vertex_t*		li;
+
+    // Determine number of lumps:
+    //  total lump length / vertex record length.
+    numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t);
+
+    // Allocate zone memory for buffer.
+    vertexes = new vertex_t[numvertexes];
+
+    // Load data into cache.
+    data = W_LoadLump (lump);
+	
+    ml = (mapvertex_t *)data;
+    li = vertexes;
+
+    // Copy and convert vertex coordinates,
+    // internal representation as fixed.
+    for (i=0 ; i<numvertexes ; i++, li++, ml++)
+    {
+	li->x = SHORT(ml->x)<<FRACBITS;
+	li->y = SHORT(ml->y)<<FRACBITS;
+    }
+
+    // Free buffer memory.
+    W_FreeLump(data);
+}
+
+//
+// GetSectorAtNullAddress
+//
+sector_t* GetSectorAtNullAddress(void)
+{
+    return sectors + 0;
+#if 0
+    static boolean null_sector_is_initialized = false;
+    static sector_t null_sector;
+
+    if (!null_sector_is_initialized)
+    {
+        memset(&null_sector, 0, sizeof(null_sector));
+        I_GetMemoryValue(0, &null_sector.floorheight, 4);
+        I_GetMemoryValue(4, &null_sector.ceilingheight, 4);
+        null_sector_is_initialized = true;
+    }
+
+    return &null_sector;
+#endif
+}
+
+//
+// P_LoadSegs
+//
+void P_LoadSegs (int lump)
+{
+    byte*		data;
+    int			i;
+    mapseg_t*		ml;
+    seg_t*		li;
+    line_t*		ldef;
+    int			linedef;
+    int			side;
+    int                 sidenum;
+	
+    numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
+    segs = new seg_t[numsegs];
+
+    memset (segs, 0, numsegs*sizeof(seg_t));
+
+    data = W_LoadLump (lump);
+	
+    ml = (mapseg_t *)data;
+    li = segs;
+    for (i=0 ; i<numsegs ; i++, li++, ml++)
+    {
+	li->v1 = &vertexes[SHORT(ml->v1)];
+	li->v2 = &vertexes[SHORT(ml->v2)];
+
+	li->angle = (SHORT(ml->angle))<<16;
+	li->offset = (SHORT(ml->offset))<<16;
+	linedef = SHORT(ml->linedef);
+	ldef = &lines[linedef];
+	li->linedef = ldef;
+	side = SHORT(ml->side);
+	li->sidedef = &sides[ldef->sidenum[side]];
+	li->frontsector = sides[ldef->sidenum[side]].sector;
+
+        if (ldef-> flags & ML_TWOSIDED)
+        {
+            sidenum = ldef->sidenum[side ^ 1];
+
+            // If the sidenum is out of range, this may be a "glass hack"
+            // impassible window.  Point at side #0 (this may not be
+            // the correct Vanilla behavior; however, it seems to work for
+            // OTTAWAU.WAD, which is the one place I've seen this trick
+            // used).
+
+            if (sidenum < 0 || sidenum >= numsides)
+            {
+                li->backsector = GetSectorAtNullAddress();
+            }
+            else
+            {
+                li->backsector = sides[sidenum].sector;
+            }
+        }
+        else
+        {
+	    li->backsector = 0;
+        }
+    }
+	
+    W_FreeLump(data);
+}
+
+
+//
+// P_LoadSubsectors
+//
+void P_LoadSubsectors (int lump)
+{
+    byte*		data;
+    int			i;
+    mapsubsector_t*	ms;
+    subsector_t*	ss;
+	
+    numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t);
+    subsectors = new subsector_t[numsubsectors];
+
+    data = W_LoadLump (lump);
+	
+    ms = (mapsubsector_t *)data;
+    memset (subsectors,0, numsubsectors*sizeof(subsector_t));
+    ss = subsectors;
+    
+    for (i=0 ; i<numsubsectors ; i++, ss++, ms++)
+    {
+	ss->numlines = SHORT(ms->numsegs);
+	ss->firstline = SHORT(ms->firstseg);
+    }
+	
+    W_FreeLump(data);
+}
+
+
+
+//
+// P_LoadSectors
+//
+void P_LoadSectors (int lump)
+{
+    byte*		data;
+    int			i;
+    mapsector_t*	ms;
+    sector_t*		ss;
+	
+    numsectors = W_LumpLength (lump) / sizeof(mapsector_t);
+    sectors = new sector_t[numsectors];
+
+    memset (sectors, 0, numsectors*sizeof(sector_t));
+    data = W_LoadLump (lump);
+	
+    ms = (mapsector_t *)data;
+    ss = sectors;
+    for (i=0 ; i<numsectors ; i++, ss++, ms++)
+    {
+	ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
+	ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
+	ss->floorpic = R_FlatNumForName(ms->floorpic);
+	ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
+	ss->lightlevel = SHORT(ms->lightlevel);
+	ss->special = SHORT(ms->special);
+	ss->tag = SHORT(ms->tag);
+///	ss->thinglist = NULL;
+    }
+	
+    W_FreeLump(data);
+}
+
+
+//
+// P_LoadNodes
+//
+void P_LoadNodes (int lump)
+{
+    byte*	data;
+    int		i;
+    int		j;
+    int		k;
+    mapnode_t*	mn;
+    node_t*	no;
+	
+    numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
+    nodes = new node_t[numnodes];
+
+    data = W_LoadLump (lump);
+	
+    mn = (mapnode_t *)data;
+    no = nodes;
+    
+    for (i=0 ; i<numnodes ; i++, no++, mn++)
+    {
+	no->x = SHORT(mn->x)<<FRACBITS;
+	no->y = SHORT(mn->y)<<FRACBITS;
+	no->dx = SHORT(mn->dx)<<FRACBITS;
+	no->dy = SHORT(mn->dy)<<FRACBITS;
+	for (j=0 ; j<2 ; j++)
+	{
+	    no->children[j] = SHORT(mn->children[j]);
+	    for (k=0 ; k<4 ; k++)
+		no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
+	}
+    }
+	
+    W_FreeLump(data);
+}
+
+
+//
+// P_LoadThings
+//
+void P_LoadThings (int lump)
+{
+#if 0
+    byte               *data;
+    int			i;
+    mapthing_t         *mt;
+    mapthing_t          spawnthing;
+    int			numthings;
+    boolean		spawn;
+
+    data = W_LoadLump (lump);
+    numthings = W_LumpLength (lump) / sizeof(mapthing_t);
+	
+    mt = (mapthing_t *)data;
+    for (i=0 ; i<numthings ; i++, mt++)
+    {
+	spawn = true;
+
+	// Do not spawn cool, new monsters if !commercial
+	if (gamemode != commercial)
+	{
+	    switch (SHORT(mt->type))
+	    {
+	      case 68:	// Arachnotron
+	      case 64:	// Archvile
+	      case 88:	// Boss Brain
+	      case 89:	// Boss Shooter
+	      case 69:	// Hell Knight
+	      case 67:	// Mancubus
+	      case 71:	// Pain Elemental
+	      case 65:	// Former Human Commando
+	      case 66:	// Revenant
+	      case 84:	// Wolf SS
+		spawn = false;
+		break;
+	    }
+	}
+	if (spawn == false)
+	    break;
+
+	// Do spawn all other stuff. 
+	spawnthing.x = SHORT(mt->x);
+	spawnthing.y = SHORT(mt->y);
+	spawnthing.angle = SHORT(mt->angle);
+	spawnthing.type = SHORT(mt->type);
+	spawnthing.options = SHORT(mt->options);
+	
+	P_SpawnMapThing(&spawnthing);
+    }
+
+    W_FreeLump(data);
+#endif
+}
+
+
+//
+// P_LoadLineDefs
+// Also counts secret lines for intermissions.
+//
+void P_LoadLineDefs (int lump)
+{
+    byte*		data;
+    int			i;
+    maplinedef_t*	mld;
+    line_t*		ld;
+    vertex_t*		v1;
+    vertex_t*		v2;
+	
+    numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
+    lines = new line_t[numlines];
+
+    memset (lines, 0, numlines*sizeof(line_t));
+    data = W_LoadLump (lump);
+	
+    mld = (maplinedef_t *)data;
+    ld = lines;
+    for (i=0 ; i<numlines ; i++, mld++, ld++)
+    {
+	ld->flags = SHORT(mld->flags);
+	ld->special = SHORT(mld->special);
+	ld->tag = SHORT(mld->tag);
+	v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
+	v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
+	ld->dx = v2->x - v1->x;
+	ld->dy = v2->y - v1->y;
+	
+	if (!ld->dx)
+	    ld->slopetype = ST_VERTICAL;
+	else if (!ld->dy)
+	    ld->slopetype = ST_HORIZONTAL;
+	else
+	{
+	    if (FixedDiv (ld->dy , ld->dx) > 0)
+		ld->slopetype = ST_POSITIVE;
+	    else
+		ld->slopetype = ST_NEGATIVE;
+	}
+		
+	if (v1->x < v2->x)
+	{
+	    ld->bbox[BOXLEFT] = v1->x;
+	    ld->bbox[BOXRIGHT] = v2->x;
+	}
+	else
+	{
+	    ld->bbox[BOXLEFT] = v2->x;
+	    ld->bbox[BOXRIGHT] = v1->x;
+	}
+
+	if (v1->y < v2->y)
+	{
+	    ld->bbox[BOXBOTTOM] = v1->y;
+	    ld->bbox[BOXTOP] = v2->y;
+	}
+	else
+	{
+	    ld->bbox[BOXBOTTOM] = v2->y;
+	    ld->bbox[BOXTOP] = v1->y;
+	}
+
+	ld->sidenum[0] = SHORT(mld->sidenum[0]);
+	ld->sidenum[1] = SHORT(mld->sidenum[1]);
+
+	if (ld->sidenum[0] != -1)
+	    ld->frontsector = sides[ld->sidenum[0]].sector;
+	else
+	    ld->frontsector = 0;
+
+	if (ld->sidenum[1] != -1)
+	    ld->backsector = sides[ld->sidenum[1]].sector;
+	else
+	    ld->backsector = 0;
+    }
+
+    W_FreeLump(data);
+}
+
+
+//
+// P_LoadSideDefs
+//
+void P_LoadSideDefs (int lump)
+{
+    byte*		data;
+    int			i;
+    mapsidedef_t*	msd;
+    side_t*		sd;
+	
+    numsides = W_LumpLength (lump) / sizeof(mapsidedef_t);
+    sides = new side_t[numsides];
+
+    memset (sides, 0, numsides*sizeof(side_t));
+    data = W_LoadLump (lump);
+	
+    msd = (mapsidedef_t *)data;
+    sd = sides;
+    for (i=0 ; i<numsides ; i++, msd++, sd++)
+    {
+	sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
+	sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
+	sd->toptexture = R_TextureNumForName(msd->toptexture);
+	sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
+	sd->midtexture = R_TextureNumForName(msd->midtexture);
+	sd->sector = &sectors[SHORT(msd->sector)];
+    }
+
+    W_FreeLump(data);
+}
+
+
+
+//
+// P_GroupLines
+// Builds sector line lists and subsector sector numbers.
+// Finds block bounding boxes for sectors.
+//
+void P_GroupLines (void)
+{
+    line_t**		linebuffer;
+    int			i;
+    int			j;
+    line_t*		li;
+    sector_t*		sector;
+    subsector_t*	ss;
+    seg_t*		seg;
+    fixed_t		bbox[4];
+    int  totallines;
+	
+    // look up sector number for each subsector
+    ss = subsectors;
+    for (i=0 ; i<numsubsectors ; i++, ss++)
+    {
+	seg = &segs[ss->firstline];
+	ss->sector = seg->sidedef->sector;
+    }
+
+    // count number of lines in each sector
+    li = lines;
+    totallines = 0;
+    for (i=0 ; i<numlines ; i++, li++)
+    {
+	totallines++;
+	li->frontsector->linecount++;
+
+	if (li->backsector && li->backsector != li->frontsector)
+	{
+	    li->backsector->linecount++;
+	    totallines++;
+	}
+    }
+
+    // build line tables for each sector	
+    linebuffer = new line_t* [totallines];
+
+    for (i=0; i<numsectors; ++i)
+    {
+        // Assign the line buffer for this sector
+
+        sectors[i].lines = linebuffer;
+        linebuffer += sectors[i].linecount;
+
+        // Reset linecount to zero so in the next stage we can count
+        // lines into the list.
+
+        sectors[i].linecount = 0;
+    }
+
+    // Assign lines to sectors
+
+    for (i=0; i<numlines; ++i)
+    { 
+        li = &lines[i];
+
+        if (li->frontsector != NULL)
+        {
+            sector = li->frontsector;
+
+            sector->lines[sector->linecount] = li;
+            ++sector->linecount;
+        }
+
+        if (li->backsector != NULL && li->frontsector != li->backsector)
+        {
+            sector = li->backsector;
+
+            sector->lines[sector->linecount] = li;
+            ++sector->linecount;
+        }
+    }
+    
+    // Generate bounding boxes for sectors
+	
+    sector = sectors;
+    for (i=0 ; i<numsectors ; i++, sector++)
+    {
+	M_ClearBox (bbox);
+
+	for (j=0 ; j<sector->linecount; j++)
+	{
+            li = sector->lines[j];
+
+            M_AddToBox (bbox, li->v1->x, li->v1->y);
+            M_AddToBox (bbox, li->v2->x, li->v2->y);
+	}
+
+////	// set the degenmobj_t to the middle of the bounding box
+////	sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
+////	sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
+		
+    }
+	
+}
+
+
+//
+// P_SetupLevel
+//
+void P_SetupLevel ( const char *lumpname )
+{
+    int		lumpnum;
+	
+    lumpnum = W_GetNumForName (lumpname);
+	
+    // note: most of this ordering is important	
+///    P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
+    P_LoadVertexes (lumpnum+ML_VERTEXES);
+    P_LoadSectors (lumpnum+ML_SECTORS);
+    P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
+
+    P_LoadLineDefs (lumpnum+ML_LINEDEFS);
+    P_LoadSubsectors (lumpnum+ML_SSECTORS);
+    P_LoadNodes (lumpnum+ML_NODES);
+    P_LoadSegs (lumpnum+ML_SEGS);
+
+    P_GroupLines ();
+///    P_LoadReject (lumpnum+ML_REJECT);
+
+    P_LoadThings (lumpnum+ML_THINGS);
+}
+
+
+void P_FreeLevelData (void)
+{
+    if (vertexes)
+    {
+        delete[] vertexes;
+        vertexes = NULL;
+        numvertexes = 0;
+    }
+
+    if (sectors)
+    {
+        delete[] sectors;
+        sectors = NULL;
+        numsectors = 0;
+    }
+
+    if (sides)
+    {
+        delete[] sides;
+        sides = NULL;
+        numsides = 0;
+    }
+
+    if (lines)
+    {
+        delete[] lines;
+        lines = NULL;
+        numlines = 0;
+    }
+
+    if (segs)
+    {
+        delete[] segs;
+        segs = NULL;
+        numsegs = 0;
+    }
+
+    if (subsectors)
+    {
+        delete[] subsectors;
+        subsectors = NULL;
+        numsubsectors = 0;
+    }
+
+    if (nodes)
+    {
+        delete[] nodes;
+        nodes = NULL;
+        numnodes = 0;
+    }
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/r_bsp.cc b/Source/Plugins/vpo_dll/r_bsp.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a94926f95c73d266fb7bd449d3e2cfb5cdfe9ed3
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_bsp.cc
@@ -0,0 +1,577 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	BSP traversal, handling of LineSegs for rendering.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+seg_t*		curline;
+side_t*		sidedef;
+line_t*		linedef;
+sector_t*	frontsector;
+sector_t*	backsector;
+
+drawseg_t	drawsegs[MAXDRAWSEGS+10];
+drawseg_t*	ds_p;
+
+int total_drawsegs;
+
+
+void R_StoreWallRange ( int	start, int	stop );
+
+
+//
+// R_ClearDrawSegs
+//
+void R_ClearDrawSegs (void)
+{
+    total_drawsegs = 0;
+
+    ds_p = drawsegs;
+}
+
+
+
+//
+// ClipWallSegment
+// Clips the given range of columns
+// and includes it in the new clip list.
+//
+typedef	struct
+{
+    int	first;
+    int last;
+    
+} cliprange_t;
+
+
+// andrewj: increased limit to 128 for Visplane Explorer
+// #define MAXSOLIDSEGS		32
+#define MAXSOLIDSEGS  128
+
+// newend is one past the last valid seg
+cliprange_t	solidsegs[MAXSOLIDSEGS+8];
+cliprange_t*	newend;
+
+int max_solidsegs;
+
+
+
+//
+// R_ClipSolidWallSegment
+// Does handle solid walls,
+//  e.g. single sided LineDefs (middle texture)
+//  that entirely block the view.
+// 
+void
+R_ClipSolidWallSegment ( int   first, int   last )
+{
+    cliprange_t*	next;
+    cliprange_t*	start;
+
+    // Find the first range that touches the range
+    //  (adjacent pixels are touching).
+    start = solidsegs;
+    while (start->last < first-1)
+	start++;
+
+    if (first < start->first)
+    {
+	if (last < start->first-1)
+	{
+	    // Post is entirely visible (above start),
+	    //  so insert a new clippost.
+	    R_StoreWallRange (first, last);
+	    next = newend;
+	    newend++;
+
+      // andrewj: check for solidseg overflow
+      max_solidsegs = MAX(max_solidsegs, (newend - solidsegs));
+      if (max_solidsegs >= MAXSOLIDSEGS)
+        throw overflow_exception();
+	    
+	    while (next != start)
+	    {
+		*next = *(next-1);
+		next--;
+	    }
+	    next->first = first;
+	    next->last = last;
+	    return;
+	}
+		
+	// There is a fragment above *start.
+	R_StoreWallRange (first, start->first - 1);
+	// Now adjust the clip size.
+	start->first = first;	
+    }
+
+    // Bottom contained in start?
+    if (last <= start->last)
+	return;			
+		
+    next = start;
+    while (last >= (next+1)->first-1)
+    {
+	// There is a fragment between two posts.
+	R_StoreWallRange (next->last + 1, (next+1)->first - 1);
+	next++;
+	
+	if (last <= next->last)
+	{
+	    // Bottom is contained in next.
+	    // Adjust the clip size.
+	    start->last = next->last;	
+	    goto crunch;
+	}
+    }
+	
+    // There is a fragment after *next.
+    R_StoreWallRange (next->last + 1, last);
+    // Adjust the clip size.
+    start->last = last;
+	
+    // Remove start+1 to next from the clip list,
+    // because start now covers their area.
+  crunch:
+    if (next == start)
+    {
+	// Post just extended past the bottom of one post.
+	return;
+    }
+    
+
+    while (next++ != newend)
+    {
+	// Remove a post.
+	*++start = *next;
+    }
+
+    newend = start+1;
+
+    // andrewj: check for solidseg overflow
+    max_solidsegs = MAX(max_solidsegs, (newend - solidsegs));
+    if (max_solidsegs >= MAXSOLIDSEGS)
+      throw overflow_exception();
+}
+
+
+
+//
+// R_ClipPassWallSegment
+// Clips the given range of columns,
+//  but does not includes it in the clip list.
+// Does handle windows,
+//  e.g. LineDefs with upper and lower texture.
+//
+void R_ClipPassWallSegment ( int first, int last )
+{
+    cliprange_t*	start;
+
+    // Find the first range that touches the range
+    //  (adjacent pixels are touching).
+    start = solidsegs;
+    while (start->last < first-1)
+	start++;
+
+    if (first < start->first)
+    {
+	if (last < start->first-1)
+	{
+	    // Post is entirely visible (above start).
+	    R_StoreWallRange (first, last);
+	    return;
+	}
+		
+	// There is a fragment above *start.
+	R_StoreWallRange (first, start->first - 1);
+    }
+
+    // Bottom contained in start?
+    if (last <= start->last)
+	return;			
+		
+    while (last >= (start+1)->first-1)
+    {
+	// There is a fragment between two posts.
+	R_StoreWallRange (start->last + 1, (start+1)->first - 1);
+	start++;
+	
+	if (last <= start->last)
+	    return;
+    }
+	
+    // There is a fragment after *next.
+    R_StoreWallRange (start->last + 1, last);
+}
+
+
+
+//
+// R_ClearClipSegs
+//
+void R_ClearClipSegs (void)
+{
+    solidsegs[0].first = -0x7fffffff;
+    solidsegs[0].last = -1;
+    solidsegs[1].first = viewwidth;
+    solidsegs[1].last = 0x7fffffff;
+
+    newend = solidsegs+2;
+    max_solidsegs = 2;
+}
+
+//
+// R_AddLine
+// Clips the given segment
+// and adds any visible pieces to the line list.
+//
+void R_AddLine (seg_t*	line)
+{
+    int			x1;
+    int			x2;
+    angle_t		angle1;
+    angle_t		angle2;
+    angle_t		span;
+    angle_t		tspan;
+    
+    curline = line;
+
+    // OPTIMIZE: quickly reject orthogonal back sides.
+    angle1 = R_PointToAngle (line->v1->x, line->v1->y);
+    angle2 = R_PointToAngle (line->v2->x, line->v2->y);
+    
+    // Clip to view edges.
+    // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW).
+    span = angle1 - angle2;
+    
+    // Back side? I.e. backface culling?
+    if (span >= ANG180)
+	return;		
+
+    // Global angle needed by segcalc.
+    rw_angle1 = angle1;
+    angle1 -= viewangle;
+    angle2 -= viewangle;
+	
+    tspan = angle1 + clipangle;
+    if (tspan > 2*clipangle)
+    {
+	tspan -= 2*clipangle;
+
+	// Totally off the left edge?
+	if (tspan >= span)
+	    return;
+	
+	angle1 = clipangle;
+    }
+    tspan = clipangle - angle2;
+    if (tspan > 2*clipangle)
+    {
+	tspan -= 2*clipangle;
+
+	// Totally off the left edge?
+	if (tspan >= span)
+	    return;	
+	angle2 = -clipangle;
+    }
+    
+    // The seg is in the view range,
+    // but not necessarily visible.
+    angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
+    angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
+    x1 = viewangletox[angle1];
+    x2 = viewangletox[angle2];
+
+    // Does not cross a pixel?
+    if (x1 == x2)
+	return;				
+	
+    backsector = line->backsector;
+
+    // Single sided line?
+    if (!backsector)
+	goto clipsolid;		
+
+    // Closed door.
+    if (backsector->ceilingheight <= frontsector->floorheight
+	|| backsector->floorheight >= frontsector->ceilingheight)
+	goto clipsolid;		
+
+    // Window.
+    if (backsector->ceilingheight != frontsector->ceilingheight
+	|| backsector->floorheight != frontsector->floorheight)
+	goto clippass;	
+		
+    // Reject empty lines used for triggers
+    //  and special events.
+    // Identical floor and ceiling on both sides,
+    // identical light levels on both sides,
+    // and no middle texture.
+    if (backsector->ceilingpic == frontsector->ceilingpic
+	&& backsector->floorpic == frontsector->floorpic
+	&& backsector->lightlevel == frontsector->lightlevel
+	&& curline->sidedef->midtexture == 0)
+    {
+	return;
+    }
+    
+				
+  clippass:
+    R_ClipPassWallSegment (x1, x2-1);	
+    return;
+		
+  clipsolid:
+    R_ClipSolidWallSegment (x1, x2-1);
+}
+
+
+//
+// R_CheckBBox
+// Checks BSP node/subtree bounding box.
+// Returns true
+//  if some part of the bbox might be visible.
+//
+int	checkcoord[12][4] =
+{
+    {3,0,2,1},
+    {3,0,2,0},
+    {3,1,2,0},
+    {0},
+    {2,0,2,1},
+    {0,0,0,0},
+    {3,1,3,0},
+    {0},
+    {2,0,3,1},
+    {2,1,3,1},
+    {2,1,3,0}
+};
+
+
+boolean R_CheckBBox (fixed_t*	bspcoord)
+{
+    int			boxx;
+    int			boxy;
+    int			boxpos;
+
+    fixed_t		x1;
+    fixed_t		y1;
+    fixed_t		x2;
+    fixed_t		y2;
+    
+    angle_t		angle1;
+    angle_t		angle2;
+    angle_t		span;
+    angle_t		tspan;
+    
+    cliprange_t*	start;
+
+    int			sx1;
+    int			sx2;
+    
+    // Find the corners of the box
+    // that define the edges from current viewpoint.
+    if (viewx <= bspcoord[BOXLEFT])
+	boxx = 0;
+    else if (viewx < bspcoord[BOXRIGHT])
+	boxx = 1;
+    else
+	boxx = 2;
+		
+    if (viewy >= bspcoord[BOXTOP])
+	boxy = 0;
+    else if (viewy > bspcoord[BOXBOTTOM])
+	boxy = 1;
+    else
+	boxy = 2;
+		
+    boxpos = (boxy<<2)+boxx;
+    if (boxpos == 5)
+	return true;
+	
+    x1 = bspcoord[checkcoord[boxpos][0]];
+    y1 = bspcoord[checkcoord[boxpos][1]];
+    x2 = bspcoord[checkcoord[boxpos][2]];
+    y2 = bspcoord[checkcoord[boxpos][3]];
+    
+    // check clip list for an open space
+    angle1 = R_PointToAngle (x1, y1) - viewangle;
+    angle2 = R_PointToAngle (x2, y2) - viewangle;
+	
+    span = angle1 - angle2;
+
+    // Sitting on a line?
+    if (span >= ANG180)
+	return true;
+    
+    tspan = angle1 + clipangle;
+
+    if (tspan > 2*clipangle)
+    {
+	tspan -= 2*clipangle;
+
+	// Totally off the left edge?
+	if (tspan >= span)
+	    return false;	
+
+	angle1 = clipangle;
+    }
+    tspan = clipangle - angle2;
+    if (tspan > 2*clipangle)
+    {
+	tspan -= 2*clipangle;
+
+	// Totally off the left edge?
+	if (tspan >= span)
+	    return false;
+	
+	angle2 = -clipangle;
+    }
+
+
+    // Find the first clippost
+    //  that touches the source post
+    //  (adjacent pixels are touching).
+    angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
+    angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
+    sx1 = viewangletox[angle1];
+    sx2 = viewangletox[angle2];
+
+    // Does not cross a pixel.
+    if (sx1 == sx2)
+	return false;			
+    sx2--;
+	
+    start = solidsegs;
+    while (start->last < sx2)
+	start++;
+    
+    if (sx1 >= start->first
+	&& sx2 <= start->last)
+    {
+	// The clippost contains the new span.
+	return false;
+    }
+
+    return true;
+}
+
+
+
+//
+// R_Subsector
+// Determine floor/ceiling planes.
+// Add sprites of things in sector.
+// Draw one or more line segments.
+//
+void R_Subsector (int num)
+{
+    int			count;
+    seg_t*		line;
+    subsector_t*	sub;
+	
+#ifdef RANGECHECK
+    if (num>=numsubsectors)
+	I_Error ("R_Subsector: ss %i with numss = %i",
+		 num,
+		 numsubsectors);
+#endif
+
+    sscount++;
+    sub = &subsectors[num];
+    frontsector = sub->sector;
+    count = sub->numlines;
+    line = &segs[sub->firstline];
+
+    if (frontsector->floorheight < viewz)
+    {
+	floorplane = R_FindPlane (frontsector->floorheight,
+				  frontsector->floorpic,
+				  frontsector->lightlevel);
+    }
+    else
+	floorplane = NULL;
+    
+    if (frontsector->ceilingheight > viewz 
+	|| frontsector->ceilingpic == skyflatnum)
+    {
+	ceilingplane = R_FindPlane (frontsector->ceilingheight,
+				    frontsector->ceilingpic,
+				    frontsector->lightlevel);
+    }
+    else
+	ceilingplane = NULL;
+		
+////    R_AddSprites (frontsector);	
+
+    while (count--)
+    {
+	R_AddLine (line);
+	line++;
+    }
+}
+
+
+
+
+//
+// RenderBSPNode
+// Renders all subsectors below a given node,
+//  traversing subtree recursively.
+// Just call with BSP root.
+void R_RenderBSPNode (int bspnum)
+{
+    node_t*	bsp;
+    int		side;
+
+    // Found a subsector?
+    if (bspnum & NF_SUBSECTOR)
+    {
+	if (bspnum == -1)			
+	    R_Subsector (0);
+	else
+	    R_Subsector (bspnum&(~NF_SUBSECTOR));
+	return;
+    }
+		
+    bsp = &nodes[bspnum];
+    
+    // Decide which side the view point is on.
+    side = R_PointOnSide (viewx, viewy, bsp);
+
+    // Recursively divide front space.
+    R_RenderBSPNode (bsp->children[side]); 
+
+    // Possibly divide back space.
+    if (R_CheckBBox (bsp->bbox[side^1]))	
+	R_RenderBSPNode (bsp->children[side^1]);
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/r_bsp.h b/Source/Plugins/vpo_dll/r_bsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b7528105bbc3dad218097619efc66062f8dfcfc
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_bsp.h
@@ -0,0 +1,57 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Refresh module, BSP traversal and handling.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __R_BSP__
+#define __R_BSP__
+
+extern seg_t*		curline;
+extern side_t*		sidedef;
+extern line_t*		linedef;
+extern sector_t*	frontsector;
+extern sector_t*	backsector;
+
+extern int		rw_x;
+extern int		rw_stopx;
+
+extern boolean		segtextured;
+
+// false if the back side is the same plane
+extern boolean		markfloor;		
+extern boolean		markceiling;
+
+extern boolean		skymap;
+
+extern drawseg_t	drawsegs[MAXDRAWSEGS+10];
+extern drawseg_t*	ds_p;
+
+
+// BSP?
+void R_ClearClipSegs (void);
+void R_ClearDrawSegs (void);
+
+void R_RenderBSPNode (int bspnum);
+
+#endif
diff --git a/Source/Plugins/vpo_dll/r_defs.h b/Source/Plugins/vpo_dll/r_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fd619a1ae8290b14b06547e696c6af0e387a3e0
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_defs.h
@@ -0,0 +1,321 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//      Refresh/rendering module, shared data struct definitions.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __R_DEFS__
+#define __R_DEFS__
+
+
+// Silhouette, needed for clipping Segs (mainly)
+// and sprites representing things.
+#define SIL_NONE		0
+#define SIL_BOTTOM		1
+#define SIL_TOP			2
+#define SIL_BOTH		3
+
+// #define MAXDRAWSEGS		256
+#define MAXDRAWSEGS		1024     // andrewj: increased for Visplane Explorer
+
+
+#define skyflatnum  2
+
+
+//
+// INTERNAL MAP TYPES
+//  used by play and refresh
+//
+
+//
+// Your plain vanilla vertex.
+// Note: transformed values not buffered locally,
+//  like some DOOM-alikes ("wt", "WebView") did.
+//
+typedef struct
+{
+    fixed_t	x;
+    fixed_t	y;
+    
+} vertex_t;
+
+
+// Forward of LineDefs, for Sectors.
+struct line_s;
+
+
+//
+// The SECTORS record, at runtime.
+// Stores things/mobjs.
+//
+typedef	struct
+{
+    fixed_t	floorheight;
+    fixed_t	ceilingheight;
+
+    short	floorpic;
+    short	ceilingpic;
+    short	lightlevel;
+    short	special;
+    short	tag;
+
+    // 0 = untraversed, 1,2 = sndlines -1
+    int		soundtraversed;
+
+///    // thing that made a sound (or null)
+///    mobj_t*	soundtarget;
+
+///    // mapblock bounding box for height changes
+///    int		blockbox[4];
+
+    // origin for any sounds played by the sector
+///    degenmobj_t	soundorg;
+
+    // if == validcount, already checked
+    int		validcount;
+
+///    // list of mobjs in sector
+///    mobj_t*	thinglist;
+
+    // thinker_t for reversable actions
+    void*	specialdata;
+
+    int			linecount;
+    struct line_s**	lines;	// [linecount] size
+    
+} sector_t;
+
+
+
+//
+// The SideDef.
+//
+
+typedef struct
+{
+    // add this to the calculated texture column
+    fixed_t	textureoffset;
+    
+    // add this to the calculated texture top
+    fixed_t	rowoffset;
+
+    // Texture indices.
+    // We do not maintain names here. 
+    short	toptexture;
+    short	bottomtexture;
+    short	midtexture;
+
+    // Sector the SideDef is facing.
+    sector_t*	sector;
+    
+} side_t;
+
+
+
+//
+// Move clipping aid for LineDefs.
+//
+typedef enum
+{
+    ST_HORIZONTAL,
+    ST_VERTICAL,
+    ST_POSITIVE,
+    ST_NEGATIVE
+
+} slopetype_t;
+
+
+
+typedef struct line_s
+{
+    // Vertices, from v1 to v2.
+    vertex_t*	v1;
+    vertex_t*	v2;
+
+    // Precalculated v2 - v1 for side checking.
+    fixed_t	dx;
+    fixed_t	dy;
+
+    // Animation related.
+    short	flags;
+    short	special;
+    short	tag;
+
+    // Visual appearance: SideDefs.
+    //  sidenum[1] will be -1 if one sided
+    short	sidenum[2];			
+
+    // Neat. Another bounding box, for the extent
+    //  of the LineDef.
+    fixed_t	bbox[4];
+
+    // To aid move clipping.
+    slopetype_t	slopetype;
+
+    // Front and back sector.
+    // Note: redundant? Can be retrieved from SideDefs.
+    sector_t*	frontsector;
+    sector_t*	backsector;
+
+    // if == validcount, already checked
+    int		validcount;
+
+    // thinker_t for reversable actions
+    void*	specialdata;		
+} line_t;
+
+
+
+
+//
+// A SubSector.
+// References a Sector.
+// Basically, this is a list of LineSegs,
+//  indicating the visible walls that define
+//  (all or some) sides of a convex BSP leaf.
+//
+typedef struct subsector_s
+{
+    sector_t*	sector;
+
+    short	numlines;
+    short	firstline;
+    
+} subsector_t;
+
+
+
+//
+// The LineSeg.
+//
+typedef struct
+{
+    vertex_t*	v1;
+    vertex_t*	v2;
+    
+    fixed_t	offset;
+
+    angle_t	angle;
+
+    side_t*	sidedef;
+    line_t*	linedef;
+
+    // Sector references.
+    // Could be retrieved from linedef, too.
+    // backsector is NULL for one sided lines
+    sector_t*	frontsector;
+    sector_t*	backsector;
+    
+} seg_t;
+
+
+
+//
+// BSP node.
+//
+typedef struct
+{
+    // Partition line.
+    fixed_t	x;
+    fixed_t	y;
+    fixed_t	dx;
+    fixed_t	dy;
+
+    // Bounding box for each child.
+    fixed_t	bbox[2][4];
+
+    // If NF_SUBSECTOR its a subsector.
+    unsigned short children[2];
+    
+} node_t;
+
+
+
+
+
+
+//
+// OTHER TYPES
+//
+
+
+
+//
+// ?
+//
+typedef struct drawseg_s
+{
+    seg_t*		curline;
+    int			x1;
+    int			x2;
+
+    fixed_t		scale1;
+    fixed_t		scale2;
+    fixed_t		scalestep;
+
+    // 0=none, 1=bottom, 2=top, 3=both
+    int			silhouette;
+
+    // do not clip sprites above this
+    fixed_t		bsilheight;
+
+    // do not clip sprites below this
+    fixed_t		tsilheight;
+    
+    // Pointers to lists for sprite clipping,
+    //  all three adjusted so [x1] is first value.
+    short*		sprtopclip;		
+    short*		sprbottomclip;	
+    short*		maskedtexturecol;
+    
+} drawseg_t;
+
+
+
+//
+// Now what is a visplane, anyway?
+// 
+typedef struct
+{
+  fixed_t		height;
+  int			picnum;
+  int			lightlevel;
+  int			minx;
+  int			maxx;
+  
+  // leave pads for [minx-1]/[maxx+1]
+  
+  byte		pad1;
+  // Here lies the rub for all
+  //  dynamic resize/change of resolution.
+  byte		top[SCREENWIDTH];
+  byte		pad2;
+  byte		pad3;
+  // See above.
+  byte		bottom[SCREENWIDTH];
+  byte		pad4;
+
+} visplane_t;
+
+
+#endif
diff --git a/Source/Plugins/vpo_dll/r_main.cc b/Source/Plugins/vpo_dll/r_main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..66ec13edbbc344918dc1b89e00cd1ac03481e045
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_main.cc
@@ -0,0 +1,683 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Rendering main loop and setup functions,
+//	 utility functions (BSP, geometry, trigonometry).
+//	See tables.c, too.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+// #include "r_sky.h"
+
+namespace vpo
+{
+
+
+// Fineangles in the SCREENWIDTH wide window.
+#define FIELDOFVIEW		2048	
+
+int			viewangleoffset;
+
+// increment every time a check is made
+int			validcount = 1;		
+
+
+int			centerx;
+int			centery;
+
+fixed_t			centerxfrac;
+fixed_t			centeryfrac;
+fixed_t			projection;
+
+// just for profiling purposes
+int			framecount;	
+
+int			sscount;
+int			linecount;
+int			loopcount;
+
+fixed_t			viewx;
+fixed_t			viewy;
+fixed_t			viewz;
+
+angle_t			viewangle;
+
+fixed_t			viewcos;
+fixed_t			viewsin;
+
+
+//
+// precalculated math tables
+//
+angle_t			clipangle;
+
+// The viewangletox[viewangle + FINEANGLES/4] lookup
+// maps the visible view angles to screen X coordinates,
+// flattening the arc to a flat projection plane.
+// There will be many angles mapped to the same X. 
+int			viewangletox[FINEANGLES/2];
+
+// The xtoviewangleangle[] table maps a screen pixel
+// to the lowest viewangle that maps back to x ranges
+// from clipangle to -clipangle.
+angle_t			xtoviewangle[SCREENWIDTH+1];
+
+
+// UNUSED.
+// The finetangentgent[angle+FINEANGLES/4] table
+// holds the fixed_t tangent values for view angles,
+// ranging from INT_MIN to 0 to INT_MAX.
+// fixed_t		finetangent[FINEANGLES/2];
+
+// fixed_t		finesine[5*FINEANGLES/4];
+const fixed_t*		finecosine = &finesine[FINEANGLES/4];
+
+
+// bumped light from gun blasts
+int			extralight;			
+
+
+// from R_DRAW
+int		viewwidth;
+int		scaledviewwidth;
+int		viewheight;
+int		viewwindowx;
+int		viewwindowy; 
+
+
+// from R_THINGS
+fixed_t  pspritescale;
+fixed_t  pspriteiscale;
+
+short  screenheightarray[SCREENWIDTH];
+short  negonearray[SCREENWIDTH];
+
+
+//
+// R_AddPointToBox
+// Expand a given bbox
+// so that it encloses a given point.
+//
+void R_AddPointToBox ( int  x, int  y, fixed_t* box )
+{
+    if (x< box[BOXLEFT])
+	box[BOXLEFT] = x;
+    if (x> box[BOXRIGHT])
+	box[BOXRIGHT] = x;
+    if (y< box[BOXBOTTOM])
+	box[BOXBOTTOM] = y;
+    if (y> box[BOXTOP])
+	box[BOXTOP] = y;
+}
+
+
+//
+// R_PointOnSide
+// Traverse BSP (sub) tree,
+//  check point against partition plane.
+// Returns side 0 (front) or 1 (back).
+//
+int R_PointOnSide ( fixed_t	x, fixed_t	y, node_t*	node )
+{
+    fixed_t	dx;
+    fixed_t	dy;
+    fixed_t	left;
+    fixed_t	right;
+	
+    if (!node->dx)
+    {
+	if (x <= node->x)
+	    return node->dy > 0;
+	
+	return node->dy < 0;
+    }
+    if (!node->dy)
+    {
+	if (y <= node->y)
+	    return node->dx < 0;
+	
+	return node->dx > 0;
+    }
+	
+    dx = (x - node->x);
+    dy = (y - node->y);
+	
+    // Try to quickly decide by looking at sign bits.
+    if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
+    {
+	if  ( (node->dy ^ dx) & 0x80000000 )
+	{
+	    // (left is negative)
+	    return 1;
+	}
+	return 0;
+    }
+
+    left = FixedMul ( node->dy>>FRACBITS , dx );
+    right = FixedMul ( dy , node->dx>>FRACBITS );
+	
+    if (right < left)
+    {
+	// front side
+	return 0;
+    }
+    // back side
+    return 1;			
+}
+
+
+int R_PointOnSegSide ( fixed_t	x, fixed_t	y, seg_t*	line )
+{
+    fixed_t	lx;
+    fixed_t	ly;
+    fixed_t	ldx;
+    fixed_t	ldy;
+    fixed_t	dx;
+    fixed_t	dy;
+    fixed_t	left;
+    fixed_t	right;
+	
+    lx = line->v1->x;
+    ly = line->v1->y;
+	
+    ldx = line->v2->x - lx;
+    ldy = line->v2->y - ly;
+	
+    if (!ldx)
+    {
+	if (x <= lx)
+	    return ldy > 0;
+	
+	return ldy < 0;
+    }
+    if (!ldy)
+    {
+	if (y <= ly)
+	    return ldx < 0;
+	
+	return ldx > 0;
+    }
+	
+    dx = (x - lx);
+    dy = (y - ly);
+	
+    // Try to quickly decide by looking at sign bits.
+    if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
+    {
+	if  ( (ldy ^ dx) & 0x80000000 )
+	{
+	    // (left is negative)
+	    return 1;
+	}
+	return 0;
+    }
+
+    left = FixedMul ( ldy>>FRACBITS , dx );
+    right = FixedMul ( dy , ldx>>FRACBITS );
+	
+    if (right < left)
+    {
+	// front side
+	return 0;
+    }
+    // back side
+    return 1;			
+}
+
+
+//
+// R_PointToAngle
+// To get a global angle from cartesian coordinates,
+//  the coordinates are flipped until they are in
+//  the first octant of the coordinate system, then
+//  the y (<=x) is scaled and divided by x to get a
+//  tangent (slope) value which is looked up in the
+//  tantoangle[] table.
+
+angle_t R_PointToAngle ( fixed_t	x, fixed_t	y )
+{	
+    x -= viewx;
+    y -= viewy;
+    
+    if ( (!x) && (!y) )
+	return 0;
+
+    if (x>= 0)
+    {
+	// x >=0
+	if (y>= 0)
+	{
+	    // y>= 0
+
+	    if (x>y)
+	    {
+		// octant 0
+		return tantoangle[ SlopeDiv(y,x)];
+	    }
+	    else
+	    {
+		// octant 1
+		return ANG90-1-tantoangle[ SlopeDiv(x,y)];
+	    }
+	}
+	else
+	{
+	    // y<0
+	    y = -y;
+
+	    if (x>y)
+	    {
+		// octant 8
+		return -tantoangle[SlopeDiv(y,x)];
+	    }
+	    else
+	    {
+		// octant 7
+		return ANG270+tantoangle[ SlopeDiv(x,y)];
+	    }
+	}
+    }
+    else
+    {
+	// x<0
+	x = -x;
+
+	if (y>= 0)
+	{
+	    // y>= 0
+	    if (x>y)
+	    {
+		// octant 3
+		return ANG180-1-tantoangle[ SlopeDiv(y,x)];
+	    }
+	    else
+	    {
+		// octant 2
+		return ANG90+ tantoangle[ SlopeDiv(x,y)];
+	    }
+	}
+	else
+	{
+	    // y<0
+	    y = -y;
+
+	    if (x>y)
+	    {
+		// octant 4
+		return ANG180+tantoangle[ SlopeDiv(y,x)];
+	    }
+	    else
+	    {
+		 // octant 5
+		return ANG270-1-tantoangle[ SlopeDiv(x,y)];
+	    }
+	}
+    }
+    return 0;
+}
+
+
+angle_t R_PointToAngle2 ( fixed_t	x1, fixed_t	y1, fixed_t	x2, fixed_t	y2 )
+{	
+    viewx = x1;
+    viewy = y1;
+    
+    return R_PointToAngle (x2, y2);
+}
+
+
+fixed_t R_PointToDist ( fixed_t	x, fixed_t	y )
+{
+    int		angle;
+    fixed_t	dx;
+    fixed_t	dy;
+    fixed_t	temp;
+    fixed_t	dist;
+    fixed_t     frac;
+	
+    dx = abs(x - viewx);
+    dy = abs(y - viewy);
+	
+    if (dy>dx)
+    {
+	temp = dx;
+	dx = dy;
+	dy = temp;
+    }
+
+    // Fix crashes in udm1.wad
+
+    if (dx != 0)
+    {
+        frac = FixedDiv(dy, dx);
+    }
+    else
+    {
+	frac = 0;
+    }
+	
+    angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT;
+
+    // use as cosine
+    dist = FixedDiv (dx, finesine[angle] );	
+	
+    return dist;
+}
+
+
+//
+// R_ScaleFromGlobalAngle
+// Returns the texture mapping scale
+//  for the current line (horizontal span)
+//  at the given angle.
+// rw_distance must be calculated first.
+//
+fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
+{
+    fixed_t		scale;
+    angle_t		anglea;
+    angle_t		angleb;
+    int			sinea;
+    int			sineb;
+    fixed_t		num;
+    int			den;
+
+    // UNUSED
+#if 0
+{
+    fixed_t		dist;
+    fixed_t		z;
+    fixed_t		sinv;
+    fixed_t		cosv;
+	
+    sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT];	
+    dist = FixedDiv (rw_distance, sinv);
+    cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT];
+    z = abs(FixedMul (dist, cosv));
+    scale = FixedDiv(projection, z);
+    return scale;
+}
+#endif
+
+    anglea = ANG90 + (visangle-viewangle);
+    angleb = ANG90 + (visangle-rw_normalangle);
+
+    // both sines are allways positive
+    sinea = finesine[anglea>>ANGLETOFINESHIFT];	
+    sineb = finesine[angleb>>ANGLETOFINESHIFT];
+    num = FixedMul(projection,sineb)<<0;
+    den = FixedMul(rw_distance,sinea);
+
+    if (den > num>>16)
+    {
+	scale = FixedDiv (num, den);
+
+	if (scale > 64*FRACUNIT)
+	    scale = 64*FRACUNIT;
+	else if (scale < 256)
+	    scale = 256;
+    }
+    else
+	scale = 64*FRACUNIT;
+	
+    return scale;
+}
+
+
+void R_InitBuffer ( int		width, int		height ) 
+{ 
+    int		i;
+	
+    // Handle resize,
+    //  e.g. smaller view windows
+    //  with border and/or status bar.
+    viewwindowx = (SCREENWIDTH-width) >> 1; 
+    viewwindowy = 0; 
+
+    // this was from R_InitSprites
+    for (i=0 ; i<SCREENWIDTH ; i++)
+    {
+      negonearray[i] = -1;
+    }
+
+#if 0
+    // Column offset. For windows.
+    for (i=0 ; i<width ; i++) 
+	columnofs[i] = viewwindowx + i;
+
+    // Samw with base row offset.
+    if (width == SCREENWIDTH) 
+	viewwindowy = 0; 
+    else 
+	viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1; 
+
+    // Preclaculate all row offsets.
+    for (i=0 ; i<height ; i++) 
+	ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH; 
+#endif
+} 
+
+
+//
+// R_InitTextureMapping
+//
+void R_InitTextureMapping (void)
+{
+    int			i;
+    int			x;
+    int			t;
+    fixed_t		focallength;
+    
+    // Use tangent table to generate viewangletox:
+    //  viewangletox will give the next greatest x
+    //  after the view angle.
+    //
+    // Calc focallength
+    //  so FIELDOFVIEW angles covers SCREENWIDTH.
+    focallength = FixedDiv (centerxfrac,
+			    finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
+	
+    for (i=0 ; i<FINEANGLES/2 ; i++)
+    {
+	if (finetangent[i] > FRACUNIT*2)
+	    t = -1;
+	else if (finetangent[i] < -FRACUNIT*2)
+	    t = viewwidth+1;
+	else
+	{
+	    t = FixedMul (finetangent[i], focallength);
+	    t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
+
+	    if (t < -1)
+		t = -1;
+	    else if (t>viewwidth+1)
+		t = viewwidth+1;
+	}
+	viewangletox[i] = t;
+    }
+    
+    // Scan viewangletox[] to generate xtoviewangle[]:
+    //  xtoviewangle will give the smallest view angle
+    //  that maps to x.	
+    for (x=0;x<=viewwidth;x++)
+    {
+	i = 0;
+	while (viewangletox[i]>x)
+	    i++;
+	xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
+    }
+    
+    // Take out the fencepost cases from viewangletox.
+    for (i=0 ; i<FINEANGLES/2 ; i++)
+    {
+	t = FixedMul (finetangent[i], focallength);
+	t = centerx - t;
+	
+	if (viewangletox[i] == -1)
+	    viewangletox[i] = 0;
+	else if (viewangletox[i] == viewwidth+1)
+	    viewangletox[i]  = viewwidth;
+    }
+	
+    clipangle = xtoviewangle[0];
+}
+
+
+
+//
+// R_SetViewSize
+//
+void R_SetViewSize ( int  blocks, int  detail )
+{
+    fixed_t	cosadj;
+    fixed_t	dy;
+    int		i;
+
+    if (blocks == 11)
+    {
+	scaledviewwidth = SCREENWIDTH;
+	viewheight = SCREENHEIGHT;
+    }
+    else
+    {
+	scaledviewwidth = blocks*32;
+	viewheight = (blocks*168/10)&~7;
+    }
+    
+    viewwidth = scaledviewwidth >> 0;
+	
+    centery = viewheight/2;
+    centerx = viewwidth/2;
+    centerxfrac = centerx<<FRACBITS;
+    centeryfrac = centery<<FRACBITS;
+    projection = centerxfrac;
+
+    R_InitBuffer (scaledviewwidth, viewheight);
+	
+    R_InitTextureMapping ();
+
+    // psprite scales
+    pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
+    pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
+    
+    // thing clipping
+    for (i=0 ; i<viewwidth ; i++)
+	screenheightarray[i] = viewheight;
+    
+    // planes
+    for (i=0 ; i<viewheight ; i++)
+    {
+	dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
+	dy = abs(dy);
+	yslope[i] = FixedDiv ( (viewwidth<<0)/2*FRACUNIT, dy);
+    }
+	
+    for (i=0 ; i<viewwidth ; i++)
+    {
+	cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
+	distscale[i] = FixedDiv (FRACUNIT,cosadj);
+    }
+    
+}
+
+
+
+//
+// R_Init
+//
+void R_Init (void)
+{
+    R_SetViewSize (11, 0);
+	
+    framecount = 0;
+}
+
+
+//
+// R_PointInSubsector
+//
+subsector_t* R_PointInSubsector ( fixed_t	x, fixed_t	y )
+{
+    node_t*	node;
+    int		side;
+    int		nodenum;
+
+    // single subsector is a special case
+    if (!numnodes)				
+	return subsectors;
+		
+    nodenum = numnodes-1;
+
+    while (! (nodenum & NF_SUBSECTOR) )
+    {
+	node = &nodes[nodenum];
+	side = R_PointOnSide (x, y, node);
+	nodenum = node->children[side];
+    }
+	
+    return &subsectors[nodenum & ~NF_SUBSECTOR];
+}
+
+
+//
+// R_SetupFrame
+//
+void R_SetupFrame (fixed_t x, fixed_t y, fixed_t z, angle_t angle)
+{		
+    viewx = x;
+    viewy = y;
+    viewz = z;
+
+    viewangle = angle;
+
+    viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
+    viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
+	
+    sscount = 0;
+	
+    framecount++;
+    validcount++;
+}
+
+
+//
+// R_RenderView
+//
+void R_RenderView (fixed_t x, fixed_t y, fixed_t z, angle_t angle)
+{	
+    R_SetupFrame (x, y, z, angle);
+
+    // Clear buffers.
+    R_ClearClipSegs ();
+    R_ClearDrawSegs ();
+    R_ClearPlanes ();
+///  R_ClearSprites ();
+    
+    // The head node is the last node output.
+    R_RenderBSPNode (numnodes - 1);
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/r_main.h b/Source/Plugins/vpo_dll/r_main.h
new file mode 100644
index 0000000000000000000000000000000000000000..ceb7a728d320b564b816d0c45036cad849c5d04f
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_main.h
@@ -0,0 +1,113 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	System specific interface stuff.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __R_MAIN__
+#define __R_MAIN__
+
+
+//
+// POV related.
+//
+extern fixed_t		viewcos;
+extern fixed_t		viewsin;
+
+extern int		viewwidth;
+extern int		viewheight;
+extern int		viewwindowx;
+extern int		viewwindowy;
+
+
+extern int		centerx;
+extern int		centery;
+
+extern fixed_t		centerxfrac;
+extern fixed_t		centeryfrac;
+extern fixed_t		projection;
+
+extern int		validcount;
+
+extern int		linecount;
+extern int		loopcount;
+
+
+//
+// Lighting LUT.
+// Used for z-depth cuing per column/row,
+//  and other lighting effects (sector ambient, flash).
+//
+
+// Lighting constants.
+// Now why not 32 levels here?
+#define LIGHTLEVELS	        16
+#define LIGHTSEGSHIFT	         4
+
+#define MAXLIGHTSCALE		48
+#define LIGHTSCALESHIFT		12
+#define MAXLIGHTZ	       128
+#define LIGHTZSHIFT		20
+
+
+// Number of diminishing brightness levels.
+// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
+#define NUMCOLORMAPS		32
+
+
+//
+// Utility functions.
+int R_PointOnSide ( fixed_t	x, fixed_t	y, node_t*	node );
+
+int R_PointOnSegSide ( fixed_t	x, fixed_t	y, seg_t*	line );
+
+angle_t R_PointToAngle ( fixed_t	x, fixed_t	y );
+
+angle_t R_PointToAngle2 ( fixed_t	x1, fixed_t	y1, fixed_t	x2, fixed_t	y2 );
+
+fixed_t R_PointToDist ( fixed_t	x, fixed_t	y );
+
+
+fixed_t R_ScaleFromGlobalAngle (angle_t visangle);
+
+subsector_t* R_PointInSubsector ( fixed_t	x, fixed_t	y );
+
+void R_AddPointToBox ( int		x, int		y, fixed_t*	box );
+
+
+
+// R_THINGS
+
+extern short  screenheightarray[SCREENWIDTH];
+extern short  negonearray[SCREENWIDTH];
+
+
+//
+// REFRESH - the actual rendering functions.
+//
+
+void R_Init (void);
+
+void R_RenderView (fixed_t x, fixed_t y, fixed_t z, angle_t angle);
+
+#endif
diff --git a/Source/Plugins/vpo_dll/r_plane.cc b/Source/Plugins/vpo_dll/r_plane.cc
new file mode 100644
index 0000000000000000000000000000000000000000..46c09763fa9ae9ea6d3d07e91e18c57acc23ac48
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_plane.cc
@@ -0,0 +1,355 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Here is a core component: drawing the floors and ceilings,
+//	 while maintaining a per column clipping list only.
+//	Moreover, the sky areas have to be determined.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+//
+// opening
+//
+
+// Here comes the obnoxious "visplane".
+visplane_t		visplanes[MAXVISPLANES+10];
+visplane_t*		lastvisplane;
+visplane_t*		floorplane;
+visplane_t*		ceilingplane;
+
+int total_visplanes;
+
+short			openings[MAXOPENINGS+400];
+short*			lastopening;
+
+int total_openings;
+
+
+//
+// Clip values are the solid pixel bounding the range.
+//  floorclip starts out SCREENHEIGHT
+//  ceilingclip starts out -1
+//
+short			floorclip[SCREENWIDTH];
+short			ceilingclip[SCREENWIDTH];
+
+//
+// spanstart holds the start of a plane span
+// initialized to 0 at start
+//
+int			spanstart[SCREENHEIGHT];
+int			spanstop[SCREENHEIGHT];
+
+//
+// texture mapping
+//
+fixed_t			planeheight;
+
+fixed_t			yslope[SCREENHEIGHT];
+fixed_t			distscale[SCREENWIDTH];
+fixed_t			basexscale;
+fixed_t			baseyscale;
+
+fixed_t			cachedheight[SCREENHEIGHT];
+fixed_t			cacheddistance[SCREENHEIGHT];
+fixed_t			cachedxstep[SCREENHEIGHT];
+fixed_t			cachedystep[SCREENHEIGHT];
+
+
+
+#if 0
+//
+// R_MapPlane
+//
+// Uses global vars:
+//  planeheight
+//  ds_source
+//  basexscale
+//  baseyscale
+//  viewx
+//  viewy
+//
+// BASIC PRIMITIVE
+//
+void R_MapPlane ( int  y, int  x1, int  x2 )
+{
+    angle_t	angle;
+    fixed_t	distance;
+    fixed_t	length;
+    unsigned	index;
+	
+#ifdef RANGECHECK
+    if (x2 < x1
+     || x1 < 0
+     || x2 >= viewwidth
+     || y > viewheight)
+    {
+	I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
+    }
+#endif
+
+    if (planeheight != cachedheight[y])
+    {
+	cachedheight[y] = planeheight;
+	distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
+	ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
+	ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
+    }
+    else
+    {
+	distance = cacheddistance[y];
+	ds_xstep = cachedxstep[y];
+	ds_ystep = cachedystep[y];
+    }
+	
+    length = FixedMul (distance,distscale[x1]);
+    angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
+    ds_xfrac = viewx + FixedMul(finecosine[angle], length);
+    ds_yfrac = -viewy - FixedMul(finesine[angle], length);
+
+    if (fixedcolormap)
+	ds_colormap = fixedcolormap;
+    else
+    {
+	index = distance >> LIGHTZSHIFT;
+	
+	if (index >= MAXLIGHTZ )
+	    index = MAXLIGHTZ-1;
+
+	ds_colormap = planezlight[index];
+    }
+	
+    ds_y = y;
+    ds_x1 = x1;
+    ds_x2 = x2;
+
+    // high or low detail
+    spanfunc ();	
+}
+#endif
+
+
+//
+// R_ClearPlanes
+// At begining of frame.
+//
+void R_ClearPlanes (void)
+{
+    int		i;
+    angle_t	angle;
+    
+    // opening / clipping determination
+    for (i=0 ; i<viewwidth ; i++)
+    {
+	floorclip[i] = viewheight;
+	ceilingclip[i] = -1;
+    }
+
+    total_visplanes = 0;
+    total_openings  = 0;
+
+    lastvisplane = visplanes;
+    lastopening = openings;
+
+    // texture calculation
+    memset (cachedheight, 0, sizeof(cachedheight));
+
+    // left to right mapping
+    angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
+	
+    // scale will be unit scale at SCREENWIDTH/2 distance
+    basexscale = FixedDiv (finecosine[angle],centerxfrac);
+    baseyscale = -FixedDiv (finesine[angle],centerxfrac);
+}
+
+
+
+
+//
+// R_FindPlane
+//
+visplane_t* R_FindPlane ( fixed_t height, int  picnum, int  lightlevel )
+{
+    visplane_t*	check;
+	
+    if (picnum == skyflatnum)
+    {
+	height = 0;			// all skys map together
+	lightlevel = 0;
+    }
+	
+    for (check=visplanes; check<lastvisplane; check++)
+    {
+	if (height == check->height
+	    && picnum == check->picnum
+	    && lightlevel == check->lightlevel)
+	{
+	    break;
+	}
+    }
+    
+			
+    if (check < lastvisplane)
+	return check;
+		
+    if (total_visplanes >= MAXVISPLANES)
+      throw overflow_exception(); // I_Error ("R_FindPlane: no more visplanes");
+		
+    total_visplanes++;
+    lastvisplane++;
+
+    check->height = height;
+    check->picnum = picnum;
+    check->lightlevel = lightlevel;
+    check->minx = SCREENWIDTH;
+    check->maxx = -1;
+    
+    memset (check->top,0xff,sizeof(check->top));
+		
+    return check;
+}
+
+
+//
+// R_CheckPlane
+//
+visplane_t* R_CheckPlane ( visplane_t* pl, int  start, int  stop )
+{
+    int		intrl;
+    int		intrh;
+    int		unionl;
+    int		unionh;
+    int		x;
+	
+    if (start < pl->minx)
+    {
+	intrl = pl->minx;
+	unionl = start;
+    }
+    else
+    {
+	unionl = pl->minx;
+	intrl = start;
+    }
+	
+    if (stop > pl->maxx)
+    {
+	intrh = pl->maxx;
+	unionh = stop;
+    }
+    else
+    {
+	unionh = pl->maxx;
+	intrh = stop;
+    }
+
+    for (x=intrl ; x<= intrh ; x++)
+	if (pl->top[x] != 0xff)
+	    break;
+
+    if (x > intrh)
+    {
+	pl->minx = unionl;
+	pl->maxx = unionh;
+
+	// use the same one
+	return pl;		
+    }
+	
+    // make a new visplane
+    lastvisplane->height = pl->height;
+    lastvisplane->picnum = pl->picnum;
+    lastvisplane->lightlevel = pl->lightlevel;
+    
+    if (total_visplanes >= MAXVISPLANES)
+      throw overflow_exception(); // I_Error ("R_FindPlane: no more visplanes");
+
+    total_visplanes++;
+
+    pl = lastvisplane++;
+    pl->minx = start;
+    pl->maxx = stop;
+
+    memset (pl->top,0xff,sizeof(pl->top));
+
+    return pl;
+}
+
+
+#if 0
+//
+// R_MakeSpans
+//
+void R_MakeSpans ( int  x, int  t1, int  b1, int  t2, int  b2 )
+{
+    while (t1 < t2 && t1<=b1)
+    {
+	R_MapPlane (t1,spanstart[t1],x-1);
+	t1++;
+    }
+    while (b1 > b2 && b1>=t1)
+    {
+	R_MapPlane (b1,spanstart[b1],x-1);
+	b1--;
+    }
+	
+    while (t2 < t1 && t2<=b2)
+    {
+	spanstart[t2] = x;
+	t2++;
+    }
+    while (b2 > b1 && b2>=t2)
+    {
+	spanstart[b2] = x;
+	b2--;
+    }
+}
+#endif
+
+
+
+#if 0
+    was: R_DrawPlanes()
+
+				
+    if (ds_p - drawsegs > MAXDRAWSEGS)
+	I_Error ("R_DrawPlanes: drawsegs overflow (%i)",
+		 ds_p - drawsegs);
+    
+    if (lastvisplane - visplanes > MAXVISPLANES)
+	I_Error ("R_DrawPlanes: visplane overflow (%i)",
+		 lastvisplane - visplanes);
+    
+    if (lastopening - openings > MAXOPENINGS)
+	I_Error ("R_DrawPlanes: opening overflow (%i)",
+		 lastopening - openings);
+#endif
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/r_plane.h b/Source/Plugins/vpo_dll/r_plane.h
new file mode 100644
index 0000000000000000000000000000000000000000..5634d0276d6c9face6f818ee6c5660d3b4facd5d
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_plane.h
@@ -0,0 +1,64 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Refresh, visplane stuff (floor, ceilings).
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __R_PLANE__
+#define __R_PLANE__
+
+
+// Visplane related.
+extern  short * lastopening;
+
+
+typedef void (*planefunction_t) (int top, int bottom);
+
+extern short		floorclip[SCREENWIDTH];
+extern short		ceilingclip[SCREENWIDTH];
+
+extern fixed_t		yslope[SCREENHEIGHT];
+extern fixed_t		distscale[SCREENWIDTH];
+
+void R_ClearPlanes (void);
+
+void R_MapPlane ( int y, int x1, int x2 );
+void R_MakeSpans ( int x, int t1, int b1, int t2, int b2 );
+void R_DrawPlanes (void);
+
+visplane_t* R_FindPlane ( fixed_t height, int picnum, int lightlevel );
+visplane_t* R_CheckPlane ( visplane_t* pl, int start, int stop );
+
+// #define MAXVISPLANES	128
+#define MAXVISPLANES	512   // andrewj: increased for Visplane Explorer
+
+// #define MAXOPENINGS	SCREENWIDTH*64
+#define MAXOPENINGS	SCREENWIDTH*256  // andrewj: increased for Visplane Explorer
+
+extern int total_visplanes;
+extern int total_drawsegs;
+extern int total_openings;
+extern int   max_solidsegs;
+
+
+#endif
diff --git a/Source/Plugins/vpo_dll/r_segs.cc b/Source/Plugins/vpo_dll/r_segs.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c38816e6865ade41dcaeb88c6b38937d9a98a0a0
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_segs.cc
@@ -0,0 +1,622 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	All the clipping: columns, horizontal spans, sky columns.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+// OPTIMIZE: closed two sided lines as single sided
+
+// True if any of the segs textures might be visible.
+boolean		segtextured;	
+
+// False if the back side is the same plane.
+boolean		markfloor;	
+boolean		markceiling;
+
+boolean		maskedtexture;
+int		toptexture;
+int		bottomtexture;
+int		midtexture;
+
+
+angle_t		rw_normalangle;
+// angle to line origin
+int		rw_angle1;	
+
+//
+// regular wall
+//
+int		rw_x;
+int		rw_stopx;
+angle_t		rw_centerangle;
+fixed_t		rw_offset;
+fixed_t		rw_distance;
+fixed_t		rw_scale;
+fixed_t		rw_scalestep;
+fixed_t		rw_midtexturemid;
+fixed_t		rw_toptexturemid;
+fixed_t		rw_bottomtexturemid;
+
+int		worldtop;
+int		worldbottom;
+int		worldhigh;
+int		worldlow;
+
+fixed_t		pixhigh;
+fixed_t		pixlow;
+fixed_t		pixhighstep;
+fixed_t		pixlowstep;
+
+fixed_t		topfrac;
+fixed_t		topstep;
+
+fixed_t		bottomfrac;
+fixed_t		bottomstep;
+
+
+short*		maskedtexturecol;
+
+
+// R_DRAW bits
+int              dc_x;
+int              dc_yl;
+int              dc_yh;
+fixed_t          dc_iscale;
+fixed_t          dc_texturemid;
+
+
+//
+// R_RenderSegLoop
+// Draws zero, one, or two textures (and possibly a masked
+//  texture) for walls.
+// Can draw or mark the starting pixel of floor and ceiling
+//  textures.
+// CALLED: CORE LOOPING ROUTINE.
+//
+#define HEIGHTBITS		12
+#define HEIGHTUNIT		(1<<HEIGHTBITS)
+
+void R_RenderSegLoop (void)
+{
+  angle_t		angle;
+  int			yl;
+  int			yh;
+  int			mid;
+  fixed_t		texturecolumn;
+  int			top;
+  int			bottom;
+
+  for ( ; rw_x < rw_stopx ; rw_x++)
+  {
+    // mark floor / ceiling areas
+    yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
+
+    // no space above wall?
+    if (yl < ceilingclip[rw_x]+1)
+      yl = ceilingclip[rw_x]+1;
+
+    if (markceiling)
+    {
+      top = ceilingclip[rw_x]+1;
+      bottom = yl-1;
+
+      if (bottom >= floorclip[rw_x])
+        bottom = floorclip[rw_x]-1;
+
+      if (top <= bottom)
+      {
+        ceilingplane->top[rw_x] = top;
+        ceilingplane->bottom[rw_x] = bottom;
+      }
+    }
+
+    yh = bottomfrac>>HEIGHTBITS;
+
+    if (yh >= floorclip[rw_x])
+      yh = floorclip[rw_x]-1;
+
+    if (markfloor)
+    {
+      top = yh+1;
+      bottom = floorclip[rw_x]-1;
+      if (top <= ceilingclip[rw_x])
+        top = ceilingclip[rw_x]+1;
+      if (top <= bottom)
+      {
+        floorplane->top[rw_x] = top;
+        floorplane->bottom[rw_x] = bottom;
+      }
+    }
+
+    // texturecolumn and lighting are independent of wall tiers
+    if (segtextured)
+    {
+      // calculate texture offset
+      angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
+      texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
+      texturecolumn >>= FRACBITS;
+
+      dc_x = rw_x;
+      dc_iscale = 0xffffffffu / (unsigned)rw_scale;
+    }
+    else
+    {
+      // purely to shut up the compiler
+
+      texturecolumn = 0;
+    }
+
+    // draw the wall tiers
+    if (midtexture)
+    {
+      // single sided line
+      dc_yl = yl;
+      dc_yh = yh;
+      dc_texturemid = rw_midtexturemid;
+      ///---	    dc_source = R_GetColumn(midtexture,texturecolumn);
+      ///---	    colfunc ();
+      ceilingclip[rw_x] = viewheight;
+      floorclip[rw_x] = -1;
+    }
+    else
+    {
+      // two sided line
+      if (toptexture)
+      {
+        // top wall
+        mid = pixhigh>>HEIGHTBITS;
+        pixhigh += pixhighstep;
+
+        if (mid >= floorclip[rw_x])
+          mid = floorclip[rw_x]-1;
+
+        if (mid >= yl)
+        {
+          dc_yl = yl;
+          dc_yh = mid;
+          dc_texturemid = rw_toptexturemid;
+          ///---		    dc_source = R_GetColumn(toptexture,texturecolumn);
+          ///---		    colfunc ();
+          ceilingclip[rw_x] = mid;
+        }
+        else
+          ceilingclip[rw_x] = yl-1;
+      }
+      else
+      {
+        // no top wall
+        if (markceiling)
+          ceilingclip[rw_x] = yl-1;
+      }
+
+      if (bottomtexture)
+      {
+        // bottom wall
+        mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
+        pixlow += pixlowstep;
+
+        // no space above wall?
+        if (mid <= ceilingclip[rw_x])
+          mid = ceilingclip[rw_x]+1;
+
+        if (mid <= yh)
+        {
+          dc_yl = mid;
+          dc_yh = yh;
+          dc_texturemid = rw_bottomtexturemid;
+///---          dc_source = R_GetColumn(bottomtexture, texturecolumn);
+///---          colfunc ();
+          floorclip[rw_x] = mid;
+        }
+        else
+          floorclip[rw_x] = yh+1;
+      }
+      else
+      {
+        // no bottom wall
+        if (markfloor)
+          floorclip[rw_x] = yh+1;
+      }
+
+      if (maskedtexture)
+      {
+        // save texturecol
+        //  for backdrawing of masked mid texture
+        maskedtexturecol[rw_x] = texturecolumn;
+      }
+    }
+
+    rw_scale += rw_scalestep;
+    topfrac += topstep;
+    bottomfrac += bottomstep;
+  }
+}
+
+
+
+
+//
+// R_StoreWallRange
+// A wall segment will be drawn
+//  between start and stop pixels (inclusive).
+//
+void R_StoreWallRange ( int	start, int	stop )
+{
+  fixed_t		hyp;
+  fixed_t		sineval;
+  angle_t		distangle, offsetangle;
+  fixed_t		vtop;
+
+  // don't overflow and crash
+  total_drawsegs++;
+
+  if (total_drawsegs >= MAXDRAWSEGS)
+    throw overflow_exception();
+
+#ifdef RANGECHECK
+  if (start >=viewwidth || start > stop)
+    I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
+#endif
+
+  sidedef = curline->sidedef;
+  linedef = curline->linedef;
+
+  // mark the segment as visible for auto map
+  linedef->flags |= ML_MAPPED;
+
+  // calculate rw_distance for scale calculation
+  rw_normalangle = curline->angle + ANG90;
+  offsetangle = abs((int)rw_normalangle-rw_angle1);
+
+  if (offsetangle > ANG90)
+    offsetangle = ANG90;
+
+  distangle = ANG90 - offsetangle;
+  hyp = R_PointToDist (curline->v1->x, curline->v1->y);
+  sineval = finesine[distangle>>ANGLETOFINESHIFT];
+  rw_distance = FixedMul (hyp, sineval);
+
+
+  ds_p->x1 = rw_x = start;
+  ds_p->x2 = stop;
+  ds_p->curline = curline;
+  rw_stopx = stop+1;
+
+  // calculate scale at both ends and step
+  ds_p->scale1 = rw_scale = 
+    R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
+
+  if (stop > start )
+  {
+    ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
+    ds_p->scalestep = rw_scalestep = 
+      (ds_p->scale2 - rw_scale) / (stop-start);
+  }
+  else
+  {
+    ds_p->scale2 = ds_p->scale1;
+  }
+
+  // calculate texture boundaries
+  //  and decide if floor / ceiling marks are needed
+  worldtop = frontsector->ceilingheight - viewz;
+  worldbottom = frontsector->floorheight - viewz;
+
+  midtexture = toptexture = bottomtexture = maskedtexture = 0;
+  ds_p->maskedtexturecol = NULL;
+
+  if (!backsector)
+  {
+    // single sided line
+    midtexture = sidedef->midtexture;
+    // a single sided line is terminal, so it must mark ends
+    markfloor = markceiling = true;
+    if (linedef->flags & ML_DONTPEGBOTTOM)
+    {
+      vtop = frontsector->floorheight
+             + 128; ///??? textureheight[sidedef->midtexture];
+      // bottom of texture at bottom
+      rw_midtexturemid = vtop - viewz;	
+    }
+    else
+    {
+      // top of texture at top
+      rw_midtexturemid = worldtop;
+    }
+    rw_midtexturemid += sidedef->rowoffset;
+
+    ds_p->silhouette = SIL_BOTH;
+    ds_p->sprtopclip = screenheightarray;
+    ds_p->sprbottomclip = negonearray;
+    ds_p->bsilheight = INT_MAX;
+    ds_p->tsilheight = INT_MIN;
+  }
+  else
+  {
+    // two sided line
+    ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
+    ds_p->silhouette = 0;
+
+    if (frontsector->floorheight > backsector->floorheight)
+    {
+      ds_p->silhouette = SIL_BOTTOM;
+      ds_p->bsilheight = frontsector->floorheight;
+    }
+    else if (backsector->floorheight > viewz)
+    {
+      ds_p->silhouette = SIL_BOTTOM;
+      ds_p->bsilheight = INT_MAX;
+      // ds_p->sprbottomclip = negonearray;
+    }
+
+    if (frontsector->ceilingheight < backsector->ceilingheight)
+    {
+      ds_p->silhouette |= SIL_TOP;
+      ds_p->tsilheight = frontsector->ceilingheight;
+    }
+    else if (backsector->ceilingheight < viewz)
+    {
+      ds_p->silhouette |= SIL_TOP;
+      ds_p->tsilheight = INT_MIN;
+      // ds_p->sprtopclip = screenheightarray;
+    }
+
+    if (backsector->ceilingheight <= frontsector->floorheight)
+    {
+      ds_p->sprbottomclip = negonearray;
+      ds_p->bsilheight = INT_MAX;
+      ds_p->silhouette |= SIL_BOTTOM;
+    }
+
+    if (backsector->floorheight >= frontsector->ceilingheight)
+    {
+      ds_p->sprtopclip = screenheightarray;
+      ds_p->tsilheight = INT_MIN;
+      ds_p->silhouette |= SIL_TOP;
+    }
+
+    worldhigh = backsector->ceilingheight - viewz;
+    worldlow = backsector->floorheight - viewz;
+
+    // hack to allow height changes in outdoor areas
+    if (frontsector->ceilingpic == skyflatnum 
+        && backsector->ceilingpic == skyflatnum)
+    {
+      worldtop = worldhigh;
+    }
+
+
+    if (worldlow != worldbottom 
+        || backsector->floorpic != frontsector->floorpic
+        || backsector->lightlevel != frontsector->lightlevel)
+    {
+      markfloor = true;
+    }
+    else
+    {
+      // same plane on both sides
+      markfloor = false;
+    }
+
+
+    if (worldhigh != worldtop 
+        || backsector->ceilingpic != frontsector->ceilingpic
+        || backsector->lightlevel != frontsector->lightlevel)
+    {
+      markceiling = true;
+    }
+    else
+    {
+      // same plane on both sides
+      markceiling = false;
+    }
+
+    if (backsector->ceilingheight <= frontsector->floorheight
+        || backsector->floorheight >= frontsector->ceilingheight)
+    {
+      // closed door
+      markceiling = markfloor = true;
+    }
+
+
+    if (worldhigh < worldtop)
+    {
+      // top texture
+      toptexture = sidedef->toptexture;
+      if (linedef->flags & ML_DONTPEGTOP)
+      {
+        // top of texture at top
+        rw_toptexturemid = worldtop;
+      }
+      else
+      {
+        vtop = backsector->ceilingheight
+               + 128; ///???  textureheight[sidedef->toptexture];
+
+        // bottom of texture
+        rw_toptexturemid = vtop - viewz;	
+      }
+    }
+    if (worldlow > worldbottom)
+    {
+      // bottom texture
+      bottomtexture = sidedef->bottomtexture;
+
+      if (linedef->flags & ML_DONTPEGBOTTOM )
+      {
+        // bottom of texture at bottom
+        // top of texture at top
+        rw_bottomtexturemid = worldtop;
+      }
+      else	// top of texture at top
+        rw_bottomtexturemid = worldlow;
+    }
+    rw_toptexturemid += sidedef->rowoffset;
+    rw_bottomtexturemid += sidedef->rowoffset;
+
+    // allocate space for masked texture tables
+    if (sidedef->midtexture)
+    {
+      // masked midtexture
+      maskedtexture = true;
+      ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
+      lastopening += rw_stopx - rw_x;
+      total_openings += (rw_stopx - rw_x);
+
+      if (total_openings >= MAXOPENINGS)
+        throw overflow_exception();
+    }
+  }
+
+  // calculate rw_offset (only needed for textured lines)
+  segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
+
+  if (segtextured)
+  {
+    offsetangle = rw_normalangle-rw_angle1;
+
+    if (offsetangle > ANG180)
+      offsetangle = -offsetangle;
+
+    if (offsetangle > ANG90)
+      offsetangle = ANG90;
+
+    sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
+    rw_offset = FixedMul (hyp, sineval);
+
+    if (rw_normalangle-rw_angle1 < ANG180)
+      rw_offset = -rw_offset;
+
+    rw_offset += sidedef->textureoffset + curline->offset;
+    rw_centerangle = ANG90 + viewangle - rw_normalangle;
+
+  }
+
+  // if a floor / ceiling plane is on the wrong side
+  //  of the view plane, it is definitely invisible
+  //  and doesn't need to be marked.
+
+
+  if (frontsector->floorheight >= viewz)
+  {
+    // above view plane
+    markfloor = false;
+  }
+
+  if (frontsector->ceilingheight <= viewz 
+      && frontsector->ceilingpic != skyflatnum)
+  {
+    // below view plane
+    markceiling = false;
+  }
+
+
+  // calculate incremental stepping values for texture edges
+  worldtop >>= 4;
+  worldbottom >>= 4;
+
+  topstep = -FixedMul (rw_scalestep, worldtop);
+  topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
+
+  bottomstep = -FixedMul (rw_scalestep,worldbottom);
+  bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
+
+  if (backsector)
+  {	
+    worldhigh >>= 4;
+    worldlow >>= 4;
+
+    if (worldhigh < worldtop)
+    {
+      pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
+      pixhighstep = -FixedMul (rw_scalestep,worldhigh);
+    }
+
+    if (worldlow > worldbottom)
+    {
+      pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
+      pixlowstep = -FixedMul (rw_scalestep,worldlow);
+    }
+  }
+
+  // andrewj: make sure floorplane/ceilingplane are not NULL (prevent a crash)
+  if (!   floorplane) markfloor   = false;
+  if (! ceilingplane) markceiling = false;
+
+  // render it
+  if (markceiling)
+    ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
+
+  if (markfloor)
+    floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
+
+  R_RenderSegLoop ();
+
+
+  // save sprite clipping info
+  if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture)
+      && !ds_p->sprtopclip)
+  {
+    memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
+    ds_p->sprtopclip = lastopening - start;
+    lastopening += rw_stopx - start;
+    total_openings += (rw_stopx - start);
+
+    if (total_openings >= MAXOPENINGS)
+      throw overflow_exception();
+  }
+
+  if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture)
+      && !ds_p->sprbottomclip)
+  {
+    memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
+    ds_p->sprbottomclip = lastopening - start;
+    lastopening += rw_stopx - start;	
+    total_openings += (rw_stopx - start);
+
+    if (total_openings >= MAXOPENINGS)
+      throw overflow_exception();
+  }
+
+  if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
+  {
+    ds_p->silhouette |= SIL_TOP;
+    ds_p->tsilheight = INT_MIN;
+  }
+  if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
+  {
+    ds_p->silhouette |= SIL_BOTTOM;
+    ds_p->bsilheight = INT_MAX;
+  }
+  ds_p++;
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/r_state.h b/Source/Plugins/vpo_dll/r_state.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3dca05eda0b12de9242922a8098cb72aa08c02a
--- /dev/null
+++ b/Source/Plugins/vpo_dll/r_state.h
@@ -0,0 +1,107 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Refresh/render internal state variables (global).
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_STATE__
+#define __R_STATE__
+
+
+//
+// Refresh internal data structures,
+//  for rendering.
+//
+
+// needed for pre rendering (fracs)
+extern fixed_t*		spritewidth;
+
+extern fixed_t*		spriteoffset;
+extern fixed_t*		spritetopoffset;
+
+extern int		viewwidth;
+extern int		scaledviewwidth;
+extern int		viewheight;
+
+extern int		firstflat;
+
+
+//
+// Lookup tables for map data.
+//
+extern int		numvertexes;
+extern vertex_t*	vertexes;
+
+extern int		numsegs;
+extern seg_t*		segs;
+
+extern int		numsectors;
+extern sector_t*	sectors;
+
+extern int		numsubsectors;
+extern subsector_t*	subsectors;
+
+extern int		numnodes;
+extern node_t*		nodes;
+
+extern int		numlines;
+extern line_t*		lines;
+
+extern int		numsides;
+extern side_t*		sides;
+
+
+//
+// POV data.
+//
+extern fixed_t		viewx;
+extern fixed_t		viewy;
+extern fixed_t		viewz;
+
+extern angle_t		viewangle;
+
+
+// ?
+extern angle_t		clipangle;
+
+extern int		viewangletox[FINEANGLES/2];
+extern angle_t		xtoviewangle[SCREENWIDTH+1];
+//extern fixed_t		finetangent[FINEANGLES/2];
+
+extern fixed_t		rw_distance;
+extern angle_t		rw_normalangle;
+
+
+
+// angle to line origin
+extern int		rw_angle1;
+
+// Segs count?
+extern int		sscount;
+
+extern visplane_t*	floorplane;
+extern visplane_t*	ceilingplane;
+
+
+#endif
diff --git a/Source/Plugins/vpo_dll/stdint.h b/Source/Plugins/vpo_dll/stdint.h
new file mode 100644
index 0000000000000000000000000000000000000000..d02608a5972642c7b7a13b987f21e2502a5af3ea
--- /dev/null
+++ b/Source/Plugins/vpo_dll/stdint.h
@@ -0,0 +1,247 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2008 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/Source/Plugins/vpo_dll/sys_endian.h b/Source/Plugins/vpo_dll/sys_endian.h
new file mode 100644
index 0000000000000000000000000000000000000000..16f80ef85ddb937b6ceed5a846cc8430b5d0426a
--- /dev/null
+++ b/Source/Plugins/vpo_dll/sys_endian.h
@@ -0,0 +1,128 @@
+//------------------------------------------------------------------------
+//  EDGE Endian handling
+//------------------------------------------------------------------------
+//
+//  Eureka DOOM Editor
+//
+//  Copyright (C) 2006-2008 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+//
+//  Using code from SDL_byteorder.h and SDL_endian.h.
+//  Copyright (C) 1997-2004 Sam Lantinga.
+//
+//------------------------------------------------------------------------
+
+#ifndef __SYS_ENDIAN_H__
+#define __SYS_ENDIAN_H__
+
+
+// ---- determine byte order ----
+
+#define UT_LIL_ENDIAN  1234
+#define UT_BIG_ENDIAN  4321
+
+#if defined(__LITTLE_ENDIAN__) || defined(WIN32) ||  \
+    defined(__i386__) || defined(__i386) ||          \
+    defined(__ia64__) || defined(__x86_64__)  ||     \
+    defined(__alpha__) || defined(__alpha)  ||       \
+    defined(__arm__) || defined(__SYMBIAN32__) ||    \
+    (defined(__mips__) && defined(__MIPSEL__))
+#define UT_BYTEORDER   UT_LIL_ENDIAN
+#else
+#define UT_BYTEORDER   UT_BIG_ENDIAN
+#endif
+
+
+// ---- the gruntwork of swapping ----
+
+#if defined(__GNUC__) && defined(__i386__)
+static inline u16_t UT_Swap16(u16_t x)
+{
+  __asm__("xchgb %b0,%h0" : "=q" (x) :  "0" (x));
+  return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+static inline u16_t UT_Swap16(u16_t x)
+{
+  __asm__("xchgb %b0,%h0" : "=Q" (x) :  "0" (x));
+  return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+static inline u16_t UT_Swap16(u16_t x)
+{
+  u16_t result;
+
+  __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (x >> 8), "r" (x));
+  return result;
+}
+#else
+static inline u16_t UT_Swap16(u16_t x) {
+  return((x<<8)|(x>>8));
+}
+#endif
+
+#if defined(__GNUC__) && defined(__i386__)
+static inline u32_t UT_Swap32(u32_t x)
+{
+  __asm__("bswap %0" : "=r" (x) : "0" (x));
+  return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+static inline u32_t UT_Swap32(u32_t x)
+{
+  __asm__("bswapl %0" : "=r" (x) : "0" (x));
+  return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+static inline u32_t UT_Swap32(u32_t x)
+{
+  u32_t result;
+
+  __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result) : "0" (x>>24), "r" (x));
+  __asm__("rlwimi %0,%2,8,8,15"   : "=&r" (result) : "0" (result),    "r" (x));
+  __asm__("rlwimi %0,%2,24,0,7"   : "=&r" (result) : "0" (result),    "r" (x));
+  return result;
+}
+#else
+static inline u32_t UT_Swap32(u32_t x) {
+  return ((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24));
+}
+#endif
+
+
+// ---- byte swap from specified endianness to native ----
+
+#if (UT_BYTEORDER == UT_LIL_ENDIAN)
+#define LE_U16(X)  ((u16_t)(X))
+#define LE_U32(X)  ((u32_t)(X))
+#define BE_U16(X)  UT_Swap16(X)
+#define BE_U32(X)  UT_Swap32(X)
+#else
+#define LE_U16(X)  UT_Swap16(X)
+#define LE_U32(X)  UT_Swap32(X)
+#define BE_U16(X)  ((u16_t)(X))
+#define BE_U32(X)  ((u32_t)(X))
+#endif
+
+// signed versions of the above
+#define LE_S16(X)  ((s16_t) LE_U16((u16_t) (X)))
+#define LE_S32(X)  ((s32_t) LE_U32((u32_t) (X)))
+#define BE_S16(X)  ((s16_t) BE_U16((u16_t) (X)))
+#define BE_S32(X)  ((s32_t) BE_U32((u32_t) (X)))
+
+
+#endif // __SYS_ENDIAN_H__
+
+//--- editor settings ---
+// vi:ts=4:sw=4:noexpandtab
diff --git a/Source/Plugins/vpo_dll/sys_macro.h b/Source/Plugins/vpo_dll/sys_macro.h
new file mode 100644
index 0000000000000000000000000000000000000000..c30e8e119a230649aaed9e8522c86a3e44c781d5
--- /dev/null
+++ b/Source/Plugins/vpo_dll/sys_macro.h
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------
+//  Macros
+//------------------------------------------------------------------------
+//
+//  Eureka DOOM Editor
+//
+//  Copyright (C) 2006-2008 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+
+#ifndef __SYS_MACRO_H__
+#define __SYS_MACRO_H__
+
+// basic macros
+
+#ifndef NULL
+#define NULL    ((void*) 0)
+#endif
+
+#ifndef M_PI
+#define M_PI  3.14159265358979323846
+#endif
+
+#ifndef MAX
+#define MAX(a,b)  ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b)  ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ABS
+#define ABS(a)  ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef SGN
+#define SGN(a)  ((a) < 0 ? -1 : (a) > 0 ? +1 : 0)
+#endif
+
+#ifndef I_ROUND
+#define I_ROUND(x)  ((int) (((x) < 0.0f) ? ((x) - 0.5f) : ((x) + 0.5f)))
+#endif
+
+#ifndef CLAMP
+#define CLAMP(low,x,high)  \
+    ((x) < (low) ? (low) : (x) > (high) ? (high) : (x))
+#endif
+
+#endif  /* __SYS_MACRO_H__ */
+
+//--- editor settings ---
+// vi:ts=4:sw=4:noexpandtab
diff --git a/Source/Plugins/vpo_dll/sys_type.h b/Source/Plugins/vpo_dll/sys_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0ad6c3891174b502af5be378e5e29a874e45df1
--- /dev/null
+++ b/Source/Plugins/vpo_dll/sys_type.h
@@ -0,0 +1,39 @@
+//------------------------------------------------------------------------
+//  Type definitions
+//------------------------------------------------------------------------
+//
+//  Eureka DOOM Editor
+//
+//  Copyright (C) 2006-2008 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+
+#ifndef __SYS_TYPE_H__
+#define __SYS_TYPE_H__
+
+// basic types
+
+typedef char  s8_t;
+typedef short s16_t;
+typedef int   s32_t;
+ 
+typedef unsigned char  u8_t;
+typedef unsigned short u16_t;
+typedef unsigned int   u32_t;
+
+typedef u8_t byte;
+
+#endif  /* __SYS_TYPE_H__ */
+
+//--- editor settings ---
+// vi:ts=4:sw=4:noexpandtab
diff --git a/Source/Plugins/vpo_dll/tables.cc b/Source/Plugins/vpo_dll/tables.cc
new file mode 100644
index 0000000000000000000000000000000000000000..43f90b4625e8250b975ce6ba66c80ee52f827896
--- /dev/null
+++ b/Source/Plugins/vpo_dll/tables.cc
@@ -0,0 +1,2129 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Lookup tables.
+//	Do not try to look them up :-).
+//	In the order of appearance: 
+//
+//	int finetangent[4096]	- Tangens LUT.
+//	 Should work with BAM fairly well (12 of 16bit,
+//      effectively, by shifting).
+//
+//	int finesine[10240]		- Sine lookup.
+//	 Guess what, serves as cosine, too.
+//	 Remarkable thing is, how to use BAMs with this? 
+//
+//	int tantoangle[2049]	- ArcTan LUT,
+//	  maps tan(angle) to angle fast. Gotta search.
+//	
+//    
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+int
+SlopeDiv
+( unsigned	num,
+  unsigned	den)
+{
+    unsigned 	ans;
+    
+    if (den < 512)
+	return SLOPERANGE;
+
+    ans = (num<<3)/(den>>8);
+
+    return ans <= SLOPERANGE ? ans : SLOPERANGE;
+}
+
+
+const int finetangent[4096] =
+{
+    -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683,
+    -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368,
+    -5178251,-4882318,-4618375,-4381502,-4167737,-3973855,-3797206,-3635590,
+    -3487165,-3350381,-3223918,-3106651,-2997613,-2895966,-2800983,-2712030,
+    -2628549,-2550052,-2476104,-2406322,-2340362,-2277919,-2218719,-2162516,
+    -2109087,-2058233,-2009771,-1963536,-1919378,-1877161,-1836758,-1798063,
+    -1760956,-1725348,-1691149,-1658278,-1626658,-1596220,-1566898,-1538632,
+    -1511367,-1485049,-1459630,-1435065,-1411312,-1388330,-1366084,-1344537,
+    -1323658,-1303416,-1283783,-1264730,-1246234,-1228269,-1210813,-1193846,
+    -1177345,-1161294,-1145673,-1130465,-1115654,-1101225,-1087164,-1073455,
+    -1060087,-1047046,-1034322,-1021901,-1009774,-997931,-986361,-975054,
+    -964003,-953199,-942633,-932298,-922186,-912289,-902602,-893117,
+    -883829,-874730,-865817,-857081,-848520,-840127,-831898,-823827,
+    -815910,-808143,-800521,-793041,-785699,-778490,-771411,-764460,
+    -757631,-750922,-744331,-737853,-731486,-725227,-719074,-713023,
+    -707072,-701219,-695462,-689797,-684223,-678737,-673338,-668024,
+    -662792,-657640,-652568,-647572,-642651,-637803,-633028,-628323,
+    -623686,-619117,-614613,-610174,-605798,-601483,-597229,-593033,
+    -588896,-584815,-580789,-576818,-572901,-569035,-565221,-561456,
+    -557741,-554074,-550455,-546881,-543354,-539870,-536431,-533034,
+    -529680,-526366,-523094,-519861,-516667,-513512,-510394,-507313,
+    -504269,-501261,-498287,-495348,-492443,-489571,-486732,-483925,
+    -481150,-478406,-475692,-473009,-470355,-467730,-465133,-462565,
+    -460024,-457511,-455024,-452564,-450129,-447720,-445337,-442978,
+    -440643,-438332,-436045,-433781,-431540,-429321,-427125,-424951,
+    -422798,-420666,-418555,-416465,-414395,-412344,-410314,-408303,
+    -406311,-404338,-402384,-400448,-398530,-396630,-394747,-392882,
+    -391034,-389202,-387387,-385589,-383807,-382040,-380290,-378555,
+    -376835,-375130,-373440,-371765,-370105,-368459,-366826,-365208,
+    -363604,-362013,-360436,-358872,-357321,-355783,-354257,-352744,
+    -351244,-349756,-348280,-346816,-345364,-343924,-342495,-341078,
+    -339671,-338276,-336892,-335519,-334157,-332805,-331464,-330133,
+    -328812,-327502,-326201,-324910,-323629,-322358,-321097,-319844,
+    -318601,-317368,-316143,-314928,-313721,-312524,-311335,-310154,
+    -308983,-307819,-306664,-305517,-304379,-303248,-302126,-301011,
+    -299904,-298805,-297714,-296630,-295554,-294485,-293423,-292369,
+    -291322,-290282,-289249,-288223,-287204,-286192,-285186,-284188,
+    -283195,-282210,-281231,-280258,-279292,-278332,-277378,-276430,
+    -275489,-274553,-273624,-272700,-271782,-270871,-269965,-269064,
+    -268169,-267280,-266397,-265519,-264646,-263779,-262917,-262060,
+    -261209,-260363,-259522,-258686,-257855,-257029,-256208,-255392,
+    -254581,-253774,-252973,-252176,-251384,-250596,-249813,-249035,
+    -248261,-247492,-246727,-245966,-245210,-244458,-243711,-242967,
+    -242228,-241493,-240763,-240036,-239314,-238595,-237881,-237170,
+    -236463,-235761,-235062,-234367,-233676,-232988,-232304,-231624,
+    -230948,-230275,-229606,-228941,-228279,-227621,-226966,-226314,
+    -225666,-225022,-224381,-223743,-223108,-222477,-221849,-221225,
+    -220603,-219985,-219370,-218758,-218149,-217544,-216941,-216341,
+    -215745,-215151,-214561,-213973,-213389,-212807,-212228,-211652,
+    -211079,-210509,-209941,-209376,-208815,-208255,-207699,-207145,
+    -206594,-206045,-205500,-204956,-204416,-203878,-203342,-202809,
+    -202279,-201751,-201226,-200703,-200182,-199664,-199149,-198636,
+    -198125,-197616,-197110,-196606,-196105,-195606,-195109,-194614,
+    -194122,-193631,-193143,-192658,-192174,-191693,-191213,-190736,
+    -190261,-189789,-189318,-188849,-188382,-187918,-187455,-186995,
+    -186536,-186080,-185625,-185173,-184722,-184274,-183827,-183382,
+    -182939,-182498,-182059,-181622,-181186,-180753,-180321,-179891,
+    -179463,-179037,-178612,-178190,-177769,-177349,-176932,-176516,
+    -176102,-175690,-175279,-174870,-174463,-174057,-173653,-173251,
+    -172850,-172451,-172053,-171657,-171263,-170870,-170479,-170089,
+    -169701,-169315,-168930,-168546,-168164,-167784,-167405,-167027,
+    -166651,-166277,-165904,-165532,-165162,-164793,-164426,-164060,
+    -163695,-163332,-162970,-162610,-162251,-161893,-161537,-161182,
+    -160828,-160476,-160125,-159775,-159427,-159079,-158734,-158389,
+    -158046,-157704,-157363,-157024,-156686,-156349,-156013,-155678,
+    -155345,-155013,-154682,-154352,-154024,-153697,-153370,-153045,
+    -152722,-152399,-152077,-151757,-151438,-151120,-150803,-150487,
+    -150172,-149859,-149546,-149235,-148924,-148615,-148307,-148000,
+    -147693,-147388,-147084,-146782,-146480,-146179,-145879,-145580,
+    -145282,-144986,-144690,-144395,-144101,-143808,-143517,-143226,
+    -142936,-142647,-142359,-142072,-141786,-141501,-141217,-140934,
+    -140651,-140370,-140090,-139810,-139532,-139254,-138977,-138701,
+    -138426,-138152,-137879,-137607,-137335,-137065,-136795,-136526,
+    -136258,-135991,-135725,-135459,-135195,-134931,-134668,-134406,
+    -134145,-133884,-133625,-133366,-133108,-132851,-132594,-132339,
+    -132084,-131830,-131576,-131324,-131072,-130821,-130571,-130322,
+    -130073,-129825,-129578,-129332,-129086,-128841,-128597,-128353,
+    -128111,-127869,-127627,-127387,-127147,-126908,-126669,-126432,
+    -126195,-125959,-125723,-125488,-125254,-125020,-124787,-124555,
+    -124324,-124093,-123863,-123633,-123404,-123176,-122949,-122722,
+    -122496,-122270,-122045,-121821,-121597,-121374,-121152,-120930,
+    -120709,-120489,-120269,-120050,-119831,-119613,-119396,-119179,
+    -118963,-118747,-118532,-118318,-118104,-117891,-117678,-117466,
+    -117254,-117044,-116833,-116623,-116414,-116206,-115998,-115790,
+    -115583,-115377,-115171,-114966,-114761,-114557,-114354,-114151,
+    -113948,-113746,-113545,-113344,-113143,-112944,-112744,-112546,
+    -112347,-112150,-111952,-111756,-111560,-111364,-111169,-110974,
+    -110780,-110586,-110393,-110200,-110008,-109817,-109626,-109435,
+    -109245,-109055,-108866,-108677,-108489,-108301,-108114,-107927,
+    -107741,-107555,-107369,-107184,-107000,-106816,-106632,-106449,
+    -106266,-106084,-105902,-105721,-105540,-105360,-105180,-105000,
+    -104821,-104643,-104465,-104287,-104109,-103933,-103756,-103580,
+    -103404,-103229,-103054,-102880,-102706,-102533,-102360,-102187,
+    -102015,-101843,-101671,-101500,-101330,-101159,-100990,-100820,
+    -100651,-100482,-100314,-100146,-99979,-99812,-99645,-99479,
+    -99313,-99148,-98982,-98818,-98653,-98489,-98326,-98163,
+    -98000,-97837,-97675,-97513,-97352,-97191,-97030,-96870,
+    -96710,-96551,-96391,-96233,-96074,-95916,-95758,-95601,
+    -95444,-95287,-95131,-94975,-94819,-94664,-94509,-94354,
+    -94200,-94046,-93892,-93739,-93586,-93434,-93281,-93129,
+    -92978,-92826,-92675,-92525,-92375,-92225,-92075,-91926,
+    -91777,-91628,-91480,-91332,-91184,-91036,-90889,-90742,
+    -90596,-90450,-90304,-90158,-90013,-89868,-89724,-89579,
+    -89435,-89292,-89148,-89005,-88862,-88720,-88577,-88435,
+    -88294,-88152,-88011,-87871,-87730,-87590,-87450,-87310,
+    -87171,-87032,-86893,-86755,-86616,-86479,-86341,-86204,
+    -86066,-85930,-85793,-85657,-85521,-85385,-85250,-85114,
+    -84980,-84845,-84710,-84576,-84443,-84309,-84176,-84043,
+    -83910,-83777,-83645,-83513,-83381,-83250,-83118,-82987,
+    -82857,-82726,-82596,-82466,-82336,-82207,-82078,-81949,
+    -81820,-81691,-81563,-81435,-81307,-81180,-81053,-80925,
+    -80799,-80672,-80546,-80420,-80294,-80168,-80043,-79918,
+    -79793,-79668,-79544,-79420,-79296,-79172,-79048,-78925,
+    -78802,-78679,-78557,-78434,-78312,-78190,-78068,-77947,
+    -77826,-77705,-77584,-77463,-77343,-77223,-77103,-76983,
+    -76864,-76744,-76625,-76506,-76388,-76269,-76151,-76033,
+    -75915,-75797,-75680,-75563,-75446,-75329,-75213,-75096,
+    -74980,-74864,-74748,-74633,-74517,-74402,-74287,-74172,
+    -74058,-73944,-73829,-73715,-73602,-73488,-73375,-73262,
+    -73149,-73036,-72923,-72811,-72699,-72587,-72475,-72363,
+    -72252,-72140,-72029,-71918,-71808,-71697,-71587,-71477,
+    -71367,-71257,-71147,-71038,-70929,-70820,-70711,-70602,
+    -70494,-70385,-70277,-70169,-70061,-69954,-69846,-69739,
+    -69632,-69525,-69418,-69312,-69205,-69099,-68993,-68887,
+    -68781,-68676,-68570,-68465,-68360,-68255,-68151,-68046,
+    -67942,-67837,-67733,-67629,-67526,-67422,-67319,-67216,
+    -67113,-67010,-66907,-66804,-66702,-66600,-66498,-66396,
+    -66294,-66192,-66091,-65989,-65888,-65787,-65686,-65586,
+    -65485,-65385,-65285,-65185,-65085,-64985,-64885,-64786,
+    -64687,-64587,-64488,-64389,-64291,-64192,-64094,-63996,
+    -63897,-63799,-63702,-63604,-63506,-63409,-63312,-63215,
+    -63118,-63021,-62924,-62828,-62731,-62635,-62539,-62443,
+    -62347,-62251,-62156,-62060,-61965,-61870,-61775,-61680,
+    -61585,-61491,-61396,-61302,-61208,-61114,-61020,-60926,
+    -60833,-60739,-60646,-60552,-60459,-60366,-60273,-60181,
+    -60088,-59996,-59903,-59811,-59719,-59627,-59535,-59444,
+    -59352,-59261,-59169,-59078,-58987,-58896,-58805,-58715,
+    -58624,-58534,-58443,-58353,-58263,-58173,-58083,-57994,
+    -57904,-57815,-57725,-57636,-57547,-57458,-57369,-57281,
+    -57192,-57104,-57015,-56927,-56839,-56751,-56663,-56575,
+    -56487,-56400,-56312,-56225,-56138,-56051,-55964,-55877,
+    -55790,-55704,-55617,-55531,-55444,-55358,-55272,-55186,
+    -55100,-55015,-54929,-54843,-54758,-54673,-54587,-54502,
+    -54417,-54333,-54248,-54163,-54079,-53994,-53910,-53826,
+    -53741,-53657,-53574,-53490,-53406,-53322,-53239,-53156,
+    -53072,-52989,-52906,-52823,-52740,-52657,-52575,-52492,
+    -52410,-52327,-52245,-52163,-52081,-51999,-51917,-51835,
+    -51754,-51672,-51591,-51509,-51428,-51347,-51266,-51185,
+    -51104,-51023,-50942,-50862,-50781,-50701,-50621,-50540,
+    -50460,-50380,-50300,-50221,-50141,-50061,-49982,-49902,
+    -49823,-49744,-49664,-49585,-49506,-49427,-49349,-49270,
+    -49191,-49113,-49034,-48956,-48878,-48799,-48721,-48643,
+    -48565,-48488,-48410,-48332,-48255,-48177,-48100,-48022,
+    -47945,-47868,-47791,-47714,-47637,-47560,-47484,-47407,
+    -47331,-47254,-47178,-47102,-47025,-46949,-46873,-46797,
+    -46721,-46646,-46570,-46494,-46419,-46343,-46268,-46193,
+    -46118,-46042,-45967,-45892,-45818,-45743,-45668,-45593,
+    -45519,-45444,-45370,-45296,-45221,-45147,-45073,-44999,
+    -44925,-44851,-44778,-44704,-44630,-44557,-44483,-44410,
+    -44337,-44263,-44190,-44117,-44044,-43971,-43898,-43826,
+    -43753,-43680,-43608,-43535,-43463,-43390,-43318,-43246,
+    -43174,-43102,-43030,-42958,-42886,-42814,-42743,-42671,
+    -42600,-42528,-42457,-42385,-42314,-42243,-42172,-42101,
+    -42030,-41959,-41888,-41817,-41747,-41676,-41605,-41535,
+    -41465,-41394,-41324,-41254,-41184,-41113,-41043,-40973,
+    -40904,-40834,-40764,-40694,-40625,-40555,-40486,-40416,
+    -40347,-40278,-40208,-40139,-40070,-40001,-39932,-39863,
+    -39794,-39726,-39657,-39588,-39520,-39451,-39383,-39314,
+    -39246,-39178,-39110,-39042,-38973,-38905,-38837,-38770,
+    -38702,-38634,-38566,-38499,-38431,-38364,-38296,-38229,
+    -38161,-38094,-38027,-37960,-37893,-37826,-37759,-37692,
+    -37625,-37558,-37491,-37425,-37358,-37291,-37225,-37158,
+    -37092,-37026,-36959,-36893,-36827,-36761,-36695,-36629,
+    -36563,-36497,-36431,-36365,-36300,-36234,-36168,-36103,
+    -36037,-35972,-35907,-35841,-35776,-35711,-35646,-35580,
+    -35515,-35450,-35385,-35321,-35256,-35191,-35126,-35062,
+    -34997,-34932,-34868,-34803,-34739,-34675,-34610,-34546,
+    -34482,-34418,-34354,-34289,-34225,-34162,-34098,-34034,
+    -33970,-33906,-33843,-33779,-33715,-33652,-33588,-33525,
+    -33461,-33398,-33335,-33272,-33208,-33145,-33082,-33019,
+    -32956,-32893,-32830,-32767,-32705,-32642,-32579,-32516,
+    -32454,-32391,-32329,-32266,-32204,-32141,-32079,-32017,
+    -31955,-31892,-31830,-31768,-31706,-31644,-31582,-31520,
+    -31458,-31396,-31335,-31273,-31211,-31150,-31088,-31026,
+    -30965,-30904,-30842,-30781,-30719,-30658,-30597,-30536,
+    -30474,-30413,-30352,-30291,-30230,-30169,-30108,-30048,
+    -29987,-29926,-29865,-29805,-29744,-29683,-29623,-29562,
+    -29502,-29441,-29381,-29321,-29260,-29200,-29140,-29080,
+    -29020,-28959,-28899,-28839,-28779,-28719,-28660,-28600,
+    -28540,-28480,-28420,-28361,-28301,-28241,-28182,-28122,
+    -28063,-28003,-27944,-27884,-27825,-27766,-27707,-27647,
+    -27588,-27529,-27470,-27411,-27352,-27293,-27234,-27175,
+    -27116,-27057,-26998,-26940,-26881,-26822,-26763,-26705,
+    -26646,-26588,-26529,-26471,-26412,-26354,-26295,-26237,
+    -26179,-26120,-26062,-26004,-25946,-25888,-25830,-25772,
+    -25714,-25656,-25598,-25540,-25482,-25424,-25366,-25308,
+    -25251,-25193,-25135,-25078,-25020,-24962,-24905,-24847,
+    -24790,-24732,-24675,-24618,-24560,-24503,-24446,-24389,
+    -24331,-24274,-24217,-24160,-24103,-24046,-23989,-23932,
+    -23875,-23818,-23761,-23704,-23647,-23591,-23534,-23477,
+    -23420,-23364,-23307,-23250,-23194,-23137,-23081,-23024,
+    -22968,-22911,-22855,-22799,-22742,-22686,-22630,-22573,
+    -22517,-22461,-22405,-22349,-22293,-22237,-22181,-22125,
+    -22069,-22013,-21957,-21901,-21845,-21789,-21733,-21678,
+    -21622,-21566,-21510,-21455,-21399,-21343,-21288,-21232,
+    -21177,-21121,-21066,-21010,-20955,-20900,-20844,-20789,
+    -20734,-20678,-20623,-20568,-20513,-20457,-20402,-20347,
+    -20292,-20237,-20182,-20127,-20072,-20017,-19962,-19907,
+    -19852,-19797,-19742,-19688,-19633,-19578,-19523,-19469,
+    -19414,-19359,-19305,-19250,-19195,-19141,-19086,-19032,
+    -18977,-18923,-18868,-18814,-18760,-18705,-18651,-18597,
+    -18542,-18488,-18434,-18380,-18325,-18271,-18217,-18163,
+    -18109,-18055,-18001,-17946,-17892,-17838,-17784,-17731,
+    -17677,-17623,-17569,-17515,-17461,-17407,-17353,-17300,
+    -17246,-17192,-17138,-17085,-17031,-16977,-16924,-16870,
+    -16817,-16763,-16710,-16656,-16603,-16549,-16496,-16442,
+    -16389,-16335,-16282,-16229,-16175,-16122,-16069,-16015,
+    -15962,-15909,-15856,-15802,-15749,-15696,-15643,-15590,
+    -15537,-15484,-15431,-15378,-15325,-15272,-15219,-15166,
+    -15113,-15060,-15007,-14954,-14901,-14848,-14795,-14743,
+    -14690,-14637,-14584,-14531,-14479,-14426,-14373,-14321,
+    -14268,-14215,-14163,-14110,-14057,-14005,-13952,-13900,
+    -13847,-13795,-13742,-13690,-13637,-13585,-13533,-13480,
+    -13428,-13375,-13323,-13271,-13218,-13166,-13114,-13062,
+    -13009,-12957,-12905,-12853,-12800,-12748,-12696,-12644,
+    -12592,-12540,-12488,-12436,-12383,-12331,-12279,-12227,
+    -12175,-12123,-12071,-12019,-11967,-11916,-11864,-11812,
+    -11760,-11708,-11656,-11604,-11552,-11501,-11449,-11397,
+    -11345,-11293,-11242,-11190,-11138,-11086,-11035,-10983,
+    -10931,-10880,-10828,-10777,-10725,-10673,-10622,-10570,
+    -10519,-10467,-10415,-10364,-10312,-10261,-10209,-10158,
+    -10106,-10055,-10004,-9952,-9901,-9849,-9798,-9747,
+    -9695,-9644,-9592,-9541,-9490,-9438,-9387,-9336,
+    -9285,-9233,-9182,-9131,-9080,-9028,-8977,-8926,
+    -8875,-8824,-8772,-8721,-8670,-8619,-8568,-8517,
+    -8466,-8414,-8363,-8312,-8261,-8210,-8159,-8108,
+    -8057,-8006,-7955,-7904,-7853,-7802,-7751,-7700,
+    -7649,-7598,-7547,-7496,-7445,-7395,-7344,-7293,
+    -7242,-7191,-7140,-7089,-7038,-6988,-6937,-6886,
+    -6835,-6784,-6733,-6683,-6632,-6581,-6530,-6480,
+    -6429,-6378,-6327,-6277,-6226,-6175,-6124,-6074,
+    -6023,-5972,-5922,-5871,-5820,-5770,-5719,-5668,
+    -5618,-5567,-5517,-5466,-5415,-5365,-5314,-5264,
+    -5213,-5162,-5112,-5061,-5011,-4960,-4910,-4859,
+    -4808,-4758,-4707,-4657,-4606,-4556,-4505,-4455,
+    -4404,-4354,-4303,-4253,-4202,-4152,-4101,-4051,
+    -4001,-3950,-3900,-3849,-3799,-3748,-3698,-3648,
+    -3597,-3547,-3496,-3446,-3395,-3345,-3295,-3244,
+    -3194,-3144,-3093,-3043,-2992,-2942,-2892,-2841,
+    -2791,-2741,-2690,-2640,-2590,-2539,-2489,-2439,
+    -2388,-2338,-2288,-2237,-2187,-2137,-2086,-2036,
+    -1986,-1935,-1885,-1835,-1784,-1734,-1684,-1633,
+    -1583,-1533,-1483,-1432,-1382,-1332,-1281,-1231,
+    -1181,-1131,-1080,-1030,-980,-929,-879,-829,
+    -779,-728,-678,-628,-578,-527,-477,-427,
+    -376,-326,-276,-226,-175,-125,-75,-25,
+    25,75,125,175,226,276,326,376,
+    427,477,527,578,628,678,728,779,
+    829,879,929,980,1030,1080,1131,1181,
+    1231,1281,1332,1382,1432,1483,1533,1583,
+    1633,1684,1734,1784,1835,1885,1935,1986,
+    2036,2086,2137,2187,2237,2288,2338,2388,
+    2439,2489,2539,2590,2640,2690,2741,2791,
+    2841,2892,2942,2992,3043,3093,3144,3194,
+    3244,3295,3345,3395,3446,3496,3547,3597,
+    3648,3698,3748,3799,3849,3900,3950,4001,
+    4051,4101,4152,4202,4253,4303,4354,4404,
+    4455,4505,4556,4606,4657,4707,4758,4808,
+    4859,4910,4960,5011,5061,5112,5162,5213,
+    5264,5314,5365,5415,5466,5517,5567,5618,
+    5668,5719,5770,5820,5871,5922,5972,6023,
+    6074,6124,6175,6226,6277,6327,6378,6429,
+    6480,6530,6581,6632,6683,6733,6784,6835,
+    6886,6937,6988,7038,7089,7140,7191,7242,
+    7293,7344,7395,7445,7496,7547,7598,7649,
+    7700,7751,7802,7853,7904,7955,8006,8057,
+    8108,8159,8210,8261,8312,8363,8414,8466,
+    8517,8568,8619,8670,8721,8772,8824,8875,
+    8926,8977,9028,9080,9131,9182,9233,9285,
+    9336,9387,9438,9490,9541,9592,9644,9695,
+    9747,9798,9849,9901,9952,10004,10055,10106,
+    10158,10209,10261,10312,10364,10415,10467,10519,
+    10570,10622,10673,10725,10777,10828,10880,10931,
+    10983,11035,11086,11138,11190,11242,11293,11345,
+    11397,11449,11501,11552,11604,11656,11708,11760,
+    11812,11864,11916,11967,12019,12071,12123,12175,
+    12227,12279,12331,12383,12436,12488,12540,12592,
+    12644,12696,12748,12800,12853,12905,12957,13009,
+    13062,13114,13166,13218,13271,13323,13375,13428,
+    13480,13533,13585,13637,13690,13742,13795,13847,
+    13900,13952,14005,14057,14110,14163,14215,14268,
+    14321,14373,14426,14479,14531,14584,14637,14690,
+    14743,14795,14848,14901,14954,15007,15060,15113,
+    15166,15219,15272,15325,15378,15431,15484,15537,
+    15590,15643,15696,15749,15802,15856,15909,15962,
+    16015,16069,16122,16175,16229,16282,16335,16389,
+    16442,16496,16549,16603,16656,16710,16763,16817,
+    16870,16924,16977,17031,17085,17138,17192,17246,
+    17300,17353,17407,17461,17515,17569,17623,17677,
+    17731,17784,17838,17892,17946,18001,18055,18109,
+    18163,18217,18271,18325,18380,18434,18488,18542,
+    18597,18651,18705,18760,18814,18868,18923,18977,
+    19032,19086,19141,19195,19250,19305,19359,19414,
+    19469,19523,19578,19633,19688,19742,19797,19852,
+    19907,19962,20017,20072,20127,20182,20237,20292,
+    20347,20402,20457,20513,20568,20623,20678,20734,
+    20789,20844,20900,20955,21010,21066,21121,21177,
+    21232,21288,21343,21399,21455,21510,21566,21622,
+    21678,21733,21789,21845,21901,21957,22013,22069,
+    22125,22181,22237,22293,22349,22405,22461,22517,
+    22573,22630,22686,22742,22799,22855,22911,22968,
+    23024,23081,23137,23194,23250,23307,23364,23420,
+    23477,23534,23591,23647,23704,23761,23818,23875,
+    23932,23989,24046,24103,24160,24217,24274,24331,
+    24389,24446,24503,24560,24618,24675,24732,24790,
+    24847,24905,24962,25020,25078,25135,25193,25251,
+    25308,25366,25424,25482,25540,25598,25656,25714,
+    25772,25830,25888,25946,26004,26062,26120,26179,
+    26237,26295,26354,26412,26471,26529,26588,26646,
+    26705,26763,26822,26881,26940,26998,27057,27116,
+    27175,27234,27293,27352,27411,27470,27529,27588,
+    27647,27707,27766,27825,27884,27944,28003,28063,
+    28122,28182,28241,28301,28361,28420,28480,28540,
+    28600,28660,28719,28779,28839,28899,28959,29020,
+    29080,29140,29200,29260,29321,29381,29441,29502,
+    29562,29623,29683,29744,29805,29865,29926,29987,
+    30048,30108,30169,30230,30291,30352,30413,30474,
+    30536,30597,30658,30719,30781,30842,30904,30965,
+    31026,31088,31150,31211,31273,31335,31396,31458,
+    31520,31582,31644,31706,31768,31830,31892,31955,
+    32017,32079,32141,32204,32266,32329,32391,32454,
+    32516,32579,32642,32705,32767,32830,32893,32956,
+    33019,33082,33145,33208,33272,33335,33398,33461,
+    33525,33588,33652,33715,33779,33843,33906,33970,
+    34034,34098,34162,34225,34289,34354,34418,34482,
+    34546,34610,34675,34739,34803,34868,34932,34997,
+    35062,35126,35191,35256,35321,35385,35450,35515,
+    35580,35646,35711,35776,35841,35907,35972,36037,
+    36103,36168,36234,36300,36365,36431,36497,36563,
+    36629,36695,36761,36827,36893,36959,37026,37092,
+    37158,37225,37291,37358,37425,37491,37558,37625,
+    37692,37759,37826,37893,37960,38027,38094,38161,
+    38229,38296,38364,38431,38499,38566,38634,38702,
+    38770,38837,38905,38973,39042,39110,39178,39246,
+    39314,39383,39451,39520,39588,39657,39726,39794,
+    39863,39932,40001,40070,40139,40208,40278,40347,
+    40416,40486,40555,40625,40694,40764,40834,40904,
+    40973,41043,41113,41184,41254,41324,41394,41465,
+    41535,41605,41676,41747,41817,41888,41959,42030,
+    42101,42172,42243,42314,42385,42457,42528,42600,
+    42671,42743,42814,42886,42958,43030,43102,43174,
+    43246,43318,43390,43463,43535,43608,43680,43753,
+    43826,43898,43971,44044,44117,44190,44263,44337,
+    44410,44483,44557,44630,44704,44778,44851,44925,
+    44999,45073,45147,45221,45296,45370,45444,45519,
+    45593,45668,45743,45818,45892,45967,46042,46118,
+    46193,46268,46343,46419,46494,46570,46646,46721,
+    46797,46873,46949,47025,47102,47178,47254,47331,
+    47407,47484,47560,47637,47714,47791,47868,47945,
+    48022,48100,48177,48255,48332,48410,48488,48565,
+    48643,48721,48799,48878,48956,49034,49113,49191,
+    49270,49349,49427,49506,49585,49664,49744,49823,
+    49902,49982,50061,50141,50221,50300,50380,50460,
+    50540,50621,50701,50781,50862,50942,51023,51104,
+    51185,51266,51347,51428,51509,51591,51672,51754,
+    51835,51917,51999,52081,52163,52245,52327,52410,
+    52492,52575,52657,52740,52823,52906,52989,53072,
+    53156,53239,53322,53406,53490,53574,53657,53741,
+    53826,53910,53994,54079,54163,54248,54333,54417,
+    54502,54587,54673,54758,54843,54929,55015,55100,
+    55186,55272,55358,55444,55531,55617,55704,55790,
+    55877,55964,56051,56138,56225,56312,56400,56487,
+    56575,56663,56751,56839,56927,57015,57104,57192,
+    57281,57369,57458,57547,57636,57725,57815,57904,
+    57994,58083,58173,58263,58353,58443,58534,58624,
+    58715,58805,58896,58987,59078,59169,59261,59352,
+    59444,59535,59627,59719,59811,59903,59996,60088,
+    60181,60273,60366,60459,60552,60646,60739,60833,
+    60926,61020,61114,61208,61302,61396,61491,61585,
+    61680,61775,61870,61965,62060,62156,62251,62347,
+    62443,62539,62635,62731,62828,62924,63021,63118,
+    63215,63312,63409,63506,63604,63702,63799,63897,
+    63996,64094,64192,64291,64389,64488,64587,64687,
+    64786,64885,64985,65085,65185,65285,65385,65485,
+    65586,65686,65787,65888,65989,66091,66192,66294,
+    66396,66498,66600,66702,66804,66907,67010,67113,
+    67216,67319,67422,67526,67629,67733,67837,67942,
+    68046,68151,68255,68360,68465,68570,68676,68781,
+    68887,68993,69099,69205,69312,69418,69525,69632,
+    69739,69846,69954,70061,70169,70277,70385,70494,
+    70602,70711,70820,70929,71038,71147,71257,71367,
+    71477,71587,71697,71808,71918,72029,72140,72252,
+    72363,72475,72587,72699,72811,72923,73036,73149,
+    73262,73375,73488,73602,73715,73829,73944,74058,
+    74172,74287,74402,74517,74633,74748,74864,74980,
+    75096,75213,75329,75446,75563,75680,75797,75915,
+    76033,76151,76269,76388,76506,76625,76744,76864,
+    76983,77103,77223,77343,77463,77584,77705,77826,
+    77947,78068,78190,78312,78434,78557,78679,78802,
+    78925,79048,79172,79296,79420,79544,79668,79793,
+    79918,80043,80168,80294,80420,80546,80672,80799,
+    80925,81053,81180,81307,81435,81563,81691,81820,
+    81949,82078,82207,82336,82466,82596,82726,82857,
+    82987,83118,83250,83381,83513,83645,83777,83910,
+    84043,84176,84309,84443,84576,84710,84845,84980,
+    85114,85250,85385,85521,85657,85793,85930,86066,
+    86204,86341,86479,86616,86755,86893,87032,87171,
+    87310,87450,87590,87730,87871,88011,88152,88294,
+    88435,88577,88720,88862,89005,89148,89292,89435,
+    89579,89724,89868,90013,90158,90304,90450,90596,
+    90742,90889,91036,91184,91332,91480,91628,91777,
+    91926,92075,92225,92375,92525,92675,92826,92978,
+    93129,93281,93434,93586,93739,93892,94046,94200,
+    94354,94509,94664,94819,94975,95131,95287,95444,
+    95601,95758,95916,96074,96233,96391,96551,96710,
+    96870,97030,97191,97352,97513,97675,97837,98000,
+    98163,98326,98489,98653,98818,98982,99148,99313,
+    99479,99645,99812,99979,100146,100314,100482,100651,
+    100820,100990,101159,101330,101500,101671,101843,102015,
+    102187,102360,102533,102706,102880,103054,103229,103404,
+    103580,103756,103933,104109,104287,104465,104643,104821,
+    105000,105180,105360,105540,105721,105902,106084,106266,
+    106449,106632,106816,107000,107184,107369,107555,107741,
+    107927,108114,108301,108489,108677,108866,109055,109245,
+    109435,109626,109817,110008,110200,110393,110586,110780,
+    110974,111169,111364,111560,111756,111952,112150,112347,
+    112546,112744,112944,113143,113344,113545,113746,113948,
+    114151,114354,114557,114761,114966,115171,115377,115583,
+    115790,115998,116206,116414,116623,116833,117044,117254,
+    117466,117678,117891,118104,118318,118532,118747,118963,
+    119179,119396,119613,119831,120050,120269,120489,120709,
+    120930,121152,121374,121597,121821,122045,122270,122496,
+    122722,122949,123176,123404,123633,123863,124093,124324,
+    124555,124787,125020,125254,125488,125723,125959,126195,
+    126432,126669,126908,127147,127387,127627,127869,128111,
+    128353,128597,128841,129086,129332,129578,129825,130073,
+    130322,130571,130821,131072,131324,131576,131830,132084,
+    132339,132594,132851,133108,133366,133625,133884,134145,
+    134406,134668,134931,135195,135459,135725,135991,136258,
+    136526,136795,137065,137335,137607,137879,138152,138426,
+    138701,138977,139254,139532,139810,140090,140370,140651,
+    140934,141217,141501,141786,142072,142359,142647,142936,
+    143226,143517,143808,144101,144395,144690,144986,145282,
+    145580,145879,146179,146480,146782,147084,147388,147693,
+    148000,148307,148615,148924,149235,149546,149859,150172,
+    150487,150803,151120,151438,151757,152077,152399,152722,
+    153045,153370,153697,154024,154352,154682,155013,155345,
+    155678,156013,156349,156686,157024,157363,157704,158046,
+    158389,158734,159079,159427,159775,160125,160476,160828,
+    161182,161537,161893,162251,162610,162970,163332,163695,
+    164060,164426,164793,165162,165532,165904,166277,166651,
+    167027,167405,167784,168164,168546,168930,169315,169701,
+    170089,170479,170870,171263,171657,172053,172451,172850,
+    173251,173653,174057,174463,174870,175279,175690,176102,
+    176516,176932,177349,177769,178190,178612,179037,179463,
+    179891,180321,180753,181186,181622,182059,182498,182939,
+    183382,183827,184274,184722,185173,185625,186080,186536,
+    186995,187455,187918,188382,188849,189318,189789,190261,
+    190736,191213,191693,192174,192658,193143,193631,194122,
+    194614,195109,195606,196105,196606,197110,197616,198125,
+    198636,199149,199664,200182,200703,201226,201751,202279,
+    202809,203342,203878,204416,204956,205500,206045,206594,
+    207145,207699,208255,208815,209376,209941,210509,211079,
+    211652,212228,212807,213389,213973,214561,215151,215745,
+    216341,216941,217544,218149,218758,219370,219985,220603,
+    221225,221849,222477,223108,223743,224381,225022,225666,
+    226314,226966,227621,228279,228941,229606,230275,230948,
+    231624,232304,232988,233676,234367,235062,235761,236463,
+    237170,237881,238595,239314,240036,240763,241493,242228,
+    242967,243711,244458,245210,245966,246727,247492,248261,
+    249035,249813,250596,251384,252176,252973,253774,254581,
+    255392,256208,257029,257855,258686,259522,260363,261209,
+    262060,262917,263779,264646,265519,266397,267280,268169,
+    269064,269965,270871,271782,272700,273624,274553,275489,
+    276430,277378,278332,279292,280258,281231,282210,283195,
+    284188,285186,286192,287204,288223,289249,290282,291322,
+    292369,293423,294485,295554,296630,297714,298805,299904,
+    301011,302126,303248,304379,305517,306664,307819,308983,
+    310154,311335,312524,313721,314928,316143,317368,318601,
+    319844,321097,322358,323629,324910,326201,327502,328812,
+    330133,331464,332805,334157,335519,336892,338276,339671,
+    341078,342495,343924,345364,346816,348280,349756,351244,
+    352744,354257,355783,357321,358872,360436,362013,363604,
+    365208,366826,368459,370105,371765,373440,375130,376835,
+    378555,380290,382040,383807,385589,387387,389202,391034,
+    392882,394747,396630,398530,400448,402384,404338,406311,
+    408303,410314,412344,414395,416465,418555,420666,422798,
+    424951,427125,429321,431540,433781,436045,438332,440643,
+    442978,445337,447720,450129,452564,455024,457511,460024,
+    462565,465133,467730,470355,473009,475692,478406,481150,
+    483925,486732,489571,492443,495348,498287,501261,504269,
+    507313,510394,513512,516667,519861,523094,526366,529680,
+    533034,536431,539870,543354,546881,550455,554074,557741,
+    561456,565221,569035,572901,576818,580789,584815,588896,
+    593033,597229,601483,605798,610174,614613,619117,623686,
+    628323,633028,637803,642651,647572,652568,657640,662792,
+    668024,673338,678737,684223,689797,695462,701219,707072,
+    713023,719074,725227,731486,737853,744331,750922,757631,
+    764460,771411,778490,785699,793041,800521,808143,815910,
+    823827,831898,840127,848520,857081,865817,874730,883829,
+    893117,902602,912289,922186,932298,942633,953199,964003,
+    975054,986361,997931,1009774,1021901,1034322,1047046,1060087,
+    1073455,1087164,1101225,1115654,1130465,1145673,1161294,1177345,
+    1193846,1210813,1228269,1246234,1264730,1283783,1303416,1323658,
+    1344537,1366084,1388330,1411312,1435065,1459630,1485049,1511367,
+    1538632,1566898,1596220,1626658,1658278,1691149,1725348,1760956,
+    1798063,1836758,1877161,1919378,1963536,2009771,2058233,2109087,
+    2162516,2218719,2277919,2340362,2406322,2476104,2550052,2628549,
+    2712030,2800983,2895966,2997613,3106651,3223918,3350381,3487165,
+    3635590,3797206,3973855,4167737,4381502,4618375,4882318,5178251,
+    5512368,5892567,6329090,6835455,7429880,8137527,8994149,10052327,
+    11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304
+};
+
+
+const int finesine[10240] =
+{
+    25,75,125,175,226,276,326,376,
+    427,477,527,578,628,678,728,779,
+    829,879,929,980,1030,1080,1130,1181,
+    1231,1281,1331,1382,1432,1482,1532,1583,
+    1633,1683,1733,1784,1834,1884,1934,1985,
+    2035,2085,2135,2186,2236,2286,2336,2387,
+    2437,2487,2537,2587,2638,2688,2738,2788,
+    2839,2889,2939,2989,3039,3090,3140,3190,
+    3240,3291,3341,3391,3441,3491,3541,3592,
+    3642,3692,3742,3792,3843,3893,3943,3993,
+    4043,4093,4144,4194,4244,4294,4344,4394,
+    4445,4495,4545,4595,4645,4695,4745,4796,
+    4846,4896,4946,4996,5046,5096,5146,5197,
+    5247,5297,5347,5397,5447,5497,5547,5597,
+    5647,5697,5748,5798,5848,5898,5948,5998,
+    6048,6098,6148,6198,6248,6298,6348,6398,
+    6448,6498,6548,6598,6648,6698,6748,6798,
+    6848,6898,6948,6998,7048,7098,7148,7198,
+    7248,7298,7348,7398,7448,7498,7548,7598,
+    7648,7697,7747,7797,7847,7897,7947,7997,
+    8047,8097,8147,8196,8246,8296,8346,8396,
+    8446,8496,8545,8595,8645,8695,8745,8794,
+    8844,8894,8944,8994,9043,9093,9143,9193,
+    9243,9292,9342,9392,9442,9491,9541,9591,
+    9640,9690,9740,9790,9839,9889,9939,9988,
+    10038,10088,10137,10187,10237,10286,10336,10386,
+    10435,10485,10534,10584,10634,10683,10733,10782,
+    10832,10882,10931,10981,11030,11080,11129,11179,
+    11228,11278,11327,11377,11426,11476,11525,11575,
+    11624,11674,11723,11773,11822,11872,11921,11970,
+    12020,12069,12119,12168,12218,12267,12316,12366,
+    12415,12464,12514,12563,12612,12662,12711,12760,
+    12810,12859,12908,12957,13007,13056,13105,13154,
+    13204,13253,13302,13351,13401,13450,13499,13548,
+    13597,13647,13696,13745,13794,13843,13892,13941,
+    13990,14040,14089,14138,14187,14236,14285,14334,
+    14383,14432,14481,14530,14579,14628,14677,14726,
+    14775,14824,14873,14922,14971,15020,15069,15118,
+    15167,15215,15264,15313,15362,15411,15460,15509,
+    15557,15606,15655,15704,15753,15802,15850,15899,
+    15948,15997,16045,16094,16143,16191,16240,16289,
+    16338,16386,16435,16484,16532,16581,16629,16678,
+    16727,16775,16824,16872,16921,16970,17018,17067,
+    17115,17164,17212,17261,17309,17358,17406,17455,
+    17503,17551,17600,17648,17697,17745,17793,17842,
+    17890,17939,17987,18035,18084,18132,18180,18228,
+    18277,18325,18373,18421,18470,18518,18566,18614,
+    18663,18711,18759,18807,18855,18903,18951,19000,
+    19048,19096,19144,19192,19240,19288,19336,19384,
+    19432,19480,19528,19576,19624,19672,19720,19768,
+    19816,19864,19912,19959,20007,20055,20103,20151,
+    20199,20246,20294,20342,20390,20438,20485,20533,
+    20581,20629,20676,20724,20772,20819,20867,20915,
+    20962,21010,21057,21105,21153,21200,21248,21295,
+    21343,21390,21438,21485,21533,21580,21628,21675,
+    21723,21770,21817,21865,21912,21960,22007,22054,
+    22102,22149,22196,22243,22291,22338,22385,22433,
+    22480,22527,22574,22621,22668,22716,22763,22810,
+    22857,22904,22951,22998,23045,23092,23139,23186,
+    23233,23280,23327,23374,23421,23468,23515,23562,
+    23609,23656,23703,23750,23796,23843,23890,23937,
+    23984,24030,24077,24124,24171,24217,24264,24311,
+    24357,24404,24451,24497,24544,24591,24637,24684,
+    24730,24777,24823,24870,24916,24963,25009,25056,
+    25102,25149,25195,25241,25288,25334,25381,25427,
+    25473,25520,25566,25612,25658,25705,25751,25797,
+    25843,25889,25936,25982,26028,26074,26120,26166,
+    26212,26258,26304,26350,26396,26442,26488,26534,
+    26580,26626,26672,26718,26764,26810,26856,26902,
+    26947,26993,27039,27085,27131,27176,27222,27268,
+    27313,27359,27405,27450,27496,27542,27587,27633,
+    27678,27724,27770,27815,27861,27906,27952,27997,
+    28042,28088,28133,28179,28224,28269,28315,28360,
+    28405,28451,28496,28541,28586,28632,28677,28722,
+    28767,28812,28858,28903,28948,28993,29038,29083,
+    29128,29173,29218,29263,29308,29353,29398,29443,
+    29488,29533,29577,29622,29667,29712,29757,29801,
+    29846,29891,29936,29980,30025,30070,30114,30159,
+    30204,30248,30293,30337,30382,30426,30471,30515,
+    30560,30604,30649,30693,30738,30782,30826,30871,
+    30915,30959,31004,31048,31092,31136,31181,31225,
+    31269,31313,31357,31402,31446,31490,31534,31578,
+    31622,31666,31710,31754,31798,31842,31886,31930,
+    31974,32017,32061,32105,32149,32193,32236,32280,
+    32324,32368,32411,32455,32499,32542,32586,32630,
+    32673,32717,32760,32804,32847,32891,32934,32978,
+    33021,33065,33108,33151,33195,33238,33281,33325,
+    33368,33411,33454,33498,33541,33584,33627,33670,
+    33713,33756,33799,33843,33886,33929,33972,34015,
+    34057,34100,34143,34186,34229,34272,34315,34358,
+    34400,34443,34486,34529,34571,34614,34657,34699,
+    34742,34785,34827,34870,34912,34955,34997,35040,
+    35082,35125,35167,35210,35252,35294,35337,35379,
+    35421,35464,35506,35548,35590,35633,35675,35717,
+    35759,35801,35843,35885,35927,35969,36011,36053,
+    36095,36137,36179,36221,36263,36305,36347,36388,
+    36430,36472,36514,36555,36597,36639,36681,36722,
+    36764,36805,36847,36889,36930,36972,37013,37055,
+    37096,37137,37179,37220,37262,37303,37344,37386,
+    37427,37468,37509,37551,37592,37633,37674,37715,
+    37756,37797,37838,37879,37920,37961,38002,38043,
+    38084,38125,38166,38207,38248,38288,38329,38370,
+    38411,38451,38492,38533,38573,38614,38655,38695,
+    38736,38776,38817,38857,38898,38938,38979,39019,
+    39059,39100,39140,39180,39221,39261,39301,39341,
+    39382,39422,39462,39502,39542,39582,39622,39662,
+    39702,39742,39782,39822,39862,39902,39942,39982,
+    40021,40061,40101,40141,40180,40220,40260,40300,
+    40339,40379,40418,40458,40497,40537,40576,40616,
+    40655,40695,40734,40773,40813,40852,40891,40931,
+    40970,41009,41048,41087,41127,41166,41205,41244,
+    41283,41322,41361,41400,41439,41478,41517,41556,
+    41595,41633,41672,41711,41750,41788,41827,41866,
+    41904,41943,41982,42020,42059,42097,42136,42174,
+    42213,42251,42290,42328,42366,42405,42443,42481,
+    42520,42558,42596,42634,42672,42711,42749,42787,
+    42825,42863,42901,42939,42977,43015,43053,43091,
+    43128,43166,43204,43242,43280,43317,43355,43393,
+    43430,43468,43506,43543,43581,43618,43656,43693,
+    43731,43768,43806,43843,43880,43918,43955,43992,
+    44029,44067,44104,44141,44178,44215,44252,44289,
+    44326,44363,44400,44437,44474,44511,44548,44585,
+    44622,44659,44695,44732,44769,44806,44842,44879,
+    44915,44952,44989,45025,45062,45098,45135,45171,
+    45207,45244,45280,45316,45353,45389,45425,45462,
+    45498,45534,45570,45606,45642,45678,45714,45750,
+    45786,45822,45858,45894,45930,45966,46002,46037,
+    46073,46109,46145,46180,46216,46252,46287,46323,
+    46358,46394,46429,46465,46500,46536,46571,46606,
+    46642,46677,46712,46747,46783,46818,46853,46888,
+    46923,46958,46993,47028,47063,47098,47133,47168,
+    47203,47238,47273,47308,47342,47377,47412,47446,
+    47481,47516,47550,47585,47619,47654,47688,47723,
+    47757,47792,47826,47860,47895,47929,47963,47998,
+    48032,48066,48100,48134,48168,48202,48237,48271,
+    48305,48338,48372,48406,48440,48474,48508,48542,
+    48575,48609,48643,48676,48710,48744,48777,48811,
+    48844,48878,48911,48945,48978,49012,49045,49078,
+    49112,49145,49178,49211,49244,49278,49311,49344,
+    49377,49410,49443,49476,49509,49542,49575,49608,
+    49640,49673,49706,49739,49771,49804,49837,49869,
+    49902,49935,49967,50000,50032,50065,50097,50129,
+    50162,50194,50226,50259,50291,50323,50355,50387,
+    50420,50452,50484,50516,50548,50580,50612,50644,
+    50675,50707,50739,50771,50803,50834,50866,50898,
+    50929,50961,50993,51024,51056,51087,51119,51150,
+    51182,51213,51244,51276,51307,51338,51369,51401,
+    51432,51463,51494,51525,51556,51587,51618,51649,
+    51680,51711,51742,51773,51803,51834,51865,51896,
+    51926,51957,51988,52018,52049,52079,52110,52140,
+    52171,52201,52231,52262,52292,52322,52353,52383,
+    52413,52443,52473,52503,52534,52564,52594,52624,
+    52653,52683,52713,52743,52773,52803,52832,52862,
+    52892,52922,52951,52981,53010,53040,53069,53099,
+    53128,53158,53187,53216,53246,53275,53304,53334,
+    53363,53392,53421,53450,53479,53508,53537,53566,
+    53595,53624,53653,53682,53711,53739,53768,53797,
+    53826,53854,53883,53911,53940,53969,53997,54026,
+    54054,54082,54111,54139,54167,54196,54224,54252,
+    54280,54308,54337,54365,54393,54421,54449,54477,
+    54505,54533,54560,54588,54616,54644,54672,54699,
+    54727,54755,54782,54810,54837,54865,54892,54920,
+    54947,54974,55002,55029,55056,55084,55111,55138,
+    55165,55192,55219,55246,55274,55300,55327,55354,
+    55381,55408,55435,55462,55489,55515,55542,55569,
+    55595,55622,55648,55675,55701,55728,55754,55781,
+    55807,55833,55860,55886,55912,55938,55965,55991,
+    56017,56043,56069,56095,56121,56147,56173,56199,
+    56225,56250,56276,56302,56328,56353,56379,56404,
+    56430,56456,56481,56507,56532,56557,56583,56608,
+    56633,56659,56684,56709,56734,56760,56785,56810,
+    56835,56860,56885,56910,56935,56959,56984,57009,
+    57034,57059,57083,57108,57133,57157,57182,57206,
+    57231,57255,57280,57304,57329,57353,57377,57402,
+    57426,57450,57474,57498,57522,57546,57570,57594,
+    57618,57642,57666,57690,57714,57738,57762,57785,
+    57809,57833,57856,57880,57903,57927,57950,57974,
+    57997,58021,58044,58067,58091,58114,58137,58160,
+    58183,58207,58230,58253,58276,58299,58322,58345,
+    58367,58390,58413,58436,58459,58481,58504,58527,
+    58549,58572,58594,58617,58639,58662,58684,58706,
+    58729,58751,58773,58795,58818,58840,58862,58884,
+    58906,58928,58950,58972,58994,59016,59038,59059,
+    59081,59103,59125,59146,59168,59190,59211,59233,
+    59254,59276,59297,59318,59340,59361,59382,59404,
+    59425,59446,59467,59488,59509,59530,59551,59572,
+    59593,59614,59635,59656,59677,59697,59718,59739,
+    59759,59780,59801,59821,59842,59862,59883,59903,
+    59923,59944,59964,59984,60004,60025,60045,60065,
+    60085,60105,60125,60145,60165,60185,60205,60225,
+    60244,60264,60284,60304,60323,60343,60363,60382,
+    60402,60421,60441,60460,60479,60499,60518,60537,
+    60556,60576,60595,60614,60633,60652,60671,60690,
+    60709,60728,60747,60766,60785,60803,60822,60841,
+    60859,60878,60897,60915,60934,60952,60971,60989,
+    61007,61026,61044,61062,61081,61099,61117,61135,
+    61153,61171,61189,61207,61225,61243,61261,61279,
+    61297,61314,61332,61350,61367,61385,61403,61420,
+    61438,61455,61473,61490,61507,61525,61542,61559,
+    61577,61594,61611,61628,61645,61662,61679,61696,
+    61713,61730,61747,61764,61780,61797,61814,61831,
+    61847,61864,61880,61897,61913,61930,61946,61963,
+    61979,61995,62012,62028,62044,62060,62076,62092,
+    62108,62125,62141,62156,62172,62188,62204,62220,
+    62236,62251,62267,62283,62298,62314,62329,62345,
+    62360,62376,62391,62407,62422,62437,62453,62468,
+    62483,62498,62513,62528,62543,62558,62573,62588,
+    62603,62618,62633,62648,62662,62677,62692,62706,
+    62721,62735,62750,62764,62779,62793,62808,62822,
+    62836,62850,62865,62879,62893,62907,62921,62935,
+    62949,62963,62977,62991,63005,63019,63032,63046,
+    63060,63074,63087,63101,63114,63128,63141,63155,
+    63168,63182,63195,63208,63221,63235,63248,63261,
+    63274,63287,63300,63313,63326,63339,63352,63365,
+    63378,63390,63403,63416,63429,63441,63454,63466,
+    63479,63491,63504,63516,63528,63541,63553,63565,
+    63578,63590,63602,63614,63626,63638,63650,63662,
+    63674,63686,63698,63709,63721,63733,63745,63756,
+    63768,63779,63791,63803,63814,63825,63837,63848,
+    63859,63871,63882,63893,63904,63915,63927,63938,
+    63949,63960,63971,63981,63992,64003,64014,64025,
+    64035,64046,64057,64067,64078,64088,64099,64109,
+    64120,64130,64140,64151,64161,64171,64181,64192,
+    64202,64212,64222,64232,64242,64252,64261,64271,
+    64281,64291,64301,64310,64320,64330,64339,64349,
+    64358,64368,64377,64387,64396,64405,64414,64424,
+    64433,64442,64451,64460,64469,64478,64487,64496,
+    64505,64514,64523,64532,64540,64549,64558,64566,
+    64575,64584,64592,64601,64609,64617,64626,64634,
+    64642,64651,64659,64667,64675,64683,64691,64699,
+    64707,64715,64723,64731,64739,64747,64754,64762,
+    64770,64777,64785,64793,64800,64808,64815,64822,
+    64830,64837,64844,64852,64859,64866,64873,64880,
+    64887,64895,64902,64908,64915,64922,64929,64936,
+    64943,64949,64956,64963,64969,64976,64982,64989,
+    64995,65002,65008,65015,65021,65027,65033,65040,
+    65046,65052,65058,65064,65070,65076,65082,65088,
+    65094,65099,65105,65111,65117,65122,65128,65133,
+    65139,65144,65150,65155,65161,65166,65171,65177,
+    65182,65187,65192,65197,65202,65207,65212,65217,
+    65222,65227,65232,65237,65242,65246,65251,65256,
+    65260,65265,65270,65274,65279,65283,65287,65292,
+    65296,65300,65305,65309,65313,65317,65321,65325,
+    65329,65333,65337,65341,65345,65349,65352,65356,
+    65360,65363,65367,65371,65374,65378,65381,65385,
+    65388,65391,65395,65398,65401,65404,65408,65411,
+    65414,65417,65420,65423,65426,65429,65431,65434,
+    65437,65440,65442,65445,65448,65450,65453,65455,
+    65458,65460,65463,65465,65467,65470,65472,65474,
+    65476,65478,65480,65482,65484,65486,65488,65490,
+    65492,65494,65496,65497,65499,65501,65502,65504,
+    65505,65507,65508,65510,65511,65513,65514,65515,
+    65516,65518,65519,65520,65521,65522,65523,65524,
+    65525,65526,65527,65527,65528,65529,65530,65530,
+    65531,65531,65532,65532,65533,65533,65534,65534,
+    65534,65535,65535,65535,65535,65535,65535,65535,
+    65535,65535,65535,65535,65535,65535,65535,65534,
+    65534,65534,65533,65533,65532,65532,65531,65531,
+    65530,65530,65529,65528,65527,65527,65526,65525,
+    65524,65523,65522,65521,65520,65519,65518,65516,
+    65515,65514,65513,65511,65510,65508,65507,65505,
+    65504,65502,65501,65499,65497,65496,65494,65492,
+    65490,65488,65486,65484,65482,65480,65478,65476,
+    65474,65472,65470,65467,65465,65463,65460,65458,
+    65455,65453,65450,65448,65445,65442,65440,65437,
+    65434,65431,65429,65426,65423,65420,65417,65414,
+    65411,65408,65404,65401,65398,65395,65391,65388,
+    65385,65381,65378,65374,65371,65367,65363,65360,
+    65356,65352,65349,65345,65341,65337,65333,65329,
+    65325,65321,65317,65313,65309,65305,65300,65296,
+    65292,65287,65283,65279,65274,65270,65265,65260,
+    65256,65251,65246,65242,65237,65232,65227,65222,
+    65217,65212,65207,65202,65197,65192,65187,65182,
+    65177,65171,65166,65161,65155,65150,65144,65139,
+    65133,65128,65122,65117,65111,65105,65099,65094,
+    65088,65082,65076,65070,65064,65058,65052,65046,
+    65040,65033,65027,65021,65015,65008,65002,64995,
+    64989,64982,64976,64969,64963,64956,64949,64943,
+    64936,64929,64922,64915,64908,64902,64895,64887,
+    64880,64873,64866,64859,64852,64844,64837,64830,
+    64822,64815,64808,64800,64793,64785,64777,64770,
+    64762,64754,64747,64739,64731,64723,64715,64707,
+    64699,64691,64683,64675,64667,64659,64651,64642,
+    64634,64626,64617,64609,64600,64592,64584,64575,
+    64566,64558,64549,64540,64532,64523,64514,64505,
+    64496,64487,64478,64469,64460,64451,64442,64433,
+    64424,64414,64405,64396,64387,64377,64368,64358,
+    64349,64339,64330,64320,64310,64301,64291,64281,
+    64271,64261,64252,64242,64232,64222,64212,64202,
+    64192,64181,64171,64161,64151,64140,64130,64120,
+    64109,64099,64088,64078,64067,64057,64046,64035,
+    64025,64014,64003,63992,63981,63971,63960,63949,
+    63938,63927,63915,63904,63893,63882,63871,63859,
+    63848,63837,63825,63814,63803,63791,63779,63768,
+    63756,63745,63733,63721,63709,63698,63686,63674,
+    63662,63650,63638,63626,63614,63602,63590,63578,
+    63565,63553,63541,63528,63516,63504,63491,63479,
+    63466,63454,63441,63429,63416,63403,63390,63378,
+    63365,63352,63339,63326,63313,63300,63287,63274,
+    63261,63248,63235,63221,63208,63195,63182,63168,
+    63155,63141,63128,63114,63101,63087,63074,63060,
+    63046,63032,63019,63005,62991,62977,62963,62949,
+    62935,62921,62907,62893,62879,62865,62850,62836,
+    62822,62808,62793,62779,62764,62750,62735,62721,
+    62706,62692,62677,62662,62648,62633,62618,62603,
+    62588,62573,62558,62543,62528,62513,62498,62483,
+    62468,62453,62437,62422,62407,62391,62376,62360,
+    62345,62329,62314,62298,62283,62267,62251,62236,
+    62220,62204,62188,62172,62156,62141,62125,62108,
+    62092,62076,62060,62044,62028,62012,61995,61979,
+    61963,61946,61930,61913,61897,61880,61864,61847,
+    61831,61814,61797,61780,61764,61747,61730,61713,
+    61696,61679,61662,61645,61628,61611,61594,61577,
+    61559,61542,61525,61507,61490,61473,61455,61438,
+    61420,61403,61385,61367,61350,61332,61314,61297,
+    61279,61261,61243,61225,61207,61189,61171,61153,
+    61135,61117,61099,61081,61062,61044,61026,61007,
+    60989,60971,60952,60934,60915,60897,60878,60859,
+    60841,60822,60803,60785,60766,60747,60728,60709,
+    60690,60671,60652,60633,60614,60595,60576,60556,
+    60537,60518,60499,60479,60460,60441,60421,60402,
+    60382,60363,60343,60323,60304,60284,60264,60244,
+    60225,60205,60185,60165,60145,60125,60105,60085,
+    60065,60045,60025,60004,59984,59964,59944,59923,
+    59903,59883,59862,59842,59821,59801,59780,59759,
+    59739,59718,59697,59677,59656,59635,59614,59593,
+    59572,59551,59530,59509,59488,59467,59446,59425,
+    59404,59382,59361,59340,59318,59297,59276,59254,
+    59233,59211,59190,59168,59146,59125,59103,59081,
+    59059,59038,59016,58994,58972,58950,58928,58906,
+    58884,58862,58840,58818,58795,58773,58751,58729,
+    58706,58684,58662,58639,58617,58594,58572,58549,
+    58527,58504,58481,58459,58436,58413,58390,58367,
+    58345,58322,58299,58276,58253,58230,58207,58183,
+    58160,58137,58114,58091,58067,58044,58021,57997,
+    57974,57950,57927,57903,57880,57856,57833,57809,
+    57785,57762,57738,57714,57690,57666,57642,57618,
+    57594,57570,57546,57522,57498,57474,57450,57426,
+    57402,57377,57353,57329,57304,57280,57255,57231,
+    57206,57182,57157,57133,57108,57083,57059,57034,
+    57009,56984,56959,56935,56910,56885,56860,56835,
+    56810,56785,56760,56734,56709,56684,56659,56633,
+    56608,56583,56557,56532,56507,56481,56456,56430,
+    56404,56379,56353,56328,56302,56276,56250,56225,
+    56199,56173,56147,56121,56095,56069,56043,56017,
+    55991,55965,55938,55912,55886,55860,55833,55807,
+    55781,55754,55728,55701,55675,55648,55622,55595,
+    55569,55542,55515,55489,55462,55435,55408,55381,
+    55354,55327,55300,55274,55246,55219,55192,55165,
+    55138,55111,55084,55056,55029,55002,54974,54947,
+    54920,54892,54865,54837,54810,54782,54755,54727,
+    54699,54672,54644,54616,54588,54560,54533,54505,
+    54477,54449,54421,54393,54365,54337,54308,54280,
+    54252,54224,54196,54167,54139,54111,54082,54054,
+    54026,53997,53969,53940,53911,53883,53854,53826,
+    53797,53768,53739,53711,53682,53653,53624,53595,
+    53566,53537,53508,53479,53450,53421,53392,53363,
+    53334,53304,53275,53246,53216,53187,53158,53128,
+    53099,53069,53040,53010,52981,52951,52922,52892,
+    52862,52832,52803,52773,52743,52713,52683,52653,
+    52624,52594,52564,52534,52503,52473,52443,52413,
+    52383,52353,52322,52292,52262,52231,52201,52171,
+    52140,52110,52079,52049,52018,51988,51957,51926,
+    51896,51865,51834,51803,51773,51742,51711,51680,
+    51649,51618,51587,51556,51525,51494,51463,51432,
+    51401,51369,51338,51307,51276,51244,51213,51182,
+    51150,51119,51087,51056,51024,50993,50961,50929,
+    50898,50866,50834,50803,50771,50739,50707,50675,
+    50644,50612,50580,50548,50516,50484,50452,50420,
+    50387,50355,50323,50291,50259,50226,50194,50162,
+    50129,50097,50065,50032,50000,49967,49935,49902,
+    49869,49837,49804,49771,49739,49706,49673,49640,
+    49608,49575,49542,49509,49476,49443,49410,49377,
+    49344,49311,49278,49244,49211,49178,49145,49112,
+    49078,49045,49012,48978,48945,48911,48878,48844,
+    48811,48777,48744,48710,48676,48643,48609,48575,
+    48542,48508,48474,48440,48406,48372,48338,48304,
+    48271,48237,48202,48168,48134,48100,48066,48032,
+    47998,47963,47929,47895,47860,47826,47792,47757,
+    47723,47688,47654,47619,47585,47550,47516,47481,
+    47446,47412,47377,47342,47308,47273,47238,47203,
+    47168,47133,47098,47063,47028,46993,46958,46923,
+    46888,46853,46818,46783,46747,46712,46677,46642,
+    46606,46571,46536,46500,46465,46429,46394,46358,
+    46323,46287,46252,46216,46180,46145,46109,46073,
+    46037,46002,45966,45930,45894,45858,45822,45786,
+    45750,45714,45678,45642,45606,45570,45534,45498,
+    45462,45425,45389,45353,45316,45280,45244,45207,
+    45171,45135,45098,45062,45025,44989,44952,44915,
+    44879,44842,44806,44769,44732,44695,44659,44622,
+    44585,44548,44511,44474,44437,44400,44363,44326,
+    44289,44252,44215,44178,44141,44104,44067,44029,
+    43992,43955,43918,43880,43843,43806,43768,43731,
+    43693,43656,43618,43581,43543,43506,43468,43430,
+    43393,43355,43317,43280,43242,43204,43166,43128,
+    43091,43053,43015,42977,42939,42901,42863,42825,
+    42787,42749,42711,42672,42634,42596,42558,42520,
+    42481,42443,42405,42366,42328,42290,42251,42213,
+    42174,42136,42097,42059,42020,41982,41943,41904,
+    41866,41827,41788,41750,41711,41672,41633,41595,
+    41556,41517,41478,41439,41400,41361,41322,41283,
+    41244,41205,41166,41127,41088,41048,41009,40970,
+    40931,40891,40852,40813,40773,40734,40695,40655,
+    40616,40576,40537,40497,40458,40418,40379,40339,
+    40300,40260,40220,40180,40141,40101,40061,40021,
+    39982,39942,39902,39862,39822,39782,39742,39702,
+    39662,39622,39582,39542,39502,39462,39422,39382,
+    39341,39301,39261,39221,39180,39140,39100,39059,
+    39019,38979,38938,38898,38857,38817,38776,38736,
+    38695,38655,38614,38573,38533,38492,38451,38411,
+    38370,38329,38288,38248,38207,38166,38125,38084,
+    38043,38002,37961,37920,37879,37838,37797,37756,
+    37715,37674,37633,37592,37551,37509,37468,37427,
+    37386,37344,37303,37262,37220,37179,37137,37096,
+    37055,37013,36972,36930,36889,36847,36805,36764,
+    36722,36681,36639,36597,36556,36514,36472,36430,
+    36388,36347,36305,36263,36221,36179,36137,36095,
+    36053,36011,35969,35927,35885,35843,35801,35759,
+    35717,35675,35633,35590,35548,35506,35464,35421,
+    35379,35337,35294,35252,35210,35167,35125,35082,
+    35040,34997,34955,34912,34870,34827,34785,34742,
+    34699,34657,34614,34571,34529,34486,34443,34400,
+    34358,34315,34272,34229,34186,34143,34100,34057,
+    34015,33972,33929,33886,33843,33799,33756,33713,
+    33670,33627,33584,33541,33498,33454,33411,33368,
+    33325,33281,33238,33195,33151,33108,33065,33021,
+    32978,32934,32891,32847,32804,32760,32717,32673,
+    32630,32586,32542,32499,32455,32411,32368,32324,
+    32280,32236,32193,32149,32105,32061,32017,31974,
+    31930,31886,31842,31798,31754,31710,31666,31622,
+    31578,31534,31490,31446,31402,31357,31313,31269,
+    31225,31181,31136,31092,31048,31004,30959,30915,
+    30871,30826,30782,30738,30693,30649,30604,30560,
+    30515,30471,30426,30382,30337,30293,30248,30204,
+    30159,30114,30070,30025,29980,29936,29891,29846,
+    29801,29757,29712,29667,29622,29577,29533,29488,
+    29443,29398,29353,29308,29263,29218,29173,29128,
+    29083,29038,28993,28948,28903,28858,28812,28767,
+    28722,28677,28632,28586,28541,28496,28451,28405,
+    28360,28315,28269,28224,28179,28133,28088,28042,
+    27997,27952,27906,27861,27815,27770,27724,27678,
+    27633,27587,27542,27496,27450,27405,27359,27313,
+    27268,27222,27176,27131,27085,27039,26993,26947,
+    26902,26856,26810,26764,26718,26672,26626,26580,
+    26534,26488,26442,26396,26350,26304,26258,26212,
+    26166,26120,26074,26028,25982,25936,25889,25843,
+    25797,25751,25705,25658,25612,25566,25520,25473,
+    25427,25381,25334,25288,25241,25195,25149,25102,
+    25056,25009,24963,24916,24870,24823,24777,24730,
+    24684,24637,24591,24544,24497,24451,24404,24357,
+    24311,24264,24217,24171,24124,24077,24030,23984,
+    23937,23890,23843,23796,23750,23703,23656,23609,
+    23562,23515,23468,23421,23374,23327,23280,23233,
+    23186,23139,23092,23045,22998,22951,22904,22857,
+    22810,22763,22716,22668,22621,22574,22527,22480,
+    22433,22385,22338,22291,22243,22196,22149,22102,
+    22054,22007,21960,21912,21865,21817,21770,21723,
+    21675,21628,21580,21533,21485,21438,21390,21343,
+    21295,21248,21200,21153,21105,21057,21010,20962,
+    20915,20867,20819,20772,20724,20676,20629,20581,
+    20533,20485,20438,20390,20342,20294,20246,20199,
+    20151,20103,20055,20007,19959,19912,19864,19816,
+    19768,19720,19672,19624,19576,19528,19480,19432,
+    19384,19336,19288,19240,19192,19144,19096,19048,
+    19000,18951,18903,18855,18807,18759,18711,18663,
+    18614,18566,18518,18470,18421,18373,18325,18277,
+    18228,18180,18132,18084,18035,17987,17939,17890,
+    17842,17793,17745,17697,17648,17600,17551,17503,
+    17455,17406,17358,17309,17261,17212,17164,17115,
+    17067,17018,16970,16921,16872,16824,16775,16727,
+    16678,16629,16581,16532,16484,16435,16386,16338,
+    16289,16240,16191,16143,16094,16045,15997,15948,
+    15899,15850,15802,15753,15704,15655,15606,15557,
+    15509,15460,15411,15362,15313,15264,15215,15167,
+    15118,15069,15020,14971,14922,14873,14824,14775,
+    14726,14677,14628,14579,14530,14481,14432,14383,
+    14334,14285,14236,14187,14138,14089,14040,13990,
+    13941,13892,13843,13794,13745,13696,13646,13597,
+    13548,13499,13450,13401,13351,13302,13253,13204,
+    13154,13105,13056,13007,12957,12908,12859,12810,
+    12760,12711,12662,12612,12563,12514,12464,12415,
+    12366,12316,12267,12218,12168,12119,12069,12020,
+    11970,11921,11872,11822,11773,11723,11674,11624,
+    11575,11525,11476,11426,11377,11327,11278,11228,
+    11179,11129,11080,11030,10981,10931,10882,10832,
+    10782,10733,10683,10634,10584,10534,10485,10435,
+    10386,10336,10286,10237,10187,10137,10088,10038,
+    9988,9939,9889,9839,9790,9740,9690,9640,
+    9591,9541,9491,9442,9392,9342,9292,9243,
+    9193,9143,9093,9043,8994,8944,8894,8844,
+    8794,8745,8695,8645,8595,8545,8496,8446,
+    8396,8346,8296,8246,8196,8147,8097,8047,
+    7997,7947,7897,7847,7797,7747,7697,7648,
+    7598,7548,7498,7448,7398,7348,7298,7248,
+    7198,7148,7098,7048,6998,6948,6898,6848,
+    6798,6748,6698,6648,6598,6548,6498,6448,
+    6398,6348,6298,6248,6198,6148,6098,6048,
+    5998,5948,5898,5848,5798,5748,5697,5647,
+    5597,5547,5497,5447,5397,5347,5297,5247,
+    5197,5146,5096,5046,4996,4946,4896,4846,
+    4796,4745,4695,4645,4595,4545,4495,4445,
+    4394,4344,4294,4244,4194,4144,4093,4043,
+    3993,3943,3893,3843,3792,3742,3692,3642,
+    3592,3541,3491,3441,3391,3341,3291,3240,
+    3190,3140,3090,3039,2989,2939,2889,2839,
+    2788,2738,2688,2638,2587,2537,2487,2437,
+    2387,2336,2286,2236,2186,2135,2085,2035,
+    1985,1934,1884,1834,1784,1733,1683,1633,
+    1583,1532,1482,1432,1382,1331,1281,1231,
+    1181,1130,1080,1030,980,929,879,829,
+    779,728,678,628,578,527,477,427,
+    376,326,276,226,175,125,75,25,
+    -25,-75,-125,-175,-226,-276,-326,-376,
+    -427,-477,-527,-578,-628,-678,-728,-779,
+    -829,-879,-929,-980,-1030,-1080,-1130,-1181,
+    -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583,
+    -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985,
+    -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387,
+    -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788,
+    -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190,
+    -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592,
+    -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993,
+    -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394,
+    -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796,
+    -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197,
+    -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597,
+    -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998,
+    -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398,
+    -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798,
+    -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198,
+    -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598,
+    -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997,
+    -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396,
+    -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794,
+    -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193,
+    -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591,
+    -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988,
+    -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386,
+    -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782,
+    -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179,
+    -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575,
+    -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970,
+    -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366,
+    -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760,
+    -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154,
+    -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548,
+    -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941,
+    -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334,
+    -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726,
+    -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118,
+    -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509,
+    -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899,
+    -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289,
+    -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678,
+    -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067,
+    -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455,
+    -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842,
+    -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228,
+    -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614,
+    -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000,
+    -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384,
+    -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768,
+    -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151,
+    -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533,
+    -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915,
+    -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295,
+    -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675,
+    -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054,
+    -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433,
+    -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810,
+    -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186,
+    -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562,
+    -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937,
+    -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311,
+    -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684,
+    -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056,
+    -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427,
+    -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797,
+    -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166,
+    -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534,
+    -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902,
+    -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268,
+    -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633,
+    -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997,
+    -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360,
+    -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722,
+    -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083,
+    -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443,
+    -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801,
+    -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159,
+    -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515,
+    -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871,
+    -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225,
+    -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578,
+    -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930,
+    -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280,
+    -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630,
+    -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978,
+    -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325,
+    -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670,
+    -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015,
+    -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358,
+    -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699,
+    -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040,
+    -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379,
+    -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717,
+    -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053,
+    -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388,
+    -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722,
+    -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055,
+    -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386,
+    -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715,
+    -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043,
+    -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370,
+    -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695,
+    -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019,
+    -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341,
+    -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662,
+    -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982,
+    -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299,
+    -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616,
+    -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931,
+    -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244,
+    -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556,
+    -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866,
+    -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174,
+    -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481,
+    -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787,
+    -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091,
+    -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393,
+    -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693,
+    -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992,
+    -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289,
+    -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585,
+    -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879,
+    -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171,
+    -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462,
+    -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750,
+    -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037,
+    -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323,
+    -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606,
+    -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888,
+    -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168,
+    -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446,
+    -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723,
+    -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998,
+    -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271,
+    -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542,
+    -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811,
+    -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078,
+    -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344,
+    -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608,
+    -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869,
+    -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129,
+    -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387,
+    -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644,
+    -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898,
+    -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150,
+    -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401,
+    -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649,
+    -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896,
+    -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140,
+    -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383,
+    -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624,
+    -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862,
+    -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099,
+    -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334,
+    -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566,
+    -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797,
+    -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026,
+    -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252,
+    -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477,
+    -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699,
+    -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920,
+    -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138,
+    -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354,
+    -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569,
+    -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781,
+    -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991,
+    -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199,
+    -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404,
+    -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608,
+    -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810,
+    -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009,
+    -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206,
+    -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402,
+    -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594,
+    -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785,
+    -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974,
+    -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160,
+    -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345,
+    -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527,
+    -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706,
+    -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884,
+    -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059,
+    -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233,
+    -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404,
+    -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572,
+    -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739,
+    -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903,
+    -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065,
+    -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225,
+    -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382,
+    -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537,
+    -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690,
+    -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841,
+    -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989,
+    -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135,
+    -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279,
+    -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420,
+    -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559,
+    -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696,
+    -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831,
+    -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963,
+    -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092,
+    -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220,
+    -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345,
+    -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468,
+    -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588,
+    -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706,
+    -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822,
+    -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935,
+    -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046,
+    -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155,
+    -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261,
+    -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365,
+    -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466,
+    -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565,
+    -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662,
+    -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756,
+    -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848,
+    -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938,
+    -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025,
+    -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109,
+    -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192,
+    -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271,
+    -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349,
+    -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424,
+    -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496,
+    -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566,
+    -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634,
+    -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699,
+    -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762,
+    -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822,
+    -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880,
+    -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936,
+    -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989,
+    -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040,
+    -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088,
+    -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133,
+    -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177,
+    -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217,
+    -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256,
+    -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292,
+    -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325,
+    -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356,
+    -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385,
+    -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411,
+    -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434,
+    -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455,
+    -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474,
+    -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490,
+    -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504,
+    -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515,
+    -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524,
+    -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530,
+    -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534,
+    -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535,
+    -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534,
+    -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531,
+    -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525,
+    -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516,
+    -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505,
+    -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492,
+    -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476,
+    -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458,
+    -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437,
+    -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414,
+    -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388,
+    -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360,
+    -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329,
+    -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296,
+    -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260,
+    -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222,
+    -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182,
+    -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139,
+    -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094,
+    -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046,
+    -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995,
+    -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943,
+    -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887,
+    -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830,
+    -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770,
+    -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707,
+    -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642,
+    -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575,
+    -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505,
+    -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433,
+    -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358,
+    -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281,
+    -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202,
+    -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120,
+    -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035,
+    -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949,
+    -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859,
+    -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768,
+    -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674,
+    -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578,
+    -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479,
+    -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378,
+    -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274,
+    -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168,
+    -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060,
+    -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949,
+    -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836,
+    -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721,
+    -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603,
+    -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483,
+    -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360,
+    -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236,
+    -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108,
+    -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979,
+    -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847,
+    -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713,
+    -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577,
+    -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438,
+    -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297,
+    -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153,
+    -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007,
+    -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859,
+    -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709,
+    -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556,
+    -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402,
+    -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244,
+    -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085,
+    -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923,
+    -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759,
+    -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593,
+    -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425,
+    -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254,
+    -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081,
+    -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906,
+    -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729,
+    -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549,
+    -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367,
+    -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183,
+    -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997,
+    -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809,
+    -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618,
+    -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426,
+    -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231,
+    -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034,
+    -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835,
+    -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633,
+    -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430,
+    -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225,
+    -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017,
+    -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807,
+    -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595,
+    -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381,
+    -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165,
+    -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947,
+    -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727,
+    -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505,
+    -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280,
+    -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054,
+    -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826,
+    -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595,
+    -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363,
+    -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128,
+    -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892,
+    -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653,
+    -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413,
+    -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171,
+    -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926,
+    -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680,
+    -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432,
+    -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182,
+    -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929,
+    -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675,
+    -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420,
+    -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162,
+    -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902,
+    -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640,
+    -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377,
+    -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112,
+    -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844,
+    -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575,
+    -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305,
+    -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032,
+    -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757,
+    -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481,
+    -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203,
+    -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923,
+    -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642,
+    -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358,
+    -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073,
+    -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786,
+    -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498,
+    -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207,
+    -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915,
+    -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622,
+    -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326,
+    -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029,
+    -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731,
+    -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430,
+    -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128,
+    -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825,
+    -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520,
+    -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213,
+    -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904,
+    -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595,
+    -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283,
+    -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970,
+    -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655,
+    -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339,
+    -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021,
+    -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702,
+    -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382,
+    -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059,
+    -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736,
+    -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411,
+    -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084,
+    -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756,
+    -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427,
+    -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096,
+    -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764,
+    -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430,
+    -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095,
+    -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759,
+    -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421,
+    -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082,
+    -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742,
+    -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400,
+    -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057,
+    -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713,
+    -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368,
+    -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021,
+    -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673,
+    -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324,
+    -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974,
+    -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622,
+    -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269,
+    -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915,
+    -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560,
+    -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204,
+    -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846,
+    -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488,
+    -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128,
+    -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767,
+    -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405,
+    -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042,
+    -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678,
+    -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313,
+    -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947,
+    -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580,
+    -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212,
+    -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843,
+    -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473,
+    -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102,
+    -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730,
+    -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357,
+    -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984,
+    -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609,
+    -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233,
+    -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857,
+    -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480,
+    -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102,
+    -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723,
+    -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343,
+    -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962,
+    -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581,
+    -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199,
+    -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816,
+    -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432,
+    -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048,
+    -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663,
+    -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277,
+    -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890,
+    -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503,
+    -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115,
+    -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727,
+    -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338,
+    -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948,
+    -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557,
+    -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167,
+    -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775,
+    -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383,
+    -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990,
+    -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597,
+    -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204,
+    -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810,
+    -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415,
+    -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020,
+    -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624,
+    -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228,
+    -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832,
+    -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435,
+    -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038,
+    -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640,
+    -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243,
+    -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844,
+    -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446,
+    -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047,
+    -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648,
+    -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248,
+    -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848,
+    -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448,
+    -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048,
+    -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647,
+    -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247,
+    -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846,
+    -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445,
+    -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043,
+    -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642,
+    -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240,
+    -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839,
+    -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437,
+    -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035,
+    -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633,
+    -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231,
+    -1181,-1130,-1080,-1030,-980,-929,-879,-829,
+    -779,-728,-678,-628,-578,-527,-477,-427,
+    -376,-326,-276,-226,-175,-125,-75,-25,
+    25,75,125,175,226,276,326,376,
+    427,477,527,578,628,678,728,779,
+    829,879,929,980,1030,1080,1130,1181,
+    1231,1281,1331,1382,1432,1482,1532,1583,
+    1633,1683,1733,1784,1834,1884,1934,1985,
+    2035,2085,2135,2186,2236,2286,2336,2387,
+    2437,2487,2537,2587,2638,2688,2738,2788,
+    2839,2889,2939,2989,3039,3090,3140,3190,
+    3240,3291,3341,3391,3441,3491,3542,3592,
+    3642,3692,3742,3792,3843,3893,3943,3993,
+    4043,4093,4144,4194,4244,4294,4344,4394,
+    4445,4495,4545,4595,4645,4695,4745,4796,
+    4846,4896,4946,4996,5046,5096,5146,5197,
+    5247,5297,5347,5397,5447,5497,5547,5597,
+    5647,5697,5747,5798,5848,5898,5948,5998,
+    6048,6098,6148,6198,6248,6298,6348,6398,
+    6448,6498,6548,6598,6648,6698,6748,6798,
+    6848,6898,6948,6998,7048,7098,7148,7198,
+    7248,7298,7348,7398,7448,7498,7548,7598,
+    7648,7697,7747,7797,7847,7897,7947,7997,
+    8047,8097,8147,8196,8246,8296,8346,8396,
+    8446,8496,8545,8595,8645,8695,8745,8794,
+    8844,8894,8944,8994,9043,9093,9143,9193,
+    9243,9292,9342,9392,9442,9491,9541,9591,
+    9640,9690,9740,9790,9839,9889,9939,9988,
+    10038,10088,10137,10187,10237,10286,10336,10386,
+    10435,10485,10534,10584,10634,10683,10733,10782,
+    10832,10882,10931,10981,11030,11080,11129,11179,
+    11228,11278,11327,11377,11426,11476,11525,11575,
+    11624,11674,11723,11773,11822,11872,11921,11970,
+    12020,12069,12119,12168,12218,12267,12316,12366,
+    12415,12464,12514,12563,12612,12662,12711,12760,
+    12810,12859,12908,12957,13007,13056,13105,13154,
+    13204,13253,13302,13351,13401,13450,13499,13548,
+    13597,13647,13696,13745,13794,13843,13892,13941,
+    13990,14040,14089,14138,14187,14236,14285,14334,
+    14383,14432,14481,14530,14579,14628,14677,14726,
+    14775,14824,14873,14922,14971,15020,15069,15118,
+    15167,15215,15264,15313,15362,15411,15460,15509,
+    15557,15606,15655,15704,15753,15802,15850,15899,
+    15948,15997,16045,16094,16143,16191,16240,16289,
+    16338,16386,16435,16484,16532,16581,16629,16678,
+    16727,16775,16824,16872,16921,16970,17018,17067,
+    17115,17164,17212,17261,17309,17358,17406,17455,
+    17503,17551,17600,17648,17697,17745,17793,17842,
+    17890,17939,17987,18035,18084,18132,18180,18228,
+    18277,18325,18373,18421,18470,18518,18566,18614,
+    18663,18711,18759,18807,18855,18903,18951,19000,
+    19048,19096,19144,19192,19240,19288,19336,19384,
+    19432,19480,19528,19576,19624,19672,19720,19768,
+    19816,19864,19912,19959,20007,20055,20103,20151,
+    20199,20246,20294,20342,20390,20438,20485,20533,
+    20581,20629,20676,20724,20772,20819,20867,20915,
+    20962,21010,21057,21105,21153,21200,21248,21295,
+    21343,21390,21438,21485,21533,21580,21628,21675,
+    21723,21770,21817,21865,21912,21960,22007,22054,
+    22102,22149,22196,22243,22291,22338,22385,22432,
+    22480,22527,22574,22621,22668,22716,22763,22810,
+    22857,22904,22951,22998,23045,23092,23139,23186,
+    23233,23280,23327,23374,23421,23468,23515,23562,
+    23609,23656,23703,23750,23796,23843,23890,23937,
+    23984,24030,24077,24124,24171,24217,24264,24311,
+    24357,24404,24451,24497,24544,24591,24637,24684,
+    24730,24777,24823,24870,24916,24963,25009,25056,
+    25102,25149,25195,25241,25288,25334,25381,25427,
+    25473,25520,25566,25612,25658,25705,25751,25797,
+    25843,25889,25936,25982,26028,26074,26120,26166,
+    26212,26258,26304,26350,26396,26442,26488,26534,
+    26580,26626,26672,26718,26764,26810,26856,26902,
+    26947,26993,27039,27085,27131,27176,27222,27268,
+    27313,27359,27405,27450,27496,27542,27587,27633,
+    27678,27724,27770,27815,27861,27906,27952,27997,
+    28042,28088,28133,28179,28224,28269,28315,28360,
+    28405,28451,28496,28541,28586,28632,28677,28722,
+    28767,28812,28858,28903,28948,28993,29038,29083,
+    29128,29173,29218,29263,29308,29353,29398,29443,
+    29488,29533,29577,29622,29667,29712,29757,29801,
+    29846,29891,29936,29980,30025,30070,30114,30159,
+    30204,30248,30293,30337,30382,30427,30471,30516,
+    30560,30604,30649,30693,30738,30782,30826,30871,
+    30915,30959,31004,31048,31092,31136,31181,31225,
+    31269,31313,31357,31402,31446,31490,31534,31578,
+    31622,31666,31710,31754,31798,31842,31886,31930,
+    31974,32017,32061,32105,32149,32193,32236,32280,
+    32324,32368,32411,32455,32499,32542,32586,32630,
+    32673,32717,32760,32804,32847,32891,32934,32978,
+    33021,33065,33108,33151,33195,33238,33281,33325,
+    33368,33411,33454,33498,33541,33584,33627,33670,
+    33713,33756,33799,33843,33886,33929,33972,34015,
+    34057,34100,34143,34186,34229,34272,34315,34358,
+    34400,34443,34486,34529,34571,34614,34657,34699,
+    34742,34785,34827,34870,34912,34955,34997,35040,
+    35082,35125,35167,35210,35252,35294,35337,35379,
+    35421,35464,35506,35548,35590,35633,35675,35717,
+    35759,35801,35843,35885,35927,35969,36011,36053,
+    36095,36137,36179,36221,36263,36305,36347,36388,
+    36430,36472,36514,36556,36597,36639,36681,36722,
+    36764,36805,36847,36889,36930,36972,37013,37055,
+    37096,37137,37179,37220,37262,37303,37344,37386,
+    37427,37468,37509,37551,37592,37633,37674,37715,
+    37756,37797,37838,37879,37920,37961,38002,38043,
+    38084,38125,38166,38207,38248,38288,38329,38370,
+    38411,38451,38492,38533,38573,38614,38655,38695,
+    38736,38776,38817,38857,38898,38938,38979,39019,
+    39059,39100,39140,39180,39221,39261,39301,39341,
+    39382,39422,39462,39502,39542,39582,39622,39662,
+    39702,39742,39782,39822,39862,39902,39942,39982,
+    40021,40061,40101,40141,40180,40220,40260,40299,
+    40339,40379,40418,40458,40497,40537,40576,40616,
+    40655,40695,40734,40773,40813,40852,40891,40931,
+    40970,41009,41048,41087,41127,41166,41205,41244,
+    41283,41322,41361,41400,41439,41478,41517,41556,
+    41595,41633,41672,41711,41750,41788,41827,41866,
+    41904,41943,41982,42020,42059,42097,42136,42174,
+    42213,42251,42290,42328,42366,42405,42443,42481,
+    42520,42558,42596,42634,42672,42711,42749,42787,
+    42825,42863,42901,42939,42977,43015,43053,43091,
+    43128,43166,43204,43242,43280,43317,43355,43393,
+    43430,43468,43506,43543,43581,43618,43656,43693,
+    43731,43768,43806,43843,43880,43918,43955,43992,
+    44029,44067,44104,44141,44178,44215,44252,44289,
+    44326,44363,44400,44437,44474,44511,44548,44585,
+    44622,44659,44695,44732,44769,44806,44842,44879,
+    44915,44952,44989,45025,45062,45098,45135,45171,
+    45207,45244,45280,45316,45353,45389,45425,45462,
+    45498,45534,45570,45606,45642,45678,45714,45750,
+    45786,45822,45858,45894,45930,45966,46002,46037,
+    46073,46109,46145,46180,46216,46252,46287,46323,
+    46358,46394,46429,46465,46500,46536,46571,46606,
+    46642,46677,46712,46747,46783,46818,46853,46888,
+    46923,46958,46993,47028,47063,47098,47133,47168,
+    47203,47238,47273,47308,47342,47377,47412,47446,
+    47481,47516,47550,47585,47619,47654,47688,47723,
+    47757,47792,47826,47861,47895,47929,47963,47998,
+    48032,48066,48100,48134,48168,48202,48237,48271,
+    48305,48338,48372,48406,48440,48474,48508,48542,
+    48575,48609,48643,48676,48710,48744,48777,48811,
+    48844,48878,48911,48945,48978,49012,49045,49078,
+    49112,49145,49178,49211,49244,49278,49311,49344,
+    49377,49410,49443,49476,49509,49542,49575,49608,
+    49640,49673,49706,49739,49771,49804,49837,49869,
+    49902,49935,49967,50000,50032,50064,50097,50129,
+    50162,50194,50226,50259,50291,50323,50355,50387,
+    50420,50452,50484,50516,50548,50580,50612,50644,
+    50675,50707,50739,50771,50803,50834,50866,50898,
+    50929,50961,50993,51024,51056,51087,51119,51150,
+    51182,51213,51244,51276,51307,51338,51369,51401,
+    51432,51463,51494,51525,51556,51587,51618,51649,
+    51680,51711,51742,51773,51803,51834,51865,51896,
+    51926,51957,51988,52018,52049,52079,52110,52140,
+    52171,52201,52231,52262,52292,52322,52353,52383,
+    52413,52443,52473,52503,52534,52564,52594,52624,
+    52653,52683,52713,52743,52773,52803,52832,52862,
+    52892,52922,52951,52981,53010,53040,53069,53099,
+    53128,53158,53187,53216,53246,53275,53304,53334,
+    53363,53392,53421,53450,53479,53508,53537,53566,
+    53595,53624,53653,53682,53711,53739,53768,53797,
+    53826,53854,53883,53912,53940,53969,53997,54026,
+    54054,54082,54111,54139,54167,54196,54224,54252,
+    54280,54309,54337,54365,54393,54421,54449,54477,
+    54505,54533,54560,54588,54616,54644,54672,54699,
+    54727,54755,54782,54810,54837,54865,54892,54920,
+    54947,54974,55002,55029,55056,55084,55111,55138,
+    55165,55192,55219,55246,55274,55300,55327,55354,
+    55381,55408,55435,55462,55489,55515,55542,55569,
+    55595,55622,55648,55675,55701,55728,55754,55781,
+    55807,55833,55860,55886,55912,55938,55965,55991,
+    56017,56043,56069,56095,56121,56147,56173,56199,
+    56225,56250,56276,56302,56328,56353,56379,56404,
+    56430,56456,56481,56507,56532,56557,56583,56608,
+    56633,56659,56684,56709,56734,56760,56785,56810,
+    56835,56860,56885,56910,56935,56959,56984,57009,
+    57034,57059,57083,57108,57133,57157,57182,57206,
+    57231,57255,57280,57304,57329,57353,57377,57402,
+    57426,57450,57474,57498,57522,57546,57570,57594,
+    57618,57642,57666,57690,57714,57738,57762,57785,
+    57809,57833,57856,57880,57903,57927,57950,57974,
+    57997,58021,58044,58067,58091,58114,58137,58160,
+    58183,58207,58230,58253,58276,58299,58322,58345,
+    58367,58390,58413,58436,58459,58481,58504,58527,
+    58549,58572,58594,58617,58639,58662,58684,58706,
+    58729,58751,58773,58795,58818,58840,58862,58884,
+    58906,58928,58950,58972,58994,59016,59038,59059,
+    59081,59103,59125,59146,59168,59190,59211,59233,
+    59254,59276,59297,59318,59340,59361,59382,59404,
+    59425,59446,59467,59488,59509,59530,59551,59572,
+    59593,59614,59635,59656,59677,59697,59718,59739,
+    59759,59780,59801,59821,59842,59862,59883,59903,
+    59923,59944,59964,59984,60004,60025,60045,60065,
+    60085,60105,60125,60145,60165,60185,60205,60225,
+    60244,60264,60284,60304,60323,60343,60363,60382,
+    60402,60421,60441,60460,60479,60499,60518,60537,
+    60556,60576,60595,60614,60633,60652,60671,60690,
+    60709,60728,60747,60766,60785,60803,60822,60841,
+    60859,60878,60897,60915,60934,60952,60971,60989,
+    61007,61026,61044,61062,61081,61099,61117,61135,
+    61153,61171,61189,61207,61225,61243,61261,61279,
+    61297,61314,61332,61350,61367,61385,61403,61420,
+    61438,61455,61473,61490,61507,61525,61542,61559,
+    61577,61594,61611,61628,61645,61662,61679,61696,
+    61713,61730,61747,61764,61780,61797,61814,61831,
+    61847,61864,61880,61897,61913,61930,61946,61963,
+    61979,61995,62012,62028,62044,62060,62076,62092,
+    62108,62125,62141,62156,62172,62188,62204,62220,
+    62236,62251,62267,62283,62298,62314,62329,62345,
+    62360,62376,62391,62407,62422,62437,62453,62468,
+    62483,62498,62513,62528,62543,62558,62573,62588,
+    62603,62618,62633,62648,62662,62677,62692,62706,
+    62721,62735,62750,62764,62779,62793,62808,62822,
+    62836,62850,62865,62879,62893,62907,62921,62935,
+    62949,62963,62977,62991,63005,63019,63032,63046,
+    63060,63074,63087,63101,63114,63128,63141,63155,
+    63168,63182,63195,63208,63221,63235,63248,63261,
+    63274,63287,63300,63313,63326,63339,63352,63365,
+    63378,63390,63403,63416,63429,63441,63454,63466,
+    63479,63491,63504,63516,63528,63541,63553,63565,
+    63578,63590,63602,63614,63626,63638,63650,63662,
+    63674,63686,63698,63709,63721,63733,63745,63756,
+    63768,63779,63791,63803,63814,63825,63837,63848,
+    63859,63871,63882,63893,63904,63915,63927,63938,
+    63949,63960,63971,63981,63992,64003,64014,64025,
+    64035,64046,64057,64067,64078,64088,64099,64109,
+    64120,64130,64140,64151,64161,64171,64181,64192,
+    64202,64212,64222,64232,64242,64252,64261,64271,
+    64281,64291,64301,64310,64320,64330,64339,64349,
+    64358,64368,64377,64387,64396,64405,64414,64424,
+    64433,64442,64451,64460,64469,64478,64487,64496,
+    64505,64514,64523,64532,64540,64549,64558,64566,
+    64575,64584,64592,64600,64609,64617,64626,64634,
+    64642,64651,64659,64667,64675,64683,64691,64699,
+    64707,64715,64723,64731,64739,64747,64754,64762,
+    64770,64777,64785,64793,64800,64808,64815,64822,
+    64830,64837,64844,64852,64859,64866,64873,64880,
+    64887,64895,64902,64908,64915,64922,64929,64936,
+    64943,64949,64956,64963,64969,64976,64982,64989,
+    64995,65002,65008,65015,65021,65027,65033,65040,
+    65046,65052,65058,65064,65070,65076,65082,65088,
+    65094,65099,65105,65111,65117,65122,65128,65133,
+    65139,65144,65150,65155,65161,65166,65171,65177,
+    65182,65187,65192,65197,65202,65207,65212,65217,
+    65222,65227,65232,65237,65242,65246,65251,65256,
+    65260,65265,65270,65274,65279,65283,65287,65292,
+    65296,65300,65305,65309,65313,65317,65321,65325,
+    65329,65333,65337,65341,65345,65349,65352,65356,
+    65360,65363,65367,65371,65374,65378,65381,65385,
+    65388,65391,65395,65398,65401,65404,65408,65411,
+    65414,65417,65420,65423,65426,65429,65431,65434,
+    65437,65440,65442,65445,65448,65450,65453,65455,
+    65458,65460,65463,65465,65467,65470,65472,65474,
+    65476,65478,65480,65482,65484,65486,65488,65490,
+    65492,65494,65496,65497,65499,65501,65502,65504,
+    65505,65507,65508,65510,65511,65513,65514,65515,
+    65516,65518,65519,65520,65521,65522,65523,65524,
+    65525,65526,65527,65527,65528,65529,65530,65530,
+    65531,65531,65532,65532,65533,65533,65534,65534,
+    65534,65535,65535,65535,65535,65535,65535,65535
+};
+
+
+
+const angle_t tantoangle[2049] =
+{
+    0,333772,667544,1001315,1335086,1668857,2002626,2336395,
+    2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492,
+    5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435,
+    8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145,
+    10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539,
+    13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536,
+    16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054,
+    18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014,
+    21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332,
+    24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930,
+    26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724,
+    29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636,
+    32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584,
+    34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492,
+    37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272,
+    40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848,
+    42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140,
+    45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072,
+    47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556,
+    50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524,
+    53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888,
+    55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576,
+    58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508,
+    61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604,
+    63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788,
+    66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984,
+    69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112,
+    71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096,
+    74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864,
+    77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336,
+    79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440,
+    82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096,
+    85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240,
+    87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792,
+    90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672,
+    92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816,
+    95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144,
+    98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592,
+    100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080,
+    103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552,
+    105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920,
+    108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120,
+    111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080,
+    113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744,
+    116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024,
+    118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864,
+    121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200,
+    124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960,
+    126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072,
+    129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480,
+    131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120,
+    134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912,
+    136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808,
+    139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752,
+    142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664,
+    144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480,
+    147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152,
+    149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616,
+    152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824,
+    154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696,
+    157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168,
+    159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208,
+    162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752,
+    164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736,
+    167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096,
+    169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800,
+    172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784,
+    174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984,
+    177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368,
+    179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856,
+    182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416,
+    184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000,
+    187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560,
+    189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016,
+    192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352,
+    194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520,
+    197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456,
+    199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128,
+    202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472,
+    204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456,
+    207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048,
+    209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184,
+    211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816,
+    214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928,
+    216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472,
+    219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384,
+    221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664,
+    223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232,
+    226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088,
+    228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152,
+    231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440,
+    233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872,
+    235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416,
+    238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072,
+    240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776,
+    242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496,
+    245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216,
+    247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904,
+    249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512,
+    252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008,
+    254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392,
+    256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600,
+    259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632,
+    261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456,
+    263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024,
+    266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336,
+    268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360,
+    270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048,
+    272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432,
+    275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416,
+    277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032,
+    279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248,
+    281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032,
+    284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384,
+    286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240,
+    288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632,
+    290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528,
+    293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864,
+    295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704,
+    297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952,
+    299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640,
+    301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768,
+    303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272,
+    306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152,
+    308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408,
+    310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040,
+    312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016,
+    314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336,
+    316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968,
+    319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912,
+    321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200,
+    323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736,
+    325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584,
+    327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712,
+    329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120,
+    331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776,
+    333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712,
+    335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864,
+    337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296,
+    340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976,
+    342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904,
+    344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048,
+    346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440,
+    348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048,
+    350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872,
+    352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944,
+    354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264,
+    356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768,
+    358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520,
+    360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488,
+    362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704,
+    364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136,
+    366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784,
+    368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680,
+    370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792,
+    372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152,
+    374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760,
+    376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584,
+    377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688,
+    379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040,
+    381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640,
+    383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488,
+    385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616,
+    387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024,
+    389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712,
+    391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680,
+    393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960,
+    395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520,
+    396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424,
+    398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608,
+    400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136,
+    402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008,
+    404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224,
+    406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784,
+    408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720,
+    409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032,
+    411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720,
+    413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784,
+    415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288,
+    417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200,
+    418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552,
+    420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344,
+    422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576,
+    424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280,
+    425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488,
+    427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168,
+    429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352,
+    431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040,
+    432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296,
+    434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088,
+    436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416,
+    438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344,
+    439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872,
+    441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968,
+    443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696,
+    444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088,
+    446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112,
+    448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800,
+    450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152,
+    451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232,
+    453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008,
+    454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512,
+    456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744,
+    458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768,
+    459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584,
+    461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160,
+    463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560,
+    464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816,
+    466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896,
+    468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832,
+    469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688,
+    471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400,
+    472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064,
+    474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648,
+    475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184,
+    477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704,
+    479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240,
+    480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760,
+    482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296,
+    483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912,
+    485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576,
+    486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320,
+    488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176,
+    489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144,
+    491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256,
+    492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544,
+    494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008,
+    495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680,
+    497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560,
+    498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680,
+    500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040,
+    501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704,
+    503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672,
+    504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944,
+    506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552,
+    507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528,
+    509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872,
+    510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616,
+    511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792,
+    513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368,
+    514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440,
+    516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976,
+    517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008,
+    519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568,
+    520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656,
+    521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304,
+    523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512,
+    524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344,
+    526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800,
+    527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880,
+    528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648,
+    530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072,
+    531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184,
+    532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048,
+    534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632,
+    535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000,
+    536870912
+};
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/tables.h b/Source/Plugins/vpo_dll/tables.h
new file mode 100644
index 0000000000000000000000000000000000000000..9885032bcf68ccfae114a020f7afa6a5dc341bdc
--- /dev/null
+++ b/Source/Plugins/vpo_dll/tables.h
@@ -0,0 +1,94 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Lookup tables.
+//	Do not try to look them up :-).
+//	In the order of appearance: 
+//
+//	int finetangent[4096]	- Tangens LUT.
+//	 Should work with BAM fairly well (12 of 16bit,
+//      effectively, by shifting).
+//
+//	int finesine[10240]		- Sine lookup.
+//	 Guess what, serves as cosine, too.
+//	 Remarkable thing is, how to use BAMs with this? 
+//
+//	int tantoangle[2049]	- ArcTan LUT,
+//	  maps tan(angle) to angle fast. Gotta search.	
+//    
+//-----------------------------------------------------------------------------
+
+
+#ifndef __TABLES__
+#define __TABLES__
+
+
+
+#include "m_fixed.h"
+	
+#define FINEANGLES		8192
+#define FINEMASK		(FINEANGLES-1)
+
+
+// 0x100000000 to 0x2000
+#define ANGLETOFINESHIFT	19		
+
+// Effective size is 10240.
+extern const fixed_t finesine[5*FINEANGLES/4];
+
+// Re-use data, is just PI/2 pahse shift.
+extern const fixed_t *finecosine;
+
+
+// Effective size is 4096.
+extern const fixed_t finetangent[FINEANGLES/2];
+
+// Binary Angle Measument, BAM.
+#define ANG45			0x20000000
+#define ANG90			0x40000000
+#define ANG180		0x80000000
+#define ANG270		0xc0000000
+
+
+#define SLOPERANGE		2048
+#define SLOPEBITS		11
+#define DBITS			(FRACBITS-SLOPEBITS)
+
+typedef unsigned angle_t;
+
+
+// Effective size is 2049;
+// The +1 size is to handle the case when x==y
+//  without additional checking.
+extern const angle_t tantoangle[SLOPERANGE+1];
+
+
+// Utility function,
+//  called by R_PointToAngle.
+int
+SlopeDiv
+( unsigned	num,
+  unsigned	den);
+
+
+#endif
+
diff --git a/Source/Plugins/vpo_dll/vpo_api.h b/Source/Plugins/vpo_dll/vpo_api.h
new file mode 100644
index 0000000000000000000000000000000000000000..f0eb99039dd976e6c9acacbbab0b20a04da021f6
--- /dev/null
+++ b/Source/Plugins/vpo_dll/vpo_api.h
@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------
+//  Visplane Overflow Library
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 1993-1996 Id Software, Inc.
+//  Copyright (C) 2005 Simon Howard
+//  Copyright (C) 2012 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+
+#ifndef __VPO_API_H__
+#define __VPO_API_H__
+
+
+// return error message when something fails
+// (this will be a static buffer, so is not guaranteed to remain valid
+//  after any other API call)
+const char* APIENTRY VPO_GetError(void);
+
+// try to load a wad file
+// returns 0 on success, negative value on error
+int APIENTRY VPO_LoadWAD(const char *wad_filename);
+
+// free all data associated with the wad file
+// can be safely called without any loaded wad file
+void APIENTRY VPO_FreeWAD(void);
+
+// retrieve the map names in the wad, one at a time
+// index starts at 0
+// returns NULL when index is past the end of the list
+// NOTE: return pointer may be a static buffer, not guaranteed to
+//       remain valid once this function is called again
+const char* APIENTRY VPO_GetMapName(unsigned int index);
+
+// try to open a map from the current wad file
+// returns 0 on success, negative value on error
+int APIENTRY VPO_OpenMap(const char *map_name);
+
+// free all data associated with a map
+// can be safely called without any opened map
+void APIENTRY VPO_CloseMap(void);
+
+// retrieve the linedefs in the current map, one at a time
+// index starts at 0
+// returns number of sides (0 to 2), or -1 for invalid index
+int APIENTRY VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *y2);
+
+// test a spot and angle, returning the number of visplanes
+// dz is the height above the floor (or offset from ceiling if < 0)
+// angle is in degrees (0 to 360), 0 is east, 90 is north
+// returns RESULT_OK on success, or a negative value spot was in the
+// void or an error occurred -- see the RESULT_* values below
+//
+// the num_xxx parameters point to variables which get _updated_ by
+// this call (i.e. new value is maximum of old value + checked value).
+// hence you need to set those variables to zero before the first
+// call at a particular (X Y) location.
+//
+// RESULT_OVERFLOW means that an internal limit overflowed (which are
+// four times or more the actual DOOM limits).
+
+#define RESULT_OK         0
+#define RESULT_BAD_Z     -1
+#define RESULT_IN_VOID   -2
+#define RESULT_OVERFLOW  -3
+
+int APIENTRY VPO_TestSpot(int x, int y, int dz, int angle,
+                 int *num_visplanes,
+                 int *num_drawsegs,
+                 int *num_openings,
+                 int *num_solidsegs);
+
+#endif  /* __VPO_API_H__ */
+
diff --git a/Source/Plugins/vpo_dll/vpo_dll.vcproj b/Source/Plugins/vpo_dll/vpo_dll.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..ebc83543af950e63b273bc24bea6907da114813f
--- /dev/null
+++ b/Source/Plugins/vpo_dll/vpo_dll.vcproj
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="vpo_dll"
+	ProjectGUID="{29C8D76F-DE3D-482D-AD7D-B86BBD0824DE}"
+	RootNamespace="vpo_dll"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)\Source\Plugins\VisplaneExplorer\Resources"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\vpo.dll"
+				ModuleDefinitionFile="exports.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				FixedBaseAddress="1"
+				SupportUnloadOfDelayLoadedDLL="true"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)\Source\Plugins\VisplaneExplorer\Resources"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="4"
+				InlineFunctionExpansion="2"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(ProjectDir)&quot;"
+				PreprocessorDefinitions="WIN32;_RELEASE;_WINDOWS;_USRDLL"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				EnableEnhancedInstructionSet="2"
+				FloatingPointModel="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\vpo.dll"
+				ModuleDefinitionFile="exports.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				FixedBaseAddress="1"
+				SupportUnloadOfDelayLoadedDLL="true"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\m_bbox.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\m_fixed.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\p_setup.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\r_bsp.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\r_main.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\r_plane.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\r_segs.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\tables.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\vpo_main.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\vpo_stuff.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\w_file.cc"
+				>
+			</File>
+			<File
+				RelativePath=".\w_wad.cc"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\doomdata.h"
+				>
+			</File>
+			<File
+				RelativePath=".\doomdef.h"
+				>
+			</File>
+			<File
+				RelativePath=".\doomtype.h"
+				>
+			</File>
+			<File
+				RelativePath=".\exports.def"
+				>
+			</File>
+			<File
+				RelativePath=".\inttypes.h"
+				>
+			</File>
+			<File
+				RelativePath=".\m_bbox.h"
+				>
+			</File>
+			<File
+				RelativePath=".\m_fixed.h"
+				>
+			</File>
+			<File
+				RelativePath=".\r_bsp.h"
+				>
+			</File>
+			<File
+				RelativePath=".\r_defs.h"
+				>
+			</File>
+			<File
+				RelativePath=".\r_main.h"
+				>
+			</File>
+			<File
+				RelativePath=".\r_plane.h"
+				>
+			</File>
+			<File
+				RelativePath=".\r_state.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdint.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sys_endian.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sys_macro.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sys_type.h"
+				>
+			</File>
+			<File
+				RelativePath=".\tables.h"
+				>
+			</File>
+			<File
+				RelativePath=".\vpo_api.h"
+				>
+			</File>
+			<File
+				RelativePath=".\vpo_local.h"
+				>
+			</File>
+			<File
+				RelativePath=".\w_file.h"
+				>
+			</File>
+			<File
+				RelativePath=".\w_wad.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/Source/Plugins/vpo_dll/vpo_local.h b/Source/Plugins/vpo_dll/vpo_local.h
new file mode 100644
index 0000000000000000000000000000000000000000..667b1fedc500dc2bb7fb39a7bf0d985e3dab614e
--- /dev/null
+++ b/Source/Plugins/vpo_dll/vpo_local.h
@@ -0,0 +1,80 @@
+//------------------------------------------------------------------------
+//  Visplane Overflow Library
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 1993-1996 Id Software, Inc.
+//  Copyright (C) 2005 Simon Howard
+//  Copyright (C) 2012 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+
+#ifndef __VPO_LOCAL_H__
+#define __VPO_LOCAL_H__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "sys_type.h"
+#include "sys_macro.h"
+#include "sys_endian.h"
+
+namespace vpo
+{
+
+#include "doomtype.h"
+#include "doomdef.h"
+#include "doomdata.h"
+
+#include "m_bbox.h"
+#include "m_fixed.h"
+
+#include "w_file.h"
+#include "w_wad.h"
+
+#include "tables.h"
+#include "r_defs.h"
+#include "r_state.h"
+
+#include "r_main.h"
+#include "r_bsp.h"
+#include "r_plane.h"
+
+
+//------------------------------------------------------------
+
+#define SHORT(x)  LE_S16(x)
+#define LONG(x)   LE_S32(x)
+
+void P_SetupLevel (const char *lumpname );
+void P_FreeLevelData (void);
+
+void I_Error (const char *error, ...);
+
+sector_t * X_SectorForPoint(fixed_t x, fixed_t y);
+
+// exceptions thrown on overflows
+class overflow_exception { };
+
+} // namespace vpo
+
+
+#endif  /* __VPO_LOCAL_H__ */
+
+//--- editor settings ---
+// vi:ts=4:sw=4:noexpandtab
diff --git a/Source/Plugins/vpo_dll/vpo_main.cc b/Source/Plugins/vpo_dll/vpo_main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..085a22831de985bf6c21b3744d40a810ab9f6b92
--- /dev/null
+++ b/Source/Plugins/vpo_dll/vpo_main.cc
@@ -0,0 +1,294 @@
+//------------------------------------------------------------------------
+//  Visplane Overflow Library
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 1993-1996 Id Software, Inc.
+//  Copyright (C) 2005 Simon Howard
+//  Copyright (C) 2012 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+
+#include "vpo_local.h"
+#include "vpo_api.h"
+
+
+static char error_buffer[1024];
+
+// cache for the sector lookup
+static int last_x, last_y;
+static vpo::sector_t *last_sector;
+
+
+static void ClearError(void)
+{
+	strcpy(error_buffer, "(No Error)");
+}
+
+static void SetError(const char *msg, ...)
+{
+	va_list argptr;
+
+	va_start(argptr, msg);
+	memset(error_buffer, 0, sizeof(error_buffer));
+	vsnprintf(error_buffer, sizeof(error_buffer) - 1, msg, argptr);
+	va_end(argptr);
+}
+
+
+const char* APIENTRY VPO_GetError(void)
+{
+	return error_buffer;
+}
+
+
+//------------------------------------------------------------------------
+
+int APIENTRY VPO_LoadWAD(const char *wad_filename)
+{
+	ClearError();
+
+	// free any previously loaded wad
+	VPO_FreeWAD();
+
+	vpo::R_Init();
+
+	if (! vpo::W_AddFile(wad_filename))
+	{
+		SetError("Could not open/read the file: %s", wad_filename);
+		return -1;
+	}
+
+	return 0;  // OK !
+}
+
+
+int APIENTRY VPO_OpenMap(const char *map_name)
+{
+	// check a wad is loaded
+	if (vpo::numlumps <= 0)
+	{
+		SetError("VPO_OpenMap called without any loaded map");
+		return -1;
+	}
+
+	ClearError();
+
+	// close any previously loaded map
+	VPO_CloseMap();
+
+	if (vpo::W_CheckNumForName(map_name) < 0)
+	{
+		SetError("No such map in wad: %s", map_name);
+		return -1;
+	}
+
+	vpo::P_SetupLevel(map_name);
+
+	return 0;  // OK !
+}
+
+
+void APIENTRY VPO_FreeWAD(void)
+{
+	VPO_CloseMap();
+
+	vpo::W_RemoveFile();
+}
+
+
+void APIENTRY VPO_CloseMap(void)
+{
+	ClearError();
+
+	last_x = -77777;
+	last_y = -77777;
+	last_sector = NULL;
+
+	vpo::P_FreeLevelData();
+}
+
+
+const char* APIENTRY VPO_GetMapName(unsigned int index)
+{
+	static char buffer[16];
+
+	for (unsigned int lump_i = 0 ; lump_i < vpo::numlumps ; lump_i++)
+	{
+		if (! vpo::lumpinfo[lump_i].is_map_header)
+			continue;
+
+		if (index == 0)
+		{
+			// found it
+			memcpy(buffer, vpo::lumpinfo[lump_i].name, 8);
+			buffer[8] = 0;
+
+			return buffer;
+		}
+		
+		index--;
+	}
+
+	// not found
+	return NULL;
+}
+
+
+int APIENTRY VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *y2)
+{
+	if (index >= (unsigned int)vpo::numlines)
+		return -1;
+	
+	const vpo::line_t *L = &vpo::lines[index];
+
+	*x1 = L->v1->x >> FRACBITS;
+	*y1 = L->v1->y >> FRACBITS;
+
+	*x2 = L->v2->x >> FRACBITS;
+	*y2 = L->v2->y >> FRACBITS;
+
+	return L->backsector ? 2 : 1;
+}
+
+
+//------------------------------------------------------------------------
+
+int APIENTRY VPO_TestSpot(int x, int y, int dz, int angle,
+                 int *num_visplanes, int *num_drawsegs,
+                 int *num_openings,  int *num_solidsegs)
+{
+	// the actual spot we will use
+	// (this prevents issues with X_SectorForPoint getting the wrong
+	//  value when the casted ray hits a vertex)
+	vpo::fixed_t rx = (x << FRACBITS) + (FRACUNIT / 2);
+	vpo::fixed_t ry = (y << FRACBITS) + (FRACUNIT / 2);
+
+	vpo::sector_t *sec;
+
+	// optimization: we cache the last sector lookup
+	if (x == last_x && y == last_y)
+		sec = last_sector;
+	else
+	{
+		sec = vpo::X_SectorForPoint(rx, ry);
+
+		last_x = x;
+		last_y = y;
+		last_sector = sec;
+	}
+
+	if (! sec)
+		return RESULT_IN_VOID;
+	
+	vpo::fixed_t rz;
+	
+	if (dz < 0)
+		rz = sec->ceilingheight + (dz << FRACBITS);
+	else
+		rz = sec->floorheight + (dz << FRACBITS);
+
+	if (rz <= sec->floorheight || rz >= sec->ceilingheight)
+		return RESULT_BAD_Z;
+
+	// convert angle to the 32-bit BAM representation
+	if (angle == 360)
+		angle = 0;
+
+	vpo::fixed_t ang2 = vpo::FixedDiv(angle << FRACBITS, 360 << FRACBITS);
+
+	vpo::angle_t r_ang = (vpo::angle_t) (ang2 << 16);
+
+	int result = RESULT_OK;
+
+	// perform a no-draw render and see how many visplanes were needed
+	try
+	{
+		vpo::R_RenderView(rx, ry, rz, r_ang);
+	}
+	catch (vpo::overflow_exception& e)
+	{
+		result = RESULT_OVERFLOW;
+	}
+
+	*num_visplanes = MAX(*num_visplanes, vpo::total_visplanes);
+	*num_drawsegs  = MAX(*num_drawsegs,  vpo::total_drawsegs);
+	*num_openings  = MAX(*num_openings,  vpo::total_openings);
+	*num_solidsegs = MAX(*num_solidsegs, vpo::max_solidsegs);
+
+	return result;
+}
+
+
+//------------------------------------------------------------------------
+
+#ifdef VPO_TEST_PROGRAM
+
+#define EYE_HEIGHT  41
+
+int main(int argc, char **argv)
+{
+	printf("----------------\n");
+	printf("VPO TEST PROGRAM\n");
+	printf("----------------\n");
+	printf("\n");
+
+	if (argc < 5 ||
+	    (strcmp (argv[1], "-h") == 0 ||
+	     strcmp (argv[1], "--help") == 0 ||
+	     strcmp (argv[1], "/?") == 0) )
+	{
+		printf("Usage: vpotest file.wad MAP01 x y angle\n");
+		fflush(stdout);
+		return 0;
+	}
+
+	const char *filename = argv[1];
+	const char *map = argv[2];
+
+	int x = atoi(argv[3]);
+	int y = atoi(argv[4]);
+	int angle = atoi(argv[5]);
+
+	printf("Loading file: %s [%s]\n", filename, map);
+
+	if (VPO_LoadWAD(filename) != 0)
+	{
+		printf("ERROR: %s\n", VPO_GetError());
+		fflush(stdout);
+		return 1;
+	}
+
+	if (VPO_OpenMap(map) != 0)
+	{
+		printf("ERROR: %s\n", VPO_GetError());
+		fflush(stdout);
+		VPO_FreeWAD();
+		return 1;
+	}
+
+	int vp_num = VPO_TestSpot(TEST_VISPLANES, x, y, EYE_HEIGHT, angle);
+
+	printf("\n");
+	printf("Visplanes @ (%d %d) ---> %d\n", x, y, vp_num);
+	fflush(stdout);
+
+	VPO_CloseMap();
+	VPO_FreeWAD();
+
+	return 0;
+}
+
+#endif // VPO_TEST_PROGRAM
+
+//--- editor settings ---
+// vi:ts=4:sw=4:noexpandtab
diff --git a/Source/Plugins/vpo_dll/vpo_stuff.cc b/Source/Plugins/vpo_dll/vpo_stuff.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d56b92b9f3611d5ed30f7f1b371ce8aada4ddbfd
--- /dev/null
+++ b/Source/Plugins/vpo_dll/vpo_stuff.cc
@@ -0,0 +1,113 @@
+//------------------------------------------------------------------------
+//  VPO_LIB : misc stuff
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 1993-1996 Id Software, Inc.
+//  Copyright (C) 2005 Simon Howard
+//  Copyright (C) 2012 Andrew Apted
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+void I_Error (const char *error, ...)
+{
+	va_list	argptr;
+
+	va_start(argptr, error);
+	vfprintf(stderr, error, argptr);
+	va_end(argptr);
+
+	fprintf(stderr, "\n\n");
+	fflush(stderr);
+
+	exit(-1);
+}
+
+
+static int ClosestLine_CastingHoriz(fixed_t x, fixed_t y, int *side)
+{
+	int     best_match = -1;
+	fixed_t best_dist  = 32000 << FRACBITS;
+
+	for (int n = 0 ; n < numlines ; n++)
+	{
+		fixed_t ly1 = lines[n].v1->y;
+		fixed_t ly2 = lines[n].v2->y;
+
+		// ignore purely horizontal lines
+		if (ly1 == ly2)
+			continue;
+
+		// does the linedef cross the horizontal ray?
+		if ( (y < ly1) && (y < ly2) ) continue;
+		if ( (y > ly1) && (y > ly2) ) continue;
+
+		fixed_t lx1 = lines[n].v1->x;
+		fixed_t lx2 = lines[n].v2->x;
+
+		fixed_t quot = FixedDiv(y - ly1, ly2 - ly1);
+		fixed_t dist = lx1 - x + FixedMul(lx2 - lx1, quot);
+
+		if (abs(dist) < best_dist)
+		{
+			best_match = n;
+			best_dist  = abs(dist);
+
+			if (side)
+			{
+				if (best_dist < FRACUNIT / 8)
+					*side = 0;  // on the line
+				else if ( (ly1 > ly2) == (dist > 0))
+					*side = 1;  // right side
+				else
+					*side = -1; // left side
+			}
+		}
+	}
+
+	return best_match;
+}
+
+
+sector_t * X_SectorForPoint(fixed_t x, fixed_t y)
+{
+	/* hack, hack...  I look for the first LineDef crossing
+	   an horizontal half-line drawn from the cursor */
+
+	int sd = 0;
+	int ld = ClosestLine_CastingHoriz(x, y, &sd);
+
+	// VOID checks
+	if (ld < 0)
+		return NULL;
+
+	if (lines[ld].sidenum[sd <= 0 ? 1 : 0] < 0)
+		return NULL;
+	
+	// get sector as DOOM would
+	// (need this to handle self-referencing linedef tricks)
+	subsector_t *sub = R_PointInSubsector(x, y); 
+
+	return sub->sector;
+}
+
+
+} // namespace vpo
+
+//--- editor settings ---
+// vi:ts=4:sw=4:noexpandtab
diff --git a/Source/Plugins/vpo_dll/w_file.cc b/Source/Plugins/vpo_dll/w_file.cc
new file mode 100644
index 0000000000000000000000000000000000000000..68e6adf7bec632c05db92699abaaea6727ada921
--- /dev/null
+++ b/Source/Plugins/vpo_dll/w_file.cc
@@ -0,0 +1,85 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2008 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	WAD I/O functions.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+wad_file_t *W_OpenFile(const char *path)
+{
+    wad_file_t *result;
+
+    FILE *fstream = fopen(path, "rb");
+
+    if (fstream == NULL)
+    {
+        return NULL;
+    }
+
+    // Create a new wad_file_t to hold the file handle.
+
+    result = new wad_file_t;
+
+    result->fstream = fstream;
+
+//    result->length = M_FileLength(fstream);
+
+    return result;
+}
+
+
+void W_CloseFile(wad_file_t *wad)
+{
+    fclose(wad->fstream);
+
+    delete wad;
+}
+
+
+// Read data from the specified position in the file into the 
+// provided buffer.  Returns the number of bytes read.
+
+size_t W_Read(wad_file_t *wad, unsigned int offset,
+              void *buffer, size_t buffer_len)
+{
+    size_t result;
+
+    // Jump to the specified position in the file.
+
+    fseek(wad->fstream, offset, SEEK_SET);
+
+    // Read into the buffer.
+
+    result = fread(buffer, 1, buffer_len, wad->fstream);
+
+    return result;
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/w_file.h b/Source/Plugins/vpo_dll/w_file.h
new file mode 100644
index 0000000000000000000000000000000000000000..22266706385a51d0971f1f81c27a275fe94aaf41
--- /dev/null
+++ b/Source/Plugins/vpo_dll/w_file.h
@@ -0,0 +1,55 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2008 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	WAD I/O functions.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __W_FILE__
+#define __W_FILE__
+
+#include <stdio.h>
+#include "doomtype.h"
+
+typedef struct _wad_file_s
+{
+    FILE *fstream;
+
+} wad_file_t;
+
+// Open the specified file. Returns a pointer to a new wad_file_t 
+// handle for the WAD file, or NULL if it could not be opened.
+
+wad_file_t *W_OpenFile(const char *path);
+
+// Close the specified WAD file.
+
+void W_CloseFile(wad_file_t *wad);
+
+// Read data from the specified file into the provided buffer.  The
+// data is read from the specified offset from the start of the file.
+// Returns the number of bytes read.
+
+size_t W_Read(wad_file_t *wad, unsigned int offset,
+              void *buffer, size_t buffer_len);
+
+#endif /* #ifndef __W_FILE__ */
diff --git a/Source/Plugins/vpo_dll/w_wad.cc b/Source/Plugins/vpo_dll/w_wad.cc
new file mode 100644
index 0000000000000000000000000000000000000000..87fbfd07988805daa1c590956d02a87030f1f82c
--- /dev/null
+++ b/Source/Plugins/vpo_dll/w_wad.cc
@@ -0,0 +1,359 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	Handles WAD file header, directory, lump I/O.
+//
+//-----------------------------------------------------------------------------
+
+#include "vpo_local.h"
+
+namespace vpo
+{
+
+
+typedef struct
+{
+    // Should be "IWAD" or "PWAD".
+    char		identification[4];		
+    int			numlumps;
+    int			infotableofs;
+} PACKEDATTR wadinfo_t;
+
+
+typedef struct
+{
+    int			filepos;
+    int			size;
+    char		name[8];
+} PACKEDATTR filelump_t;
+
+//
+// GLOBALS
+//
+
+// Location of each lump on disk.
+
+lumpinfo_t *lumpinfo;	
+unsigned int numlumps = 0;
+
+
+
+
+//
+// LUMP BASED ROUTINES.
+//
+
+// andrewj: added this to find level names
+bool CheckMapHeader(filelump_t *lumps, int num_after)
+{
+  static const char *level_lumps[] =
+  {
+    "THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES",
+    "SEGS", "SSECTORS", "NODES", "SECTORS",
+
+    NULL // end of list
+  };
+
+  if (num_after < 4)
+    return false;
+
+  int seen_mask  = 0;
+  int seen_count = 0;
+
+  for (int i = 0 ; level_lumps[i] ; i++)
+  {
+    const char *name = level_lumps[i];
+
+    // level lumps are never valid map header names
+    if (strncmp(lumps[0].name, name, 8) == 0)
+      return false;
+
+    for (int pos = 1 ; pos <= 4 ; pos++)
+    {
+      if (strncmp(lumps[pos].name, name, 8) == 0)
+      {
+        int mask = 1 << i;
+
+        // check if name was duplicated
+        if (seen_mask & mask)
+          return false;
+
+        seen_mask |= mask;
+        seen_count += 1;
+      }
+    }
+
+    // found enough level lumps
+    if (seen_count >= 4)
+      return true;
+  }
+
+  return false;
+}
+
+
+//
+// W_AddFile
+//
+// All files are optional, but at least one file must be
+//  found (PWAD, if all required lumps are present).
+// Files with a .wad extension are wadlink files
+//  with multiple lumps.
+// Other files are single lumps with the base filename
+//  for the lump name.
+
+wad_file_t *W_AddFile (const char *filename)
+{
+    wadinfo_t header;
+    lumpinfo_t *lump_p;
+    unsigned int i;
+    wad_file_t *wad_file;
+    int length;
+    int startlump;
+    filelump_t *fileinfo;
+    filelump_t *filerover;
+    
+    // open the file and add to directory
+
+    wad_file = W_OpenFile(filename);
+
+    if (wad_file == NULL)
+    {
+///	printf (" couldn't open %s\n", filename);
+	return NULL;
+    }
+
+    startlump = numlumps;
+	
+    W_Read(wad_file, 0, &header, sizeof(header));
+
+	if (strncmp(header.identification,"IWAD",4))
+	{
+	    // Homebrew levels?
+	    if (strncmp(header.identification,"PWAD",4))
+	    {
+		I_Error ("Wad file %s doesn't have IWAD "
+			 "or PWAD id\n", filename);
+	    }
+	    
+	    // ???modifiedgame = true;		
+	}
+
+	header.numlumps = LONG(header.numlumps);
+	header.infotableofs = LONG(header.infotableofs);
+
+	length = header.numlumps * sizeof(filelump_t);
+
+	fileinfo = new filelump_t[header.numlumps];
+
+  W_Read(wad_file, header.infotableofs, fileinfo, length);
+	numlumps += header.numlumps;
+
+
+    // Fill in lumpinfo
+    lumpinfo = (lumpinfo_t *)realloc(lumpinfo, numlumps * sizeof(lumpinfo_t));
+
+    if (lumpinfo == NULL)
+    {
+	I_Error ("Couldn't realloc lumpinfo");
+    }
+
+    lump_p = &lumpinfo[startlump];
+	
+    filerover = fileinfo;
+
+    for (i=startlump; i<numlumps; ++i)
+    {
+      lump_p->wad_file = wad_file;
+      lump_p->position = LONG(filerover->filepos);
+      lump_p->size = LONG(filerover->size);
+
+      strncpy(lump_p->name, filerover->name, 8);
+
+      lump_p->is_map_header = CheckMapHeader(filerover, numlumps - i - 1);
+
+        ++lump_p;
+        ++filerover;
+    }
+	
+    delete[] fileinfo;
+
+    return wad_file;
+}
+
+
+void W_RemoveFile(void)
+{
+    if (lumpinfo)
+    {
+        // andrewj: horrible hack, assumes a single wad file
+        W_CloseFile(lumpinfo[0].wad_file);
+
+        free(lumpinfo);
+
+        lumpinfo = NULL;
+        numlumps = 0;
+    }
+}
+
+
+
+//
+// W_NumLumps
+//
+int W_NumLumps (void)
+{
+    return numlumps;
+}
+
+
+//
+// W_CheckNumForName
+// Returns -1 if name not found.
+//
+
+int W_CheckNumForName (const char* name)
+{
+    int i;
+
+    {
+        // scan backwards so patch lump files take precedence
+
+        for (i=numlumps-1; i >= 0; --i)
+        {
+            if (!strncasecmp(lumpinfo[i].name, name, 8))
+            {
+                return i;
+            }
+        }
+    }
+
+    // TFB. Not found.
+
+    return -1;
+}
+
+
+//
+// W_GetNumForName
+// Calls W_CheckNumForName, but bombs out if not found.
+//
+int W_GetNumForName (const char* name)
+{
+    int	i;
+
+    i = W_CheckNumForName (name);
+    
+    if (i < 0)
+    {
+        I_Error ("W_GetNumForName: %s not found!", name);
+    }
+ 
+    return i;
+}
+
+
+//
+// W_LumpLength
+// Returns the buffer size needed to load the given lump.
+//
+int W_LumpLength (unsigned int lump)
+{
+    if (lump >= numlumps)
+    {
+	I_Error ("W_LumpLength: %i >= numlumps", lump);
+    }
+
+    return lumpinfo[lump].size;
+}
+
+
+
+//
+// W_ReadLump
+// Loads the lump into the given buffer,
+//  which must be >= W_LumpLength().
+//
+void W_ReadLump(unsigned int lump, void *dest)
+{
+    int c;
+    lumpinfo_t *l;
+	
+    if (lump >= numlumps)
+    {
+	I_Error ("W_ReadLump: %i >= numlumps", lump);
+    }
+
+    l = lumpinfo+lump;
+	
+///    I_BeginRead ();
+	
+    c = W_Read(l->wad_file, l->position, dest, l->size);
+
+    if (c < l->size)
+    {
+	I_Error ("W_ReadLump: only read %i of %i on lump %i",
+		 c, l->size, lump);	
+    }
+
+///    I_EndRead ();
+}
+
+
+
+//
+// W_LoadLump
+//
+// Load a lump into memory and return a pointer to a buffer containing
+// the lump data.
+//
+
+byte * W_LoadLump(int lumpnum)
+{
+    byte *result;
+    lumpinfo_t *lump;
+
+    if ((unsigned)lumpnum >= numlumps)
+    {
+	I_Error ("W_LoadLump: %i >= numlumps", lumpnum);
+    }
+
+    lump = &lumpinfo[lumpnum];
+
+    // load it now
+
+    result = new byte[W_LumpLength(lumpnum) + 1];
+
+    W_ReadLump (lumpnum, result);
+
+    return result;
+}
+
+
+void W_FreeLump(byte * data)
+{
+    delete[] data;
+}
+
+
+} // namespace vpo
+
diff --git a/Source/Plugins/vpo_dll/w_wad.h b/Source/Plugins/vpo_dll/w_wad.h
new file mode 100644
index 0000000000000000000000000000000000000000..440bd7a7f87c74bf27c971ae3a1ecb821bac5999
--- /dev/null
+++ b/Source/Plugins/vpo_dll/w_wad.h
@@ -0,0 +1,79 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//	WAD I/O functions.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __W_WAD__
+#define __W_WAD__
+
+#include <stdio.h>
+
+#include "doomtype.h"
+#include "w_file.h"
+
+
+//
+// TYPES
+//
+
+//
+// WADFILE I/O related stuff.
+//
+
+typedef struct lumpinfo_s lumpinfo_t;
+
+struct lumpinfo_s
+{
+    char	name[8];
+    wad_file_t *wad_file;
+    int		position;
+    int		size;
+    bool  is_map_header;  // e.g. MAP01 or E1M1
+
+    // Used for hash table lookups
+
+    lumpinfo_t *next;
+};
+
+
+extern lumpinfo_t *lumpinfo;
+extern unsigned int numlumps;
+
+
+wad_file_t *W_AddFile (const char *filename);
+
+void W_RemoveFile(void);
+
+
+int	W_CheckNumForName (const char* name);
+int	W_GetNumForName (const char* name);
+
+int	W_LumpLength (unsigned int lump);
+
+byte * W_LoadLump(int lumpnum);
+void   W_FreeLump(byte * data);
+
+
+#endif  // __W_WAD__