Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix off-by-one string table parse error #36

Merged
merged 3 commits into from
Feb 19, 2024
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
50 changes: 25 additions & 25 deletions Core/DatFileParsing/SawyerStreamReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Text;
using System.Text;
using OpenLoco.ObjectEditor.Headers;
using OpenLoco.ObjectEditor.Objects;
using OpenLoco.ObjectEditor.Types;
Expand Down Expand Up @@ -154,47 +154,47 @@ public static (DatFileInfo DatFileInfo, ILocoObject? LocoObject) LoadFullObjectF
return new(new DatFileInfo(s5Header, objectHeader), newObj);
}

static string CStringToString(ReadOnlySpan<byte> data, Encoding enc)
{
var ptr = 0;
while (data[ptr++] != '\0') ;
return enc.GetString(data[0..(ptr - 1)]); // do -1 to exclude the \0
}

static Dictionary<LanguageId, string> GetNewLanguageDictionary()
{
var languageDict = new Dictionary<LanguageId, string>();
foreach (var language in Enum.GetValues<LanguageId>())
{
languageDict.Add(language, string.Empty);
}
return languageDict;
}

public static (StringTable table, int bytesRead) LoadStringTable(ReadOnlySpan<byte> data, string[] stringNames, ILogger? logger = null)
{
var stringTable = new StringTable();

if (data.Length == 0 || stringNames.Length == 0)
{
logger?.Warning($"No data for language table");
return (stringTable, 0);
}

var ptr = 0;

foreach (var locoString in stringNames)
{
stringTable.Table.Add(locoString, []);
// init language table
stringTable.Table.Add(locoString, GetNewLanguageDictionary());
var languageDict = stringTable[locoString];

// add empty strings for every single language
foreach (var language in Enum.GetValues<LanguageId>())
{
languageDict.Add(language, string.Empty);
}

for (; ptr < data.Length && data[ptr] != 0xFF;)
// read string
for (; ptr < data.Length && data[ptr] != 0xFF; ++ptr)
{
LeftofZen marked this conversation as resolved.
Show resolved Hide resolved
var lang = (LanguageId)data[ptr++];
var ini = ptr;

while (data[ptr++] != '\0')
{
;
}

var str = Encoding.Latin1.GetString(data[ini..(ptr - 1)]); // do -1 to exclude the \0

if (!languageDict.ContainsKey(lang))
{
logger?.Error($"Skipping unknown language: \"{lang}\"");
break;
}

languageDict[lang] = str;
languageDict[lang] = CStringToString(data[ptr..], Encoding.Latin1);
ptr += languageDict[lang].Length;
}

ptr++; // add one because we skipped the 0xFF byte at the end
Expand Down
6 changes: 3 additions & 3 deletions Core/Data/LanguageId.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace OpenLoco.ObjectEditor.Data
namespace OpenLoco.ObjectEditor.Data
{
public enum LanguageId : uint8_t
{
Expand All @@ -16,7 +16,7 @@ public enum LanguageId : uint8_t
chinese_traditional,
id_12,
portuguese,
blank = 254,
end = 255
//blank = 254,
//end = 255
LeftofZen marked this conversation as resolved.
Show resolved Hide resolved
};
}
16 changes: 14 additions & 2 deletions Core/Objects/TrainSignalObject.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;
using OpenLoco.ObjectEditor.Headers;
using OpenLoco.ObjectEditor.Types;

namespace OpenLoco.ObjectEditor.Objects
{
Expand Down Expand Up @@ -33,7 +34,7 @@ public record TrainSignalObject(
[property: LocoStructOffset(0x13), LocoArrayLength(TrainSignalObject.ModsLength), Browsable(false)] object_id[] ModHeaderIds,
[property: LocoStructOffset(0x1A)] uint16_t DesignedYear,
[property: LocoStructOffset(0x1C)] uint16_t ObsoleteYear
) : ILocoStruct, ILocoStructVariableData
) : ILocoStruct, ILocoStructVariableData, IImageTableStrings
{
public const int ModsLength = 7;

Expand All @@ -49,5 +50,16 @@ public ReadOnlySpan<byte> Save()
=> Mods
.SelectMany(mod => mod.Write().ToArray())
.ToArray();

public bool TryGetImageName(int id, out string? value)
=> ImageIdNameMap.TryGetValue(id, out value);

public static Dictionary<int, string> ImageIdNameMap = new()
{
LeftofZen marked this conversation as resolved.
Show resolved Hide resolved
{ 80, "redLights" },
{ 88, "redLights2" },
{ 96, "greenLights" },
{ 104, "greenLights2" },
};
}
}
1 change: 1 addition & 0 deletions Gui/Gui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<Authors>LeftofZen</Authors>
<Product>$(AssemblyName) $(AssemblyVersion)</Product>
<Version>$(AssemblyVersion)</Version>
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Gui/MainFormModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ static void SerialiseHeaderIndexToFile(string filename, HeaderIndex headerIndex,
}
else
{
var obj = SawyerStreamReader.LoadFullObjectFromFile(filename);
var obj = SawyerStreamReader.LoadFullObjectFromFile(filename, logger: logger);
LeftofZen marked this conversation as resolved.
Show resolved Hide resolved
var uiObj = new UiLocoObject { DatFileInfo = obj.DatFileInfo, LocoObject = obj.LocoObject };
_ = ObjectCache.TryAdd(filename, uiObj);
return uiObj;
Expand Down
Loading