From 6e2f5746b0b810eced9a7a04f99815e7bc9e31f5 Mon Sep 17 00:00:00 2001 From: KujiKita Date: Fri, 12 Jul 2019 06:14:51 +0300 Subject: [PATCH] Release v0.4.7.0 A3DA, Aet, AetDB, AuthDB, DataBank, DEX, DIVA, DIVAFILE, FARC, STR, VAG --- {KKdMainLib => KKdBaseLib}/DCC.cs | 7 +- KKdBaseLib/Extensions.cs | 233 ++++++++++++++++++ {KKdMainLib/Types => KKdBaseLib}/Half.cs | 73 +++--- {KKdMainLib/Types => KKdBaseLib}/IKeyFrame.cs | 23 +- KKdBaseLib/KKdBaseLib.csproj | 61 +++++ {KKdMainLib/Types => KKdBaseLib}/KKdList.cs | 10 +- KKdBaseLib/Pointer.cs | 26 ++ KKdBaseLib/Properties/AssemblyInfo.cs | 15 ++ {KKdMainLib => KKdBaseLib}/Text.cs | 4 +- {KKdMainLib/Types => KKdBaseLib}/Vector.cs | 2 +- KKdBaseLib/Vector3.cs | 77 ++++++ KKdBaseLib/Vector4.cs | 77 ++++++ KKdBaseLib/bin/KKdBaseLib.dll | Bin 0 -> 32768 bytes .../KKdBaseLib.csproj.CoreCompileInputs.cache | 1 + .../KKdBaseLib.csproj.FileListAbsolute.txt | 3 + KKdBaseLib/obj/Release/KKdBaseLib.dll | Bin 0 -> 32768 bytes KKdMainLib/A3DA.cs | 20 +- KKdMainLib/Aet.cs | 12 +- KKdMainLib/DB/Aet.cs | 1 + KKdMainLib/DB/Spr.cs | 1 + KKdMainLib/DEX.cs | 14 +- KKdMainLib/DIVAFILE.cs | 54 ++-- KKdMainLib/DataBank.cs | 3 +- KKdMainLib/Extensions.cs | 181 ++++++++++++++ KKdMainLib/F2nd/Header.cs | 22 ++ KKdMainLib/F2nd/POF.cs | 14 ++ KKdMainLib/F2nd/Struct.cs | 87 +++++++ KKdMainLib/FARC.cs | 7 +- KKdMainLib/IO/IOExtensions.cs | 14 +- KKdMainLib/IO/Stream.cs | 2 +- KKdMainLib/KKdMainLib.csproj | 20 +- KKdMainLib/Main.cs | 56 +---- KKdMainLib/MathExtensions.cs | 226 ----------------- KKdMainLib/MessagePack/IO.cs | 2 +- KKdMainLib/MessagePack/JSONIO.cs | 22 +- KKdMainLib/MessagePack/MsgPack.cs | 2 +- KKdMainLib/PDHeader.cs | 79 ------ KKdMainLib/POF.cs | 125 ---------- KKdMainLib/Properties/AssemblyInfo.cs | 4 +- KKdMainLib/STR.cs | 212 ++++++++-------- KKdMainLib/Types/Pointer.cs | 43 ---- KKdSoundLib/DIVA.cs | 2 +- KKdSoundLib/Extensions.cs | 2 +- KKdSoundLib/KKdSoundLib.csproj | 4 + KKdSoundLib/Properties/AssemblyInfo.cs | 4 +- KKdSoundLib/VAG.cs | 2 +- PD_Tool.sln | 16 +- PD_Tool/PD_Tool.csproj | 4 + PD_Tool/Properties/AssemblyInfo.cs | 4 +- PD_Tool/classes/FARC.cs | 2 +- PD_Tool/classes/Tools/DB.cs | 6 - 51 files changed, 1085 insertions(+), 796 deletions(-) rename {KKdMainLib => KKdBaseLib}/DCC.cs (95%) create mode 100644 KKdBaseLib/Extensions.cs rename {KKdMainLib/Types => KKdBaseLib}/Half.cs (59%) rename {KKdMainLib/Types => KKdBaseLib}/IKeyFrame.cs (87%) create mode 100644 KKdBaseLib/KKdBaseLib.csproj rename {KKdMainLib/Types => KKdBaseLib}/KKdList.cs (91%) create mode 100644 KKdBaseLib/Pointer.cs create mode 100644 KKdBaseLib/Properties/AssemblyInfo.cs rename {KKdMainLib => KKdBaseLib}/Text.cs (86%) rename {KKdMainLib/Types => KKdBaseLib}/Vector.cs (97%) create mode 100644 KKdBaseLib/Vector3.cs create mode 100644 KKdBaseLib/Vector4.cs create mode 100644 KKdBaseLib/bin/KKdBaseLib.dll create mode 100644 KKdBaseLib/obj/Release/KKdBaseLib.csproj.CoreCompileInputs.cache create mode 100644 KKdBaseLib/obj/Release/KKdBaseLib.csproj.FileListAbsolute.txt create mode 100644 KKdBaseLib/obj/Release/KKdBaseLib.dll create mode 100644 KKdMainLib/Extensions.cs create mode 100644 KKdMainLib/F2nd/Header.cs create mode 100644 KKdMainLib/F2nd/POF.cs create mode 100644 KKdMainLib/F2nd/Struct.cs delete mode 100644 KKdMainLib/MathExtensions.cs delete mode 100644 KKdMainLib/PDHeader.cs delete mode 100644 KKdMainLib/POF.cs delete mode 100644 KKdMainLib/Types/Pointer.cs diff --git a/KKdMainLib/DCC.cs b/KKdBaseLib/DCC.cs similarity index 95% rename from KKdMainLib/DCC.cs rename to KKdBaseLib/DCC.cs index fce29fc..f17f755 100644 --- a/KKdMainLib/DCC.cs +++ b/KKdBaseLib/DCC.cs @@ -1,8 +1,6 @@ //Original research by Samyuu -using KKdMainLib.IO; - -namespace KKdMainLib +namespace KKdBaseLib { public static class DCC //Databank_Checksum_Calculator { @@ -41,14 +39,11 @@ namespace KKdMainLib 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, }; - public static ushort CalculateChecksum(string file) => CalculateChecksum(File.ReadAllBytes(file)); - public static ushort CalculateChecksum(byte[] data) { ushort result = 0xFFFF; for (int i = 0; i < data.Length; i++) result = (ushort)(ChecksumLookupTable[(result >> 8) ^ data[i]] ^ (result << 8)); - return result; } } diff --git a/KKdBaseLib/Extensions.cs b/KKdBaseLib/Extensions.cs new file mode 100644 index 0000000..0c6b00e --- /dev/null +++ b/KKdBaseLib/Extensions.cs @@ -0,0 +1,233 @@ +using System; + +namespace KKdBaseLib +{ + public static unsafe class Extensions + { + private const double RadPi = 180 / Math.PI; + public static double ToDegrees(this double val) => val * RadPi; + public static double ToRadians(this double val) => val / RadPi; + + public static double Acos (this double d ) => Math.Acos (d ); + public static double Asin (this double d ) => Math.Asin (d ); + public static double Atan (this double d ) => Math.Atan (d ); + public static double Aсtg (this double d ) => 1 / Math.Atan (d ); + public static double Cos (this double d ) => Math.Cos (d ); + public static double Cosh (this double val) => Math.Cosh (val); + public static double Sin (this double a ) => Math.Sin (a ); + public static double Sinh (this double val) => Math.Sinh (val); + public static double Tan (this double a ) => Math.Tan (a ); + public static double Tanh (this double val) => Math.Tanh (val); + public static double Ctg (this double a ) => 1 / Math.Tan (a ); + public static double Ctgh (this double val) => 1 / Math.Tanh (val); + + public static double Abs (this double val) => Math.Abs (val); + public static double Ceiling(this double a ) => Math.Ceiling(a ); + public static double Exp (this double d ) => Math.Exp (d ); + public static double Log (this double d ) => Math.Log (d ); + public static double Log10 (this double d ) => Math.Log10 (d ); + public static double Round (this double d ) => Math.Round (d ); + public static int Sign (this double val) => Math.Sign (val); + public static double Sqrt (this double d ) => Math.Sqrt (d ); + + + public static double Atan2(this double y , double x ) => Math.Atan2(y , x ); + public static double Log (this double val , double newBase) => Math.Log (val , newBase); + public static double Max (this double val1, double val2 ) => Math.Max (val1, val2 ); + public static double Min (this double val1, double val2 ) => Math.Min (val1, val2 ); + public static double Pow (this double x , double y ) => Math.Pow (x , y ); + public static double Round(this double val , int d ) => Math.Round(val , d ); + + public static float ToDegrees(this float val) => (float)(val * RadPi); + public static float ToRadians(this float val) => (float)(val / RadPi); + + public static float Acos (this float d ) => (float) Math.Acos (d ) ; + public static float Asin (this float d ) => (float) Math.Asin (d ) ; + public static float Atan (this float d ) => (float) Math.Atan (d ) ; + public static float Aсtg (this float d ) => (float)(1 / Math.Atan (d )); + public static float Cos (this float d ) => (float) Math.Cos (d ) ; + public static float Cosh (this float val) => (float) Math.Cosh (val) ; + public static float Sin (this float a ) => (float) Math.Sin (a ) ; + public static float Sinh (this float val) => (float) Math.Sinh (val) ; + public static float Tan (this float a ) => (float) Math.Tan (a ) ; + public static float Tanh (this float val) => (float) Math.Tanh (val) ; + public static float Ctg (this float a ) => (float)(1 / Math.Tan (a )); + public static float Ctgh (this float val) => (float)(1 / Math.Tanh (val)); + + public static float Abs (this float val) => Math.Abs (val) ; + public static float Ceiling(this float a ) => (float) Math.Ceiling(a ) ; + public static float Exp (this float d ) => (float) Math.Exp (d ) ; + public static float Log (this float d ) => (float) Math.Log (d ) ; + public static float Log10 (this float d ) => (float) Math.Log10 (d ) ; + public static float Round (this float d ) => (float) Math.Round (d ) ; + public static float Sqrt (this float d ) => (float) Math.Sqrt (d ) ; + + + public static float Atan2(this float y , float x ) => (float)Math.Atan2(y , x ); + public static float Log (this float val , float newBase) => (float)Math.Log (val , newBase); + public static float Max (this float val1, float val2 ) => Math.Max (val1, val2 ); + public static float Min (this float val1, float val2 ) => Math.Min (val1, val2 ); + public static float Pow (this float x , float y ) => (float)Math.Pow (x , y ); + public static float Round(this float val , int d ) => (float)Math.Round(val , d ); + + public static void FloorCeiling( ref double Value) => + Value = Value % 1 >= 0.5 ? (long)(Value + 0.5) : (long) Value; + + public static long FloorCeiling(this double Value) => + Value % 1 >= 0.5 ? (long)(Value + 0.5) : (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 byte* bufPtr = buf.GetPtr(); + + public static 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 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 > 0x0000007F) c = 0x0000007F; + else if (c < -0x00000080) c = -0x00000080; return ( sbyte)c; } + + public static byte CITB (this int c) + { if (c > 0x000000FF) c = 0x000000FF; + else if (c < 0x00000000) c = 0x00000000; return ( byte)c; } + + public static short CITS (this int c) + { if (c > 0x00007FFF) c = 0x00007FFF; + else if (c < -0x00008000) c = -0x00008000; return ( short)c; } + + public static ushort CITUS(this int c) + { if (c > 0x0000FFFF) c = 0x0000FFFF; + else if (c < 0x00000000) c = 0x00000000; return (ushort)c; } + + public static sbyte CFTSB(this float c) + { c = c.Round(); if (c > 0x0000007F) c = 0x0000007F; + else if (c < -0x00000080) c = -0x00000080; return ( sbyte)c; } + + public static byte CFTB (this float c) + { c = c.Round(); if (c > 0x000000FF) c = 0x000000FF; + else if (c < 0x00000000) c = 0x00000000; return ( byte)c; } + + public static short CFTS (this float c) + { c = c.Round(); if (c > 0x00007FFF) c = 0x00007FFF; + else if (c < -0x00008000) c = -0x00008000; return ( short)c; } + + public static ushort CFTUS(this float c) + { c = c.Round(); if (c > 0x0000FFFF) c = 0x0000FFFF; + else if (c < 0x00000000) c = 0x00000000; return (ushort)c; } + + public static int CFTI (this float c) + { c = c.Round(); return ( int)c; } + + public static uint CFTUI(this float c) + { c = c.Round(); return ( uint)c; } + + public static sbyte CFTSB(this double c) + { c = c.Round(); if (c > 0x0000007F) c = 0x0000007F; + else if (c < -0x00000080) c = -0x00000080; return ( sbyte)c; } + + public static byte CFTB (this double c) + { c = c.Round(); if (c > 0x000000FF) c = 0x000000FF; + else if (c < 0x00000000) c = 0x00000000; return ( byte)c; } + + public static short CFTS (this double c) + { c = c.Round(); if (c > 0x00007FFF) c = 0x00007FFF; + else if (c < -0x00008000) c = -0x00008000; return ( short)c; } + + public static ushort CFTUS(this double c) + { c = c.Round(); if (c > 0x0000FFFF) c = 0x0000FFFF; + else if (c < 0x00000000) c = 0x00000000; return (ushort)c; } + + public static int CFTI (this double c) + { c = c.Round(); if (c > 0x7FFFFFFF) c = 0x7FFFFFFF; + else if (c < -0x80000000) c = -0x80000000; return ( int)c; } + + public static uint CFTUI(this double c) + { c = c.Round(); if (c > 0xFFFFFFFF) c = 0xFFFFFFFF; + else if (c < 0x00000000) c = 0x00000000; return ( uint)c; } + + public static sbyte* GetPtr(this sbyte[] array) { fixed ( sbyte* tempPtr = array) return tempPtr; } + public static byte* GetPtr(this byte[] array) { fixed ( byte* tempPtr = array) return tempPtr; } + public static short* GetPtr(this short[] array) { fixed ( short* tempPtr = array) return tempPtr; } + public static ushort* GetPtr(this ushort[] array) { fixed (ushort* tempPtr = array) return tempPtr; } + public static int* GetPtr(this int[] array) { fixed ( int* tempPtr = array) return tempPtr; } + public static uint* GetPtr(this uint[] array) { fixed ( uint* tempPtr = array) return tempPtr; } + public static long* GetPtr(this long[] array) { fixed ( long* tempPtr = array) return tempPtr; } + public static ulong* GetPtr(this ulong[] array) { fixed ( ulong* tempPtr = array) return tempPtr; } + public static float* GetPtr(this float[] array) { fixed ( float* tempPtr = array) return tempPtr; } + public static double* GetPtr(this double[] array) { fixed (double* tempPtr = array) return tempPtr; } + + public static string ToString(this int d, bool IsBE) => + BitConverter.GetBytes((int)((long)d).Endian(4, IsBE)).ToASCII(); + + public static string ToString(this object d) + { + if (d == null) return "Null"; + else if (d is float F32) return ToString(F32); + else if (d is double F64) return ToString(F64); + return d.ToString(); + } + + private static readonly string NumberDecimalSeparator = + System.Globalization.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 sbyte? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this sbyte d) => d.ToString(); + public static string ToString(this byte? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this byte d) => d.ToString(); + public static string ToString(this short? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this short d) => d.ToString(); + public static string ToString(this ushort? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this ushort d) => d.ToString(); + public static string ToString(this int? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this int d) => d.ToString(); + public static string ToString(this uint? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this uint d) => d.ToString(); + public static string ToString(this long? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this long d) => d.ToString(); + public static string ToString(this ulong? d) => d.GetValueOrDefault().ToString(); + public static string ToString(this ulong d) => d.ToString(); + 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; } + } +} diff --git a/KKdMainLib/Types/Half.cs b/KKdBaseLib/Half.cs similarity index 59% rename from KKdMainLib/Types/Half.cs rename to KKdBaseLib/Half.cs index 9809672..5b176e6 100644 --- a/KKdMainLib/Types/Half.cs +++ b/KKdBaseLib/Half.cs @@ -1,6 +1,6 @@ using System; -namespace KKdMainLib.Types +namespace KKdBaseLib { public struct Half : IFormattable { @@ -34,49 +34,44 @@ namespace KKdMainLib.Types 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); + else if (val == double.NaN ) h._value = 0x7FFF; + else if (val == -double.NaN ) h._value = 0xFFFF; + else + { + ushort Sign = (ushort)(val < 0 ? 0x8000 : 0); + 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 = Math.Abs(x - exponent_max / Pow2) > + Math.Abs(x - exponent_min / Pow2) ? exponent_max : exponent_min; + ushort mantissa = (ushort)(i + MaxPow - 1); + h._value = (ushort)(Sign | ((mantissa & 0x001F) << 10) | (exponent & 0x03FF)); + return h; + } + if (val < 1) i--; + else i++; + } + h._value = (ushort)(Sign | 0x7C00); + } 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 = Math.Abs(x - exponent_max / Pow2) > - Math.Abs(x - exponent_min / Pow2) ? exponent_max : 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++; - } - - return i >= +0 ? (ushort)0x7C00 : (ushort)0xFC00; - } - - public override string ToString() => ((double)this).ToString(); + public override string ToString() => Extensions.ToString((double)this); public string ToString(string format, IFormatProvider formatProvider) => ((double)this).ToString(format, formatProvider); public override int GetHashCode() => base.GetHashCode(); diff --git a/KKdMainLib/Types/IKeyFrame.cs b/KKdBaseLib/IKeyFrame.cs similarity index 87% rename from KKdMainLib/Types/IKeyFrame.cs rename to KKdBaseLib/IKeyFrame.cs index 4e7bb4e..dc75763 100644 --- a/KKdMainLib/Types/IKeyFrame.cs +++ b/KKdBaseLib/IKeyFrame.cs @@ -1,4 +1,4 @@ -namespace KKdMainLib.Types +namespace KKdBaseLib { public interface IKeyFrame { @@ -27,9 +27,9 @@ public IKeyFrame Check() => this; public override string ToString() => - Main.ToString(Frame); + Extensions.ToString(Frame); public string ToString(bool Brackets) => - Main.ToString(Frame); + Extensions.ToString(Frame); } public struct KeyFrameT1 : IKeyFrame @@ -51,8 +51,8 @@ public override string ToString() => ToString(true); public string ToString(bool Brackets) => - (Brackets ? "(" : "") + Main.ToString(Frame) + "," + - Main.ToString(Value) + (Brackets ? ")" : ""); + (Brackets ? "(" : "") + Extensions.ToString(Frame) + "," + + Extensions.ToString(Value) + (Brackets ? ")" : ""); } public struct KeyFrameT2 : IKeyFrame @@ -81,16 +81,15 @@ public IKeyFrame Check() { - if (Value.Equals(default(TVal)) && Interpolation.Equals(default(TVal))) - return ToKeyFrameT0(); - else if (Value.Equals(default(TVal))) return ToKeyFrameT1(); + if (Value.Equals(default(TVal)) && Interpolation.Equals(default(TVal))) return ToKeyFrameT0(); + else if ( Interpolation.Equals(default(TVal))) return ToKeyFrameT1(); return this; } public override string ToString() => ToString(true); public string ToString(bool Brackets) => - (Brackets ? "(" : "") + Main.ToString(Frame) + "," + Main. - ToString(Value) + "," + Main.ToString(Interpolation) + (Brackets ? ")" : ""); + (Brackets ? "(" : "") + Extensions.ToString(Frame) + "," + Extensions. + ToString(Value) + "," + Extensions.ToString(Interpolation) + (Brackets ? ")" : ""); } public struct KeyFrameT3 : IKeyFrame @@ -123,8 +122,8 @@ public override string ToString() => ToString(true); public string ToString(bool Brackets) => - (Brackets ? "(" : "") + Main.ToString(Frame) + "," + Main.ToString(Value) + "," + - Main.ToString(Interpolation1) + "," + Main.ToString(Interpolation2) + (Brackets ? ")" : ""); + (Brackets ? "(" : "") + Extensions.ToString(Frame) + "," + Extensions.ToString(Value) + "," + + Extensions.ToString(Interpolation1) + "," + Extensions.ToString(Interpolation2) + (Brackets ? ")" : ""); public IKeyFrame ToKeyFrameT2(IKeyFrame Previous, out IKeyFrame Current) diff --git a/KKdBaseLib/KKdBaseLib.csproj b/KKdBaseLib/KKdBaseLib.csproj new file mode 100644 index 0000000..410cb91 --- /dev/null +++ b/KKdBaseLib/KKdBaseLib.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + {437F63F1-8C23-429E-AB14-38B85C9EDB16} + Library + KKdBaseLib + KKdBaseLib + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + true + 7.3 + IDE0044, IDE0045, IDE0046, IDE0055, IDE0059, IDE1006 + + + AnyCPU + embedded + true + bin\ + TRACE + prompt + 4 + true + true + 7.3 + IDE0044, IDE0045, IDE0046, IDE0055, IDE0059, IDE1006 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/KKdMainLib/Types/KKdList.cs b/KKdBaseLib/KKdList.cs similarity index 91% rename from KKdMainLib/Types/KKdList.cs rename to KKdBaseLib/KKdList.cs index 543a7e5..37ffe6e 100644 --- a/KKdMainLib/Types/KKdList.cs +++ b/KKdBaseLib/KKdList.cs @@ -1,6 +1,6 @@ using System.Collections; -namespace KKdMainLib.Types +namespace KKdBaseLib { public struct KKdList : IEnumerator, IEnumerable { @@ -64,8 +64,8 @@ namespace KKdMainLib.Types { if (IsNull) return; - for (int i = index; i < Count; i++) - array[i] = array[i + 1]; + for (int i = index + 1; i < Count; i++) + array[i - 1] = array[i]; } public void RemoveRange(int IndexStart, int IndexEnd) @@ -84,7 +84,7 @@ namespace KKdMainLib.Types if (IsNull) return false; for (int i = 0; i < Count; i++) if (array[i] == null && val == null) return true; - else if ( val == null) continue; + else if (array[i] == null || val == null) continue; else if (array[i] .Equals(val) ) return true; return false; } @@ -94,7 +94,7 @@ namespace KKdMainLib.Types if (IsNull) return -1; for (int i = 0; i < Count; i++) if (array[i] == null && val == null) return i; - else if ( val == null) continue; + else if (array[i] == null || val == null) continue; else if (array[i] .Equals(val) ) return i; return -1; } diff --git a/KKdBaseLib/Pointer.cs b/KKdBaseLib/Pointer.cs new file mode 100644 index 0000000..4bd391b --- /dev/null +++ b/KKdBaseLib/Pointer.cs @@ -0,0 +1,26 @@ +namespace KKdBaseLib +{ + public struct Pointer + { + public int Offset; + public T Value; + + public override string ToString() => Extensions.ToString(Value); + } + + public struct CountPointer + { + public int Count { get => Entries != null ? Entries.Length : 0; + set => Entries = new T[value]; } + public int Offset; + public T[] Entries; + + + public T this[int index] + { get => Count > 0 ? Entries[index] : default; + set { if (Count > 0) Entries[index] = value; } } + + public override string ToString() => Count < 1 ? "No Entries" : + Count == 1 ? Entries[0].ToString() : "Count: " + Count; + } +} \ No newline at end of file diff --git a/KKdBaseLib/Properties/AssemblyInfo.cs b/KKdBaseLib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8f23168 --- /dev/null +++ b/KKdBaseLib/Properties/AssemblyInfo.cs @@ -0,0 +1,15 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("KKdBaseLib")] +[assembly: AssemblyDescription("A base library")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("KKdBaseLib")] +[assembly: AssemblyCopyright("korenkonder © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: Guid("437F63F1-8C23-429E-AB14-38B85C9EDB16")] +[assembly: AssemblyVersion("0.0.1.0")] +[assembly: AssemblyFileVersion("0.0.1.0")] diff --git a/KKdMainLib/Text.cs b/KKdBaseLib/Text.cs similarity index 86% rename from KKdMainLib/Text.cs rename to KKdBaseLib/Text.cs index 5e5ea39..b29f9d3 100644 --- a/KKdMainLib/Text.cs +++ b/KKdBaseLib/Text.cs @@ -1,9 +1,11 @@ using System.Text; -namespace KKdMainLib +namespace KKdBaseLib { public static class Text { + public readonly static Encoding ShiftJIS = Encoding.GetEncoding(932); + public static string ToASCII(this byte[] Array) => Encoding.ASCII.GetString(Array ?? new byte[0]); public static string ToUTF8 (this byte[] Array) => Encoding.UTF8 .GetString(Array ?? new byte[0]); public static byte[] ToASCII(this string Data ) => Encoding.ASCII.GetBytes (Data ?? "" ); diff --git a/KKdMainLib/Types/Vector.cs b/KKdBaseLib/Vector.cs similarity index 97% rename from KKdMainLib/Types/Vector.cs rename to KKdBaseLib/Vector.cs index 431f9c1..feb652e 100644 --- a/KKdMainLib/Types/Vector.cs +++ b/KKdBaseLib/Vector.cs @@ -1,4 +1,4 @@ -namespace KKdMainLib.Types +namespace KKdBaseLib { public struct Vector2 { diff --git a/KKdBaseLib/Vector3.cs b/KKdBaseLib/Vector3.cs new file mode 100644 index 0000000..8e0ebd2 --- /dev/null +++ b/KKdBaseLib/Vector3.cs @@ -0,0 +1,77 @@ +namespace KKdBaseLib +{ + public struct Vector3 + { + public double X; + public double Y; + public double Z; + + public Vector3(double X, double Y, double Z) + { this.X = X; this.Y = Y; this.Z = Z; } + + public double Length => (X * X + Y * Y + Z * Z).Sqrt(); + public Vector3 Normalized => this = new Vector3() + { X = X * (1 / Length), Y = Y * (1 / Length), Z = Z * (1 / Length) }; + + public static Vector3 operator +(Vector3 left, Vector3 right) + { left.X += right.X; left.Y += right.Y; left.Z += right.Z; return left; } + public static Vector3 operator -(Vector3 left, Vector3 right) + { left.X -= right.X; left.Y -= right.Y; left.Z -= right.Z; return left; } + public static Vector3 operator -(Vector3 vec) + { vec.X = -vec.X; vec.Y = -vec.Y; vec.Z = -vec.Z; return vec; } + public static Vector3 operator *(Vector3 vec, double scale) + { vec.X *= scale ; vec.Y *= scale ; vec.Z *= scale ; return vec; } + public static Vector3 operator *( double scale, Vector3 vec) + { vec.X *= scale ; vec.Y *= scale ; vec.Z *= scale ; return vec; } + public static Vector3 operator *(Vector3 vec, Vector3 scale) + { vec.X *= scale.X; vec.Y *= scale.Y; vec.Z *= scale.Z; return vec; } + public static Vector3 operator /(Vector3 vec, double scale) + { vec.X /= scale ; vec.Y /= scale ; vec.Z /= scale ; return vec; } + public static Vector3 operator /(Vector3 vec, Vector3 scale) + { vec.X /= scale.X; vec.Y /= scale.Y; vec.Z /= scale.Z; return vec; } + public static bool operator ==(Vector3 A, Vector3 B) => A.Equals(B); + public static bool operator !=(Vector3 A, Vector3 B) => !A.Equals(B); + + public static double Distance (Vector3 left, Vector3 right) => + (right.X - left.X) * (right.X - left.X) + (right.Y - left.Y) * + (right.Y - left.Y) + (right.Z - left.Z) * (right.Z - left.Z).Sqrt(); + public static double DistanceSquared(Vector3 left, Vector3 right) => + (right.X - left.X) * (right.X - left.X) + (right.Y - left.Y) * + (right.Y - left.Y) + (right.Z - left.Z) * (right.Z - left.Z); + public static double Dot (Vector3 left, Vector3 right) => + (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z); + public static Vector3 Cross(Vector3 left, Vector3 right) => + new Vector3 { X = (left.Y * right.Z) - (left.Z * right.Y), + Y = (left.Z * right.X) - (left.X * right.Z), + Z = (left.X * right.Y) - (left.Y * right.X), }; + public static Vector3 Lerp (Vector3 a, Vector3 b, double blend) => + new Vector3 { X = blend * (b.X - a.X) + a.X, + Y = blend * (b.Y - a.Y) + a.Y, + Z = blend * (b.Z - a.Z) + a.Z }; + public static Vector3 Lerp (Vector3 a, Vector3 b, Vector3 blend) => + new Vector3 { X = blend.X * (b.X - a.X) + a.X, + Y = blend.Y * (b.Y - a.Y) + a.Y, + Z = blend.Z * (b.Z - a.Z) + a.Z }; + public Vector3 Round( ) => + new Vector3 { X = X.Round( ), Y = Y.Round( ), Z = Z.Round( ) }; + public Vector3 Round(int d) => + new Vector3 { X = X.Round(d), Y = Y.Round(d), Z = Z.Round(d) }; + + public override int GetHashCode() + { + unchecked + { + int hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + return hashCode; + } + } + public override bool Equals(object obj) => + obj is Vector3 vec ? Equals(vec) : false; + public bool Equals(Vector3 other) => + X == other.X && Y == other.Y && Z == other.Z; + + public override string ToString() => "X: " + X + "; Y: " + Y + "; Z: " + Z; + } +} diff --git a/KKdBaseLib/Vector4.cs b/KKdBaseLib/Vector4.cs new file mode 100644 index 0000000..e276265 --- /dev/null +++ b/KKdBaseLib/Vector4.cs @@ -0,0 +1,77 @@ +namespace KKdBaseLib +{ + public struct Vector4 + { + public double X; + public double Y; + public double Z; + public double W; + + public Vector4(double X, double Y, double Z, double W) + { this.X = X; this.Y = Y; this.Z = Z; this.W = W; } + + public double Length => (X * X + Y * Y + Z * Z + W * W).Sqrt(); + public Vector4 Normalized => this = new Vector4() + { X = X * (1 / Length), Y = Y * (1 / Length), Z = Z * (1 / Length), W = W * (1 / Length) }; + + public static Vector4 operator +(Vector4 left, Vector4 right) + { left.X += right.X; left.Y += right.Y; left.Z += right.Z; left.W += right.W; return left; } + public static Vector4 operator -(Vector4 left, Vector4 right) + { left.X -= right.X; left.Y -= right.Y; left.Z -= right.Z; left.W -= right.W; return left; } + public static Vector4 operator -(Vector4 vec) + { vec.X = -vec.X; vec.Y = -vec.Y; vec.Z = -vec.Z; vec.W = -vec.W; return vec; } + public static Vector4 operator *(Vector4 vec, double scale) + { vec.X *= scale ; vec.Y *= scale ; vec.Z *= scale ; vec.W *= scale ; return vec; } + public static Vector4 operator *( double scale, Vector4 vec) + { vec.X *= scale ; vec.Y *= scale ; vec.Z *= scale ; vec.W *= scale ; return vec; } + public static Vector4 operator *(Vector4 vec, Vector4 scale) + { vec.X *= scale.X; vec.Y *= scale.Y; vec.Z *= scale.Z; vec.W *= scale.W; return vec; } + public static Vector4 operator /(Vector4 vec, double scale) + { vec.X /= scale ; vec.Y /= scale ; vec.Z /= scale ; vec.W /= scale ; return vec; } + public static Vector4 operator /(Vector4 vec, Vector4 scale) + { vec.X /= scale.X; vec.Y /= scale.Y; vec.Z /= scale.Z; vec.W /= scale.W; return vec; } + public static bool operator ==(Vector4 A, Vector4 B) => A.Equals(B); + public static bool operator !=(Vector4 A, Vector4 B) => !A.Equals(B); + + public static double Distance (Vector4 left, Vector4 right) => + ((right.X - left.X) * (right.X - left.X) + (right.Y - left.Y) * (right.Y - left.Y) + + (right.Z - left.Z) * (right.Z - left.Z) + (right.W - left.W) * (right.W - left.W)).Sqrt(); + public static double DistanceSquared(Vector4 left, Vector4 right) => + (right.X - left.X) * (right.X - left.X) + (right.Y - left.Y) * (right.Y - left.Y) + + (right.Z - left.Z) * (right.Z - left.Z) + (right.W - left.W) * (right.W - left.W); + public static double Dot (Vector4 left, Vector4 right) => + (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); + public static Vector4 Lerp (Vector4 a, Vector4 b, double blend) => + new Vector4 { X = blend * (b.X - a.X) + a.X, + Y = blend * (b.Y - a.Y) + a.Y, + Z = blend * (b.Z - a.Z) + a.Z, + W = blend * (b.W - a.W) + a.W }; + public static Vector4 Lerp (Vector4 a, Vector4 b, Vector4 blend) => + new Vector4 { X = blend.X * (b.X - a.X) + a.X, + Y = blend.Y * (b.Y - a.Y) + a.Y, + Z = blend.Z * (b.Z - a.Z) + a.Z, + W = blend.W * (b.W - a.W) + a.W }; + public Vector4 Round( ) => + new Vector4 { X = X.Round( ), Y = Y.Round( ), Z = Z.Round( ), W = W.Round( ) }; + public Vector4 Round(int d) => + new Vector4 { X = X.Round(d), Y = Y.Round(d), Z = Z.Round(d), W = W.Round(d) }; + + public override int GetHashCode() + { + unchecked + { + int hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + hashCode = (hashCode * 397) ^ W.GetHashCode(); + return hashCode; + } + } + public override bool Equals(object obj) => + obj is Vector4 vec ? Equals(vec) : false; + public bool Equals(Vector4 other) => + X == other.X && Y == other.Y && Z == other.Z && W == other.W; + + public override string ToString() => "X: " + X + "; Y: " + Y + "; Z: " + Z + "; W: " + W; + } +} diff --git a/KKdBaseLib/bin/KKdBaseLib.dll b/KKdBaseLib/bin/KKdBaseLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..9adfdc16a677e6fe52d433c81c5eb3b6a3b4fd5b GIT binary patch literal 32768 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
  • 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
  • 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 @@ -47,11 +46,12 @@ namespace KKdMainLib.A3DA dataArray = new string[4]; Dict = new Dictionary(); Data = new A3DAData(); - PDHead Header = new PDHead(); + Header Header = new Header(); Data.Format = IO.Format = Main.Format.F; Header.SectionSignature = IO.ReadInt32(); - if (Header.SectionSignature == 0x41443341) { Header = IO.ReadHeader(true); Data.Format = Header.Format; } + if (Header.SectionSignature == 0x41443341) + { Header = IO.ReadHeader(true, true); Data.Format = Header.Format; } if (Header.SectionSignature != 0x44334123) { IO.Close(); return 0; } IO.Offset = IO.Position - 4; @@ -96,14 +96,14 @@ namespace KKdMainLib.A3DA A3DAReader(); - if (Header.Format >= Main.Format.F && Header.Format != Main.Format.FT) + if (Header.SectionSignature == 0x5F5F5F43) { IO.Position = IO.Offset + Data.BinaryOffset; IO.Offset = IO.Position; IO.Position = 0; + IO = File.OpenReader(IO.ReadBytes(Data.BinaryLength)); A3DCReader(); } - IO.Close(); name = ""; @@ -1224,9 +1224,9 @@ namespace KKdMainLib.A3DA IO.WriteEOFC(0); IO.Offset = 0; IO.Position = 0; - PDHead Header = new PDHead { Signature = 0x41443341, Format = Main.Format.F2LE, + Header Header = new Header { Signature = 0x41443341, Format = Main.Format.F2LE, DataSize = A3DCEnd, SectionSize = A3DCEnd, InnerSignature = 0x01131010 }; - IO.Write(Header); + IO.Write(Header, true); } return IO.ToArray(true); @@ -2435,7 +2435,7 @@ namespace KKdMainLib.A3DA public static void Write(this Stream IO, string Data, double? val, byte r) { if (val != null) IO.Write(Data, (double)val, r); } public static void Write(this Stream IO, string Data, ref bool val) => - IO.Write(Data, Main.ToString(val)); + IO.Write(Data, Extensions.ToString(val)); public static void Write(this Stream IO, string Data, long val) => IO.Write(Data, val.ToString( )); public static void Write(this Stream IO, string Data, ulong val) => diff --git a/KKdMainLib/Aet.cs b/KKdMainLib/Aet.cs index 53deda2..4f24b43 100644 --- a/KKdMainLib/Aet.cs +++ b/KKdMainLib/Aet.cs @@ -1,7 +1,8 @@ //Original: AetSet.bt Version: 2.0 by samyuu +using KKdBaseLib; using KKdMainLib.IO; -using KKdMainLib.Types; +using KKdMainLib.F2nd; using KKdMainLib.MessagePack; namespace KKdMainLib.Aet @@ -436,15 +437,6 @@ namespace KKdMainLib.Aet public static class AetExt { - private readonly static System.Text.Encoding ShiftJIS = System.Text.Encoding.GetEncoding(932); - - public static Pointer ReadPointerStringShiftJIS(this Stream IO) - { Pointer val = IO.ReadPointer(); - val.Value = ShiftJIS.GetString(IO.ReadAtOffset(val.Offset)); return val; } - - public static void WriteShiftJIS(this Stream IO, string String) => - IO.Write(ShiftJIS.GetBytes(String)); - public static MsgPack ReadMP(this MsgPack msg, ref CountPointer val, string Name) { val.Offset = 0; diff --git a/KKdMainLib/DB/Aet.cs b/KKdMainLib/DB/Aet.cs index ba3e45d..df55da7 100644 --- a/KKdMainLib/DB/Aet.cs +++ b/KKdMainLib/DB/Aet.cs @@ -1,6 +1,7 @@ //Original: https://github.com/blueskythlikesclouds/MikuMikuLibrary/ using System.Collections.Generic; +using KKdBaseLib; using KKdMainLib.IO; using KKdMainLib.MessagePack; diff --git a/KKdMainLib/DB/Spr.cs b/KKdMainLib/DB/Spr.cs index ff8b3c5..e7c7ba7 100644 --- a/KKdMainLib/DB/Spr.cs +++ b/KKdMainLib/DB/Spr.cs @@ -1,6 +1,7 @@ //Original: https://github.com/blueskythlikesclouds/MikuMikuLibrary/ using System.Collections.Generic; +using KKdBaseLib; using KKdMainLib.IO; using KKdMainLib.MessagePack; diff --git a/KKdMainLib/DEX.cs b/KKdMainLib/DEX.cs index d46c732..243f513 100644 --- a/KKdMainLib/DEX.cs +++ b/KKdMainLib/DEX.cs @@ -1,24 +1,24 @@ using System.Collections.Generic; using KKdMainLib.IO; +using KKdMainLib.F2nd; using KKdMainLib.MessagePack; -using MPIO = KKdMainLib.MessagePack.IO; namespace KKdMainLib { public class DEX { public DEX() - { Dex = null; Header = new PDHead(); } + { Dex = null; Header = new Header(); } private int Offset = 0; - private PDHead Header; + private Header Header; private Stream IO; public EXP[] Dex; public int DEXReader(string filepath, string ext) { - Header = new PDHead(); + Header = new Header(); IO = File.OpenReader(filepath + ext); Header.Format = Main.Format.F; @@ -94,9 +94,9 @@ namespace KKdMainLib public void DEXWriter(string filepath, Main.Format Format) { - Header = new PDHead() { Format = Format }; + Header = new Header(); IO = File.OpenWriter(filepath + (Format > Main.Format.F ? ".dex" : ".bin"), true); - IO.Format = Format; + Header.Format = IO.Format = Format; IO.Offset = Format > Main.Format.F ? 0x20 : 0; IO.Write(0x64); @@ -177,7 +177,7 @@ namespace KKdMainLib int i0 = 0; int i1 = 0; this.Dex = new EXP[0]; - Header = new PDHead(); + Header = new Header(); MsgPack MsgPack = file.ReadMPAllAtOnce(JSON); if (!MsgPack.ElementArray("Dex", out MsgPack Dex)) return; diff --git a/KKdMainLib/DIVAFILE.cs b/KKdMainLib/DIVAFILE.cs index 4a7682a..16ccf36 100644 --- a/KKdMainLib/DIVAFILE.cs +++ b/KKdMainLib/DIVAFILE.cs @@ -1,5 +1,6 @@ using System; using System.Security.Cryptography; +using KKdBaseLib; using KKdMainLib.IO; using MSIO = System.IO; @@ -14,53 +15,54 @@ namespace KKdMainLib public static void Decrypt(this string file) { Console.Title = "DIVAFILE Decrypt - File: " + 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); + Stream IO = File.OpenReader(file); + if (IO.ReadInt64() != 0x454C494641564944) + { IO.Close(); return; } + int StreamLength = IO.ReadInt32(); + int FileLength = IO.ReadInt32(); + byte[] encrypted = IO.ReadBytes(StreamLength); + byte[] decrypted = new byte[StreamLength]; + IO.Close(); + 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, + using (CryptoStream cryptoData = new CryptoStream(new MSIO.MemoryStream(encrypted), crypto.CreateDecryptor(crypto.Key, crypto.IV), CryptoStreamMode.Read)) - cryptoData.Read(decrypted, 0, StreamLenght); + cryptoData.Read(decrypted, 0, StreamLength); } - Stream writer = File.OpenWriter(file, FileLenght); - for (int i = 0x10; i < StreamLenght && i < FileLenght + 0x10; i++) - writer.Write(decrypted[i]); - writer.Close(); + IO = File.OpenWriter(file, FileLength); + IO.Write(decrypted, FileLength < StreamLength ? FileLength : StreamLength); + IO.Close(); } public static void Encrypt(this string file) { Console.Title = "DIVAFILE Encrypt - File: " + Path.GetFileName(file); - Stream reader = File.OpenReader(file); - int FileLenghtOrigin = reader.Length; - int FileLenght = FileLenghtOrigin.Align(16); - reader.Close(); + Stream IO = File.OpenReader(file); + int FileLengthOrigin = IO.Length; + int FileLength = FileLengthOrigin.Align(16); + IO.Close(); byte[] In = File.OpenReader(file).ToArray(true); - byte[] Inalign = new byte[FileLenght]; + byte[] Inalign = new byte[FileLength]; for (int i = 0; i < In.Length; i++) Inalign[i] = In[i]; In = null; - byte[] encrypted = new byte[FileLenght]; + byte[] encrypted = new byte[FileLength]; 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); + cryptoData.Read(encrypted, 0, FileLength); } - Stream writer = File.OpenWriter(file, Inalign.Length); - writer.Write(0x454C494641564944); - writer.Write(FileLenght); - writer.Write(FileLenghtOrigin); - writer.Write(encrypted); - writer.Close(); + IO = File.OpenWriter(file, Inalign.Length); + IO.Write(0x454C494641564944); + IO.Write(FileLength); + IO.Write(FileLengthOrigin); + IO.Write(encrypted); + IO.Close(); } } } diff --git a/KKdMainLib/DataBank.cs b/KKdMainLib/DataBank.cs index 7d361a8..8ec1251 100644 --- a/KKdMainLib/DataBank.cs +++ b/KKdMainLib/DataBank.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using KKdBaseLib; using KKdMainLib.IO; using KKdMainLib.MessagePack; @@ -120,7 +121,7 @@ namespace KKdMainLib } else if (file.Contains("PvList")) { - if (psrDat != null) + if (pvList != null) { if (Compact) msgPack.Add("Compact", Compact); diff --git a/KKdMainLib/Extensions.cs b/KKdMainLib/Extensions.cs new file mode 100644 index 0000000..158be1d --- /dev/null +++ b/KKdMainLib/Extensions.cs @@ -0,0 +1,181 @@ +using System.Collections.Generic; +using KKdBaseLib; +using KKdMainLib.IO; +using KKdMainLib.F2nd; + +namespace KKdMainLib +{ + public static class HeaderExtensions + { + public static Header ReadHeader(this Stream stream, bool Seek, bool ReadSectionSignature = true) + { + if (Seek) + if (stream.Position > 4) stream.LongPosition -= 4; + else stream.LongPosition = 0; + return stream.ReadHeader(ReadSectionSignature); + } + + public static Header ReadHeader(this Stream stream, bool ReadSectionSignature = true) + { + Header Header = new Header + { Format = Main.Format.F2LE, Signature = stream.ReadInt32(), + DataSize = stream.ReadInt32(), + Length = stream.ReadInt32() }; + if (stream.ReadUInt32() == 0x18000000) + { Header.Format = Main.Format.F2BE; } + Header.ID = stream.ReadInt32(); + Header.SectionSize = stream.ReadInt32(); + Header.Count = stream.ReadInt32(); + stream.ReadInt32(); + if (Header.Length == 0x40) + { + stream.ReadInt64(); + stream.ReadInt64(); + Header.InnerSignature = stream.ReadInt32(); + stream.ReadInt32(); + stream.ReadInt64(); + } + stream.Format = Header.Format; + if (ReadSectionSignature) Header.SectionSignature = stream.ReadInt32Endian(); + return Header; + } + + public static void Write(this Stream stream, Header Header, bool Extended = false) + { + stream.Write(Header.Signature); + stream.Write(Header.DataSize); + stream.Write((Header.Format < Main.Format.X && Extended) ? 0x40 : 0x20); + stream.Write(Header.Format == Main.Format.F2BE ? 0x18000000 : 0x10000000); + stream.Write(Header.ID); + stream.Write(Header.SectionSize); + stream.Write(0x00); + stream.Write(0x00); + if (Header.Format < Main.Format.X && Extended) + { + stream.Write(Header.Format < Main.Format.MGF ? (int)((Header.SectionSignature ^ + (Header.DataSize * (long)Header.Signature)) - Header.ID + Header.SectionSize) : 0); + stream.Write(0x00); + stream.Write(0x00L); + stream.Write(Header.InnerSignature); + stream.Write(0x00); + stream.Write(0x00L); + } + } + + public static void WriteEOFC(this Stream stream, int ID = 0) => + stream.Write(new Header { ID = ID, Length = 0x20, Signature = 0x43464F45 }); + } + + public static class POFExtensions + { + public static POF AddPOF(this Header Header) => + new POF { Offsets = new List(), Offset = Header.DataSize + Header.Length }; + + public static void GetOffset(this Stream stream, ref POF POF) + { if (stream.Format > Main.Format.F) POF.Offsets.Add(stream.Position + (stream.IsX ? stream.Offset : 0x00)); } + + public static void ReadPOF(this Stream stream, ref POF POF) + { + if (stream.ReadString(3) == "POF") + { + 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.Length, 0); + POF.Length = stream.ReadInt32(); + while (POF.Length + POF.Offset + POF.Header.Length > 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; + } + } + } + + public static void Write(this Stream stream, ref POF POF, int ID) + { + POF.Offsets.Sort(); + long CurrentPOFOffset = 0; + long POFOffset = 0; + byte BitShift = (byte)(2 + POF.Type); + int Max1 = (0x00FF >> BitShift) << BitShift; + int Max2 = (0xFFFF >> BitShift) << BitShift; + POF.Length = 5 + ID; + for (int i = 0; i < POF.Offsets.Count; i++) + { + POFOffset = POF.Offsets[i] - CurrentPOFOffset; + CurrentPOFOffset = POF.Offsets[i]; + if (POFOffset <= Max1) POF.Length += 1; + else if (POFOffset <= Max2) POF.Length += 2; + else POF.Length += 4; + POF.Offsets[i] = POFOffset; + } + + long POFLengthAling = POF.Length.Align(16); + POF.Header = new Header { DataSize = (int)POFLengthAling, ID = ID, Format = Main.Format.F2LE, + Length = 0x20, SectionSize = (int)POFLengthAling, Signature = 0x30464F50 }; + POF.Header.Signature += POF.Type << 24; + stream.Write(POF.Header); + + stream.Write(POF.Length); + for (int i = 0; i < POF.Offsets.Count; i++) + { + POFOffset = POF.Offsets[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); + } + } + + public static class PointerExt + { + public static Pointer ReadPointer(this Stream IO) => + new Pointer { Offset = IO.ReadInt32() }; + + public static Pointer ReadPointerString(this Stream IO) + { Pointer val = IO.ReadPointer(); + val.Value = IO.ReadStringAtOffset(val.Offset); return val; } + + public static CountPointer ReadCountPointer(this Stream IO) => + new CountPointer { Count = IO.ReadInt32(), Offset = IO.ReadInt32() }; + + public static Pointer ReadPointerEndian(this Stream IO) => + new Pointer { Offset = IO.ReadInt32Endian() }; + + public static Pointer ReadPointerStringEndian(this Stream IO) + { Pointer val = IO.ReadPointerEndian(); + val.Value = IO.ReadStringAtOffset(val.Offset); return val; } + + public static CountPointer ReadCountPointerEndian(this Stream IO) => + new CountPointer { Count = IO.ReadInt32Endian(), Offset = IO.ReadInt32Endian() }; + + public static Pointer ReadPointerX(this Stream IO) => + new Pointer { Offset = (int)IO.ReadIntX() }; + + public static Pointer ReadPointerStringX(this Stream IO) + { Pointer val = IO.ReadPointerX(); + val.Value = IO.ReadStringAtOffset(val.Offset); return val; } + + public static CountPointer ReadCountPointerX(this Stream IO) => + new CountPointer { Count = (int)IO.ReadIntX(), Offset = (int)IO.ReadIntX() }; + } +} diff --git a/KKdMainLib/F2nd/Header.cs b/KKdMainLib/F2nd/Header.cs new file mode 100644 index 0000000..63e2af0 --- /dev/null +++ b/KKdMainLib/F2nd/Header.cs @@ -0,0 +1,22 @@ +using KKdBaseLib; + +namespace KKdMainLib.F2nd +{ + public struct Header + { + public int Signature; + public int DataSize; + public int Length; + public Main.Format Format; + public int ID; + public int SectionSize; + public int Count; + public int InnerSignature; + public int SectionSignature; + public bool IsBE => Format == Main.Format.F2BE; + public bool IsX => Format == Main.Format.X || Format == Main.Format.XHD; + + + public override string ToString() => Signature.ToString(false); + } +} diff --git a/KKdMainLib/F2nd/POF.cs b/KKdMainLib/F2nd/POF.cs new file mode 100644 index 0000000..4c7527c --- /dev/null +++ b/KKdMainLib/F2nd/POF.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace KKdMainLib.F2nd +{ + public struct POF + { + public byte Type; + public int Length; + public int Offset; + public int LastOffset; + public List Offsets; + public Header Header; + } +} diff --git a/KKdMainLib/F2nd/Struct.cs b/KKdMainLib/F2nd/Struct.cs new file mode 100644 index 0000000..631fa0d --- /dev/null +++ b/KKdMainLib/F2nd/Struct.cs @@ -0,0 +1,87 @@ +using KKdBaseLib; +using KKdMainLib.IO; + +namespace KKdMainLib.F2nd +{ + public struct Struct + { + public Header Header; + public byte[] Data; + public Struct[] SubStructs; + public bool HasEOFC; + public Mini POF; + public Mini ENRS; + + public long DataOffset; + + public override string ToString() => Header.ToString() + (SubStructs != null ? "; SubStructs: " + + SubStructs.Length : "") + (POF != null ? "; Has " + POF.Header.ToString() : "") + + (ENRS != null ? "; Has ENRS" : "") + (HasEOFC ? "; Has EOFC" : ""); + + public static Struct ReadStruct(byte[] Data) + { + Stream stream = File.OpenReader(Data); + Struct Struct = ReadStruct(ref stream, stream.ReadHeader(false)); + stream.Close(); + return Struct; + } + + private static Struct ReadStruct(ref Stream stream, Header Header) + { + Struct Struct = new Struct { Header = Header, DataOffset = + stream.Position, Data = stream.ReadBytes(Header.SectionSize) }; + int ID = Header.ID; + + KKdList SubStructs = KKdList.New; + long Length = stream.Length - stream.Position; + long Position = 0; + while (Length > Position) + { + Header = stream.ReadHeader(false); + Position += Header.Length + Header.DataSize; + if (Header.ID == ID && Header.Signature == 0x43464F45) + { Struct.HasEOFC = true; break; } + else if (Header.ID == 0 && Header.Signature == 0x53524E45) + SubStructs.Add(new Struct { Header = Header, DataOffset = + stream.Position, Data = stream.ReadBytes(Header.SectionSize) }); + else if (Header.ID <= ID) + { stream.LongPosition -= Header.Length; break; } + else SubStructs.Add(ReadStruct(ref stream, Header)); + //(Header.Signature == 0x30464F50 || Header.Signature == + // 0x31464F50 || Header.Signature == 0x53524E45) + } + + for (int i = 0; i < SubStructs.Capacity; i++) + { + string Sig = SubStructs[i].Header.ToString(); + if (Sig == "ENRS" || Sig == "POF0" || Sig == "POF1") + { + if (Sig == "ENRS") Struct.ENRS = (Mini)SubStructs[i]; + else Struct.POF = (Mini)SubStructs[i]; + SubStructs.RemoveAt(i); SubStructs.Capacity--; i--; + } + } + + if (SubStructs.Capacity > 0) + { + Struct.SubStructs = SubStructs.ToArray(); + } + return Struct; + } + + public class Mini + { + public Header Header; + public byte[] Data; + public bool HasEOFC; + + public static explicit operator Mini(Struct Struct) => + new Mini() { Header = Struct.Header, Data = Struct.Data, HasEOFC = Struct.HasEOFC }; + + public static explicit operator Struct( Mini Struct) => + new Struct() { Header = Struct.Header, Data = Struct.Data, HasEOFC = Struct.HasEOFC }; + + public override string ToString() => Header.ToString() + (HasEOFC ? "; Has EOFC" : ""); + } + } +} diff --git a/KKdMainLib/FARC.cs b/KKdMainLib/FARC.cs index 684f311..3675e44 100644 --- a/KKdMainLib/FARC.cs +++ b/KKdMainLib/FARC.cs @@ -2,6 +2,7 @@ using System.IO.Compression; using System.Security.Cryptography; +using KKdBaseLib; using KKdMainLib.IO; using MSIO = System.IO; @@ -203,7 +204,7 @@ namespace KKdMainLib return SkipData; } - public void Pack() + public void Pack(Farc Signature = Farc.FArC) { NewFARC(); string[] files = Directory.GetFiles(DirectoryPath); @@ -211,6 +212,7 @@ namespace KKdMainLib for (int i = 0; i < files.Length; i++) Files[i] = new FARCFile { Name = Path.GetFileName(files[i]), Data = File.ReadAllBytes(files[i]) }; files = null; + this.Signature = Signature; Save(); } @@ -219,7 +221,8 @@ namespace KKdMainLib for (int i = 0; i < Files.Length; i++) { string ext = Path.GetExtension(Files[i].Name).ToLower(); - if (ext == ".a3da" || ext == ".diva" || ext == ".vag") Signature = Farc.FArc; + if (ext == ".a3da" || ext == ".diva" || ext == ".drs" || ext == ".dve" || ext == ".vag") + { Signature = Farc.FArc; break; } } Stream writer = File.OpenWriter(DirectoryPath + ".farc", true); diff --git a/KKdMainLib/IO/IOExtensions.cs b/KKdMainLib/IO/IOExtensions.cs index 5af8ef2..c3ba13e 100644 --- a/KKdMainLib/IO/IOExtensions.cs +++ b/KKdMainLib/IO/IOExtensions.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using KKdBaseLib; namespace KKdMainLib.IO { @@ -10,7 +10,7 @@ namespace KKdMainLib.IO stream.NullTerminated(End).ToUTF8 (); public static byte[] NullTerminated (this Stream stream, byte End = 0) { - List s = new List(); + KKdList s = KKdList.New; while (stream.LongPosition < stream.LongLength) { byte a = stream.ReadByte(); @@ -73,5 +73,15 @@ namespace KKdMainLib.IO stream.LongPosition = Position; return s; } + + public static Pointer ReadPointerStringShiftJIS(this Stream IO) + { Pointer val = IO.ReadPointer(); + val.Value = IO.ReadStringShiftJISAtOffset(val.Offset); return val; } + + public static string ReadStringShiftJISAtOffset(this Stream IO, long Offset = 0, long Length = 0) => + Text.ShiftJIS.GetString(IO.ReadAtOffset(Offset, Length)); + + public static void WriteShiftJIS(this Stream IO, string String) => + IO.Write(Text.ShiftJIS.GetBytes(String)); } } diff --git a/KKdMainLib/IO/Stream.cs b/KKdMainLib/IO/Stream.cs index 1cdad9d..b174097 100644 --- a/KKdMainLib/IO/Stream.cs +++ b/KKdMainLib/IO/Stream.cs @@ -1,5 +1,5 @@ using System; -using KKdMainLib.Types; +using KKdBaseLib; using MSIO = System.IO; namespace KKdMainLib.IO diff --git a/KKdMainLib/KKdMainLib.csproj b/KKdMainLib/KKdMainLib.csproj index ebf5db8..2d80aea 100644 --- a/KKdMainLib/KKdMainLib.csproj +++ b/KKdMainLib/KKdMainLib.csproj @@ -42,6 +42,9 @@ + + + @@ -51,24 +54,15 @@ - - - - - - + - - - - @@ -77,5 +71,11 @@ + + + {437f63f1-8c23-429e-ab14-38b85c9edb16} + KKdBaseLib + + \ No newline at end of file diff --git a/KKdMainLib/Main.cs b/KKdMainLib/Main.cs index 71d6191..f7c4d51 100644 --- a/KKdMainLib/Main.cs +++ b/KKdMainLib/Main.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Windows.Forms; using System.Globalization; using System.Collections.Generic; +using KKdBaseLib; using KKdMainLib.IO; namespace KKdMainLib @@ -219,7 +220,7 @@ namespace KKdMainLib 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; } + return val.ToDouble(out value); value = null; return false; } public static bool FindValue(this Dictionary Dict, out string value, string args) @@ -294,59 +295,6 @@ namespace KKdMainLib 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 object d) - { - if (d == null) return "Null"; - else if (d is float F32) return ToString(F32); - else if (d is double F64) return ToString(F64); - return d.ToString(); - } - 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 sbyte? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this sbyte d) => d.ToString(); - public static string ToString(this byte? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this byte d) => d.ToString(); - public static string ToString(this short? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this short d) => d.ToString(); - public static string ToString(this ushort? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this ushort d) => d.ToString(); - public static string ToString(this int? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this int d) => d.ToString(); - public static string ToString(this uint? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this uint d) => d.ToString(); - public static string ToString(this long? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this long d) => d.ToString(); - public static string ToString(this ulong? d) => d.GetValueOrDefault().ToString(); - public static string ToString(this ulong d) => d.ToString(); - 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 { diff --git a/KKdMainLib/MathExtensions.cs b/KKdMainLib/MathExtensions.cs deleted file mode 100644 index cb0b4c1..0000000 --- a/KKdMainLib/MathExtensions.cs +++ /dev/null @@ -1,226 +0,0 @@ -using System; - -namespace KKdMainLib -{ - public static class MathExtensions - { - private const double RadPi = 180 / Math.PI; - public static double ToDegrees(this double val) => val * RadPi; - public static double ToRadians(this double val) => val / RadPi; - - public static double Acos (this double d ) => Math.Acos (d ); - public static double Asin (this double d ) => Math.Asin (d ); - public static double Atan (this double d ) => Math.Atan (d ); - public static double Aсtg (this double d ) => 1 / Math.Atan (d ); - public static double Cos (this double d ) => Math.Cos (d ); - public static double Cosh (this double val) => Math.Cosh (val); - public static double Sin (this double a ) => Math.Sin (a ); - public static double Sinh (this double val) => Math.Sinh (val); - public static double Tan (this double a ) => Math.Tan (a ); - public static double Tanh (this double val) => Math.Tanh (val); - public static double Ctg (this double a ) => 1 / Math.Tan (a ); - public static double Ctgh (this double val) => 1 / Math.Tanh (val); - - public static double Abs (this double val) => Math.Abs (val); - public static double Ceiling(this double a ) => Math.Ceiling(a ); - public static double Exp (this double d ) => Math.Exp (d ); - public static double Log (this double d ) => Math.Log (d ); - public static double Log10 (this double d ) => Math.Log10 (d ); - public static double Round (this double d ) => Math.Round (d ); - public static int Sign (this double val) => Math.Sign (val); - public static double Sqrt (this double d ) => Math.Sqrt (d ); - - - public static double Atan2(this double y , double x ) => Math.Atan2(y , x ); - public static double Log (this double val , double newBase) => Math.Log (val , newBase); - public static double Max (this double val1, double val2 ) => Math.Max (val1, val2 ); - public static double Min (this double val1, double val2 ) => Math.Min (val1, val2 ); - public static double Pow (this double x , double y ) => Math.Pow (x , y ); - public static double Round(this double val , int d ) => Math.Round(val , d ); - - public static void FloorCeiling( ref double Value) => - Value = Value % 1 >= 0.5 ? (long)(Value + 0.5) : (long) Value; - - public static long FloorCeiling(this double Value) => - Value % 1 >= 0.5 ? (long)(Value + 0.5) : (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 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 index 7904196..67421d5 100644 --- a/KKdMainLib/MessagePack/IO.cs +++ b/KKdMainLib/MessagePack/IO.cs @@ -1,6 +1,6 @@ using System; +using KKdBaseLib; using KKdMainLib.IO; -using KKdMainLib.Types; namespace KKdMainLib.MessagePack { diff --git a/KKdMainLib/MessagePack/JSONIO.cs b/KKdMainLib/MessagePack/JSONIO.cs index b92c2f6..ef6eb1e 100644 --- a/KKdMainLib/MessagePack/JSONIO.cs +++ b/KKdMainLib/MessagePack/JSONIO.cs @@ -1,7 +1,7 @@ //Original or reader part: https://github.com/MarcosLopezC/LightJson/ +using KKdBaseLib; using KKdMainLib.IO; -using KKdMainLib.Types; namespace KKdMainLib.MessagePack { @@ -241,16 +241,16 @@ namespace KKdMainLib.MessagePack case MsgPack val: Write(val, End, TabChar, Tab, Style); break; case bool val: Write(val); break; case string val: Write(val); break; - case sbyte val: _IO.Write(Main.ToString(val)); break; - case byte val: _IO.Write(Main.ToString(val)); break; - case short val: _IO.Write(Main.ToString(val)); break; - case ushort val: _IO.Write(Main.ToString(val)); break; - case int val: _IO.Write(Main.ToString(val)); break; - case uint val: _IO.Write(Main.ToString(val)); break; - case long val: _IO.Write(Main.ToString(val)); break; - case ulong val: _IO.Write(Main.ToString(val)); break; - case float val: _IO.Write(Main.ToString(val)); break; - case double val: _IO.Write(Main.ToString(val)); break; + case sbyte val: _IO.Write(Extensions.ToString(val)); break; + case byte val: _IO.Write(Extensions.ToString(val)); break; + case short val: _IO.Write(Extensions.ToString(val)); break; + case ushort val: _IO.Write(Extensions.ToString(val)); break; + case int val: _IO.Write(Extensions.ToString(val)); break; + case uint val: _IO.Write(Extensions.ToString(val)); break; + case long val: _IO.Write(Extensions.ToString(val)); break; + case ulong val: _IO.Write(Extensions.ToString(val)); break; + case float val: _IO.Write(Extensions.ToString(val)); break; + case double val: _IO.Write(Extensions.ToString(val)); break; } } private void Write( bool val) => _IO.Write(val ? "true" : "false"); diff --git a/KKdMainLib/MessagePack/MsgPack.cs b/KKdMainLib/MessagePack/MsgPack.cs index 59a6268..70bf4e0 100644 --- a/KKdMainLib/MessagePack/MsgPack.cs +++ b/KKdMainLib/MessagePack/MsgPack.cs @@ -1,5 +1,5 @@ using System; -using KKdMainLib.Types; +using KKdBaseLib; namespace KKdMainLib.MessagePack { diff --git a/KKdMainLib/PDHeader.cs b/KKdMainLib/PDHeader.cs deleted file mode 100644 index ebc45b7..0000000 --- a/KKdMainLib/PDHeader.cs +++ /dev/null @@ -1,79 +0,0 @@ -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 InnerSignature; - public int SectionSignature; - 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.LongPosition -= 4; - else stream.LongPosition = 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(); - if (Header.Lenght == 0x40) - { - stream.Position = 0x30; - Header.InnerSignature = stream.ReadInt32(); - } - stream.IsBE = Header.Format == Main.Format.F2BE; - stream.Format = Header.Format; - stream.LongPosition = Position + Header.Lenght; - Header.SectionSignature = stream.ReadInt32Endian(); - return Header; - } - - public static void Write(this Stream stream, PDHead Header, bool X = false) - { - stream.Write(Header.Signature); - stream.Write(Header.DataSize); - stream.Write((Header.Format < Main.Format.X && !X) ? 0x40 : 0x20); - 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); - if (Header.Format < Main.Format.X && !X) - { - stream.Write(Header.Format < Main.Format.MGF ? (int)((Header.SectionSignature ^ - (Header.DataSize * (long)Header.Signature)) - Header.ID + Header.SectionSize) : 0); - stream.Write(0x00); - stream.Write(0x00L); - stream.Write(Header.InnerSignature); - stream.Write(0x00); - stream.Write(0x00L); - } - } - - public static void WriteEOFC(this Stream stream, int ID = 0) => - stream.Write(new PDHead { ID = ID, - Lenght = 0x20, Signature = 0x43464F45 }, true); - - } -} diff --git a/KKdMainLib/POF.cs b/KKdMainLib/POF.cs deleted file mode 100644 index 0b39cdc..0000000 --- a/KKdMainLib/POF.cs +++ /dev/null @@ -1,125 +0,0 @@ -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 (POF != null) 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]) - System.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, true); - - 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); - } - - public static long ReadUInt32Endian(this Stream IO, ref POF POF ) => - IO.GetOffset(ref POF).ReadUInt32Endian( ); - public static long ReadUInt32Endian(this Stream IO, ref POF POF, bool IsBE) => - IO.GetOffset(ref POF).ReadUInt32Endian(IsBE); - public static long ReadInt64 (this Stream IO, ref POF POF) => - IO.GetOffset(ref POF).ReadInt64(); - - public static string ReadStringAtOffset(this Stream IO, ref POF POF, long Offset = 0, long Length = 0) => - IO.GetOffset(ref POF).ReadStringAtOffset(Offset, Length); - } -} diff --git a/KKdMainLib/Properties/AssemblyInfo.cs b/KKdMainLib/Properties/AssemblyInfo.cs index b6bdc52..71d3833 100644 --- a/KKdMainLib/Properties/AssemblyInfo.cs +++ b/KKdMainLib/Properties/AssemblyInfo.cs @@ -11,5 +11,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("2BA7EFC6-91D1-8BBC-C487-06C7F36CC789")] -[assembly: AssemblyVersion("0.4.6.4")] -[assembly: AssemblyFileVersion("0.4.6.4")] +[assembly: AssemblyVersion("0.4.7.0")] +[assembly: AssemblyFileVersion("0.4.7.0")] diff --git a/KKdMainLib/STR.cs b/KKdMainLib/STR.cs index e816370..62b5f86 100644 --- a/KKdMainLib/STR.cs +++ b/KKdMainLib/STR.cs @@ -1,186 +1,184 @@ -using KKdMainLib.IO; -using KKdMainLib.Types; +using KKdBaseLib; +using KKdMainLib.IO; +using KKdMainLib.F2nd; using KKdMainLib.MessagePack; namespace KKdMainLib { public class STR { - public struct String - { - public int ID; - public int StrOffset; - public string Str; - } - public STR() - { Offset = 0; OffsetX = 0; STRs = null; POF = null; Header = new PDHead(); } + { Offset = 0; OffsetX = 0; STRs = null; Header = new Header(); } private long Offset; private long OffsetX; - public String[] STRs; private POF POF; - private PDHead Header; + private Header Header; + private Stream IO; + + public String[] STRs; public int STRReader(string filepath, string ext) { - Stream reader = File.OpenReader(filepath + ext); + IO = File.OpenReader(filepath + ext); - Header = new PDHead(); - reader.Format = Main.Format.F; - Header.Signature = reader.ReadInt32(); + Header = new Header(); + IO.Format = Main.Format.F; + Header.Signature = IO.ReadInt32(); if (Header.Signature == 0x41525453) { - Header = reader.ReadHeader(true); + Header = IO.ReadHeader(true); POF = Header.AddPOF(); - reader.Position = Header.Lenght; + IO.Position = Header.Length; - long Count = reader.ReadInt32Endian(); - Offset = reader.ReadInt32Endian(); + long Count = IO.ReadInt32Endian(); + Offset = IO.ReadInt32Endian(); if (Offset == 0) { Offset = Count; - OffsetX = reader.ReadInt64(); - Count = reader.ReadInt64(); - reader.Offset = Header.Lenght; - reader.Format = Main.Format.X; + OffsetX = IO.ReadInt64(); + Count = IO.ReadInt64(); + IO.Offset = Header.Length; + IO.Format = Main.Format.X; + IO.LongOffset += Offset; + IO.Position = 0; } - reader.LongPosition = reader.IsX ? Offset + reader.Offset : Offset; + else IO.Position = Header.Length + 0x40; STRs = new String[Count]; for (int i = 0; i < Count; i++) + STRs[i].ID = IO.ReadInt32Endian(); + + if (IO.IsX) { - STRs[i].StrOffset = reader.GetOffset(ref POF).ReadInt32Endian(); - STRs[i].ID = reader.ReadInt32Endian(); - if (reader.IsX) STRs[i].StrOffset += (int)OffsetX; + IO.Offset = Header.Length; + for (int i = 0; i < Count; i++) + STRs[i].Str.Value = IO.ReadStringAtOffset(STRs[i].Str.Offset + OffsetX); + } + else + { + IO.Offset = 0; + for (int i = 0; i < Count; i++) + STRs[i].Str.Value = STRs[i].Str.Offset > 0 ? + IO.ReadStringAtOffset(STRs[i].Str.Offset) : null; } - 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); + IO.Position = POF.Offset; + IO.ReadPOF(ref POF); } else { - reader.Position -= 4; + IO.Position -= 4; int Count = 0; - for (int a = 0, i = 0; reader.Position > 0 && reader.Position < reader.Length; i++, Count++) + for (int a = 0, i = 0; IO.Position > 0 && IO.Position < IO.Length; i++, Count++) { - a = reader.ReadInt32(); + a = IO.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(); + IO.LongPosition = STRs[i].Str.Offset; + STRs[i].ID = i; + STRs[i].Str.Value = IO.NullTerminatedUTF8(); } } - reader.Close(); + IO.Close(); return 1; } public void STRWriter(string filepath) { + if (STRs == null || STRs.Length == 0 || Header.Format > Main.Format.F2BE) return; uint Offset = 0; uint CurrentOffset = 0; - Stream writer = File.OpenWriter(filepath + (Header. - Format > Main.Format.FT ? ".str" : ".bin"), true); - writer.Format = Header.Format; + IO = File.OpenWriter(filepath + (Header.Format > Main.Format.FT ? ".str" : ".bin"), true); + IO.Format = Header.Format; POF = new POF(); - writer.IsBE = writer.Format == Main.Format.F2BE; + IO.IsBE = IO.Format == Main.Format.F2BE; long Count = STRs.LongLength; - if (writer.Format > Main.Format.FT) + if (IO.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(0x10); + IO.Position = 0x40; + IO.WriteX(Count); + IO.GetOffset(ref POF); + IO.WriteX(0x80); + IO.Position = 0x80; + for (int i = 0; i < Count; i++) IO.Write(0x00L); + IO.Align(0x10); } else { - for (int i = 0; i < Count; i++) writer.Write(0x00); - writer.Align(0x20); + for (int i = 0; i < Count; i++) IO.Write(0x00); + IO.Align(0x20); } KKdList UsedSTR = KKdList.New; KKdList UsedSTRPos = KKdList.New; int[] STRPos = new int[Count]; - for (int i1 = 0; i1 < Count; i1++) + for (int i = 0; i < Count; i++) { - if (UsedSTR.Contains(STRs[i1].Str)) + if (!UsedSTR.Contains(STRs[i].Str.Value)) { - for (int i2 = 0; i2 < Count; i2++) - if (UsedSTR[i2] == STRs[i1].Str) - { STRPos[i1] = UsedSTRPos[i2]; break; } + STRPos[i] = IO.Position; + UsedSTRPos.Add(STRPos[i]); + UsedSTR.Add(STRs[i].Str.Value); + IO.Write(STRs[i].Str.Value + "\0"); } 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(0x10); - 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; + for (int i2 = 0; i2 < Count; i2++) + if (UsedSTR[i2] == STRs[i].Str.Value) + { STRPos[i] = UsedSTRPos[i2]; break; } } - if (writer.Format > Main.Format.FT) + if (IO.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); + IO.Align(0x10); + Offset = IO.UIntPosition; + IO.Position = 0x80; + for (int i = 0; i < Count; i++) + { + IO.GetOffset(ref POF); + IO.WriteEndian(STRPos[i]); + IO.WriteEndian(STRs[i].ID); + } + + IO.UIntPosition = Offset; + IO.Write(ref POF, 1); + CurrentOffset = IO.UIntPosition; + IO.WriteEOFC(0); + Header.DataSize = (int)(CurrentOffset - 0x40); Header.Signature = 0x41525453; - Header.SectionSize = (int)(Offset - Header.Lenght); - writer.Position = 0; - writer.Write(Header); + Header.SectionSize = (int)(Offset - 0x40); + IO.Position = 0; + IO.Write(Header); } - writer.Close(); + else + { + IO.Position = 0; + for (int i = 0; i < Count; i++) IO.Write(STRPos[i]); + } + IO.Close(); } public void MsgPackReader(string file, bool JSON) { MsgPack MsgPack = file.ReadMPAllAtOnce(JSON); - if (!MsgPack.Element("STR", out MsgPack STR)) return; + Header = new Header(); + System.Enum.TryParse(STR.ReadString("Format"), out Header.Format); if (!STR.ElementArray("Strings", out MsgPack Strings)) return; STRs = new String[Strings.Array.Length]; for (int i = 0; i < STRs.Length; i++) { - STRs[i].ID = Strings[i].ReadInt32 ("ID" ); - STRs[i].Str = Strings[i].ReadString("Str"); + STRs[i].ID = Strings[i].ReadInt32 ("ID" ); + STRs[i].Str.Value = Strings[i].ReadString("Str"); } MsgPack = MsgPack.New; @@ -188,17 +186,27 @@ namespace KKdMainLib public void MsgPackWriter(string file, bool JSON) { + if (STRs == null || STRs.Length == 0) return; MsgPack STR_ = new MsgPack("STR").Add("Format", Header.Format.ToString()); MsgPack Strings = new MsgPack(STRs.Length, "Strings"); for (int i = 0; i < STRs.Length; i++) { Strings[i] = MsgPack.New.Add("ID", STRs[i].ID); - if (STRs[i].Str != null) if (STRs[i].Str != "") - Strings[i].Add("S", STRs[i].Str); ; + if (STRs[i].Str.Value != null || STRs[i].Str.Value != "") + Strings[i] = Strings[i].Add("Str", STRs[i].Str.Value); } STR_.Add(Strings); - STR_.Write(true, file, JSON); + STR_.WriteAfterAll(true, file, JSON); + } + + public struct String + { + public int ID; + public Pointer Str; + + public override string ToString() => "ID: " + ID + (Str.Value != null || + Str.Value != "" ? ("; Str: " + Str.Value) : ""); } } } diff --git a/KKdMainLib/Types/Pointer.cs b/KKdMainLib/Types/Pointer.cs deleted file mode 100644 index 49c9b23..0000000 --- a/KKdMainLib/Types/Pointer.cs +++ /dev/null @@ -1,43 +0,0 @@ -using KKdMainLib.IO; - -namespace KKdMainLib.Types -{ - public struct Pointer - { - public int Offset; - public T Value; - - public override string ToString() => Main.ToString(Value); - } - - public struct CountPointer - { - public int Count { get => Entries != null ? Entries.Length : 0; - set => Entries = new T[value]; } - public int Offset; - public T[] Entries; - - - public T this[int index] - { get => Count > 0 ? Entries[index] : default; - set { if (Count > 0) Entries[index] = value; } } - - public override string ToString() => Count < 1 ? "No Entries" : - Count == 1 ? Entries[0].ToString() : "Count: " + Count; - } - - public static class PointerExt - { - public static Pointer ReadPointer(this Stream IO) => - new Pointer { Offset = IO.ReadInt32() }; - - public static Pointer ReadPointerString(this Stream IO) - { - Pointer val = IO.ReadPointer(); - val.Value = IO.ReadStringAtOffset(val.Offset); return val; - } - - public static CountPointer ReadCountPointer(this Stream IO) => - new CountPointer { Count = IO.ReadInt32(), Offset = IO.ReadInt32() }; - } -} \ No newline at end of file diff --git a/KKdSoundLib/DIVA.cs b/KKdSoundLib/DIVA.cs index 02d5841..33ade02 100644 --- a/KKdSoundLib/DIVA.cs +++ b/KKdSoundLib/DIVA.cs @@ -1,4 +1,4 @@ -using KKdMainLib; +using KKdBaseLib; using KKdMainLib.IO; namespace KKdSoundLib diff --git a/KKdSoundLib/Extensions.cs b/KKdSoundLib/Extensions.cs index 291e391..583a3e3 100644 --- a/KKdSoundLib/Extensions.cs +++ b/KKdSoundLib/Extensions.cs @@ -1,4 +1,4 @@ -using KKdMainLib; +using KKdBaseLib; using KKdMainLib.IO; namespace KKdSoundLib diff --git a/KKdSoundLib/KKdSoundLib.csproj b/KKdSoundLib/KKdSoundLib.csproj index 4601d1c..bf2f80d 100644 --- a/KKdSoundLib/KKdSoundLib.csproj +++ b/KKdSoundLib/KKdSoundLib.csproj @@ -52,6 +52,10 @@ + + {da55bfd3-927e-473c-a779-f9e6365384ae} + KKdBaseLib + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789} KKdMainLib diff --git a/KKdSoundLib/Properties/AssemblyInfo.cs b/KKdSoundLib/Properties/AssemblyInfo.cs index 994f0f8..67c6912 100644 --- a/KKdSoundLib/Properties/AssemblyInfo.cs +++ b/KKdSoundLib/Properties/AssemblyInfo.cs @@ -11,5 +11,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("D8A3F2D7-10CC-5723-EC9A-45D3B9C2DFEA")] -[assembly: AssemblyVersion("0.0.2.3")] -[assembly: AssemblyFileVersion("0.0.2.3")] +[assembly: AssemblyVersion("0.0.3.0")] +[assembly: AssemblyFileVersion("0.0.3.0")] diff --git a/KKdSoundLib/VAG.cs b/KKdSoundLib/VAG.cs index c2b923f..07884d8 100644 --- a/KKdSoundLib/VAG.cs +++ b/KKdSoundLib/VAG.cs @@ -1,4 +1,4 @@ -using KKdMainLib; +using KKdBaseLib; using KKdMainLib.IO; namespace KKdSoundLib diff --git a/PD_Tool.sln b/PD_Tool.sln index bee5bd2..6b72a21 100644 --- a/PD_Tool.sln +++ b/PD_Tool.sln @@ -3,22 +3,24 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29025.244 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PD_Tool", "PD_Tool\PD_Tool.csproj", "{7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KKdBaseLib", "KKdBaseLib\KKdBaseLib.csproj", "{437F63F1-8C23-429E-AB14-38B85C9EDB16}" 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 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PD_Tool", "PD_Tool\PD_Tool.csproj", "{7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E}" +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 + {437F63F1-8C23-429E-AB14-38B85C9EDB16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {437F63F1-8C23-429E-AB14-38B85C9EDB16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {437F63F1-8C23-429E-AB14-38B85C9EDB16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {437F63F1-8C23-429E-AB14-38B85C9EDB16}.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 @@ -27,6 +29,10 @@ Global {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 + {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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PD_Tool/PD_Tool.csproj b/PD_Tool/PD_Tool.csproj index a137fc8..879b0c6 100644 --- a/PD_Tool/PD_Tool.csproj +++ b/PD_Tool/PD_Tool.csproj @@ -59,6 +59,10 @@ + + {437f63f1-8c23-429e-ab14-38b85c9edb16} + KKdBaseLib + {2BA7EFC6-91D1-8BBC-C487-06C7F36CC789} KKdMainLib diff --git a/PD_Tool/Properties/AssemblyInfo.cs b/PD_Tool/Properties/AssemblyInfo.cs index 173e3ad..195dc74 100644 --- a/PD_Tool/Properties/AssemblyInfo.cs +++ b/PD_Tool/Properties/AssemblyInfo.cs @@ -11,5 +11,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("7B5D5A3A-A6F8-4813-C97D-ACFC98F7397E")] -[assembly: AssemblyVersion("0.4.6.4")] -[assembly: AssemblyFileVersion("0.4.6.4")] +[assembly: AssemblyVersion("0.4.7.0")] +[assembly: AssemblyFileVersion("0.4.7.0")] diff --git a/PD_Tool/classes/FARC.cs b/PD_Tool/classes/FARC.cs index a07d2cc..b8587f6 100644 --- a/PD_Tool/classes/FARC.cs +++ b/PD_Tool/classes/FARC.cs @@ -64,7 +64,7 @@ namespace PD_Tool else if (type == "R") return; else FARC.Signature = KKdFARC.Farc.FArC; Console.Title = "FARC Creator - Directory: " + Path.GetDirectoryName(file); - new KKdFARC(file, true).Pack(); + new KKdFARC(file, true).Pack(FARC.Signature); } } } diff --git a/PD_Tool/classes/Tools/DB.cs b/PD_Tool/classes/Tools/DB.cs index 74c71b0..e92e2b4 100644 --- a/PD_Tool/classes/Tools/DB.cs +++ b/PD_Tool/classes/Tools/DB.cs @@ -36,7 +36,6 @@ namespace PD_Tool.Tools DataBank DB; string[] file_split; - int File_Checksum = 0, Get_Checksum; foreach (string file in FileNames) { ext = Path.GetExtension(file); @@ -48,11 +47,6 @@ namespace PD_Tool.Tools DB = new DataBank(); if (file_split.Length == 5 && ext == ".dat" && MP) { - if (!int.TryParse(file_split[3], out File_Checksum)) continue; - - Get_Checksum = DCC.CalculateChecksum(file); - if (File_Checksum != Get_Checksum) continue; - filepath = file.Replace(filename + ".dat", ""); Console.Title = "DataBank Converter: " + filename; DB. DBReader(file);