Skip to content

Commit

Permalink
Support for rebuilding DC1 song milos
Browse files Browse the repository at this point in the history
MoveDir and SkeletonDir support was added and now every Milo used by DC1 songs can be rebuilt by MiloEditor
  • Loading branch information
ihatecompvir committed Jan 2, 2025
1 parent 2d65c33 commit 664ee81
Show file tree
Hide file tree
Showing 11 changed files with 376 additions and 53 deletions.
2 changes: 1 addition & 1 deletion MiloLib/Assets/Band/BandCrowdMeterDir.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public BandCrowdMeterDir Read(EndianReader reader, bool standalone, DirectoryMet
else
{
// fields only read when dir is not proxied
if (!entry.isDir)
if (!entry.isEntryInRootDir)
{
if (revision < 3)
{
Expand Down
2 changes: 1 addition & 1 deletion MiloLib/Assets/Band/BandScoreboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public BandScoreboard Read(EndianReader reader, bool standalone, DirectoryMeta p
if (BitConverter.IsLittleEndian) (revision, altRevision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)(combinedRevision >> 16 & 0xFFFF));
else (altRevision, revision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)(combinedRevision >> 16 & 0xFFFF));

if (!entry.isDir)
if (!entry.isEntryInRootDir)
{
sym = Symbol.Read(reader);
}
Expand Down
2 changes: 1 addition & 1 deletion MiloLib/Assets/Band/BandStarDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public BandStarDisplay Read(EndianReader reader, bool standalone, DirectoryMeta
if (BitConverter.IsLittleEndian) (revision, altRevision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)(combinedRevision >> 16 & 0xFFFF));
else (altRevision, revision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)(combinedRevision >> 16 & 0xFFFF));

if (entry.isDir)
if (entry.isEntryInRootDir)
starType = Symbol.Read(reader);

base.Read(reader, false, parent, entry);
Expand Down
2 changes: 1 addition & 1 deletion MiloLib/Assets/Char/Character.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public Character Read(EndianReader reader, bool standalone, DirectoryMeta parent
base.Read(reader, false, parent, entry);

// these fields only present if dir is not proxied
if (revision < 4 || !entry.isDir)
if (revision < 4 || !entry.isEntryInRootDir)
{
lodCount = reader.ReadUInt32();
for (int i = 0; i < lodCount; i++)
Expand Down
212 changes: 168 additions & 44 deletions MiloLib/Assets/DirectoryMeta.cs

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions MiloLib/Assets/Ham/MoveDir.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using MiloLib.Classes;
using MiloLib.Utils;

namespace MiloLib.Assets.Ham
{
[Name("MoveDir"), Description("Dir for HamMoves, contains debugging functionality")]
public class MoveDir : SkeletonDir
{
public ushort altRevision;
public ushort revision;

public uint unkInt1;
public uint unkInt2;
public uint unkInt3;
public uint unkInt4;

public MoveDir(ushort revision, ushort altRevision = 0) : base(revision, altRevision)
{
revision = revision;
altRevision = altRevision;
return;
}

public MoveDir Read(EndianReader reader, bool standalone, DirectoryMeta parent, DirectoryMeta.Entry entry)
{
uint combinedRevision = reader.ReadUInt32();
if (BitConverter.IsLittleEndian) (revision, altRevision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)((combinedRevision >> 16) & 0xFFFF));
else (altRevision, revision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)((combinedRevision >> 16) & 0xFFFF));

base.Read(reader, false, parent, entry);

if (entry != null && !entry.isEntryInRootDir)
{
unkInt1 = reader.ReadUInt32();
unkInt2 = reader.ReadUInt32();
unkInt3 = reader.ReadUInt32();
unkInt4 = reader.ReadUInt32();
}
else
{
// there is prooooobably some fields here but ive never seen them be anything but empty
reader.ReadBlock(25);
}

if (standalone)
if ((reader.Endianness == Endian.BigEndian ? 0xADDEADDE : 0xDEADDEAD) != reader.ReadUInt32()) throw new Exception("Got to end of standalone asset but didn't find the expected end bytes, read likely did not succeed");

return this;
}

public override void Write(EndianWriter writer, bool standalone, DirectoryMeta parent, DirectoryMeta.Entry? entry)
{
writer.WriteUInt32(BitConverter.IsLittleEndian ? (uint)((altRevision << 16) | revision) : (uint)((revision << 16) | altRevision));

base.Write(writer, false, parent, entry);

if (entry == null)
{
writer.WriteUInt32(unkInt1);
writer.WriteUInt32(unkInt2);
writer.WriteUInt32(unkInt3);
writer.WriteUInt32(unkInt4);
}
else
{
writer.WriteBlock(new byte[25]);
}

if (standalone)
writer.WriteBlock(new byte[4] { 0xAD, 0xDE, 0xAD, 0xDE });
}

public override bool IsDirectory()
{
return true;
}

}
}
120 changes: 120 additions & 0 deletions MiloLib/Assets/Ham/SkeletonDir.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using MiloLib.Assets.UI;
using MiloLib.Classes;
using MiloLib.Utils;

namespace MiloLib.Assets.Ham
{
[Name("SkeletonDir"), Description("Dir with skeleton tracking/debugging functionality")]
public class SkeletonDir : PanelDir
{
public ushort altRevision;
public ushort revision;

public Symbol unknownSym = new(0, "");

public bool unkBool;
[Name("Use Smoothing"), Description("Apply joint smoothing?"), MinVersion(2)]
public bool useSmoothing;
public bool unkBool3;

[Name("Smoothing"), Description("0.0 means raw data is returned. Increasing leads to more highly smoothed position values. As it's increased, responsiveness to raw data decreases. Increased smoothing leads to increased latency in the returned values. Must be within [0.0 .. 1.0]"), MinVersion(2)]
public float smoothing;
[Name("Correction"), Description("Correction parameter. Lower values are slower to correct towards the raw data, and appear smoother, while higher values will correct toward the raw data more quickly. Values must be in the range [0.0 .. 1.0]."), MinVersion(2)]
public float correction;
[Name("Prediction"), Description("The number of frames to predict into the future. Values must be greater than or equal to zero. Values greater than 0.5 will likely lead to overshooting when moving quickly. This effect can be damped by using small values of fMaxDeviationRadius."), MinVersion(2)]
public float prediction;
[Name("Jitter Radius"), Description("The radius in meters for jitter reduction. Any jitter beyond this radius is clamped to the radius"), MinVersion(2)]
public float jitterRadius;
[Name("Max Deviation Radius"), Description("The maximum radius in meters that filtered positions are allowed to deviate from raw data. Filtered values that would be more than this radius from the raw data are clamped at this distance, in the direction of the filtered value."), MinVersion(2)]
public float maxDeviationRadius;

public SkeletonDir(ushort revision, ushort altRevision = 0) : base(revision, altRevision)
{
revision = revision;
altRevision = altRevision;
return;
}

public SkeletonDir Read(EndianReader reader, bool standalone, DirectoryMeta parent, DirectoryMeta.Entry entry)
{
uint combinedRevision = reader.ReadUInt32();
if (BitConverter.IsLittleEndian) (revision, altRevision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)((combinedRevision >> 16) & 0xFFFF));
else (altRevision, revision) = ((ushort)(combinedRevision & 0xFFFF), (ushort)((combinedRevision >> 16) & 0xFFFF));

base.Read(reader, false, parent, entry);

// don't read these fields if the entry is in another directory
if (entry != null && !entry.isEntryInRootDir)
{
unknownSym = Symbol.Read(reader);

if (revision != 0)
{
unkBool = reader.ReadBoolean();
}

if (revision > 1)
{
useSmoothing = reader.ReadBoolean();
smoothing = reader.ReadFloat();
correction = reader.ReadFloat();
prediction = reader.ReadFloat();
jitterRadius = reader.ReadFloat();
maxDeviationRadius = reader.ReadFloat();
}

if (revision > 2)
{
unkBool3 = reader.ReadBoolean();
}
}

if (standalone)
if ((reader.Endianness == Endian.BigEndian ? 0xADDEADDE : 0xDEADDEAD) != reader.ReadUInt32()) throw new Exception("Got to end of standalone asset but didn't find the expected end bytes, read likely did not succeed");

return this;
}

public override void Write(EndianWriter writer, bool standalone, DirectoryMeta parent, DirectoryMeta.Entry? entry)
{
writer.WriteUInt32(BitConverter.IsLittleEndian ? (uint)((altRevision << 16) | revision) : (uint)((revision << 16) | altRevision));

base.Write(writer, false, parent, entry);

if (entry == null)
{

Symbol.Write(writer, unknownSym);

if (revision != 0)
{
writer.WriteBoolean(unkBool);
}

if (revision > 1)
{
writer.WriteBoolean(useSmoothing);
writer.WriteFloat(smoothing);
writer.WriteFloat(correction);
writer.WriteFloat(prediction);
writer.WriteFloat(jitterRadius);
writer.WriteFloat(maxDeviationRadius);
}

if (revision > 2)
{
writer.WriteBoolean(unkBool3);
}
}

if (standalone)
writer.WriteBlock(new byte[4] { 0xAD, 0xDE, 0xAD, 0xDE });
}

public override bool IsDirectory()
{
return true;
}

}
}
2 changes: 1 addition & 1 deletion MiloLib/Assets/ObjectDir.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public ObjectDir Read(EndianReader reader, bool standalone, DirectoryMeta parent
if (entry.type.value == "WorldInstance")
{
reader.ReadBoolean();
if (entry.isDir)
if (entry.isEntryInRootDir)
return this;
}

Expand Down
4 changes: 2 additions & 2 deletions MiloLib/Assets/Rnd/RndDir.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public RndDir Read(EndianReader reader, bool standalone, DirectoryMeta parent, D

// the RndDir ends immediately when it is an entry unless the entry is a RndDir or Character, probably others too, why?
// TODO: investigate if this is just for RB3/DC1 or others too
if (entry.isDir && entry.type.value != "Character" && entry.type.value != "RndDir" && entry.type.value != "BandCrowdMeterDir" && entry.type.value != "CrowdMeterIcon" && entry.type.value != "EndingBonusDir" && entry.type.value != "UnisonIcon" && entry.type.value != "BandScoreboard" && entry.type.value != "BandStarDisplay" && entry.type.value != "PanelDir")
if (entry.isEntryInRootDir && entry.type.value != "Character" && entry.type.value != "RndDir" && entry.type.value != "BandCrowdMeterDir" && entry.type.value != "CrowdMeterIcon" && entry.type.value != "EndingBonusDir" && entry.type.value != "UnisonIcon" && entry.type.value != "BandScoreboard" && entry.type.value != "BandStarDisplay" && entry.type.value != "PanelDir" && entry.type.value != "MoveDir" && entry.type.value != "SkeletonDir")
{
return this;
}
Expand Down Expand Up @@ -93,7 +93,7 @@ public override void Write(EndianWriter writer, bool standalone, DirectoryMeta p

if (entry != null)
{
if (entry.isDir && entry.type.value != "Character" && entry.type.value != "RndDir" && entry.type.value != "BandCrowdMeterDir" && entry.type.value != "CrowdMeterIcon" && entry.type.value != "EndingBonusDir" && entry.type.value != "UnisonIcon" && entry.type.value != "BandScoreboard" && entry.type.value != "BandStarDisplay" && entry.type.value != "PanelDir")
if (entry.isEntryInRootDir && entry.type.value != "Character" && entry.type.value != "RndDir" && entry.type.value != "BandCrowdMeterDir" && entry.type.value != "CrowdMeterIcon" && entry.type.value != "EndingBonusDir" && entry.type.value != "UnisonIcon" && entry.type.value != "BandScoreboard" && entry.type.value != "BandStarDisplay" && entry.type.value != "PanelDir" && entry.type.value != "MoveDir" && entry.type.value != "SkeletonDir")
{
if (standalone)
writer.WriteBlock(new byte[4] { 0xAD, 0xDE, 0xAD, 0xDE });
Expand Down
2 changes: 1 addition & 1 deletion MiloLib/Assets/UI/PanelDir.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public PanelDir Read(EndianReader reader, bool standalone, DirectoryMeta parent,
base.Read(reader, false, parent, entry);

// if this is not an entry inside another directory (as in, not an inlined subdir), read the camera
if (!entry.isDir)
if (!entry.isEntryInRootDir)
{
if (revision != 0)
cam = Symbol.Read(reader);
Expand Down
2 changes: 1 addition & 1 deletion MiloLib/Assets/WorldInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public WorldInstance Read(EndianReader reader, bool standalone, DirectoryMeta pa

base.Read(reader, false, parent, entry);

if (standalone && !entry.isDir)
if (standalone && !entry.isEntryInRootDir)
if ((reader.Endianness == Endian.BigEndian ? 0xADDEADDE : 0xDEADDEAD) != reader.ReadUInt32()) throw new Exception("Got to end of standalone asset but didn't find the expected end bytes, read likely did not succeed");

return this;
Expand Down

0 comments on commit 664ee81

Please sign in to comment.