From 2010e0203490750d70b5920b7c3cecd2740e947a Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 2 Sep 2022 18:36:34 +0200 Subject: [PATCH] Add some start for Evp Data. --- Penumbra.GameData/Files/MtrlFile.Write.cs | 1 - Penumbra.GameData/Structs/EqpEntry.cs | 117 +++++++++++----------- Penumbra/Meta/Files/EvpFile.cs | 68 +++++++++++++ Penumbra/Meta/Files/MetaBaseFile.cs | 2 +- 4 files changed, 128 insertions(+), 60 deletions(-) create mode 100644 Penumbra/Meta/Files/EvpFile.cs diff --git a/Penumbra.GameData/Files/MtrlFile.Write.cs b/Penumbra.GameData/Files/MtrlFile.Write.cs index 8a3df6f5..4b54c30f 100644 --- a/Penumbra.GameData/Files/MtrlFile.Write.cs +++ b/Penumbra.GameData/Files/MtrlFile.Write.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using System.Text; diff --git a/Penumbra.GameData/Structs/EqpEntry.cs b/Penumbra.GameData/Structs/EqpEntry.cs index 8ea20ecc..b2f3f22c 100644 --- a/Penumbra.GameData/Structs/EqpEntry.cs +++ b/Penumbra.GameData/Structs/EqpEntry.cs @@ -9,23 +9,23 @@ namespace Penumbra.GameData.Structs; [Flags] public enum EqpEntry : ulong { - BodyEnabled = 0x00_01ul, - BodyHideWaist = 0x00_02ul, - BodyHideThighs = 0x00_04ul, - BodyHideGlovesS = 0x00_08ul, - _4 = 0x00_10ul, - BodyHideGlovesM = 0x00_20ul, - BodyHideGlovesL = 0x00_40ul, - BodyHideGorget = 0x00_80ul, - BodyShowLeg = 0x01_00ul, - BodyShowHand = 0x02_00ul, - BodyShowHead = 0x04_00ul, - BodyShowNecklace = 0x08_00ul, - BodyShowBracelet = 0x10_00ul, - BodyShowTail = 0x20_00ul, - DisableBreastPhysics = 0x40_00ul, - _15 = 0x80_00ul, - BodyMask = 0xFF_FFul, + BodyEnabled = 0x00_01ul, + BodyHideWaist = 0x00_02ul, + BodyHideThighs = 0x00_04ul, + BodyHideGlovesS = 0x00_08ul, + _4 = 0x00_10ul, + BodyHideGlovesM = 0x00_20ul, + BodyHideGlovesL = 0x00_40ul, + BodyHideGorget = 0x00_80ul, + BodyShowLeg = 0x01_00ul, + BodyShowHand = 0x02_00ul, + BodyShowHead = 0x04_00ul, + BodyShowNecklace = 0x08_00ul, + BodyShowBracelet = 0x10_00ul, + BodyShowTail = 0x20_00ul, + BodyDisableBreastPhysics = 0x40_00ul, + BodyHasVfxObject = 0x80_00ul, + BodyMask = 0xFF_FFul, LegsEnabled = 0x01ul << 16, LegsHideKneePads = 0x02ul << 16, @@ -75,7 +75,7 @@ public enum EqpEntry : ulong _55 = 0x00_80_00ul << 40, HeadShowHrothgarHat = 0x01_00_00ul << 40, HeadShowVieraHat = 0x02_00_00ul << 40, - _58 = 0x04_00_00ul << 40, + HeadHasVfxObject = 0x04_00_00ul << 40, _59 = 0x08_00_00ul << 40, _60 = 0x10_00_00ul << 40, _61 = 0x20_00_00ul << 40, @@ -136,22 +136,22 @@ public static class Eqp { return entry switch { - EqpEntry.BodyEnabled => EquipSlot.Body, - EqpEntry.BodyHideWaist => EquipSlot.Body, - EqpEntry.BodyHideThighs => EquipSlot.Body, - EqpEntry.BodyHideGlovesS => EquipSlot.Body, - EqpEntry._4 => EquipSlot.Body, - EqpEntry.BodyHideGlovesM => EquipSlot.Body, - EqpEntry.BodyHideGlovesL => EquipSlot.Body, - EqpEntry.BodyHideGorget => EquipSlot.Body, - EqpEntry.BodyShowLeg => EquipSlot.Body, - EqpEntry.BodyShowHand => EquipSlot.Body, - EqpEntry.BodyShowHead => EquipSlot.Body, - EqpEntry.BodyShowNecklace => EquipSlot.Body, - EqpEntry.BodyShowBracelet => EquipSlot.Body, - EqpEntry.BodyShowTail => EquipSlot.Body, - EqpEntry.DisableBreastPhysics => EquipSlot.Body, - EqpEntry._15 => EquipSlot.Body, + EqpEntry.BodyEnabled => EquipSlot.Body, + EqpEntry.BodyHideWaist => EquipSlot.Body, + EqpEntry.BodyHideThighs => EquipSlot.Body, + EqpEntry.BodyHideGlovesS => EquipSlot.Body, + EqpEntry._4 => EquipSlot.Body, + EqpEntry.BodyHideGlovesM => EquipSlot.Body, + EqpEntry.BodyHideGlovesL => EquipSlot.Body, + EqpEntry.BodyHideGorget => EquipSlot.Body, + EqpEntry.BodyShowLeg => EquipSlot.Body, + EqpEntry.BodyShowHand => EquipSlot.Body, + EqpEntry.BodyShowHead => EquipSlot.Body, + EqpEntry.BodyShowNecklace => EquipSlot.Body, + EqpEntry.BodyShowBracelet => EquipSlot.Body, + EqpEntry.BodyShowTail => EquipSlot.Body, + EqpEntry.BodyDisableBreastPhysics => EquipSlot.Body, + EqpEntry.BodyHasVfxObject => EquipSlot.Body, EqpEntry.LegsEnabled => EquipSlot.Legs, EqpEntry.LegsHideKneePads => EquipSlot.Legs, @@ -198,9 +198,9 @@ public static class Eqp EqpEntry._55 => EquipSlot.Head, EqpEntry.HeadShowHrothgarHat => EquipSlot.Head, EqpEntry.HeadShowVieraHat => EquipSlot.Head, + EqpEntry.HeadHasVfxObject => EquipSlot.Head, - // Currently unused. - EqpEntry._58 => EquipSlot.Unknown, + // currently unused EqpEntry._59 => EquipSlot.Unknown, EqpEntry._60 => EquipSlot.Unknown, EqpEntry._61 => EquipSlot.Unknown, @@ -215,22 +215,22 @@ public static class Eqp { return entry switch { - EqpEntry.BodyEnabled => "Enabled", - EqpEntry.BodyHideWaist => "Hide Waist", - EqpEntry.BodyHideThighs => "Hide Thigh Pads", - EqpEntry.BodyHideGlovesS => "Hide Small Gloves", - EqpEntry._4 => "Unknown 4", - EqpEntry.BodyHideGlovesM => "Hide Medium Gloves", - EqpEntry.BodyHideGlovesL => "Hide Large Gloves", - EqpEntry.BodyHideGorget => "Hide Gorget", - EqpEntry.BodyShowLeg => "Show Legs", - EqpEntry.BodyShowHand => "Show Hands", - EqpEntry.BodyShowHead => "Show Head", - EqpEntry.BodyShowNecklace => "Show Necklace", - EqpEntry.BodyShowBracelet => "Show Bracelet", - EqpEntry.BodyShowTail => "Show Tail", - EqpEntry.DisableBreastPhysics => "Disable Breast Physics", - EqpEntry._15 => "Unknown 15", + EqpEntry.BodyEnabled => "Enabled", + EqpEntry.BodyHideWaist => "Hide Waist", + EqpEntry.BodyHideThighs => "Hide Thigh Pads", + EqpEntry.BodyHideGlovesS => "Hide Small Gloves", + EqpEntry._4 => "Unknown 4", + EqpEntry.BodyHideGlovesM => "Hide Medium Gloves", + EqpEntry.BodyHideGlovesL => "Hide Large Gloves", + EqpEntry.BodyHideGorget => "Hide Gorget", + EqpEntry.BodyShowLeg => "Show Legs", + EqpEntry.BodyShowHand => "Show Hands", + EqpEntry.BodyShowHead => "Show Head", + EqpEntry.BodyShowNecklace => "Show Necklace", + EqpEntry.BodyShowBracelet => "Show Bracelet", + EqpEntry.BodyShowTail => "Show Tail", + EqpEntry.BodyDisableBreastPhysics => "Disable Breast Physics", + EqpEntry.BodyHasVfxObject => "Has Special Effects", EqpEntry.LegsEnabled => "Enabled", EqpEntry.LegsHideKneePads => "Hide Knee Pads", @@ -277,12 +277,13 @@ public static class Eqp EqpEntry._55 => "Unknown 55", EqpEntry.HeadShowHrothgarHat => "Show on Hrothgar", EqpEntry.HeadShowVieraHat => "Show on Viera", - EqpEntry._58 => "Unknown 58", - EqpEntry._59 => "Unknown 59", - EqpEntry._60 => "Unknown 60", - EqpEntry._61 => "Unknown 61", - EqpEntry._62 => "Unknown 62", - EqpEntry._63 => "Unknown 63", + EqpEntry.HeadHasVfxObject => "Has Special Effects", + + EqpEntry._59 => "Unknown 59", + EqpEntry._60 => "Unknown 60", + EqpEntry._61 => "Unknown 61", + EqpEntry._62 => "Unknown 62", + EqpEntry._63 => "Unknown 63", _ => throw new InvalidEnumArgumentException(), }; diff --git a/Penumbra/Meta/Files/EvpFile.cs b/Penumbra/Meta/Files/EvpFile.cs new file mode 100644 index 00000000..b6dcbb30 --- /dev/null +++ b/Penumbra/Meta/Files/EvpFile.cs @@ -0,0 +1,68 @@ +using System; + +namespace Penumbra.Meta.Files; + + +// EVP file structure: +// [Identifier:3 bytes, EVP] +// [NumModels:ushort] +// NumModels x [ModelId:ushort] +// Containing the relevant model IDs. Seems to be sorted. +// NumModels x [DataArray]:512 Byte] +// Containing Flags in each byte, 0x01 set for Body, 0x02 set for Helmet. Unsure where the index into this array comes from. +public unsafe class EvpFile : MetaBaseFile +{ + public const int FlagArraySize = 512; + + [Flags] + public enum EvpFlag : byte + { + None = 0x00, + Body = 0x01, + Head = 0x02, + Both = Body | Head, + } + + public int NumModels + => Data[ 3 ]; + + public ReadOnlySpan< ushort > ModelSetIds + => new(Data + 4, NumModels); + + public ushort ModelSetId( int idx ) + => idx >= 0 && idx < NumModels ? ( ( ushort* )( Data + 4 ) )[ idx ] : ushort.MaxValue; + + public ReadOnlySpan< EvpFlag > Flags( int idx ) + => new(Data + 4 + idx * FlagArraySize, FlagArraySize); + + public EvpFlag Flag( ushort modelSet, int arrayIndex ) + { + if( arrayIndex is >= FlagArraySize or < 0 ) + { + return EvpFlag.None; + } + + var ids = ModelSetIds; + for( var i = 0; i < ids.Length; ++i ) + { + var model = ids[ i ]; + if( model < modelSet ) + { + continue; + } + + if( model > modelSet ) + { + break; + } + + return Flags( i )[ arrayIndex ]; + } + + return EvpFlag.None; + } + + public EvpFile() + : base( ( Interop.Structs.CharacterUtility.Index )1 ) // TODO: Name + { } +} \ No newline at end of file diff --git a/Penumbra/Meta/Files/MetaBaseFile.cs b/Penumbra/Meta/Files/MetaBaseFile.cs index 8bc827f5..8a167216 100644 --- a/Penumbra/Meta/Files/MetaBaseFile.cs +++ b/Penumbra/Meta/Files/MetaBaseFile.cs @@ -12,7 +12,7 @@ public unsafe class MetaBaseFile : IDisposable public CharacterUtility.InternalIndex Index { get; } public MetaBaseFile( Interop.Structs.CharacterUtility.Index idx ) - => Index = CharacterUtility.ReverseIndices[(int) idx]; + => Index = CharacterUtility.ReverseIndices[ ( int )idx ]; protected (IntPtr Data, int Length) DefaultData => Penumbra.CharacterUtility.DefaultResource( Index );