From 834442e5142a29458ca0d0d932f7b1528b01281d Mon Sep 17 00:00:00 2001 From: KujiKita Date: Sat, 25 May 2019 13:26:08 +0300 Subject: [PATCH] Release v0.4.5.7 Some fixes and changes --- .gitignore | 9 + KKdMainLib/A3DA/A3DA.cs | 2343 ++++++++++++++++++++++++ KKdMainLib/A3DA/A3DAExt.cs | 390 ++++ KKdMainLib/DB/Auth.cs | 173 ++ KKdMainLib/DEX.cs | 293 +++ KKdMainLib/DIVAFILE.cs | 64 + KKdMainLib/FARC.cs | 356 ++++ KKdMainLib/IO/File.cs | 50 + KKdMainLib/IO/IOExtensions.cs | 21 + KKdMainLib/IO/Stream.cs | 399 ++++ KKdMainLib/KKdMainLib.csproj | 68 + KKdMainLib/Main.cs | 360 ++++ KKdMainLib/MathExtensions.cs | 196 ++ KKdMainLib/MessagePack/IO.cs | 339 ++++ KKdMainLib/MessagePack/MsgPack.cs | 291 +++ KKdMainLib/PDHeader.cs | 63 + KKdMainLib/POF.cs | 113 ++ KKdMainLib/Properties/AssemblyInfo.cs | 15 + KKdMainLib/STR.cs | 227 +++ KKdMainLib/Text.cs | 17 + KKdMainLib/Types/Half.cs | 102 ++ KKdMainLib/Xml.cs | 102 ++ KKdSoundLib/DIVA.cs | 214 +++ KKdSoundLib/Extensions.cs | 94 + KKdSoundLib/KKdSoundLib.csproj | 59 + KKdSoundLib/Properties/AssemblyInfo.cs | 15 + KKdSoundLib/VAG.cs | 792 ++++++++ KKdSoundLib/WAV.cs | 23 + PD_Tool.sln | 37 + PD_Tool/PD_Tool.csproj | 69 + PD_Tool/Program.cs | 113 ++ PD_Tool/Properties/AssemblyInfo.cs | 15 + PD_Tool/classes/DIVAFILE.cs | 34 + PD_Tool/classes/DataBase.cs | 54 + PD_Tool/classes/FARC.cs | 54 + PD_Tool/classes/Tools/A3D.cs | 82 + PD_Tool/classes/Tools/DEX.cs | 61 + PD_Tool/classes/Tools/DIV.cs | 38 + PD_Tool/classes/Tools/STR.cs | 39 + PD_Tool/classes/Tools/VAG.cs | 59 + README.md | 18 + 41 files changed, 7861 insertions(+) create mode 100644 .gitignore create mode 100644 KKdMainLib/A3DA/A3DA.cs create mode 100644 KKdMainLib/A3DA/A3DAExt.cs create mode 100644 KKdMainLib/DB/Auth.cs create mode 100644 KKdMainLib/DEX.cs create mode 100644 KKdMainLib/DIVAFILE.cs create mode 100644 KKdMainLib/FARC.cs create mode 100644 KKdMainLib/IO/File.cs create mode 100644 KKdMainLib/IO/IOExtensions.cs create mode 100644 KKdMainLib/IO/Stream.cs create mode 100644 KKdMainLib/KKdMainLib.csproj create mode 100644 KKdMainLib/Main.cs create mode 100644 KKdMainLib/MathExtensions.cs create mode 100644 KKdMainLib/MessagePack/IO.cs create mode 100644 KKdMainLib/MessagePack/MsgPack.cs create mode 100644 KKdMainLib/PDHeader.cs create mode 100644 KKdMainLib/POF.cs create mode 100644 KKdMainLib/Properties/AssemblyInfo.cs create mode 100644 KKdMainLib/STR.cs create mode 100644 KKdMainLib/Text.cs create mode 100644 KKdMainLib/Types/Half.cs create mode 100644 KKdMainLib/Xml.cs create mode 100644 KKdSoundLib/DIVA.cs create mode 100644 KKdSoundLib/Extensions.cs create mode 100644 KKdSoundLib/KKdSoundLib.csproj create mode 100644 KKdSoundLib/Properties/AssemblyInfo.cs create mode 100644 KKdSoundLib/VAG.cs create mode 100644 KKdSoundLib/WAV.cs create mode 100644 PD_Tool.sln create mode 100644 PD_Tool/PD_Tool.csproj create mode 100644 PD_Tool/Program.cs create mode 100644 PD_Tool/Properties/AssemblyInfo.cs create mode 100644 PD_Tool/classes/DIVAFILE.cs create mode 100644 PD_Tool/classes/DataBase.cs create mode 100644 PD_Tool/classes/FARC.cs create mode 100644 PD_Tool/classes/Tools/A3D.cs create mode 100644 PD_Tool/classes/Tools/DEX.cs create mode 100644 PD_Tool/classes/Tools/DIV.cs create mode 100644 PD_Tool/classes/Tools/STR.cs create mode 100644 PD_Tool/classes/Tools/VAG.cs create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15a263f --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.vs +build +KKdMainLib/bin +KKdMainLib/obj +KKdMathLib/bin +KKdMathLib/obj +KKdSoundLib/bin +KKdSoundLib/obj +PD_Tool/obj diff --git a/KKdMainLib/A3DA/A3DA.cs b/KKdMainLib/A3DA/A3DA.cs new file mode 100644 index 0000000..16393d7 --- /dev/null +++ b/KKdMainLib/A3DA/A3DA.cs @@ -0,0 +1,2343 @@ +using System; +using System.Collections.Generic; +using KKdMainLib.IO; +using KKdMainLib.Types; +using KKdMainLib.MessagePack; +using MPIO = KKdMainLib.MessagePack.IO; + +namespace KKdMainLib.A3DA +{ + public class A3DA + { + private const bool A3DCOpt = true; + private const string d = "."; + private const string BO = "bin_offset"; + private const string MTBO = "model_transform.bin_offset"; + + private int SOi0; + private int SOi1; + private int[] SO0; + private int[] SO1; + private string name; + private string nameView; + private string value; + private string[] dataArray; + private MsgPack MsgPack; + private Values UsedValues; + private Dictionary Dict; + + private bool IsX => Data.Header.Format == Main.Format.X || Data.Header.Format == Main.Format.XHD; + + public Stream IO; + public A3DAData Data; + + public A3DA() + { Data = new A3DAData(); Dict = new Dictionary(); + IO = File.OpenWriter(); UsedValues = new Values(); } + + public int A3DAReader(string file) + { + name = ""; + nameView = ""; + dataArray = new string[4]; + Dict = new Dictionary(); + Data = new A3DAData { Header = new PDHead() }; + + IO = File.OpenReader(file + ".a3da"); + Data.Header.Format = IO.Format = Main.Format.F; + Data.Header.Signature = IO.ReadInt32(); + if (Data.Header.Signature == 0x41443341) Data.Header = IO.ReadHeader(true); + if (Data.Header.Signature != 0x44334123) return 0; + + IO.Offset = IO.Position - 4; + Data.Header.Signature = IO.ReadInt32(); + + if (Data.Header.Signature == 0x5F5F5F41) + { + IO.Position = 0x10; + Data.Header.Format = IO.Format = Main.Format.DT; + } + else if (Data.Header.Signature == 0x5F5F5F43) + { + Data.Head = new Header(); + IO.Position = IO.Offset + 0x10; + IO.ReadInt32(); + IO.ReadInt32(); + Data.Head.HeaderOffset = IO.ReadInt32Endian(true); + + IO.Position = IO.Offset + Data.Head.HeaderOffset; + if (IO.ReadInt32() != 0x50) return 0; + Data.Head.StringOffset = IO.ReadInt32Endian(true); + Data.Head.StringLength = IO.ReadInt32Endian(true); + Data.Head.Count = IO.ReadInt32Endian(true); + if (IO.ReadInt32() != 0x4C42) return 0; + Data.Head.BinaryOffset = IO.ReadInt32Endian(true); + Data.Head.BinaryLength = IO.ReadInt32Endian(true); + + IO.Position = IO.Offset + Data.Head.StringOffset; + } + else return 0; + + if (Data.Header.Format < Main.Format.F || Data.Header.Format == Main.Format.FT) + Data.Head.StringLength = IO.Length - 0x10; + + string[] STRData = IO.ReadString(Data.Head.StringLength).Replace("\r", "").Split('\n'); + for (int i = 0; i < STRData.Length; i++) + { + dataArray = STRData[i].Split('='); + if (dataArray.Length == 2) + Dict.GetDictionary(dataArray[0], dataArray[1]); + } + STRData = null; + + A3DAReader(); + + if (Data.Header.Format == Main.Format.F || Data.Header.Format > Main.Format.FT) + { + IO.Position = IO.Offset + Data.Head.BinaryOffset; + IO.Offset = IO.Position; + A3DCReader(); + } + + IO.Close(); + + name = ""; + nameView = ""; + dataArray = null; + Dict = null; + return 1; + } + + private void A3DAReader() + { + int i0 = 0; + int i1 = 0; + + if (Dict.StartsWith("_")) + { + Data._ = new _(); + Dict.FindValue(out Data._.CompressF16 , "_.compress_f16" ); + Dict.FindValue(out Data._.ConverterVersion, "_.converter.version"); + Dict.FindValue(out Data._.FileName , "_.file_name" ); + Dict.FindValue(out Data._.PropertyVersion , "_.property.version" ); + } + + if (Dict.StartsWith("camera_auxiliary")) + { + name = "camera_auxiliary" + d; + + Data.CameraAuxiliary = new CameraAuxiliary + { + AutoExposure = Dict.ReadKey(name + "auto_exposure" + d), + Exposure = Dict.ReadKey(name + "exposure" + d), + Gamma = Dict.ReadKey(name + "gamma" + d), + GammaRate = Dict.ReadKey(name + "gamma_rate" + d), + Saturate = Dict.ReadKey(name + "saturate" + d) + }; + } + + if (Dict.StartsWith("play_control")) + { + name = "play_control" + d; + + Data.PlayControl = new PlayControl(); + Dict.FindValue(out Data.PlayControl.Begin , name + "begin" ); + Dict.FindValue(out Data.PlayControl.Div , name + "div" ); + Dict.FindValue(out Data.PlayControl.FPS , name + "fps" ); + Dict.FindValue(out Data.PlayControl.Offset, name + "offset"); + Dict.FindValue(out Data.PlayControl.Size , name + "size" ); + } + + if (Dict.StartsWith("post_process")) + { + name = "post_process" + d; + + Data.PostProcess = new PostProcess() + { + Ambient = Dict.ReadRGBAKey(name + "Ambient" + d), + Diffuse = Dict.ReadRGBAKey(name + "Diffuse" + d), + Specular = Dict.ReadRGBAKey(name + "Specular" + d), + LensFlare = Dict.ReadKey (name + "lens_flare" + d), + LensGhost = Dict.ReadKey (name + "lens_ghost" + d), + LensShaft = Dict.ReadKey (name + "lens_shaft" + d), + }; + } + + if (Dict.FindValue(out value, "dof.name")) + { + Data.DOF = new DOF { Name = value }; + Data.Header.Format = Main.Format.FT; + Data.DOF.MT = Dict.ReadMT("dof" + d); + } + + if (Dict.FindValue(out value, "ambient.length")) + { + Data.Ambient = new Ambient[int.Parse(value)]; + Data.Header.Format = Main.Format.MGF; + for (i0 = 0; i0 < Data.Ambient.Length; i0++) + { + name = "ambient" + d + i0 + d; + Dict.FindValue(out Data.Ambient[i0].Name, name + "name"); + Data.Ambient[i0]. LightDiffuse = Dict.ReadRGBAKey(name + "light.Diffuse" + d); + Data.Ambient[i0].RimLightDiffuse = Dict.ReadRGBAKey(name + "rimlight.Diffuse" + d); + } + } + + if (Dict.FindValue(out value, "camera_root.length")) + { + Data.CameraRoot = new CameraRoot[int.Parse(value)]; + for (i0 = 0; i0 < Data.CameraRoot.Length; i0++) + { + name = "camera_root" + d + i0 + d; + nameView = name + "view_point" + d; + + Dict.FindValue(out Data.CameraRoot[i0].ViewPoint. + Aspect , nameView + "aspect" ); + Dict.FindValue(out Data.CameraRoot[i0].ViewPoint. + CameraApertureH, nameView + "camera_aperture_h"); + Dict.FindValue(out Data.CameraRoot[i0].ViewPoint. + CameraApertureW, nameView + "camera_aperture_w"); + Dict.FindValue(out Data.CameraRoot[i0].ViewPoint. + FOVHorizontal , nameView + "fov_is_horizontal"); + + Data.CameraRoot[i0].MT = Dict.ReadMT(name); + Data.CameraRoot[i0].Interest = Dict.ReadMT(name + "interest" + d); + Data.CameraRoot[i0].ViewPoint.MT = Dict.ReadMT(nameView); + Data.CameraRoot[i0].ViewPoint.FocalLength = Dict.ReadKey(nameView + "focal_length" + d); + Data.CameraRoot[i0].ViewPoint.FOV = Dict.ReadKey(nameView + "fov" + d); + Data.CameraRoot[i0].ViewPoint.Roll = Dict.ReadKey(nameView + "roll" + d); + } + } + + if (Dict.FindValue(out value, "chara.length")) + { + Data.Chara = new ModelTransform[int.Parse(value)]; + for (i0 = 0; i0 < Data.Chara.Length; i0++) + Data.Chara[i0] = Dict.ReadMT("chara" + d + i0 + d); + } + + if (Dict.FindValue(out value, "curve.length")) + { + Data.Curve = new Curve[int.Parse(value)]; + for (i0 = 0; i0 < Data.Curve.Length; i0++) + { + name = "curve" + d + i0 + d; + + Dict.FindValue(out Data.Curve[i0].Name, name + "name"); + Data.Curve[i0].CV = Dict.ReadKey(name + "cv" + d); + } + } + + if (Dict.FindValue(out value, "event.length")) + { + Data.Event = new Event[int.Parse(value)]; + for (i0 = 0; i0 < Data.Event.Length; i0++) + { + name = "event" + d + i0 + d; + + Dict.FindValue(out Data.Event[i0].Begin , name + "begin" ); + Dict.FindValue(out Data.Event[i0].ClipBegin , name + "clip_begin" ); + Dict.FindValue(out Data.Event[i0].ClipEnd , name + "clip_en" ); + Dict.FindValue(out Data.Event[i0].End , name + "end" ); + Dict.FindValue(out Data.Event[i0].Name , name + "name" ); + Dict.FindValue(out Data.Event[i0].Param1 , name + "param1" ); + Dict.FindValue(out Data.Event[i0].Ref , name + "ref" ); + Dict.FindValue(out Data.Event[i0].TimeRefScale, name + "time_ref_scale"); + Dict.FindValue(out Data.Event[i0].Type , name + "type" ); + } + } + + if (Dict.FindValue(out value, "fog.length")) + { + Data.Fog = new Fog[int.Parse(value)]; + for (i0 = 0; i0 < Data.Fog.Length; i0++) + { + name = "fog" + d + i0 + d; + + Dict.FindValue(out Data.Fog[i0].Id, name + "id"); + Data.Fog[i0].Density = Dict.ReadKey (name + "density" + d); + Data.Fog[i0].Diffuse = Dict.ReadRGBAKey(name + "Diffuse" + d); + Data.Fog[i0].End = Dict.ReadKey (name + "end" + d); + Data.Fog[i0].Start = Dict.ReadKey (name + "start" + d); + } + } + + if (Dict.FindValue(out value, "light.length")) + { + Data.Light = new Light[int.Parse(value)]; + for (i0 = 0; i0 < Data.Light.Length; i0++) + { + name = "light" + d + i0 + d; + + Dict.FindValue(out Data.Light[i0].Id , name + "id" ); + Dict.FindValue(out Data.Light[i0].Name, name + "name"); + Dict.FindValue(out Data.Light[i0].Type, name + "type"); + + Data.Light[i0].Ambient = Dict.ReadRGBAKey(name + "Ambient" + d); + Data.Light[i0].Diffuse = Dict.ReadRGBAKey(name + "Diffuse" + d); + Data.Light[i0].Incandescence = Dict.ReadRGBAKey(name + "Incandescence" + d); + Data.Light[i0].Specular = Dict.ReadRGBAKey(name + "Specular" + d); + Data.Light[i0].Position = Dict.ReadMT (name + "position" + d); + Data.Light[i0].SpotDirection = Dict.ReadMT (name + "spot_direction" + d); + } + } + + if (Dict.FindValue(out value, "m_objhrc.length")) + { + Data.MObjectHRC = new MObjectHRC[int.Parse(value)]; + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + name = "m_objhrc" + d + i0 + d; + + if (Dict.StartsWith(name + "joint_orient")) + { + Data.MObjectHRC[i0].JointOrient = new Vector3(); + Dict.FindValue(out Data.MObjectHRC[i0].JointOrient.X, name + "joint_orient.x"); + Dict.FindValue(out Data.MObjectHRC[i0].JointOrient.Y, name + "joint_orient.y"); + Dict.FindValue(out Data.MObjectHRC[i0].JointOrient.Z, name + "joint_orient.z"); + } + + if (Dict.FindValue(out value, name + "instance.length")) + { + Data.MObjectHRC[i0].Instance = new Instance[int.Parse(value)]; + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + { + nameView = name + "instance" + d + i1 + d; + + Dict.FindValue(out Data.MObjectHRC[i0].Instance[i1]. Name, nameView + "name"); + Dict.FindValue(out Data.MObjectHRC[i0].Instance[i1]. Shadow, nameView + "shadow"); + Dict.FindValue(out Data.MObjectHRC[i0].Instance[i1].UIDName, nameView + "uid_name"); + + Data.MObjectHRC[i0].Instance[i1].MT = Dict.ReadMT(name); + } + } + + if (Dict.FindValue(out value, name + "node.length")) + { + Data.MObjectHRC[i0].Node = new Node[int.Parse(value)]; + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + { + nameView = name + "node" + d + i1 + d; + Dict.FindValue(out Data.MObjectHRC[i0].Node[i1].Name , nameView + "name" ); + Dict.FindValue(out Data.MObjectHRC[i0].Node[i1].Parent, nameView + "parent"); + + Data.MObjectHRC[i0].Node[i1].MT = Dict.ReadMT(name); + } + } + + Data.MObjectHRC[i0].MT = Dict.ReadMT(name); + } + } + + if (Dict.FindValue(out value, "m_objhrc_list.length")) + { + Data.MObjectHRCList = new string[int.Parse(value)]; + for (i0 = 0; i0 < Data.MObjectHRCList.Length; i0++) + Dict.FindValue(out Data.MObjectHRCList[i0], "m_objhrc_list" + d + i0); + } + + if (Dict.FindValue(out value, "material_list.length")) + { + Data.MaterialList = new MaterialList[int.Parse(value)]; + Data.Header.Format = Main.Format.X; + for (i0 = 0; i0 < Data.MaterialList.Length; i0++) + { + name = "material_list" + d + i0 + d; + Dict.FindValue(out Data.MaterialList[i0].HashName, name + "hash_name"); + Dict.FindValue(out Data.MaterialList[i0]. Name, name + "name"); + + Data.MaterialList[i0].BlendColor = Dict.ReadRGBAKey(name + "blend_color" + d); + Data.MaterialList[i0].GlowIntensity = Dict.ReadKey (name + "glow_intensity" + d); + Data.MaterialList[i0].Incandescence = Dict.ReadRGBAKey(name + "incandescence" + d); + } + } + + if (Dict.FindValue(out value, "motion.length")) + { + Data.Motion = new string[int.Parse(value)]; + for (i0 = 0; i0 < Data.Motion.Length; i0++) + Dict.FindValue(out Data.Motion[i0], "motion" + d + i0 + d + "name"); + } + + if (Dict.FindValue(out value, "object.length")) + { + Data.Object = new Object[int.Parse(value)]; + for (i0 = 0; i0 < Data.Object.Length; i0++) + { + name = "object" + d + i0 + d; + + Dict.FindValue(out Data.Object[i0].Morph , name + "morph" ); + Dict.FindValue(out Data.Object[i0].MorphOffset, name + "morph_offset"); + Dict.FindValue(out Data.Object[i0]. Name, name + "name"); + Dict.FindValue(out Data.Object[i0]. ParentName, name + "parent_name"); + Dict.FindValue(out Data.Object[i0]. UIDName, name + "uid_name"); + + if (Dict.FindValue(out value, name + "tex_pat.length")) + { + Data.Object[i0].TP = new Object.TexturePattern[int.Parse(value)]; + for (i1 = 0; i1 < Data.Object[i0].TP.Length; i1++) + { + nameView = name + "tex_pat" + d + i1 + d; + Dict.FindValue(out Data.Object[i0].TP[i1].Name , nameView + "name" ); + Dict.FindValue(out Data.Object[i0].TP[i1].Pat , nameView + "pat" ); + Dict.FindValue(out Data.Object[i0].TP[i1].PatOffset, nameView + "pat_offset"); + } + } + + if (Dict.FindValue(out value, name + "tex_transform.length")) + { + Data.Object[i0].TT = new Object.TextureTransform[int.Parse(value)]; + for (i1 = 0; i1 < Data.Object[i0].TT.Length; i1++) + { + nameView = name + "tex_transform" + d + i1 + d; + + Dict.FindValue(out Data.Object[i0].TT[i1].Name, nameView + "name"); + Data.Object[i0].TT[i1].C = Dict.ReadKeyUV(nameView + "coverage" ); + Data.Object[i0].TT[i1].O = Dict.ReadKeyUV(nameView + "offset" ); + Data.Object[i0].TT[i1].R = Dict.ReadKeyUV(nameView + "repeat" ); + Data.Object[i0].TT[i1].Ro = Dict.ReadKey (nameView + "rotate" + d); + Data.Object[i0].TT[i1].RF = Dict.ReadKey (nameView + "rotateFrame"+ d); + Data.Object[i0].TT[i1].TF = Dict.ReadKeyUV(nameView + "translateFrame"); + } + } + + Data.Object[i0].MT = Dict.ReadMT(name); + } + } + + if (Dict.FindValue(out value, "objhrc.length")) + { + Data.ObjectHRC = new ObjectHRC[int.Parse(value)]; + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + { + name = "objhrc" + d + i0 + d; + + if (Dict.StartsWith(name + "joint_orient")) + { + Data.ObjectHRC[i0].JointOrient = new Vector3(); + Dict.FindValue(out Data.ObjectHRC[i0].JointOrient.X, name + "joint_orient.x"); + Dict.FindValue(out Data.ObjectHRC[i0].JointOrient.Y, name + "joint_orient.y"); + Dict.FindValue(out Data.ObjectHRC[i0].JointOrient.Z, name + "joint_orient.z"); + } + Dict.FindValue(out Data.ObjectHRC[i0]. Name, name + "name"); + Dict.FindValue(out Data.ObjectHRC[i0]. Shadow, name + "shadow"); + Dict.FindValue(out Data.ObjectHRC[i0].UIDName, name + "uid_name"); + if (Dict.FindValue(out value, name + "node.length")) + { + Data.ObjectHRC[i0].Node = new Node[int.Parse(value)]; + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + { + name = "objhrc" + d + i0 + d + "node" + d + i1 + d; + + Dict.FindValue(out Data.ObjectHRC[i0].Node[i1].Name , name + "name" ); + Dict.FindValue(out Data.ObjectHRC[i0].Node[i1].Parent, name + "parent"); + + Data.ObjectHRC[i0].Node[i1].MT = Dict.ReadMT(name); + } + } + } + } + + if (Dict.FindValue(out value, "object_list.length")) + { + Data.ObjectList = new string[int.Parse(value)]; + for (i0 = 0; i0 < Data.ObjectList.Length; i0++) + Dict.FindValue(out Data.ObjectList[i0], "object_list" + d + i0); + } + + if (Dict.FindValue(out value, "objhrc_list.length")) + { + Data.ObjectHRCList = new string[int.Parse(value)]; + for (i0 = 0; i0 < Data.ObjectHRCList.Length; i0++) + Dict.FindValue(out Data.ObjectHRCList[i0], "objhrc_list" + d + i0); + } + + if (Dict.FindValue(out value, "point.length")) + { + Data.Point = new ModelTransform[int.Parse(value)]; + for (i0 = 0; i0 < Data.Point.Length; i0++) + Data.Point[i0] = Dict.ReadMT("point" + d + i0 + d); + } + } + + public void A3DAWriter(bool A3DC = false) + { + int i0 = 0; + int i1 = 0; + DateTime date = DateTime.Now; + if (A3DC && Data._.CompressF16 != null) + if (Data._.CompressF16 != 0) + IO.Write("", "#-compress_f16"); + if (!A3DC) + IO.Write("#A3DA__________\n"); + IO.Write("#", DateTime.UtcNow.ToString("ddd MMM dd HH:mm:ss yyyy", + System.Globalization.CultureInfo.InvariantCulture)); + if (A3DC && Data._.CompressF16 != 0) + IO.Write("_.compress_f16=", Data._.CompressF16); + + IO.Write("_.converter.version=", Data._.ConverterVersion); + IO.Write("_.file_name=", Data._.FileName); + IO.Write("_.property.version=", Data._.PropertyVersion); + + if (Data.Ambient != null && Data.Header.Format == Main.Format.MGF) + { + SO0 = Data.Ambient.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.Ambient.Length; i0++) + { + SOi0 = SO0[i0]; + name = "ambient" + d + SOi0 + d; + + IO.Write(Data.Ambient[SOi0]. LightDiffuse, name, "light.Diffuse", A3DC); + IO.Write(name + "name=", Data.Ambient[SOi0].Name); + IO.Write(Data.Ambient[SOi0].RimLightDiffuse, name, "rimlight.Diffuse", A3DC); + } + IO.Write("fog.length=", Data.Fog.Length); + } + + if (Data.CameraAuxiliary != null) + { + name = "camera_auxiliary" + d; + IO.Write(Data.CameraAuxiliary.AutoExposure, name, "auto_exposure", A3DC); + IO.Write(Data.CameraAuxiliary. Exposure, name, "exposure", A3DC); + IO.Write(Data.CameraAuxiliary.Gamma , name, "gamma" , A3DC); + IO.Write(Data.CameraAuxiliary.GammaRate , name, "gamma_rate" , A3DC); + IO.Write(Data.CameraAuxiliary.Saturate , name, "saturate" , A3DC); + } + + if (Data.CameraRoot != null) + { + SO0 = Data.CameraRoot.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.CameraRoot.Length; i0++) + { + SOi0 = SO0[i0]; + name = "camera_root" + d + SOi0 + d; + nameView = name + "view_point" + d; + + IO.Write(Data.CameraRoot[SOi0].Interest, name + "interest" + d, A3DC, IsX); + IO.Write(Data.CameraRoot[SOi0].MT, name, A3DC, IsX, 0b11110); + IO.Write(nameView + "aspect=", Data.CameraRoot[i0].ViewPoint.Aspect); + if (Data.CameraRoot[i0].ViewPoint.CameraApertureH != null) + IO.Write(nameView + "camera_aperture_h=", Data.CameraRoot[i0].ViewPoint.CameraApertureH); + if (Data.CameraRoot[i0].ViewPoint.CameraApertureW != null) + IO.Write(nameView + "camera_aperture_w=", Data.CameraRoot[i0].ViewPoint.CameraApertureW); + IO.Write(Data.CameraRoot[SOi0].ViewPoint.FocalLength, nameView + "focal_length" + d, A3DC); + IO.Write(Data.CameraRoot[SOi0].ViewPoint.FOV, nameView + "fov" + d, A3DC); + IO.Write(nameView + "fov_is_horizontal=", Data.CameraRoot[i0].ViewPoint.FOVHorizontal); + IO.Write(Data.CameraRoot[SOi0].ViewPoint.MT, nameView, A3DC, IsX, 0b10000); + IO.Write(Data.CameraRoot[SOi0].ViewPoint.Roll, nameView + "roll" + d, A3DC); + IO.Write(Data.CameraRoot[SOi0].ViewPoint.MT, nameView, A3DC, IsX, 0b01111); + IO.Write(Data.CameraRoot[SOi0].MT, name, A3DC, IsX, 0b00001); + } + IO.Write("camera_root.length=", Data.CameraRoot.Length); + } + + if (Data.Chara != null) + { + SO0 = Data.Chara.Length.SortWriter(); + name = "chara" + d; + + for (i0 = 0; i0 < Data.Chara.Length; i0++) + IO.Write(Data.Chara[SO0[i0]], name + SO0[i0] + d, A3DC, IsX); + IO.Write(name + "length=", Data.Chara.Length); + } + + if (Data.Curve != null) + { + SO0 = Data.Curve.Length.SortWriter(); + SOi0 = 0; + + for (i0 = 0; i0 < Data.Curve.Length; i0++) + { + SOi0 = SO0[i0]; + name = "curve" + d + SOi0 + d; + + IO.Write(Data.Curve[SOi0].CV, name + "cv" + d, A3DC); + IO.Write(name + "name=", Data.Curve[SOi0].Name); + } + IO.Write("curve.length=", Data.Curve.Length); + } + + if (Data.DOF != null && Data.Header.Format == Main.Format.FT) + { + IO.Write("dof.name=", Data.DOF.Name); + IO.Write(Data.DOF.MT, "dof" + d, A3DC, IsX); + } + + if (Data.Event != null) + { + SO0 = Data.Event.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.Event.Length; i0++) + { + SOi0 = SO0[i0]; + name = "event" + d + SOi0 + d; + + IO.Write(name + "begin=" , Data.Event[SOi0].Begin ); + IO.Write(name + "clip_begin=" , Data.Event[SOi0].ClipBegin ); + IO.Write(name + "clip_en=" , Data.Event[SOi0].ClipEnd ); + IO.Write(name + "end=" , Data.Event[SOi0].End ); + IO.Write(name + "name=" , Data.Event[SOi0].Name ); + IO.Write(name + "param1=" , Data.Event[SOi0].Param1 ); + IO.Write(name + "ref=" , Data.Event[SOi0].Ref ); + IO.Write(name + "time_ref_scale=", Data.Event[SOi0].TimeRefScale); + IO.Write(name + "type=" , Data.Event[SOi0].Type ); + } + } + + if (Data.Fog != null) + { + SO0 = Data.Fog.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.Fog.Length; i0++) + { + SOi0 = SO0[i0]; + name = "fog" + d + SOi0 + d; + + IO.Write(Data.Fog[SOi0].Diffuse, name, "Diffuse", A3DC); + IO.Write(Data.Fog[SOi0].Density, name, "density", A3DC); + IO.Write(Data.Fog[SOi0].End , name, "end" , A3DC); + IO.Write(name + "id=", Data.Fog[SOi0].Id); + IO.Write(Data.Fog[SOi0].Start , name, "start" , A3DC); + } + IO.Write("fog.length=", Data.Fog.Length); + } + + if (Data.Light != null) + { + SO0 = Data.Light.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.Light.Length; i0++) + { + SOi0 = SO0[i0]; + name = "light" + d + SOi0 + d; + + IO.Write(Data.Light[SOi0].Ambient , name, "Ambient" , A3DC); + IO.Write(Data.Light[SOi0].Diffuse , name, "Diffuse" , A3DC); + IO.Write(Data.Light[SOi0].Incandescence, name, "Incandescence", A3DC); + IO.Write(Data.Light[SOi0].Specular , name, "Specular" , A3DC); + IO.Write(name + "id=", Data.Light[SOi0].Id); + IO.Write(name + "name=", Data.Light[SOi0].Name); + IO.Write(Data.Light[SOi0].Position , name + "position" + d, A3DC, IsX); + IO.Write(Data.Light[SOi0].SpotDirection, name + "spot_direction" + d, A3DC, IsX); + IO.Write(name + "type=", Data.Light[SOi0].Type); + } + IO.Write("light.length=", Data.Light.Length); + } + + if (Data.MObjectHRC != null) + { + SO0 = Data.MObjectHRC.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + SOi0 = SO0[i0]; + name = "m_objhrc" + d + SOi0 + d; + + if (IsX && Data.MObjectHRC[i0].JointOrient != null) + { + IO.Write(name + "joint_orient.x=", Data.MObjectHRC[SOi0].JointOrient.X); + IO.Write(name + "joint_orient.y=", Data.MObjectHRC[SOi0].JointOrient.Y); + IO.Write(name + "joint_orient.z=", Data.MObjectHRC[SOi0].JointOrient.Z); + } + + if (Data.MObjectHRC[i0].Instance != null) + { + nameView = name + "instance" + d; + SO1 = Data.MObjectHRC[i0].Instance.Length.SortWriter(); + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + { + SOi1 = SO1[i1]; + IO.Write(Data.MObjectHRC[SOi0].Instance[SOi1].MT, + nameView + SOi1 + d, A3DC, IsX, 0b10000); + IO.Write(nameView + SOi1 + d + "name=", + Data.MObjectHRC[SOi0].Instance[SOi1]. Name); + IO.Write(Data.MObjectHRC[SOi0].Instance[SOi1].MT, + nameView + SOi1 + d, A3DC, IsX, 0b01100); + IO.Write(nameView + SOi1 + d + "shadow=", + Data.MObjectHRC[SOi0].Instance[SOi1]. Shadow); + IO.Write(Data.MObjectHRC[SOi0].Instance[SOi1].MT, + nameView + SOi1 + d, A3DC, IsX, 0b00010); + IO.Write(nameView + SOi1 + d + "uid_name=", + Data.MObjectHRC[SOi0].Instance[SOi1].UIDName); + IO.Write(Data.MObjectHRC[SOi0].Instance[SOi1].MT, + nameView + SOi1 + d, A3DC, IsX, 0b00001); + } + IO.Write(nameView + "length=", Data.MObjectHRC[SOi0].Instance.Length); + } + + IO.Write(Data.MObjectHRC[SOi0].MT, name, A3DC, IsX, 0b10000); + IO.Write(name + "name=", Data.MObjectHRC[SOi0].Name); + + if (Data.MObjectHRC[i0].Node != null) + { + nameView = name + "node" + d; + SO1 = Data.MObjectHRC[i0].Node.Length.SortWriter(); + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + { + SOi1 = SO1[i1]; + IO.Write(Data.MObjectHRC[SOi0].Node[SOi1].MT, nameView + SOi1 + d, A3DC, IsX, 0b10000); + IO.Write(nameView + SOi1 + d + "name=", Data.MObjectHRC[SOi0].Node[SOi1].Name ); + IO.Write(nameView + SOi1 + d + "parent=", Data.MObjectHRC[SOi0].Node[SOi1].Parent); + IO.Write(Data.MObjectHRC[SOi0].Node[SOi1].MT, nameView + SOi1 + d, A3DC, IsX, 0b01111); + } + IO.Write(nameView + "length=", Data. MObjectHRC[SOi0].Node.Length); + } + + IO.Write(Data.MObjectHRC[SOi0].MT, name, A3DC, IsX, 0b01111); + } + IO.Write("m_objhrc.length=", Data.MObjectHRC.Length); + } + + if (Data.MObjectHRCList != null) + { + SO0 = Data.MObjectHRCList.Length.SortWriter(); + name = "m_objhrc_list" + d; + for (i0 = 0; i0 < Data.MObjectHRCList.Length; i0++) + IO.Write(name + SO0[i0] + "=", Data.MObjectHRCList[SO0[i0]]); + IO.Write(name + "length=", Data.MObjectHRCList.Length); + } + + if (Data.MaterialList != null && IsX) + { + SO0 = Data.MaterialList.Length.SortWriter(); + name = "material_list" + d; + for (i0 = 0; i0 < Data.MaterialList.Length; i0++) + { + SOi0 = SO0[i0]; + IO.Write(Data.MaterialList[SOi0].BlendColor , name + SOi0 + d, "blend_color" + d, A3DC); + IO.Write(Data.MaterialList[SOi0].GlowIntensity, name + SOi0 + d + "glow_intensity" , A3DC); + IO.Write(name + SOi0 + "hash_name=", Data.MaterialList[SOi0].HashName); + IO.Write(Data.MaterialList[SOi0].Incandescence, name + SOi0 + d, "incandescence" + d, A3DC); + IO.Write(name + SOi0 + "name=", Data.MaterialList[SOi0].Name); + } + IO.Write(name + "length=", Data.MaterialList.Length); + } + + if (Data.Motion != null) + { + SO0 = Data.Motion.Length.SortWriter(); + name = "motion" + d; + for (i0 = 0; i0 < Data.Motion.Length; i0++) + IO.Write(name + SO0[i0] + d + "name=", Data.Motion[SO0[i0]]); + IO.Write(name + "length=", Data.Motion.Length); + } + + if (Data.Object != null) + { + SO0 = Data.Object.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.Object.Length; i0++) + { + SOi0 = SO0[i0]; + name = "object" + d + SOi0 + d; + + IO.Write(Data.Object[SOi0].MT, name, A3DC, IsX, 0b10000); + if (Data.Object[SOi0].Morph != null) + { + IO.Write(name + "morph=" , Data.Object[SOi0].Morph ); + IO.Write(name + "morph_offset=", Data.Object[SOi0].MorphOffset); + } + IO.Write(name + "name=" , Data.Object[SOi0].Name ); + IO.Write(name + "parent_name=", Data.Object[SOi0].ParentName); + IO.Write(Data.Object[SOi0].MT, name, A3DC, IsX, 0b01100); + + if (Data.Object[SOi0].TP != null) + { + nameView = name + "tex_pat" + d; + SO1 = Data.Object[SOi0].TP.Length.SortWriter(); + for (i1 = 0; i1 < Data.Object[SOi0].TP.Length; i1++) + { + SOi1 = SO1[i1]; + IO.Write(nameView + SOi1 + d + "name=" , Data.Object[SOi0].TP[SOi1].Name ); + IO.Write(nameView + SOi1 + d + "pat=" , Data.Object[SOi0].TP[SOi1].Pat ); + IO.Write(nameView + SOi1 + d + "pat_offset=", Data.Object[SOi0].TP[SOi1].PatOffset); + } + IO.Write(nameView + "length=", Data.Object[SOi0].TP.Length); + } + + if (Data.Object[SOi0].TT != null) + { + SO1 = Data.Object[SOi0].TT.Length.SortWriter(); + nameView = name + "tex_transform" + d; + for (i1 = 0; i1 < Data.Object[SOi0].TT.Length; i1++) + { + SOi1 = SO1[i1]; + IO.Write(nameView + SOi1 + d + "name=", Data.Object[SOi0].TT[SOi1].Name); + IO.Write(Data.Object[SOi0].TT[SOi1].C , nameView + SOi1 + d, "coverage" , A3DC); + IO.Write(Data.Object[SOi0].TT[SOi1].O , nameView + SOi1 + d, "offset" , A3DC); + IO.Write(Data.Object[SOi0].TT[SOi1].R , nameView + SOi1 + d, "repeat" , A3DC); + IO.Write(Data.Object[SOi0].TT[SOi1].Ro, nameView + SOi1 + d, "rotate" , A3DC); + IO.Write(Data.Object[SOi0].TT[SOi1].RF, nameView + SOi1 + d, "rotateFrame" , A3DC); + IO.Write(Data.Object[SOi0].TT[SOi1].TF, nameView + SOi1 + d, "translateFrame", A3DC); + } + IO.Write(nameView + "length=", + Data.Object[SOi0].TT.Length); + } + + IO.Write(Data.Object[SOi0].MT, name, A3DC, IsX, 0b00010); + IO.Write(name + "uid_name=", Data.Object[SOi0].UIDName); + IO.Write(Data.Object[SOi0].MT, name, A3DC, IsX, 0b00001); + } + IO.Write("object.length=", Data.Object.Length); + } + + if (Data.ObjectList != null) + { + SO0 = Data.ObjectList.Length.SortWriter(); + for (i0 = 0; i0 < Data.ObjectList.Length; i0++) + IO.Write("object_list" + d + SO0[i0] + "=", Data.ObjectList[SO0[i0]]); + IO.Write("object_list.length=", Data.ObjectList.Length); + } + + if (Data.ObjectHRC != null) + { + SO0 = Data.ObjectHRC.Length.SortWriter(); + SOi0 = 0; + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + { + SOi0 = SO0[i0]; + name = "objhrc" + d + SOi0 + d; + IO.Write(name + "name=", Data.ObjectHRC[SOi0].Name); + + if (IsX && Data.ObjectHRC[i0].JointOrient != null) + { + IO.Write(name + "joint_orient.x=", Data.ObjectHRC[SOi0].JointOrient.X); + IO.Write(name + "joint_orient.y=", Data.ObjectHRC[SOi0].JointOrient.Y); + IO.Write(name + "joint_orient.z=", Data.ObjectHRC[SOi0].JointOrient.Z); + } + + if (Data.ObjectHRC[i0].Node != null) + { + SO1 = Data.ObjectHRC[i0].Node.Length.SortWriter(); + nameView = name + "node" + d; + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + { + SOi1 = SO1[i1]; + IO.Write(Data.ObjectHRC[SOi0].Node[SOi1].MT, nameView + SOi1 + d, A3DC, IsX, 0b10000); + IO.Write(nameView + SOi1 + d + "name=" , Data.ObjectHRC[SOi0].Node[SOi1].Name ); + IO.Write(nameView + SOi1 + d + "parent=", Data.ObjectHRC[SOi0].Node[SOi1].Parent); + IO.Write(Data.ObjectHRC[SOi0].Node[SOi1].MT, nameView + SOi1 + d, A3DC, IsX, 0b01111); + } + IO.Write(nameView + "length=", Data.ObjectHRC[SOi0].Node.Length); + } + + if (Data.ObjectHRC[SOi0].Shadow != null) + IO.Write(name + "shadow=", Data.ObjectHRC[SOi0].Shadow); + IO.Write(name + "uid_name=", Data.ObjectHRC[SOi0].UIDName); + } + IO.Write("objhrc.length=", Data.ObjectHRC.Length); + } + + if (Data.ObjectHRCList != null) + { + SO0 = Data.ObjectHRCList.Length.SortWriter(); + for (i0 = 0; i0 < Data.ObjectHRCList.Length; i0++) + IO.Write("objhrc_list" + d + SO0[i0] + "=", Data.ObjectHRCList[SO0[i0]]); + IO.Write("objhrc_list.length=", Data.ObjectHRCList.Length); + } + + if (Data.PlayControl != null) + { + IO.Write("play_control.begin=", Data.PlayControl.Begin); + if (Data.PlayControl.Div != null && A3DC) + IO.Write("play_control.div=", Data.PlayControl.Div); + IO.Write("play_control.fps=", Data.PlayControl.FPS); + if (Data.PlayControl.Offset != null) + { if ( A3DC) { IO.Write("play_control.offset=", Data.PlayControl.Offset); + IO.Write("play_control.size=" , Data.PlayControl.Size ); } + else IO.Write("play_control.size=", Data.PlayControl.Size + Data.PlayControl.Offset); + } + else IO.Write("play_control.size=", Data.PlayControl.Size); + } + + if (Data.PostProcess != null) + { + name = "post_process" + d; + IO.Write(Data.PostProcess.Ambient , name, "Ambient" , A3DC); + IO.Write(Data.PostProcess.Diffuse , name, "Diffuse" , A3DC); + IO.Write(Data.PostProcess.Specular , name, "Specular" , A3DC); + IO.Write(Data.PostProcess.LensFlare, name, "lens_flare", A3DC); + IO.Write(Data.PostProcess.LensGhost, name, "lens_ghost", A3DC); + IO.Write(Data.PostProcess.LensShaft, name, "lens_shaft", A3DC); + } + + if (Data.Point != null) + { + SO0 = Data.Point.Length.SortWriter(); + for (i0 = 0; i0 < Data.Point.Length; i0++) + IO.Write(Data.Point[SO0[i0]], "point" + d + SO0[i0] + d, A3DC, IsX); + IO.Write("point.length=", Data.Point.Length); + } + + if (!A3DC) + IO.Close(); + } + + private int CompressF16 => (int)Data._.CompressF16; + + private void A3DCReader() + { + int i0 = 0; + int i1 = 0; + + if (Data.Ambient != null) + for (i0 = 0; i0 < Data.Ambient.Length; i0++) + { + IO.ReadRGBAKey(ref Data.Ambient[i0]. LightDiffuse, CompressF16); + IO.ReadRGBAKey(ref Data.Ambient[i0].RimLightDiffuse, CompressF16); + } + + if (Data.CameraAuxiliary != null) + { + IO.ReadKey(ref Data.CameraAuxiliary.AutoExposure, CompressF16); + IO.ReadKey(ref Data.CameraAuxiliary. Exposure, CompressF16); + IO.ReadKey(ref Data.CameraAuxiliary.Gamma , CompressF16); + IO.ReadKey(ref Data.CameraAuxiliary.GammaRate , CompressF16); + IO.ReadKey(ref Data.CameraAuxiliary.Saturate , CompressF16); + } + + if (Data.CameraRoot != null) + for (i0 = 0; i0 < Data.CameraRoot.Length; i0++) + { + IO.ReadMT(ref Data.CameraRoot[i0].MT , CompressF16); + IO.ReadMT(ref Data.CameraRoot[i0].Interest , CompressF16); + IO.ReadMT(ref Data.CameraRoot[i0].ViewPoint.MT, CompressF16); + IO.ReadKey(ref Data.CameraRoot[i0].ViewPoint.FocalLength, CompressF16); + IO.ReadKey(ref Data.CameraRoot[i0].ViewPoint.FOV , CompressF16); + IO.ReadKey(ref Data.CameraRoot[i0].ViewPoint.Roll , CompressF16); + } + + if (Data.Chara != null) + for (i0 = 0; i0 < Data.Chara.Length; i0++) + IO.ReadMT(ref Data.Chara[i0], CompressF16); + + if (Data.Curve != null) + for (i0 = 0; i0 < Data.Curve.Length; i0++) + IO.ReadKey(ref Data.Curve[i0].CV, CompressF16); + + if (Data.DOF != null) + IO.ReadMT(ref Data.DOF.MT, CompressF16); + + if (Data.Fog != null) + for (i0 = 0; i0 < Data.Fog.Length; i0++) + { + IO.ReadKey (ref Data.Fog[i0].Density, CompressF16); + IO.ReadRGBAKey(ref Data.Fog[i0].Diffuse, CompressF16); + IO.ReadKey (ref Data.Fog[i0].End , CompressF16); + IO.ReadKey (ref Data.Fog[i0].Start , CompressF16); + } + + if (Data.Light != null) + for (i0 = 0; i0 < Data.Light.Length; i0++) + { + IO.ReadRGBAKey(ref Data.Light[i0].Ambient , CompressF16); + IO.ReadRGBAKey(ref Data.Light[i0].Diffuse , CompressF16); + IO.ReadRGBAKey(ref Data.Light[i0].Incandescence, CompressF16); + IO.ReadMT (ref Data.Light[i0].Position , CompressF16); + IO.ReadRGBAKey(ref Data.Light[i0].Specular , CompressF16); + IO.ReadMT (ref Data.Light[i0].SpotDirection, CompressF16); + } + + if (Data.MObjectHRC != null) + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + IO.ReadMT(ref Data.MObjectHRC[i0].MT, CompressF16); + + if (Data.MObjectHRC[i0].Instance != null) + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + IO.ReadMT(ref Data.MObjectHRC[i0].Instance[i1].MT, CompressF16); + + if (Data.MObjectHRC[i0].Node != null) + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + IO.ReadMT(ref Data.MObjectHRC[i0].Node[i1].MT, CompressF16); + } + + if (Data.MaterialList != null) + for (i0 = 0; i0 < Data.MaterialList.Length; i0++) + { + IO.ReadRGBAKey(ref Data.MaterialList[i0].BlendColor , CompressF16); + IO.ReadKey (ref Data.MaterialList[i0].GlowIntensity, CompressF16); + IO.ReadRGBAKey(ref Data.MaterialList[i0].Incandescence, CompressF16); + } + + if (Data.Object != null) + for (i0 = 0; i0 < Data.Object.Length; i0++) + { + IO.ReadMT(ref Data.Object[i0].MT, CompressF16); + if (Data.Object[i0].TT != null) + for (i1 = 0; i1 < Data.Object[i0].TT.Length; i1++) + { + IO.ReadKeyUV(ref Data.Object[i0].TT[i1].C , CompressF16); + IO.ReadKeyUV(ref Data.Object[i0].TT[i1].O , CompressF16); + IO.ReadKeyUV(ref Data.Object[i0].TT[i1].R , CompressF16); + IO.ReadKey (ref Data.Object[i0].TT[i1].Ro, CompressF16); + IO.ReadKey (ref Data.Object[i0].TT[i1].RF, CompressF16); + IO.ReadKeyUV(ref Data.Object[i0].TT[i1].TF, CompressF16); + } + } + + if (Data.ObjectHRC != null) + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + if (Data.ObjectHRC[i0].Node != null) + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + IO.ReadMT(ref Data.ObjectHRC[i0].Node[i1].MT, CompressF16); + + + if (Data.Point != null) + for (i0 = 0; i0 < Data.Point.Length; i0++) + IO.ReadMT(ref Data.Point[i0], CompressF16); + + if (Data.PostProcess != null) + { + IO.ReadRGBAKey(ref Data.PostProcess.Ambient , CompressF16); + IO.ReadRGBAKey(ref Data.PostProcess.Diffuse , CompressF16); + IO.ReadRGBAKey(ref Data.PostProcess.Specular , CompressF16); + IO.ReadKey (ref Data.PostProcess.LensFlare, CompressF16); + IO.ReadKey (ref Data.PostProcess.LensGhost, CompressF16); + IO.ReadKey (ref Data.PostProcess.LensShaft, CompressF16); + } + } + + public void A3DCWriter(string file) + { + int i0 = 0; + int i1 = 0; + if (A3DCOpt) { UsedValues.BinOffset = new List(); UsedValues.Value = new List(); } + + if (Data.Header.Format > Main.Format.FT) + { + int a = (int)((long)int.Parse(Data._.ConverterVersion) * BitConverter. + ToInt32(Data._.FileName.ToUTF8(), 0) * int.Parse(Data._.PropertyVersion)); + + IO.Write(0x41443341); + IO.Write(0x00); + IO.Write(0x40); + IO.Write(0x10000000); + IO.Write((long)0x00); + IO.Write((long)0x00); + IO.Write(a); + IO.Write(0x00); + IO.Write((long)0x00); + IO.Write(0x01131010); + IO.Write(0x00); + IO.Write(0x00); + IO.Write(0x00); + } + else Data._.CompressF16 = null; + + int A3DCStart = IO.Position; + + IO.Close(); + IO = File.OpenWriter(); + + for (byte i = 0; i < 2; i++) + { + bool ReturnToOffset = i == 1; + IO.Position = 0; + + if (Data.CameraRoot != null) + for (i0 = 0; i0 < Data.CameraRoot.Length; i0++) + { + IO.WriteOffset(ref Data.CameraRoot[i0].Interest , ReturnToOffset); + IO.WriteOffset(ref Data.CameraRoot[i0]. MT, ReturnToOffset); + IO.WriteOffset(ref Data.CameraRoot[i0].ViewPoint.MT, ReturnToOffset); + } + + if (Data.DOF != null) + IO.WriteOffset(ref Data.DOF.MT, ReturnToOffset); + + if (Data.Light != null) + for (i0 = 0; i0 < Data.Light.Length; i0++) + { + IO.WriteOffset(ref Data.Light[i0].Position , ReturnToOffset); + IO.WriteOffset(ref Data.Light[i0].SpotDirection, ReturnToOffset); + } + + if (Data.MObjectHRC != null) + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + if (Data.MObjectHRC[i0].Instance != null) + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + IO.WriteOffset(ref Data.MObjectHRC[i0].Instance[i1].MT, ReturnToOffset); + + IO.WriteOffset(ref Data.MObjectHRC[i0].MT, ReturnToOffset); + + if (Data.MObjectHRC[i0].Node != null) + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + IO.WriteOffset(ref Data.MObjectHRC[i0].Node[i1].MT, ReturnToOffset); + } + + if (Data.Object != null) + for (i0 = 0; i0 < Data.Object.Length; i0++) + IO.WriteOffset(ref Data.Object[i0].MT, ReturnToOffset); + + if (Data.ObjectHRC != null) + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + if (Data.ObjectHRC[i0].Node != null) + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + IO.WriteOffset(ref Data.ObjectHRC[i0].Node[i1].MT, ReturnToOffset); + + if (ReturnToOffset) continue; + + if (Data.Ambient != null) + for (i0 = 0; i0 < Data.Ambient.Length; i0++) + { + Write(ref Data.Ambient[i0]. LightDiffuse); + Write(ref Data.Ambient[i0].RimLightDiffuse); + } + + if (Data.CameraAuxiliary != null) + { + Write(ref Data.CameraAuxiliary.AutoExposure); + Write(ref Data.CameraAuxiliary. Exposure); + Write(ref Data.CameraAuxiliary.Gamma ); + Write(ref Data.CameraAuxiliary.GammaRate ); + Write(ref Data.CameraAuxiliary.Saturate ); + } + + if (Data.CameraRoot != null) + for (i0 = 0; i0 < Data.CameraRoot.Length; i0++) + { + Write(ref Data.CameraRoot[i0].Interest ); + Write(ref Data.CameraRoot[i0] .MT); + Write(ref Data.CameraRoot[i0].ViewPoint.MT); + Write(ref Data.CameraRoot[i0].ViewPoint.FOV ); + Write(ref Data.CameraRoot[i0].ViewPoint.FocalLength); + Write(ref Data.CameraRoot[i0].ViewPoint.Roll ); + } + + if (Data.Chara != null) + for (i0 = 0; i0 < Data.Chara.Length; i0++) + Write(ref Data.Chara[i0]); + + if (Data.Curve != null) + for (i0 = 0; i0 < Data.Curve.Length; i0++) + Write(ref Data.Curve[i0].CV); + + if (Data.DOF != null && Data.Header.Format == Main.Format.FT) + Write(ref Data.DOF.MT); + + if (Data.Fog != null) + for (i0 = 0; i0 < Data.Fog.Length; i0++) + { + Write(ref Data.Fog[i0].Density); + Write(ref Data.Fog[i0].Diffuse); + Write(ref Data.Fog[i0].End ); + Write(ref Data.Fog[i0].Start ); + } + + if (Data.Light != null) + for (i0 = 0; i0 < Data.Light.Length; i0++) + { + Write(ref Data.Light[i0].Ambient ); + Write(ref Data.Light[i0].Diffuse ); + Write(ref Data.Light[i0].Incandescence); + Write(ref Data.Light[i0].Specular ); + Write(ref Data.Light[i0].Position ); + Write(ref Data.Light[i0].SpotDirection); + } + + if (Data.MObjectHRC != null) + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + if (Data.MObjectHRC[i0].Instance != null) + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + Write(ref Data.MObjectHRC[i0].Instance[i1].MT); + + Write(ref Data.MObjectHRC[i0].MT); + + if (Data.MObjectHRC[i0].Node != null) + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + Write(ref Data.MObjectHRC[i0].Node[i1].MT); + } + + if (Data.MaterialList != null && IsX) + for (i0 = 0; i0 < Data.MaterialList.Length; i0++) + { + Write(ref Data.MaterialList[SO0[i0]].BlendColor ); + Write(ref Data.MaterialList[SO0[i0]].GlowIntensity); + Write(ref Data.MaterialList[SO0[i0]].Incandescence); + } + + if (Data.Object != null) + for (i0 = 0; i0 < Data.Object.Length; i0++) + { + Write(ref Data.Object[i0].MT); + if (Data.Object[i0].TT != null) + for (i1 = 0; i1 < Data.Object[i0].TT.Length; i1++) + { + Write(ref Data.Object[i0].TT[i1].C ); + Write(ref Data.Object[i0].TT[i1].O ); + Write(ref Data.Object[i0].TT[i1].R ); + Write(ref Data.Object[i0].TT[i1].Ro); + Write(ref Data.Object[i0].TT[i1].RF); + Write(ref Data.Object[i0].TT[i1].TF); + } + } + + if (Data.ObjectHRC != null) + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + if (Data.ObjectHRC[i0].Node != null) + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + Write(ref Data.ObjectHRC[i0].Node[i1].MT); + + if (Data.Point != null) + for (i0 = 0; i0 < Data.Point.Length; i0++) + Write(ref Data.Point[i0]); + + if (Data.PostProcess != null) + { + Write(ref Data.PostProcess.Ambient ); + Write(ref Data.PostProcess.Diffuse ); + Write(ref Data.PostProcess.Specular ); + Write(ref Data.PostProcess.LensFlare); + Write(ref Data.PostProcess.LensGhost); + Write(ref Data.PostProcess.LensShaft); + } + + IO.Align(0x10, true); + } + + byte[] A3DCData = IO.ToArray(true); + + IO = File.OpenWriter(); + A3DAWriter(true); + byte[] A3DAData = IO.ToArray(true); + + Data.Head = new Header(); + IO = File.OpenWriter(file + ".a3da"); + IO.Position = A3DCStart + 0x40; + + Data.Head.StringOffset = IO.Position - A3DCStart; + IO.Write(A3DAData); + Data.Head.StringLength = IO.Position - A3DCStart - Data.Head.StringOffset; + IO.Align(0x20, true); + + Data.Head.BinaryOffset = IO.Position - A3DCStart; + IO.Write(A3DCData); + Data.Head.BinaryLength = IO.Position - A3DCStart - Data.Head.BinaryOffset; + IO.Align(0x10, true); + + int A3DCEnd = IO.Position; + + if (CompressF16 != 0) + { + IO.Align(0x10); + A3DCEnd = IO.Position; + IO.WriteEOFC(0); + IO.Position = 0x04; + IO.Write(A3DCEnd - A3DCStart); + IO.Position = 0x14; + IO.Write(A3DCEnd - A3DCStart); + } + + IO.Position = A3DCStart; + IO.Write("#A3D", "C__________"); + IO.Write(0x2000); + IO.Write(0x00); + IO.WriteEndian(0x20, true); + IO.Write(0x10000200); + IO.Write(0x50); + IO.WriteEndian(Data.Head.StringOffset, true); + IO.WriteEndian(Data.Head.StringLength, true); + IO.WriteEndian(0x01, true); + IO.Write(0x4C42); + IO.WriteEndian(Data.Head.BinaryOffset, true); + IO.WriteEndian(Data.Head.BinaryLength, true); + IO.WriteEndian(0x20, true); + if (Data.Header.Format != Main.Format.F) + { + IO.Position = A3DCEnd; + IO.WriteEOFC(0); + } + + IO.Close(); + } + + private void Write(ref ModelTransform MT) + { Write(ref MT.Scale); Write(ref MT.Rot, true); Write(ref MT.Trans); Write(ref MT.Visibility); } + + private void Write(ref RGBAKey RGBA) + { Write(ref RGBA.R); Write(ref RGBA.G); Write(ref RGBA.B); Write(ref RGBA.A); } + + private void Write(ref Vector3 Key, bool F16 = false) + { Write(ref Key.X, F16); Write(ref Key.Y, F16); Write(ref Key.Z, F16); } + + private void Write(ref KeyUV UV) + { Write(ref UV.U); Write(ref UV.V); } + + private void Write(ref Key Key, bool F16 = false) + { + if (Key == null) return; + + int i = 0; + if (Key.Trans != null) + { + Key.BinOffset = IO.Position; + IO.Write(Key.Type); + IO.Write(0x00); + IO.Write((float)Key.Max); + IO.Write(Key.Trans.Length); + for (i = 0; i < Key.Trans.Length; i++) + { + if (F16 && CompressF16 > 0) + { IO.Write((ushort)Key.Trans[i].Frame ); IO.Write(( Half)Key.Trans[i].Value[0]); } + else + { IO.Write(( float)Key.Trans[i].Frame ); IO.Write((float)Key.Trans[i].Value[0]); } + if (F16 && CompressF16 == 2) + { IO.Write(( Half)Key.Trans[i].Value[1]); IO.Write(( Half)Key.Trans[i].Value[2]); } + else + { IO.Write(( float)Key.Trans[i].Value[1]); IO.Write((float)Key.Trans[i].Value[2]); } + } + } + else + { + if (!UsedValues.Value.Contains(Key.Value) || !A3DCOpt) + { + Key.BinOffset = IO.Position; + IO.Write( Key.Type ); + IO.Write((float?)Key.Value); + if (A3DCOpt) + { UsedValues.BinOffset.Add(Key.BinOffset); UsedValues.Value.Add(Key.Value); } + return; + } + + for (i = 0; i < UsedValues.Value.Count; i++) + if (UsedValues.Value[i] == Key.Value) + { Key.BinOffset = UsedValues.BinOffset[i]; return; } + } + } + + public void MsgPackReader(string file) + { + int i = 0; + int i0 = 0; + int i1 = 0; + + MPIO IO = new MPIO(File.OpenReader(file + ".mp")); + MsgPack = IO.Read(); + IO.Close(); + IO = null; + + if (MsgPack.Element("A3D", out MsgPack A3D)) + { + Data.Header = new PDHead(); + Enum.TryParse(A3D.ReadString("Format"), out Data.Header.Format); + MsgPack Temp = new MsgPack(); + + if (A3D.Element("_", out Temp)) + { + Data._ = new _ + { + CompressF16 = Temp.ReadNInt32("CompressF16" ), + ConverterVersion = Temp.ReadString("ConverterVersion"), + FileName = Temp.ReadString("FileName" ), + PropertyVersion = Temp.ReadString("PropertyVersion" ), + }; + } + + if (A3D.Element("Ambient", out Temp, typeof(object[]))) + { + Data.Ambient = new Ambient[((object[])Temp.Object).Length]; + MsgPack Ambient = new MsgPack(); + + for (i = 0; i < Data.Ambient.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + Ambient = (MsgPack)Temp[i]; + Data.Ambient[i] = new Ambient + { + Name = Ambient.ReadString ( "Name"), + LightDiffuse = Ambient.ReadRGBAKey( "LightDiffuse"), + RimLightDiffuse = Ambient.ReadRGBAKey("RimLightDiffuse"), + }; + } + } + + if (A3D.Element("CameraAuxiliary", out MsgPack CameraAuxiliary)) + Data.CameraAuxiliary = new CameraAuxiliary + { + AutoExposure = CameraAuxiliary.ReadKey("AutoExposure"), + Exposure = CameraAuxiliary.ReadKey( "Exposure"), + Gamma = CameraAuxiliary.ReadKey("Gamma" ), + GammaRate = CameraAuxiliary.ReadKey("GammaRate" ), + Saturate = CameraAuxiliary.ReadKey("Saturate" ), + }; + + if (A3D.Element("CameraRoot", out MsgPack CameraRoot, typeof(object[]))) + { + Data.CameraRoot = new CameraRoot[((object[])CameraRoot.Object).Length]; + MsgPack _Root = new MsgPack(); + for (i = 0; i < Data.CameraRoot.Length; i++) + if (CameraRoot[i].GetType() == typeof(MsgPack)) + { + _Root = (MsgPack)CameraRoot[i]; + Data.CameraRoot[i] = new CameraRoot + { + MT = _Root.ReadMT(), + Interest = _Root.ReadMT("Interest"), + }; + if (!_Root.Element("ViewPoint", out MsgPack ViewPoint)) continue; + + Data.CameraRoot[i].ViewPoint = new ViewPoint + { + MT = ViewPoint.ReadMT(), + Aspect = ViewPoint.ReadNDouble("Aspect" ), + CameraApertureH = ViewPoint.ReadNDouble("CameraApertureH"), + CameraApertureW = ViewPoint.ReadNDouble("CameraApertureW"), + FOVHorizontal = ViewPoint.ReadNDouble("FOVHorizontal" ), + FocalLength = ViewPoint.ReadKey ("FocalLength" ), + FOV = ViewPoint.ReadKey ("FOV" ), + Roll = ViewPoint.ReadKey ("Roll" ), + }; + } + } + + if (A3D.Element("Chara", out Temp, typeof(object[]))) + { + Data.Chara = new ModelTransform[((object[])Temp.Object).Length]; + for (i = 0; i < Data.Chara.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + Data.Chara[i] = ((MsgPack)Temp[i]).ReadMT(); + } + + if (A3D.Element("Curve", out Temp, typeof(object[]))) + { + Data.Curve = new Curve[((object[])Temp.Object).Length]; + MsgPack Curve = new MsgPack(); + for (i = 0; i < Data.Curve.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + Curve = (MsgPack)Temp[i]; + Data.Curve[i] = new Curve + { + Name = Curve.ReadString("Name"), + CV = Curve.ReadKey ("CV"), + }; + } + } + + if (A3D.Element("DOF", out Temp, typeof(object[]))) + Data.DOF = new DOF + { + MT = Temp.ReadMT(), + Name = Temp.ReadString("Name"), + }; + + if (A3D.Element("Event", out Temp, typeof(object[]))) + { + Data.Event = new Event[((object[])Temp.Object).Length]; + MsgPack Event = new MsgPack(); + for (i = 0; i < Data.Event.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + Event = (MsgPack)Temp[i]; + Data.Event[i] = new Event + { + Begin = Event.ReadNDouble( "Begin" ), + ClipBegin = Event.ReadNDouble("ClipBegin" ), + ClipEnd = Event.ReadNDouble("ClipEnd" ), + End = Event.ReadNDouble( "End" ), + Name = Event.ReadString ("Name" ), + Param1 = Event.ReadString ("Param1" ), + Ref = Event.ReadString ("Ref" ), + TimeRefScale = Event.ReadNDouble("TimeRefScale"), + Type = Event.ReadNInt32 ("Type" ), + }; + } + } + + if (A3D.Element("Fog", out Temp, typeof(object[]))) + { + Data.Fog = new Fog[((object[])Temp.Object).Length]; + MsgPack Fog = new MsgPack(); + for (i = 0; i < Data.Fog.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + Fog = (MsgPack)Temp[i]; + Data.Fog[i] = new Fog + { + Id = Fog.ReadNInt32 ("Id" ), + Density = Fog.ReadKey ("Density"), + Diffuse = Fog.ReadRGBAKey("Diffuse"), + End = Fog.ReadKey ("End" ), + Start = Fog.ReadKey ("Start" ), + }; + } + } + + if (A3D.Element("Light", out Temp, typeof(object[]))) + { + Data.Light = new Light[((object[])Temp.Object).Length]; + MsgPack Light = new MsgPack(); + for (i = 0; i < Data.Light.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + Light = (MsgPack)Temp[i]; + Data.Light[i] = new Light + { + Id = Light.ReadNInt32 ("Id" ), + Name = Light.ReadString ("Name" ), + Type = Light.ReadString ("Type" ), + Ambient = Light.ReadRGBAKey("Ambient" ), + Diffuse = Light.ReadRGBAKey("Diffuse" ), + Incandescence = Light.ReadRGBAKey("Incandescence"), + Position = Light.ReadMT ("Position" ), + Specular = Light.ReadRGBAKey("Specular" ), + SpotDirection = Light.ReadMT ("SpotDirection"), + }; + } + } + + if (A3D.Element("MaterialList", out Temp, typeof(object[]))) + { + Data.MaterialList = new MaterialList[((object[])Temp.Object).Length]; + MsgPack MaterialList = new MsgPack(); + for (i = 0; i < Data.MaterialList.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + MaterialList = (MsgPack)Temp[i]; + Data.MaterialList[i] = new MaterialList + { + HashName = MaterialList.ReadString ( "HashName"), + Name = MaterialList.ReadString ( "Name"), + BlendColor = MaterialList.ReadRGBAKey( "BlendColor"), + GlowIntensity = MaterialList.ReadKey ("GlowIntensity"), + Incandescence = MaterialList.ReadRGBAKey("Incandescence"), + }; + } + } + + if (A3D.Element("MObjectHRC", out Temp, typeof(object[]))) + { + Data.MObjectHRC = new MObjectHRC[((object[])Temp.Object).Length]; + MsgPack _Node = new MsgPack(); + MsgPack _Instance = new MsgPack(); + MsgPack MObjectHRC = new MsgPack(); + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + if (Temp[i0].GetType() == typeof(MsgPack)) + { + MObjectHRC = (MsgPack)Temp[i0]; + Data.MObjectHRC[i0] = new MObjectHRC + { + MT = MObjectHRC.ReadMT(), + Name = MObjectHRC.ReadString("Name"), + }; + + if (MObjectHRC.Element("JointOrient", out MsgPack JointOrient, typeof(MsgPack))) + { + Data.MObjectHRC[i0].JointOrient = new Vector3 + { + X = JointOrient.ReadDouble("X"), + Y = JointOrient.ReadDouble("Y"), + Z = JointOrient.ReadDouble("Z"), + }; + } + + if (MObjectHRC.Element("Instance", out MsgPack Instance, typeof(object[]))) + { + Data.MObjectHRC[i0].Instance = + new Instance[((object[])Instance.Object).Length]; + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + { + if (Instance[i1].GetType() != typeof(MsgPack)) continue; + + _Instance = (MsgPack)Instance[i1]; + Data.MObjectHRC[i0].Instance[i1] = new Instance + { + MT = _Instance.ReadMT(), + Name = _Instance.ReadString( "Name"), + Shadow = _Instance.ReadNInt32( "Shadow"), + UIDName = _Instance.ReadString("UIDName"), + }; + } + } + + if (MObjectHRC.Element("Node", out MsgPack Node, typeof(object[]))) + { + Data.MObjectHRC[i0].Node = new Node[((object[])Node.Object).Length]; + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + { + if (Node[i1].GetType() != typeof(MsgPack)) continue; + + _Node = (MsgPack)Node[i1]; + Data.MObjectHRC[i0].Node[i1] = new Node + { + MT = _Node.ReadMT(), + Name = _Node.ReadString( "Name"), + Parent = _Node.ReadNInt32("Parent"), + }; + } + } + } + } + } + + if (A3D.Element("MObjectHRCList", out Temp, typeof(object[]))) + { + Data.MObjectHRCList = new string[((object[])Temp.Object).Length]; + for (i = 0; i < Data.MObjectHRCList.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + Data.MObjectHRCList[i] = ((MsgPack)Temp[i]).ReadString(); + } + + if (A3D.Element("Motion", out Temp, typeof(object[]))) + { + Data.Motion = new string[((object[])Temp.Object).Length]; + for (i = 0; i < Data.Motion.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + Data.Motion[i] = ((MsgPack)Temp[i]).ReadString(); + } + + if (A3D.Element("Object", out Temp, typeof(object[]))) + { + Data.Object = new Object[((object[])Temp.Object).Length]; + MsgPack _TP = new MsgPack(); + MsgPack _TT = new MsgPack(); + MsgPack Object = new MsgPack(); + for (i0 = 0; i0 < Data.Object.Length; i0++) + if (Temp[i0].GetType() == typeof(MsgPack)) + { + Object = (MsgPack)Temp[i0]; + Data.Object[i0] = new Object + { + MT = Object.ReadMT(), + Morph = Object.ReadString("Morph" ), + MorphOffset = Object.ReadNInt32("MorphOffset"), + Name = Object.ReadString( "Name"), + ParentName = Object.ReadString( "ParentName"), + UIDName = Object.ReadString( "UIDName"), + }; + + if (Object.Element("TP", out MsgPack TP, typeof(object[]))) + { + Data.Object[i0].TP = new Object.TexturePattern[((object[])TP.Object).Length]; + for (i1 = 0; i1 < Data.Object[i0].TP.Length; i1++) + { + if (TP[i1].GetType() != typeof(MsgPack)) continue; + + _TP = (MsgPack)TP[i1]; + Data.Object[i0].TP[i1] = new Object.TexturePattern + { + Name = _TP.ReadString("Name" ), + Pat = _TP.ReadString("Pat" ), + PatOffset = _TP.ReadNInt32("PatOffset"), + }; + } + } + + if (Object.Element("TT", out MsgPack TT, typeof(object[]))) + { + Data.Object[i0].TT = new Object.TextureTransform[((object[])TT.Object).Length]; + for (i1 = 0; i1 < Data.Object[i0].TT.Length; i1++) + { + if (TT[i1].GetType() != typeof(MsgPack)) continue; + + _TT = (MsgPack)TT[i1]; + Data.Object[i0].TT[i1] = new Object.TextureTransform + { + Name = _TT.ReadString("Name"), + C = _TT.ReadKeyUV ("C" ), + O = _TT.ReadKeyUV ("C" ), + R = _TT.ReadKeyUV ("C" ), + Ro = _TT.ReadKey ("Ro" ), + RF = _TT.ReadKey ("RF" ), + TF = _TT.ReadKeyUV ("TF" ), + }; + } + } + } + } + + if (A3D.Element("ObjectHRC", out Temp, typeof(object[]))) + { + Data.ObjectHRC = new ObjectHRC[((object[])Temp.Object).Length]; + MsgPack _Node = new MsgPack(); + MsgPack _Instance = new MsgPack(); + MsgPack ObjectHRC = new MsgPack(); + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + if (Temp[i0].GetType() == typeof(MsgPack)) + { + ObjectHRC = (MsgPack)Temp[i0]; + Data.ObjectHRC[i0] = new ObjectHRC + { + Name = ObjectHRC.ReadString ( "Name"), + Shadow = ObjectHRC.ReadNDouble( "Shadow"), + UIDName = ObjectHRC.ReadString ("UIDName"), + }; + + if (ObjectHRC.Element("JointOrient", out MsgPack JointOrient, typeof(MsgPack))) + { + Data.ObjectHRC[i0].JointOrient = new Vector3 + { + X = JointOrient.ReadDouble("X"), + Y = JointOrient.ReadDouble("Y"), + Z = JointOrient.ReadDouble("Z"), + }; + } + + if (ObjectHRC.Element("Node", out MsgPack Node, typeof(object[]))) + { + Data.ObjectHRC[i0].Node = new Node[((object[])Node.Object).Length]; + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + { + if (Node[i1].GetType() != typeof(MsgPack)) continue; + + _Node = (MsgPack)Node[i1]; + Data.ObjectHRC[i0].Node[i1] = new Node + { + MT = _Node.ReadMT(), + Name = _Node.ReadString( "Name"), + Parent = _Node.ReadInt32 ("Parent"), + }; + } + } + } + } + + if (A3D.Element("ObjectHRCList", out Temp, typeof(object[]))) + { + Data.ObjectHRCList = new string[((object[])Temp.Object).Length]; + for (i = 0; i < Data.ObjectHRCList.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + Data.ObjectHRCList[i] = ((MsgPack)Temp[i]).ReadString(); + } + + if (A3D.Element("ObjectList", out Temp, typeof(object[]))) + { + Data.ObjectList = new string[((object[])Temp.Object).Length]; + for (i = 0; i < Data.ObjectList.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + Data.ObjectList[i] = ((MsgPack)Temp[i]).ReadString(); + } + + if (A3D.Element("PlayControl", out Temp)) + Data.PlayControl = new PlayControl + { + Begin = Temp.ReadNDouble("Begin" ), + Div = Temp.ReadNDouble("Div" ), + FPS = Temp.ReadNDouble("FPS" ), + Offset = Temp.ReadNDouble("Offset"), + Size = Temp.ReadNDouble("Size" ), + }; + + if (A3D.Element("Point", out Temp, typeof(object[]))) + { + Data.Point = new ModelTransform[((object[])Temp.Object).Length]; + for (i = 0; i < Data.Point.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + Data.Point[i] = ((MsgPack)Temp[i]).ReadMT(); + } + + if (A3D.Element("PostProcess", out Temp)) + Data.PostProcess = new PostProcess + { + Ambient = Temp.ReadRGBAKey("Ambient" ), + Diffuse = Temp.ReadRGBAKey("Diffuse" ), + LensFlare = Temp.ReadKey ("LensFlare"), + LensGhost = Temp.ReadKey ("LensGhost"), + LensShaft = Temp.ReadKey ("LensShaft"), + Specular = Temp.ReadRGBAKey("Specular" ), + }; + + Temp = null; + } + MsgPack = null; + } + + public void MsgPackWriter(string file) + { + int i = 0; + int i0 = 0; + int i1 = 0; + + MsgPack A3D = new MsgPack("A3D") + .Add("Format", Data.Header.Format.ToString()) + .Add(new MsgPack("_").Add("CompressF16" , Data._.CompressF16 ) + .Add("ConverterVersion", Data._.ConverterVersion) + .Add("FileName" , Data._.FileName ) + .Add("PropertyVersion" , Data._.PropertyVersion )); + + if (Data.Ambient != null) + { + MsgPack Ambient = new MsgPack("Ambient", Data.Ambient.Length); + for (i = 0; i < Data.Ambient.Length; i++) + Ambient[i] = new MsgPack() + .Add(Data.Ambient[i]. LightDiffuse.WriteMP( "LightDiffuse")) + .Add("Name", Data.Ambient[i].Name) + .Add(Data.Ambient[i].RimLightDiffuse.WriteMP("RimLightDiffuse")); + A3D.Add(Ambient); + } + + if (Data.CameraAuxiliary != null) + A3D.Add(new MsgPack("CameraAuxiliary") + .Add(Data.CameraAuxiliary.AutoExposure.WriteMP("AutoExposure")) + .Add(Data.CameraAuxiliary. Exposure.WriteMP( "Exposure")) + .Add(Data.CameraAuxiliary.Gamma .WriteMP("Gamma" )) + .Add(Data.CameraAuxiliary.GammaRate .WriteMP("GammaRate" )) + .Add(Data.CameraAuxiliary.Saturate .WriteMP("Saturate" ))); + + if (Data.CameraRoot != null) + { + MsgPack CameraRoot = new MsgPack("CameraRoot", Data.CameraRoot.Length); + for (i = 0; i < Data.CameraRoot.Length; i++) + { + CameraRoot[i] = Data.CameraRoot[i].MT.WriteMP() + .Add(Data.CameraRoot[i].Interest .WriteMP("Interest")) + .Add(Data.CameraRoot[i].ViewPoint.MT.WriteMP("ViewPoint") + .Add("Aspect" , Data.CameraRoot[i].ViewPoint.Aspect ) + .Add("CameraApertureH", Data.CameraRoot[i].ViewPoint.CameraApertureH) + .Add("CameraApertureW", Data.CameraRoot[i].ViewPoint.CameraApertureW) + .Add("FOVHorizontal" , Data.CameraRoot[i].ViewPoint.FOVHorizontal ) + .Add(Data.CameraRoot[i].ViewPoint.FocalLength.WriteMP("FocalLength")) + .Add(Data.CameraRoot[i].ViewPoint.FOV .WriteMP("FOV" )) + .Add(Data.CameraRoot[i].ViewPoint.Roll .WriteMP("Roll" ))); + } + A3D.Add(CameraRoot); + } + + if (Data.Chara != null) + { + MsgPack Chara = new MsgPack("Chara", Data.Chara.Length); + for (i = 0; i < Data.Curve.Length; i++) Chara[i] = Data.Chara[i].WriteMP(); + A3D.Add(Chara); + } + + if (Data.Curve != null) + { + MsgPack Curve = new MsgPack("Curve", Data.Curve.Length); + for (i = 0; i < Data.Curve.Length; i++) + Curve[i] = new MsgPack().Add("Name", Data.Curve[i].Name) + .Add(Data.Curve[i].CV.WriteMP("CV")); + A3D.Add(Curve); + } + + if (Data.DOF != null) + A3D.Add(new MsgPack("DOF").Add("Name", Data.DOF.Name).Add(Data.DOF.MT.WriteMP("MT"))); + + if (Data.Event != null) + { + MsgPack Event = new MsgPack("Events", Data.Event.Length); + for (i = 0; i < Data.Event.Length; i++) + Event[i] = new MsgPack().Add("Begin" , Data.Event[i].Begin ) + .Add("ClipBegin" , Data.Event[i].ClipBegin ) + .Add("ClipEnd" , Data.Event[i].ClipEnd ) + .Add("End" , Data.Event[i].End ) + .Add("Name" , Data.Event[i].Name ) + .Add("Param1" , Data.Event[i].Param1 ) + .Add("Ref" , Data.Event[i].Ref ) + .Add("TimeRefScale", Data.Event[i].TimeRefScale) + .Add("Type" , Data.Event[i].Type ); + A3D.Add(Event); + } + + if (Data.Fog != null) + { + MsgPack Fog = new MsgPack("Fog", Data.Fog.Length); + for (i = 0; i < Data.Fog.Length; i++) + Fog[i] = new MsgPack().Add("Id", Data.Fog[i].Id) + .Add(Data.Fog[i].Density.WriteMP("Density")) + .Add(Data.Fog[i].Diffuse.WriteMP("Diffuse")) + .Add(Data.Fog[i].End .WriteMP("End" )) + .Add(Data.Fog[i].Start .WriteMP("Start" )); + A3D.Add(Fog); + } + + if (Data.Light != null) + { + MsgPack Light = new MsgPack("Light", Data.Light.Length); + for (i = 0; i < Data.Light.Length; i++) + Light[i] = new MsgPack() + .Add("Id", Data.Light[i].Id) + .Add("Name", Data.Light[i].Name) + .Add("Type", Data.Light[i].Type) + .Add(Data.Light[i].Ambient .WriteMP("Ambient" )) + .Add(Data.Light[i].Diffuse .WriteMP("Diffuse" )) + .Add(Data.Light[i].Incandescence.WriteMP("Incandescence")) + .Add(Data.Light[i].Position .WriteMP("Position" )) + .Add(Data.Light[i].Specular .WriteMP("Specular" )) + .Add(Data.Light[i].SpotDirection.WriteMP("SpotDirection")); + A3D.Add(Light); + } + + if (Data.MObjectHRC != null) + { + MsgPack MObjectHRC = new MsgPack("MObjectHRC", Data.MObjectHRC.Length); + for (i0 = 0; i0 < Data.MObjectHRC.Length; i0++) + { + MsgPack _MObjectHRC = new MsgPack().Add("Name", Data.MObjectHRC[i0].Name); + + if (IsX && Data.MObjectHRC[i0].JointOrient != null) + _MObjectHRC.Add(new MsgPack("JointOrient") + .Add("X", Data.MObjectHRC[i0].JointOrient.X) + .Add("Y", Data.MObjectHRC[i0].JointOrient.Y) + .Add("Z", Data.MObjectHRC[i0].JointOrient.Z)); + + if (Data.MObjectHRC[i0].Instance != null) + { + MsgPack Instance = new MsgPack("Instance", Data.MObjectHRC[i0].Instance.Length); + for (i1 = 0; i1 < Data.MObjectHRC[i0].Instance.Length; i1++) + Instance[i1] = Data.MObjectHRC[i0].Instance[i1].MT.WriteMP(new MsgPack() + .Add( "Name", Data.MObjectHRC[i0].Instance[i1]. Name) + .Add("Shadow" , Data.MObjectHRC[i0].Instance[i1].Shadow ) + .Add("UIDName", Data.MObjectHRC[i0].Instance[i1].UIDName)); + _MObjectHRC.Add(Instance); + } + + if (Data.MObjectHRC[i0].Node != null) + { + MsgPack Node = new MsgPack("Node", Data.MObjectHRC[i0].Node.Length); + for (i1 = 0; i1 < Data.MObjectHRC[i0].Node.Length; i1++) + Node[i1] = Data.MObjectHRC[i0].Node[i1].MT.WriteMP(new MsgPack() + .Add("Name" , Data.MObjectHRC[i0].Node[i1].Name ) + .Add("Parent", Data.MObjectHRC[i0].Node[i1].Parent)); + _MObjectHRC.Add(Node); + } + + MObjectHRC[i0] = Data.MObjectHRC[i0].MT.WriteMP(_MObjectHRC); + } + A3D.Add(MObjectHRC); + } + + if (Data.MObjectHRCList != null) + { + MsgPack MObjectHRCList = new MsgPack("MObjectHRCList", Data.MObjectHRCList.Length); + for (i = 0; i < Data.MObjectHRCList.Length; i++) MObjectHRCList[i] = Data.MObjectHRCList[i]; + A3D.Add(MObjectHRCList); + } + + if (Data.MaterialList != null) + { + MsgPack MaterialList = new MsgPack("MaterialList", Data.MaterialList.Length); + for (i = 0; i < Data.MaterialList.Length; i++) + MaterialList[i] = new MsgPack("Material") + .Add("HashName", Data.MaterialList[i].HashName) + .Add( "Name", Data.MaterialList[i]. Name) + .Add(Data.MaterialList[i].BlendColor .WriteMP("BlendColor" )) + .Add(Data.MaterialList[i].GlowIntensity.WriteMP("GlowIntensity")) + .Add(Data.MaterialList[i].Incandescence.WriteMP("Incandescence")); + A3D.Add(MaterialList); + } + + if (Data.Motion != null) + { + MsgPack Motion = new MsgPack("Motion", Data.Motion.Length); + for (i = 0; i < Data.Motion.Length; i++) Motion[i] = Data.Motion[i]; + A3D.Add(Motion); + } + + if (Data.Object != null) + { + MsgPack Object = new MsgPack("Object", Data.Object.Length); + for (i0 = 0; i0 < Data.Object.Length; i0++) + { + MsgPack _Object = Data.Object[i0].MT.WriteMP( + new MsgPack().Add("Morph" , Data.Object[i0].Morph ) + .Add("MorphOffset", Data.Object[i0].MorphOffset) + .Add( "Name" , Data.Object[i0]. Name ) + .Add("ParentName" , Data.Object[i0].ParentName ) + .Add( "UIDName" , Data.Object[i0]. UIDName )); + if (Data.Object[i0].TP != null) + { + MsgPack TP = new MsgPack("TP", Data.Object[i0].TP.Length); + for (i1 = 0; i1 < Data.Object[i0].TP.Length; i1++) + TP[i1] = new MsgPack().Add("Name" , Data.Object[i0].TP[i1].Name ) + .Add("Pat" , Data.Object[i0].TP[i1].Pat ) + .Add("PatOffset", Data.Object[i0].TP[i1].PatOffset); + _Object.Add(TP); + } + if (Data.Object[i0].TT != null) + { + MsgPack TT = new MsgPack("TT", Data.Object[i0].TT.Length); + for (i1 = 0; i1 < Data.Object[i0].TT.Length; i1++) + TT[i1] = new MsgPack().Add("Name", Data.Object[i0].TT[i1].Name) + .Add(Data.Object[i0].TT[i1].C .WriteMP("C" )) + .Add(Data.Object[i0].TT[i1].O .WriteMP("O" )) + .Add(Data.Object[i0].TT[i1].R .WriteMP("R" )) + .Add(Data.Object[i0].TT[i1].Ro.WriteMP("Ro")) + .Add(Data.Object[i0].TT[i1].RF.WriteMP("RF")) + .Add(Data.Object[i0].TT[i1].TF.WriteMP("TF")); + _Object.Add(TT); + } + Object[i0] = _Object; + } + A3D.Add(Object); + } + + if (Data.ObjectHRC != null) + { + MsgPack ObjectHRC = new MsgPack("ObjectHRC", Data.ObjectHRC.Length); + for (i0 = 0; i0 < Data.ObjectHRC.Length; i0++) + { + MsgPack _ObjectHRC = new MsgPack().Add( "Name", Data.ObjectHRC[i0]. Name) + .Add("Shadow" , Data.ObjectHRC[i0].Shadow ) + .Add("UIDName", Data.ObjectHRC[i0].UIDName); + + if (IsX && Data.ObjectHRC[i0].JointOrient != null) + _ObjectHRC.Add(new MsgPack("JointOrient") + .Add("X", Data.ObjectHRC[i0].JointOrient.X) + .Add("Y", Data.ObjectHRC[i0].JointOrient.Y) + .Add("Z", Data.ObjectHRC[i0].JointOrient.Z)); + + if (Data.ObjectHRC[i0].Node != null) + { + MsgPack Node = new MsgPack("Node", Data.ObjectHRC[i0].Node.Length); + for (i1 = 0; i1 < Data.ObjectHRC[i0].Node.Length; i1++) + Node[i1] = Data.ObjectHRC[i0].Node[i1].MT.WriteMP(new MsgPack() + .Add("Name" , Data.ObjectHRC[i0].Node[i1].Name ) + .Add("Parent", Data.ObjectHRC[i0].Node[i1].Parent)); + _ObjectHRC.Add(Node); + } + ObjectHRC[i0] = _ObjectHRC; + } + A3D.Add(ObjectHRC); + } + + if (Data.ObjectHRCList != null) + { + MsgPack ObjectHRCList = new MsgPack("ObjectHRCList", Data.ObjectHRCList.Length); + for (i = 0; i < Data.ObjectHRCList.Length; i++) ObjectHRCList[i] = Data.ObjectHRCList[i]; + A3D.Add(ObjectHRCList); + } + + if (Data.ObjectList != null) + { + MsgPack ObjectList = new MsgPack("ObjectList", Data.ObjectList.Length); + for (i = 0; i < Data.ObjectList.Length; i++) ObjectList[i] = Data.ObjectList[i]; + A3D.Add(ObjectList); + } + + if (Data.PlayControl != null) + A3D.Add(new MsgPack("PlayControl") + .Add("Begin" , Data.PlayControl.Begin ) + .Add("Div" , Data.PlayControl.Div ) + .Add("FPS" , Data.PlayControl.FPS ) + .Add("Offset", Data.PlayControl.Offset) + .Add("Size" , Data.PlayControl.Size )); + + if (Data.Point != null) + { + MsgPack Point = new MsgPack("Point", Data.Point.Length); + for (i = 0; i < Data.Point.Length; i++) + Point[i] = Data.Point[i].WriteMP(); + A3D.Add(Point); + } + + if (Data.PostProcess != null) + A3D.Add(new MsgPack("PostProcess").Add(Data.PostProcess.Ambient .WriteMP("Ambient" )) + .Add(Data.PostProcess.Diffuse .WriteMP("Diffuse" )) + .Add(Data.PostProcess.LensFlare.WriteMP("LensFlare")) + .Add(Data.PostProcess.LensGhost.WriteMP("LensGhost")) + .Add(Data.PostProcess.LensShaft.WriteMP("LensShaft")) + .Add(Data.PostProcess.Specular .WriteMP("Specular" ))); + + MsgPack = new MsgPack(MsgPack.Types.FixMap).Add(A3D); + + MPIO IO = new MPIO(File.OpenWriter(file + ".mp", true)); + IO.Write(MsgPack, true); + IO = null; + MsgPack = null; + } + } + + public struct _ + { + public int? CompressF16; + public string FileName; + public string PropertyVersion; + public string ConverterVersion; + } + + public struct A3DAData + { + public string[] Motion; + public string[] ObjectList; + public string[] ObjectHRCList; + public string[] MObjectHRCList; + public _ _; + public DOF DOF; + public Fog[] Fog; + public Curve[] Curve; + public Event[] Event; + public Light[] Light; + public Header Head; + public PDHead Header; + public Object[] Object; + public Ambient[] Ambient; + public ObjectHRC[] ObjectHRC; + public CameraRoot[] CameraRoot; + public MObjectHRC[] MObjectHRC; + public PlayControl PlayControl; + public PostProcess PostProcess; + public MaterialList[] MaterialList; + public ModelTransform[] Chara; + public ModelTransform[] Point; + public CameraAuxiliary CameraAuxiliary; + } + + public struct Ambient + { + public string Name; + public RGBAKey LightDiffuse; + public RGBAKey RimLightDiffuse; + } + + public class CameraAuxiliary + { + public Key Gamma; + public Key Exposure; + public Key Saturate; + public Key GammaRate; + public Key AutoExposure; + } + + public struct CameraRoot + { + public ViewPoint ViewPoint; + public ModelTransform MT; + public ModelTransform Interest; + } + + public struct Curve + { + public string Name; + public Key CV; + } + + public class DOF + { + public string Name; + public ModelTransform MT; + } + + public struct Event + { + public int? Type; + public double? End; + public double? Begin; + public double? ClipEnd; + public double? ClipBegin; + public double? TimeRefScale; + public string Name; + public string Param1; + public string Ref; + } + + public struct Fog + { + public int? Id; + public Key End; + public Key Start; + public Key Density; + public RGBAKey Diffuse; + } + + public struct Header + { + public int Count; + public int BinaryLength; + public int BinaryOffset; + public int HeaderOffset; + public int StringLength; + public int StringOffset; + } + + public class Key + { + public int? Type; + public int? Length; + public int? BinOffset; + public double? Max; + public double? Value; + public double? EPTypePost; + public double? EPTypePre; + public RawD RawData; + public Transform[] Trans; + + public class RawD + { + public int? KeyType; + public int? ValueListSize; + public string ValueType; + public string[] ValueList; + } + + public struct Transform + { + public int Type; + public double Frame; + public double[] Value; + + public override string ToString() => ToString(true); + public string ToString(bool Brackets) + { + if (Value == null) + return Main.ToString(Frame); + + string s = ""; + if (Brackets && Type > 0) s += "("; + s += Main.ToString(Frame); + if (Type == 1 && Value.Length > 0) s += "," + Main.ToString(Value[0]); + if (Type == 2 && Value.Length > 1) s += "," + Main.ToString(Value[1]); + if (Type == 3 && Value.Length > 2) s += "," + Main.ToString(Value[2]); + if (Brackets && Type > 0) s += ")"; + return s; + } + } + } + + public struct Instance + { + public int? Shadow; + public string Name; + public string UIDName; + public ModelTransform MT; + } + + public struct KeyUV + { + public Key U; + public Key V; + } + + public struct Light + { + public int? Id; + public string Name; + public string Type; + public RGBAKey Ambient; + public RGBAKey Diffuse; + public RGBAKey Specular; + public RGBAKey Incandescence; + public ModelTransform Position; + public ModelTransform SpotDirection; + } + + public struct MaterialList + { + public string Name; + public string HashName; + public Key GlowIntensity; + public RGBAKey BlendColor; + public RGBAKey Incandescence; + } + + public struct MObjectHRC + { + public string Name; + public Node[] Node; + public Vector3 JointOrient; + public Instance[] Instance; + public ModelTransform MT; + } + + public struct ModelTransform + { + public bool Writed; + public int? BinOffset; + public Key Visibility; + public Vector3 Rot; + public Vector3 Scale; + public Vector3 Trans; + } + + public struct Node + { + public int? Parent; + public string Name; + public ModelTransform MT; + } + + public struct Object + { + public int? MorphOffset; + public string Name; + public string Morph; + public string UIDName; + public string ParentName; + public ModelTransform MT; + public TexturePattern[] TP; //TexPat + public TextureTransform[] TT; //TexTrans + + public struct TexturePattern + { + public int? PatOffset; + public string Pat; + public string Name; + } + + public struct TextureTransform + { + public string Name; + public KeyUV C; //Coverage + public KeyUV O; //Offset + public KeyUV R; //Repeat + public Key Ro; //Rotate + public Key RF; //RotateFrame + public KeyUV TF; //TranslateFrameU + } + } + + public struct ObjectHRC + { + public double? Shadow; + public string Name; + public string UIDName; + public Node[] Node; + public Vector3 JointOrient; + } + + public class PlayControl + { + public double? Begin; + public double? Div; + public double? FPS; + public double? Offset; + public double? Size; + } + + public class PostProcess + { + public Key LensFlare; + public Key LensGhost; + public Key LensShaft; + public RGBAKey Ambient; + public RGBAKey Diffuse; + public RGBAKey Specular; + } + + public struct RGBAKey + { + public Key R; + public Key G; + public Key B; + public Key A; + } + + public struct Values + { + public List< int?> BinOffset; + public List Value; + } + + public class Vector3 + { + public T X; + public T Y; + public T Z; + } + + public struct ViewPoint + { + public double? Aspect; + public double? FOVHorizontal; + public double? CameraApertureH; + public double? CameraApertureW; + public Key FOV; + public Key Roll; + public Key FocalLength; + public ModelTransform MT; + } +} diff --git a/KKdMainLib/A3DA/A3DAExt.cs b/KKdMainLib/A3DA/A3DAExt.cs new file mode 100644 index 0000000..69544a2 --- /dev/null +++ b/KKdMainLib/A3DA/A3DAExt.cs @@ -0,0 +1,390 @@ +using System.Collections.Generic; +using KKdMainLib.IO; +using KKdMainLib.MessagePack; + +namespace KKdMainLib.A3DA +{ + public static class A3DAExt + { + private const string d = "."; + private const string BO = "bin_offset"; + private const string MTBO = "model_transform" + d + BO; + + private static string value; + private static string[] dataArray; + private static int SOi; + private static int[] SO; + + public static ModelTransform ReadMT(this Dictionary Dict, string Temp) + { + ModelTransform MT = new ModelTransform(); + Dict.FindValue(out MT.BinOffset, Temp + MTBO); + + MT.Rot = Dict.ReadVec3(Temp + "rot" + d); + MT.Scale = Dict.ReadVec3(Temp + "scale" + d); + MT.Trans = Dict.ReadVec3(Temp + "trans" + d); + MT.Visibility = Dict.ReadKey (Temp + "visibility" + d); + return MT; + } + + public static RGBAKey ReadRGBAKey(this Dictionary Dict, string Temp) => + new RGBAKey { A = Dict.ReadKey(Temp + "a" + d), B = Dict.ReadKey(Temp + "b" + d), + G = Dict.ReadKey(Temp + "g" + d), R = Dict.ReadKey(Temp + "r" + d) }; + + public static Vector3 ReadVec3(this Dictionary Dict, string Temp) => + new Vector3 { X = Dict.ReadKey(Temp + "x" + d), Y = + Dict.ReadKey(Temp + "y" + d), Z = Dict.ReadKey(Temp + "z" + d) }; + + public static KeyUV ReadKeyUV(this Dictionary Dict, string Temp) => + new KeyUV { U = Dict.ReadKey(Temp + "U" + d), V = Dict.ReadKey(Temp + "V" + d) }; + + public static Key ReadKey(this Dictionary Dict, string Temp) + { + Key Key = new Key(); + Dict.FindValue(out Key.BinOffset, Temp + BO ); + Dict.FindValue(out Key.Type , Temp + "type"); + + if (Key.Type == null) return Key; + if (Key.Type == 0x0000) return Key; + + if (Key.Type == 0x0001) { Dict.FindValue(out Key.Value, Temp + "value"); return Key; } + + int i = 0, i0 = 0; + byte i1 = 0; + Dict.FindValue(out Key.EPTypePost, Temp + "ep_type_post"); + Dict.FindValue(out Key.EPTypePre , Temp + "ep_type_pre" ); + Dict.FindValue(out Key.Length , Temp + "key.length" ); + Dict.FindValue(out Key.Max , Temp + "max" ); + if (Dict.StartsWith(Temp + "raw_data")) + Dict.FindValue(out Key.RawData.KeyType, Temp + "raw_data_key_type"); + + if (Key.Length != null) + { + Key.Trans = new Key.Transform[(int)Key.Length]; + for (i0 = 0; i0 < Key.Length; i0++) + if (Dict.FindValue(out value, Temp + "key" + d + i0 + d + "data")) + { + Key.Trans[i0] = new Key.Transform(); + dataArray = value.Replace("(", "").Replace(")", "").Split(','); + Key.Trans[i0].Type = dataArray.Length - 1; + Key.Trans[i0].Frame = dataArray[0].ToDouble(); + Key.Trans[i0].Value = new double[Key.Trans[i0].Type]; + for (i1 = 1; i1 < dataArray.Length; i1++) + Key.Trans[i0].Value[i1 - 1] = dataArray[i1].ToDouble(); + } + } + else if (Key.RawData.KeyType != null) + { + Key.RawData = new Key.RawD(); + Dict.FindValue(out Key.RawData.ValueType, Temp + "raw_data.value_type"); + if (Dict.FindValue(out value, Temp + "raw_data.value_list")) + Key.RawData.ValueList = value.Split(','); + Dict.FindValue(out Key.RawData.ValueListSize, Temp + "raw_data.value_list_size"); + value = ""; + + int DataSize = (int)Key.RawData.KeyType + 1; + Key.Length = Key.RawData.ValueListSize / DataSize; + Key.Trans = new Key.Transform[(int)Key.Length]; + for (i = 0; i < Key.Length; i++) + { + Key.Trans[i].Type = (int)Key.RawData.KeyType; + Key.Trans[i].Frame = Key.RawData.ValueList[i * DataSize + 0].ToDouble(); + Key.Trans[i].Value = new double[Key.Trans[i0].Type]; + for (i1 = 1; i1 < Key.Trans[i].Type; i1++) + Key.Trans[i].Value[i1 - 1] = Key.RawData.ValueList[i * DataSize + i1].ToDouble(); + } + Key.RawData.ValueList = null; + } + return Key; + } + + public static void Write(this Stream IO, ModelTransform MT, + string Temp, bool A3DC, bool IsX = false, byte Flags = 0b11111) + { + if (A3DC && !MT.Writed && (Flags & 0b10000) == 0b10000) + { IO.Write(Temp + MTBO + "=", MT.BinOffset); MT.Writed = true; } + + if (A3DC) return; + + if ((Flags & 0b01000) == 0b01000) IO.Write(MT.Rot , Temp + "rot" + d, A3DC); + if ((Flags & 0b00100) == 0b00100) IO.Write(MT.Scale , Temp + "scale" + d, A3DC); + if ((Flags & 0b00010) == 0b00010) IO.Write(MT.Trans , Temp + "trans" + d, A3DC); + if ((Flags & 0b00001) == 0b00001) IO.Write(MT.Visibility, Temp + "visibility" + d, A3DC); + } + + public static void Write(this Stream IO, RGBAKey RGBA, string Temp, string Data, bool A3DC = false) + { + IO.Write(Temp + Data + "=", "true"); + IO.Write(RGBA.A, Temp + Data + d + "a" + d, A3DC); IO.Write(RGBA.B, Temp + Data + d + "b" + d, A3DC); + IO.Write(RGBA.G, Temp + Data + d + "g" + d, A3DC); IO.Write(RGBA.R, Temp + Data + d + "r" + d, A3DC); + } + + public static void Write(this Stream IO, Vector3 Key, string Temp, bool A3DC = false) + { IO.Write(Key.X, Temp + "x" + d, A3DC); IO.Write(Key.Y, + Temp + "y" + d, A3DC); IO.Write(Key.Z, Temp + "z" + d, A3DC); } + + public static void Write(this Stream IO, KeyUV UV, string Temp, string Data, bool A3DC = false) + { IO.Write(UV.U, Temp, Data + "U", A3DC); IO.Write(UV.V, Temp, Data + "V", A3DC); } + + public static void Write(this Stream IO, Key Key, string Temp, string Data, bool A3DC = false) + { if (Key != null) { IO.Write(Temp + Data + "=", "true"); IO.Write(Key, Temp + Data + d, A3DC); } } + + public static void Write(this Stream IO, Key Key, string Temp, bool A3DC = false) + { + if (Key == null) return; + + if (A3DC) { IO.Write(Temp + BO + "=", Key.BinOffset); return; } + + int i = 0; + if (Key.Trans != null) + if (Key.Trans.Length == 0) + { + IO.Write(Temp + "type=", Key.Type); + if (Key.Type > 0) IO.Write(Temp + "value=", Key.Value); + return; + } + + if (Key.EPTypePost != null) IO.Write(Temp + "ep_type_post=", Key.EPTypePost); + if (Key.EPTypePre != null) IO.Write(Temp + "ep_type_pre=" , Key.EPTypePre ); + if (Key.RawData == null && Key.Trans != null) + { + SO = Key.Trans.Length.SortWriter(); + for (i = 0; i < Key.Trans.Length; i++) + { + SOi = SO[i]; + IO.Write(Temp + "key" + d + SOi + d + "data=", Key.Trans[SOi].ToString()); + IO.Write(Temp + "key" + d + SOi + d + "type=", Key.Trans[SOi].Type ); + } + IO.Write(Temp + "key.length=", Key.Length); + if (Key.Max != null) IO.Write(Temp + "max=", Key.Max); + } + else if (Key.Trans != null) + { + if (Key.Max != null) IO.Write(Temp + "max=", Key.Max); + for (i = 0; i < Key.Trans.Length; i++) + { + if (Key.RawData.KeyType < Key.Trans[i].Type || Key.RawData.KeyType == null) + Key.RawData.KeyType = Key.Trans[i].Type; + if (Key.RawData.KeyType == 3) break; + } + Key.RawData.ValueListSize = Key.Trans.Length * (Key.RawData.KeyType + 1); + IO.Write(Temp + "raw_data.value_list="); + for (i = 0; i < Key.Trans.Length; i++) + IO.Write(Key.Trans[i].ToString(false)); + IO.Position = IO.Position - 1; + IO.Write('\n'); + IO.Write(Temp + "raw_data.value_list_size=", Key.RawData.ValueListSize); + IO.Write(Temp + "raw_data.value_type=" , Key.RawData.ValueType ); + IO.Write(Temp + "raw_data_key_type=" , Key.RawData. KeyType ); + } + IO.Write(Temp + "type=", Key.Type & 0xFF); + } + + public static void ReadMT(this Stream IO, ref ModelTransform MT, int C_F16) + { + if (MT.BinOffset == null) return; + + IO.Position = IO.Offset + (int)MT.BinOffset; + + IO.ReadOffset(ref MT.Scale); + IO.ReadOffset(ref MT.Rot ); + IO.ReadOffset(ref MT.Trans); + MT.Visibility.BinOffset = IO.ReadInt32(); + + IO.ReadVec3(ref MT.Scale , C_F16); + IO.ReadVec3(ref MT.Rot , C_F16, true); + IO.ReadVec3(ref MT.Trans , C_F16); + IO.ReadKey (ref MT.Visibility, C_F16); + } + + public static void ReadRGBAKey(this Stream IO, ref RGBAKey RGBA, int C_F16) + { IO.ReadKey(ref RGBA.R, C_F16); IO.ReadKey(ref RGBA.G, C_F16); + IO.ReadKey(ref RGBA.B, C_F16); IO.ReadKey(ref RGBA.A, C_F16); } + + public static void ReadVec3(this Stream IO, ref Vector3 Key, int C_F16, bool F16 = false) + { IO.ReadKey(ref Key.X, C_F16, F16); IO.ReadKey(ref Key.Y, C_F16, F16); IO.ReadKey(ref Key.Z, C_F16, F16); } + + public static void ReadKeyUV(this Stream IO, ref KeyUV UV, int C_F16) + { IO.ReadKey(ref UV.U, C_F16); IO.ReadKey(ref UV.V, C_F16); } + + public static void ReadKey(this Stream IO, ref Key Key, int C_F16, bool F16 = false) + { + if (Key.BinOffset == null || Key.BinOffset < 0) return; + + IO.Position = IO.Offset + (int)Key.BinOffset; + Key.Type = IO.ReadInt32(); + + Key.Value = IO.ReadSingle(); + if (Key.Type == 0x0000 || Key.Type == 0x0001) return; + + Key.Max = IO.ReadSingle(); + Key.Length = IO.ReadInt32 (); + Key.Trans = new Key.Transform[(int)Key.Length]; + int Ke = (int)Key.Length; + for (int i = 0; i < Key.Length; i++) + { + Key.Trans[i] = new Key.Transform { Type = 3, Value = new double[3] }; + if (F16 && C_F16 > 0) + { Key.Trans[i].Frame = IO.ReadUInt16(); Key.Trans[i].Value[0] = (double)IO.ReadHalf (); } + else + { Key.Trans[i].Frame = IO.ReadSingle(); Key.Trans[i].Value[0] = IO.ReadSingle(); } + + if (F16 && C_F16 == 2) + { Key.Trans[i].Value[1] = (double)IO.ReadHalf (); + Key.Trans[i].Value[2] = (double)IO.ReadHalf (); } + else + { Key.Trans[i].Value[1] = IO.ReadSingle(); + Key.Trans[i].Value[2] = IO.ReadSingle(); } + } + } + + public static void ReadOffset(this Stream IO, ref Vector3 Key) + { Key.X.BinOffset = IO.ReadInt32(); Key.Y.BinOffset = IO.ReadInt32(); Key.Z.BinOffset = IO.ReadInt32(); } + + public static void WriteOffset(this Stream IO, ref ModelTransform MT, bool ReturnToOffset) + { + if (ReturnToOffset) + { + IO.Position = (int)MT.BinOffset; + IO.WriteOffset(MT.Scale); + IO.WriteOffset(MT.Rot ); + IO.WriteOffset(MT.Trans); + IO.Write(MT.Visibility.BinOffset); + } + else + { + MT.BinOffset = IO.Position; + IO.Position += 0x30; + IO.Length += 0x30; + } + } + + public static void WriteOffset(this Stream IO, Vector3 Key) + { + IO.Write(Key.X.BinOffset); + IO.Write(Key.Y.BinOffset); + IO.Write(Key.Z.BinOffset); + } + + public static ModelTransform ReadMT(this MsgPack k, string name) + { if (k.Element(name, out MsgPack Name)) return Name.ReadMT(); return new ModelTransform(); } + + public static ModelTransform ReadMT(this MsgPack k) => + new ModelTransform { Rot = k.ReadVec3("Rot" ), Scale = k.ReadVec3("Scale" ), + Trans = k.ReadVec3("Trans"), Visibility = k.ReadKey ("Visibility") }; + + public static RGBAKey ReadRGBAKey(this MsgPack k, string name) + { if (k.Element(name, out MsgPack Name)) return Name.ReadRGBAKey(); return new RGBAKey(); } + + public static RGBAKey ReadRGBAKey(this MsgPack k) => + new RGBAKey { R = k.ReadKey("R"), G = k.ReadKey("G"), B = k.ReadKey("B"), A = k.ReadKey("A") }; + + public static Vector3 ReadVec3(this MsgPack k, string name) + { if (k.Element(name, out MsgPack Name)) return Name.ReadVec3(); return new Vector3(); } + + public static Vector3 ReadVec3(this MsgPack k) => + new Vector3 { X = k.ReadKey("X"), Y = k.ReadKey("Y"), Z = k.ReadKey("Z") }; + + public static KeyUV ReadKeyUV(this MsgPack k, string name) + { if (k.Element(name, out MsgPack Name)) return Name.ReadKeyUV(); return new KeyUV(); } + + public static KeyUV ReadKeyUV(this MsgPack k) => + new KeyUV { U = k.ReadKey("U"), V = k.ReadKey("V") }; + + public static Key ReadKey(this MsgPack k, string name) + { if (k.Element(name, out MsgPack Name)) return Name.ReadKey(); return new Key(); } + + public static Key ReadKey(this MsgPack k) + { + if (k == null) return new Key(); + + Key Key = new Key { EPTypePost = k.ReadNDouble("Post"), + EPTypePre = k.ReadNDouble("Pre"), Max = k.ReadNDouble("M"), + Type = k.ReadNInt32("T"), Value = k.ReadNDouble("V") }; + if (k.ReadBoolean("RD")) Key.RawData = new Key.RawD(); + if (Key.Type == 0) Key.Value = 0.0; + + if (Key.Type < 2) return Key; + + if (!k.Element("Trans", out MsgPack Trans, typeof(object[]))) return Key; + + Key.Length = ((object[])Trans.Object).Length; + Key.Trans = new Key.Transform[Key.Length.Value]; + MsgPack _Trans = new MsgPack(); + byte i1 = 0; + for (int i = 0; i < Key.Length; i++) + { + Key.Trans[i] = new Key.Transform(); + if (Trans[i].GetType() != typeof(MsgPack)) continue; + + _Trans = (MsgPack)Trans[i]; + if (_Trans.Object.GetType() != typeof(object[])) continue; + Key.Trans[i].Type = ((object[])_Trans.Object).Length - 1; + Key.Trans[i].Value = new double[Key.Trans[i].Type]; + + if (_Trans[0].GetType() != typeof(MsgPack)) continue; + Key.Trans[i].Frame = ((MsgPack)_Trans[0]).ReadDouble(); + + for (i1 = 0; i1 < Key.Trans[i].Type; i1++) + Key.Trans[i].Value[i1] = ((MsgPack)_Trans[i1 + 1]).ReadDouble(); + } + return Key; + } + + public static MsgPack WriteMP(this ModelTransform MT, string name) => + MT.WriteMP(new MsgPack(name)); + + public static MsgPack WriteMP(this ModelTransform MT) => + MT.WriteMP(new MsgPack( )); + + public static MsgPack WriteMP(this ModelTransform MT, MsgPack MTs) => + MTs.Add(MT.Rot .WriteMP("Rot" )) + .Add(MT.Scale .WriteMP("Scale" )) + .Add(MT.Trans .WriteMP("Trans" )) + .Add(MT.Visibility.WriteMP("Visibility")); + + public static MsgPack WriteMP(this RGBAKey RGBA, string name) + { + if (RGBA.R == null && RGBA.G == null && RGBA.B == null && RGBA.A == null) return MsgPack.Null; + return new MsgPack(name).Add(RGBA.R.WriteMP("R")).Add(RGBA.G.WriteMP("G")) + .Add(RGBA.B.WriteMP("B")).Add(RGBA.A.WriteMP("A")); + } + + public static MsgPack WriteMP(this Vector3 Key, string name) => + new MsgPack(name).Add(Key.X.WriteMP("X")).Add(Key.Y.WriteMP("Y")).Add(Key.Z.WriteMP("Z")); + + public static MsgPack WriteMP(this KeyUV UV, string name) + { + if (UV.U == null && UV.V == null) return MsgPack.Null; + return new MsgPack(name).Add(UV.U.WriteMP("U")).Add(UV.V.WriteMP("V")); + } + + public static MsgPack WriteMP(this Key Key, string name) + { + if (Key == null) return MsgPack.Null; + if (Key.Type == null) return MsgPack.Null; + + MsgPack Keys = new MsgPack(name).Add("T", Key.Type); + if (Key.Trans != null) + { + Keys.Add("Post", Key.EPTypePost).Add("Pre", Key.EPTypePre).Add("M", Key.Max); + + if (Key.RawData != null) Keys.Add("RD", true); + + byte i0 = 0; + MsgPack Trans = new MsgPack("Trans", Key.Trans.Length); + for (int i = 0; i < Key.Trans.Length; i++) + { + MsgPack K = new MsgPack(Key.Trans[i].Type + 1); + K[0] = Key.Trans[i].Frame; + for (i0 = 1; i0 < Key.Trans[i].Type + 1; i0++) + K[i0] = Key.Trans[i].Value[i0 - 1]; + Trans[i] = K; + } + Keys.Add(Trans); + } + else if (Key.Value != 0) Keys.Add("V", Key.Value); + return Keys; + } + } +} diff --git a/KKdMainLib/DB/Auth.cs b/KKdMainLib/DB/Auth.cs new file mode 100644 index 0000000..174e87a --- /dev/null +++ b/KKdMainLib/DB/Auth.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using KKdMainLib.IO; +using KKdMainLib.MessagePack; +using MPIO = KKdMainLib.MessagePack.IO; + +namespace KKdMainLib.DB +{ + public struct Auth + { + public int Signature { get; private set; } + public string[] Category { get; private set; } + public UID[] _UID { get; private set; } + public Stream IO { get; private set; } + + public int BINReader(string file) + { + Dictionary Dict = new Dictionary(); + string[] dataArray; + + IO = File.OpenReader(file + ".bin"); + + IO.Format = Main.Format.F; + Signature = IO.ReadInt32(); + if (Signature != 0x44334123) return 0; + Signature = IO.ReadInt32(); + if (Signature != 0x5F5F5F41) return 0; + IO.ReadInt64(); + + string[] STRData = IO.ReadString(IO.Length - IO.Position).Replace("\r", "").Split('\n'); + for (int i = 0; i < STRData.Length; i++) + { + dataArray = STRData[i].Split('='); + if (dataArray.Length == 2) + Dict.GetDictionary(dataArray[0], dataArray[1]); + } + + if (Dict.FindValue(out string value, "category.length")) + { + Category = new string[int.Parse(value)]; + for (int i0 = 0; i0 < Category.Length; i0++) + if (Dict.FindValue(out value, "category." + i0 + ".value")) + Category[i0] = value; + } + + if (Dict.FindValue(out value, "uid.length")) + { + _UID = new UID[int.Parse(value)]; + for (int i0 = 0; i0 < _UID.Length; i0++) + { + Dict.FindValue(out _UID[i0].Category, "uid." + i0 + ".category"); + Dict.FindValue(out _UID[i0].Size , "uid." + i0 + ".size" ); + Dict.FindValue(out _UID[i0].Value , "uid." + i0 + ".value" ); + } + } + + IO.Close(); + return 1; + } + + public void BINWriter(string file) + { + IO = File.OpenWriter(file + ".bin", true); + + IO.Write("#A3DA__________\n"); + IO.Write("#", DateTime.UtcNow.ToString("ddd MMM dd HH:mm:ss yyyy", + System.Globalization.CultureInfo.InvariantCulture)); + + if (Category != null) + { + int[] SO = Category.Length.SortWriter(); + for (int i = 0; i < Category.Length; i++) + if (Category[SO[i]] != null) + IO.Write("category." + SO[i] + ".value=", Category[SO[i]]); + IO.Write("category.length=", Category.Length); + } + + if (_UID != null) + { + int[] SO = _UID.Length.SortWriter(); + for (int i = 0; i < _UID.Length; i++) + { + if (_UID[SO[i]].Category != null) + if (_UID[SO[i]].Category != "") + IO.Write("uid." + SO[i] + ".category=", _UID[SO[i]].Category); + if (_UID[SO[i]].Size != null) + IO.Write("uid." + SO[i] + ".size=" , _UID[SO[i]].Size ); + if (_UID[SO[i]].Value != null) + if (_UID[SO[i]].Value != "") + IO.Write("uid." + SO[i] + ".value=" , _UID[SO[i]].Value ); + } + IO.Write("uid.length=", _UID.Length); + } + + IO.Close(); + } + + public void MsgPackReader(string file) + { + MPIO IO = new MPIO(File.OpenReader(file + ".mp")); + MsgPack MsgPack = IO.Read(); + IO.Close(); + IO = null; + + if (MsgPack.Element("AuthDB", out MsgPack AuthDB)) + { + if (AuthDB.Element("Category", out MsgPack Temp, typeof(object[]))) + { + this.Category = new string[((object[])Temp.Object).Length]; + MsgPack Category = new MsgPack(); + for (int i = 0; i < this.Category.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + Category = (MsgPack)Temp[i]; + this.Category[i] = Category.ReadString(); + } + } + + if (AuthDB.Element("UID", out Temp, typeof(object[]))) + { + _UID = new UID[((object[])Temp.Object).Length]; + MsgPack UID = new MsgPack(); + for (int i = 0; i < _UID.Length; i++) + if (Temp[i].GetType() == typeof(MsgPack)) + { + UID = (MsgPack)Temp[i]; + _UID[i].Category = UID.ReadString("C"); + _UID[i].Size = UID.ReadNInt32("S"); + _UID[i].Value = UID.ReadString("V"); + } + } + } + MsgPack = null; + } + + public void MsgPackWriter(string file) + { + MsgPack AuthDB = new MsgPack("AuthDB"); + if (Category != null) + { + MsgPack Category = new MsgPack("Category", this.Category.Length); + for (int i = 0; i < this.Category.Length; i++) + Category[i] = this.Category[i]; + AuthDB.Add(Category); + } + + if (_UID != null) + { + MsgPack UID = new MsgPack("UID", _UID.Length); + for (int i = 0; i < _UID.Length; i++) + UID[i] = new MsgPack() + .Add("C", _UID[i].Category) + .Add("S", _UID[i].Size ) + .Add("V", _UID[i].Value ); + AuthDB.Add(UID); + } + + MsgPack MsgPack = new MsgPack(MsgPack.Types.FixMap).Add(AuthDB); + + MPIO IO = new MPIO(File.OpenWriter(file + ".mp", true)); + IO.Write(MsgPack, true); + IO = null; + MsgPack = null; + } + + public struct UID + { + public int? Size; + public string Value; + public string Category; + } + } +} diff --git a/KKdMainLib/DEX.cs b/KKdMainLib/DEX.cs new file mode 100644 index 0000000..c179d80 --- /dev/null +++ b/KKdMainLib/DEX.cs @@ -0,0 +1,293 @@ +using System.Collections.Generic; +using KKdMainLib.IO; +using KKdMainLib.MessagePack; +using MPIO = KKdMainLib.MessagePack.IO; + +namespace KKdMainLib +{ + public class DEX + { + public DEX() + { Dex = null; Header = new PDHead(); } + + private int Offset = 0; + private PDHead Header; + + private MsgPack MsgPack; + public Stream IO; + public EXP[] Dex; + + public int DEXReader(string filepath, string ext) + { + Header = new PDHead(); + IO = File.OpenReader(filepath + ext); + + Header.Format = Main.Format.F; + Header.Signature = IO.ReadInt32(); + if (Header.Signature == 0x43505845) + Header = IO.ReadHeader(true); + if (Header.Signature != 0x64) + return 0; + + Offset = IO.Position - 0x4; + Dex = new EXP[IO.ReadInt32()]; + int DEXOffset = IO.ReadInt32(); + if (IO.ReadInt32() == 0x00) Header.Format = Main.Format.X; + int DEXNameOffset = IO.ReadInt32(); + if (Header.IsX) IO.ReadInt32(); + + IO.Seek(DEXOffset + Offset, 0); + for (int i0 = 0; i0 < Dex.Length; i0++) + Dex[i0] = new EXP { Main = new List(), Eyes = new List() }; + + for (int i0 = 0; i0 < Dex.Length; i0++) + { + Dex[i0].MainOffset = IO.ReadInt32(); + if (Header.IsX) IO.ReadInt32(); + Dex[i0].EyesOffset = IO.ReadInt32(); + if (Header.IsX) IO.ReadInt32(); + } + IO.Seek(DEXNameOffset + Offset, 0); + for (int i0 = 0; i0 < Dex.Length; i0++) + { + Dex[i0].NameOffset = IO.ReadInt32(); + if (Header.IsX) IO.ReadInt32(); + } + + for (int i0 = 0; i0 < Dex.Length; i0++) + { + EXPElement element = new EXPElement(); + IO.Seek(Dex[i0].MainOffset + Offset, 0); + while (true) + { + element.Frame = IO.ReadSingle(); + element.Both = IO.ReadUInt16(); + element.ID = IO.ReadUInt16(); + element.Value = IO.ReadSingle(); + element.Trans = IO.ReadSingle(); + Dex[i0].Main.Add(element); + + if (element.Frame == 999999 || element.Both == 0xFFFF) + break; + } + + IO.Seek(Dex[i0].EyesOffset + Offset, 0); + while(true) + { + element.Frame = IO.ReadSingle(); + element.Both = IO.ReadUInt16(); + element.ID = IO.ReadUInt16(); + element.Value = IO.ReadSingle(); + element.Trans = IO.ReadSingle(); + Dex[i0].Eyes.Add(element); + + if (element.Frame == 999999 || element.Both == 0xFFFF) + break; + } + + IO.Seek(Dex[i0].NameOffset + Offset, 0); + Dex[i0].Name = IO.NullTerminatedUTF8(); + } + + IO.Close(); + return 1; + } + + public void DEXWriter(string filepath, Main.Format Format) + { + Header = new PDHead() { Format = Format }; + IO = File.OpenWriter(filepath + (Header.Format > Main.Format.F ? ".Dex" : ".bin"), true); + IO.Format = Header.Format; + + if (IO.Format > Main.Format.F) + { + Header.Lenght = 0x20; + Header.DataSize = 0x00; + Header.Signature = 0x43505845; + Header.SectionSize = 0x00; + IO.Write(Header); + } + + IO.Write(0x64); + IO.Write(Dex.Length); + + if (Header.IsX) IO.Write((long)0x28); + else IO.Write( 0x20); + if (Header.IsX) IO.Write((long)0x00); + else IO.Write( 0x00); + + int Position0 = IO.Position; + IO.Write((long)0x00); + IO.Write((long)0x00); + + for (int i = 0; i < Dex.Length * 3; i++) + if (Header.IsX) IO.Write((long)0x00); + else IO.Write( 0x00); + + IO.Align(0x20, true); + + for (int i0 = 0; i0 < Dex.Length; i0++) + { + Dex[i0].MainOffset = IO.Position - Header.Lenght; + for (int i1 = 0; i1 < Dex[i0].Main.Count; i1++) + { + IO.Write(Dex[i0].Main[i1].Frame); + IO.Write(Dex[i0].Main[i1].Both ); + IO.Write(Dex[i0].Main[i1].ID ); + IO.Write(Dex[i0].Main[i1].Value); + IO.Write(Dex[i0].Main[i1].Trans); + } + IO.Align(0x20, true); + + Dex[i0].EyesOffset = IO.Position - Header.Lenght; + for (int i1 = 0; i1 < Dex[i0].Eyes.Count; i1++) + { + IO.Write(Dex[i0].Eyes[i1].Frame); + IO.Write(Dex[i0].Eyes[i1].Both ); + IO.Write(Dex[i0].Eyes[i1].ID ); + IO.Write(Dex[i0].Eyes[i1].Value); + IO.Write(Dex[i0].Eyes[i1].Trans); + } + IO.Align(0x20, true); + } + for (int i0 = 0; i0 < Dex.Length; i0++) + { + Dex[i0].NameOffset = IO.Position - Header.Lenght; + IO.Write(Dex[i0].Name + "\0"); + } + IO.Align(0x10, true); + + if (Header.IsX) IO.Seek(Header.Lenght + 0x28, 0); + else IO.Seek(Header.Lenght + 0x20, 0); + for (int i0 = 0; i0 < Dex.Length; i0++) + { + IO.Write(Dex[i0].MainOffset); + if (Header.IsX) IO.Write(0x00); + IO.Write(Dex[i0].EyesOffset); + if (Header.IsX) IO.Write(0x00); + } + int Position1 = IO.Position - Header.Lenght; + for (int i0 = 0; i0 < Dex.Length; i0++) + { + IO.Write(Dex[i0].NameOffset); + if (Header.IsX) IO.Write(0x00); + } + + if (Header.IsX) IO.Seek(Position0 - 8, 0); + else IO.Seek(Position0 - 4, 0); + IO.Write(Position1); + + if (IO.Format > Main.Format.F) + { + Offset = IO.Length - Header.Lenght; + IO.Seek(IO.Length, 0); + IO.WriteEOFC(0); + IO.Seek(0, 0); + Header.DataSize = Offset; + Header.SectionSize = Offset; + IO.Write(Header); + } + IO.Close(); + } + + public void MsgPackReader(string filepath) + { + int i0 = 0; + int i1 = 0; + this.Dex = new EXP[0]; + Header = new PDHead(); + + MPIO IO = new MPIO(File.OpenReader(filepath + ".mp")); + MsgPack = IO.Read(); + IO.Close(); + IO = null; + + if (MsgPack.Element("Dex", out MsgPack Dex, typeof(object[]))) + { + MsgPack Temp = new MsgPack(); + + this.Dex = new EXP[((object[])Dex.Object).Length]; + MsgPack EXP = new MsgPack(); + for (i0 = 0; i0 < this.Dex.Length; i0++) + if (Dex[i0].GetType() == typeof(MsgPack)) + { + this.Dex[i0] = new EXP(); + EXP = (MsgPack)Dex[i0]; + this.Dex[i0].Name = EXP.ReadString("Name"); + if (EXP.Element("Main", out Temp, typeof(object[]))) + { + this.Dex[i0].Main = new List + { Capacity = ((object[])Temp.Object).Length }; + for (i1 = 0; i1 < this.Dex[i0].Main.Capacity; i1++) + if (Temp[i1].GetType() == typeof(MsgPack)) + this.Dex[i0].Main.Add(ReadEXP((MsgPack)Temp[i1])); + } + if (EXP.Element("Eyes", out Temp, typeof(object[]))) + { + this.Dex[i0].Eyes = new List + { Capacity = ((object[])Temp.Object).Length }; + for (i1 = 0; i1 < this.Dex[i0].Eyes.Capacity; i1++) + if (Temp[i1].GetType() == typeof(MsgPack)) + this.Dex[i0].Eyes.Add(ReadEXP((MsgPack)Temp[i1])); + } + } + } + MsgPack = null; + } + + private EXPElement ReadEXP(MsgPack mp) => + new EXPElement() { Frame = mp.ReadSingle("F"), Both = mp.ReadUInt16("B"), + ID = mp.ReadUInt16("I"), Value = mp.ReadSingle("V"), + Trans = mp.ReadSingle("T") }; + + public void MsgPackWriter(string filepath) + { + int i0 = 0; + int i1 = 0; + MsgPack Dex = new MsgPack("Dex", this.Dex.Length); + for (i0 = 0; i0 < this.Dex.Length; i0++) + { + MsgPack EXP = new MsgPack().Add("Name", this.Dex[i0].Name); + MsgPack Main = new MsgPack("Main", this.Dex[i0].Main.Count); + for (i1 = 0; i1 < this.Dex[i0].Main.Count; i1++) + Main[i1] = WriteEXP(this.Dex[i0].Main[i1]); + EXP.Add(Main); + + MsgPack Eyes = new MsgPack("Eyes", this.Dex[i0].Eyes.Count); + for (i1 = 0; i1 < this.Dex[i0].Eyes.Count; i1++) + Eyes[i1] = WriteEXP(this.Dex[i0].Eyes[i1]); + EXP.Add(Eyes); + Dex[i0] = EXP; + } + + MsgPack = new MsgPack(MsgPack.Types.FixMap).Add(Dex); + + MPIO IO = new MPIO(File.OpenWriter(filepath + ".mp", true)); + IO.Write(MsgPack, true); + IO = null; + } + + private MsgPack WriteEXP(EXPElement element) => + new MsgPack().Add("F", element.Frame).Add("B", element.Both ).Add("I", element.ID ) + .Add("V", element.Value).Add("T", element.Trans); + + public struct EXP + { + public int MainOffset; + public int EyesOffset; + public int NameOffset; + public string Name; + public List Main; + public List Eyes; + } + + public struct EXPElement + { + public float Frame; + public ushort Both; + public ushort ID; + public float Value; + public float Trans; + } + } +} diff --git a/KKdMainLib/DIVAFILE.cs b/KKdMainLib/DIVAFILE.cs new file mode 100644 index 0000000..e7e1e08 --- /dev/null +++ b/KKdMainLib/DIVAFILE.cs @@ -0,0 +1,64 @@ +using System; +using System.Security.Cryptography; +using KKdMainLib.IO; +using MSIO = System.IO; + +namespace KKdMainLib +{ + public static class DIVAFILE + { + private static readonly byte[] Key = "file access deny".ToASCII(); + + public static void Decrypt(this string file) + { + Console.Title = "DIVAFILE Decrypt - File: " + MSIO.Path.GetFileName(file); + Stream reader = File.OpenReader(file); + if (reader.ReadInt64() != 0x454C494641564944) + { reader.Close(); return; } + int StreamLenght = reader.ReadInt32(); + int FileLenght = reader.ReadInt32(); + byte[] decrypted = new byte[StreamLenght]; + reader.Seek(0, 0); + using (AesManaged crypto = new AesManaged()) + { + crypto.Key = Key; crypto.IV = new byte[16]; + crypto.Mode = CipherMode.ECB; crypto.Padding = PaddingMode.Zeros; + using (CryptoStream cryptoData = new CryptoStream(reader.BaseStream, + crypto.CreateDecryptor(crypto.Key, crypto.IV), CryptoStreamMode.Read)) + cryptoData.Read(decrypted, 0, StreamLenght); + } + Stream writer = File.OpenWriter(file, FileLenght); + for (int i = 0x10; i < StreamLenght && i < FileLenght + 0x10; i++) + writer.Write(decrypted[i]); + writer.Close(); + } + + public static void Encrypt(this string file) + { + Console.Title = "DIVAFILE Encrypt - File: " + MSIO.Path.GetFileName(file); + Stream reader = File.OpenReader(file); + int FileLenghtOrigin = reader.Length; + int FileLenght = FileLenghtOrigin.Align(16); + reader.Close(); + byte[] In = File.OpenReader(file).ToArray(true); + byte[] Inalign = new byte[FileLenght]; + for (int i = 0; i < In.Length; i++) Inalign[i] = In[i]; + In = null; + byte[] encrypted = new byte[FileLenght]; + using (AesManaged crypto = new AesManaged()) + { + crypto.Key = Key; crypto.IV = new byte[16]; + crypto.Mode = CipherMode.ECB; crypto.Padding = PaddingMode.Zeros; + using (CryptoStream cryptoData = new CryptoStream(new MSIO.MemoryStream(Inalign), + crypto.CreateEncryptor(crypto.Key, crypto.IV), CryptoStreamMode.Read)) + cryptoData.Read(encrypted, 0, FileLenght); + } + Stream writer = File.OpenWriter(file, Inalign.Length); + writer.Write(0x454C494641564944); + writer.Write(FileLenght); + writer.Write(FileLenghtOrigin); + writer.Write(encrypted); + writer.Close(); + } + } +} diff --git a/KKdMainLib/FARC.cs b/KKdMainLib/FARC.cs new file mode 100644 index 0000000..5ea9fd9 --- /dev/null +++ b/KKdMainLib/FARC.cs @@ -0,0 +1,356 @@ +//Original: https://github.com/blueskythlikesclouds/MikuMikuLibrary/ + +using System; +using System.IO.Compression; +using System.Security.Cryptography; +using KKdMainLib.IO; +using MSIO = System.IO; + +namespace KKdMainLib +{ + public class FARC + { + public FARC() { Files = new FARCFile[0]; Signature = Farc.FArC; FT = false; } + + public FARCFile[] Files = new FARCFile[0]; + public Farc Signature = Farc.FArC; + + private bool FT = false; + + private readonly byte[] Key = Text.ToASCII("project_diva.bin"); + + private readonly byte[] KeyFT = { 0x13, 0x72, 0xD5, 0x7B, 0x6E, 0x9E, + 0x31, 0xEB, 0xA2, 0x39, 0xB8, 0x3C, 0x15, 0x57, 0xC6, 0xBB }; + + AesManaged GetAes(bool isFT, byte[] iv) + { + AesManaged AesManaged = new AesManaged { KeySize = 128, Key = isFT ? KeyFT : Key, + BlockSize = 128, Mode = isFT ? CipherMode.CBC : CipherMode.ECB, + Padding = PaddingMode.Zeros, IV = iv ?? new byte[16] }; + return AesManaged; + } + + public void UnPack(string file, bool SaveToDisk = true) + { + Files = null; + Signature = Farc.FArC; + FT = false; + Console.Title = "FARC Extractor - Archive: " + MSIO.Path.GetFileName(file); + if (!MSIO.File.Exists(file)) + { + Console.WriteLine("File {0} doesn't exist.", MSIO.Path.GetFileName(file)); + Console.Clear(); + return; + } + + Stream reader = File.OpenReader(file); + string directory = MSIO.Path.GetFullPath(file).Replace(MSIO.Path.GetExtension(file), ""); + Signature = (Farc)reader.ReadInt32Endian(true); + if (Signature != Farc.FArc && Signature != Farc.FArC && Signature != Farc.FARC) + { + Console.WriteLine("Unknown signature"); reader.Close(); + Console.Clear(); + return; + } + + MSIO.Directory.CreateDirectory(directory); + int HeaderLength = reader.ReadInt32Endian(true); + if (Signature != Farc.FARC) + { + reader.ReadUInt32(); + HeaderReader(HeaderLength, ref Files, ref reader); + reader.Close(); + + for (int i = 0; i < Files.Length; i++) + { + if (Signature == Farc.FArC) + using (MSIO.MemoryStream memorystream = new MSIO.MemoryStream( + File.ReadAllBytes(file, Files[i].SizeComp, Files[i].Offset))) + { + GZipStream gZipStream = new GZipStream(memorystream, CompressionMode.Decompress); + Files[i].Data = new byte[Files[i].SizeUnc]; + gZipStream.Read(Files[i].Data, 0, Files[i].SizeUnc); + } + else + Files[i].Data = File.ReadAllBytes(file, Files[i].SizeUnc, Files[i].Offset); + + if (SaveToDisk) + { + File.WriteAllBytes(MSIO.Path.Combine(directory, Files[i].Name), Files[i].Data); + Files[i].Data = null; + } + } + Console.Clear(); + return; + } + + int Mode = reader.ReadInt32Endian(true); + reader.ReadUInt32(); + bool GZip = (Mode & 2) == 2; + bool ECB = (Mode & 4) == 4; + + int FARCType = reader.ReadInt32Endian(true); + FT = FARCType == 0x10; + bool CBC = !FT && FARCType != 0x40; + if (ECB && CBC) + { + byte[] Header = new byte[HeaderLength - 0x08]; + FT = true; + reader.Close(); + MSIO.FileStream stream = new MSIO.FileStream(file, MSIO.FileMode.Open, + MSIO.FileAccess.ReadWrite, MSIO.FileShare.ReadWrite); + stream.Seek(0x10, 0); + + using (CryptoStream cryptoStream = new CryptoStream(stream, + GetAes(true, null).CreateDecryptor(), CryptoStreamMode.Read)) + cryptoStream.Read(Header, 0x00, HeaderLength - 0x08); + Header = SkipData(Header, 0x10); + Stream CBCreader = new Stream(new MSIO.MemoryStream(Header)); + CBCreader.BaseStream.Seek(0, 0); + + FARCType = CBCreader.ReadInt32Endian(true); + FT = FARCType == 0x10; + if (CBCreader.ReadInt32Endian(true) == 1) + Files = new FARCFile[CBCreader.ReadInt32Endian(true)]; + CBCreader.ReadUInt32(); + HeaderReader(HeaderLength, ref Files, ref CBCreader); + CBCreader.Close(); + } + else + { + if (reader.ReadInt32Endian(true) == 1) + Files = new FARCFile[reader.ReadInt32Endian(true)]; + reader.ReadUInt32(); + HeaderReader(HeaderLength, ref Files, ref reader); + reader.Close(); + } + + for (int i = 0; i < Files.Length; i++) + { + int FileSize = ECB || Files[i].ECB ? Files[i].SizeComp.Align(0x10) : Files[i].SizeComp; + MSIO.FileStream stream = new MSIO.FileStream(file, MSIO.FileMode.Open, + MSIO.FileAccess.ReadWrite, MSIO.FileShare.ReadWrite); + stream.Seek(Files[i].Offset, 0); + Files[i].Data = new byte[FileSize]; + + bool Encrypted = false; + if (ECB) + { + if ((FT && Files[i].ECB) || CBC) + { + using (CryptoStream cryptoStream = new CryptoStream(stream, + GetAes(true, null).CreateDecryptor(), CryptoStreamMode.Read)) + cryptoStream.Read(Files[i].Data, 0, FileSize); + Files[i].Data = SkipData(Files[i].Data, 0x10); + } + else + using (CryptoStream cryptoStream = new CryptoStream(stream, + GetAes(false, null).CreateDecryptor(), CryptoStreamMode.Read)) + cryptoStream.Read(Files[i].Data, 0, FileSize); + Encrypted = true; + } + + bool Compressed = false; + bool LocalGZip = (FT && Files[i].GZip) || GZip && Files[i].SizeUnc != 0; + if (LocalGZip) + { + GZipStream gZipStream; + if (Encrypted) + { + gZipStream = new GZipStream(new MSIO. + MemoryStream(Files[i].Data), CompressionMode.Decompress); + stream.Close(); + } + else gZipStream = new GZipStream(stream, CompressionMode.Decompress); + Files[i].Data = new byte[Files[i].SizeUnc]; + gZipStream.Read(Files[i].Data, 0, Files[i].SizeUnc); + + Compressed = true; + } + + if (!Encrypted && !Compressed) + { + Files[i].Data = new byte[Files[i].SizeUnc]; + stream.Read(Files[i].Data, 0, Files[i].SizeUnc); + stream.Close(); + } + + if (SaveToDisk) + { + File.WriteAllBytes(MSIO.Path.Combine(directory, Files[i].Name), Files[i].Data); + Files[i].Data = null; + } + + } + Console.Clear(); + } + + byte[] SkipData(byte[] Data, int Skip) + { + byte[] SkipData = new byte[Data.Length - Skip]; + for (int i = 0; i < Data.Length - Skip; i++) SkipData[i] = Data[i + Skip]; + return SkipData; + } + + void HeaderReader(int HeaderLenght, ref FARCFile[] Files, ref Stream reader) + { + if (Files == null) + { + int Count = 0; + long Position = reader.BaseStream.Position; + while (reader.BaseStream.Position < HeaderLenght) + { + reader.NullTerminated(); + reader.ReadInt32(); + if (Signature != Farc.FArc ) reader.ReadInt32(); + reader.ReadInt32(); + if (Signature == Farc.FARC && FT) reader.ReadInt32(); + Count++; + } + reader.Seek(Position, 0); + Files = new FARCFile[Count]; + } + + int LocalMode = 0; + for (int i = 0; i < Files.Length; i++) + { + Files[i].Name = reader.NullTerminatedUTF8(); + Files[i].Offset = reader.ReadInt32Endian(true); + if (Signature != Farc.FArc) Files[i].SizeComp = reader.ReadInt32Endian(true); + Files[i].SizeUnc = reader.ReadInt32Endian(true); + if (Signature == Farc.FARC && FT) + { + LocalMode = reader.ReadInt32Endian(true); + Files[i].GZip = (LocalMode & 2) == 2; + Files[i].ECB = (LocalMode & 4) == 4; + } + } + } + + public void Pack(string file) + { + Files = null; + FT = false; + string[] files = MSIO.Directory.GetFiles(file); + Files = new FARCFile[files.Length]; + + for (int i = 0; i < files.Length; i++) + { + Files[i] = new FARCFile { Name = files[i] }; + string ext = MSIO.Path.GetExtension(files[i]).ToLower(); + if (ext == ".a3da" || ext == ".mot" || ext == ".vag") + Signature = Farc.FArc; + } + files = null; + + Stream writer = File.OpenWriter(file + ".farc", true); + writer.WriteEndian((int)Signature, true); + + Stream HeaderWriter = File.OpenWriter(); + for (int i = 0; i < 3; i++) HeaderWriter.WriteByte(0x00); + if (Signature == Farc.FArc) HeaderWriter.WriteByte(0x20); + else if (Signature == Farc.FArC) HeaderWriter.WriteByte(0x10); + else if (Signature == Farc.FARC) + { + HeaderWriter.WriteByte(0x06); + for (int i = 0; i < 7; i++) HeaderWriter.WriteByte(0x00); + HeaderWriter.WriteByte(0x40); + for (int i = 0; i < 8; i++) HeaderWriter.WriteByte(0x00); + } + int HeaderPartLength = Signature == Farc.FArc ? 0x09 : 0x0D; + for (int i = 0; i < Files.Length; i++) + HeaderWriter.Length += MSIO.Path.GetFileName(Files[i].Name).Length + HeaderPartLength; + writer.WriteEndian(HeaderWriter.Length, true); + writer.Write(HeaderWriter.ToArray(true)); + HeaderWriter = null; + + int Align = writer.Position.Align(0x10) - writer.Position; + for (int i1 = 0; i1 < Align; i1++) + if (Signature == Farc.FArc) writer.WriteByte(0x00); + else writer.WriteByte(0x78); + + for (int i = 0; i < Files.Length; i++) + CompressStuff(i, ref Files, ref writer); + + if (Signature == Farc.FARC) writer.Seek(0x1C, 0); + else writer.Seek(0x0C, 0); + for (int i = 0; i < Files.Length; i++) + { + writer.Write(MSIO.Path.GetFileName(Files[i].Name) + "\0"); + writer.WriteEndian(Files[i].Offset, true); + if (Signature != Farc.FArc) + writer.WriteEndian(Files[i].SizeComp, true); + writer.WriteEndian(Files[i].SizeUnc, true); + } + writer.Close(); + } + + void CompressStuff(int i, ref FARCFile[] Files, ref Stream writer) + { + Files[i].Offset = writer.Position; + Files[i].Data = File.ReadAllBytes(Files[i].Name); + Files[i].SizeUnc = Files[i].Data.Length; + + if (Signature != Farc.FArc) + { + if (Signature != Farc.FArc) + { + MSIO.MemoryStream stream = new MSIO.MemoryStream(); + using (GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress)) + gZipStream.Write(Files[i].Data, 0, Files[i].Data.Length); + Files[i].Data = stream.ToArray(); + stream.Dispose(); + Files[i].SizeComp = Files[i].Data.Length; + } + else if (Signature == Farc.FARC) + { + int AlignData = Files[i].Data.Length.Align(0x40); + byte[] Data = new byte[AlignData]; + for (int i1 = 0; i1 < Files[i].Data.Length; i1++) + Data[i1] = Files[i].Data[i1]; + for (int i1 = Files[i].Data.Length; i1 < AlignData; i1++) + Data[i1] = 0x78; + + Files[i].Data = Encrypt(Data, false); + } + } + writer.Write(Files[i].Data); + Files[i].Data = null; + + if (Signature != Farc.FARC) + { + int Align = writer.Position.Align(0x20) - writer.Position; + for (int i1 = 0; i1 < Align; i1++) + if (Signature == Farc.FArc) writer.WriteByte(0x00); + else writer.WriteByte(0x78); + } + } + + byte[] Encrypt(byte[] Data, bool isFT) + { + MSIO.MemoryStream stream = new MSIO.MemoryStream(); + using (CryptoStream cryptoStream = new CryptoStream(stream, + GetAes(isFT, null).CreateEncryptor(),CryptoStreamMode.Write)) + cryptoStream.Write(Data, 0, Data.Length); + return stream.ToArray(); + } + + public enum Farc + { + FArc = 0x46417263, + FArC = 0x46417243, + FARC = 0x46415243, + } + + public struct FARCFile + { + public int Offset; + public int SizeComp; + public int SizeUnc; + public bool GZip; + public bool ECB; + public byte[] Data; + public string Name; + } + } +} diff --git a/KKdMainLib/IO/File.cs b/KKdMainLib/IO/File.cs new file mode 100644 index 0000000..7f167b2 --- /dev/null +++ b/KKdMainLib/IO/File.cs @@ -0,0 +1,50 @@ +using System; +using MSIO = System.IO; + +namespace KKdMainLib.IO +{ + public static class File + { + public static Stream OpenReader(byte[] Data) => new Stream(new MSIO.MemoryStream(Data), Data); + public static Stream OpenWriter( ) => new Stream(new MSIO.MemoryStream( )); + + public static Stream OpenReader(string file, bool ReadAllAtOnce) + { Stream IO = OpenReader(file); if (ReadAllAtOnce) return OpenReader(IO.ToArray(true)); return IO; } + public static Stream OpenReader(string file) + { Stream IO = new Stream(new MSIO.FileStream(file, MSIO.FileMode.Open, MSIO.FileAccess.ReadWrite, + MSIO.FileShare.ReadWrite)) { File = file }; return IO; } + public static Stream OpenWriter(string file, bool SetLength0) + { Stream IO = OpenWriter(file); IO.SetLength(0 ); return IO; } + public static Stream OpenWriter(string file, int SetLength) + { Stream IO = OpenWriter(file); IO.SetLength(SetLength); return IO; } + public static Stream OpenWriter(string file) + { Stream IO = new Stream(new MSIO.FileStream(file, + MSIO.FileMode.OpenOrCreate, MSIO.FileAccess.ReadWrite, MSIO.FileShare.ReadWrite)) { File = file }; + MSIO.File. SetCreationTimeUtc(file, DateTime.UtcNow); + MSIO.File. SetLastWriteTimeUtc(file, DateTime.UtcNow); + MSIO.File.SetLastAccessTimeUtc(file, DateTime.UtcNow); return IO; } + + public static byte[] ReadAllBytes(string file, int length, int offset) + { Stream IO = OpenReader(file); byte[] Data = IO.ReadBytes(length, offset); IO.Close(); return Data; } + + public static byte[] ReadAllBytes(string file) + { Stream IO = OpenReader(file); byte[] Data = IO.ReadBytes(IO.Length); IO.Close(); return Data; } + + public static string ReadAllText (string file) + { Stream IO = OpenReader(file); string Data = IO.ReadStringUTF8(IO.Length); IO.Close(); return Data; } + + public static string[] ReadAllLines(string file) + { Stream IO = OpenReader(file); string Data = IO.ReadStringUTF8(IO.Length); IO.Close(); + return Data.Replace("\r", "").Split('\n'); } + + public static void WriteAllBytes(string file, byte[] data) + { Stream IO = OpenWriter(file); IO.Write(data); IO.Close(); } + + public static void WriteAllText (string file, string data) + { Stream IO = OpenWriter(file); IO.Write(data); IO.Close(); } + + public static void WriteAllLines(string file, string[] data) + { Stream IO = OpenWriter(file); for (int i = 0; i < data.Length; i++) IO.Write(data[i] + "\r\n"); IO.Close(); } + + } +} diff --git a/KKdMainLib/IO/IOExtensions.cs b/KKdMainLib/IO/IOExtensions.cs new file mode 100644 index 0000000..40b4473 --- /dev/null +++ b/KKdMainLib/IO/IOExtensions.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace KKdMainLib.IO +{ + public static class IOExtensions + { + public static string NullTerminatedASCII(this Stream stream, byte End = 0) => stream.NullTerminated(End).ToASCII(); + public static string NullTerminatedUTF8 (this Stream stream, byte End = 0) => stream.NullTerminated(End).ToUTF8 (); + public static byte[] NullTerminated (this Stream stream, byte End = 0) + { + List s = new List(); + while (true && stream.LongPosition > 0 && stream.LongPosition < stream.LongLength) + { + byte a = stream.ReadByte(); + if (a == End) break; + else s.Add(a); + } + return s.ToArray(); + } + } +} diff --git a/KKdMainLib/IO/Stream.cs b/KKdMainLib/IO/Stream.cs new file mode 100644 index 0000000..6311724 --- /dev/null +++ b/KKdMainLib/IO/Stream.cs @@ -0,0 +1,399 @@ +using System; +using KKdMainLib.Types; +using MSIO = System.IO; + +namespace KKdMainLib.IO +{ + public unsafe class Stream : IDisposable + { + private MSIO.Stream stream; + private int i, i0, TempBitRead, TempBitWrite; + private ushort ValRead; + private byte BitRead, BitWrite, ValWrite; + private byte[] buf; + private byte[] data; + + private Main.Format _format = Main.Format.NULL; + + public Main.Format Format + { get => _format; + set { _format = value; + IsBE = _format == Main.Format.F2BE; + IsX = _format == Main.Format.X || _format == Main.Format.XHD; } } + + public bool IsBE = false; + public bool IsX = false; + + public int Offset { get => ( int)LongOffset; set => LongOffset = value; } + public uint UIntOffset { get => (uint)LongOffset; set => LongOffset = value; } + public long LongOffset; + + public int Length { get => ( int)stream. Length; set => stream.SetLength (value); } + public uint UIntLength { get => (uint)stream. Length; set => stream.SetLength (value); } + public long LongLength { get => stream. Length; set => stream.SetLength (value); } + public int Position { get => ( int)stream.Position; set => stream.Position = value ; } + public uint UIntPosition { get => (uint)stream.Position; set => stream.Position = value ; } + public long LongPosition { get => stream.Position; set => stream.Position = value ; } + + public bool CanRead => stream.CanRead; + public bool CanSeek => stream.CanSeek; + public bool CanTimeout => stream.CanTimeout; + public bool CanWrite => stream.CanWrite; + + public string File = null; + + public Stream(MSIO.Stream output = null, byte[] Data = null, bool isBE = false) + { + if (output == null) output = MSIO.Stream.Null; + BitRead = 8; + ValRead = ValRead = BitWrite = 0; + stream = output; + Format = Main.Format.NULL; + buf = new byte[16]; + IsBE = isBE; + data = Data; + } + + public void Close() => Dispose(); + + public void Flush() => stream.Flush(); + + public void SetLength(long length = 0) => stream.SetLength(length); + + public long Seek(long offset, SeekOrigin origin = 0) => + stream.Seek(offset, (MSIO.SeekOrigin)(int)origin); + + public long? Seek(long? offset, SeekOrigin origin) + { if (offset == null) return null; return stream.Seek((long)offset, (MSIO.SeekOrigin)(int)origin); } + + public void Dispose() + { CheckWrited(); Dispose(true); } + + private void Dispose(bool disposing) + { if (disposing && stream != MSIO.Stream.Null) stream.Flush(); stream.Dispose(); data = null; } + + public MSIO.Stream BaseStream + { get { stream.Flush(); return stream; } set { stream = value; } } + + public void Align(long Align) + { + long Al = Align - Position % Align; + if (Position % Align != 0) + stream.Seek(Position + Al, 0); + } + + public void Align(long Align, bool SetLength) + { + if (SetLength) stream.SetLength(Position); + long Al = Align - Position % Align; + if (Position % Align != 0) stream.Seek(Position + Al, 0); + if (SetLength) stream.SetLength(Position); + } + + public void Align(long Align, bool SetLength0, bool SetLength1) + { + if (SetLength0) stream.SetLength(Position); + long Al = Align - Position % Align; + if (Position % Align != 0) stream.Seek(Position + Al, 0); + if (SetLength1) stream.SetLength(Position); + } + + public bool ReadBoolean() => stream.ReadByte() == 1; + public sbyte ReadSByte() => ( sbyte)stream.ReadByte(); + public byte ReadByte() => ( byte)stream.ReadByte(); + public sbyte ReadInt8() => ( sbyte) IntFromArray(1); + public byte ReadUInt8() => ( byte)UIntFromArray(1); + public short ReadInt16() => ( short) IntFromArray(2); + public ushort ReadUInt16() => (ushort)UIntFromArray(2); + public int ReadInt24() => ( int) IntFromArray(3); + public int ReadInt32() => ( int) IntFromArray(4); + public uint ReadUInt32() => ( uint)UIntFromArray(4); + public long ReadInt64() => IntFromArray(8); + public ulong ReadUInt64() => UIntFromArray(8); + public Half ReadHalf() { ushort a = ReadUInt16(); return ( Half ) a; } + public float ReadSingle() { uint a = ReadUInt32(); return *( float*)&a; } + public double ReadDouble() { ulong a = ReadUInt64(); return *(double*)&a; } + + public short ReadInt16Endian() => ( short) IntFromArray(2, IsBE); + public ushort ReadUInt16Endian() => (ushort)UIntFromArray(2, IsBE); + public int ReadInt24Endian() => ( int) IntFromArray(3, IsBE); + public int ReadInt32Endian() => ( int) IntFromArray(4, IsBE); + public uint ReadUInt32Endian() => ( uint)UIntFromArray(4, IsBE); + public long ReadInt64Endian() => IntFromArray(8, IsBE); + public ulong ReadUInt64Endian() => UIntFromArray(8, IsBE); + public Half ReadHalfEndian() + { ushort a = ReadUInt16Endian(); return ( Half ) a; } + public float ReadSingleEndian() + { uint a = ReadUInt32Endian(); return *( float*)&a; } + public double ReadDoubleEndian() + { ulong a = ReadUInt64Endian(); return *(double*)&a; } + + public short ReadInt16Endian(bool IsBE) => ( short) IntFromArray(2, IsBE); + public ushort ReadUInt16Endian(bool IsBE) => (ushort)UIntFromArray(2, IsBE); + public int ReadInt24Endian(bool IsBE) => ( int) IntFromArray(3, IsBE); + public int ReadInt32Endian(bool IsBE) => ( int) IntFromArray(4, IsBE); + public uint ReadUInt32Endian(bool IsBE) => ( uint)UIntFromArray(4, IsBE); + public long ReadInt64Endian(bool IsBE) => IntFromArray(8, IsBE); + public ulong ReadUInt64Endian(bool IsBE) => UIntFromArray(8, IsBE); + public Half ReadHalfEndian(bool IsBE) + { ushort a = ReadUInt16Endian(IsBE); return ( Half ) a; } + public float ReadSingleEndian(bool IsBE) + { uint a = ReadUInt32Endian(IsBE); return *( float*)&a; } + public double ReadDoubleEndian(bool IsBE) + { ulong a = ReadUInt64Endian(IsBE); return *(double*)&a; } + + public void Write(byte[] Val) => stream.Write(Val, 0, Val. Length); + public void Write(byte[] Val, int Length) => stream.Write(Val, 0 , Length); + public void Write(byte[] Val, int Offset, int Length) => stream.Write(Val, Offset, Length); + public void Write(char[] val, bool UTF8 = true) + { if (UTF8) Write(val.ToUTF8()); else Write(val.ToASCII()); } + + public void WriteByte(byte val) => stream.WriteByte(val); + + public void Write( bool val) => stream.WriteByte((byte)(val ? 1 : 0)); + public void Write( sbyte val) => stream.WriteByte((byte) val); + public void Write( byte val) => stream.WriteByte( val); + public void Write( short val) => ToArray(2, val); + public void Write(ushort val) => ToArray(2, val); + public void Write( int val) => ToArray(4, val); + public void Write( uint val) => ToArray(4, val); + public void Write( long val) => ToArray(8, val); + public void Write( ulong val) => ToArray(8, val); + public void Write( Half val) => ToArray(2, (ushort) val); + public void Write( float val) => ToArray(4, *( uint*)&val); + public void Write(double val) => ToArray(8, *(ulong*)&val); + + public void Write( sbyte? val) => Write(val.GetValueOrDefault()); + public void Write( byte? val) => Write(val.GetValueOrDefault()); + public void Write( short? val) => Write(val.GetValueOrDefault()); + public void Write(ushort? val) => Write(val.GetValueOrDefault()); + public void Write( int? val) => Write(val.GetValueOrDefault()); + public void Write( uint? val) => Write(val.GetValueOrDefault()); + public void Write( long? val) => Write(val.GetValueOrDefault()); + public void Write( ulong? val) => Write(val.GetValueOrDefault()); + public void Write( float? val) => Write(val.GetValueOrDefault()); + public void Write(double? val) => Write(val.GetValueOrDefault()); + + public void Write( bool* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( sbyte* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( byte* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( short* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write(ushort* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( int* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( uint* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( long* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( ulong* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write( float* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + public void Write(double* val, int Length) + { for (i = 0; i < Length; i++) Write(val[i]); } + + public void WriteEndian( short* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian(ushort* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian( int* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian( uint* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian( long* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian( ulong* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian( float* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + public void WriteEndian(double* val, int Length) + { for (i = 0; i < Length; i++) WriteEndian(val[i]); } + + public void WriteEndian( short* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian(ushort* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian( int* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian( uint* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian( long* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian( ulong* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian( float* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + public void WriteEndian(double* val, int Length, bool IsBE) + { for (i = 0; i < Length; i++) WriteEndian(val[i], IsBE); } + + public void Write( char val, bool UTF8 = true) + { if (UTF8) Write(val.ToString().ToUTF8()); else Write(val.ToString().ToASCII()); } + public void Write(string val, bool UTF8 = true) + { if (UTF8) Write(val .ToUTF8()); else Write(val .ToASCII()); } + + public void Write(string Data, ref bool? val) => Write(Data, val.GetValueOrDefault() ); + public void Write(string Data, long? val) => Write(Data, val.GetValueOrDefault() ); + public void Write(string Data, ulong? val) => Write(Data, val.GetValueOrDefault() ); + public void Write(string Data, double? val) => Write(Data, val.ToString( )); + public void Write(string Data, double? val, byte r) => Write(Data, val.ToString(r )); + public void Write(string Data, ref bool val) => Write(Data, Main.ToString(val)); + public void Write(string Data, long val) => Write(Data, val.ToString( )); + public void Write(string Data, ulong val) => Write(Data, val.ToString( )); + public void Write(string Data, double val) => Write(Data, val.ToString( )); + public void Write(string Data, double val, byte r) => Write(Data, val.ToString(r )); + public void Write(string Data, string val) => Write((Data + val + "\n").ToUTF8()); + + public void WriteEndian( short val) => ToArray(2, Endian(val, 2, IsBE)); + public void WriteEndian(ushort val) => ToArray(2, Endian(val, 2, IsBE)); + public void WriteEndian( int val) => ToArray(4, Endian(val, 4, IsBE)); + public void WriteEndian( uint val) => ToArray(4, Endian(val, 4, IsBE)); + public void WriteEndian( long val) => ToArray(8, Endian(val, 8, IsBE)); + public void WriteEndian( ulong val) => ToArray(8, Endian(val, 8, IsBE)); + public void WriteEndian( float val) => ToArray(4, Endian(*( uint*)&val, 4, IsBE)); + public void WriteEndian(double val) => ToArray(8, Endian(*(ulong*)&val, 8, IsBE)); + + public void WriteEndian( short val, bool IsBE) => ToArray(2, Endian(val, 2, IsBE)); + public void WriteEndian(ushort val, bool IsBE) => ToArray(2, Endian(val, 2, IsBE)); + public void WriteEndian( int val, bool IsBE) => ToArray(4, Endian(val, 4, IsBE)); + public void WriteEndian( uint val, bool IsBE) => ToArray(4, Endian(val, 4, IsBE)); + public void WriteEndian( long val, bool IsBE) => ToArray(8, Endian(val, 8, IsBE)); + public void WriteEndian( ulong val, bool IsBE) => ToArray(8, Endian(val, 8, IsBE)); + public void WriteEndian( float val, bool IsBE) => ToArray(4, Endian(*( uint*)&val, 4, IsBE)); + public void WriteEndian(double val, bool IsBE) => ToArray(8, Endian(*(ulong*)&val, 8, IsBE)); + + public long Endian( long BE, byte Length, bool IsBE) + { if (IsBE) { for (byte i = 0; i < Length; i++) { buf[i] = (byte)BE; BE >>= 8; } BE = 0; + for (byte i = 0; i < Length; i++) { BE |= buf[i]; if (i < Length - 1) BE <<= 8; } } return BE; } + + public ulong Endian( ulong BE, byte Length, bool IsBE) + { if (IsBE) { for (byte i = 0; i < Length; i++) { buf[i] = (byte)BE; BE >>= 8; } BE = 0; + for (byte i = 0; i < Length; i++) { BE |= buf[i]; if (i < Length - 1) BE <<= 8; } } return BE; } + + /*public void WriteEndian( short val) => ToArrayEndian(2, val, IsBE); + public void WriteEndian(ushort val) => ToArrayEndian(2, val, IsBE); + public void WriteEndian( int val) => ToArrayEndian(4, val, IsBE); + public void WriteEndian( uint val) => ToArrayEndian(4, val, IsBE); + public void WriteEndian( long val) => ToArrayEndian(8, val, IsBE); + public void WriteEndian( ulong val) => ToArrayEndian(8, val, IsBE); + public void WriteEndian( float val) => ToArrayEndian(4, *( uint*)&val, IsBE); + public void WriteEndian(double val) => ToArrayEndian(8, *(ulong*)&val, IsBE); + + public void WriteEndian( short val, bool IsBE) => ToArrayEndian(2, val, IsBE); + public void WriteEndian(ushort val, bool IsBE) => ToArrayEndian(2, val, IsBE); + public void WriteEndian( int val, bool IsBE) => ToArrayEndian(4, val, IsBE); + public void WriteEndian( uint val, bool IsBE) => ToArrayEndian(4, val, IsBE); + public void WriteEndian( long val, bool IsBE) => ToArrayEndian(8, val, IsBE); + public void WriteEndian( ulong val, bool IsBE) => ToArrayEndian(8, val, IsBE); + public void WriteEndian( float val, bool IsBE) => ToArrayEndian(4, *( uint*)&val, IsBE); + public void WriteEndian(double val, bool IsBE) => ToArrayEndian(8, *(ulong*)&val, IsBE); + + private void ToArrayEndian(byte L, long val, bool IsBE = false) + { CheckWrited(); if (IsBE) for (i = L; i > 0; i--) { buf[i - 1] = (byte)val; val >>= 8; } + else for (i = 0; i < L; i++) { buf[i ] = (byte)val; val >>= 8; } Write(buf, L); } + + private void ToArrayEndian(byte L, ulong val, bool IsBE = false) + { CheckWrited(); if (IsBE) for (i = L; i > 0; i--) { buf[i - 1] = (byte)val; val >>= 8; } + else for (i = 0; i < L; i++) { buf[i ] = (byte)val; val >>= 8; } Write(buf, L); }*/ + + private void ToArray(byte L, long val) + { CheckWrited(); for (i = 0; i < L; i++) { buf[i] = (byte)val; val >>= 8; } Write(buf, L); } + + private void ToArray(byte L, ulong val) + { CheckWrited(); for (i = 0; i < L; i++) { buf[i] = (byte)val; val >>= 8; } Write(buf, L); } + + private long IntFromArray(byte L, bool IsBE = false) { Read(L); long val = 0; if (IsBE) + for (i = 0; i < L; i++) { val <<= 8; val |= buf[i ]; } else + for (i = L; i > 0; i--) { val <<= 8; val |= buf[i - 1]; } return val; } + + private ulong UIntFromArray(byte L, bool IsBE = false) { Read(L); ulong val = 0; if (IsBE) + for (i = 0; i < L; i++) { val <<= 8; val |= buf[i ]; } else + for (i = L; i > 0; i--) { val <<= 8; val |= buf[i - 1]; } return val; } + + private void Read(byte Length) => stream.Read(buf, 0, Length); + + public string ReadString(long Length, bool UTF8 = true) + { if (UTF8) return ReadStringUTF8 (Length); + else return ReadStringASCII(Length); } + + public string ReadStringUTF8 (long Length) => ReadBytes(Length).ToUTF8 (); + public string ReadStringASCII(long Length) => ReadBytes(Length).ToASCII(); + + + public string ReadString(long? Length, bool UTF8 = true) + { if (UTF8) return ReadStringUTF8 (Length); + else return ReadStringASCII(Length); } + + public string ReadStringUTF8 (long? Length) => ReadBytes(Length).ToUTF8 (); + public string ReadStringASCII(long? Length) => ReadBytes(Length).ToASCII(); + + public byte[] ReadBytes(long Length, int Offset = 0) + { byte[] Buf = new byte[Length]; if (Offset > 0) stream.Position = Offset; + stream.Read(Buf, 0, (int)Length); return Buf; } + + public void ReadBytes(long Length, byte[] Buf, long Offset = 0) + { if (Offset > 0) stream.Position = Offset; stream.Read(Buf, 0, (int)Length); } + + public byte[] ReadBytes(long? Length, int Offset = 0) + { if (Length == null) return new byte[0]; else return ReadBytes((long)Length, Offset); } + + public void ReadBytes(long Length, byte Bits, byte[] Buf, long Offset = 0) + { if (Offset > 0) stream.Seek(Offset, 0); + if (Bits > 0 && Bits < 8) for (i0 = 0; i0 < Length; i0++) Buf[i0] = ReadBits(Bits); } + + public byte ReadBits(byte Bits) + { + BitRead += Bits; + TempBitRead = 8 - BitRead; + if (TempBitRead < 0) + { + BitRead = (byte)-TempBitRead; + TempBitRead = 8 + TempBitRead; + ValRead = (ushort)((ValRead << 8) | (byte)stream.ReadByte()); + } + return (byte)((ValRead >> TempBitRead) & ((1 << Bits) - 1)); + } + + public byte ReadHalfByte() => ReadBits(4); + + public void Write(byte val, byte Bits) + { + BitWrite += Bits; + TempBitWrite = 8 - BitWrite; + if (TempBitWrite < 0) + { + BitWrite = (byte)-TempBitWrite; + TempBitWrite = 8 + TempBitWrite; + stream.WriteByte((byte)(ValWrite | (val >> BitWrite))); + ValWrite = 0; + } + ValWrite |= (byte)(val << TempBitWrite); + } + + public void CheckRead () { if (BitRead > 0) ValRead = 0; BitRead = 8; } + public void CheckWrited() { if (BitWrite > 0) { Write(ValWrite); ValWrite = BitWrite = 0; } } + + public byte[] ToArray(bool Close) + { byte[] Data = ToArray(); if (Close) this.Close(); return Data; } + + public byte[] ToArray() + { + long Offset = stream.Position; + LongPosition = 0; + byte[] Data = ReadBytes(stream.Length); + LongPosition = Offset; + return Data; + } + } + + public enum SeekOrigin + { + Begin = 0, + Current = 1, + End = 2, + } +} diff --git a/KKdMainLib/KKdMainLib.csproj b/KKdMainLib/KKdMainLib.csproj new file mode 100644 index 0000000..0ef046c --- /dev/null +++ b/KKdMainLib/KKdMainLib.csproj @@ -0,0 +1,68 @@ + + + + + Debug + AnyCPU + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789} + Library + KKdMainLib + KKdMainLib + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + true + + + AnyCPU + embedded + true + bin\ + TRACE + prompt + 4 + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/KKdMainLib/Main.cs b/KKdMainLib/Main.cs new file mode 100644 index 0000000..9b6debf --- /dev/null +++ b/KKdMainLib/Main.cs @@ -0,0 +1,360 @@ +using System; +using System.Windows.Forms; +using System.Globalization; +using System.Collections.Generic; + +namespace KKdMainLib +{ + public static unsafe class Main + { + public static void ConsoleDesign(string text, params string[] args) + { + text = string.Format(text, args); + string Text = "█ █"; + Text = Text.Remove(3) + text + Text.Remove(0, text.Length + 3); + Console.WriteLine(Text); + } + + public static void ConsoleDesign(bool Fill) + { + if (Fill) Console.WriteLine("████████████████████████████████████████████████████"); + else Console.WriteLine("█ █"); + } + + public const string TimeFormatHHmmssfff = "{0:d2}:{1:d2}:{2:d2}.{3:d3}"; + + public static void WriteTime(this TimeSpan time, bool WriteLine = false) + { + if (WriteLine) Console.WriteLine(TimeFormatHHmmssfff, + time.Hours, time.Minutes, time.Seconds, time.Milliseconds); + else Console.Write (TimeFormatHHmmssfff, + time.Hours, time.Minutes, time.Seconds, time.Milliseconds); + } + + public static void WriteTime(this TimeSpan time, string Text, bool WriteLine = true) + { + if (WriteLine) Console.WriteLine(TimeFormatHHmmssfff + " - " + Text, + time.Hours, time.Minutes, time.Seconds, time.Milliseconds); + else Console.Write (TimeFormatHHmmssfff + " - " + Text, + time.Hours, time.Minutes, time.Seconds, time.Milliseconds); + } + + private static string GetArgs(string name, bool And, params string[] ext) + { + string Out = ""; + if (And) Out = "|"; + Out += name + " files ("; + for (int i = 0; i < ext.Length; i++) + { Out += "*." + ext[i]; if (i + 1 < ext.Length) Out += ", "; } + Out += ")|"; + for (int i = 0; i < ext.Length; i++) + { Out += "*." + ext[i]; if (i + 1 < ext.Length) Out += ";"; } + + return Out; + } + + private static string GetArgs(string name, params string[] ext) + { + string Out = name + " files ("; + for (int i = 0; i < ext.Length; i++) + { Out += "*." + ext[i]; if (i + 1 < ext.Length) Out += ", "; } + Out += ")|"; + for (int i = 0; i < ext.Length; i++) + { Out += "*." + ext[i]; if (i + 1 < ext.Length) Out += ";"; } + + return Out; + } + + public static string Choose(int code, string filetype, out string[] FileNames) + { + string MsgPack = GetArgs("MessagePack", true, "mp"); + string BIN = GetArgs("BIN", true, "bin"); + string XML = GetArgs("XML", true, "xml"); + + FileNames = new string[0]; + if (code == 1) + { + Console.WriteLine("Choose file(s) to open:"); + OpenFileDialog ofd = new OpenFileDialog { InitialDirectory = + Application.StartupPath, Multiselect = true }; + + if (filetype == "a3da") ofd.Filter = GetArgs("A3DA", "a3da", "mp") + + GetArgs("A3DA", true, "a3da") + MsgPack; + else if (filetype == "bin" ) ofd.Filter = GetArgs("BIN" , "bin", "mp") + + BIN + MsgPack; + else if (filetype == "bon" ) ofd.Filter = GetArgs("BON" , "bon", "bin", "mp") + + GetArgs("BON", true, "bon") + BIN + MsgPack; + else if (filetype == "dex" ) ofd.Filter = GetArgs("DEX" , "dex", "bin", "mp") + + GetArgs("DEX", true, "dex") + BIN + MsgPack; + else if (filetype == "diva") ofd.Filter = GetArgs("DIVA", "diva", "wav") + + GetArgs("DIVA", true, "diva") + GetArgs("WAV", true, "wav"); + else if (filetype == "dsc" ) ofd.Filter = GetArgs("DSC" , "dsc", "mp") + + GetArgs("DSC", true, "dsc") + MsgPack; + else if (filetype == "farc") ofd.Filter = "FARC Archives (*.farc)|*.farc"; + else if (filetype == "image") ofd.Filter = GetArgs("Image", "dds", "png") + + GetArgs("DDS", true, "dds") + GetArgs("PNG", true, "png"); + else if (filetype == "kki") ofd.Filter = GetArgs("KKI", "kki"); + else if (filetype == "mot") ofd.Filter = GetArgs("MOT", "mot", "mp") + + GetArgs("MOT", true, "mot") + MsgPack; + else if (filetype == "ppd") ofd.Filter = GetArgs("PPD", "ppd", "pak", "mod") + + GetArgs("PPD", true, "ppd") + GetArgs("PAK", true, "pak") + GetArgs("MOD", true, "mod"); + else if (filetype == "str") ofd.Filter = GetArgs("STR", "str", "bin", "mp") + + GetArgs("STR", true, "str") + BIN + MsgPack; + else if (filetype == "vag") ofd.Filter = GetArgs("VAG", "vag", "wav") + + GetArgs("VAG", true, "vag") + GetArgs("WAV", true, "wav"); + else if (filetype == "xml") ofd.Filter = GetArgs("XML", "xml"); + else ofd.Filter = GetArgs("All;", false, "*"); + + if (ofd.ShowDialog() == DialogResult.OK) + FileNames = ofd.FileNames; + } + else if (code == 2) + { + FolderBrowserDialog fbd = new FolderBrowserDialog(); + Console.WriteLine("Choose folder:"); + fbd.SelectedPath = Application.StartupPath; + if (fbd.ShowDialog() == DialogResult.OK) + return fbd.SelectedPath.ToString(); + } + return ""; + } + + public static void ChooseSave(int code, string filetype, + out string InitialDirectory, out string[] FileNames) + { + InitialDirectory = ""; + FileNames = new string[0]; + Console.WriteLine("Choose file to save:"); + SaveFileDialog sfd = new SaveFileDialog { InitialDirectory = Application.StartupPath }; + switch (filetype) + { + case "kki": + sfd.Filter = "KKI file (*.kki)|*.kki"; + break; + } + if (sfd.ShowDialog() == DialogResult.OK) + { + InitialDirectory = sfd.InitialDirectory.ToString(); + FileNames = sfd.FileNames; + } + } + + public static string NullTerminated(this string Source, ref int i, byte End) + { + string s = ""; + while (true) + { + if (Source[i] == End) break; + else s += Source[i]; + i++; + } + return s; + } + + public static bool StartsWith(this Dictionary Dict, string args, char Split) => + Dict.StartsWith(args.Split(Split)); + + public static bool StartsWith(this Dictionary Dict, string args) => + Dict.StartsWith(args.Split('.')); + + public static bool StartsWith(this Dictionary Dict, string[] args) + { + Dictionary bufDict = new Dictionary(); + if (Dict == null) + Dict = new Dictionary(); + if (args.Length > 1) + { + string[] NewArgs = new string[args.Length - 1]; + for (int i = 0; i < args.Length - 1; i++) + NewArgs[i] = args[i + 1]; + if (!Dict.ContainsKey(args[0])) + return false; + bufDict = (Dictionary)Dict[args[0]]; + return StartsWith(bufDict, NewArgs); + } + return Dict.ContainsKey(args[0]); + } + + public static bool FindValue(this Dictionary Dict, + ref bool value, char Split, string args) + { if (Dict.FindValue(out string val, args.Split(Split))) + return bool.TryParse(val, out value); return false; } + + public static bool FindValue(this Dictionary Dict, + ref int value, char Split, string args) + { if (Dict.FindValue(out string val, args.Split(Split))) + return int.TryParse(val, out value); return false; } + + public static bool FindValue(this Dictionary Dict, + ref double value, char Split, string args) + { if (Dict.FindValue(out string val, args.Split(Split))) + return val.ToDouble(out value); return false; } + + public static bool FindValue(this Dictionary Dict, + ref string value, char Split, string args) + { if (Dict.FindValue(out string val, args.Split(Split))) + { value = val; return true; } return false; } + + public static bool FindValue(this Dictionary Dict, + out bool value, string args) + { if (Dict.FindValue(out string val, args.Split('.' ))) + return bool.TryParse(val, out value); value = false; return false; } + + public static bool FindValue(this Dictionary Dict, + out int value, string args) + { if (Dict.FindValue(out string val, args.Split('.' ))) + return int.TryParse(val, out value); value = 0; return false; } + + public static bool FindValue(this Dictionary Dict, + out double value, string args) + { if (Dict.FindValue(out string val, args.Split('.' ))) + return val.ToDouble(out value); value = 0; return false; } + + public static bool FindValue(this Dictionary Dict, + out int? value, string args) + { if (Dict.FindValue(out string val, args.Split('.' ))) + { bool Val = int.TryParse(val, out int _value); + value = _value; return Val; } value = null; return false; } + + public static bool FindValue(this Dictionary Dict, + out double? value, string args) + { if (Dict.FindValue(out string val, args.Split('.' ))) + return ToDouble(val, out value); value = null; return false; } + + public static bool FindValue(this Dictionary Dict, + out string value, string args) + { if (Dict.FindValue(out string val, args.Split('.' ))) + { value = val; return true; } value = null; return false; } + + public static bool FindValue(this Dictionary Dict, + out string value, string[] args) + { + value = ""; + if (Dict == null) return false; + else if (args.Length < 1) return false; + + if (!Dict.ContainsKey(args[0])) return false; + else if (args.Length > 1) + { + string[] NewArgs = new string[args.Length - 1]; + for (int i = 0; i < args.Length - 1; i++) NewArgs[i] = args[i + 1]; + return ((Dictionary)Dict[args[0]]).FindValue(out value, NewArgs); + } + else if (args.Length == 1) + { + if (Dict[args[0]].GetType() == Dict.GetType()) + return ((Dictionary)Dict[args[0]]).FindValue(out value, args); + else if (Dict[args[0]].GetType() != typeof(string)) return false; + } + + value = (string)Dict[args[0]]; + return true; + } + + public static void GetDictionary(this Dictionary Dict, + string args, string value, char Split = '.') => + Dict.GetDictionary(args.Split(Split), value); + + public static void GetDictionary(this Dictionary Dict, + string[] args, string value) + { + Dictionary bufDict = new Dictionary(); + if (Dict == null) Dict = new Dictionary(); + if (args.Length > 1) + { + string[] NewArgs = new string[args.Length - 1]; + for (int i = 0; i < args.Length - 1; i++) NewArgs[i] = args[i + 1]; + if (!Dict.ContainsKey(args[0])) Dict.Add(args[0], null); + if (Dict[args[0]] != null) + { + if (Dict[args[0]].GetType() == typeof(string)) + Dict[args[0]] = new Dictionary { { "", Dict[args[0]] } }; + } + else Dict[args[0]] = new Dictionary(); + bufDict = (Dictionary)Dict[args[0]]; + bufDict.GetDictionary(NewArgs, value); + Dict[args[0]] = bufDict; + } + else if (!Dict.ContainsKey(args[0])) Dict.Add(args[0], value); + } + + public static string ToTitleCase(this string s) + { return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s); } + + public static int[] SortWriter(this int Length) + { + int i = 0; + List A = new List(); + for (i = 0; i < Length; i++) A.Add(i.ToString()); + A.Sort(); + int[] B = new int[Length]; + for (i = 0; i < Length; i++) B[i] = int.Parse(A[i]); + return B; + } + + private static readonly string NumberDecimalSeparator = + NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; + + public static string ToString(this bool? d) => d.GetValueOrDefault().ToString(); + + public static string ToString(this bool d) => d.ToString().ToLower(); + + public static string ToString(this float? d, byte round) => d.GetValueOrDefault().ToString(round); + public static string ToString(this float? d) => d.GetValueOrDefault().ToString(); + + public static string ToString(this float d, byte round) => + Math.Round(d, round).ToString().ToLower().Replace(NumberDecimalSeparator, "."); + + public static string ToString(this float d) => + d .ToString().ToLower().Replace(NumberDecimalSeparator, "."); + + public static string ToString(this double? d, byte round) => d.GetValueOrDefault().ToString(round); + public static string ToString(this double? d) => d.GetValueOrDefault().ToString(); + + public static string ToString(this double d, byte round) => + Math.Round(d, round).ToString().ToLower().Replace(NumberDecimalSeparator, "."); + + public static string ToString(this double d) => + d .ToString().ToLower().Replace(NumberDecimalSeparator, "."); + + public static float ToSingle(this string s) => + float. Parse(s.Replace(".", NumberDecimalSeparator)); + + public static bool ToSingle(this string s, out float value) => + float.TryParse(s.Replace(".", NumberDecimalSeparator), out value); + + public static double ToDouble(this string s) => + double. Parse(s.Replace(".", NumberDecimalSeparator)); + + public static bool ToDouble(this string s, out double value) => + double.TryParse(s.Replace(".", NumberDecimalSeparator), out value); + + public static bool ToSingle(this string s, out float? value) + { bool Val = ToSingle(s, out float val); value = val; return Val; } + + public static bool ToDouble(this string s, out double? value) + { bool Val = ToDouble(s, out double val); value = val; return Val; } + + public enum Format : byte + { + NULL = 0, + DT = 1, + PDA = 2, + DT2 = 3, + DTe = 4, + F = 5, + FT = 6, + F2LE = 7, + F2BE = 8, + MGF = 9, + X = 10, + XHD = 11, + } + + public struct ThreadArgs + { + public int Thread; + public int ID; + } + } +} diff --git a/KKdMainLib/MathExtensions.cs b/KKdMainLib/MathExtensions.cs new file mode 100644 index 0000000..f6c471d --- /dev/null +++ b/KKdMainLib/MathExtensions.cs @@ -0,0 +1,196 @@ +using System; + +namespace KKdMainLib +{ + public static class MathExtensions + { + public static void FloorCeiling(ref double Value) + { if (Value % 1 >= 0.5) Value = (long)(Value + 0.5); + else Value = (long) Value; } + + public static long FloorCeiling(this double Value) + { if (Value % 1 >= 0.5) return (long)(Value + 0.5); + else return (long) Value; } + + public static int Align(this int value, int alignement, int divide = 1) => + ((value % alignement == 0) ? value : (value + alignement - value % alignement)) / divide; + + public static uint Align(this uint value, uint alignement, uint divide = 1) => + ((value % alignement == 0) ? value : (value + alignement - value % alignement)) / divide; + + public static long Align(this long value, long alignement, long divide = 1) => + ((value % alignement == 0) ? value : (value + alignement - value % alignement)) / divide; + + public static ulong Align(this ulong value, ulong alignement, ulong divide = 1) => + ((value % alignement == 0) ? value : (value + alignement - value % alignement)) / divide; + + public static byte[] buf = new byte[8]; + public static unsafe byte* bufPtr = buf.GetPtr(); + + public static unsafe long Endian(this long LE, byte Len, bool IsBE) + { if (IsBE) { for (byte i = 0; i < Len; i++) { bufPtr[i] = (byte)LE; LE >>= 8; } LE = 0; + for (byte i = 0; i < Len; i++) { LE |= bufPtr[i]; if (i < Len - 1) LE <<= 8; } } return LE; } + + public static unsafe ulong Endian(this ulong LE, byte Len, bool IsBE) + { if (IsBE) { for (byte i = 0; i < Len; i++) { bufPtr[i] = (byte)LE; LE >>= 8; } LE = 0; + for (byte i = 0; i < Len; i++) { LE |= bufPtr[i]; if (i < Len - 1) LE <<= 8; } } return LE; } + + public static sbyte CITSB(this int c) + { + if (c > 0x7F) c = 0x7F; + else if (c < -0x80) c = -0x80; + return (sbyte)c; + } + + public static byte CITB(this int c) + { + if (c > 0xFF) c = 0xFF; + else if (c < 0x00) c = 0x00; + return (byte)c; + } + + public static short CITS(this int c) + { + if (c > 0x7FFF) c = 0x7FFF; + else if (c < -0x8000) c = -0x8000; + return (short)c; + } + + public static ushort CITUS(this int c) + { + if (c > 0xFFFF) c = 0xFFFF; + else if (c < 0x0000) c = 0x0000; + return (ushort)c; + } + + public static sbyte CFTSB(this float c) + { + c = c.Round(); + if (c > 0x7F) c = 0x7F; + else if (c < -0x80) c = -0x80; + return (sbyte)c; + } + + public static byte CFTB(this float c) + { + c = c.Round(); + if (c > 0xFF) c = 0xFF; + else if (c < 0x00) c = 0x00; + return (byte)c; + } + + public static short CFTS(this float c) + { + c = c.Round(); + if (c > 0x7FFF) c = 0x7FFF; + else if (c < -0x8000) c = -0x8000; + return (short)c; + } + + public static ushort CFTUS(this float c) + { + c = c.Round(); + if (c > 0xFFFF) c = 0xFFFF; + else if (c < 0x0000) c = 0x0000; + return (ushort)c; + } + + public static int CFTI(this float c) + { + c = c.Round(); + if (c > 0x7FFFFFFF) c = 0x7FFFFFFF; + else if (c < -0x80000000) c = -0x80000000; + return (int)c; + } + + public static uint CFTUI(this float c) + { + c = c.Round(); + if (c > 0xFFFFFFFF) c = 0xFFFFFFFF; + else if (c < 0x00000000) c = 0x00000000; + return (uint)c; + } + + public static float Round(this float c) => (float)Math.Round(c); + + public static sbyte CFTSB(this double c) + { + c = Math.Round(c); + if (c > 0x7F) c = 0x7F; + else if (c < -0x80) c = -0x80; + return (sbyte)c; + } + + public static byte CFTB(this double c) + { + c = Math.Round(c); + if (c > 0xFF) c = 0xFF; + else if (c < 0x00) c = 0x00; + return (byte)c; + } + + public static short CFTS(this double c) + { + c = Math.Round(c); + if (c > 0x7FFF) c = 0x7FFF; + else if (c < -0x8000) c = -0x8000; + return (short)c; + } + + public static ushort CFTUS(this double c) + { + c = Math.Round(c); + if (c > 0xFFFF) c = 0xFFFF; + else if (c < 0x0000) c = 0x0000; + return (ushort)c; + } + + public static int CFTI(this double c) + { + c = Math.Round(c); + if (c > 0x7FFFFFFF) c = 0x7FFFFFFF; + else if (c < -0x80000000) c = -0x80000000; + return (int)c; + } + + public static uint CFTUI(this double c) + { + c = Math.Round(c); + if (c > 0xFFFFFFFF) c = 0xFFFFFFFF; + else if (c < 0x00000000) c = 0x00000000; + return (uint)c; + } + + public static double Round(this double c) => Math.Round(c); + + public static unsafe sbyte* GetPtr(this sbyte[] array) + { sbyte* Ptr; fixed ( sbyte* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe byte* GetPtr(this byte[] array) + { byte* Ptr; fixed ( byte* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe short* GetPtr(this short[] array) + { short* Ptr; fixed ( short* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe ushort* GetPtr(this ushort[] array) + { ushort* Ptr; fixed (ushort* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe int* GetPtr(this int[] array) + { int* Ptr; fixed ( int* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe uint* GetPtr(this uint[] array) + { uint* Ptr; fixed ( uint* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe long* GetPtr(this long[] array) + { long* Ptr; fixed ( long* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe ulong* GetPtr(this ulong[] array) + { ulong* Ptr; fixed ( ulong* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe float* GetPtr(this float[] array) + { float* Ptr; fixed ( float* tempPtr = array) Ptr = tempPtr; return Ptr; } + + public static unsafe double* GetPtr(this double[] array) + { double* Ptr; fixed (double* tempPtr = array) Ptr = tempPtr; return Ptr; } + } +} diff --git a/KKdMainLib/MessagePack/IO.cs b/KKdMainLib/MessagePack/IO.cs new file mode 100644 index 0000000..8e4a0ec --- /dev/null +++ b/KKdMainLib/MessagePack/IO.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using KKdMainLib.IO; + +namespace KKdMainLib.MessagePack +{ + public class IO + { + public Stream _IO; + + public IO( ) => _IO = File.OpenWriter(); + public IO(Stream IO) => _IO = IO; + + public void Close() => _IO.Close(); + + public MsgPack Read(bool NotArray = true) + { + MsgPack MsgPack = new MsgPack(); + byte Unk = _IO.ReadByte(); + MsgPack.Type = (MsgPack.Types)Unk; + if (NotArray) + { + MsgPack.Name = ReadString(MsgPack.Type); + if (MsgPack.Name != null) { Unk = _IO.ReadByte(); MsgPack.Type = (MsgPack.Types)Unk; } + } + + bool FixArr = MsgPack.Type >= MsgPack.Types.FixArr && MsgPack.Type <= MsgPack.Types.FixArrMax; + bool FixMap = MsgPack.Type >= MsgPack.Types.FixMap && MsgPack.Type <= MsgPack.Types.FixMapMax; + bool FixStr = MsgPack.Type >= MsgPack.Types.FixStr && MsgPack.Type <= MsgPack.Types.FixStrMax; + bool PosInt = MsgPack.Type >= MsgPack.Types.PosInt && MsgPack.Type <= MsgPack.Types.PosIntMax; + bool NegInt = MsgPack.Type >= MsgPack.Types.NegInt && MsgPack.Type <= MsgPack.Types.NegIntMax; + if (FixArr || FixMap || FixStr || PosInt || NegInt) + { + if (FixArr || FixMap) + { + MsgPack.Type = FixMap ? MsgPack.Types.FixMap : MsgPack.Types.FixArr; + if (FixMap) + { + MsgPack.Object = new List(); + for (int i = 0; i < Unk - (byte)MsgPack.Type; i++) + MsgPack.Add(Read()); + } + else + { + MsgPack.Object = new object[Unk - (byte)MsgPack.Type]; + for (int i = 0; i < Unk - (byte)MsgPack.Type; i++) + MsgPack[i] = Read(false); + } + } + else if (FixStr) + { MsgPack.Object = ReadString(MsgPack.Type); MsgPack.Type = MsgPack.Types.FixStr; } + else if (PosInt) + { MsgPack.Object = (ulong) Unk; MsgPack.Type = MsgPack.Types.PosInt; } + else if (NegInt) + { MsgPack.Object = ( long)(sbyte)Unk; MsgPack.Type = MsgPack.Types.NegInt; } + return MsgPack; + } + + bool Boolean = false; + while (!Boolean) + { + Boolean = ReadNil (ref MsgPack); + Boolean = ReadArr (ref MsgPack); + Boolean = ReadMap (ref MsgPack); + Boolean = ReadExt (ref MsgPack); + Boolean = ReadString (ref MsgPack); + Boolean = ReadBoolean(ref MsgPack); + Boolean = ReadBytes (ref MsgPack); + Boolean = ReadInt (ref MsgPack); + Boolean = ReadUInt (ref MsgPack); + Boolean = ReadFloat (ref MsgPack); + break; + } + return MsgPack; + } + + private bool ReadInt(ref MsgPack MsgPack) + { + if (MsgPack.Type == MsgPack.Types.Int8 ) MsgPack.Object = (long)_IO.ReadSByte(); + else if (MsgPack.Type == MsgPack.Types.Int16) MsgPack.Object = (long)_IO.ReadInt16Endian(true); + else if (MsgPack.Type == MsgPack.Types.Int32) MsgPack.Object = (long)_IO.ReadInt32Endian(true); + else if (MsgPack.Type == MsgPack.Types.Int64) MsgPack.Object = (long)_IO.ReadInt64Endian(true); + else return false; + return true; + } + + private bool ReadUInt(ref MsgPack MsgPack) + { + if (MsgPack.Type == MsgPack.Types.UInt8 ) MsgPack.Object = (ulong)_IO.ReadByte(); + else if (MsgPack.Type == MsgPack.Types.UInt16) MsgPack.Object = (ulong)_IO.ReadUInt16Endian(true); + else if (MsgPack.Type == MsgPack.Types.UInt32) MsgPack.Object = (ulong)_IO.ReadUInt32Endian(true); + else if (MsgPack.Type == MsgPack.Types.UInt64) MsgPack.Object = (ulong)_IO.ReadUInt64Endian(true); + else return false; + return true; + } + + private bool ReadFloat(ref MsgPack MsgPack) + { + if (MsgPack.Type == MsgPack.Types.Float32) MsgPack.Object = _IO.ReadSingleEndian(true); + else if (MsgPack.Type == MsgPack.Types.Float64) MsgPack.Object = _IO.ReadDoubleEndian(true); + else return false; + return true; + } + + private bool ReadBoolean(ref MsgPack MsgPack) + { + if (MsgPack.Type == MsgPack.Types.False) MsgPack.Object = false; + else if (MsgPack.Type == MsgPack.Types.True ) MsgPack.Object = true ; + else return false; + return true; + } + + private bool ReadBytes(ref MsgPack MsgPack) + { + int Length = 0; + if (MsgPack.Type == MsgPack.Types.Bin8 ) Length = _IO.ReadByte(); + else if (MsgPack.Type == MsgPack.Types.Bin16) Length = _IO.ReadInt16Endian(true); + else if (MsgPack.Type == MsgPack.Types.Bin32) Length = _IO.ReadInt32Endian(true); + else return false; + MsgPack.Object = _IO.ReadBytes(Length); + return true; + } + + private bool ReadString(ref MsgPack MsgPack) + { + string val = ReadString(MsgPack.Type); + if (val != null) MsgPack.Object = val; + else return false; + return true; + } + + private string ReadString(MsgPack.Types Val) + { + if (Val >= MsgPack.Types.FixStr && Val <= MsgPack.Types.FixStrMax) + return _IO.ReadString(Val - MsgPack.Types.FixStr); + else if (Val >= MsgPack.Types.Str8 && Val <= MsgPack.Types.Str32) + { + Enum.TryParse(Val.ToString(), out MsgPack.Types Type); + int Length = 0; + if (Type == MsgPack.Types.Str8 ) Length = _IO.ReadByte(); + else if (Type == MsgPack.Types.Str16) Length = _IO.ReadInt16Endian(true); + else Length = _IO.ReadInt32Endian(true); + return _IO.ReadString(Length); + } + return null; + } + + private bool ReadNil(ref MsgPack MsgPack) + { + if (MsgPack.Type == MsgPack.Types.Nil) + MsgPack.Object = null; + else return false; + return true; + } + + private bool ReadArr(ref MsgPack MsgPack) + { + int Length = 0; + if (MsgPack.Type == MsgPack.Types.Arr16) Length = _IO.ReadInt16Endian(true); + else if (MsgPack.Type == MsgPack.Types.Arr32) Length = _IO.ReadInt32Endian(true); + else return false; + MsgPack.Object = new object[Length]; + for (int i = 0; i < Length; i++) MsgPack[i] = Read(false); + return true; + } + + private bool ReadMap(ref MsgPack MsgPack) + { + int Length = 0; + if (MsgPack.Type == MsgPack.Types.Map16) Length = _IO.ReadInt16Endian(true); + else if (MsgPack.Type == MsgPack.Types.Map32) Length = _IO.ReadInt32Endian(true); + else return false; + MsgPack.Object = new List(); + for (int i = 0; i < Length; i++) MsgPack.Add(Read()); + return true; + } + + private bool ReadExt(ref MsgPack MsgPack) + { + int Length = 0; + if (MsgPack.Type == MsgPack.Types.FixExt1 ) Length = 1 ; + else if (MsgPack.Type == MsgPack.Types.FixExt2 ) Length = 2 ; + else if (MsgPack.Type == MsgPack.Types.FixExt4 ) Length = 4 ; + else if (MsgPack.Type == MsgPack.Types.FixExt8 ) Length = 8 ; + else if (MsgPack.Type == MsgPack.Types.FixExt16) Length = 16; + else if (MsgPack.Type == MsgPack.Types. Ext8 ) Length = _IO.ReadByte(); + else if (MsgPack.Type == MsgPack.Types. Ext16) Length = _IO.ReadInt16Endian(true); + else if (MsgPack.Type == MsgPack.Types. Ext32) Length = _IO.ReadInt32Endian(true); + else return false; + MsgPack.Object = new MsgPack.Ext { Type = _IO.ReadSByte(), Data = _IO.ReadBytes(Length) }; + return true; + } + + public IO Write(MsgPack MsgPack, bool Close = false) + { Write(MsgPack); if (Close) this.Close(); return this; } + + public IO Write(MsgPack MsgPack) + { + if (MsgPack.Name != null) Write(MsgPack.Name); + if (MsgPack.Object == null) { WriteNil(); return this; } + + if (MsgPack.Object.GetType() == typeof(List)) + { + List Obj = (List)MsgPack.Object; + WriteMap(Obj.Count); + foreach (object obj in Obj) Write(obj); + } + else if (MsgPack.Object.GetType() == typeof(object[])) + { + object[] Obj = (object[])MsgPack.Object; + WriteArr(Obj.Length); + foreach (object obj in Obj) Write(obj); + } + else Write(MsgPack.Object); + + return this; + } + + private void Write(object obj) + { + if (obj == null ) WriteNil (); + else if (obj.GetType() == typeof(MsgPack)) Write((MsgPack)obj); + else + { + Type type = obj.GetType(); + if (type == typeof(byte[])) Write((byte[])obj); + else if (type == typeof( bool)) Write(( bool)obj); + else if (type == typeof( sbyte)) Write(( sbyte)obj); + else if (type == typeof( byte)) Write(( byte)obj); + else if (type == typeof( short)) Write(( short)obj); + else if (type == typeof(ushort)) Write((ushort)obj); + else if (type == typeof( int)) Write(( int)obj); + else if (type == typeof( uint)) Write(( uint)obj); + else if (type == typeof( long)) Write(( long)obj); + else if (type == typeof( ulong)) Write(( ulong)obj); + else if (type == typeof( float)) Write(( float)obj); + else if (type == typeof(double)) Write((double)obj); + else if (type == typeof(string)) Write((string)obj); + else if (type == typeof(MsgPack.Ext)) Write((MsgPack.Ext)obj); + } + } + + private void Write( sbyte val) { if (val < -0x20) _IO.Write((byte)0xD0); _IO.Write(val); } + private void Write( byte val) { if (val >= 0x80) _IO.Write((byte)0xCC); _IO.Write(val); } + private void Write( short val) { if (( sbyte)val == val) Write(( sbyte)val); + else if (( byte)val == val) Write(( byte)val); + else { _IO.Write((byte)0xD1); _IO.WriteEndian(val, true); } } + private void Write(ushort val) { if (( byte)val == val) Write(( byte)val); + else { _IO.Write((byte)0xCD); _IO.WriteEndian(val, true); } } + private void Write( int val) { if (( short)val == val) Write(( short)val); + else if ((ushort)val == val) Write((ushort)val); + else { _IO.Write((byte)0xD2); _IO.WriteEndian(val, true); } } + private void Write( uint val) { if ((ushort)val == val) Write((ushort)val); + else { _IO.Write((byte)0xCE); _IO.WriteEndian(val, true); } } + private void Write( long val) { if (( int)val == val) Write(( int)val); + else if (( uint)val == val) Write(( uint)val); + else { _IO.Write((byte)0xD3); _IO.WriteEndian(val, true); } } + private void Write( ulong val) { if (( uint)val == val) Write(( uint)val); + else { _IO.Write((byte)0xCF); _IO.WriteEndian(val, true); } } + private void Write( float val) { if (( long)val == val) Write(( long)val); + else { _IO.Write((byte)0xCA); _IO.WriteEndian(val, true); } } + private void Write(double val) { if (( long)val == val) Write(( long)val); + else if (( float)val == val) Write(( float)val); + else { _IO.Write((byte)0xCB); _IO.WriteEndian(val, true); } } + + private void Write( bool val) + { _IO.Write((byte)(val ? 0xC3 : 0xC2)); } + + private void Write(byte[] val) + { + if (val == null) { WriteNil(); return; } + + if (val.Length < 0x100) + { _IO.Write((byte)0xC4); _IO.Write (( byte)val.Length ); } + else if (val.Length < 0x10000) + { _IO.Write((byte)0xC5); _IO.WriteEndian((ushort)val.Length, true); } + else + { _IO.Write((byte)0xC6); _IO.WriteEndian( val.Length, true); } + _IO.Write(val); + } + + private void Write(string val) + { + if (val == null) { WriteNil(); return; } + + byte[] array = Text.ToUTF8(val); + if (array.Length < 0x20) + _IO.Write((byte)(0xA0 | (array.Length & 0x1F))); + else if (array.Length < 0x100) + { _IO.Write((byte) 0xD9); _IO.Write (( byte)array.Length); } + else if (array.Length < 0x10000) + { _IO.Write((byte )0xDA); _IO.WriteEndian((ushort)array.Length, true); } + else + { _IO.Write((byte) 0xDB); _IO.WriteEndian( array.Length, true); } + _IO.Write(array); + } + + private void WriteNil() => _IO.Write((byte)0xC0); + + private void WriteArr(int val) + { + if (val == 0) { WriteNil(); return; } + else if (val < 0x10) _IO.Write((byte)(0x90 | (val & 0x0F))); + else if (val < 0x10000) { _IO.Write((byte) 0xDC); _IO.WriteEndian((ushort)val, true); } + else { _IO.Write((byte) 0xDD); _IO.WriteEndian( val, true); } + } + + private void WriteMap(int val) + { + if (val == 0) { WriteNil(); return; } + else if (val < 0x10) _IO.Write((byte)(0x80 | (val & 0x0F))); + else if (val < 0x10000) { _IO.Write((byte) 0xDE); _IO.WriteEndian((ushort)val, true); } + else { _IO.Write((byte) 0xDF); _IO.WriteEndian( val, true); } + } + + private void WriteExt(MsgPack.Ext val) + { + if (val.Data == null) { WriteNil(); return; } + + if (val.Data.Length < 1 ) { WriteNil(); return; } + else if (val.Data.Length == 1 ) _IO.Write((byte)0xD4); + else if (val.Data.Length == 2 ) _IO.Write((byte)0xD5); + else if (val.Data.Length == 4 ) _IO.Write((byte)0xD6); + else if (val.Data.Length == 8 ) _IO.Write((byte)0xD7); + else if (val.Data.Length == 16) _IO.Write((byte)0xD8); + else + { + if (val.Data.Length < 0x100) + { _IO.Write((byte)0xC7); _IO.Write (( byte)val.Data.Length); } + else if (val.Data.Length < 0x10000) + { _IO.Write((byte)0xC8); _IO.WriteEndian((ushort)val.Data.Length, true); } + else + { _IO.Write((byte)0xC9); _IO.WriteEndian( val.Data.Length, true); } + } + _IO.Write(val.Type); + _IO.Write(val.Data); + } + } +} diff --git a/KKdMainLib/MessagePack/MsgPack.cs b/KKdMainLib/MessagePack/MsgPack.cs new file mode 100644 index 0000000..ce0e26f --- /dev/null +++ b/KKdMainLib/MessagePack/MsgPack.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; + +namespace KKdMainLib.MessagePack +{ + public class MsgPack + { + public Types Type; + public string Name; + public object Object; + + public MsgPack( Types Type = Types.Map32) => NewMsgPack(null, Type); + public MsgPack(string Name, Types Type = Types.Map32) => NewMsgPack(Name, Type); + public MsgPack( long Count) => NewMsgPack(null, Count); + public MsgPack(string Name, long Count) => NewMsgPack(Name, Count); + public MsgPack(string Name, Types Type, object Object) { this.Name = Name; this.Type = Type; this.Object = Object; } + + public static MsgPack Null => null; + + public object this[int index] + { get { return ((object[])Object)[index]; } + set { object[] Data = (object[])Object; Data[index] = value; Object = Data; } } + + public MsgPack(List Object, string Name, Types Type) + { this.Object = Object; this.Name = Name; this.Type = Type; } + + private void NewMsgPack(string Name, Types Type) + { Object = new List(); this.Name = Name; this.Type = Type; } + + private void NewMsgPack(string Name, long Count) + { if (Count > 0) Object = new object[Count]; else Object = null; this.Name = Name; Type = Types.Arr32; } + + + public MsgPack Add(object obj) + { if (obj != null) if (typeof(List) == Object.GetType()) + { List Obj = (List)Object; Obj.Add(obj); Object = Obj; } return this; } + + public MsgPack Add( sbyte? val) => Add(null, val); + public MsgPack Add( byte? val) => Add(null, val); + public MsgPack Add( short? val) => Add(null, val); + public MsgPack Add(ushort? val) => Add(null, val); + public MsgPack Add( int? val) => Add(null, val); + public MsgPack Add( uint? val) => Add(null, val); + public MsgPack Add( long? val) => Add(null, val); + public MsgPack Add( ulong? val) => Add(null, val); + public MsgPack Add( float? val) => Add(null, val); + public MsgPack Add(double? val) => Add(null, val); + + public MsgPack Add(byte[] val) => Add(null, val); + public MsgPack Add(string val) => Add(null, val); + public MsgPack Add( bool val) => Add(null, val); + public MsgPack Add( sbyte val) => Add(null, val); + public MsgPack Add( byte val) => Add(null, val); + public MsgPack Add( short val) => Add(null, val); + public MsgPack Add(ushort val) => Add(null, val); + public MsgPack Add( int val) => Add(null, val); + public MsgPack Add( uint val) => Add(null, val); + public MsgPack Add( long val) => Add(null, val); + public MsgPack Add( ulong val) => Add(null, val); + public MsgPack Add( float val) => Add(null, val); + public MsgPack Add(double val) => Add(null, val); + + public MsgPack Add(string Val, sbyte? val) { if (val == null) Add(Null); else Add(Val, ( sbyte)val); return this; } + public MsgPack Add(string Val, byte? val) { if (val == null) Add(Null); else Add(Val, ( byte)val); return this; } + public MsgPack Add(string Val, short? val) { if (val == null) Add(Null); else Add(Val, ( short)val); return this; } + public MsgPack Add(string Val, ushort? val) { if (val == null) Add(Null); else Add(Val, (ushort)val); return this; } + public MsgPack Add(string Val, int? val) { if (val == null) Add(Null); else Add(Val, ( int)val); return this; } + public MsgPack Add(string Val, uint? val) { if (val == null) Add(Null); else Add(Val, ( uint)val); return this; } + public MsgPack Add(string Val, long? val) { if (val == null) Add(Null); else Add(Val, ( long)val); return this; } + public MsgPack Add(string Val, ulong? val) { if (val == null) Add(Null); else Add(Val, ( ulong)val); return this; } + public MsgPack Add(string Val, float? val) { if (val == null) Add(Null); else Add(Val, ( float)val); return this; } + public MsgPack Add(string Val, double? val) { if (val == null) Add(Null); else Add(Val, (double)val); return this; } + + public MsgPack Add(string Val, byte[] val) + { if (val == null) Add(Null); else + Add(new MsgPack(Val, Types. Bin32, val)); return this; } + public MsgPack Add(string Val, string val) + { if (val == null) Add(Null); else + Add(new MsgPack(Val, Types. Str32, val)); return this; } + public MsgPack Add(string Val, bool val) + { Add(new MsgPack(Val, val ? + Types.True : Types. False, val)); return this; } + public MsgPack Add(string Val, sbyte val) + { Add(new MsgPack(Val, Types. Int8, val)); return this; } + public MsgPack Add(string Val, byte val) + { Add(new MsgPack(Val, Types. UInt8, val)); return this; } + public MsgPack Add(string Val, short val) + { Add(new MsgPack(Val, Types. Int16, val)); return this; } + public MsgPack Add(string Val, ushort val) + { Add(new MsgPack(Val, Types. UInt16, val)); return this; } + public MsgPack Add(string Val, int val) + { Add(new MsgPack(Val, Types. Int32, val)); return this; } + public MsgPack Add(string Val, uint val) + { Add(new MsgPack(Val, Types. UInt32, val)); return this; } + public MsgPack Add(string Val, long val) + { Add(new MsgPack(Val, Types. Int64, val)); return this; } + public MsgPack Add(string Val, ulong val) + { Add(new MsgPack(Val, Types. UInt64, val)); return this; } + public MsgPack Add(string Val, float val) + { Add(new MsgPack(Val, Types.Float32, val)); return this; } + public MsgPack Add(string Val, double val) + { Add(new MsgPack(Val, Types.Float64, val)); return this; } + + public bool ReadBoolean(string Name) => ReadNBoolean(Name).GetValueOrDefault(); + public sbyte ReadInt8(string Name) => ReadNInt8(Name).GetValueOrDefault(); + public byte ReadUInt8(string Name) => ReadNUInt8(Name).GetValueOrDefault(); + public short ReadInt16(string Name) => ReadNInt16(Name).GetValueOrDefault(); + public ushort ReadUInt16(string Name) => ReadNUInt16(Name).GetValueOrDefault(); + public int ReadInt32(string Name) => ReadNInt32(Name).GetValueOrDefault(); + public uint ReadUInt32(string Name) => ReadNUInt32(Name).GetValueOrDefault(); + public long ReadInt64(string Name) => ReadNInt64(Name).GetValueOrDefault(); + public ulong ReadUInt64(string Name) => ReadNUInt64(Name).GetValueOrDefault(); + public float ReadSingle(string Name) => ReadNSingle(Name).GetValueOrDefault(); + public double ReadDouble(string Name) => ReadNDouble(Name).GetValueOrDefault(); + + public bool? ReadNBoolean(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack.ReadNBoolean(); return null; } + public sbyte? ReadNInt8(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNInt8(); return null; } + public byte? ReadNUInt8(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNUInt8(); return null; } + public short? ReadNInt16(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNInt16(); return null; } + public ushort? ReadNUInt16(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNUInt16(); return null; } + public int? ReadNInt32(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNInt32(); return null; } + public uint? ReadNUInt32(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNUInt32(); return null; } + public long? ReadNInt64(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNInt64(); return null; } + public ulong? ReadNUInt64(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNUInt64(); return null; } + public float? ReadNSingle(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNSingle(); return null; } + public double? ReadNDouble(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadNDouble(); return null; } + public string ReadString(string Name) + { if (Element(Name, out MsgPack MsgPack)) return MsgPack. ReadString(); return null; } + + public bool ReadBoolean() => ReadNBoolean().GetValueOrDefault(); + public sbyte ReadInt8() => ReadNInt8().GetValueOrDefault(); + public byte ReadUInt8() => ReadNUInt8().GetValueOrDefault(); + public short ReadInt16() => ReadNInt16().GetValueOrDefault(); + public ushort ReadUInt16() => ReadNUInt16().GetValueOrDefault(); + public int ReadInt32() => ReadNInt32().GetValueOrDefault(); + public uint ReadUInt32() => ReadNUInt32().GetValueOrDefault(); + public long ReadInt64() => ReadNInt64().GetValueOrDefault(); + public ulong ReadUInt64() => ReadNUInt64().GetValueOrDefault(); + public float ReadSingle() => ReadNSingle().GetValueOrDefault(); + public double ReadDouble() => ReadNDouble().GetValueOrDefault(); + + public bool? ReadNBoolean() + { if (Object == null) return null; + if (Object.GetType() == typeof( bool)) return ( bool) Object; return null; ; } + public sbyte? ReadNInt8() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return ( sbyte)( long)Object; + else if (Object.GetType() == typeof( ulong)) return ( sbyte)(ulong)Object; return null; } + public byte? ReadNUInt8() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return ( byte)( long)Object; + else if (Object.GetType() == typeof( ulong)) return ( byte)(ulong)Object; return null; } + public short? ReadNInt16() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return ( short)( long)Object; + else if (Object.GetType() == typeof( ulong)) return ( short)(ulong)Object; return null; } + public ushort? ReadNUInt16() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return (ushort)( long)Object; + else if (Object.GetType() == typeof( ulong)) return (ushort)(ulong)Object; return null; } + public int? ReadNInt32() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return ( int)( long)Object; + else if (Object.GetType() == typeof( ulong)) return ( int)(ulong)Object; return null; } + public uint? ReadNUInt32() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return ( uint)( long)Object; + else if (Object.GetType() == typeof( ulong)) return ( uint)(ulong)Object; return null; } + public long? ReadNInt64() + { if (Object == null) return null; + if (Object.GetType() == typeof( long)) return ( long) Object; + else if (Object.GetType() == typeof( ulong)) return ( long)(ulong)Object; return null; } + public ulong? ReadNUInt64() + { if (Object == null) return null; + if (Object.GetType() == typeof( ulong)) return ( ulong) Object; + else if (Object.GetType() == typeof( long)) return ( ulong)( long)Object; return null; } + public float? ReadNSingle() + { if (Object == null) return null; + if (Object.GetType() == typeof(double)) return (float)(double)Object; + else if (Object.GetType() == typeof( float)) return (float) Object; + else if (Object.GetType() == typeof( long)) return (float)( long)Object; + else if (Object.GetType() == typeof( ulong)) return (float)( ulong)Object; return null; } + public double? ReadNDouble() + { if (Object == null) return null; + if (Object.GetType() == typeof(double)) return (double) Object; + else if (Object.GetType() == typeof( float)) return (double)(float)Object; + else if (Object.GetType() == typeof( long)) return (double)( long)Object; + else if (Object.GetType() == typeof( ulong)) return (double)(ulong)Object; return null; } + public string ReadString() + { if (Object == null) return null; + if (Object.GetType() == typeof(string)) return (string) Object; return null; } + + public bool Element(string Name, out MsgPack MsgPack, Type Type) + { if (Element(out MsgPack, Name)) return MsgPack.Object.GetType() == Type; return false; } + + public bool Element(string Name, out MsgPack MsgPack) + { if (Element(out MsgPack, Name)) return MsgPack != null; return false; } + + public bool Element(out MsgPack MsgPack, string Name) + { + MsgPack = null; + if (Object == null) return false; + + Type type = Object.GetType(); + if (type == typeof(List)) + { + List Obj = (List)Object; + foreach (object obj in Obj) + { + if (obj == null) continue; type = obj.GetType(); + if (type == typeof(MsgPack)) if (((MsgPack)obj).Name == Name) + { MsgPack = (MsgPack)obj; return true; } + } + } + else if (type == typeof(object[])) + { + object[] Obj = (object[])Object; + foreach (object obj in Obj) + { + if (obj == null) continue; type = obj.GetType(); + if (type == typeof(MsgPack)) if (((MsgPack)obj).Name == Name) + { MsgPack = (MsgPack)obj; return true; } + } + } + return false; + } + + public enum Types : byte + { + PosInt = 0b00000000, + FixMap = 0b10000000, + FixArr = 0b10010000, + FixStr = 0b10100000, + Nil = 0b11000000, + NeverUsed = 0b11000001, + False = 0b11000010, + True = 0b11000011, + Bin8 = 0b11000100, + Bin16 = 0b11000101, + Bin32 = 0b11000110, + Ext8 = 0b11000111, + Ext16 = 0b11001000, + Ext32 = 0b11001001, + Float32 = 0b11001010, + Float64 = 0b11001011, + UInt8 = 0b11001100, + UInt16 = 0b11001101, + UInt32 = 0b11001110, + UInt64 = 0b11001111, + Int8 = 0b11010000, + Int16 = 0b11010001, + Int32 = 0b11010010, + Int64 = 0b11010011, + FixExt1 = 0b11010100, + FixExt2 = 0b11010101, + FixExt4 = 0b11010110, + FixExt8 = 0b11010111, + FixExt16 = 0b11011000, + Str8 = 0b11011001, + Str16 = 0b11011010, + Str32 = 0b11011011, + Arr16 = 0b11011100, + Arr32 = 0b11011101, + Map16 = 0b11011110, + Map32 = 0b11011111, + NegInt = 0b11100000, + PosIntMax = 0b01111111, + FixMapMax = 0b10001111, + FixArrMax = 0b10011111, + FixStrMax = 0b10111111, + NegIntMax = 0b11111111, + } + + public struct Ext + { + public byte[] Data; + public sbyte Type; + } + } +} diff --git a/KKdMainLib/PDHeader.cs b/KKdMainLib/PDHeader.cs new file mode 100644 index 0000000..a39e4f9 --- /dev/null +++ b/KKdMainLib/PDHeader.cs @@ -0,0 +1,63 @@ +using KKdMainLib.IO; + +namespace KKdMainLib +{ + public struct PDHead + { + public int ID; + public int Lenght; + public int DataSize; + public int Signature; + public int SectionSize; + public int RealSignature; + public Main.Format Format; + public bool IsBE => Format == Main.Format.F2BE; + public bool IsX => Format == Main.Format.X || Format == Main.Format.XHD; + } + + public static class PDHeadExtensions + { + public static PDHead ReadHeader(this Stream stream, bool Seek) + { + if (Seek) + if (stream.Position >= 4) stream.Seek(-4, SeekOrigin.Current); + else stream.Seek( 0, 0); + return stream.ReadHeader(); + } + + public static PDHead ReadHeader(this Stream stream) + { + long Position = stream.LongPosition; + PDHead Header = new PDHead + { Format = Main.Format.F2LE, Signature = stream.ReadInt32(), + DataSize = stream.ReadInt32(), Lenght = stream.ReadInt32() }; + if (stream.ReadUInt32() == 0x18000000) + { Header.Format = Main.Format.F2BE; } + Header.ID = stream.ReadInt32(); + Header.SectionSize = stream.ReadInt32(); + stream.IsBE = Header.Format == Main.Format.F2BE; + stream.Format = Header.Format; + stream.LongPosition = Position + Header.Lenght; + Header.Signature = stream.ReadInt32Endian(); + return Header; + } + + public static void Write(this Stream stream, PDHead Header) + { + stream.Write(Header.Signature); + stream.Write(Header.DataSize); + stream.Write(Header.Lenght); + if (Header.Format == Main.Format.F2BE) stream.Write(0x18000000); + else stream.Write(0x10000000); + stream.Write(Header.ID); + stream.Write(Header.SectionSize); + stream.Write(0x00); + stream.Write(0x00); + } + + public static void WriteEOFC(this Stream stream, int ID) + { PDHead Header = new PDHead { Format = Main.Format.F2LE, ID = ID, + Lenght = 0x20, Signature = 0x43464F45, }; stream.Write(Header); } + + } +} diff --git a/KKdMainLib/POF.cs b/KKdMainLib/POF.cs new file mode 100644 index 0000000..9947791 --- /dev/null +++ b/KKdMainLib/POF.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using KKdMainLib.IO; + +namespace KKdMainLib +{ + public class POF + { + public byte Type; + public int Lenght; + public int Offset; + public int LastOffset; + public List Offsets; + public List POFOffsets; + public PDHead Header; + + public POF() + { Type = 0; Lenght = 0; Offset = 0; LastOffset = 0; Offsets = new List(); + POFOffsets = new List(); Header = new PDHead(); } + } + + public static class POFExtensions + { + public static POF AddPOF(this PDHead Header) + { + POF POF = new POF { Offsets = new List(), POFOffsets = + new List(), Offset = Header.DataSize + Header.Lenght }; + return POF; + } + public static Stream GetOffset(this Stream stream, ref POF POF) + {if (stream.Format > Main.Format.F) POF.POFOffsets.Add(stream.Position - (stream.IsX ? stream.Offset : 0x00)); return stream; } + + public static void ReadPOF(this Stream stream, ref POF POF) + { + if (stream.ReadString(3) == "POF") + { + POF.POFOffsets.Sort(); + POF.Type = byte.Parse(stream.ReadString(1)); + int IsX = POF.Type + 2; + stream.Seek(-4, SeekOrigin.Current); + POF.Header = stream.ReadHeader(); + stream.Seek(POF.Offset + POF.Header.Lenght, 0); + POF.Lenght = stream.ReadInt32(); + while (POF.Lenght + POF.Offset + POF.Header.Lenght > stream.Position) + { + int a = stream.ReadByte(); + if (a >> 6 == 0) break; + else if (a >> 6 == 1) a = a & 0x3F; + else if (a >> 6 == 2) + { + a = a & 0x3F; + a = (a << 8) | stream.ReadByte(); + } + else if (a >> 6 == 3) + { + a = a & 0x3F; + a = (a << 8) | stream.ReadByte(); + a = (a << 8) | stream.ReadByte(); + a = (a << 8) | stream.ReadByte(); + } + a <<= IsX; + POF.LastOffset += a; + POF.Offsets.Add(POF.LastOffset); + } + + for (int i = 0; i < POF.Offsets.Count && i < POF.POFOffsets.Count; i++) + if (POF.Offsets[i] != POF.POFOffsets[i]) + Console.WriteLine("Not right POF{0} offset table.\n" + + " Expected: {1}\n Got: {2}", POF.Type, + POF.Offsets[i].ToString("X8"), POF.POFOffsets[i].ToString("X8")); + } + } + + public static void Write(this Stream stream, ref POF POF, int ID) + { + POF.POFOffsets.Sort(); + long CurrentPOFOffset = 0; + long POFOffset = 0; + byte BitShift = (byte)(2 + POF.Type); + int Max1 = (0x00FF >> BitShift) << BitShift; + int Max2 = (0xFFFF >> BitShift) << BitShift; + POF.Lenght = 5 + ID; + for (int i = 0; i < POF.POFOffsets.Count; i++) + { + POFOffset = POF.POFOffsets[i] - CurrentPOFOffset; + CurrentPOFOffset = POF.POFOffsets[i]; + if (POFOffset <= Max1) POF.Lenght += 1; + else if (POFOffset <= Max2) POF.Lenght += 2; + else POF.Lenght += 4; + POF.POFOffsets[i] = POFOffset; + } + + long POFLenghtAling = POF.Lenght.Align(16); + POF.Header = new PDHead { DataSize = (int)POFLenghtAling, ID = ID, Format = Main.Format.F2LE, + Lenght = 0x20, SectionSize = (int)POFLenghtAling, Signature = 0x30464F50 }; + POF.Header.Signature += POF.Type << 24; + stream.Write(POF.Header); + + stream.Write(POF.Lenght); + for (int i = 0; i < POF.POFOffsets.Count; i++) + { + POFOffset = POF.POFOffsets[i]; + if (POFOffset <= Max1) stream.Write (( byte)((1 << 6) | (POFOffset >> BitShift))); + else if (POFOffset <= Max2) stream.WriteEndian((ushort)((2 << 14) | (POFOffset >> BitShift)), true); + else stream.WriteEndian(( uint)((3 << 30) | (POFOffset >> BitShift)), true); + } + stream.Write(0x00); + stream.Align(16, true); + stream.WriteEOFC(ID); + } + + } +} diff --git a/KKdMainLib/Properties/AssemblyInfo.cs b/KKdMainLib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c237e12 --- /dev/null +++ b/KKdMainLib/Properties/AssemblyInfo.cs @@ -0,0 +1,15 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("KKdMainLib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("KKdMainLib")] +[assembly: AssemblyCopyright("Copyright korenkonder © 2018-2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: Guid("2BA7EFC6-91D1-8BBC-C487-06C7F36CC789")] +[assembly: AssemblyVersion("0.4.5.7")] +[assembly: AssemblyFileVersion("0.4.5.7")] diff --git a/KKdMainLib/STR.cs b/KKdMainLib/STR.cs new file mode 100644 index 0000000..b45b7a1 --- /dev/null +++ b/KKdMainLib/STR.cs @@ -0,0 +1,227 @@ +using System; +using System.Xml.Linq; +using System.Collections.Generic; +using KKdMainLib.IO; +using KKdMainLib.MessagePack; +using MPIO = KKdMainLib.MessagePack.IO; + +namespace KKdMainLib +{ + public class STR + { + public struct String + { + public int ID; + public int StrOffset; + public string Str; + } + + public STR() + { Count = 0; Offset = 0; OffsetX = 0; STRs = null; POF = null; Header = new PDHead(); } + + public long Count; + private long Offset; + private long OffsetX; + public String[] STRs; + private POF POF; + private PDHead Header; + + public int STRReader(string filepath, string ext) + { + Stream reader = File.OpenReader(filepath + ext); + + Header = new PDHead(); + reader.Format = Main.Format.F; + Header.Signature = reader.ReadInt32(); + if (Header.Signature == 0x41525453) + { + Header = reader.ReadHeader(true); + POF = Header.AddPOF(); + reader.Position = Header.Lenght; + + Count = reader.ReadInt32Endian(); + Offset = reader.ReadInt32Endian(); + + if (Offset == 0) + { + Offset = Count; + OffsetX = reader.ReadInt64(); + Count = reader.ReadInt64(); + reader.Offset = Header.Lenght; + reader.Format = Main.Format.X; + } + reader.LongPosition = reader.IsX ? Offset + reader.Offset : Offset; + + STRs = new String[Count]; + for (int i = 0; i < Count; i++) + { + STRs[i].StrOffset = reader.GetOffset(ref POF).ReadInt32Endian(); + STRs[i].ID = reader.ReadInt32Endian(); + if (reader.IsX) STRs[i].StrOffset += (int)OffsetX; + } + + for (int i = 0; i < Count; i++) + { + reader.LongPosition = STRs[i].StrOffset + (reader.IsX ? reader.Offset : 0); + STRs[i].Str = reader.NullTerminatedUTF8(); + } + + reader.Position = POF.Offset; + reader.ReadPOF(ref POF); + } + else + { + reader.Position -= 4; + Count = 0; + for (int a = 0, i = 0; reader.Position > 0 && reader.Position < reader.Length; i++, Count++) + { + a = reader.ReadInt32(); + if (a == 0) break; + } + STRs = new String[Count]; + + for (int i = 0; i < Count; i++) + { + reader.LongPosition = STRs[i].StrOffset + (reader.IsX ? reader.Offset : 0); + STRs[i].ID = i; + STRs[i].Str = reader.NullTerminatedUTF8(); + } + } + + reader.Close(); + return 1; + } + + public void STRWriter(string filepath) + { + uint Offset = 0; + uint CurrentOffset = 0; + Stream writer = File.OpenWriter(filepath + (Header. + Format > Main.Format.FT ? ".str" : ".bin"), true); + writer.Format = Header.Format; + POF = new POF(); + writer.IsBE = writer.Format == Main.Format.F2BE; + + if (writer.Format > Main.Format.FT) + { + writer.Position = 0x40; + writer.WriteEndian(Count); + writer.GetOffset(ref POF).WriteEndian(0x80); + writer.Position = 0x80; + for (int i = 0; i < Count; i++) + { + writer.GetOffset(ref POF).Write(0x00); + writer.WriteEndian(STRs[i].ID); + } + writer.Align(16); + } + else + { + for (int i = 0; i < Count; i++) + writer.Write(0x00); + writer.Align(32); + } + + List UsedSTR = new List(); + List UsedSTRPos = new List(); + int[] STRPos = new int[Count]; + for (int i1 = 0; i1 < Count; i1++) + { + if (UsedSTR.Contains(STRs[i1].Str)) + { + for (int i2 = 0; i2 < Count; i2++) + if (UsedSTR[i2] == STRs[i1].Str) + { STRPos[i1] = UsedSTRPos[i2]; break; } + } + else + { + STRPos[i1] = writer.Position; + UsedSTRPos.Add(STRPos[i1]); + UsedSTR.Add(STRs[i1].Str); + writer.Write(STRs[i1].Str); + writer.WriteByte(0); + } + } + if (writer.Format > Main.Format.FT) + { + writer.Align(16); + Offset = writer.UIntPosition; + writer.Position = 0x80; + } + else + writer.Position = 0; + for (int i1 = 0; i1 < Count; i1++) + { + writer.WriteEndian(STRPos[i1]); + if (writer.Format > Main.Format.FT) writer.Position += 4; + } + + if (writer.Format > Main.Format.FT) + { + writer.UIntPosition = Offset; + writer.Write(ref POF, 1); + CurrentOffset = writer.UIntPosition; + writer.WriteEOFC(0); + Header.Lenght = 0x40; + Header.DataSize = (int)(CurrentOffset - Header.Lenght); + Header.Signature = 0x41525453; + Header.SectionSize = (int)(Offset - Header.Lenght); + writer.Position = 0; + writer.Write(Header); + } + writer.Close(); + } + + public void MsgPackReader(string filepath) + { + //STRs = new List(); + + Xml Xml = new Xml(); + Xml.OpenXml(filepath + ".xml", true); + Xml.Compact = true; + int i = 0; + foreach (XElement STR_ in Xml.doc.Elements("STR")) + { + foreach (XAttribute Entry in STR_.Attributes()) + if (Entry.Name == "Format") + Enum.TryParse(Entry.Value, out Header.Format); + foreach (XElement STREntry in STR_.Elements()) + { + if (STREntry.Name == "STREntry") + { + String Str = new String(); + foreach (XAttribute Entry in STREntry.Attributes()) + { + if (Entry.Name == "ID" ) Str.ID = int.Parse(Entry.Value); + if (Entry.Name == "String") Str.Str = Entry.Value ; + } + //STRs.Add(Str); + } + i++; + } + } + Count = i; + } + + public void MsgPackWriter(string filepath) + { + MsgPack STR_ = new MsgPack("STR").Add("Format", Header.Format.ToString()).Add("Count", Count); + MsgPack Strings = new MsgPack("Strings", Count); + for (int i = 0; i < Count; i++) + { + Strings[i] = new MsgPack().Add("ID", STRs[i].ID); + if (STRs[i].Str != null) + if (STRs[i].Str != "") + ((MsgPack)Strings[i]).Add("S", STRs[i].Str); ; + } + STR_.Add(Strings); + + MsgPack MsgPack = new MsgPack(MsgPack.Types.FixMap).Add(STR_); + + MPIO IO = new MPIO(File.OpenWriter(filepath + ".mp", true)); + IO.Write(MsgPack, true); + IO = null; + MsgPack = null; + } + } +} diff --git a/KKdMainLib/Text.cs b/KKdMainLib/Text.cs new file mode 100644 index 0000000..af7c17c --- /dev/null +++ b/KKdMainLib/Text.cs @@ -0,0 +1,17 @@ +using System; +using System.Text; + +namespace KKdMainLib +{ + public static class Text + { + public static string ToASCII(this byte[] Array) => Encoding.ASCII.GetString(Array); + public static string ToUTF8 (this byte[] Array) => Encoding.UTF8 .GetString(Array); + public static byte[] ToASCII(this string Data ) => Encoding.ASCII.GetBytes (Data ); + public static byte[] ToUTF8 (this string Data ) => Encoding.UTF8 .GetBytes (Data ); + public static byte[] ToASCII(this char[] Data ) => Encoding.ASCII.GetBytes (Data ); + public static byte[] ToUTF8 (this char[] Data ) => Encoding.UTF8 .GetBytes (Data ); + public static string ToBase64(this byte[] Array) => Convert. ToBase64String(Array); + public static byte[] FromBase64(this string Data ) => Convert.FromBase64String(Data ); + } +} diff --git a/KKdMainLib/Types/Half.cs b/KKdMainLib/Types/Half.cs new file mode 100644 index 0000000..6da762e --- /dev/null +++ b/KKdMainLib/Types/Half.cs @@ -0,0 +1,102 @@ +using System; + +namespace KKdMainLib.Types +{ + public struct Half : IFormattable + { + private ushort _value; + + public static explicit operator Half(ushort bits) => new Half() { _value = bits }; + + public static explicit operator ushort(Half bits) => bits._value; + + public static explicit operator double(Half h) + { + if (h._value == 0x0000) + return +0; + else if (h._value == 0x8000) + return (-0); + else if (h._value == 0x7C00) + return double.PositiveInfinity; + else if (h._value == 0xFC00) + return double.NegativeInfinity; + else if (h._value >> 10 == 0x1F) + return double.NaN; + else if (h._value >> 10 == 0x3F) + return -double.NaN; + + long exponent = ((h._value >> 10) & 0x1F); + long mantissa = (h._value & 0x3FF); + sbyte n = (sbyte)(((h._value >> 15 & 0x01) == 0) ? 1 : -1); + + double m = (((long)1 << 10) | mantissa) / Math.Pow(2, 10); + double x = Math.Pow(2, exponent - (0x1F >> 1)); + double d = n * m * x; + return d; + } + + public static explicit operator Half(double val) + { + Half h = new Half(); + if (val == +0) + h._value = 0x0000; + else if (val == -0) + h._value = 0x8000; + else if (val == double.NaN) + h._value = 0x7FFF; + else if (val == -double.NaN) + h._value = 0xFFFF; + else if (val == double.PositiveInfinity) + h._value = 0x7C00; + else if (val == double.NegativeInfinity) + h._value = 0xFC00; + else + h._value = ToDouble(val); + return h; + } + + public static ushort ToDouble(double val) + { + ushort Sign = 0; + if (val < 0) + Sign = 0x8000; + val = Math.Abs(val); + double Pow1 = 1; + double Pow2 = 1 << 10; + double x = 0; + + int MaxPow = (1 << 4); + + int i = 0; + while (i < MaxPow && i > -MaxPow + 1) + { + Pow1 = Math.Pow(2, i); + x = val / Pow1; + if (x >= 1 && x < 2) + { + ushort exponent_max = (ushort)Math.Ceiling(x * Pow2); + ushort exponent_min = (ushort)Math.Floor (x * Pow2); + ushort exponent = 0; + if (Math.Abs(x - exponent_max / Pow2) > Math.Abs(x - exponent_min / Pow2)) + exponent = exponent_max; + else exponent = exponent_min; + ushort mantissa = (ushort)(i + MaxPow - 1); + ushort d = (ushort)(Sign | ((mantissa & 0x001F) << 10) | (exponent & 0x03FF)); + return d; + } + else if (val < 1) i--; + else i++; + } + + if (i >= +0) + return 0x7C00; + else + return 0xFC00; + } + + public override string ToString() => ((double)this).ToString(); + public string ToString(string format, IFormatProvider formatProvider) => + ((double)this).ToString(format, formatProvider); + public override int GetHashCode() => base.GetHashCode(); + } +} diff --git a/KKdMainLib/Xml.cs b/KKdMainLib/Xml.cs new file mode 100644 index 0000000..cf2efa9 --- /dev/null +++ b/KKdMainLib/Xml.cs @@ -0,0 +1,102 @@ +using System; +using System.Xml; +using System.Text; +using System.Xml.Linq; + +namespace KKdMainLib +{ + public class Xml + { + public XDocument doc; + + public bool Compact = false; + + public Xml() { doc = new XDocument(); } + + public void OpenXml(string file, bool compact) + { + doc = XDocument.Load(file); + Compact = compact; + } + + public void SaveXml(string file) + { + XmlWriter writer = XmlWriter.Create(file, settings); + doc.Save(writer); + writer.Dispose(); + Compact = false; + GC.Collect(); + } + + public readonly XmlWriterSettings settings = new XmlWriterSettings + { Encoding = Encoding.UTF8, NewLineChars = "\n", Indent = true, IndentChars = "\t" }; + + public void Reader(XElement Child, ref bool value, string localName) + { if (Child.Name == localName) value = bool.Parse(Child.Value); } + + public void Reader(XAttribute Entry, ref bool value, string localName) + { if (Entry.Name == localName) value = bool.Parse(Entry.Value); } + + public void Reader(XElement Child, ref int value, string localName) + { if (Child.Name == localName) value = int.Parse(Child.Value); } + + public void Reader(XAttribute Entry, ref int value, string localName) + { if (Entry.Name == localName) value = int.Parse(Entry.Value); } + + public void Reader(XElement Child, ref uint value, string localName) + { if (Child.Name == localName) value = uint.Parse(Child.Value); } + + public void Reader(XAttribute Entry, ref uint value, string localName) + { if (Entry.Name == localName) value = uint.Parse(Entry.Value); } + + public void Reader(XElement Child, ref long value, string localName) + { if (Child.Name == localName) value = long.Parse(Child.Value); } + + public void Reader(XAttribute Entry, ref long value, string localName) + { if (Entry.Name == localName) value = long.Parse(Entry.Value); } + + public void Reader(XElement Child, ref ulong value, string localName) + { if (Child.Name == localName) value = ulong.Parse(Child.Value); } + + public void Reader(XAttribute Entry, ref ulong value, string localName) + { if (Entry.Name == localName) value = ulong.Parse(Entry.Value); } + + public void Reader(XElement Child, ref double value, string localName) + { if (Child.Name == localName) value = Child.Value.ToDouble(); } + + public void Reader(XAttribute Entry, ref double value, string localName) + { if (Entry.Name == localName) value = Entry.Value.ToDouble(); } + + public void Reader(XElement Child, ref string value, string localName) + { if (Child.Name == localName) value = Child.Value; } + + public void Reader(XAttribute Entry, ref string value, string localName) + { if (Entry.Name == localName) value = Entry.Value; } + + public void Reader(XElement Child, ref string[] value, string localName, params char[] Separate) + { if (Child.Name == localName) value = Child.Value.Split(Separate); } + + public void Reader(XAttribute Entry, ref string[] value, string localName, params char[] Separate) + { if (Entry.Name == localName) value = Entry.Value.Split(Separate); } + + public void Writer(XElement element, bool value, string localName) => + Writer(element, value.ToString().ToLower(), localName); + + public void Writer(XElement element, long value, string localName) => + Writer(element, value.ToString().ToLower(), localName); + + public void Writer(XElement element, ulong value, string localName) => + Writer(element, value.ToString().ToLower(), localName); + + public void Writer(XElement element, double value, string localName) => + Writer(element, value.ToString(), localName); + + public void Writer(XElement element, string value, string localName) + { + if (Compact && value != "" && value != null) + element.Add(new XAttribute(localName, value)); + else if (!Compact) + element.Add(new XElement(localName, value)); + } + } +} diff --git a/KKdSoundLib/DIVA.cs b/KKdSoundLib/DIVA.cs new file mode 100644 index 0000000..8c22e7c --- /dev/null +++ b/KKdSoundLib/DIVA.cs @@ -0,0 +1,214 @@ +using KKdMainLib; +using KKdMainLib.IO; +using MSIO = System.IO; + +namespace KKdSoundLib +{ + public unsafe class DIVA + { + public DIVAFile Data = new DIVAFile(); + + public string file = ""; + private int c, i; + + public DIVA() { Data = new DIVAFile(); file = ""; } + public DIVA(string filepath) { Data = new DIVAFile(); file = filepath; } + + public void DIVAReader(bool ToArray = false) + { + if (MSIO.File.Exists(file + ".diva")) + { + Data = new DIVAFile(); + Stream reader = File.OpenReader(file + ".diva"); + + if (reader.ReadString(0x04) == "DIVA") + { + reader.ReadInt32(); + Data.Size = reader.ReadUInt32(); + Data.SampleRate = reader.ReadUInt32(); + Data.SamplesCount = reader.ReadUInt32(); + reader.ReadInt64(); + Data.Channels = reader.ReadUInt16(); + reader.ReadUInt16(); + Data.Name = reader.ReadString(0x20); + + Stream writer = File.OpenWriter(); + if (!ToArray) writer = File.OpenWriter(file + ".wav", true); + writer.LongPosition = 0x2C; + + byte value = 0; + int[] current = new int[Data.Channels]; + int[] currentclamp = new int[Data.Channels]; + sbyte[] stepindex = new sbyte[Data.Channels]; + float f; + + int* currentPtr = current.GetPtr(); + int* currentclampPtr = currentclamp.GetPtr(); + sbyte* stepindexPtr = stepindex.GetPtr(); + + for (i = 0; i < Data.SamplesCount; i++) + for (c = 0; c < Data.Channels; c++) + { + value = reader.ReadHalfByte(); + IMADecoder(value, ref currentPtr[c], ref currentclampPtr[c], ref stepindexPtr[c]); + f = (float)(currentPtr[c] / 32768.0); + writer.Write(f); + } + + WAV.Header Header = new WAV.Header + { Bytes = 4, Channels = Data.Channels, Format = 3, + SampleRate = Data.SampleRate, Size = Data.SamplesCount * Data.Channels * 4}; + writer.Write(Header, 0); + if (ToArray) Data.Data = writer.ToArray(); + writer.Close(); + } + reader.Close(); + } + } + + private byte[] BuildWavHeader(WAV.Header Header, short Bytes) + { + Stream writer = File.OpenWriter(); + writer.Write(Header); + byte[] Data = writer.ToArray(); + writer.Close(); + return Data; + } + + public void DIVAWriter() + { + if (MSIO.File.Exists(file + ".wav")) + { + Stream reader = File.OpenReader(file + ".wav"); + Stream writer = File.OpenWriter(file + ".diva", true); + + Data = new DIVAFile(); + WAV.Header Header = reader.ReadWAVHeader(); + if (Header.IsSupported) + { + Data.Channels = Header.Channels; + Data.SampleRate = Header.SampleRate; + writer.LongPosition = 0x40; + + byte value = 0; + int[] sample = new int[Data.Channels]; + int[] current = new int[Data.Channels]; + int[] currentclamp = new int[Data.Channels]; + sbyte[] stepindex = new sbyte[Data.Channels]; + + int* samplePtr = sample.GetPtr(); + int* currentPtr = current.GetPtr(); + int* currentclampPtr = currentclamp.GetPtr(); + sbyte* stepindexPtr = stepindex.GetPtr(); + Data.SamplesCount = Header.Size / Header.Channels / Header.Bytes; + + for (i = 0; i < Data.SamplesCount; i++) + for (c = 0; c < Header.Channels; c++) + { + samplePtr[c] = (reader.ReadWAVSample(Header.Bytes, Header.Format) * 0x8000).CFTI(); + value = IMAEncoder(samplePtr[c], ref currentPtr[c], ref currentclampPtr[c], ref stepindexPtr[c]); + writer.Write(value, 4); + } + writer.CheckWrited(); + + writer.LongPosition = 0x00; + writer.Write("DIVA"); + writer.Write(0x00); + writer.Write((Data.SamplesCount * Data.Channels).Align(2, 2)); + writer.Write(Data.SampleRate); + writer.Write(Data.SamplesCount); + writer.Write(0x00); + writer.Write(0x00); + writer.Write(Data.Channels); + } + reader.Close(); + writer.Close(); + } + } + + private void IMADecoder(byte value, ref int current, ref int currentclamp, ref sbyte stepindex) + { + step = ima_step_table[stepindex]; + + diff = step >> 3; + if ((value & 1) == 1) diff += step >> 2; + if ((value & 2) == 2) diff += step >> 1; + if ((value & 4) == 4) diff += step; + + if ((value & 8) == 8) + { currentclamp -= diff; current = currentclamp; + if (currentclamp < -0x8000) currentclamp = -0x8000; } + else + { currentclamp += diff; current = currentclamp; + if (currentclamp > 0x7FFF) currentclamp = 0x7FFF; } + + stepindex += ima_index_table[value & 7]; + if (stepindex < 0) stepindex = 0; + if (stepindex > 88) stepindex = 88; + } + + private int delta, diff; + private byte value; + private short step; + + private byte IMAEncoder(int sample, ref int current, ref int currentclamp, ref sbyte stepindex) + { + value = 0; + step = ima_step_table[stepindex]; + + delta = sample - current; + + if (delta < 0) + { value |= 8; delta = -delta; } + diff = step >> 3; + if (delta > step) + { value |= 4; diff += step; delta -= step; } + step >>= 1; + if (delta > step) + { value |= 2; diff += step; delta -= step; } + step >>= 1; + if (delta > step) + { value |= 1; diff += step; } + + if ((value & 8) == 8) + { currentclamp -= diff; current = currentclamp; + if (currentclamp < -0x8000) currentclamp = -0x8000; } + else + { currentclamp += diff; current = currentclamp; + if (currentclamp > 0x7FFF) currentclamp = 0x7FFF; } + + stepindex += ima_index_table[value & 0x07]; + if (stepindex < 0) stepindex = 0; + if (stepindex > 88) stepindex = 88; + return value; + } + + private readonly sbyte[] ima_index_table = + { -1, -1, -1, -1, 2, 4, 6, 8 }; + + private readonly short[] ima_step_table = { + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 + }; + + public struct DIVAFile + { + public uint Size; + public uint SampleRate; + public uint SamplesCount; + public string Name; + public ushort Channels; + public byte[] Data; + } + } +} diff --git a/KKdSoundLib/Extensions.cs b/KKdSoundLib/Extensions.cs new file mode 100644 index 0000000..7436ed6 --- /dev/null +++ b/KKdSoundLib/Extensions.cs @@ -0,0 +1,94 @@ +using KKdMainLib.IO; + +namespace KKdSoundLib +{ + public static class Extensions + { + public static double ReadWAVSample(this Stream IO, ushort Bytes, ushort Format) + { + if (Bytes == 2) return IO. ReadInt16() / (double)0x00008000; + else if (Bytes == 4 && Format == 0x01) return IO. ReadInt32() / (double)0x80000000; + else if (Bytes == 4 && Format == 0x03) return IO.ReadSingle(); + else if (Bytes == 8 && Format == 0x03) return IO.ReadDouble(); + else return 0; + } + + public static void Write(this Stream IO, double Sample, ushort Bytes, ushort Format) + { + if (Bytes == 2) IO.Write ((ushort)(Sample * 0x00008000)); + else if (Bytes == 4 && Format == 0x01) IO.Write (( int)(Sample * 0x80000000)); + else if (Bytes == 4 && Format == 0x03) IO.Write ((float) Sample); + else if (Bytes == 8 && Format == 0x03) IO.Write ( Sample); + } + + public static WAV.Header ReadWAVHeader(this Stream IO) + { + WAV.Header Header = new WAV.Header(); + if (IO.ReadString(4) != "RIFF") return Header; + IO.ReadUInt32(); + if (IO.ReadString(4) != "WAVE") return Header; + if (IO.ReadString(4) != "fmt ") return Header; + int Offset = IO.ReadInt32(); + Header.Format = IO.ReadUInt16(); + if (Header.Format == 0x01 || Header.Format == 0x03 || Header.Format == 0xFFFE) + { + Header.Channels = IO.ReadUInt16(); + Header.SampleRate = IO.ReadUInt32(); + IO.ReadInt32(); IO.ReadInt16(); + Header.Bytes = IO.ReadUInt16(); + if (Header.Bytes % 8 != 0) return Header; + Header.Bytes >>= 3; + if (Header.Bytes == 0) return Header; + if (Header.Format == 0xFFFE) + { + IO.ReadInt32(); + Header.ChannelMask = IO.ReadUInt32(); + Header.Format = IO.ReadUInt16(); + } + if (Header.Bytes < 1 || (Header.Bytes > 4 && Header.Bytes != 8)) return Header; + if (Header.Bytes > 0 && Header.Bytes < 4 && Header.Format == 3) return Header; + if (Header.Bytes == 8 && Header.Format == 1) return Header; + IO.Seek(Offset + 0x14, 0); + if (IO.ReadString(4) != "data") return Header; + Header.Size = IO.ReadUInt32(); + Header.HeaderSize = IO.UIntPosition; + Header.IsSupported = true; + return Header; + } + return Header; + } + + public static void Write(this Stream IO, WAV.Header Header, long Seek) => IO.Write(Header, Seek, 0); + + public static void Write(this Stream IO, WAV.Header Header, long Seek, SeekOrigin Origin) + { IO.Seek(Seek, Origin); IO.Write(Header); } + + public static void Write(this Stream IO, WAV.Header Header) + { + IO.Write("RIFF"); + if (Header.Format != 0xFFFE) IO.Write(Header.Size + 0x24); + else IO.Write(Header.Size + 0x3C); + IO.Write("WAVE"); + IO.Write("fmt "); + IO.Write(0x10); + IO.Write(Header.Format); + IO.Write((short)Header.Channels); + IO.Write(Header.SampleRate); + IO.Write(Header.SampleRate * Header.Channels * Header.Bytes); + IO.Write((short)(Header.Channels * Header.Bytes)); + IO.Write((short)(Header.Bytes << 3)); + if (Header.Format == 0xFFFE) + { + IO.Write((short)0x16); + IO.Write((short)(Header.Bytes << 3)); + IO.Write(Header.ChannelMask); + IO.Write(Header.Bytes == 2 ? 0x01 : 0x03); + IO.Write(0x00100000); + IO.Write(0xAA000080); + IO.Write(0x719B3800); + } + IO.Write("data"); + IO.Write(Header.Size); + } + } +} diff --git a/KKdSoundLib/KKdSoundLib.csproj b/KKdSoundLib/KKdSoundLib.csproj new file mode 100644 index 0000000..f5d7746 --- /dev/null +++ b/KKdSoundLib/KKdSoundLib.csproj @@ -0,0 +1,59 @@ + + + + + Debug + AnyCPU + {D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA} + Library + KKdSoundLib + KKdSoundLib + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + true + + + AnyCPU + embedded + true + bin\ + TRACE + prompt + 4 + true + true + + + + + + + + + + + + + + + + + + + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789} + KKdMainLib + + + + \ No newline at end of file diff --git a/KKdSoundLib/Properties/AssemblyInfo.cs b/KKdSoundLib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2c29003 --- /dev/null +++ b/KKdSoundLib/Properties/AssemblyInfo.cs @@ -0,0 +1,15 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("KKdSoundLib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("KKdSoundLib")] +[assembly: AssemblyCopyright("Copyright korenkonder © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: Guid("D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA")] +[assembly: AssemblyVersion("0.0.2.1")] +[assembly: AssemblyFileVersion("0.0.2.1")] diff --git a/KKdSoundLib/VAG.cs b/KKdSoundLib/VAG.cs new file mode 100644 index 0000000..a1507a4 --- /dev/null +++ b/KKdSoundLib/VAG.cs @@ -0,0 +1,792 @@ +using KKdMainLib; +using KKdMainLib.IO; +using MSIO = System.IO; + +namespace KKdSoundLib +{ + public unsafe class VAG + { + private int c, d0, d1, e, g, i, i1, i2, j, s, PrNR, ShF, PrNRCount; + private uint VBS; + private float f; + private ushort ch; + private const uint BS = 28; //VAGBlockSize + private int[] Samp1, Samp2, Samp3, Samp4; + private int* S1Ptr, S2Ptr, S3Ptr, S4Ptr; + + public VAGFile VAGData = new VAGFile(); + public string file = ""; + + public VAG() { VAGData = new VAGFile(); file = ""; + HEVAG1Ptr = HEVAG1.GetPtr(); HEVAG2Ptr = HEVAG2.GetPtr(); + HEVAG3Ptr = HEVAG3.GetPtr(); HEVAG4Ptr = HEVAG4.GetPtr(); + } + + public VAG(string filepath) { VAGData = new VAGFile(); file = filepath; } + + public void VAGReader() + { + if (!MSIO.File.Exists(file + ".vag")) return; + + VAGData = new VAGFile(); + Stream reader = File.OpenReader(file + ".vag", true); + + if (reader.ReadUInt32() != 0x70474156) return; + + VAGData.Version = reader.ReadUInt32Endian(true); + reader.ReadUInt32(); + VAGData.Size = reader.ReadUInt32Endian(true); + VAGData.SampleRate = reader.ReadUInt32Endian(true); + reader.ReadUInt32(); + reader.ReadUInt32(); + reader.ReadUInt16(); + VAGData.Channels = reader.ReadUInt16(); + if (VAGData.Channels < 2) VAGData.Channels = 1; + VAGData.Name = reader.ReadString(0x10); + + bool HEVAG = VAGData.Version == 0x00020001 || VAGData.Version == 0x00030000; + if (!HEVAG) VAGData.Channels = 1; + ch = VAGData.Channels; + VBS = BS * ch; + + four_bit = new int[BS]; four_bitPtr = four_bit .GetPtr(); + temp_buffer = new int[BS]; temp_bufferPtr = temp_buffer.GetPtr(); + Samp1 = new int[VAGData.Channels]; S1Ptr = Samp1.GetPtr(); + Samp2 = new int[VAGData.Channels]; S2Ptr = Samp2.GetPtr(); + Samp3 = new int[VAGData.Channels]; S3Ptr = Samp3.GetPtr(); + Samp4 = new int[VAGData.Channels]; S4Ptr = Samp4.GetPtr(); + if (VAGData.Size + 0x30 > reader.LongLength) VAGData.Size = reader.UIntLength - 0x30; + VAGData.Size = (VAGData.Size / VAGData.Channels) >> 4; + VAGData.Flags = new byte [VAGData.Size]; + VAGData.Data = new int[VAGData.Size * VBS]; + VAGData.DataPtr = VAGData.Data.GetPtr(); + VAGData.OriginDataPtr = VAGData.DataPtr; + + if (HEVAG) + for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS) + for (c = 0; c < ch; c++) + { + s = reader.ReadByte(); + PrNR = (s & 0xF0) >> 4; + ShF = s & 0x0F; + s = reader.ReadByte(); + PrNR = (s & 0xF0) | PrNR; + VAGData.Flags[i1] = (byte)(s & 0xF); + + for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2) + { + s = reader.ReadByte(); + four_bitPtr[i ] = s & 0x0F; + four_bitPtr[i2] = s & 0xF0; + four_bitPtr[i2] >>= 4; + } + + HEVAG_1 = HEVAG1Ptr[PrNR]; HEVAG_2 = HEVAG2Ptr[PrNR]; + HEVAG_3 = HEVAG3Ptr[PrNR]; HEVAG_4 = HEVAG4Ptr[PrNR]; + tS1 = S1Ptr[c]; tS2 = S2Ptr[c]; tS3 = S3Ptr[c]; tS4 = S4Ptr[c]; + DecodeHEVAG(); + S1Ptr[c] = tS1; S2Ptr[c] = tS2; S3Ptr[c] = tS3; S4Ptr[c] = tS4; + + for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2) + { + VAGData.DataPtr[i * ch + c] = temp_bufferPtr[i ]; + VAGData.DataPtr[i2 * ch + c] = temp_bufferPtr[i2]; + } + + } + else + for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS) + { + s = reader.ReadByte(); + PrNR = (s & 0xF0) >> 4; + ShF = s & 0x0F; + s = reader.ReadByte(); + VAGData.Flags[i1] = (byte)(s & 0xF); + + for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2) + { + s = reader.ReadByte(); + four_bitPtr[i ] = s & 0x0F; + four_bitPtr[i2] = s & 0xF0; + four_bitPtr[i2] >>= 4; + } + + VAG_1 = HEVAG1Ptr[PrNR]; VAG_2 = HEVAG2Ptr[PrNR]; + tS1 = S1Ptr[c]; tS2 = S2Ptr[c]; + + i = 0; i2 = 1; + while (i < BS) + { + d0 = four_bitPtr[i]; + d1 = four_bitPtr[i2]; + if (d0 > 7) d0 -= 16; + if (d1 > 7) d1 -= 16; + d0 = d0 << (20 - ShF); + d1 = d1 << (20 - ShF); + + g = ((tS1 >> 8) * VAG_1 + (tS2 >> 8) * VAG_2) >> 5; + tS2 = tS1; tS1 = g + d0; + + g = ((tS1 >> 8) * VAG_1 + (tS2 >> 8) * VAG_2) >> 5; + tS2 = tS1; tS1 = g + d1; + + temp_bufferPtr[i ] = tS2; + temp_bufferPtr[i2] = tS1; + i += 2; + i2 += 2; + } + + S1Ptr[c] = tS1; S2Ptr[c] = tS2; + + for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2) + { + VAGData.DataPtr[i ] = temp_bufferPtr[i ]; + VAGData.DataPtr[i2] = temp_bufferPtr[i2]; + } + } + + VAGData.DataPtr = VAGData.OriginDataPtr; + reader.Close(); + } + + private void DecodeHEVAG() + { + i = 0; i2 = 1; + while (i < BS) + { + d0 = four_bitPtr[i ]; + d1 = four_bitPtr[i2]; + if (d0 > 7) d0 -= 16; + if (d1 > 7) d1 -= 16; + d0 = d0 << (20 - ShF); + d1 = d1 << (20 - ShF); + + g = ((tS1 >> 8) * HEVAG_1 + (tS2 >> 8) * HEVAG_2 + + (tS3 >> 8) * HEVAG_3 + (tS4 >> 8) * HEVAG_4) >> 5; + tS4 = tS3; tS3 = tS2; tS2 = tS1; tS1 = g + d0; + + g = ((tS1 >> 8) * HEVAG_1 + (tS2 >> 8) * HEVAG_2 + + (tS3 >> 8) * HEVAG_3 + (tS4 >> 8) * HEVAG_4) >> 5; + tS4 = tS3; tS3 = tS2; tS2 = tS1; tS1 = g + d1; + + temp_bufferPtr[i ] = tS2; + temp_bufferPtr[i2] = tS1; + i += 2; + i2 += 2; + } + } + + public void WAVWriterStraight() + { + byte Flag = VAGData.Flags[0]; + if (Flag == 7) return; + WAV.Header Header = new WAV.Header(); + Stream writer = File.OpenWriter(file + ".wav", true); + writer.LongPosition = 0x2C; + + for (i = 0; i < BS; i++) + for (c = 0; c < ch; c++) + { + f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0); + writer.Write(f); + } + + for (i1 = 0, i2 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS) + { + Flag = VAGData.Flags[i1]; + if (Flag == 5 || Flag > 6) break; + for (i = 0; i < BS; i++) + for (c = 0; c < ch; c++) + { + f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0); + writer.Write(f); + } + + if (Flag == 1) break; + } + VAGData.DataPtr = VAGData.OriginDataPtr; + + Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate = + VAGData.SampleRate, Size = writer.UIntPosition - 0x2C }; + writer.Write(Header, 0); + writer.Close(); + } + + public void WAVWriter() + { + byte Flag = VAGData.Flags[0]; + if (Flag == 7) return; + WAV.Header Header = new WAV.Header(); + Stream writer; + if (Flag == 6) writer = File.OpenWriter(file + ".loop.0.wav", true); + else writer = File.OpenWriter(file + ".0.wav", true); + writer.LongPosition = 0x2C; + + for (i = 0; i < BS; i++) + for (c = 0; c < ch; c++) + { + f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0); + writer.Write(f); + } + VAGData.DataPtr += VBS; + + for (i1 = 1, i2 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS) + { + Flag = VAGData.Flags[i1]; + if (Flag == 5 || Flag > 6) break; + else if (Flag == 6) + { + Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate = + VAGData.SampleRate, Size = writer.UIntPosition - 0x2C }; + writer.Write(Header, 0); + writer.Close(); + i2++; + + writer = File.OpenWriter(file + "." + i2 + ".loop.wav", true); + writer.LongPosition = 0x2C; + } + + for (i = 0; i < BS; i++) + for (c = 0; c < ch; c++) + { + f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0); + writer.Write(f); + } + + if (Flag == 1) break; + else if (Flag == 3) + { + Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate = + VAGData.SampleRate, Size = writer.UIntPosition - 0x2C }; + writer.Write(Header, 0); + writer.Close(); + i2++; + + if (VAGData.Size == i1 + 1) + writer = File.OpenWriter(); + else + writer = File.OpenWriter(file + "." + i2 + ".wav", true); + writer.LongPosition = 0x2C; + } + } + VAGData.DataPtr = VAGData.OriginDataPtr; + + Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate = + VAGData.SampleRate, Size = writer.UIntPosition - 0x2C }; + writer.Write(Header, 0); + writer.Close(); + } + + public int WAVReaderStraight(bool ExtendedFlagging = false) + { + VAGData = new VAGFile(); + Stream reader = File.OpenReader(file + ".wav"); + WAV.Header Header = reader.ReadWAVHeader(); + if (!Header.IsSupported) { reader.Close(); return 1; } + ch = Header.Channels; + VBS = BS * ch; + + VAGData.Size = Header.Size / Header.Bytes; + VAGData.Data = new int[VAGData.Size.Align(VBS)]; + VAGData.DataPtr = VAGData.Data.GetPtr(); + VAGData.OriginDataPtr = VAGData.DataPtr; + + if (Header.Bytes == 1 && Header.Format == 0x01) + for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = (reader.ReadByte () - 0x80) << 16; + else if (Header.Bytes == 2 && Header.Format == 0x01) + for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = reader.ReadInt16 () << 8; + else if (Header.Bytes == 3 && Header.Format == 0x01) + for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = reader.ReadByte () | (reader.ReadInt16() << 8); + else if (Header.Bytes == 4 && Header.Format == 0x01) + for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = reader.ReadInt32 () >> 8; + else if (Header.Bytes == 4 && Header.Format == 0x03) + for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = (int)(reader.ReadSingle() * 8388608.0); + else if (Header.Bytes == 8 && Header.Format == 0x03) + for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = (int)(reader.ReadDouble() * 8388608.0); + + VAGData.Size = VAGData.Size.Align(VBS, VBS); + VAGData.DataPtr = VAGData.OriginDataPtr; + VAGData.Channels = ch; + VAGData.SampleRate = Header.SampleRate; + VAGData.Flags = new byte[VAGData.Size]; + if (ExtendedFlagging) VAGData.Flags[0] = 0x4; + VAGData.Flags[VAGData.Size - 1] = 0x1; + + reader.Close(); + return 0; + } + + public int WAVReader(bool ExtendedFlagging = false) + { + string[] Files; + bool HasLoop = false; + bool[] Loop; + { + if (!file.EndsWith(".0")) return WAVReaderStraight(); + file = file.Remove(file.Length - 2); + i2 = 0; + System.Collections.Generic.List files = + new System.Collections.Generic.List(); + System.Collections.Generic.List< bool> loop = + new System.Collections.Generic.List< bool>(); + while (true) + { + if (MSIO.File.Exists(file + "." + i2 + ".wav")) + { + files.Add(file + "." + i2 + ".wav"); + loop.Add(false); + } + else if (MSIO.File.Exists(file + "." + i2 + ".loop.wav")) + { + files.Add(file + "." + i2 + ".loop.wav"); + loop.Add(true); + HasLoop = true; + } + else break; + i2++; + } + Files = files.ToArray(); + Loop = loop .ToArray(); + } + + uint[] Sizes = new uint[Files.Length]; + ushort Channels = 0; + uint AlignVAG, Size = 0, SampleRate = 0; + + VAGData = new VAGFile(); + Stream reader; + WAV.Header Header; + for (i = 0; i < Files.Length; i++) + { + reader = File.OpenReader(Files[i]); + Header = reader.ReadWAVHeader(); + + if (!Header.IsSupported) { reader.Close(); return 2; } + if (i == 0) { SampleRate = Header.SampleRate; + ch = Channels = Header.Channels; VBS = BS * ch; } + if (Header.Channels != Channels ) { reader.Close(); return 3; } + if (Header.SampleRate != SampleRate) { reader.Close(); return 4; } + + Sizes[i] = Header.Size / Header.Bytes; + Size += Sizes[i].Align(VBS); + reader.Close(); + } + + VAGData.Data = new int[Size]; + VAGData.DataPtr = VAGData.Data.GetPtr(); + VAGData.OriginDataPtr = VAGData.DataPtr; + VAGData.Size = Size / VBS; + VAGData.Flags = new byte[VAGData.Size]; + + if (HasLoop) + for (i = 0; i < VAGData.Size; i++) + VAGData.Flags[i] = 0x2; + + i2 = 0; + uint Start = 0, End = 0; + for (i = 0; i < Files.Length; i++) + { + reader = File.OpenReader(Files[i]); + Header = reader.ReadWAVHeader(); + if (Header.Bytes == 1 && Header.Format == 0x01) + for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = (reader.ReadByte () - 0x80) << 16; + else if (Header.Bytes == 2 && Header.Format == 0x01) + for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = reader.ReadInt16 () << 8; + else if (Header.Bytes == 3 && Header.Format == 0x01) + for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = reader.ReadByte () | (reader.ReadInt16() << 8); + else if (Header.Bytes == 4 && Header.Format == 0x01) + for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = reader.ReadInt32 () >> 8; + else if (Header.Bytes == 4 && Header.Format == 0x03) + for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = (int)(reader.ReadSingle() * 8388608.0); + else if (Header.Bytes == 8 && Header.Format == 0x03) + for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++) + *VAGData.DataPtr = (int)(reader.ReadDouble() * 8388608.0); + reader.Close(); + + AlignVAG = Sizes[i].Align(VBS) - Sizes[i]; + VAGData.DataPtr += AlignVAG; + + AlignVAG = (Sizes[i] + AlignVAG) / VBS; + End += AlignVAG; + End--; + if (Loop[i] ) { VAGData.Flags[Start] = 0x6; VAGData.Flags[End] = 0x3; } + else if (ExtendedFlagging) VAGData.Flags[Start] = 0x4; + if (i + 1 == Files.Length && !Loop[i]) VAGData.Flags[End] = 0x1; + Start += AlignVAG; + End++; + } + + VAGData.DataPtr = VAGData.OriginDataPtr; + VAGData.Channels = ch; + VAGData.SampleRate = SampleRate; + + return 0; + } + + public void VAGWriter(bool HEVAG = true) + { + VAGData.Name = MSIO.Path.GetFileName(file); + Stream writer = File.OpenWriter(file + ".vag", true); + Samp1 = new int[ch]; S1Ptr = Samp1.GetPtr(); + Samp2 = new int[ch]; S2Ptr = Samp2.GetPtr(); + Samp3 = new int[ch]; S3Ptr = Samp3.GetPtr(); + Samp4 = new int[ch]; S4Ptr = Samp4.GetPtr(); + S_1 = new int[ch]; S_2 = new int[ch]; + S_3 = new int[ch]; S_4 = new int[ch]; + if (HEVAG) PrNRCount = 128; + else PrNRCount = 5; + max = new int[PrNRCount]; maxPtr = max .GetPtr(); + error = new int[PrNRCount]; errorPtr = error .GetPtr(); + four_bit = new int[BS]; four_bitPtr = four_bit .GetPtr(); + data_buffer = new int[BS]; data_bufferPtr = data_buffer.GetPtr(); + temp_buffer = new int[BS]; temp_bufferPtr = temp_buffer.GetPtr(); + buffer = new int[PrNRCount, BS]; + + writer.Write(0x70474156); + if (HEVAG) writer.WriteEndian(0x00020001, true); + else writer.WriteEndian(0x00000020, true); + writer.Write(0); + if (HEVAG) writer.WriteEndian((VAGData.Size * ch + ch) << 4, true); + else writer.WriteEndian((VAGData.Size + 1) << 4, true); + writer.WriteEndian(VAGData.SampleRate, true); + writer.Write(0); + writer.Write(0); + writer.Write((ushort)0); + if (HEVAG) writer.Write(VAGData.Channels); + else writer.Write((ushort)0x1); + writer.Write(VAGData.Name); + writer.LongPosition = 0x30; + + if (HEVAG) + for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS) + for (c = 0; c < ch; c++) + { + for (i = 0, s = 0; i < BS; i++) + { + data_bufferPtr[i] = VAGData.OriginDataPtr[i1 * BS * ch + i * ch + c]; + s |= data_bufferPtr[i]; + } + + if (s == 0) + { + S_1[c] = S_2[c] = S_3[c] = S_4[c] = 0; + writer.WriteByte(0); + writer.WriteByte(VAGData.Flags[i1]); + writer.WriteByte(0); + writer.WriteByte(0); + writer.Write(0); + writer.Write(0); + writer.Write(0); + continue; + } + + Calc4BitsHEVAG(); + + s = ((PrNR & 0xF) << 4) | (ShF & 0xF); + writer.WriteByte((byte)s); + s = (PrNR & 0xF0) | (VAGData.Flags[i1] & 0xF); + writer.WriteByte((byte)s); + for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2) + { + s = (four_bitPtr[i2] << 4) | four_bitPtr[i]; + writer.WriteByte((byte)s); + } + } + else + for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS) + { + for (i = 0; i < BS; i++) + { + for (c = 0, data_bufferPtr[i] = 0, s = 0; c < ch; c++) + data_bufferPtr[i] += VAGData.OriginDataPtr[i1 * BS * ch + i * ch + c]; + data_bufferPtr[i] /= ch; + s |=data_bufferPtr[i]; + c = 0; + } + + if (s == 0) + { + S_1[c] = S_2[c] = 0; + writer.WriteByte(0); + writer.WriteByte(VAGData.Flags[i1]); + writer.WriteByte(0); + writer.WriteByte(0); + writer.Write(0); + writer.Write(0); + writer.Write(0); + continue; + } + + Calc4BitsVAG(); + + s = ((PrNR & 0xF) << 4) | (ShF & 0xF); + writer.WriteByte((byte)s); + writer.WriteByte(VAGData.Flags[i1]); + for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2) + { + s = (four_bitPtr[i2] << 4) | four_bitPtr[i]; + writer.WriteByte((byte)s); + } + } + + if (!HEVAG) ch = 1; + for (c = 0; c < ch; c++) + { + writer.Write(0x77770700); + writer.Write(0x77777777); + writer.Write(0x77777777); + writer.Write(0x77777777); + } + VAGData.DataPtr = VAGData.OriginDataPtr; + writer.Close(); + } + + private int min, ShM, S1, S2, S3, S4, tS1, tS2, tS3, tS4, PrNRf; + private int VAG_1, VAG_2, HEVAG_1, HEVAG_2, HEVAG_3, HEVAG_4; + private int[] data_buffer, error, four_bit, max, S_1, S_2, S_3, S_4, temp_buffer; + private int[,] buffer; + private int* data_bufferPtr, errorPtr, four_bitPtr, maxPtr, temp_bufferPtr; + + private void Calc4BitsVAG() + { + ShF = min = 134217728; + for (j = 0; j < 5; j++) + { + maxPtr[j] = 0; + S1 = S1Ptr[c]; S2 = S2Ptr[c]; + VAG_1 = HEVAG1Ptr[j]; VAG_2 = HEVAG2Ptr[j]; + for (i = 0; i < 28; i++) + { + g = data_bufferPtr[i]; + e = ((S1 >> 8) * VAG_1 + (S2 >> 8) * VAG_2) >> 5; + e = g - e; + if (e > 7864319) e = 7864319; + if (e < -7864320) e = -7864320; + buffer[j, i] = e; + if (e < 0) e = -e; + if (e > maxPtr[j]) maxPtr[j] = e; + S2 = S1; S1 = g; + } + + if (maxPtr[j] < min) { PrNR = j; min = maxPtr[j]; } + } + + S1Ptr[c] = S1; S2Ptr[c] = S2; + + ShF = 0; + ShM = 0x4000; + min = min >> 8; + + while (ShF < 12) + { + e = min + (ShM >> 3); + if ((ShM & e) == ShM) + break; + ShF++; + ShM >>= 1; + } + + S1 = S_1[c]; S2 = S_2[c]; + for (i = 0; i < 28; i++) + { + g = buffer[PrNR, i]; + e = ((S1 >> 8) * HEVAG1Ptr[PrNR] + (S2 >> 8) * HEVAG2Ptr[PrNR]) >> 5; + e = g - e; + + d1 = e << ShF; + d0 = (int)((uint)d1 + 0x80000) >> 20; + if (d0 > 7) d0 = 7; + if (d0 < -8) d0 = -8; + four_bitPtr[i] = d0 & 0xF; + d0 = d0 << (20 - ShF); + + S2 = S1; S1 = d0 - e; + } + S_1[c] = S1; S_2[c] = S2; + } + + private void Calc4BitsHEVAG() + { + PrNRf = 0; + min = 134217728; + for (j = 0; j < PrNRCount; j++) + { + PrNR = j; + + Calc4Bits_HEVAG(); + + tS1 = S1Ptr[c]; tS2 = S2Ptr[c]; tS3 = S3Ptr[c]; tS4 = S4Ptr[c]; + DecodeHEVAG(); + i = 0; + errorPtr[j] = 0; + while (i < BS) + { + e = data_bufferPtr[i] - temp_bufferPtr[i]; + if (e < 0) e = -e; + errorPtr[j] += e; + i++; + } + + if (errorPtr[j] < min) { PrNRf = j; min = errorPtr[j]; } + } + PrNR = PrNRf; + + Calc4Bits_HEVAG(); + S1Ptr[c] = S1; S2Ptr[c] = S2; S3Ptr[c] = S3; S4Ptr[c] = S4; + S_1 [c] = tS1; S_2 [c] = tS2; S_3 [c] = tS3; S_4 [c] = tS4; + } + + private void Calc4Bits_HEVAG() + { + S1 = S1Ptr[c]; S2 = S2Ptr[c]; S3 = S3Ptr[c]; S4 = S4Ptr[c]; + HEVAG_1 = HEVAG1Ptr[PrNR]; HEVAG_2 = HEVAG2Ptr[PrNR]; + HEVAG_3 = HEVAG3Ptr[PrNR]; HEVAG_4 = HEVAG4Ptr[PrNR]; + + i = 0; + maxPtr[PrNR] = 0; + while (i < BS) + { + g = data_bufferPtr[i]; + e = ((S1 >> 8) * HEVAG_1 + (S2 >> 8) * HEVAG_2 + + (S3 >> 8) * HEVAG_3 + (S4 >> 8) * HEVAG_4) >> 5; + e = g - e; + if (e > 7864319) e = 7864319; + if (e < -7864320) e = -7864320; + temp_bufferPtr[i] = e; + if (e < 0) e = -e; + if (e > maxPtr[PrNR]) maxPtr[PrNR] = e; + S4 = S3; S3 = S2; S2 = S1; S1 = g; + i++; + } + + for (ShF = 0, ShM = 0x400000; ShF < 15; ShF++, ShM >>= 1) + { e = maxPtr[PrNR] + (ShM >> 3); if ((ShM & e) == ShM) break; } + + tS1 = S_1[c]; tS2 = S_2[c]; tS3 = S_3[c]; tS4 = S_4[c]; + i = 0; + while (i < BS) + { + g = temp_bufferPtr[i]; + e = ((tS1 >> 8) * HEVAG_1 + (tS2 >> 8) * HEVAG_2 + + (tS3 >> 8) * HEVAG_3 + (tS4 >> 8) * HEVAG_4) >> 5; + e = g - e; + + d1 = e << ShF; + d0 = (d1 + 0x80000) >> 20; + if (d0 > 7) d0 = 7; + if (d0 < -8) d0 = -8; + four_bitPtr[i] = d0 & 0xF; + d0 = d0 << (20 - ShF); + + tS4 = tS3; tS3 = tS2; tS2 = tS1; tS1 = d0 - e; + i++; + } + } + + public struct VAGFile + { + public uint Size; + public uint Version; + public uint SampleRate; + public ushort Channels; + public string Name; + public byte[] Flags; + public int[] Data; + public int* DataPtr; + public int* OriginDataPtr; + } + + private int* HEVAG1Ptr, HEVAG2Ptr, HEVAG3Ptr, HEVAG4Ptr; + + private readonly int[] HEVAG1 = new int[] + { + 0, 7680, 14720, 12544, 15616, 14731, 14507, 13920, + 13133, 12028, 10764, 9359, 7832, 6201, 4488, 2717, + 910, -910, -2717, -4488, -6201, -7832, -9359, -10764, + -12028, -13133, -13920, -14507, -14731, 5376, -6400, -10496, + -167, -7430, -8001, 6018, 3798, -8237, 9199, 13021, + 13112, -1668, 7819, 9571, 10032, -4745, -5896, -1193, + 2783, -7334, 6127, 9457, 7876, -7172, -7358, -9170, + -2638, 1873, 9214, 13204, 12437, -2653, 9331, 1642, + 4246, -8988, -2562, 3182, 7937, 10069, 8400, -8529, + 9477, 75, -9143, -7270, -2740, 8993, 13101, 9543, + 5272, -7696, 7309, 10275, 10940, 24, -8122, -8511, + 326, 8895, 12073, 8729, 12950, 10038, 9385, -4720, + 7869, 2450, 10192, 11313, 10154, 9638, 3854, 6699, + 11082, -1026, 10396, 10287, 7953, 12689, 6641, -2348, + 9290, 4633, 11247, 9807, 9736, 8440, 9307, 1698, + 10214, 8390, 7201, -88, 6193, 12325, 13064, 5333, + }; + + private readonly int[] HEVAG2 = new int[] + { + 0, 0, -6656, -7040, -7680, -7059, -7366, -7522, + -7680, -7680, -7680, -7680, -7680, -7680, -7680, -7680, + -7680, -7680, -7680, -7680, -7680, -7680, -7680, -7680, + -7680, -7680, -7522, -7366, -7059, -9216, -7168, -7424, + -2722, -2221, -3166, -4750, -6946, -2596, 1982, -3044, + -4487, -3744, -4328, -1336, -2562, -4122, 2378, -9117, + -7108, -2062, -2577, -1858, -4483, -1795, -2102, -3509, + -2647, 9183, 1859, -3012, -4792, -1144, -1048, -620, + -7585, -3891, -2735, -483, -3844, -2609, -3297, -2775, + -1882, -2241, -4160, -1958, 3745, 1948, -2835, -1961, + -4270, -3383, 2523, -2867, -3721, -310, -2411, -3067, + -3846, 2194, -1876, -3423, -3847, -2570, -2757, -5006, + -4326, -8597, -2763, -4213, -2716, -1417, -4554, -5659, + -3908, -9810, -3746, 988, 3878, -3375, 3166, -7354, + -4039, -6403, -4125, -2284, -1536, -3436, -1021, -9025, + -2791, 3248, 3316, -7809, -5189, -1290, -4075, 2999, + }; + + private readonly int[] HEVAG3 = new int[] + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3328, -3328, -3584, + -494, -2298, -2814, 2649, 3875, -2071, -1382, -3792, + -2250, -6456, 2111, -757, 300, -5486, -4787, -1237, + -1575, -2212, -315, 102, 2126, -2069, -2233, -2674, + -1929, 1860, -1124, -4139, -256, -3182, -828, -946, + -533, -2807, -1730, -714, 2821, 314, 1551, -2432, + 108, -298, -2963, -2156, 5936, -683, -3854, 130, + 3124, -2907, 434, 391, 665, -1262, -2311, -2337, + 419, -541, -2017, 1674, -3007, 302, 1008, -2852, + 2135, 1299, 360, 833, 345, -737, 2843, 2249, + 728, -805, 1367, -1915, -764, -3354, 231, -1944, + 1885, 1748, 802, 219, -706, 1562, -835, 688, + 368, -758, 46, -538, 2760, -3284, -2824, 775, + }; + + private readonly int[] HEVAG4 = new int[] + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -3072, -2304, -1024, + -541, 424, 289, -1298, -1216, 227, -2316, 1267, + 1665, 840, -506, 487, 199, -1493, -6947, -3114, + -1447, 446, -18, 258, -538, 482, 440, -391, + -1637, -5746, -2427, 1370, 622, -6878, 507, -4229, + -2259, 44, -1899, -1421, -1019, 195, -155, -336, + 256, -6937, 5, 460, -1089, -2704, 1055, 250, + -3157, -456, -2461, 172, 97, 320, -271, 163, + -933, -2880, -601, -169, 1946, 198, 41, -1161, + -501, -2780, 181, 53, 185, 482, -3397, -1074, + 80, -3462, -96, -1437, -3263, 2079, -2089, -4122, + -246, -1619, 61, 222, 473, -176, 509, -3037, + 179, -2989, -2614, -4571, -1245, 253, 1877, -1132, + }; + } +} diff --git a/KKdSoundLib/WAV.cs b/KKdSoundLib/WAV.cs new file mode 100644 index 0000000..ea0f633 --- /dev/null +++ b/KKdSoundLib/WAV.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace KKdSoundLib +{ + public static class WAV + { + public struct Header + { + public uint Size; + public uint SampleRate; + public uint HeaderSize; + public uint ChannelMask; + public bool IsSupported; + public ushort Bytes; + public ushort Format; + public ushort Channels; + } + } +} diff --git a/PD_Tool.sln b/PD_Tool.sln new file mode 100644 index 0000000..4999230 --- /dev/null +++ b/PD_Tool.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2003 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PD_Tool", "PD_Tool\PD_Tool.csproj", "{7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KKdMainLib", "KKdMainLib\KKdMainLib.csproj", "{2BA7EFC6-91D1-8BBC-C487-06C7F36CC789}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KKdSoundLib", "KKdSoundLib\KKdSoundLib.csproj", "{D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}.Release|Any CPU.Build.0 = Release|Any CPU + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789}.Release|Any CPU.Build.0 = Release|Any CPU + {D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2FEE4F36-9B44-B3ED-5542-3608014A0B4D} + EndGlobalSection +EndGlobal diff --git a/PD_Tool/PD_Tool.csproj b/PD_Tool/PD_Tool.csproj new file mode 100644 index 0000000..a7ef501 --- /dev/null +++ b/PD_Tool/PD_Tool.csproj @@ -0,0 +1,69 @@ + + + + + Debug + AnyCPU + {7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E} + Exe + PD_Tool + PD_Tool + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + ..\build\ + DEBUG;TRACE + prompt + 4 + true + + + AnyCPU + embedded + true + ..\build\ + TRACE + prompt + 4 + true + true + + + + + + + + + + + + + + + + + + + + + + + + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789} + KKdMainLib + False + + + {D8A3F2D7-10CC-5723-EC9A-45D3B9C2DF77} + KKdSoundLib + + + + \ No newline at end of file diff --git a/PD_Tool/Program.cs b/PD_Tool/Program.cs new file mode 100644 index 0000000..eb86263 --- /dev/null +++ b/PD_Tool/Program.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using KKdMainLib.IO; +using MSIO = System.IO; +using KKdMain = KKdMainLib.Main; +using KKdFARC = KKdMainLib.FARC; + +namespace PD_Tool +{ + public static class Program + { + public static string function = ""; + public static List ProcessedFiles = new List(); + + [STAThread] + public static void Main(string[] args) + { + Console.Title = "PD_Tool"; + + if (args.Length == 0) + { + while (function != "Q") MainMenu(); + Exit(); + } + + string header; + Stream reader; + KKdFARC Farc; + + foreach (string arg in args) + { + Farc = new KKdFARC(); + if (MSIO.Directory.Exists(arg)) Farc.Pack(arg); + else if (MSIO.File.Exists(arg) && MSIO.Path.GetExtension(arg) == ".farc") Farc.UnPack(arg, true); + else if (MSIO.File.Exists(arg)) + { + reader = File.OpenReader(arg); + header = reader.ReadString(8); + reader.Close(); + if (header.ToUpper() == "DIVAFILE") DIVAFILE.Decrypt(arg); + } + } + Exit(); + } + + private static void MainMenu() + { + Console.Title = "PD_Tool"; + Console.Clear(); + + KKdMain.ConsoleDesign(true); + KKdMain.ConsoleDesign(" Choose action:"); + KKdMain.ConsoleDesign(false); + KKdMain.ConsoleDesign("1. Extract FARC Archive"); + KKdMain.ConsoleDesign("2. Create FARC Archive"); + KKdMain.ConsoleDesign("3. Decrypt from DIVAFILE"); + KKdMain.ConsoleDesign("4. Encrypt to DIVAFILE"); + KKdMain.ConsoleDesign("5. DB_Tools"); + KKdMain.ConsoleDesign("6. Converting Tools"); + KKdMain.ConsoleDesign(false); + KKdMain.ConsoleDesign("Q. Quit"); + KKdMain.ConsoleDesign(false); + KKdMain.ConsoleDesign(true); + Console.WriteLine(); + + function = Console.ReadLine().ToUpper(); + bool isNumber = int.TryParse(function, out int result); + if (isNumber) Functions(); + } + + private static void Functions() + { + Console.Clear(); + if (function == "1" || function == "2") + FARC.Processor(function == "1"); + else if (function == "3" || function == "4") + { + KKdMain.Choose(1, "", out string[] FileNames); + foreach (string FileName in FileNames) DIVAFILE.Decrypt(FileName); + } + else if (function == "5") DataBase.Processor(); + else if (function == "6") + { + Console.Clear(); + Console.Title = "Converter Tools"; + KKdMain.ConsoleDesign(true); + KKdMain.ConsoleDesign(" Choose tool:"); + KKdMain.ConsoleDesign(false); + KKdMain.ConsoleDesign("1. A3DA Converter"); + KKdMain.ConsoleDesign("2. DEX Converter"); + KKdMain.ConsoleDesign("3. DIVA Converter"); + KKdMain.ConsoleDesign("4. STR Converter"); + KKdMain.ConsoleDesign("5. VAG Converter"); + KKdMain.ConsoleDesign(false); + KKdMain.ConsoleDesign("R. Return to Main Menu"); + KKdMain.ConsoleDesign("Q. Quit"); + KKdMain.ConsoleDesign(false); + KKdMain.ConsoleDesign(true); + Console.WriteLine(); + string Function = Console.ReadLine(); + Console.Clear(); + if (Function == "1") Tools.A3D.Processor(); + else if (Function == "2") Tools.DEX.Processor(); + else if (Function == "3") Tools.DIV.Processor(); + else if (Function == "4") Tools.STR.Processor(); + else if (Function == "5") Tools.VAG.Processor(); + else function = Function; + } + } + + public static void Exit() => Environment.Exit(0); + } +} \ No newline at end of file diff --git a/PD_Tool/Properties/AssemblyInfo.cs b/PD_Tool/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b6199a7 --- /dev/null +++ b/PD_Tool/Properties/AssemblyInfo.cs @@ -0,0 +1,15 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("PD_Tool")] +[assembly: AssemblyDescription("A simple tool for working with Project Diva A/DT/F/AFT/F2/X/FT files")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PD_Tool")] +[assembly: AssemblyCopyright("Copyright korenkonder © 2017-2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: Guid("7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E")] +[assembly: AssemblyVersion("0.4.5.7")] +[assembly: AssemblyFileVersion("0.4.5.7")] diff --git a/PD_Tool/classes/DIVAFILE.cs b/PD_Tool/classes/DIVAFILE.cs new file mode 100644 index 0000000..8473d0d --- /dev/null +++ b/PD_Tool/classes/DIVAFILE.cs @@ -0,0 +1,34 @@ +using KKdMainLib; +using KKdMainLib.IO; + +namespace PD_Tool +{ + public class DIVAFILE + { + public static void Decrypt(string file) + { + Stream reader = File.OpenReader(file); + if (reader.ReadInt64() != 0x454C494641564944) + { + reader.Close(); + Encrypt(file); + return; + } + reader.Close(); + file.Decrypt(); + } + + public static void Encrypt(string file) + { + Stream reader = File.OpenReader(file); + if (reader.ReadInt64() == 0x454C494641564944) + { + reader.Close(); + Decrypt(file); + return; + } + + file.Encrypt(); + } + } +} diff --git a/PD_Tool/classes/DataBase.cs b/PD_Tool/classes/DataBase.cs new file mode 100644 index 0000000..e624084 --- /dev/null +++ b/PD_Tool/classes/DataBase.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using KKdMainLib; +using KKdMainLib.DB; + +namespace PD_Tool +{ + public class DataBase + { + public static void Processor() + { + Console.Title = "DB Converter"; + Console.Clear(); + Main.ConsoleDesign(true); + Main.ConsoleDesign(" Choose type of DataBase file:"); + Main.ConsoleDesign(false); + Main.ConsoleDesign("1. Auth DB Converter"); + Main.ConsoleDesign(false); + Main.ConsoleDesign(true); + Console.WriteLine(); + string format = Console.ReadLine(); + if (format == "1") AuthDBProcessor(); + } + + public static void AuthDBProcessor() + { + Console.Title = "Auth DB Converter"; + Auth Auth = new Auth(); + Main.Choose(1, "bin", out string[] FileNames); + if (FileNames.Length < 1) return; + string filepath = ""; + string ext = ""; + + foreach (string file in FileNames) + { + Console.Title = "Auth: DB Converter: " + Path.GetFileNameWithoutExtension(file); + Auth = new Auth(); + ext = Path.GetExtension(file).ToLower(); + filepath = file.Replace(Path.GetExtension(file), ""); + + if (ext == ".bin") + { + Auth.BINReader (filepath); + Auth.MsgPackWriter(filepath); + } + else if (ext == ".mp") + { + Auth.MsgPackReader(filepath); + Auth.BINWriter (filepath); + } + } + } + } +} diff --git a/PD_Tool/classes/FARC.cs b/PD_Tool/classes/FARC.cs new file mode 100644 index 0000000..0922d31 --- /dev/null +++ b/PD_Tool/classes/FARC.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using KKdMainLib; +using KKdFARC = KKdMainLib.FARC; + +namespace PD_Tool +{ + public class FARC + { + public static void Processor(bool Extract) + { + KKdFARC FARC = new KKdFARC(); + Console.Clear(); + if (Extract) + { + Console.Title = "FARC Extractor"; + Main.Choose(1, "farc", out string[] FileNames); + foreach (string FileName in FileNames) + if (FileName != "" && File.Exists(FileName)) + FARC.UnPack(FileName); + } + else + { + string file = Main.Choose(2, "", out string[] FileNames); + Console.Clear(); + Console.Title = "FARC Creator"; + if (file != "") + { + Main.ConsoleDesign(true); + Main.ConsoleDesign(" Choose type of created FARC:"); + Main.ConsoleDesign(false); + Main.ConsoleDesign("1. FArc [DT/DT2nd/DTex/F/F2nd/X]"); + Main.ConsoleDesign("2. FArC [DT/DT2nd/DTex/F/F2nd/X] (Compressed)"); + Main.ConsoleDesign("3. FARC [F/F2nd/X] (Compressed)"); + Main.ConsoleDesign("4. FARC [FT] (Compressed)"); + Main.ConsoleDesign(false); + Main.ConsoleDesign("Note: Creating FT FARCs currently not supported."); + Main.ConsoleDesign(false); + Main.ConsoleDesign(true); + Console.WriteLine(); + Console.WriteLine("Choosed folder: {0}", file); + Console.WriteLine(); + int.TryParse(Console.ReadLine(), out int type); + if (type == 1) FARC.Signature = KKdFARC.Farc.FArc; + else if (type == 3) FARC.Signature = KKdFARC.Farc.FARC; + else FARC.Signature = KKdFARC.Farc.FArC; + Console.Clear(); + Console.Title = "FARC Creator - Directory: " + Path.GetDirectoryName(file); + FARC.Pack(file); + } + } + } + } +} diff --git a/PD_Tool/classes/Tools/A3D.cs b/PD_Tool/classes/Tools/A3D.cs new file mode 100644 index 0000000..72d3f2c --- /dev/null +++ b/PD_Tool/classes/Tools/A3D.cs @@ -0,0 +1,82 @@ +using System; +using KKdMainLib; +using KKdMainLib.IO; +using MSIO = System.IO; +using KKdA3DA = KKdMainLib.A3DA.A3DA; + +namespace PD_Tool.Tools +{ + class A3D + { + public static void Processor() + { + Console.Title = "A3DA Converter"; + Main.Choose(1, "a3da", out string[] FileNames); + if (FileNames.Length < 1) return; + string filepath = ""; + string ext = ""; + + bool MP = true; + foreach (string file in FileNames) + if (file.EndsWith(".mp" )) { MP = false; break; } + + Main.Format Format = Main.Format.NULL; + if (!MP) + { + Console.Clear(); + Main.ConsoleDesign(true); + Main.ConsoleDesign(" Choose type of format to export:"); + Main.ConsoleDesign(false); + Main.ConsoleDesign("1. DT PS3"); + Main.ConsoleDesign("2. F PS3/PSV"); + Main.ConsoleDesign("3. FT PS4"); + Main.ConsoleDesign("4. F2nd PS3/PSV"); + Main.ConsoleDesign("5. MGF PSV"); + Main.ConsoleDesign("6. X PS4/PSV"); + Main.ConsoleDesign(false); + Main.ConsoleDesign(true); + Console.WriteLine(); + string format = Console.ReadLine(); + if (format == "1") Format = Main.Format.DT ; + else if (format == "2") Format = Main.Format.F ; + else if (format == "3") Format = Main.Format.FT ; + else if (format == "4") Format = Main.Format.F2LE; + else if (format == "5") Format = Main.Format.MGF ; + else if (format == "6") Format = Main.Format.X ; + else return; + } + + KKdA3DA A; + foreach (string file in FileNames) + try + { + ext = MSIO.Path.GetExtension(file); + filepath = file.Replace(ext, ""); + ext = ext.ToLower(); + Console.Title = "A3DA Converter: " + + MSIO.Path.GetFileNameWithoutExtension(file); + A = new KKdA3DA(); + if (ext == ".a3da") + { + A.A3DAReader (filepath); + A.MsgPackWriter(filepath); + } + else if (ext == ".mp" ) + { + A.MsgPackReader(filepath); + A.IO = File.OpenWriter(filepath + ".a3da", true); + if (A.Data.Header.Format < Main.Format.F2LE) + A.Data._.CompressF16 = Format == Main.Format.MGF ? 2 : 1; + A.Data.Header.Format = Format; + + if (A.Data.Header.Format > Main.Format.DT && A.Data.Header.Format != Main.Format.FT) + A.A3DCWriter(filepath); + else + A.A3DAWriter(); + } + } + catch (Exception e) + { Console.WriteLine(e); } + } + } +} diff --git a/PD_Tool/classes/Tools/DEX.cs b/PD_Tool/classes/Tools/DEX.cs new file mode 100644 index 0000000..ac552ba --- /dev/null +++ b/PD_Tool/classes/Tools/DEX.cs @@ -0,0 +1,61 @@ +using System; +using KKdMainLib; +using MSIO = System.IO; +using KKdDEX = KKdMainLib.DEX; + +namespace PD_Tool.Tools +{ + public class DEX + { + public static void Processor() + { + Console.Title = "DEX Converter"; + KKdDEX DEX; + Main.Choose(1, "dex", out string[] FileNames); + if (FileNames.Length < 1) return; + string filepath = ""; + string ext = ""; + + bool MP = true; + foreach (string file in FileNames) + if (file.EndsWith(".mp" )) + { MP = false; break; } + + Console.Clear(); + string format = ""; + Main.ConsoleDesign(true); + Main.ConsoleDesign(" Choose type of exporting file:"); + Main.ConsoleDesign(false); + Main.ConsoleDesign("1. F/FT PS3/PS4/PSVita"); + Main.ConsoleDesign("2. F2nd PS3/PSVita"); + Main.ConsoleDesign("3. X PS4/PSVita"); + if (MP) Main.ConsoleDesign("9. MessagePack"); + Main.ConsoleDesign(false); + Main.ConsoleDesign(true); + Console.WriteLine(); + format = Console.ReadLine(); + + Main.Format Format = Main.Format.NULL; + if (format == "1") Format = Main.Format.F ; + else if (format == "2") Format = Main.Format.F2LE; + else if (format == "3") Format = Main.Format.X ; + else if (format == "9" && MP ) Format = Main.Format.NULL; + else return; + + foreach (string file in FileNames) + { + DEX = new KKdDEX(); + ext = MSIO.Path.GetExtension(file).ToLower(); + filepath = file.Replace(MSIO.Path.GetExtension(file), ""); + + if (ext == ".bin" || ext == ".dex") + DEX.DEXReader(filepath, ext); + else DEX.MsgPackReader(filepath); + + if (Format > Main.Format.NULL) + DEX.DEXWriter(filepath, Format); + else DEX.MsgPackWriter(filepath); + } + } + } +} diff --git a/PD_Tool/classes/Tools/DIV.cs b/PD_Tool/classes/Tools/DIV.cs new file mode 100644 index 0000000..30e768b --- /dev/null +++ b/PD_Tool/classes/Tools/DIV.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using KKdMainLib; +using KKdSoundLib; + +namespace PD_Tool.Tools +{ + public class DIV + { + public static void Processor() + { + Console.Title = "DIVA Converter"; + Main.Choose(1, "diva", out string[] FileNames); + + DIVA DIVA; + foreach (string file in FileNames) + try + { + string filepath = file.Replace(Path.GetExtension(file), ""); + string ext = Path.GetExtension(file); + Console.Title = "DIVA Converter: " + Path.GetFileNameWithoutExtension(file); + DIVA = new DIVA(filepath); + switch (ext.ToLower()) + { + case ".diva": + DIVA.DIVAReader(); + break; + case ".wav": + DIVA.DIVAWriter(); + break; + } + GC.Collect(); + } + catch (Exception e) { Console.WriteLine(e.Message); } + + } + } +} \ No newline at end of file diff --git a/PD_Tool/classes/Tools/STR.cs b/PD_Tool/classes/Tools/STR.cs new file mode 100644 index 0000000..4ce4089 --- /dev/null +++ b/PD_Tool/classes/Tools/STR.cs @@ -0,0 +1,39 @@ +using System; +using KKdMainLib; +using MSIO = System.IO; +using KKdSTR = KKdMainLib.STR; + +namespace PD_Tool.Tools +{ + public class STR + { + public static void Processor() + { + Console.Title = "STR Converter"; + Main.Choose(1, "str", out string[] FileNames); + + KKdSTR Data; + string filepath = ""; + string ext = ""; + foreach (string file in FileNames) + { + filepath = file.Replace(MSIO.Path.GetExtension(file), ""); + ext = MSIO.Path.GetExtension(file).ToLower(); + Data = new KKdSTR(); + + Console.Title = "PD_Tool: Converter Tools: STR Reader: " + + MSIO.Path.GetFileNameWithoutExtension(file); + if (ext == ".str" || ext == ".bin") + { + Data.STRReader (filepath, ext); + Data.MsgPackWriter(filepath); + } + else if (ext == ".mp") + { + Data.MsgPackReader(filepath); + Data.STRWriter (filepath); + } + } + } + } +} diff --git a/PD_Tool/classes/Tools/VAG.cs b/PD_Tool/classes/Tools/VAG.cs new file mode 100644 index 0000000..63bfe95 --- /dev/null +++ b/PD_Tool/classes/Tools/VAG.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using KKdMainLib; +using KKdVAG = KKdSoundLib.VAG; + +namespace PD_Tool.Tools +{ + public class VAG + { + public static void Processor() + { + Console.Title = "VAG Converter"; + Main.Choose(1, "vag", out string[] FileNames); + bool InputWAV = false; + foreach (string file in FileNames) + if (Path.GetExtension(file) == ".wav") + InputWAV = true; + + bool HE_VAG = true; + if (InputWAV) + { + Console.Clear(); + Main.ConsoleDesign(true); + Main.ConsoleDesign(" Choose type of format to export:"); + Main.ConsoleDesign(false); + Main.ConsoleDesign("1. VAG (Downmix to 1 ch)"); + Main.ConsoleDesign("2. HEVAG"); + Main.ConsoleDesign(false); + Main.ConsoleDesign(true); + Console.WriteLine(); + string format = Console.ReadLine(); + HE_VAG = format == "2"; + } + + KKdVAG VAG; + foreach (string file in FileNames) + try + { + string ext = Path.GetExtension(file); + string filepath = file.Remove(file.Length - ext.Length); + Console.Title = "VAG Converter: " + + Path.GetFileNameWithoutExtension(file); + VAG = new KKdVAG() { file = filepath }; + switch (ext.ToLower()) + { + case ".vag": + VAG.VAGReader(); + VAG.WAVWriter(); + break; + case ".wav": + VAG.WAVReader(); + VAG.VAGWriter(HE_VAG); + break; + } + } + catch (Exception e) { Console.WriteLine(e.Message); } + } + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d64ffa1 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# PD_Tool +A simple tool for working with Project Diva DT/FT/F/F2/X files + +# Dependencies: ++ `.NET Framework 4.6.1`: Required to run/build PD_Tool C# project. + +# Tools: +- `FARC Extract/Create` +- `DIVAFILE Encrypt/Decrypt` +- `DB_Tools` + - `Auth DB Converter` +- `Converting Tools` + - `A3DA Converter` + - `DEX Converter` + - `DIVA Converter` + - `STR Converter` + - `VAG Converter` + \ No newline at end of file