Fix Endfield
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||
<Version>1.36.00</Version>
|
||||
<AssemblyVersion>1.36.00</AssemblyVersion>
|
||||
<FileVersion>1.36.00</FileVersion>
|
||||
|
||||
@@ -624,7 +624,7 @@ namespace AssetStudio
|
||||
{
|
||||
NetEaseUtils.DecryptWithHeader(compressedBytesSpan);
|
||||
}
|
||||
if (Game.Type.IsArknightsEndfield() && i == 0)
|
||||
if (Game.Type.IsArknightsEndfield() && i == 0 && compressedBytesSpan[..32].Count((byte)0xa6) > 5)
|
||||
{
|
||||
FairGuardUtils.Decrypt(compressedBytesSpan);
|
||||
}
|
||||
@@ -660,7 +660,7 @@ namespace AssetStudio
|
||||
try
|
||||
{
|
||||
reader.Read(compressedBytesSpan);
|
||||
if (i == 0)
|
||||
if (i == 0 && compressedBytesSpan[..32].Count((byte)0xa6) > 5)
|
||||
{
|
||||
FairGuardUtils.Decrypt(compressedBytesSpan);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace AssetStudio
|
||||
m_Min = reader.ReadVector3();
|
||||
m_Max = reader.ReadVector3();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CompressedMesh
|
||||
@@ -146,6 +147,11 @@ namespace AssetStudio
|
||||
for (int i = 0; i < m_ChannelsSize; i++)
|
||||
{
|
||||
m_Channels.Add(new ChannelInfo(reader));
|
||||
|
||||
////Kh0n5u Debug2
|
||||
//if (i == 1){
|
||||
// m_Channels[i].dimension = 3;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,6 +807,7 @@ namespace AssetStudio
|
||||
GetTriangles();
|
||||
}
|
||||
|
||||
|
||||
private void ReadVertexData()
|
||||
{
|
||||
m_VertexCount = (int)m_VertexData.m_VertexCount;
|
||||
@@ -818,6 +825,11 @@ namespace AssetStudio
|
||||
{
|
||||
m_Channel.dimension = 4;
|
||||
}
|
||||
////Kh0n5u Debug4
|
||||
//if (reader.Game.Type.IsArknightsEndfield() && chn == 1)
|
||||
//{
|
||||
// m_Channel.dimension = 3;
|
||||
//}
|
||||
|
||||
var vertexFormat = MeshHelper.ToVertexFormat(m_Channel.format, version);
|
||||
var componentByteSize = (int)MeshHelper.GetFormatSize(vertexFormat);
|
||||
@@ -845,10 +857,18 @@ namespace AssetStudio
|
||||
|
||||
int[] componentsIntArray = null;
|
||||
float[] componentsFloatArray = null;
|
||||
if (MeshHelper.IsIntFormat(vertexFormat))
|
||||
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
|
||||
if (reader.Game.Type.IsArknightsEndfield() && chn == 1)
|
||||
{
|
||||
//componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
|
||||
componentsFloatArray = MeshHelper.DecompressEndfieldNormal(componentBytes,vertexFormat);
|
||||
}
|
||||
else
|
||||
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
|
||||
{
|
||||
if (MeshHelper.IsIntFormat(vertexFormat))
|
||||
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
|
||||
else
|
||||
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
|
||||
}
|
||||
|
||||
if (version[0] >= 2018)
|
||||
{
|
||||
@@ -858,7 +878,22 @@ namespace AssetStudio
|
||||
m_Vertices = componentsFloatArray;
|
||||
break;
|
||||
case 1: //kShaderChannelNormal
|
||||
m_Normals = componentsFloatArray;
|
||||
//Kh0n5u Debug3
|
||||
//if (reader.Game.Type.IsArknightsEndfield())
|
||||
//{
|
||||
// float[] m_Vertices_zero = new float[m_VertexCount * 3];
|
||||
// for (int i = 0; i < m_VertexCount; i++)
|
||||
// {
|
||||
// m_Vertices_zero[i * 3] = 0.0f;
|
||||
// m_Vertices_zero[i * 3 + 1] = 0.0f;
|
||||
// m_Vertices_zero[i * 3 + 2] = 1.0f;
|
||||
// }
|
||||
// m_Normals = m_Vertices_zero;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
m_Normals = componentsFloatArray;
|
||||
//}
|
||||
break;
|
||||
case 2: //kShaderChannelTangent
|
||||
m_Tangents = componentsFloatArray;
|
||||
@@ -1457,6 +1492,187 @@ namespace AssetStudio
|
||||
return result;
|
||||
}
|
||||
|
||||
public static UInt32[] BytesToUInt32Array(byte[] inputBytes, VertexFormat format)
|
||||
{
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new UInt32[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.UInt32:
|
||||
result[i] = BinaryPrimitives.ReadUInt32LittleEndian(inputBytes.AsSpan(i * 4));
|
||||
break;
|
||||
case VertexFormat.SInt32:
|
||||
result[i] = (UInt32)BinaryPrimitives.ReadInt32LittleEndian(inputBytes.AsSpan(i * 4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int[] BytesToSInt32Array(byte[] inputBytes, VertexFormat format)
|
||||
{
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.UInt32:
|
||||
result[i] = (int)BinaryPrimitives.ReadUInt32LittleEndian(inputBytes.AsSpan(i * 4));
|
||||
break;
|
||||
case VertexFormat.SInt32:
|
||||
result[i] = BinaryPrimitives.ReadInt32LittleEndian(inputBytes.AsSpan(i * 4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float[] DecompressEndfieldNormal(this byte[] inputBytes, VertexFormat format) // 8bits per component
|
||||
{
|
||||
var size = MeshHelper.GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new float[len * 3];
|
||||
var readFloat = new float[len];
|
||||
readFloat = MeshHelper.BytesToFloatArray(inputBytes, format);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
float value = readFloat[i];
|
||||
|
||||
float r0x = BitConverter.ToInt32(BitConverter.GetBytes(value)) & 0x40000000;
|
||||
r0x = (BitConverter.ToUInt32(BitConverter.GetBytes(r0x)) > 0) ? 1.0f : 0.0f;
|
||||
|
||||
// (((int3)v2.xxx << (32 - int3(10,10,10) - int3(0,10,20))) >> (32 - int3(10,10,10)))
|
||||
float r0y = (BitConverter.ToInt32(BitConverter.GetBytes(value)) << 22) >> 22;
|
||||
float r0z = (BitConverter.ToInt32(BitConverter.GetBytes(value)) << 12) >> 22;
|
||||
float r0w = (BitConverter.ToInt32(BitConverter.GetBytes(value)) << 2) >> 22;
|
||||
|
||||
float r1x = (BitConverter.ToUInt32(BitConverter.GetBytes(value))) >> 31;
|
||||
|
||||
float r1y = 0.00195694715f * r0y;
|
||||
float r1z = 0.00195694715f * r0z;
|
||||
float r1w = 0.00195694715f * r0w;
|
||||
|
||||
float leng = r1x * r1x + r1y * r1y + r1z * r1z + r1w * r1w;
|
||||
|
||||
float r2x = 1.0f - Math.Abs(r1y);
|
||||
float r2y = 1.0f - Math.Abs(r1z);
|
||||
float r2z = 1.0f - Math.Abs(r1y);
|
||||
|
||||
float r3z = r2x - Math.Abs(r1z);
|
||||
|
||||
r2x = r3z < 0.0f ? 1.0f : 0.0f;
|
||||
|
||||
r0y = r0y >= 0.0f ? 1.0f : 0.0f;
|
||||
r0z = r0z >= 0.0f ? 1.0f : 0.0f;
|
||||
|
||||
r0y = r0y * 2.0f - 1.0f;
|
||||
r0z = r0z * 2.0f - 1.0f;
|
||||
|
||||
r0y = r2y * r0y;
|
||||
r0z = r2z * r0z;
|
||||
|
||||
float r3x = (r2x == 1.0f) ? r0y : r1y;
|
||||
float r3y = (r2x == 1.0f) ? r0z : r1z;
|
||||
|
||||
r0y = r3x* r3x + r3y * r3y + r3z * r3z;
|
||||
r0y = 1.0f / (float)Math.Sqrt(r0y);
|
||||
|
||||
r2x = r3x * r0y;
|
||||
r2y = r3y * r0y;
|
||||
r2z = r3z * r0y;
|
||||
|
||||
|
||||
|
||||
//float old_r3x = r3x;
|
||||
//r3x = r3y * r0y - r2z;
|
||||
//r3y = r3z * r0y - r2x;
|
||||
//r3z = old_r3x * r0y - r2y;
|
||||
|
||||
//r0y = r3x * r2x + r3y * r2y + r3z * r2z;
|
||||
|
||||
//r3x = r3x - r0y;
|
||||
//r3y = r3y - r0y;
|
||||
//r3z = r3z - r0y;
|
||||
|
||||
//r0y = r3x * r3x + r3y * r3y + r3z * r3z;
|
||||
//r0y = 1.0f / (float)Math.Sqrt(r0y);
|
||||
|
||||
//r3x = r3x * r0y;
|
||||
//r3y = r3y * r0y;
|
||||
//r3z = r3z * r0y;
|
||||
|
||||
|
||||
//float length = r2x * r2x + r2y * r2y + r2z * r2z;
|
||||
|
||||
|
||||
|
||||
|
||||
// 计算result[i * 3]的值
|
||||
result[i * 3] = r2x;
|
||||
result[i * 3 + 1] = r2y;
|
||||
result[i * 3 + 2] = r2z;
|
||||
//result[i * 3] = 0;
|
||||
//result[i * 3 + 1] = 0;
|
||||
//result[i * 3 + 2] = 1;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float[] DecompressOctahedron(this byte[] inputBytes, VertexFormat format) // 8bits per component
|
||||
{
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new float[len*3];
|
||||
var readFloat = new UInt32[len];
|
||||
readFloat = BytesToUInt32Array(inputBytes, VertexFormat.UInt32);
|
||||
// read per 8 bits per component
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
var x = readFloat[i] & 0xFFFF;
|
||||
var y = (readFloat[i] >> 16) & 0xFFFF;
|
||||
var z = (readFloat[i] >> 16) & 0xFF;
|
||||
var w = (readFloat[i] >> 24) & 0xFF;
|
||||
/* HLSL Decode Example
|
||||
* float3 Decode(float2 f)
|
||||
* {
|
||||
* f = f * 2.0 - 1.0;
|
||||
* float3 n = float3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));
|
||||
* float t = saturate(-n.z);
|
||||
* n.xy += n.xy >= 0.0 ? -t : t;
|
||||
* return normalize(n);
|
||||
* }
|
||||
*/
|
||||
float f_x = x / 65535.0f * 2.0f - 1.0f;
|
||||
float f_y = y / 65535.0f * 2.0f - 1.0f;
|
||||
float f_z = 1.0f - Math.Abs(f_x) - Math.Abs(f_y);
|
||||
if (f_z < 0.0f)
|
||||
{
|
||||
float f_t = Math.Max(Math.Min(-f_z, 1.0f), 0.0f);
|
||||
f_x += f_x >= 0.0f ? -f_t : f_t;
|
||||
f_y += f_y >= 0.0f ? -f_t : f_t;
|
||||
}
|
||||
float length = (float)Math.Sqrt(f_x * f_x + f_y * f_y + f_z * f_z);
|
||||
if (length > 1e-6f)
|
||||
{
|
||||
f_x /= length;
|
||||
f_y /= length;
|
||||
f_z /= length;
|
||||
}
|
||||
result[i * 3] = f_x;
|
||||
result[i * 3 + 1] = f_y;
|
||||
result[i * 3 + 2] = f_z;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static int[] BytesToIntArray(byte[] inputBytes, VertexFormat format)
|
||||
{
|
||||
var size = GetFormatSize(format);
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace AssetStudio
|
||||
Logger.Verbose($"Attempting to decrypt block with FairGuard encryption...");
|
||||
|
||||
var encryptedOffset = 0;
|
||||
var encryptedSize = bytes.Length > 0x500 ? 0x500 : bytes.Length;
|
||||
var encryptedSize = Math.Min(0x500, bytes.Length);
|
||||
|
||||
if (encryptedSize < 0x20)
|
||||
{
|
||||
Logger.Verbose($"block size is less that minimum, skipping...");
|
||||
Logger.Verbose("block size is less that minimum, skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -27,11 +27,20 @@ namespace AssetStudio
|
||||
encrypted[i] ^= 0xA6;
|
||||
}
|
||||
|
||||
// old
|
||||
/*
|
||||
var seedPart0 = (uint)(encryptedInts[2] ^ 0x1274CBEC ^ encryptedInts[6] ^ 0x3F72EAF3);
|
||||
var seedPart1 = (uint)(encryptedInts[3] ^ 0xBE482704 ^ encryptedInts[0] ^ encryptedSize);
|
||||
var seedPart2 = (uint)(encryptedInts[1] ^ encryptedSize ^ encryptedInts[5] ^ 0x753BDCAA);
|
||||
var seedPart3 = (uint)(encryptedInts[0] ^ 0x82C57E3C ^ encryptedInts[7] ^ 0xE3D947D3);
|
||||
var seedPart4 = (uint)(encryptedInts[4] ^ 0x6F2A7347 ^ encryptedInts[7] ^ 0x4736C714);
|
||||
*/
|
||||
|
||||
var seedPart0 = (uint)(encryptedInts[2] ^ encryptedInts[6] ^ 0x226a61b9);
|
||||
var seedPart1 = (uint)(encryptedInts[3] ^ encryptedInts[0] ^ 0x7a39d018 ^ encryptedSize);
|
||||
var seedPart2 = (uint)(encryptedInts[1] ^ encryptedInts[5] ^ 0x18f6d8aa ^ encryptedSize);
|
||||
var seedPart3 = (uint)(encryptedInts[0] ^ encryptedInts[7] ^ 0xaa255fb1);
|
||||
var seedPart4 = (uint)(encryptedInts[4] ^ encryptedInts[7] ^ 0xf78dd8eb);
|
||||
|
||||
var seedInts = new uint[] { seedPart0, seedPart1, seedPart2, seedPart3, seedPart4 };
|
||||
var seedBytes = MemoryMarshal.AsBytes<uint>(seedInts);
|
||||
|
||||
@@ -4,6 +4,16 @@ namespace AssetStudio;
|
||||
public class LZ4Inv : LZ4
|
||||
{
|
||||
public new static LZ4Inv Instance => new();
|
||||
protected override (int encCount, int litCount) GetLiteralToken(ReadOnlySpan<byte> cmp, ref int cmpPos) => ((cmp[cmpPos] >> 4) & 0xf, (cmp[cmpPos++] >> 0) & 0xf);
|
||||
|
||||
protected override (int encCount, int litCount) GetLiteralToken(ReadOnlySpan<byte> cmp, ref int cmpPos)
|
||||
{
|
||||
var val = cmp[cmpPos++];
|
||||
var lit = val & 0b00110011;
|
||||
var enc = val & 0b11001100;
|
||||
enc >>= 2;
|
||||
|
||||
return ((enc & 0b11) | enc >> 2, (lit & 0b11) | lit >> 2);
|
||||
}
|
||||
|
||||
protected override int GetChunkEnd(ReadOnlySpan<byte> cmp, ref int cmpPos) => cmp[cmpPos++] << 8 | cmp[cmpPos++] << 0;
|
||||
}
|
||||
Reference in New Issue
Block a user