Skip to content

Commit cc6c044

Browse files
authored
Merge pull request #130 from MilchRatchet/dev-cleanup-fixes
Fixes, filestream debugging and test suite
2 parents 6ea7a9d + 9993686 commit cc6c044

78 files changed

Lines changed: 6295 additions & 112 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
11+
<PackageReference Include="xunit" Version="2.9.3" />
12+
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
13+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
14+
<PrivateAssets>all</PrivateAssets>
15+
</PackageReference>
16+
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<ProjectReference Include="..\LibReplanetizer\LibReplanetizer.csproj" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright (C) 2018-2021, The Replanetizer Contributors.
2+
// Replanetizer is free software: you can redistribute it
3+
// and/or modify it under the terms of the GNU General Public
4+
// License as published by the Free Software Foundation,
5+
// either version 3 of the License, or (at your option) any later version.
6+
// Please see the LICENSE.md file for more details.
7+
8+
using OpenTK.Mathematics;
9+
using Xunit;
10+
using LibReplanetizer.Models.Animations;
11+
using static LibReplanetizer.DataFunctions;
12+
13+
namespace LibReplanetizer.Tests.Animation
14+
{
15+
public class BoneDataTests
16+
{
17+
/// <summary>
18+
/// Builds a 0x10-byte RC1/2/3 BoneData block for bone at index <paramref name="num"/>.
19+
/// Translation values are pre-scaled by 1024 (raw format).
20+
/// </summary>
21+
private static byte[] BuildBoneDataBlock(int num, float txRaw, float tyRaw, float tzRaw, short unk, short parentRaw)
22+
{
23+
int totalSize = (num + 1) * 0x10;
24+
byte[] block = new byte[totalSize];
25+
int offset = num * 0x10;
26+
WriteFloat(block, offset + 0x00, txRaw);
27+
WriteFloat(block, offset + 0x04, tyRaw);
28+
WriteFloat(block, offset + 0x08, tzRaw);
29+
WriteShort(block, offset + 0x0C, unk);
30+
WriteShort(block, offset + 0x0E, parentRaw);
31+
return block;
32+
}
33+
34+
[Fact]
35+
public void Constructor_RC1_ParsesTranslation()
36+
{
37+
// Translation is stored raw * 1024; constructor divides by 1024.
38+
byte[] block = BuildBoneDataBlock(0, 1024f, 2048f, 512f, 0x7000, 0x40);
39+
var bone = new BoneData(GameType.RaC1, block, 0);
40+
41+
Assert.Equal(1.0f, bone.translation.X, 5);
42+
Assert.Equal(2.0f, bone.translation.Y, 5);
43+
Assert.Equal(0.5f, bone.translation.Z, 5);
44+
}
45+
46+
[Fact]
47+
public void Constructor_RC1_ParsesParentIndex()
48+
{
49+
// parentRaw = index * 0x40; constructor divides by 0x40
50+
byte[] block = BuildBoneDataBlock(0, 0f, 0f, 0f, 0, (short) (3 * 0x40));
51+
var bone = new BoneData(GameType.RaC1, block, 0);
52+
53+
Assert.Equal(3, bone.parent);
54+
}
55+
56+
[Fact]
57+
public void Serialize_RC1_RoundTrip()
58+
{
59+
byte[] original = BuildBoneDataBlock(0, 1024f, 2048f, 512f, 0x7000, 0x40);
60+
var bone = new BoneData(GameType.RaC1, original, 0);
61+
byte[] serialized = bone.Serialize();
62+
63+
Assert.Equal(original, serialized);
64+
}
65+
66+
[Fact]
67+
public void Serialize_RC1_AtOffset_RoundTrip()
68+
{
69+
byte[] original = BuildBoneDataBlock(2, 3072f, -1024f, 0f, 0, (short) (1 * 0x40));
70+
var bone = new BoneData(GameType.RaC1, original, 2);
71+
byte[] serialized = bone.Serialize();
72+
73+
// Serialized output is always 0x10 bytes (no num offset)
74+
Assert.Equal(0x10, serialized.Length);
75+
// Re-parse from serialized to verify values
76+
var bone2 = new BoneData(GameType.RaC1, serialized, 0);
77+
Assert.Equal(bone.translation.X, bone2.translation.X, 5);
78+
Assert.Equal(bone.translation.Y, bone2.translation.Y, 5);
79+
Assert.Equal(bone.translation.Z, bone2.translation.Z, 5);
80+
Assert.Equal(bone.parent, bone2.parent);
81+
}
82+
}
83+
84+
public class BoneMatrixTests
85+
{
86+
private static byte[] BuildBoneMatrixBlock(int num, Matrix3x4 transform, Vector3 cumOffset, short unk3C, short parentRaw)
87+
{
88+
int totalSize = (num + 1) * 0x40;
89+
byte[] block = new byte[totalSize];
90+
int offset = num * 0x40;
91+
WriteMatrix3x4(block, offset, transform);
92+
WriteFloat(block, offset + 0x30, cumOffset.X * 1024.0f);
93+
WriteFloat(block, offset + 0x34, cumOffset.Y * 1024.0f);
94+
WriteFloat(block, offset + 0x38, cumOffset.Z * 1024.0f);
95+
WriteShort(block, offset + 0x3C, unk3C);
96+
WriteShort(block, offset + 0x3E, parentRaw);
97+
return block;
98+
}
99+
100+
[Fact]
101+
public void Serialize_RC1_RoundTrip()
102+
{
103+
var transform = new Matrix3x4(
104+
1f, 0f, 0f, 0f,
105+
0f, 1f, 0f, 0f,
106+
0f, 0f, 1f, 0f);
107+
var cumOffset = new Vector3(1.0f, 2.0f, 3.0f);
108+
short unk = 0x7000;
109+
short parentRaw = (short) (2 * 0x40);
110+
111+
byte[] original = BuildBoneMatrixBlock(0, transform, cumOffset, unk, parentRaw);
112+
var matrix = new BoneMatrix(GameType.RaC1, original, 0);
113+
byte[] serialized = matrix.Serialize();
114+
115+
Assert.Equal(original, serialized);
116+
}
117+
}
118+
119+
public class ModelSoundTests
120+
{
121+
private static byte[] BuildSoundBlock(int num,
122+
int off00, float distance, int masterVolume,
123+
int volume, int distortion, int distortion2,
124+
short off18, short listIndex, int off1C)
125+
{
126+
int totalSize = (num + 1) * 0x20;
127+
byte[] block = new byte[totalSize];
128+
int offset = num * 0x20;
129+
WriteInt(block, offset + 0x00, off00);
130+
WriteFloat(block, offset + 0x04, distance);
131+
WriteInt(block, offset + 0x08, masterVolume);
132+
WriteInt(block, offset + 0x0C, volume);
133+
WriteInt(block, offset + 0x10, distortion);
134+
WriteInt(block, offset + 0x14, distortion2);
135+
WriteShort(block, offset + 0x18, off18);
136+
WriteShort(block, offset + 0x1A, listIndex);
137+
WriteInt(block, offset + 0x1C, off1C);
138+
return block;
139+
}
140+
141+
[Fact]
142+
public void Constructor_ParsesAllFieldsCorrectly()
143+
{
144+
byte[] block = BuildSoundBlock(0, 1, 10.0f, 100, 50, 5, 3, 7, 42, 0xABCD);
145+
var sound = new ModelSound(block, 0);
146+
147+
Assert.Equal(1, sound.off00);
148+
Assert.Equal(10.0f, sound.distance);
149+
Assert.Equal(100, sound.masterVolume);
150+
Assert.Equal(50, sound.volume);
151+
Assert.Equal(5, sound.distortion);
152+
Assert.Equal(3, sound.distortion2);
153+
Assert.Equal((short) 7, sound.off18);
154+
Assert.Equal((short) 42, sound.listIndex);
155+
Assert.Equal(0xABCD, sound.off1C);
156+
}
157+
158+
[Fact]
159+
public void Serialize_RoundTrip_MatchesOriginal()
160+
{
161+
byte[] original = BuildSoundBlock(0, 1, 10.0f, 100, 50, 5, 3, 7, 42, 0xABCD);
162+
var sound = new ModelSound(original, 0);
163+
byte[] serialized = sound.Serialize();
164+
165+
Assert.Equal(original, serialized);
166+
}
167+
168+
[Fact]
169+
public void Serialize_AtIndex_RoundTrip()
170+
{
171+
byte[] original = BuildSoundBlock(3, 9, -5.5f, 0, 255, -1, -2, -3, 0, 0);
172+
var sound = new ModelSound(original, 3);
173+
byte[] serialized = sound.Serialize();
174+
175+
Assert.Equal(0x20, serialized.Length);
176+
var sound2 = new ModelSound(serialized, 0);
177+
Assert.Equal(sound.off00, sound2.off00);
178+
Assert.Equal(sound.distance, sound2.distance);
179+
Assert.Equal(sound.volume, sound2.volume);
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)