Skip to content

Commit b14ecd8

Browse files
authored
Prepare for release (#16)
* add import sound * working sound effect replacement * add export/import of all images in an object * add track object image names * cleaning up ui * allow saving sound objects * add checksum to original objects file * start cleaning up object definitions, adding all attributes * cleanup a few objects, add image string names to interface object * more objects to records * add basic implementation of vehicle rotator * add start of vehicle rotator/viewer page * add image ids for trackextra object * add comment * trackextra ids account for tab preview * trackobject -> record
1 parent e2b6e0f commit b14ecd8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3510
-1392
lines changed

OpenLocoTool/DatFileParsing/LocoAttributes.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ public class LocoStructSkipReadAttribute : Attribute
4141
public class LocoStringAttribute : Attribute
4242
{ }
4343

44+
// basically a 'skip' attribute to allow deferred loading for variable data, and writing of this property will be 0
45+
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
46+
public class LocoImageIdAttribute : Attribute
47+
{ }
48+
4449
// to mark properties that seemingly have no purpose or use
4550
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
4651
public class LocoPropertyMaybeUnused : Attribute

OpenLocoTool/DatFileParsing/SawyerStreamReader.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
namespace OpenLocoTool.DatFileParsing
99
{
10-
1110
public static class SawyerStreamReader
1211
{
1312
public static List<S5Header> LoadVariableCountS5Headers(ReadOnlySpan<byte> data, int count)
@@ -125,6 +124,12 @@ public static (DatFileInfo DatFileInfo, ILocoObject LocoObject) LoadFullObjectFr
125124
logger?.Error(ex, "Error loading graphics table");
126125
}
127126

127+
// some objects have variable-sized data
128+
if (loadExtra && locoStruct is ILocoStructPostLoad locoStructPostLoad)
129+
{
130+
locoStructPostLoad.PostLoad();
131+
}
132+
128133
// add to object manager
129134
SObjectManager.Add(newObj);
130135

@@ -186,8 +191,13 @@ public static (StringTable table, int bytesRead) LoadStringTable(ReadOnlySpan<by
186191
return LoadStringTable(data, stringTableStrings);
187192
}
188193

189-
public static G1Dat LoadG1(string filename, ILogger? logger = null)
194+
public static G1Dat? LoadG1(string filename, ILogger? logger = null)
190195
{
196+
if (!File.Exists(filename))
197+
{
198+
logger?.Debug($"File {filename} does not exist");
199+
return null;
200+
}
191201
ReadOnlySpan<byte> fullData = LoadBytesFromFile(filename);
192202
var (g1Header, imageTable, imageTableBytesRead) = LoadImageTable(fullData);
193203
logger?.Info($"FileLength={new FileInfo(filename).Length} NumEntries={g1Header.NumEntries} TotalSize={g1Header.TotalSize} ImageTableLength={imageTableBytesRead}");
@@ -368,7 +378,7 @@ public static ILocoStruct GetLocoStruct(ObjectType objectType, ReadOnlySpan<byte
368378
_ => throw new InvalidDataException("Unknown chunk encoding scheme"),
369379
};
370380

371-
public static (RiffWavHeader header, byte[] data) LoadMusicTrack(byte[] data)
381+
public static (RiffWavHeader header, byte[] data) LoadWavFile(byte[] data)
372382
{
373383
using (var ms = new MemoryStream(data))
374384
using (var br = new BinaryReader(ms))
@@ -391,6 +401,7 @@ public static (RiffWavHeader header, byte[] data) LoadMusicTrack(byte[] data)
391401
{
392402
var numSounds = br.ReadUInt32();
393403
var soundOffsets = new uint32_t[numSounds];
404+
394405
for (var i = 0; i < numSounds; ++i)
395406
{
396407
soundOffsets[i] = br.ReadUInt32();
@@ -400,10 +411,10 @@ public static (RiffWavHeader header, byte[] data) LoadMusicTrack(byte[] data)
400411
{
401412
br.BaseStream.Position = soundOffsets[i];
402413
var pcmLen = br.ReadUInt32();
403-
var format = ByteReader.ReadLocoStruct<WaveFormatEx>(br.ReadBytes(ObjectAttributes.StructSize<WaveFormatEx>()));
414+
var header = ByteReader.ReadLocoStruct<WaveFormatEx>(br.ReadBytes(ObjectAttributes.StructSize<WaveFormatEx>()));
404415

405416
var pcmData = br.ReadBytes((int)pcmLen);
406-
result.Add((format, pcmData));
417+
result.Add((header, pcmData));
407418
}
408419
}
409420

OpenLocoTool/DatFileParsing/SawyerStreamWriter.cs

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,81 @@ namespace OpenLocoTool.DatFileParsing
99
{
1010
public static class SawyerStreamWriter
1111
{
12-
public static void ExportSoundEffectAsWave(string filename, WaveFormatEx header, byte[] pcmData)
12+
//public static void ExportSoundEffectAsWave(string filename, WaveFormatEx header, byte[] pcmData)
13+
//{
14+
// using (var stream = File.Create(filename))
15+
// {
16+
// stream.Write(ByteWriter.WriteLocoStruct(header));
17+
// stream.Write(pcmData);
18+
// stream.Flush();
19+
// stream.Close();
20+
// }
21+
//}
22+
23+
public static RiffWavHeader WaveFormatExToRiff(WaveFormatEx hdr, int pcmDataLength)
24+
=> new(
25+
0x46464952, // "RIFF"
26+
(uint)(pcmDataLength + 36), // file size
27+
0x45564157, // "WAVE"
28+
0x20746d66, // "fmt "
29+
16, // size of fmt chunk
30+
1, // format tag
31+
(ushort)hdr.NumberOfChannels,
32+
(uint)hdr.SampleRate,
33+
(uint)hdr.AverageBytesPerSecond,
34+
4, //(ushort)waveFHeader.BlockAlign,
35+
16, //(ushort)waveFHeader.BitsPerSample,
36+
0x61746164, // "data"
37+
(uint)pcmDataLength // data size
38+
);
39+
40+
public static WaveFormatEx RiffToWaveFormatEx(RiffWavHeader hdr)
41+
=> new(1, (short)hdr.NumberOfChannels, (int)hdr.SampleRate, (int)hdr.ByteRate, 2, 16, 0);
42+
//0x46464952, // "RIFF"
43+
//(uint)(pcmDataLength + 36), // file size
44+
//0x45564157, // "WAVE"
45+
//0x20746d66, // "fmt "
46+
//16, // size of fmt chunk
47+
//1, // format tag
48+
//(ushort)hdr.NumberOfChannels,
49+
//(uint)hdr.SampleRate,
50+
//(uint)hdr.AverageBytesPerSecond,
51+
//4, //(ushort)waveFHeader.BlockAlign,
52+
//16, //(ushort)waveFHeader.BitsPerSample,
53+
//0x61746164, // "data"
54+
//(uint)pcmDataLength // data size
55+
//);
56+
57+
public static byte[] SaveSoundEffectsToCSS(List<(RiffWavHeader header, byte[] data)> sounds)
1358
{
14-
using (var stream = File.Create(filename))
59+
using (var ms = new MemoryStream())
60+
using (var br = new BinaryWriter(ms))
1561
{
16-
stream.Write(ByteWriter.WriteLocoStruct(header));
17-
stream.Write(pcmData);
18-
stream.Flush();
19-
stream.Close();
62+
// total sounds
63+
br.Write((uint)sounds.Count);
64+
65+
var currOffset = 4 + (sounds.Count * 4); // 4 for sound count, then 32 sounds each have a 4-byte offset. its always 33 * 4 = 132 to start.
66+
67+
// sound offsets
68+
foreach (var sfx in sounds)
69+
{
70+
br.Write((uint)currOffset);
71+
currOffset += 4 + sfx.data.Length + ObjectAttributes.StructSize<WaveFormatEx>();
72+
}
73+
74+
// pcm data
75+
foreach (var sfx in sounds)
76+
{
77+
var waveHdr = RiffToWaveFormatEx(sfx.header);
78+
br.Write((uint)sfx.data.Length);
79+
br.Write(ByteWriter.WriteLocoStruct(waveHdr));
80+
br.Write(sfx.data);
81+
}
82+
83+
ms.Flush();
84+
ms.Close();
85+
86+
return ms.ToArray();
2087
}
2188
}
2289

OpenLocoTool/Data/OriginalDataFiles.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static class OriginalDataFiles
1616
{ "20s4.dat", "Flying High" },
1717
{ "20s5.dat", "Get Me To Gladstone Bay" },
1818
{ "20s6.dat", "Sandy Track Blues" },
19-
{ "40s1.dat", "A Traveller's Serenade" }, // in loco its misspelt - Seranade
19+
{ "40s1.dat", "A Traveller's Serenade" }, // todo: in loco its misspelt - Seranade
2020
{ "40s2.dat", "Latino Trip" },
2121
{ "40s3.dat", "Head To The Bop" },
2222
{ "50s1.dat", "Gettin' On The Gas" },
@@ -36,10 +36,12 @@ public static class OriginalDataFiles
3636
{ "90s2.dat", "Everlasting High-Rise" },
3737
};
3838

39-
public static readonly Dictionary<string, string> SoundEffects = new()
40-
{
41-
{ "css1.dat", "Sound Effects" },
42-
};
39+
public const string SoundEffect = "css1.dat";
40+
41+
//public static readonly Dictionary<string, string> SoundEffect = new()
42+
//{
43+
// { "css1.dat", "Sound Effects" },
44+
//};
4345

4446
public static readonly Dictionary<string, string> MiscellaneousTracks = new()
4547
{

0 commit comments

Comments
 (0)