Compare commits
5 Commits
15ce34ae19
...
d1593f38c5
Author | SHA1 | Date |
---|---|---|
Adrian | d1593f38c5 | |
Adrian | 9cc13f0e8d | |
Adrian | 48929d1fbf | |
Adrian | 35d80a6585 | |
Adrian | ce92d95bd1 |
20
README.md
20
README.md
|
@ -10,25 +10,37 @@ This includes the *Age of Empires* series and *Star Wars: Galactic Battlegrounds
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
* Create maps from bitmaps
|
||||||
* Convert AOE1 Scenario to AOE2 Scenario
|
* Convert AOE1 Scenario to AOE2 Scenario
|
||||||
* Convert a Scenario file to JSON and vice-versa
|
* Convert a Scenario file to JSON and vice-versa
|
||||||
* Decompress and recompress compressed Scenario part for hex editing
|
* Decompress and recompress compressed Scenario part for hex editing
|
||||||
* Dump unit information to easily gather Unit IDs
|
* Dump unit information to easily gather Unit IDs
|
||||||
* Extract Scenario files from Campaign file
|
* Full Campaign file editing
|
||||||
|
|
||||||
## Planned Features
|
## Planned Features
|
||||||
|
|
||||||
* Create maps from bitmaps
|
|
||||||
* Trigger implementation
|
* Trigger implementation
|
||||||
* Full conversion between all Scenario versions
|
* Full conversion between all Scenario versions
|
||||||
(mapping of Unit IDs are needed for this, see Section Contributing)
|
(mapping of Unit IDs are needed for this, see Section Contributing)
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
### Map Generation
|
||||||
|
|
||||||
|
![Generated Map](doc/GeneratedMap.jpg)
|
||||||
|
|
||||||
|
The above map is generated using:
|
||||||
|
|
||||||
|
$ GenieEdit.exe bmp2map files/examples/aoe2x-Empty.scx Europe.scx /tmp/terrain.png /tmp/elevation.png
|
||||||
|
|
||||||
|
The images are taken from [NASA's Blue Marble](http://visibleearth.nasa.gov/) imagery.
|
||||||
|
|
||||||
|
### Scenario Conversion
|
||||||
|
|
||||||
[OpeningMoves-AOE2.scx](files/OpeningMoves-AOE2.scx)
|
[OpeningMoves-AOE2.scx](files/OpeningMoves-AOE2.scx)
|
||||||
is a fully automated conversion of a Scenario file from the AOE1 demo version:
|
is a fully automated conversion of a Scenario file from the AOE1 demo version:
|
||||||
|
|
||||||
$ GenieEdit.exe convert files/examples/aoe2x-Empty.scx "files/examples/aoe1demo-Reigno_1-Opening Moves.scn" files/OpeningMoves-AOE2.scx
|
$ GenieEdit.exe convert "files/examples/aoe1demo-Reigno_1-Opening Moves.scn" files/OpeningMoves-AOE2.scx files/examples/aoe2x-Empty.scx
|
||||||
|
|
||||||
(Stone are set to 100 to be able to build a town center from the beginning.)
|
(Stone are set to 100 to be able to build a town center from the beginning.)
|
||||||
|
|
||||||
|
@ -47,7 +59,7 @@ A unit dump looks like the following:
|
||||||
# Library
|
# Library
|
||||||
|
|
||||||
The namespace `AdrianKousz.GenieEngine` contains classes
|
The namespace `AdrianKousz.GenieEngine` contains classes
|
||||||
to read, write, and manipulate Scenario files.
|
to read, write, and manipulate Scenario and Campaign files.
|
||||||
|
|
||||||
`Scenario` contains all data structures related to a Scenario file.
|
`Scenario` contains all data structures related to a Scenario file.
|
||||||
They are easily understandable.
|
They are easily understandable.
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 80 KiB |
|
@ -19,15 +19,16 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>..\..\bin\Release</OutputPath>
|
<OutputPath>..\..\bin\Release</OutputPath>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<Externalconsole>true</Externalconsole>
|
<Externalconsole>true</Externalconsole>
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="src\Program.cs" />
|
<Compile Include="src\Program.cs" />
|
||||||
|
@ -40,6 +41,11 @@
|
||||||
<Compile Include="src\DumpunitsCommand.cs" />
|
<Compile Include="src\DumpunitsCommand.cs" />
|
||||||
<Compile Include="src\CopymapConverter.cs" />
|
<Compile Include="src\CopymapConverter.cs" />
|
||||||
<Compile Include="src\ConvertCommand.cs" />
|
<Compile Include="src\ConvertCommand.cs" />
|
||||||
|
<Compile Include="src\AddBitmapCommand.cs" />
|
||||||
|
<Compile Include="src\DelBitmapCommand.cs" />
|
||||||
|
<Compile Include="src\PackCommand.cs" />
|
||||||
|
<Compile Include="src\Bmp2MapCommand.cs" />
|
||||||
|
<Compile Include="src\BitmapHelpers.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -65,6 +71,7 @@
|
||||||
<Reference Include="Newtonsoft.Json">
|
<Reference Include="Newtonsoft.Json">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
public class AddBitmapCommand : BaseCommand
|
||||||
|
{
|
||||||
|
override public void Run()
|
||||||
|
{
|
||||||
|
using (var input = File.OpenRead(args[0]))
|
||||||
|
using (var output = File.OpenWrite(args[1]))
|
||||||
|
using (var bmpstream = File.OpenRead(args[2]))
|
||||||
|
{
|
||||||
|
var scn = GenieFile.Deserialize<Scenario>(input);
|
||||||
|
var bmp = (Bitmap)Image.FromStream(bmpstream);
|
||||||
|
var cin = scn.Cinematics;
|
||||||
|
cin.BitmapWidth = bmp.Width;
|
||||||
|
cin.BitmapHeight = bmp.Height;
|
||||||
|
cin.BitmapUnknown = Scenario.ScnCinematics.ExpectedUnknownBitmapTrue;
|
||||||
|
cin.RawBitmap = bmp.ToRawBitmap();
|
||||||
|
GenieFile.Serialize(scn, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public int GetArgumentCount()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetDescription()
|
||||||
|
{
|
||||||
|
return "Add a pregame bitmap";
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Add a pregame bitmap to a scenario."
|
||||||
|
+ "\nThe bitmap has to be indexed, otherwise, the game will probably crash."
|
||||||
|
+ "\nAdditionally, a game-specific palette will be used to display the image."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input scenario> <output scenario> <bitmap>"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
public static class BitmapHelpers
|
||||||
|
{
|
||||||
|
public static unsafe void FillMap(Scenario scn, Bitmap bmp, Bitmap bmp2)
|
||||||
|
{
|
||||||
|
using (var ubmp = new UnsafeBitmap(bmp))
|
||||||
|
using (var ubmp2 = new UnsafeBitmap(bmp2))
|
||||||
|
{
|
||||||
|
var factory = new ScnDefaultFactory();
|
||||||
|
|
||||||
|
Check(ubmp);
|
||||||
|
Check(ubmp2);
|
||||||
|
|
||||||
|
var ptr = ubmp.Scan0;
|
||||||
|
var last = ptr + ubmp.Stride * ubmp.Height;
|
||||||
|
|
||||||
|
var ptr2 = ubmp2.Scan0;
|
||||||
|
var last2 = ptr2 + ubmp2.Stride * ubmp2.Height;
|
||||||
|
|
||||||
|
var map = factory.MakeMap();
|
||||||
|
map.SizeX = ubmp.Width;
|
||||||
|
map.SizeY = ubmp.Height;
|
||||||
|
map.LinearTiles = new Scenario.ScnMap.Tile[map.SizeX * map.SizeY];
|
||||||
|
|
||||||
|
var gaiaunits = new List<Scenario.ScnUnit>();
|
||||||
|
|
||||||
|
var treemapping = new short[256];
|
||||||
|
treemapping[10] = 411;
|
||||||
|
treemapping[13] = 351;
|
||||||
|
treemapping[17] = 414;
|
||||||
|
treemapping[18] = 348;
|
||||||
|
treemapping[19] = 350;
|
||||||
|
treemapping[20] = 349;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
while (ptr < last && ptr2 < last2) {
|
||||||
|
var treeid = treemapping[*ptr];
|
||||||
|
if (treeid != 0) {
|
||||||
|
var unit = factory.MakeUnit();
|
||||||
|
var posy = i / map.SizeX;
|
||||||
|
var posx = i - (posy * map.SizeX);
|
||||||
|
unit.UnitId = treeid;
|
||||||
|
unit.PosX = posx + 0.5f;
|
||||||
|
unit.PosY = posy + 0.5f;
|
||||||
|
unit.Rotation = (short)Util.Math.Rand(0, 13);
|
||||||
|
gaiaunits.Add(unit);
|
||||||
|
}
|
||||||
|
map.LinearTiles[i++] = new Scenario.ScnMap.Tile(*ptr++, (byte)(*ptr2++ / 37), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
scn.Map = map;
|
||||||
|
scn.Units[0] = gaiaunits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Check(UnsafeBitmap ubmp)
|
||||||
|
{
|
||||||
|
if (ubmp.PixelFormat != PixelFormat.Format8bppIndexed)
|
||||||
|
throw new ArgumentException("Unsupported PixelFormat");
|
||||||
|
if (ubmp.Stride != ubmp.Width)
|
||||||
|
throw new NotImplementedException("bmpbit.Stride != bmpbit.Width");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Drawing;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
public class Bmp2MapCommand : BaseCommand
|
||||||
|
{
|
||||||
|
override public void Run()
|
||||||
|
{
|
||||||
|
using (var srcstream = File.OpenRead(args[0]))
|
||||||
|
using (var outstream = File.OpenWrite(args[1]))
|
||||||
|
using (var bmpstream = File.OpenRead(args[2]))
|
||||||
|
using (var bmp2stream = File.OpenRead(args[3]))
|
||||||
|
{
|
||||||
|
var bmp = (Bitmap)Image.FromStream(bmpstream);
|
||||||
|
var bmp2 = (Bitmap)Image.FromStream(bmp2stream);
|
||||||
|
|
||||||
|
var scn = GenieFile.Deserialize<Scenario>(srcstream);
|
||||||
|
BitmapHelpers.FillMap(scn, bmp, bmp2);
|
||||||
|
GenieFile.Serialize(scn, outstream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public int GetArgumentCount()
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetDescription()
|
||||||
|
{
|
||||||
|
return "Generate a scenario map based on bitmaps";
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Generate a scenario map based on bitmaps with automatic forest generation."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nTwo bitmaps need to be specified: One terrain map and one elevation map."
|
||||||
|
+ "\nBoth bitmaps need to be indexed or grayscale."
|
||||||
|
+ "\nThe index/gray values of the first bitmap are translated directly to a terrain ID."
|
||||||
|
+ "\nThe index/gray values of the second bitmap are divided by 37 to generate elevations 0-6."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input scenario> <output scenario> <terrain bitmap> <elevation bitmap>"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
|
||||||
|
|
||||||
namespace AdrianKousz.GenieEngine
|
namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
|
@ -23,5 +22,14 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
return "Recompress a decompressed scenario file";
|
return "Recompress a decompressed scenario file";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Recompress a previously decompressed scenario file."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input binary file> <output scenario>"
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
override public void Run()
|
override public void Run()
|
||||||
{
|
{
|
||||||
using (var refstream = File.OpenRead(args[0]))
|
using (var srcstream = File.OpenRead(args[0]))
|
||||||
using (var srcstream = File.OpenRead(args[1]))
|
using (var outstream = File.OpenWrite(args[1]))
|
||||||
using (var outstream = File.OpenWrite(args[2]))
|
using (var refstream = File.OpenRead(args[2]))
|
||||||
{
|
{
|
||||||
var refscn = GenieFile.Deserialize<Scenario>(refstream);
|
var refscn = GenieFile.Deserialize<Scenario>(refstream);
|
||||||
var srcscn = GenieFile.Deserialize<Scenario>(srcstream);
|
var srcscn = GenieFile.Deserialize<Scenario>(srcstream);
|
||||||
|
@ -22,8 +22,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
srcscn.RawRemaining = refscn.RawRemaining;
|
srcscn.RawRemaining = refscn.RawRemaining;
|
||||||
|
|
||||||
srcscn.PlayerSettings.ForEach(x => {
|
srcscn.PlayerSettings.ForEach(x => {
|
||||||
x.FilenameAI = "RandomGame";
|
x.FilenameAI = x.FilenameCTY = x.FilenamePER = "RandomGame";
|
||||||
x.FilenameCTY = x.FilenamePER = "";
|
|
||||||
x.ScriptAI = x.ScriptCTY = x.ScriptPER = "";
|
x.ScriptAI = x.ScriptCTY = x.ScriptPER = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,8 +47,10 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
return "Convert AOE1 scenario to AOE2"
|
return "Convert AOE1 scenario to AOE2"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "\nThe converter needs an existing AOE2 scenario to start with. Use the following arguments:"
|
+ "\nThe converter needs an existing AOE2 scenario to start with."
|
||||||
+ "\n<AOE2 reference scenario> <AOE1 scenario> <output scenario>"
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<AOE1 scenario> <output scenario> <AOE2 reference scenario>"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,9 @@ namespace AdrianKousz.GenieEngine
|
||||||
// Other Buildings
|
// Other Buildings
|
||||||
109, 68, 103,
|
109, 68, 103,
|
||||||
};
|
};
|
||||||
units.ForEach((i, list) => {
|
units.ForEach(list => {
|
||||||
list.ForEach((j, unit) => {
|
list.ForEach(unit => {
|
||||||
mapping.ForEach((k, buildingid) => {
|
mapping.ForEach(buildingid => {
|
||||||
if (unit.UnitId == buildingid) {
|
if (unit.UnitId == buildingid) {
|
||||||
unit.PosX -= 0.5f;
|
unit.PosX -= 0.5f;
|
||||||
unit.PosY -= 0.5f;
|
unit.PosY -= 0.5f;
|
||||||
|
@ -43,7 +43,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
*/
|
*/
|
||||||
private List<Scenario.ScnUnit>[] ChangeUnits_AOE1_AOE2(IList<Scenario.ScnUnit>[] units)
|
private List<Scenario.ScnUnit>[] ChangeUnits_AOE1_AOE2(IList<Scenario.ScnUnit>[] units)
|
||||||
{
|
{
|
||||||
var array = new int[] {
|
var mapping = new short[] {
|
||||||
// Resources
|
// Resources
|
||||||
66, 66,
|
66, 66,
|
||||||
59, 59,
|
59, 59,
|
||||||
|
@ -139,22 +139,15 @@ namespace AdrianKousz.GenieEngine
|
||||||
114, 114,
|
114, 114,
|
||||||
121, 121,
|
121, 121,
|
||||||
129, 129,
|
129, 129,
|
||||||
};
|
}.ToDictionary();
|
||||||
var mapping = new Dictionary<short, short>();
|
|
||||||
var ai = 0;
|
|
||||||
while (ai < array.Length)
|
|
||||||
mapping.Add((short)array[ai++], (short)array[ai++]);
|
|
||||||
|
|
||||||
var result = new List<Scenario.ScnUnit>[Scenario.NumPlayerSections].Fill();
|
var result = units.Map(list => {
|
||||||
|
return list
|
||||||
units.ForEach((i, list) => {
|
.Filter(unit => mapping.ContainsKey(unit.UnitId))
|
||||||
list.ForEach((j, unit) => {
|
.ForEach(unit => {
|
||||||
if (mapping.ContainsKey(unit.UnitId)) {
|
|
||||||
unit.UnitId = mapping[unit.UnitId];
|
unit.UnitId = mapping[unit.UnitId];
|
||||||
result[i].Add(unit);
|
}).ToList();
|
||||||
}
|
}).ToArray();
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -164,8 +157,8 @@ namespace AdrianKousz.GenieEngine
|
||||||
*/
|
*/
|
||||||
private void ChangeTiles_AOE1_AOE2(IList<Scenario.ScnUnit>[] units, Scenario.ScnMap map)
|
private void ChangeTiles_AOE1_AOE2(IList<Scenario.ScnUnit>[] units, Scenario.ScnMap map)
|
||||||
{
|
{
|
||||||
units.ForEach((i, list) => {
|
units.ForEach(list => {
|
||||||
list.ForEach((j, unit) => {
|
list.ForEach(unit => {
|
||||||
var posx = (int)(unit.PosX - 0.5);
|
var posx = (int)(unit.PosX - 0.5);
|
||||||
var posy = (int)(unit.PosY - 0.5);
|
var posy = (int)(unit.PosY - 0.5);
|
||||||
var linearpos = posy * map.SizeX + posx;
|
var linearpos = posy * map.SizeX + posx;
|
||||||
|
@ -203,12 +196,11 @@ namespace AdrianKousz.GenieEngine
|
||||||
var treeids = new int[] {
|
var treeids = new int[] {
|
||||||
411, 351, 414, 350, 348, 349,
|
411, 351, 414, 350, 348, 349,
|
||||||
};
|
};
|
||||||
units.ForEach((i, list) => {
|
units.ForEach(list => {
|
||||||
list.ForEach((j, unit) => {
|
list.ForEach(unit => {
|
||||||
treeids.ForEach((k, treeid) => {
|
treeids.ForEach(treeid => {
|
||||||
if (unit.UnitId == treeid) {
|
if (unit.UnitId == treeid) {
|
||||||
unit.InitialFrame = (short)Util.Math.Rand(0, 13); // Whats the maximum?
|
unit.Rotation = (short)Util.Math.Rand(0, 13); // Whats the maximum?
|
||||||
unit.Rotation = unit.InitialFrame;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,16 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
override public string GetDescription()
|
override public string GetDescription()
|
||||||
{
|
{
|
||||||
return "Decompress a scenario file for hex editing";
|
return "Decompress a scenario file";
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Decompress a scenario file for hex editing."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input scenario> <output binary file>"
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Drawing;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
public class DelBitmapCommand : BaseCommand
|
||||||
|
{
|
||||||
|
override public void Run()
|
||||||
|
{
|
||||||
|
using (var input = File.OpenRead(args[0]))
|
||||||
|
using (var output = File.OpenWrite(args[1]))
|
||||||
|
{
|
||||||
|
var scn = GenieFile.Deserialize<Scenario>(input);
|
||||||
|
var cin = scn.Cinematics;
|
||||||
|
cin.BitmapWidth = 0;
|
||||||
|
cin.BitmapHeight = 0;
|
||||||
|
cin.BitmapUnknown = Scenario.ScnCinematics.ExpectedUnknownBitmapFalse;
|
||||||
|
cin.RawBitmap = new byte[0];
|
||||||
|
GenieFile.Serialize(scn, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public int GetArgumentCount()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetDescription()
|
||||||
|
{
|
||||||
|
return "Remove the pregame bitmap";
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Remove the pregame bitmap from a scenario."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input scenario> <output scenario>"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,9 +17,10 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
Console.WriteLine("{0,-8} {1,-8} {2,-8} {3}", "ID", "UnitID", "TileID", "Position");
|
Console.WriteLine("{0,-8} {1,-8} {2,-8} {3}", "ID", "UnitID", "TileID", "Position");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
scn.Units.ForEach((i, list) => {
|
var i = 0;
|
||||||
Console.WriteLine("Units of player {0}:", i);
|
scn.Units.ForEach(list => {
|
||||||
list.ForEach((j, unit) => {
|
Console.WriteLine("Units of player {0}:", i++);
|
||||||
|
list.ForEach(unit => {
|
||||||
var tilex = (int)(unit.PosX - 0.5);
|
var tilex = (int)(unit.PosX - 0.5);
|
||||||
var tiley = (int)(unit.PosY - 0.5);
|
var tiley = (int)(unit.PosY - 0.5);
|
||||||
var tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex];
|
var tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex];
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
namespace AdrianKousz.GenieEngine
|
namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
|
@ -6,9 +8,17 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
override public void Run()
|
override public void Run()
|
||||||
{
|
{
|
||||||
using (var file = File.OpenRead(args[0])) {
|
using (var file = File.OpenRead(args[0]))
|
||||||
var reader = new CpnReader(file);
|
{
|
||||||
reader.ExtractFiles();
|
var cpn = GenieFile.Deserialize<Campaign>(file);
|
||||||
|
Console.WriteLine("Extracting \"{0}\"...", cpn.Name);
|
||||||
|
cpn.Files.ForEach(x => {
|
||||||
|
using (var outfile = File.OpenWrite(x.Filename))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Extracting \"{0}\" to \"{1}\"...", x.Name, x.Filename);
|
||||||
|
outfile.Write(x.RawData);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +29,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
override public string GetDescription()
|
override public string GetDescription()
|
||||||
{
|
{
|
||||||
return "Extract scenarios from campaign file";
|
return "Extract files from campaign file";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,16 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
override public string GetDescription()
|
override public string GetDescription()
|
||||||
{
|
{
|
||||||
return "Read a JSON file and save as scenario";
|
return "Convert a JSON file to a scenario";
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Read a Scenario structure formatted as JSON and save it as a Scenario."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input json> <output scenario>"
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
public class PackCommand : BaseCommand
|
||||||
|
{
|
||||||
|
override public void Run()
|
||||||
|
{
|
||||||
|
var files = new List<Campaign.CpnFile>();
|
||||||
|
for (var i = 2; i < args.Length; i++) {
|
||||||
|
var file = new Campaign.CpnFile();
|
||||||
|
file.Filename = args[i];
|
||||||
|
file.Name = Path.GetFileNameWithoutExtension(file.Filename);
|
||||||
|
using (var stream = File.OpenRead(file.Filename))
|
||||||
|
using (var memorystream = new MemoryStream())
|
||||||
|
{
|
||||||
|
stream.CopyTo(memorystream);
|
||||||
|
file.RawData = memorystream.ToArray();
|
||||||
|
}
|
||||||
|
files.Add(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cpn = new Campaign();
|
||||||
|
cpn.Files = files;
|
||||||
|
cpn.Name = args[1];
|
||||||
|
cpn.Version = "1.00";
|
||||||
|
|
||||||
|
using (var file = File.OpenWrite(args[0]))
|
||||||
|
{
|
||||||
|
GenieFile.Serialize(cpn, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public int GetArgumentCount()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetDescription()
|
||||||
|
{
|
||||||
|
return "Pack files into a campaign file";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
System.Threading.Thread.CurrentThread.Name = "main";
|
System.Threading.Thread.CurrentThread.Name = "main";
|
||||||
|
Log.SetUncaughtExceptionHandler();
|
||||||
|
|
||||||
if (System.Diagnostics.Debugger.IsAttached) {
|
if (System.Diagnostics.Debugger.IsAttached) {
|
||||||
debug();
|
debug();
|
||||||
|
@ -26,12 +27,16 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
var result = new Dictionary<string, ICommand<string[]>>();
|
var result = new Dictionary<string, ICommand<string[]>>();
|
||||||
result.Add("convert", new ConvertCommand());
|
result.Add("convert", new ConvertCommand());
|
||||||
|
result.Add("bmp2map", new Bmp2MapCommand());
|
||||||
|
result.Add("addbmp", new AddBitmapCommand());
|
||||||
|
result.Add("delbmp", new DelBitmapCommand());
|
||||||
result.Add("compress", new CompressCommand());
|
result.Add("compress", new CompressCommand());
|
||||||
result.Add("decompress", new DecompressCommand());
|
result.Add("decompress", new DecompressCommand());
|
||||||
result.Add("extract", new ExtractCommand());
|
|
||||||
result.Add("tojson", new ToJsonCommand());
|
result.Add("tojson", new ToJsonCommand());
|
||||||
result.Add("fromjson", new FromJsonCommand());
|
result.Add("fromjson", new FromJsonCommand());
|
||||||
result.Add("dumpunits", new DumpunitsCommand());
|
result.Add("dumpunits", new DumpunitsCommand());
|
||||||
|
result.Add("extract", new ExtractCommand());
|
||||||
|
result.Add("pack", new PackCommand());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,16 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
override public string GetDescription()
|
override public string GetDescription()
|
||||||
{
|
{
|
||||||
return "Dump a scenario file to JSON";
|
return "Convert a scenario to a JSON file";
|
||||||
|
}
|
||||||
|
|
||||||
|
override public string GetHelp()
|
||||||
|
{
|
||||||
|
return "Save a Scenario structure formatted as JSON."
|
||||||
|
+ "\n"
|
||||||
|
+ "\nParameters:"
|
||||||
|
+ "\n<input scenario> <output json>"
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
namespace AdrianKousz.GenieEngine
|
namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
|
@ -11,11 +12,11 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
EnsureLittleEndian();
|
EnsureLittleEndian();
|
||||||
|
|
||||||
var temp = new byte[40];
|
var temp = input.ReadBytes(40);
|
||||||
input.Read(temp, 0, temp.Length);
|
|
||||||
|
|
||||||
var dibHeaderLength = BitConverter.ToInt32(temp, 0);
|
var dibHeaderLength = BitConverter.ToInt32(temp, 0);
|
||||||
var paletteLength = BitConverter.ToInt32(temp, 32) * 4;
|
var bitDepth = BitConverter.ToInt32(temp, 14);
|
||||||
|
var paletteLength = bitDepth > 8 ? 0 : (1 << bitDepth) * 4;
|
||||||
var pixelArrayLength = BitConverter.ToInt32(temp, 20);
|
var pixelArrayLength = BitConverter.ToInt32(temp, 20);
|
||||||
var resultLength = dibHeaderLength + paletteLength + pixelArrayLength;
|
var resultLength = dibHeaderLength + paletteLength + pixelArrayLength;
|
||||||
|
|
||||||
|
@ -37,7 +38,8 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
var bmpHeaderLength = 14;
|
var bmpHeaderLength = 14;
|
||||||
var dibHeaderLength = BitConverter.ToInt32(input, 0);
|
var dibHeaderLength = BitConverter.ToInt32(input, 0);
|
||||||
var paletteLength = BitConverter.ToInt32(input, 32) * 4;
|
var bitDepth = BitConverter.ToInt32(input, 14);
|
||||||
|
var paletteLength = bitDepth > 8 ? 0 : (1 << bitDepth) * 4;
|
||||||
var pixelArrayOffsetOutput = bmpHeaderLength + dibHeaderLength + paletteLength;
|
var pixelArrayOffsetOutput = bmpHeaderLength + dibHeaderLength + paletteLength;
|
||||||
var resultLength = input.Length + bmpHeaderLength;
|
var resultLength = input.Length + bmpHeaderLength;
|
||||||
|
|
||||||
|
@ -61,10 +63,12 @@ namespace AdrianKousz.GenieEngine
|
||||||
var bmpHeaderLength = 14;
|
var bmpHeaderLength = 14;
|
||||||
var tempstream = new MemoryStream();
|
var tempstream = new MemoryStream();
|
||||||
input.Save(tempstream, ImageFormat.Bmp);
|
input.Save(tempstream, ImageFormat.Bmp);
|
||||||
|
tempstream.Dispose();
|
||||||
var temp = tempstream.ToArray();
|
var temp = tempstream.ToArray();
|
||||||
|
|
||||||
var dibHeaderLength = BitConverter.ToInt32(temp, 0 + bmpHeaderLength);
|
var dibHeaderLength = BitConverter.ToInt32(temp, 0 + bmpHeaderLength);
|
||||||
var paletteLength = BitConverter.ToInt32(temp, 32 + bmpHeaderLength) * 4;
|
var bitDepth = BitConverter.ToInt32(temp, 14 + bmpHeaderLength);
|
||||||
|
var paletteLength = bitDepth > 8 ? 0 : (1 << bitDepth) * 4;
|
||||||
var pixelArrayOffsetInput = BitConverter.ToInt32(temp, 10);
|
var pixelArrayOffsetInput = BitConverter.ToInt32(temp, 10);
|
||||||
var pixelArrayLength = temp.Length - pixelArrayOffsetInput;
|
var pixelArrayLength = temp.Length - pixelArrayOffsetInput;
|
||||||
var resultLength = dibHeaderLength + paletteLength + pixelArrayLength;
|
var resultLength = dibHeaderLength + paletteLength + pixelArrayLength;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
public class Campaign
|
||||||
|
{
|
||||||
|
public String Version;
|
||||||
|
public String Name;
|
||||||
|
public IList<CpnFile> Files;
|
||||||
|
|
||||||
|
public class CpnFile
|
||||||
|
{
|
||||||
|
public String Name;
|
||||||
|
public String Filename;
|
||||||
|
public byte[] RawData;
|
||||||
|
public Scenario Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +0,0 @@
|
||||||
using System.IO;
|
|
||||||
using AdrianKousz.Util;
|
|
||||||
|
|
||||||
namespace AdrianKousz.GenieEngine
|
|
||||||
{
|
|
||||||
public class CpnReader
|
|
||||||
{
|
|
||||||
private static readonly string TAG = typeof(CpnReader).Name;
|
|
||||||
|
|
||||||
private ExtendedBinaryReader reader;
|
|
||||||
|
|
||||||
public CpnReader(Stream input)
|
|
||||||
{
|
|
||||||
reader = new ExtendedBinaryReader(input, Scenario.Encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ExtractFiles()
|
|
||||||
{
|
|
||||||
var version = reader.ReadString(4);
|
|
||||||
if (!version.Equals("1.00")) {
|
|
||||||
throw new System.NotSupportedException(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
var name = reader.ReadZString(256);
|
|
||||||
var count = reader.ReadInt32();
|
|
||||||
Log.i(TAG, "Extract scenarios from \"{0}\"", name);
|
|
||||||
|
|
||||||
var size = new int[count];
|
|
||||||
var offset = new int[count];
|
|
||||||
var scenname = new string[count];
|
|
||||||
var filename = new string[count];
|
|
||||||
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
size[i] = reader.ReadInt32();
|
|
||||||
offset[i] = reader.ReadInt32();
|
|
||||||
scenname[i] = reader.ReadZString(255);
|
|
||||||
filename[i] = reader.ReadZString(257);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
Log.i(TAG, "Extract scenario {0} \"{1}\" to {2}", i, scenname[i], filename[i]);
|
|
||||||
|
|
||||||
using (var file = File.OpenWrite(filename[i])) {
|
|
||||||
reader.BaseStream.Seek(offset[i], SeekOrigin.Begin);
|
|
||||||
var data = reader.ReadBytes(size[i]);
|
|
||||||
file.Write(data, 0, data.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
internal class CpnSerializerReader
|
||||||
|
{
|
||||||
|
private static readonly string TAG = typeof(CpnSerializerReader).Name;
|
||||||
|
|
||||||
|
public static CpnSerializerReader CreateDefault()
|
||||||
|
{
|
||||||
|
return new CpnSerializerReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CpnSerializerReader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Campaign ReadCampaign(ExtendedBinaryReader reader)
|
||||||
|
{
|
||||||
|
var number = 0;
|
||||||
|
var result = new Campaign();
|
||||||
|
|
||||||
|
result.Version = reader.ReadString(4);
|
||||||
|
if (!result.Version.Equals("1.00")) {
|
||||||
|
Log.w(TAG, "Continue reading unsupported version {0}", result.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Name = reader.ReadZString(256);
|
||||||
|
number = reader.ReadInt32();
|
||||||
|
|
||||||
|
result.Files = new PositionInfo()
|
||||||
|
.CreateList()
|
||||||
|
.Fill(number, () => {
|
||||||
|
return new PositionInfo {
|
||||||
|
Size = reader.ReadInt32(),
|
||||||
|
Offset = reader.ReadInt32(),
|
||||||
|
Name = reader.ReadZString(255),
|
||||||
|
Filename = reader.ReadZString(257),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.Map(x => {
|
||||||
|
var file = new Campaign.CpnFile();
|
||||||
|
reader.BaseStream.Seek(x.Offset, SeekOrigin.Begin);
|
||||||
|
file.RawData = reader.ReadBytes(x.Size);
|
||||||
|
file.Name = x.Name;
|
||||||
|
file.Filename = x.Filename;
|
||||||
|
return file;
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PositionInfo
|
||||||
|
{
|
||||||
|
public int Size;
|
||||||
|
public int Offset;
|
||||||
|
public string Name;
|
||||||
|
public string Filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using AdrianKousz.Util;
|
||||||
|
|
||||||
|
namespace AdrianKousz.GenieEngine
|
||||||
|
{
|
||||||
|
internal class CpnSerializerWriter
|
||||||
|
{
|
||||||
|
private static readonly string TAG = typeof(CpnSerializerWriter).Name;
|
||||||
|
|
||||||
|
public static CpnSerializerWriter CreateDefault()
|
||||||
|
{
|
||||||
|
return new CpnSerializerWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CpnSerializerWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(ExtendedBinaryWriter writer, Campaign value)
|
||||||
|
{
|
||||||
|
var number = 0;
|
||||||
|
|
||||||
|
if (!value.Version.Equals("1.00")) {
|
||||||
|
Log.w(TAG, "Continue writing unsupported version {0}", value.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
var headerSize = 8 + 256;
|
||||||
|
var listingSize = 8 + 255 + 257;
|
||||||
|
var listingLength = listingSize * value.Files.Count;
|
||||||
|
|
||||||
|
number = headerSize + listingLength;
|
||||||
|
|
||||||
|
writer.WriteStringRaw(value.Version);
|
||||||
|
writer.WriteZString(value.Name, 256);
|
||||||
|
writer.Write((Int32)value.Files.Count);
|
||||||
|
|
||||||
|
value.Files.ForEach(x => {
|
||||||
|
writer.Write((Int32)x.RawData.Length);
|
||||||
|
writer.Write((Int32)number);
|
||||||
|
writer.WriteZString(x.Name, 255);
|
||||||
|
writer.WriteZString(x.Filename, 257);
|
||||||
|
number += x.RawData.Length;
|
||||||
|
});
|
||||||
|
|
||||||
|
value.Files.ForEach(x => {
|
||||||
|
writer.Write(x.RawData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,13 +21,22 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
public static void Serialize<T>(T value, Stream output)
|
public static void Serialize<T>(T value, Stream output)
|
||||||
{
|
{
|
||||||
var scenarioValue = value as Scenario;
|
var scnValue = value as Scenario;
|
||||||
if (scenarioValue != null) {
|
if (scnValue != null) {
|
||||||
var scnwriter = ScnSerializerWriter.CreateDefault();
|
var scnwriter = ScnSerializerWriter.CreateDefault();
|
||||||
using (var stream = new NonDisposingStreamWrapper(output))
|
using (var writer = GetWriter(output))
|
||||||
using (var writer = GetWriter(stream))
|
|
||||||
{
|
{
|
||||||
scnwriter.Write(writer, scenarioValue);
|
scnwriter.Write(writer, scnValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cpnValue = value as Campaign;
|
||||||
|
if (cpnValue != null) {
|
||||||
|
var cpnwriter = CpnSerializerWriter.CreateDefault();
|
||||||
|
using (var writer = GetWriter(output))
|
||||||
|
{
|
||||||
|
cpnwriter.Write(writer, cpnValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,13 +70,20 @@ namespace AdrianKousz.GenieEngine
|
||||||
{
|
{
|
||||||
if (type == typeof(Scenario)) {
|
if (type == typeof(Scenario)) {
|
||||||
var scnreader = ScnSerializerReader.CreateDefault();
|
var scnreader = ScnSerializerReader.CreateDefault();
|
||||||
using (var stream = new NonDisposingStreamWrapper(input))
|
using (var reader = GetReader(input))
|
||||||
using (var reader = GetReader(stream))
|
|
||||||
{
|
{
|
||||||
return scnreader.ReadScenario(reader);
|
return scnreader.ReadScenario(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == typeof(Campaign)) {
|
||||||
|
var cpnreader = CpnSerializerReader.CreateDefault();
|
||||||
|
using (var reader = GetReader(input))
|
||||||
|
{
|
||||||
|
return cpnreader.ReadCampaign(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new System.ArgumentException("Unsupported Type");
|
throw new System.ArgumentException("Unsupported Type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,12 +93,12 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
public static ExtendedBinaryReader GetReader(Stream stream)
|
public static ExtendedBinaryReader GetReader(Stream stream)
|
||||||
{
|
{
|
||||||
return new ExtendedBinaryReader(stream, Scenario.Encoding);
|
return new ExtendedBinaryReader(new NonDisposingStreamWrapper(stream), Scenario.Encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExtendedBinaryWriter GetWriter(Stream stream)
|
public static ExtendedBinaryWriter GetWriter(Stream stream)
|
||||||
{
|
{
|
||||||
return new ExtendedBinaryWriter(stream, Scenario.Encoding);
|
return new ExtendedBinaryWriter(new NonDisposingStreamWrapper(stream), Scenario.Encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ScenarioCompression(Stream input, Stream output, bool decompress)
|
public static void ScenarioCompression(Stream input, Stream output, bool decompress)
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
public const Int32 ExpectedUnknown1 = 2;
|
public const Int32 ExpectedUnknown1 = 2;
|
||||||
public const Int32 ExpectedUnknown2 = 0;
|
public const Int32 ExpectedUnknown2 = 0;
|
||||||
public const Int32 ExpectedUnknown3 = 1;
|
public const Int32 ExpectedUnknown3 = 1;
|
||||||
public const SByte ExpectedUnknown4 = 0;
|
public const Byte ExpectedUnknown4 = 0;
|
||||||
public const Single ExpectedUnknown5 = -1;
|
public const Single ExpectedUnknown5 = -1;
|
||||||
|
|
||||||
public String VersionString;
|
public String VersionString;
|
||||||
|
@ -43,7 +43,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
public Int32 Unknown1;
|
public Int32 Unknown1;
|
||||||
public Int32 Unknown2;
|
public Int32 Unknown2;
|
||||||
public Int32 Unknown3;
|
public Int32 Unknown3;
|
||||||
public SByte Unknown4;
|
public Byte Unknown4;
|
||||||
public Single Unknown5;
|
public Single Unknown5;
|
||||||
|
|
||||||
public class ScnPlayerSettings
|
public class ScnPlayerSettings
|
||||||
|
@ -64,7 +64,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
public String ScriptAI;
|
public String ScriptAI;
|
||||||
public String ScriptCTY;
|
public String ScriptCTY;
|
||||||
public String ScriptPER;
|
public String ScriptPER;
|
||||||
public SByte AIType;
|
public Byte AIType;
|
||||||
|
|
||||||
public Int32 ResourceWood;
|
public Int32 ResourceWood;
|
||||||
public Int32 ResourceFood;
|
public Int32 ResourceFood;
|
||||||
|
@ -98,6 +98,9 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
public class ScnCinematics
|
public class ScnCinematics
|
||||||
{
|
{
|
||||||
|
public const Int16 ExpectedUnknownBitmapTrue = -1;
|
||||||
|
public const Int16 ExpectedUnknownBitmapFalse = 1;
|
||||||
|
|
||||||
public String FilenamePregame;
|
public String FilenamePregame;
|
||||||
public String FilenameVictory;
|
public String FilenameVictory;
|
||||||
public String FilenameLoss;
|
public String FilenameLoss;
|
||||||
|
@ -148,13 +151,13 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
public struct Tile
|
public struct Tile
|
||||||
{
|
{
|
||||||
public const Int32 ExpectedUnknown = 0;
|
public const Byte ExpectedUnknown = 0;
|
||||||
|
|
||||||
public SByte Id;
|
public Byte Id;
|
||||||
public SByte Elevation;
|
public Byte Elevation;
|
||||||
public SByte Unknown;
|
public Byte Unknown;
|
||||||
|
|
||||||
public Tile(SByte id, SByte el, SByte un)
|
public Tile(Byte id, Byte el, Byte un)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Elevation = el;
|
Elevation = el;
|
||||||
|
@ -166,7 +169,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
public class ScnUnit
|
public class ScnUnit
|
||||||
{
|
{
|
||||||
public const Single ExpectedUnknown1 = 1;
|
public const Single ExpectedUnknown1 = 1;
|
||||||
public const SByte ExpectedUnknown2 = 2;
|
public const Byte ExpectedUnknown2 = 2;
|
||||||
|
|
||||||
public Single PosX;
|
public Single PosX;
|
||||||
public Single PosY;
|
public Single PosY;
|
||||||
|
@ -176,7 +179,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
public Int16 InitialFrame;
|
public Int16 InitialFrame;
|
||||||
public Int32 GarrisonnedInId;
|
public Int32 GarrisonnedInId;
|
||||||
public Single Unknown1;
|
public Single Unknown1;
|
||||||
public SByte Unknown2;
|
public Byte Unknown2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,12 +50,9 @@ namespace AdrianKousz.GenieEngine
|
||||||
result.UnknownInfo = Scenario.ScnPlayerSettings.ExpectedUnknownInfo;
|
result.UnknownInfo = Scenario.ScnPlayerSettings.ExpectedUnknownInfo;
|
||||||
result.UnknownResource = Scenario.ScnPlayerSettings.ExpectedUnknownResource;
|
result.UnknownResource = Scenario.ScnPlayerSettings.ExpectedUnknownResource;
|
||||||
result.Name = "Player";
|
result.Name = "Player";
|
||||||
result.FilenameAI = "";
|
result.NameStringID = -1;
|
||||||
result.FilenameCTY = "";
|
result.FilenameAI = result.FilenameCTY = result.FilenamePER = "RandomGame";
|
||||||
result.FilenamePER = "";
|
result.ScriptAI = result.ScriptCTY = result.ScriptPER = "";
|
||||||
result.ScriptAI = "";
|
|
||||||
result.ScriptCTY = "";
|
|
||||||
result.ScriptPER = "";
|
|
||||||
result.AIType = 1;
|
result.AIType = 1;
|
||||||
result.ResourceWood = 200;
|
result.ResourceWood = 200;
|
||||||
result.ResourceFood = 200;
|
result.ResourceFood = 200;
|
||||||
|
@ -91,6 +88,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
result.FilenameVictory = "";
|
result.FilenameVictory = "";
|
||||||
result.FilenameLoss = "";
|
result.FilenameLoss = "";
|
||||||
result.FilenameBitmap = "";
|
result.FilenameBitmap = "";
|
||||||
|
result.BitmapUnknown = Scenario.ScnCinematics.ExpectedUnknownBitmapFalse;
|
||||||
result.RawBitmap = new byte[0];
|
result.RawBitmap = new byte[0];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
});
|
});
|
||||||
|
|
||||||
result.Unknown3 = reader.ReadInt32();
|
result.Unknown3 = reader.ReadInt32();
|
||||||
result.Unknown4 = reader.ReadSByte();
|
result.Unknown4 = reader.ReadByte();
|
||||||
result.Unknown5 = reader.ReadSingle();
|
result.Unknown5 = reader.ReadSingle();
|
||||||
|
|
||||||
result.Filename = reader.ReadStringInt16();
|
result.Filename = reader.ReadStringInt16();
|
||||||
|
@ -139,7 +139,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
if (Version >= 1.18f) {
|
if (Version >= 1.18f) {
|
||||||
result.PlayerSettings.ForEach(x => {
|
result.PlayerSettings.ForEach(x => {
|
||||||
x.AIType = reader.ReadSByte();
|
x.AIType = reader.ReadByte();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
result.Map.SizeY = reader.ReadInt32();
|
result.Map.SizeY = reader.ReadInt32();
|
||||||
|
|
||||||
result.Map.LinearTiles = new Scenario.ScnMap.Tile[result.Map.SizeX * result.Map.SizeY]
|
result.Map.LinearTiles = new Scenario.ScnMap.Tile[result.Map.SizeX * result.Map.SizeY]
|
||||||
.Fill(() => new Scenario.ScnMap.Tile(reader.ReadSByte(), reader.ReadSByte(), reader.ReadSByte()));
|
.Fill(() => new Scenario.ScnMap.Tile(reader.ReadByte(), reader.ReadByte(), reader.ReadByte()));
|
||||||
|
|
||||||
// ResourceCopies
|
// ResourceCopies
|
||||||
|
|
||||||
|
@ -248,21 +248,21 @@ namespace AdrianKousz.GenieEngine
|
||||||
|
|
||||||
result.Units.ForEach(x => {
|
result.Units.ForEach(x => {
|
||||||
var count = reader.ReadInt32();
|
var count = reader.ReadInt32();
|
||||||
x.Fill(() => {
|
x.Fill(count, () => {
|
||||||
var unit = factory.MakeUnit();
|
var unit = factory.MakeUnit();
|
||||||
unit.PosX = reader.ReadSingle();
|
unit.PosX = reader.ReadSingle();
|
||||||
unit.PosY = reader.ReadSingle();
|
unit.PosY = reader.ReadSingle();
|
||||||
unit.Unknown1 = reader.ReadSingle();
|
unit.Unknown1 = reader.ReadSingle();
|
||||||
unit.Id = reader.ReadInt32();
|
unit.Id = reader.ReadInt32();
|
||||||
unit.UnitId = reader.ReadInt16();
|
unit.UnitId = reader.ReadInt16();
|
||||||
unit.Unknown2 = reader.ReadSByte();
|
unit.Unknown2 = reader.ReadByte();
|
||||||
unit.Rotation = reader.ReadSingle();
|
unit.Rotation = reader.ReadSingle();
|
||||||
if (Version >= 1.18f) {
|
if (Version >= 1.18f) {
|
||||||
unit.InitialFrame = reader.ReadInt16();
|
unit.InitialFrame = reader.ReadInt16();
|
||||||
unit.GarrisonnedInId = reader.ReadInt32();
|
unit.GarrisonnedInId = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
return unit;
|
return unit;
|
||||||
}, count);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// More Player Settings and Triggers
|
// More Player Settings and Triggers
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace AdrianKousz.GenieEngine
|
||||||
// PlayerSettings 1
|
// PlayerSettings 1
|
||||||
|
|
||||||
value.PlayerSettings.ForEach(x => {
|
value.PlayerSettings.ForEach(x => {
|
||||||
writer.WriteStringPadded(x.Name, 256);
|
writer.WriteZString(x.Name, 256);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Version >= 1.18f) {
|
if (Version >= 1.18f) {
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AdrianKousz.GenieEngine\BitmapUtil.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\BitmapUtil.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\CpnReader.cs" />
|
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
<Compile Include="AssemblyInfo.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\ScnDefaultFactory.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\ScnDefaultFactory.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\IScnFactory.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\IScnFactory.cs" />
|
||||||
|
@ -41,6 +40,9 @@
|
||||||
<Compile Include="AdrianKousz.GenieEngine\Scenario.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\Scenario.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\ScnSerializerReader.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\ScnSerializerReader.cs" />
|
||||||
<Compile Include="AdrianKousz.GenieEngine\GenieFile.cs" />
|
<Compile Include="AdrianKousz.GenieEngine\GenieFile.cs" />
|
||||||
|
<Compile Include="AdrianKousz.GenieEngine\Campaign.cs" />
|
||||||
|
<Compile Include="AdrianKousz.GenieEngine\CpnSerializerReader.cs" />
|
||||||
|
<Compile Include="AdrianKousz.GenieEngine\CpnSerializerWriter.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue