Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dat/Data/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public static class Limits
public const size_t kMaxNormalEntities = kMaxEntities - kMaxMoneyEntities;
// Money is not counted in this limit
public const size_t kMaxMiscEntities = 4000;
public const int kMapRows = 384;
public const int kMapColumns = 384;
public const int kMapColumnsVanilla = 384;
public const int kMapRowsVanilla = 384;

public const int kMaxObjectTypes = 34;
public const int kMaxSawyerEncodings = 4;
Expand Down
35 changes: 28 additions & 7 deletions Dat/Types/SCV5/S5File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,25 @@ uint32_t Checksum
public List<TileElement>[,]? TileElementMap { get; set; }
byte[] OriginalTileElementData { get; set; } = [];

public (int Width, int Height) GetMapSize()
=> GetMapSize(SaveDetails, ScenarioOptions);

public static (int Width, int Height) GetMapSize(SaveDetails saveDetails, ScenarioOptions scenarioOptions)
{
if (saveDetails != null)
{
return (saveDetails.MapSizeX, saveDetails.MapSizeY);
}
else if (scenarioOptions != null)
{
return (scenarioOptions.MapSizeX, scenarioOptions.MapSizeY);
}
else
{
return (Limits.kMapColumnsVanilla, Limits.kMapRowsVanilla);
}
}

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
=> [];

Expand Down Expand Up @@ -215,6 +234,8 @@ public static S5File Read(ReadOnlySpan<byte> data)
byte[] tileElementData = [];
IGameState gameState;

var mapSize = GetMapSize(saveDetails, scenarioOptions);

if (header.Type == S5FileType.Scenario)
{
var gameStateA = SawyerStreamReader.ReadChunk<GameStateScenarioA>(ref data);
Expand All @@ -228,7 +249,7 @@ public static S5File Read(ReadOnlySpan<byte> data)
if (gameStateA.GameStateFlags.HasFlag(GameStateFlags.TileManagerLoaded))
{
tileElementData = SawyerStreamReader.ReadChunkCore(ref data).ToArray();
(tileElements, tileElementMap) = ParseTileElements(tileElementData);
(tileElements, tileElementMap) = ParseTileElements(tileElementData, mapSize.Width, mapSize.Height);
}
}
else
Expand All @@ -237,7 +258,7 @@ public static S5File Read(ReadOnlySpan<byte> data)
FixState();

tileElementData = SawyerStreamReader.ReadChunkCore(ref data).ToArray();
(tileElements, tileElementMap) = ParseTileElements(tileElementData);
(tileElements, tileElementMap) = ParseTileElements(tileElementData, mapSize.Width, mapSize.Height);
}

var checksum = BitConverter.ToUInt32(data[0..4]);
Expand All @@ -249,12 +270,12 @@ public static S5File Read(ReadOnlySpan<byte> data)
static void FixState()
{ }

static (List<TileElement>, List<TileElement>[,]) ParseTileElements(ReadOnlySpan<byte> tileElementData)
static (List<TileElement>, List<TileElement>[,]) ParseTileElements(ReadOnlySpan<byte> tileElementData, int mapWidth, int mapHeight)
{
var numTileElements = tileElementData.Length / TileElement.StructLength;

List<TileElement> tileElements = [];
var tileElementMap = new List<TileElement>[Limits.kMapColumns, Limits.kMapRows];
var tileElementMap = new List<TileElement>[mapWidth, mapHeight];

var x = 0;
var y = 0;
Expand All @@ -275,12 +296,12 @@ static void FixState()

if (el.IsLast())
{
if (x == Limits.kMapColumns - 1)
if (x == mapWidth - 1)
{
y = (y + 1) % Limits.kMapRows;
y = (y + 1) % mapHeight;
}

x = (x + 1) % Limits.kMapColumns;
x = (x + 1) % mapWidth;
}

// el.IsLast() indicates its the last element on that tile
Expand Down
4 changes: 3 additions & 1 deletion Dat/Types/SCV5/SaveDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ public record SaveDetails(
[property: LocoStructOffset(0x247)] byte var_247,
[property: LocoStructOffset(0x248), LocoArrayLength(250 * 200), Browsable(false)] uint8_t[] Image,
[property: LocoStructOffset(0xC598)] CompanyFlags ChallengeFlags,
[property: LocoStructOffset(0xC59C), LocoArrayLength(124), Browsable(false)] byte[] var_C59C)
[property: LocoStructOffset(0xC59C)] uint16_t MapSizeX,
[property: LocoStructOffset(0xC59E)] uint16_t MapSizeY,
[property: LocoStructOffset(0xC5A0), LocoArrayLength(120), Browsable(false)] byte[] var_C59C)
: ILocoStruct
{
public const int StructLength = 0xC618;
Expand Down
4 changes: 3 additions & 1 deletion Dat/Types/SCV5/ScenarioOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ public record ScenarioOptions(
[property: LocoStructOffset(0x41C1)] uint8_t MaxRiverWidth,
[property: LocoStructOffset(0x41C2)] uint8_t RiverbankWidth,
[property: LocoStructOffset(0x41C3)] uint8_t RiverMeanderRate,
[property: LocoStructOffset(0x41C4), LocoArrayLength(342), Browsable(false)] byte[] var_41C4)
[property: LocoStructOffset(0x41C4)] uint16_t MapSizeX,
[property: LocoStructOffset(0x41C6)] uint16_t MapSizeY,
[property: LocoStructOffset(0x41C8), LocoArrayLength(338), Browsable(false)] byte[] var_41C8)
: ILocoStruct
{
public const int StructLength = 0x431A;
Expand Down
11 changes: 6 additions & 5 deletions Gui/ViewModels/LocoTypes/SCV5ViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ public class SCV5ViewModel : BaseFileViewModel
[Reactive]
public Dictionary<ElementType, Bitmap> Maps { get; set; }

[Reactive, Range(0, Limits.kMapColumns - 1)]
[Reactive, Range(0, Limits.kMapColumnsVanilla - 1)]
public int TileElementX { get; set; }

[Reactive, Range(0, Limits.kMapRows - 1)]
[Reactive, Range(0, Limits.kMapRowsVanilla - 1)]
public int TileElementY { get; set; }

public ObservableCollection<TileElement> CurrentTileElements
=> CurrentS5File?.TileElementMap != null && TileElementX >= 0 && TileElementX < 384 && TileElementY >= 0 && TileElementY < 384
=> CurrentS5File?.TileElementMap != null && TileElementX >= 0 && TileElementX < CurrentS5File.GetMapSize().Width && TileElementY >= 0 && TileElementY < CurrentS5File.GetMapSize().Height
? [.. CurrentS5File.TileElementMap[TileElementX, TileElementY]]
: [];

Expand Down Expand Up @@ -199,7 +199,8 @@ async Task DownloadMissingObjects(GameObjDataFolder targetFolder)

void DrawMap()
{
Map = new WriteableBitmap(new Avalonia.PixelSize(384, 384), new Avalonia.Vector(92, 92), Avalonia.Platform.PixelFormat.Rgba8888);
(var mapWidth, var mapHeight) = CurrentS5File.GetMapSize();
Map = new WriteableBitmap(new Avalonia.PixelSize(mapWidth, mapHeight), new Avalonia.Vector(92, 92), Avalonia.Platform.PixelFormat.Rgba8888);
using (var fb = Map.Lock())
{
var teMap = CurrentS5File!.TileElementMap!;
Expand All @@ -211,7 +212,7 @@ void DrawMap()
unsafe
{
var rgba = (byte*)fb.Address;
var idx = ((x * 384) + y) * 4; // not sure why this has to be reversed to match loco
var idx = ((x * mapWidth) + y) * 4; // not sure why this has to be reversed to match loco

if (el.Type == ElementType.Surface)
{
Expand Down