mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-16 02:56:44 -04:00
Added FSO.Files for use with the API server
Don't ask me. FreeSO is the prime example of dependency hell.
This commit is contained in:
parent
4b5e584eeb
commit
8fec258215
104 changed files with 14653 additions and 163 deletions
236
server/tso.files/HIT/Hot.cs
Executable file
236
server/tso.files/HIT/Hot.cs
Executable file
|
@ -0,0 +1,236 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Files.HIT
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration constants.
|
||||
/// </summary>
|
||||
public struct EventMappingEquate
|
||||
{
|
||||
public string Label;
|
||||
public int Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This section assigns a sound ID to a number of subroutines
|
||||
/// (exported or not) in the corresponding HIT file.
|
||||
/// </summary>
|
||||
public struct TrackData
|
||||
{
|
||||
//The syntax for TrackData is A = B, where A is the sound's File ID
|
||||
//and B is the offset to the subroutine in the accompanying HIT file.
|
||||
public long FileID;
|
||||
public int SubRoutineOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HOT (short for HIT Options Table) is an ini format that defines
|
||||
/// enumeration constants and track data for HIT binary files.
|
||||
/// </summary>
|
||||
public class Hot
|
||||
{
|
||||
private int m_Version;
|
||||
private int m_LoadPriority;
|
||||
private List<EventMappingEquate> m_EventMappingEquations = new List<EventMappingEquate>();
|
||||
private List<TrackData> m_TrackDataList = new List<TrackData>();
|
||||
public Dictionary<uint, Track> Tracks = new Dictionary<uint, Track>();
|
||||
public Dictionary<uint, Patch> Patches = new Dictionary<uint, Patch>();
|
||||
public Dictionary<uint, Hitlist> Hitlists = new Dictionary<uint, Hitlist>();
|
||||
public Dictionary<uint, uint> TrackData = new Dictionary<uint, uint>();
|
||||
public Dictionary<string, EVTEntry> Events = new Dictionary<string, EVTEntry>();
|
||||
private Dictionary<string, int> EventMappingEquate = new Dictionary<string, int>();
|
||||
public HSM AsmNames;
|
||||
|
||||
/// <summary>
|
||||
/// Gets this Hot instance's list of EventMappingEquate instances.
|
||||
/// </summary>
|
||||
public List<EventMappingEquate> EventMappingEquations
|
||||
{
|
||||
get { return m_EventMappingEquations; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this Hot instance's list of TrackData instances.
|
||||
/// </summary>
|
||||
public List<TrackData> TrackDataList
|
||||
{
|
||||
get { return m_TrackDataList; }
|
||||
}
|
||||
|
||||
public Hot(byte[] FileData)
|
||||
{
|
||||
LoadFrom(FileData);
|
||||
}
|
||||
|
||||
public void LoadFrom(byte[] FileData)
|
||||
{
|
||||
StreamReader Reader = new StreamReader(new MemoryStream(FileData));
|
||||
HotReadMode ActiveState = HotReadMode.None;
|
||||
|
||||
while (!Reader.EndOfStream)
|
||||
{
|
||||
string CurrentLine = Reader.ReadLine().Trim().Replace("\r\n", "");
|
||||
|
||||
switch (CurrentLine)
|
||||
{
|
||||
case "[EventMappingEquate]":
|
||||
ActiveState = HotReadMode.EventMappingEquate;
|
||||
break;
|
||||
case "[Options]":
|
||||
ActiveState = HotReadMode.Options;
|
||||
break;
|
||||
case "[TrackData]":
|
||||
ActiveState = HotReadMode.TrackData;
|
||||
break;
|
||||
case "[EventMapping]":
|
||||
//equivalent to .evt file
|
||||
//(name)=(eventMappingEquate as event type),(trackid),0,0,0,0
|
||||
ActiveState = HotReadMode.EventMapping;
|
||||
break;
|
||||
case "[Track]":
|
||||
//equivalent to a lot of track files
|
||||
//(trackid)=0,(subroutine),(volume),(arguments),(duckingPriority),(controlGroup),(soundPressureLevel),@(hitlistID),(patchID)
|
||||
//patch id is usually 0, in favor of single item hitlists
|
||||
ActiveState = HotReadMode.Track;
|
||||
break;
|
||||
case "[Patch]":
|
||||
//(patchid)=(name),(filenameInQuotes),(looped),(piano),0,0,0
|
||||
ActiveState = HotReadMode.Patch;
|
||||
break;
|
||||
case "[GlobalHitList]":
|
||||
//(hitlistid)=(hitlistString)
|
||||
//note: many hitlists contain just one patch
|
||||
ActiveState = HotReadMode.GlobalHitList;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CurrentLine.Contains("["))
|
||||
{
|
||||
if (!CurrentLine.Contains("]"))
|
||||
{
|
||||
if (CurrentLine != "")
|
||||
{
|
||||
string[] Params = CurrentLine.Split("=".ToCharArray());
|
||||
//EventMappingEquate fields look like: kSndobPlay=1
|
||||
switch (ActiveState)
|
||||
{
|
||||
case HotReadMode.EventMappingEquate:
|
||||
EventMappingEquate EMappingEquate = new EventMappingEquate();
|
||||
EMappingEquate.Label = Params[0];
|
||||
EMappingEquate.Value = int.Parse(Params[1]);
|
||||
EventMappingEquate[EMappingEquate.Label] = EMappingEquate.Value;
|
||||
break;
|
||||
//Options fields look like: Version=1
|
||||
case HotReadMode.Options:
|
||||
switch (Params[0])
|
||||
{
|
||||
case "Version":
|
||||
m_Version = int.Parse(Params[1]);
|
||||
break;
|
||||
case "LoadPriority":
|
||||
m_LoadPriority = int.Parse(Params[1]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//TrackData fields look like: 0xb0f4=0x10
|
||||
case HotReadMode.TrackData:
|
||||
TrackData.Add(Convert.ToUInt32(Params[0], 16), Convert.ToUInt32(Params[1], 16));
|
||||
break;
|
||||
case HotReadMode.EventMapping:
|
||||
var commaSplit = Params[1].Split(',');
|
||||
Events[Params[0].ToLowerInvariant()] = new EVTEntry
|
||||
{
|
||||
Name = Params[0].ToLowerInvariant(),
|
||||
EventType = (uint)ParseEME(commaSplit[0]),
|
||||
TrackID = (commaSplit.Length>1)?(uint)ParseEME(commaSplit[1]):0
|
||||
};
|
||||
break;
|
||||
case HotReadMode.Track:
|
||||
var tid = uint.Parse(Params[0]);
|
||||
var tcSplit = Params[1].Split(',');
|
||||
|
||||
var trk = new Track()
|
||||
{
|
||||
SubroutineID = 0,//(uint)HSMConst(tcSplit[1]),
|
||||
Volume = (uint)ParseEME(tcSplit[2]),
|
||||
ArgType = (HITArgs)ParseEME(tcSplit[3]),
|
||||
DuckingPriority = (HITDuckingPriorities)ParseEME(tcSplit[4]),
|
||||
ControlGroup = (HITControlGroups)ParseEME(tcSplit[5]),
|
||||
HitlistID = (uint)HSMConst(tcSplit[7].Substring(1)), //cut out @
|
||||
SoundID = (uint)ParseEME(tcSplit[8])
|
||||
};
|
||||
|
||||
if (trk.HitlistID != 0 && TrackData.ContainsKey(trk.HitlistID)) trk.SubroutineID = TrackData[trk.HitlistID];
|
||||
if (trk.SoundID != 0 && TrackData.ContainsKey(trk.SoundID)) trk.SubroutineID = TrackData[trk.SoundID];
|
||||
|
||||
Tracks[tid] = trk;
|
||||
break;
|
||||
case HotReadMode.Patch:
|
||||
var pid = uint.Parse(Params[0]);
|
||||
var patch = new Patch(Params[1]);
|
||||
Patches[pid] = patch;
|
||||
break;
|
||||
case HotReadMode.GlobalHitList:
|
||||
var hid = uint.Parse(Params[0]);
|
||||
try
|
||||
{
|
||||
var hitlist = Hitlist.HitlistFromString(Params[1]);
|
||||
Hitlists[hid] = hitlist;
|
||||
} catch (Exception)
|
||||
{
|
||||
/*
|
||||
* todo: saxophone seems to reference an hsm.
|
||||
* 20016=sulsaxj_way_aa
|
||||
* 20017=sulsaxk_way_solo
|
||||
* 20018=sulsaxl_way_fin
|
||||
* these labels are in the hsm but they have a different case...
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int HSMConst(string input)
|
||||
{
|
||||
int result = 0;
|
||||
AsmNames?.Constants?.TryGetValue(input, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private int ParseEME(string eme)
|
||||
{
|
||||
int result = 0;
|
||||
if (int.TryParse(eme, out result)) return result;
|
||||
EventMappingEquate.TryGetValue(eme, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Hot(string Filepath) : this(File.ReadAllBytes(Filepath))
|
||||
{
|
||||
}
|
||||
|
||||
public Hot(string Filepath, HSM myAsm)
|
||||
{
|
||||
AsmNames = myAsm;
|
||||
LoadFrom(File.ReadAllBytes(Filepath));
|
||||
}
|
||||
}
|
||||
|
||||
public enum HotReadMode
|
||||
{
|
||||
None,
|
||||
EventMappingEquate,
|
||||
Options,
|
||||
TrackData,
|
||||
EventMapping,
|
||||
Track,
|
||||
Patch,
|
||||
GlobalHitList
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue