Skip to content

Commit

Permalink
fix off-by-one string table parse error (#36)
Browse files Browse the repository at this point in the history
* fix off-by-one string table parse error

* code cleanup

* code cleanup
  • Loading branch information
LeftofZen authored Feb 19, 2024
1 parent 1ae5c96 commit 6c39ccf
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 31 deletions.
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)
{
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
};
}
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()
{
{ 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);
var uiObj = new UiLocoObject { DatFileInfo = obj.DatFileInfo, LocoObject = obj.LocoObject };
_ = ObjectCache.TryAdd(filename, uiObj);
return uiObj;
Expand Down

0 comments on commit 6c39ccf

Please sign in to comment.