Skip to content

Commit 6c39ccf

Browse files
authored
fix off-by-one string table parse error (#36)
* fix off-by-one string table parse error * code cleanup * code cleanup
1 parent 1ae5c96 commit 6c39ccf

File tree

5 files changed

+44
-31
lines changed

5 files changed

+44
-31
lines changed

Core/DatFileParsing/SawyerStreamReader.cs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Text;
1+
using System.Text;
22
using OpenLoco.ObjectEditor.Headers;
33
using OpenLoco.ObjectEditor.Objects;
44
using OpenLoco.ObjectEditor.Types;
@@ -154,47 +154,47 @@ public static (DatFileInfo DatFileInfo, ILocoObject? LocoObject) LoadFullObjectF
154154
return new(new DatFileInfo(s5Header, objectHeader), newObj);
155155
}
156156

157+
static string CStringToString(ReadOnlySpan<byte> data, Encoding enc)
158+
{
159+
var ptr = 0;
160+
while (data[ptr++] != '\0') ;
161+
return enc.GetString(data[0..(ptr - 1)]); // do -1 to exclude the \0
162+
}
163+
164+
static Dictionary<LanguageId, string> GetNewLanguageDictionary()
165+
{
166+
var languageDict = new Dictionary<LanguageId, string>();
167+
foreach (var language in Enum.GetValues<LanguageId>())
168+
{
169+
languageDict.Add(language, string.Empty);
170+
}
171+
return languageDict;
172+
}
173+
157174
public static (StringTable table, int bytesRead) LoadStringTable(ReadOnlySpan<byte> data, string[] stringNames, ILogger? logger = null)
158175
{
159176
var stringTable = new StringTable();
160177

161178
if (data.Length == 0 || stringNames.Length == 0)
162179
{
180+
logger?.Warning($"No data for language table");
163181
return (stringTable, 0);
164182
}
165183

166184
var ptr = 0;
167185

168186
foreach (var locoString in stringNames)
169187
{
170-
stringTable.Table.Add(locoString, []);
188+
// init language table
189+
stringTable.Table.Add(locoString, GetNewLanguageDictionary());
171190
var languageDict = stringTable[locoString];
172191

173-
// add empty strings for every single language
174-
foreach (var language in Enum.GetValues<LanguageId>())
175-
{
176-
languageDict.Add(language, string.Empty);
177-
}
178-
179-
for (; ptr < data.Length && data[ptr] != 0xFF;)
192+
// read string
193+
for (; ptr < data.Length && data[ptr] != 0xFF; ++ptr)
180194
{
181195
var lang = (LanguageId)data[ptr++];
182-
var ini = ptr;
183-
184-
while (data[ptr++] != '\0')
185-
{
186-
;
187-
}
188-
189-
var str = Encoding.Latin1.GetString(data[ini..(ptr - 1)]); // do -1 to exclude the \0
190-
191-
if (!languageDict.ContainsKey(lang))
192-
{
193-
logger?.Error($"Skipping unknown language: \"{lang}\"");
194-
break;
195-
}
196-
197-
languageDict[lang] = str;
196+
languageDict[lang] = CStringToString(data[ptr..], Encoding.Latin1);
197+
ptr += languageDict[lang].Length;
198198
}
199199

200200
ptr++; // add one because we skipped the 0xFF byte at the end

Core/Data/LanguageId.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace OpenLoco.ObjectEditor.Data
1+
namespace OpenLoco.ObjectEditor.Data
22
{
33
public enum LanguageId : uint8_t
44
{
@@ -16,7 +16,7 @@ public enum LanguageId : uint8_t
1616
chinese_traditional,
1717
id_12,
1818
portuguese,
19-
blank = 254,
20-
end = 255
19+
//blank = 254,
20+
//end = 255
2121
};
2222
}

Core/Objects/TrainSignalObject.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44
using OpenLoco.ObjectEditor.Headers;
5+
using OpenLoco.ObjectEditor.Types;
56

67
namespace OpenLoco.ObjectEditor.Objects
78
{
@@ -33,7 +34,7 @@ public record TrainSignalObject(
3334
[property: LocoStructOffset(0x13), LocoArrayLength(TrainSignalObject.ModsLength), Browsable(false)] object_id[] ModHeaderIds,
3435
[property: LocoStructOffset(0x1A)] uint16_t DesignedYear,
3536
[property: LocoStructOffset(0x1C)] uint16_t ObsoleteYear
36-
) : ILocoStruct, ILocoStructVariableData
37+
) : ILocoStruct, ILocoStructVariableData, IImageTableStrings
3738
{
3839
public const int ModsLength = 7;
3940

@@ -49,5 +50,16 @@ public ReadOnlySpan<byte> Save()
4950
=> Mods
5051
.SelectMany(mod => mod.Write().ToArray())
5152
.ToArray();
53+
54+
public bool TryGetImageName(int id, out string? value)
55+
=> ImageIdNameMap.TryGetValue(id, out value);
56+
57+
public static Dictionary<int, string> ImageIdNameMap = new()
58+
{
59+
{ 80, "redLights" },
60+
{ 88, "redLights2" },
61+
{ 96, "greenLights" },
62+
{ 104, "greenLights2" },
63+
};
5264
}
5365
}

Gui/Gui.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
<Authors>LeftofZen</Authors>
1818
<Product>$(AssemblyName) $(AssemblyVersion)</Product>
1919
<Version>$(AssemblyVersion)</Version>
20+
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
2021
</PropertyGroup>
2122

2223
<ItemGroup>

Gui/MainFormModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ static void SerialiseHeaderIndexToFile(string filename, HeaderIndex headerIndex,
363363
}
364364
else
365365
{
366-
var obj = SawyerStreamReader.LoadFullObjectFromFile(filename);
366+
var obj = SawyerStreamReader.LoadFullObjectFromFile(filename, logger: logger);
367367
var uiObj = new UiLocoObject { DatFileInfo = obj.DatFileInfo, LocoObject = obj.LocoObject };
368368
_ = ObjectCache.TryAdd(filename, uiObj);
369369
return uiObj;

0 commit comments

Comments
 (0)