From ba19b81662157f2344ac1ea7fb078ad59dd10fbb Mon Sep 17 00:00:00 2001 From: BlueCube3310 <53150244+BlueCube3310@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:43:38 +0200 Subject: [PATCH] Add DVScene read/write support --- .../SharpNeedle/SonicTeam/DivScene/DivNode.cs | 118 ++ .../SonicTeam/DivScene/DivNodeData.cs | 508 ++++++ .../SharpNeedle/SonicTeam/DivScene/DivPage.cs | 65 + .../SonicTeam/DivScene/DivParameter.cs | 1474 +++++++++++++++++ .../SonicTeam/DivScene/DivResource.cs | 54 + .../SonicTeam/DivScene/DivScene.cs | 229 +++ .../SonicTeam/DivScene/DivTypes.cs | 25 + Source/SharpNeedle/Utilities/BinaryHelper.cs | 6 + 8 files changed, 2479 insertions(+) create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivNode.cs create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivNodeData.cs create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivPage.cs create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivParameter.cs create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivResource.cs create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivScene.cs create mode 100644 Source/SharpNeedle/SonicTeam/DivScene/DivTypes.cs diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivNode.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivNode.cs new file mode 100644 index 0000000..62ae2c5 --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivNode.cs @@ -0,0 +1,118 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +public class DivNode : IBinarySerializable +{ + public Guid GUID { get; set; } + public int Type { get; set; } + public List Children { get; set; } = new(); + public int Field1C { get; set; } + public int Field20 { get; set; } + public int Field24 { get; set; } + public int Field28 { get; set; } + public int Field2C { get; set; } + public string Name { get; set; } + public DivNodeData Data { get; set; } = new DivTransformData(); + + public DivNode() { } + + public DivNode(string name) + { + Name = name; + GUID = Guid.NewGuid(); + } + + public DivNode(string name, NodeType type) : this(name) + { + Type = (int)type; + } + + public DivNode(string name, NodeType type, DivNodeData data) : this(name, type) + { + Data = data; + } + + public void Read(BinaryObjectReader reader) + { + GUID = reader.Read(); + Type = reader.Read(); + int dataSize = reader.Read(); + + int childCount = reader.Read(); + Field1C = reader.Read(); + + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + + Name = reader.ReadDivString(64); + + switch ((NodeType)Type) + { + case NodeType.Transform: + Data = new DivTransformData(reader); + break; + + case NodeType.Camera: + Data = new DivCameraData(reader); + break; + + case NodeType.CameraMotion: + Data = new DivCameraMotionData(reader); + break; + + case NodeType.Model: + case NodeType.Model2: + Data = new DivModelData(reader); + break; + + case NodeType.Motion: + case NodeType.Motion2: + Data = new DivMotionData(reader); + break; + + case NodeType.NodeAttachment: + Data = new DivNodeAttachData(reader); + break; + + case NodeType.Parameter: + Data = new DivParameterData(reader, dataSize); + break; + + default: + reader.Skip(dataSize * 4); + break; + } + + Children.AddRange(reader.ReadObjectArray(childCount)); + } + + public void Write(BinaryObjectWriter writer) + { + writer.Write(GUID); + writer.Write(Type); + + long dataSizePos = writer.Position; + writer.WriteNulls(4); + + writer.Write(Children.Count); + writer.Write(Field1C); + + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + + writer.WriteDivString(Name, 64); + + long dataStart = writer.Position; + Data.Write(writer); + long dataEnd = writer.Position; + + writer.Seek(dataSizePos, System.IO.SeekOrigin.Begin); + writer.Write((int)(dataEnd - dataStart) / 4); + writer.Seek(dataEnd, System.IO.SeekOrigin.Begin); + + writer.WriteObjectCollection(Children); + } +} \ No newline at end of file diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivNodeData.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivNodeData.cs new file mode 100644 index 0000000..90cc5fb --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivNodeData.cs @@ -0,0 +1,508 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +public abstract class DivNodeData : IBinarySerializable +{ + public abstract void Read(BinaryObjectReader reader); + + public abstract void Write(BinaryObjectWriter writer); +} + +public class DivTransformData : DivNodeData +{ + public Matrix4x4 Transform { get; set; } + public int Field40 { get; set; } + public int Field44 { get; set; } + public int Field48 { get; set; } + public int Field4C { get; set; } + + public DivTransformData() { } + public DivTransformData(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Transform = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Transform); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + } +} + +public class DivCameraData : DivNodeData +{ + public int Field00 { get; set; } + public int FrameCount { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + public List FrameTimes { get; set; } = new List(); + public List FrameData { get; set; } = new List(); + + public DivCameraData() { } + public DivCameraData(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + FrameCount = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + + if(FrameCount > 0) + { + reader.ReadCollection(FrameCount, FrameTimes); + reader.ReadCollection(FrameCount, FrameData); + } + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(FrameCount); + writer.Write(Field08); + writer.Write(Field0C); + + if (FrameCount > 0) + { + writer.WriteCollection(FrameTimes); + writer.WriteCollection(FrameData); + } + } +} + +public class DivCameraMotionData : DivNodeData +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + + public DivCameraMotionData() { } + public DivCameraMotionData(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + } +} + +public class DivModelData : DivNodeData +{ + public int Field00 { get; set; } + public string ModelName { get; set; } + public string SkeletonName { get; set; } + public string Field84 { get; set; } + + public DivModelData() { } + public DivModelData(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + ModelName = reader.ReadDivString(64); + SkeletonName = reader.ReadDivString(64); + Field84 = reader.ReadDivString(64); + + reader.Skip(76); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteDivString(ModelName, 64); + writer.WriteDivString(SkeletonName, 64); + writer.WriteDivString(Field84, 64); + + writer.WriteNulls(76); + } +} + +public class DivMotionData : DivNodeData +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + public string Field10 { get; set; } + public float Field18 { get; set; } + + public DivMotionData() { } + public DivMotionData(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.ReadDivString(8); + Field18 = reader.Read(); + + reader.Skip(20); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.WriteDivString(Field10, 8); + writer.Write(Field18); + + writer.WriteNulls(20); + } +} + +public class DivNodeAttachData : DivNodeData +{ + public int Field00 { get; set; } + public string NodeName { get; set; } + public int Field44 { get; set; } + public int Field48 { get; set; } + public int Field4C { get; set; } + + public DivNodeAttachData() { } + public DivNodeAttachData(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + NodeName = reader.ReadDivString(64); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteDivString(NodeName, 64); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + } +} + +public class DivParameterData : DivNodeData +{ + private int UnknownDataSize; + + public int Type { get; set; } + public float StartTime { get; set; } + public float EndTime { get; set; } + public int Field0C { get; set; } + public int Field10 { get; set; } + public int Field14 { get; set; } + public int Field18 { get; set; } + public int Field1C { get; set; } + public DivParameter Parameter { get; set; } + + public DivParameterData() { } + public DivParameterData(BinaryObjectReader reader, int size) + { + UnknownDataSize = size - 8; + Read(reader); + } + + public DivParameterData(ParameterType type, float startTime, float endTime) + { + Type = (int)type; + StartTime = startTime; + EndTime = endTime; + } + + public DivParameterData(ParameterType type, float startTime, float endTime, DivParameter parameter) : this(type, startTime, endTime) + { + Parameter = parameter; + } + + public void ReadFrontiersParameter(BinaryObjectReader reader, int type) + { + switch ((FrontiersParams)type) + { + case FrontiersParams.DepthOfField: + Parameter = new DivDOFParameter(reader); + break; + + case FrontiersParams.ColorCorrection: + Parameter = new DivColorCorrectionParameter(reader); + break; + + case FrontiersParams.CameraExposure: + Parameter = new DivCameraExposureParameter(reader); + break; + + case FrontiersParams.ShadowResolution: + Parameter = new DivShadowResolutionParameter(reader); + break; + + case FrontiersParams.ChromaticAberration: + Parameter = new DivChromaAberrParameter(reader); + break; + + case FrontiersParams.Vignette: + Parameter = new DivVignetteParameter(reader); + break; + + case FrontiersParams.Fade: + Parameter = new DivFadeParameter(reader); + break; + + case FrontiersParams.Letterbox: + Parameter = new DivLetterboxParameter(reader); + break; + + case FrontiersParams.BossCutoff: + Parameter = new DivBossCutoffParameter(reader); + break; + + case FrontiersParams.Subtitle: + Parameter = new DivSubtitleParameter(reader); + break; + + case FrontiersParams.Sound: + Parameter = new DivSoundParameter(reader); + break; + + case FrontiersParams.Time: + Parameter = new DivTimeParameter(reader); + break; + + case FrontiersParams.CameraBlur: + Parameter = new DivCameraBlurParameter(reader); + break; + + case FrontiersParams.GeneralPurposeTrigger: + Parameter = new DivGeneralPurposeTriggerParameter(reader); + break; + + case FrontiersParams.DitherDepth: + Parameter = new DivDitherDepthParameter(reader); + break; + + case FrontiersParams.QTE: + Parameter = new DivQTEParameter(reader); + break; + + case FrontiersParams.ASMForcedOverwrite: + Parameter = new DivASMParameter(reader); + break; + + case FrontiersParams.Aura: + Parameter = new DivAuraParameter(reader); + break; + + case FrontiersParams.TimescaleChange: + Parameter = new DivTimescaleParameter(reader); + break; + + case FrontiersParams.CyberNoise: + Parameter = new DivCyberNoiseParameter(reader); + break; + + case FrontiersParams.MovieDisplay: + Parameter = new DivMovieDisplayParameter(reader); + break; + + case FrontiersParams.Weather: + Parameter = new DivWeatherParameter(reader); + break; + + case FrontiersParams.TheEndCable: + Parameter = new DivTheEndCableParameter(reader); + break; + + case FrontiersParams.FinalBossLighting: + Parameter = new DivFinalBossLightingParameter(reader); + break; + + default: + Parameter = new DivUnknownParameter(reader, UnknownDataSize); + break; + } + } + + public void ReadShadowGensParameter(BinaryObjectReader reader, int type) + { + switch ((ShadowGensParams)type) + { + case ShadowGensParams.DepthOfField: + Parameter = new DivDOFParameter(reader); + break; + + case ShadowGensParams.ChromaticAberration: + Parameter = new DivChromaAberrParameter(reader); + break; + + case ShadowGensParams.Vignette: + Parameter = new DivVignetteParameter(reader); + break; + + case ShadowGensParams.Fade: + Parameter = new DivFadeParameter(reader); + break; + + case ShadowGensParams.BossCutoff: + Parameter = new DivBossCutoffParameter(reader); + break; + + case ShadowGensParams.Subtitle: + Parameter = new DivSubtitleParameter(reader); + break; + + case ShadowGensParams.Sound: + Parameter = new DivSoundParameter(reader); + break; + + case ShadowGensParams.CameraBlur: + Parameter = new DivCameraBlurParameter(reader); + break; + + case ShadowGensParams.GeneralPurposeTrigger: + Parameter = new DivGeneralPurposeTriggerParameter(reader); + break; + + case ShadowGensParams.QTE: + Parameter = new DivQTEParameter(reader); + break; + + case ShadowGensParams.TimescaleChange: + Parameter = new DivTimescaleParameter(reader); + break; + + default: + Parameter = new DivUnknownParameter(reader, UnknownDataSize); + break; + } + } + + public void ReadGameSpecificParameter(BinaryObjectReader reader, GameType game, int type) + { + switch(game) + { + case GameType.Frontiers: + ReadFrontiersParameter(reader, type); + break; + + case GameType.ShadowGenerations: + ReadShadowGensParameter(reader, type); + break; + + default: + Parameter = new DivUnknownParameter(reader, UnknownDataSize); + break; + } + } + + public override void Read(BinaryObjectReader reader) + { + Type = reader.Read(); + StartTime = reader.Read(); + EndTime = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + + if(Type < 1000) + { + switch ((ParameterType)Type) + { + case ParameterType.DrawingOff: + Parameter = new DivDrawingOffParameter(reader); + break; + + case ParameterType.PathAdjust: + Parameter = new DivPathAdjustParameter(reader); + break; + + case ParameterType.Effect: + Parameter = new DivEffectParameter(reader); + break; + + case ParameterType.CullDisabled: + Parameter = new DivCullDisabledParameter(reader); + break; + + case ParameterType.UVAnimation: + Parameter = new DivUVAnimParameter(reader); + break; + + case ParameterType.MaterialAnimation: + Parameter = new DivMaterialAnimParameter(reader); + break; + + case ParameterType.CompositeAnimation: + Parameter = new DivCompositeAnimationParameter(reader); + break; + + case ParameterType.GameCamera: + Parameter = new DivGameCameraParameter(reader); + break; + + default: + Parameter = new DivUnknownParameter(reader, UnknownDataSize); + break; + } + } + else + { + ReadGameSpecificParameter(reader, GameType.Frontiers, Type); + } + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Type); + writer.Write(StartTime); + writer.Write(EndTime); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + + if(Parameter != null) + Parameter.Write(writer); + } +} + +public enum NodeType +{ + Transform = 1, + Camera = 3, + CameraMotion = 4, + Model = 5, + Motion = 6, + Model2 = 8, + Motion2 = 10, + NodeAttachment = 11, + Parameter = 12 +} \ No newline at end of file diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivPage.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivPage.cs new file mode 100644 index 0000000..6ae0b5b --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivPage.cs @@ -0,0 +1,65 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +public class DivPage : IBinarySerializable +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int StartFrame { get; set; } + public int EndFrame { get; set; } + public int Field10 { get; set; } + public int SceneEndFrame { get; set; } + public int Field1C { get; set; } + public int Field24 { get; set; } + public int Field28 { get; set; } + public int Field2C { get; set; } + public string Name { get; set; } + public int Field50 { get; set; } + public int Field54 { get; set; } + public int Field58 { get; set; } + public int Field5C { get; set; } + public int[] UnknownArray { get; set; } + public byte[] Data { get; set; } + + public void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + StartFrame = reader.Read(); + EndFrame = reader.Read(); + Field10 = reader.Read(); + int dataSize = reader.Read(); + SceneEndFrame = reader.Read(); + Field1C = reader.Read(); + int unknownCount = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Name = reader.ReadString(StringBinaryFormat.FixedLength, 32); + + UnknownArray = new int[unknownCount]; + reader.ReadArray(unknownCount, UnknownArray); + + Data = new byte[dataSize]; + reader.ReadArray(dataSize, Data); + } + + public void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(StartFrame); + writer.Write(EndFrame); + writer.Write(Field10); + writer.Write(Data.Length); + writer.Write(SceneEndFrame); + writer.Write(Field1C); + writer.Write(UnknownArray.Length); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.WriteString(StringBinaryFormat.FixedLength, Name, 32); + + writer.WriteArray(UnknownArray); + writer.WriteArray(Data); + } +} diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivParameter.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivParameter.cs new file mode 100644 index 0000000..83a250e --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivParameter.cs @@ -0,0 +1,1474 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +public abstract class DivParameter : IBinarySerializable +{ + public abstract void Read(BinaryObjectReader reader); + + public abstract void Write(BinaryObjectWriter writer); +} + +public class DivCullDisabledParameter : DivParameter +{ + public DivCullDisabledParameter() { } + public DivCullDisabledParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) { } + + public override void Write(BinaryObjectWriter writer) { } +} + +public class DivMovieDisplayParameter : DivParameter +{ + public DivMovieDisplayParameter() { } + public DivMovieDisplayParameter(BinaryObjectReader reader) { } + + public override void Read(BinaryObjectReader reader) { } + public override void Write(BinaryObjectWriter writer) { } +} + +public class DivUnknownParameter : DivParameter +{ + public byte[] Data { get; set; } + public int Size { get; set; } + + public DivUnknownParameter() { } + public DivUnknownParameter(BinaryObjectReader reader, int size) + { + Size = size; + Data = new byte[Size * 4]; + + Read(reader); + } + + public override void Read(BinaryObjectReader reader) + { + reader.ReadArray(Size * 4, Data); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.WriteArrayFixedLength(Data, Size * 4); + } +} + +class DivDrawingOffParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + + public DivDrawingOffParameter() { } + public DivDrawingOffParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + } +} + +public class DivFadeParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivFadeParameter() { } + public DivFadeParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivEffectParameter : DivParameter +{ + public Matrix4x4 LocalTransform { get; set; } + public int Field40 { get; set; } + public string Name { get; set; } + public int Field84 { get; set; } + public int Field88 { get; set; } + public int Field8C { get; set; } + public int Field90 { get; set; } + public int Field94 { get; set; } + public int Field98 { get; set; } + public int Field9C { get; set; } + public int FieldA0 { get; set; } + public float[] FieldA4 { get; set; } = new float[128]; + + public DivEffectParameter() { } + public DivEffectParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + LocalTransform = reader.Read(); + Field40 = reader.Read(); + Name = reader.ReadDivString(64); + Field84 = reader.Read(); + Field88 = reader.Read(); + Field8C = reader.Read(); + Field90 = reader.Read(); + Field94 = reader.Read(); + Field98 = reader.Read(); + Field9C = reader.Read(); + FieldA0 = reader.Read(); + reader.ReadArray(128, FieldA4); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(LocalTransform); + writer.Write(Field40); + writer.WriteDivString(Name); + writer.Write(Field84); + writer.Write(Field88); + writer.Write(Field8C); + writer.Write(Field90); + writer.Write(Field94); + writer.Write(Field98); + writer.Write(Field9C); + writer.Write(FieldA0); + writer.WriteArrayFixedLength(FieldA4, 128); + } +} + +public class DivLetterboxParameter : DivParameter +{ + public float[] Values { get; set; } = new float[32]; + + public DivLetterboxParameter() { } + public DivLetterboxParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + reader.ReadArray(32, Values); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.WriteArrayFixedLength(Values, 32); + } +} + +public class DivUVAnimParameter : DivParameter +{ + public int Field00 { get; set; } + public string Name { get; set; } + public int Field44 { get; set; } + public float Field48 { get; set; } + public int Field4C { get; set; } + public int Field50 { get; set; } + + public DivUVAnimParameter() { } + public DivUVAnimParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Name = reader.ReadDivString(64); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + Field50 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteDivString(Name, 64); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + writer.Write(Field50); + } +} + +public class DivMaterialAnimParameter : DivParameter +{ + public int Field00 { get; set; } + public string Name { get; set; } + public int Field44 { get; set; } + public float Field48 { get; set; } + public int Field4C { get; set; } + public int Field50 { get; set; } + + public DivMaterialAnimParameter() { } + public DivMaterialAnimParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Name = reader.ReadDivString(64); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + Field50 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteDivString(Name, 64); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + writer.Write(Field50); + } +} + +public class DivChromaAberrParameter : DivParameter +{ + public float Field00 { get; set; } + public float Field04 { get; set; } + public float Field08 { get; set; } + public float Field0C { get; set; } + public float Field10 { get; set; } + public float Field14 { get; set; } + public float Field18 { get; set; } + public float Field1C { get; set; } + public float Field20 { get; set; } + public float Field24 { get; set; } + public float Field28 { get; set; } + public float Field2C { get; set; } + public float Field30 { get; set; } + public float Field34 { get; set; } + public float Field38 { get; set; } + public float Field3C { get; set; } + public float Field40 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivChromaAberrParameter() { } + public DivChromaAberrParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Field30 = reader.Read(); + Field34 = reader.Read(); + Field38 = reader.Read(); + Field3C = reader.Read(); + Field40 = reader.Read(); + + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.Write(Field30); + writer.Write(Field34); + writer.Write(Field38); + writer.Write(Field3C); + writer.Write(Field40); + + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivSoundParameter : DivParameter +{ + public string CueName { get; set; } + public int Field40 { get; set; } + public int Field44 { get; set; } + + public DivSoundParameter() { } + public DivSoundParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + CueName = reader.ReadDivString(64); + Field40 = reader.Read(); + Field44 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.WriteDivString(CueName); + writer.Write(Field40); + writer.Write(Field44); + } +} + +public class DivGameCameraParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + public float Field10 { get; set; } + public float Field14 { get; set; } + public float Field18 { get; set; } + public int Field1C { get; set; } + public int Field20 { get; set; } + public int Field24 { get; set; } + public float Field28 { get; set; } + public float Field2C { get; set; } + public float Field30 { get; set; } + public int Field34 { get; set; } + public int Field38 { get; set; } + public int Field3C { get; set; } + public int Field40 { get; set; } + public float Field44 { get; set; } + public int Field48 { get; set; } + public int Field4C { get; set; } + public float NearCullingPlane { get; set; } + public float FarCullingPlane { get; set; } + public float Field58 { get; set; } + public int Field5C { get; set; } + public int Field60 { get; set; } + public int Field64 { get; set; } + + public DivGameCameraParameter() { } + public DivGameCameraParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Field30 = reader.Read(); + Field34 = reader.Read(); + Field38 = reader.Read(); + Field3C = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + NearCullingPlane = reader.Read(); + FarCullingPlane = reader.Read(); + Field58 = reader.Read(); + Field5C = reader.Read(); + Field60 = reader.Read(); + Field64 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.Write(Field30); + writer.Write(Field34); + writer.Write(Field38); + writer.Write(Field3C); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + writer.Write(NearCullingPlane); + writer.Write(FarCullingPlane); + writer.Write(Field58); + writer.Write(Field5C); + writer.Write(Field60); + writer.Write(Field64); + } +} + +public class DivSubtitleParameter : DivParameter +{ + public string CellName { get; set; } + public SubtitleLanguage Language { get; set; } + public int Field14 { get; set; } + + public DivSubtitleParameter() { } + public DivSubtitleParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + CellName = reader.ReadDivString(16); + Language = (SubtitleLanguage)reader.Read(); + Field14 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.WriteDivString(CellName, 16); + writer.Write((int)Language); + writer.Write(Field14); + } + + public enum SubtitleLanguage + { + English = 0, + French = 1, + Italian = 2, + German = 3, + Spanish = 4, + Polish = 5, + Portuguese = 6, + Russian = 7, + Japanese = 8, + Chinese1 = 9, + Chinese2 = 10, + Korean = 11 + } +} + +public class DivQTEParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public float Field08 { get; set; } + public float Field0C { get; set; } + public float Field10 { get; set; } + public float Field14 { get; set; } + public float Field18 { get; set; } + public float Field1C { get; set; } + public float Field20 { get; set; } + public int Field24 { get; set; } + public int Field28 { get; set; } + public int Field2C { get; set; } + public int Field30 { get; set; } + public int Field34 { get; set; } + public int Field38 { get; set; } + public int Field3C { get; set; } + public int Field40 { get; set; } + public int Field44 { get; set; } + public int Field48 { get; set; } + public int Field4C { get; set; } + public int Field50 { get; set; } + public int Field54 { get; set; } + public int Field58 { get; set; } + public int Field5C { get; set; } + public int Field60 { get; set; } + public int Field64 { get; set; } + public int Field68 { get; set; } + public int Field6C { get; set; } + public float Field70 { get; set; } + public float Field74 { get; set; } + public float Field78 { get; set; } + public float Field7C { get; set; } + public int[] Field80 { get; set; } = new int[48]; + public string Field140 { get; set; } + + public DivQTEParameter() { } + public DivQTEParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Field30 = reader.Read(); + Field34 = reader.Read(); + Field38 = reader.Read(); + Field3C = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + Field50 = reader.Read(); + Field54 = reader.Read(); + Field58 = reader.Read(); + Field5C = reader.Read(); + Field60 = reader.Read(); + Field64 = reader.Read(); + Field68 = reader.Read(); + Field6C = reader.Read(); + Field70 = reader.Read(); + Field74 = reader.Read(); + Field78 = reader.Read(); + Field7C = reader.Read(); + reader.ReadArray(48, Field80); + + Field140 = reader.ReadDivString(64); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.Write(Field30); + writer.Write(Field34); + writer.Write(Field38); + writer.Write(Field3C); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + writer.Write(Field50); + writer.Write(Field54); + writer.Write(Field58); + writer.Write(Field5C); + writer.Write(Field60); + writer.Write(Field64); + writer.Write(Field68); + writer.Write(Field6C); + writer.Write(Field70); + writer.Write(Field74); + writer.Write(Field78); + writer.Write(Field7C); + writer.WriteArrayFixedLength(Field80, 48); + + writer.WriteDivString(Field140, 64); + } +} + +public class DivTimescaleParameter : DivParameter +{ + public int Field00 { get; set; } + public float Scale { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + + public DivTimescaleParameter() { } + public DivTimescaleParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Scale = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Scale); + writer.Write(Field08); + writer.Write(Field0C); + } +} + +public class DivVignetteParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public float Field08 { get; set; } + public float Field0C { get; set; } + public float Field10 { get; set; } + public float Field14 { get; set; } + public float Field18 { get; set; } + public float Field1C { get; set; } + public float Field20 { get; set; } + public int Field24 { get; set; } + public float Field28 { get; set; } + public float Field2C { get; set; } + public float Field30 { get; set; } + public float Field34 { get; set; } + public float Field38 { get; set; } + public float Field3C { get; set; } + public float Field40 { get; set; } + public float Field44 { get; set; } + public float Field48 { get; set; } + public float Field4C { get; set; } + public float Field50 { get; set; } + public float Field54 { get; set; } + public float Field58 { get; set; } + public float Field5C { get; set; } + public float Field60 { get; set; } + public float Field64 { get; set; } + public float Field68 { get; set; } + public float Field6C { get; set; } + public float Field70 { get; set; } + public float Field74 { get; set; } + public float Field78 { get; set; } + public float Field7C { get; set; } + public float Field80 { get; set; } + public float Field84 { get; set; } + public int Field88 { get; set; } + public float Field8C { get; set; } + public float Field90 { get; set; } + public float Field94 { get; set; } + public float Field98 { get; set; } + public float Field9C { get; set; } + public float FieldA0 { get; set; } + public float FieldA4 { get; set; } + public float FieldA8 { get; set; } + public float FieldAC { get; set; } + public float FieldB0 { get; set; } + public float FieldB4 { get; set; } + public float FieldB8 { get; set; } + public float FieldBC { get; set; } + public float FieldC0 { get; set; } + public float FieldC4 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivVignetteParameter() { } + public DivVignetteParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Field30 = reader.Read(); + Field34 = reader.Read(); + Field38 = reader.Read(); + Field3C = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + Field50 = reader.Read(); + Field54 = reader.Read(); + Field58 = reader.Read(); + Field5C = reader.Read(); + Field60 = reader.Read(); + Field64 = reader.Read(); + Field68 = reader.Read(); + Field6C = reader.Read(); + Field70 = reader.Read(); + Field74 = reader.Read(); + Field78 = reader.Read(); + Field7C = reader.Read(); + Field80 = reader.Read(); + Field84 = reader.Read(); + Field88 = reader.Read(); + Field8C = reader.Read(); + Field90 = reader.Read(); + Field94 = reader.Read(); + Field98 = reader.Read(); + Field9C = reader.Read(); + FieldA0 = reader.Read(); + FieldA4 = reader.Read(); + FieldA8 = reader.Read(); + FieldAC = reader.Read(); + FieldB0 = reader.Read(); + FieldB4 = reader.Read(); + FieldB8 = reader.Read(); + FieldBC = reader.Read(); + FieldC0 = reader.Read(); + FieldC4 = reader.Read(); + + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.Write(Field30); + writer.Write(Field34); + writer.Write(Field38); + writer.Write(Field3C); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + writer.Write(Field50); + writer.Write(Field54); + writer.Write(Field58); + writer.Write(Field5C); + writer.Write(Field60); + writer.Write(Field64); + writer.Write(Field68); + writer.Write(Field6C); + writer.Write(Field70); + writer.Write(Field74); + writer.Write(Field78); + writer.Write(Field7C); + writer.Write(Field80); + writer.Write(Field84); + writer.Write(Field88); + writer.Write(Field8C); + writer.Write(Field90); + writer.Write(Field94); + writer.Write(Field98); + writer.Write(Field9C); + writer.Write(FieldA0); + writer.Write(FieldA4); + writer.Write(FieldA8); + writer.Write(FieldAC); + writer.Write(FieldB0); + writer.Write(FieldB4); + writer.Write(FieldB8); + writer.Write(FieldBC); + writer.Write(FieldC0); + writer.Write(FieldC4); + + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivPathAdjustParameter : DivParameter +{ + public Matrix4x4 LocalTransform { get; set; } + public int Field40 { get; set; } + public int Field44 { get; set; } + public int Field48 { get; set; } + public int Field4C { get; set; } + + public DivPathAdjustParameter() { } + public DivPathAdjustParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + LocalTransform = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(LocalTransform); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + } +} + +public class DivBossCutoffParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + + public DivBossCutoffParameter() { } + public DivBossCutoffParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + } +} + +public class DivAuraParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public int Field08 { get; set; } + public int Field0C { get; set; } + public float Field10 { get; set; } + public float Field14 { get; set; } + public float Field18 { get; set; } + public float Field1C { get; set; } + public float Field20 { get; set; } + public int Field24 { get; set; } + public int Field28 { get; set; } + public int Field2C { get; set; } + public int Field30 { get; set; } + public float Field34 { get; set; } + public float Field38 { get; set; } + public float Field3C { get; set; } + public float Field40 { get; set; } + public float Field44 { get; set; } + public int Field48 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivAuraParameter() { } + public DivAuraParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Field30 = reader.Read(); + Field34 = reader.Read(); + Field38 = reader.Read(); + Field3C = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.Write(Field30); + writer.Write(Field34); + writer.Write(Field38); + writer.Write(Field3C); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivDOFParameter : DivParameter +{ + public int Field00 { get; set; } + public float Field04 { get; set; } + public float Field08 { get; set; } + public float Field0C { get; set; } + public float Field10 { get; set; } + public float Field14 { get; set; } + public float Field18 { get; set; } + public float Field1C { get; set; } + public float Field20 { get; set; } + public float Field24 { get; set; } + public float Field28 { get; set; } + public int Field2C { get; set; } + public int Field30 { get; set; } + public float Field34 { get; set; } + public int Field38 { get; set; } + public int Field3C { get; set; } + public int Field40 { get; set; } + public int Field44 { get; set; } + public int Field48 { get; set; } + public int Field4C { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivDOFParameter() { } + public DivDOFParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + Field24 = reader.Read(); + Field28 = reader.Read(); + Field2C = reader.Read(); + Field30 = reader.Read(); + Field34 = reader.Read(); + Field38 = reader.Read(); + Field3C = reader.Read(); + Field40 = reader.Read(); + Field44 = reader.Read(); + Field48 = reader.Read(); + Field4C = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.Write(Field24); + writer.Write(Field28); + writer.Write(Field2C); + writer.Write(Field30); + writer.Write(Field34); + writer.Write(Field38); + writer.Write(Field3C); + writer.Write(Field40); + writer.Write(Field44); + writer.Write(Field48); + writer.Write(Field4C); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivTheEndCableParameter : DivParameter +{ + public int Field00 { get; set; } + public int Field04 { get; set; } + public float[] Field08 { get; set; } = new float[1024]; + + public DivTheEndCableParameter() { } + public DivTheEndCableParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + reader.ReadArray(1024, Field08); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.WriteArrayFixedLength(Field08, 1024); + } +} + +public class DivCompositeAnimationParameter : DivParameter +{ + public int Field00 { get; set; } + public string Field04 { get; set; } + public Animation[] Animations { get; set; } = new Animation[16]; + public int Field450 { get; set; } + + public DivCompositeAnimationParameter() { } + public DivCompositeAnimationParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.ReadString(StringBinaryFormat.FixedLength, 12); + Animations = reader.ReadObjectArray(16); + Field450 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteString(StringBinaryFormat.FixedLength, Field04, 12); + writer.WriteObjectCollection(Animations); + writer.Write(Field450); + } + + public class Animation : IBinarySerializable + { + public int Type { get; set; } + public string Name { get; set; } + + public Animation() + { + Type = (int)AnimationType.None; + Name = ""; + } + + public void Read(BinaryObjectReader reader) + { + Type = reader.Read(); + Name = reader.ReadString(StringBinaryFormat.FixedLength, 64); + } + + public void Write(BinaryObjectWriter writer) + { + writer.Write(Type); + writer.WriteString(StringBinaryFormat.FixedLength, Name, 64); + } + } + + public enum AnimationType + { + None = 0, + PXD = 1, + UV = 2 + } +} + +public class DivASMParameter : DivParameter +{ + public string Field00 { get; set; } + public string Field40 { get; set; } + + public DivASMParameter() { } + public DivASMParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.ReadString(StringBinaryFormat.FixedLength, 64); + Field40 = reader.ReadString(StringBinaryFormat.FixedLength, 64); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.WriteString(StringBinaryFormat.FixedLength, Field00, 64); + writer.WriteString(StringBinaryFormat.FixedLength, Field40, 64); + } +} +public class DivGeneralPurposeTriggerParameter : DivParameter +{ + public uint Field00 { get; set; } + public string TriggerName { get; set; } + + public DivGeneralPurposeTriggerParameter() { } + public DivGeneralPurposeTriggerParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + TriggerName = reader.ReadString(StringBinaryFormat.FixedLength, 64); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteString(StringBinaryFormat.FixedLength, TriggerName, 64); + } +} + +public class DivCameraBlurParameter : DivParameter +{ + public uint Field00 { get; set; } + public uint Field04 { get; set; } + public float Field08 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + public uint Flags { get; set; } + + public DivCameraBlurParameter() { } + public DivCameraBlurParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + Flags = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + writer.Write(Flags); + } +} + +public class DivShadowResolutionParameter : DivParameter +{ + public Vector2Int Resolution { get; set; } + + public DivShadowResolutionParameter() { } + public DivShadowResolutionParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Resolution = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Resolution); + } +} + +public class DivTimeParameter : DivParameter +{ + public uint Field00 { get; set; } + public uint Field04 { get; set; } + public uint Field08 { get; set; } + public uint Field0C { get; set; } + public uint Field10 { get; set; } + public uint Field14 { get; set; } + public uint Field18 { get; set; } + public uint Field1C { get; set; } + public uint Field20 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivTimeParameter() { } + public DivTimeParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + Field20 = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.Write(Field20); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivWeatherParameter : DivParameter +{ + public uint Field00 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivWeatherParameter() { } + public DivWeatherParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivFinalBossLightingParameter : DivParameter +{ + public DivFinalBossLightingParameter() { } + public DivFinalBossLightingParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) { } + + public override void Write(BinaryObjectWriter writer) { } +} + +public class DivCyberNoiseParameter : DivParameter +{ + public uint Field00 { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivCyberNoiseParameter() { } + public DivCyberNoiseParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivDitherDepthParameter : DivParameter +{ + public uint Field00 { get; set; } + public float Field04 { get; set; } + + public DivDitherDepthParameter() { } + public DivDitherDepthParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + } +} + +public class DivCameraExposureParameter : DivParameter +{ + public uint Field00 { get; set; } + public float Field04 { get; set; } + public uint Field08 { get; set; } + public uint Field0C { get; set; } + public uint Field10 { get; set; } + public uint Field14 { get; set; } + public uint Field18 { get; set; } + public uint Field1C { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivCameraExposureParameter() { } + public DivCameraExposureParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +public class DivColorCorrectionParameter : DivParameter +{ + public uint Field00 { get; set; } + public float Field04 { get; set; } + public float Field08 { get; set; } + public float Field0C { get; set; } + public float Field10 { get; set; } + public uint Field14 { get; set; } + public float Field18 { get; set; } + public uint Field1C { get; set; } + public float[] ValuesTimeline { get; set; } = new float[32]; + + public DivColorCorrectionParameter() { } + public DivColorCorrectionParameter(BinaryObjectReader reader) + => Read(reader); + + public override void Read(BinaryObjectReader reader) + { + Field00 = reader.Read(); + Field04 = reader.Read(); + Field08 = reader.Read(); + Field0C = reader.Read(); + Field10 = reader.Read(); + Field14 = reader.Read(); + Field18 = reader.Read(); + Field1C = reader.Read(); + reader.ReadArray(32, ValuesTimeline); + } + + public override void Write(BinaryObjectWriter writer) + { + writer.Write(Field00); + writer.Write(Field04); + writer.Write(Field08); + writer.Write(Field0C); + writer.Write(Field10); + writer.Write(Field14); + writer.Write(Field18); + writer.Write(Field1C); + writer.WriteArrayFixedLength(ValuesTimeline, 32); + } +} + +// < 1000 values appear to be shared between games, the others are game-specific. +public enum ParameterType +{ + ParameterSpecifiedCamera = 1, + DrawingOff = 3, + PathAdjust = 5, + CameraShake = 6, + CameraShakeLoop = 7, + Effect = 8, + PathInterpolation = 10, + CullDisabled = 11, + NearFarSetting = 12, + UVAnimation = 13, + VisibilityAnimation = 14, + MaterialAnimation = 15, + CompositeAnimation = 16, + CameraOffset = 17, + ModelFade = 18, + SonicCamera = 20, + GameCamera = 21, + PointLightSource = 22, + ControllerVibration = 25, + SpotlightModel = 26, + MaterialParameter = 27, +} + +enum FrontiersParams +{ + DepthOfField = 1001, + ColorCorrection = 1002, + CameraExposure = 1003, + ShadowResolution = 1004, + HeightFog = 1007, + ChromaticAberration = 1008, + Vignette = 1009, + Fade = 1010, + Letterbox = 1011, + ModelClipping = 1012, + BossCutoff = 1014, + Subtitle = 1015, + Sound = 1016, + Time = 1017, + LookAtIK = 1019, + CameraBlur = 1020, + GeneralPurposeTrigger = 1021, + DitherDepth = 1023, + QTE = 1024, + FacialAnimation = 1025, + ASMForcedOverwrite = 1026, + Aura = 1027, + TimescaleChange = 1028, + CyberNoise = 1029, + AuraRoad = 1031, + MovieDisplay = 1032, + Weather = 1034, + PointLightSource = 1036, + TheEndCable = 1042, + FinalBossLighting = 1043 +} + +enum ShadowGensParams +{ + DepthOfField = 1001, + HeightFog = 1009, + ChromaticAberration = 1010, + Vignette = 1011, + Fade = 1012, + BossCutoff = 1016, + Subtitle = 1017, + Sound = 1018, + CameraBlur = 1022, + GeneralPurposeTrigger = 1023, + QTE = 1026, + TimescaleChange = 1030, + TimeStop = 1041, + DepthOfFieldNew = 1047, +} \ No newline at end of file diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivResource.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivResource.cs new file mode 100644 index 0000000..11c18f7 --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivResource.cs @@ -0,0 +1,54 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +public class DivResource : IBinarySerializable +{ + public Guid GUID { get; set; } + public bool UnknownFlag { get; set; } + public ResourceType ResType { get; set; } + public int Field14 { get; set; } + public int Field18 { get; set; } + public string Name { get; set; } + + public DivResource() { } + + public DivResource(string name) + { + Name = name; + GUID = Guid.NewGuid(); + } + + public DivResource(string name, ResourceType type) : this(name) + { + ResType = type; + } + + public void Read(BinaryObjectReader reader) + { + GUID = reader.Read(); + + int resourceFlags = reader.Read(); + UnknownFlag = (resourceFlags & 1) == 1; + ResType = (ResourceType)(resourceFlags >> 1); + + Field14 = reader.Read(); + Field18 = reader.Read(); + Name = reader.ReadString(StringBinaryFormat.FixedLength, 788); + } + + public void Write(BinaryObjectWriter writer) + { + writer.Write(GUID); + writer.Write(((int)ResType << 1) | (UnknownFlag ? 1 : 0)); + writer.Write(Field14); + writer.Write(Field18); + writer.WriteString(StringBinaryFormat.FixedLength, Name, 788); + } +} + +public enum ResourceType +{ + None = 0, + AnimationStateMachine = 1, + CameraAnimation = 2, + AnimationPxd = 3, +} \ No newline at end of file diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivScene.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivScene.cs new file mode 100644 index 0000000..6a43657 --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivScene.cs @@ -0,0 +1,229 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +using System.IO; + +[NeedleResource("st/dv-scene", @"\.dvscene$")] +public class DivScene : ResourceBase, IBinarySerializable +{ + public float Duration { get; set; } + public int Field10 { get; set; } + public List UnknownList0 { get; set; } = new(); + public List Pages { get; set; } = new(); + public List UnknownList1 { get; set; } = new(); + public DivNode RootNode { get; set; } = new(); + public float Field2C { get; set; } + public float Field30 { get; set; } + public List Resources { get; set; } = new(); + + public DivScene() + { + // Register encoding provider for Shift-JIS strings + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + } + + public override void Read(IFile file) + { + BaseFile = file; + Name = Path.GetFileNameWithoutExtension(file.Name); + + using var reader = new BinaryObjectReader(file.Open(), StreamOwnership.Transfer, Endianness.Little); + reader.OffsetBinaryFormat = OffsetBinaryFormat.U32; + + Read(reader); + } + + public override void Write(IFile file) + { + BaseFile = file; + + using var writer = new BinaryObjectWriter(file.Open(FileAccess.Write), StreamOwnership.Transfer, Endianness.Little); + writer.OffsetBinaryFormat = OffsetBinaryFormat.U32; + + Write(writer); + } + + public void Read(BinaryObjectReader reader) + { + // Header + long dataOffset = reader.ReadOffsetValue(); + long resourcesOffset = reader.ReadOffsetValue(); + reader.Skip(24); + + reader.PushOffsetOrigin(); + + reader.Seek(dataOffset + 32, SeekOrigin.Begin); + { + reader.Skip(12); + + Duration = reader.Read(); + Field10 = reader.Read(); + + reader.ReadOffset(() => + { + int triggerCount = reader.Read(); + reader.Skip(12); + + reader.ReadCollection(triggerCount, UnknownList0); + }); + + reader.ReadOffset(() => + { + int pageCount = reader.Read(); + int pageChunkSize = reader.Read(); + + reader.Skip(8); + + Pages.AddRange(reader.ReadObjectArray(pageCount)); + }); + + reader.ReadOffset(() => + { + int unknownCount = reader.Read(); + reader.Skip(12); + }); + + reader.ReadOffset(() => + { + int unknownCount = reader.Read(); + reader.Skip(12); + + reader.ReadCollection(unknownCount, UnknownList1); + }); + + reader.ReadOffset(() => + { + int unknownCount = reader.Read(); + reader.Skip(12); + }); + + reader.ReadOffset(() => + { + RootNode.Read(reader); + }); + + Field2C = reader.Read(); + Field30 = reader.Read(); + reader.Skip(12); + } + + reader.ReadAtOffset(resourcesOffset, () => + { + int resourceCount = reader.Read(); + reader.Skip(12); + + Resources.AddRange(reader.ReadObjectArray(resourceCount)); + }); + } + + public void Write(BinaryObjectWriter writer) + { + long resourcesOffsetPos = writer.Position + 4; + + writer.WriteNulls(32); + long dataPos = writer.Position; + + { + writer.WriteNulls(12); + writer.Write(Duration); + writer.Write(Field10); + + long unknownList0OffsetPos = writer.Position; + long pagesOffsetPos = writer.Position + 4; + long unknownList2OffsetPos = writer.Position + 8; + long unknownList3OffsetPos = writer.Position + 12; + long unknownList4OffsetPos = writer.Position + 16; + long rootNodeOffsetPos = writer.Position + 20; + writer.WriteNulls(24); + + writer.Write(Field2C); + writer.Write(Field30); + writer.WriteNulls(12); + + { + long unknownList0Pos = writer.Position; + writer.Seek(unknownList0OffsetPos, SeekOrigin.Begin); + writer.Write((int)(unknownList0Pos - dataPos)); + writer.Seek(unknownList0Pos, SeekOrigin.Begin); + + writer.Write(UnknownList0.Count); + writer.WriteNulls(12); + writer.WriteCollection(UnknownList0); + } + + { + long pagesPos = writer.Position; + writer.Seek(pagesOffsetPos, SeekOrigin.Begin); + writer.Write((int)(pagesPos - dataPos)); + writer.Seek(pagesPos, SeekOrigin.Begin); + + writer.Write(Pages.Count); + long pageChunkSizePos = writer.Position; + writer.WriteNulls(12); + + writer.WriteObjectCollection(Pages); + + long pageChunkEndPos = writer.Position; + long pageChunkSize = pageChunkEndPos - (pageChunkSizePos + 12); + writer.Seek(pageChunkSizePos, SeekOrigin.Begin); + writer.Write((int)pageChunkSize); + writer.Seek(pageChunkSize, SeekOrigin.Begin); + } + + { + long unknownList2Pos = writer.Position; + writer.Seek(unknownList2OffsetPos, SeekOrigin.Begin); + writer.Write((int)(unknownList2Pos - dataPos)); + writer.Seek(unknownList2Pos, SeekOrigin.Begin); + + writer.WriteNulls(16); + } + + { + long unknownList3Pos = writer.Position; + writer.Seek(unknownList3OffsetPos, SeekOrigin.Begin); + writer.Write((int)(unknownList3Pos - dataPos)); + writer.Seek(unknownList3Pos, SeekOrigin.Begin); + + writer.Write(UnknownList1.Count); + writer.WriteNulls(12); + writer.WriteCollection(UnknownList1); + } + + { + long unknownList4Pos = writer.Position; + writer.Seek(unknownList4OffsetPos, SeekOrigin.Begin); + writer.Write((int)(unknownList4Pos - dataPos)); + writer.Seek(unknownList4Pos, SeekOrigin.Begin); + + writer.WriteNulls(16); + } + + { + long rootNodePos = writer.Position; + writer.Seek(rootNodeOffsetPos, SeekOrigin.Begin); + writer.Write((int)(rootNodePos - dataPos)); + writer.Seek(rootNodePos, SeekOrigin.Begin); + + RootNode.Write(writer); + } + } + + { + long resourcesPos = writer.Position; + writer.Seek(resourcesOffsetPos, SeekOrigin.Begin); + writer.Write((int)(resourcesPos - dataPos)); + writer.Seek(resourcesPos, SeekOrigin.Begin); + + writer.Write(Resources.Count); + writer.WriteNulls(12); + + writer.WriteObjectCollection(Resources); + } + } +} + +public enum GameType +{ + Frontiers, + ShadowGenerations +} \ No newline at end of file diff --git a/Source/SharpNeedle/SonicTeam/DivScene/DivTypes.cs b/Source/SharpNeedle/SonicTeam/DivScene/DivTypes.cs new file mode 100644 index 0000000..99d8f1e --- /dev/null +++ b/Source/SharpNeedle/SonicTeam/DivScene/DivTypes.cs @@ -0,0 +1,25 @@ +namespace SharpNeedle.SonicTeam.DivScene; + +public static class DivString +{ + public static string ReadDivString(this BinaryObjectReader reader, int fixedLength = 64) + { + // Shift-JIS encoded data + Span data = new byte[fixedLength]; + reader.ReadArray(fixedLength, data); + + Encoding shiftJIS = Encoding.GetEncoding(932); + return shiftJIS.GetString(data).Replace("\0", string.Empty); + } + + public static void WriteDivString(this BinaryObjectWriter writer, string value, int fixedLength = 64) + { + // Shift-JIS encoded data + Span data = new byte[fixedLength]; + + Encoding shiftJIS = Encoding.GetEncoding(932); + shiftJIS.GetBytes(value).CopyTo(data); + + writer.WriteArrayFixedLength(data, fixedLength); + } +} \ No newline at end of file diff --git a/Source/SharpNeedle/Utilities/BinaryHelper.cs b/Source/SharpNeedle/Utilities/BinaryHelper.cs index 4bae599..0df2102 100644 --- a/Source/SharpNeedle/Utilities/BinaryHelper.cs +++ b/Source/SharpNeedle/Utilities/BinaryHelper.cs @@ -208,4 +208,10 @@ public static void WriteArrayFixedLength(this BinaryObjectWriter writer, Span public static void WriteArrayFixedLength(this BinaryObjectWriter writer, T[] array, int length) where T : unmanaged => WriteArrayFixedLength(writer, array.AsSpan(), length); + + public static void WriteNulls(this BinaryObjectWriter writer, int length) + { + Span nulls = new byte[length]; + writer.WriteArray(nulls); + } } \ No newline at end of file