Skip to content

Commit 8fb2500

Browse files
authored
Update nefs binary templates (#86)
* Update nefs binary templates * Add nefs versions 0.1.0, 0.2.0, 1.3.0, 1.4.0 * Add binary template for engine bundle files
1 parent b54f6c1 commit 8fb2500

File tree

6 files changed

+627
-240
lines changed

6 files changed

+627
-240
lines changed

src/010 Templates/bdl.bt

Lines changed: 245 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -8,104 +8,264 @@
88
// Category:
99
// File Mask:
1010
// ID Bytes:
11-
// History: Label BDL files
11+
// History: Label BDL (engine bundle) files
1212
//------------------------------------------------
1313
LittleEndian();
1414

1515
struct {
16+
char magic[4];
17+
int32 version;
18+
19+
// 104: Dirt 2/3
20+
// 106: F1 2010-2015, Grid 2, Grid Autosport, Grid 2019
21+
local int64 nextPos <hidden=true> = 8;
22+
if (version >= 101)
23+
{
24+
float volumeThrottle;
25+
float volumeIdle;
26+
nextPos = 16;
27+
28+
if (version >= 102)
29+
{
30+
int32 extraBytes;
31+
nextPos = 20 + extraBytes;
32+
float volumeThrottle;
33+
float volumeIdle;
34+
35+
if (version >= 103)
36+
{
37+
int32 timbreCompensate; // bool != 0
38+
int32 pitchCompensate; // bool != 0
39+
40+
if (version >= 104)
41+
{
42+
int32 remappingOption;
43+
}
44+
}
45+
}
46+
}
47+
48+
FSeek(nextPos);
49+
int sourceRpmTimbre[2];
50+
int destRpmTimbre[2];
51+
int sourceRpmPitch[2];
52+
int destRpmPitch[2];
53+
54+
if (version >= 105)
55+
{
56+
float dynamic[2];
57+
}
58+
} header;
59+
60+
typedef struct {
1661
char magic[4];
1762
uint version;
63+
64+
int32 unused;
65+
int32 firingsPerCycle;
66+
float crLoops;
67+
float crGranular;
68+
float timeLapse;
69+
float xFadeReductionRate;
70+
71+
// 107: Dirt 2/3
72+
// 113: F1 2010-2017, Grid 2, Grid Autosport
73+
// 114: F1 2019, Grid 2019
74+
local int32 fmt = 0;
75+
local int32 rate = 48000;
76+
if (version >= 101)
77+
{
78+
if (version >= 108)
79+
{
80+
if (version >= 113)
81+
{
82+
int32 damageWobbleLength[3];
83+
int32 unused;
84+
}
85+
86+
int32 compressedDataType;
87+
fmt = compressedDataType;
88+
if (version >= 109)
89+
{
90+
int32 suggestedPlaybackRate;
91+
rate = suggestedPlaybackRate;
92+
}
93+
}
1894

19-
switch (version)
95+
float gearChangeLoopForceAmount;
96+
float gearChangeLoopForceReductionRate;
97+
98+
if (version >= 102)
99+
{
100+
int32 groupFiringsInBlocksOf;
101+
102+
if (version >= 103)
103+
{
104+
int32 sectionSize;
105+
int32 loopEnforceZc;
106+
int32 loopSuggestZc;
107+
108+
if (version >= 104)
109+
{
110+
uchar wobbleAssignments[8];
111+
uchar wobbleVolumes[8];
112+
113+
local int32 numWobbles;
114+
if (version == 104)
115+
{
116+
numWobbles = 3;
117+
}
118+
else if (version < 107)
119+
{
120+
numWobbles = 6;
121+
}
122+
else
123+
{
124+
numWobbles = (version >= 114 ? 12 : version >= 111 ? 4 : 0) + 9;
125+
}
126+
127+
struct {
128+
int32 length <comment="Should be <= 128">;
129+
if (version >= 105)
130+
{
131+
int32 looping;
132+
}
133+
134+
// first float is multiplier, next volume
135+
// conversion: (ushort)(val * 4096.0 + 0.5)
136+
float multiplierVolumes[128 * 2];
137+
} wobbles[numWobbles] <optimize=false>;
138+
139+
if (version >= 106)
140+
{
141+
int32 wobbleGearAvoidanceMask[version >= 114 ? 16 : version >= 106 ? 8 : 5];
142+
}
143+
}
144+
}
145+
}
146+
}
147+
148+
int32 sourceLength;
149+
if (sourceLength < 0)
150+
{
151+
// use compressed data
152+
//sourceLength = -sourceLength;
153+
}
154+
else
20155
{
21-
case 104: // Dirt 2/3
22-
byte data[64];
156+
int16 sourceSample[sourceLength];
157+
}
158+
159+
int32 sourceRpmTableSize;
160+
float sourceRpmTable[sourceRpmTableSize];
161+
int32 numberOfZeroCrossings;
162+
double zeroCrossings[numberOfZeroCrossings];
163+
164+
switch (fmt)
165+
{
166+
case 0: // adpcm
167+
int32 compressedDataLength;
168+
local uint32 numBlocks = (compressedDataLength - 1152) / 19;
169+
float predictionFilters[32];
170+
float dataInterpreters[256];
171+
typedef struct {
172+
ubyte lowerNibble;
173+
ubyte upper0;
174+
ubyte upper1;
175+
176+
ubyte index;
177+
ubyte diIndices[15];
178+
} AdpcmBlock;
179+
AdpcmBlock blocks[numBlocks];
180+
181+
local int16 samples[32 * numBlocks];
182+
local int16 sample0u <hidden=true>;
183+
local int16 sample1u <hidden=true>;
184+
local float sample0f <hidden=true>;
185+
local float sample1f <hidden=true>;
186+
local ubyte pfIndex <hidden=true>;
187+
local float pf0 <hidden=true>;
188+
local float pf1 <hidden=true>;
189+
local ubyte diIndexUpper <hidden=true>;
190+
local ubyte diIndexLower <hidden=true>;
191+
local int32 i <hidden=true>;
192+
local int32 oi <hidden=true>;
193+
local int32 j <hidden=true>;
194+
for (i = 0; i < numBlocks; ++i)
195+
{
196+
sample0u =
197+
((int16)blocks[i].upper0 << 8) | ((blocks[i].lowerNibble & 0x0F) << 4);
198+
sample1u =
199+
((int16)blocks[i].upper1 << 8) | (blocks[i].lowerNibble & 0xF0);
200+
201+
oi = i * 32;
202+
sample0f = (float)sample0u;
203+
samples[oi + 0] = sample0u;
204+
sample1f = (float)sample1u;
205+
samples[oi + 1] = sample1u;
206+
207+
pfIndex = (blocks[i].index & 0x0F) * 2;
208+
pf0 = predictionFilters[pfIndex];
209+
pf1 = predictionFilters[pfIndex + 1];
210+
diIndexUpper = blocks[i].index & 0xF0;
211+
for (j = 0; j < 15; ++j)
212+
{
213+
diIndexLower = blocks[i].diIndices[j];
214+
sample0f = sample0f * pf1 + sample1f * pf0 +
215+
dataInterpreters[diIndexUpper + (diIndexLower & 0x0F)];
216+
samples[oi + j * 2 + 2] = (int16)Clamp(sample0f, -0x8000, 0x7FFF);
217+
218+
sample1f = sample1f * pf1 + sample0f * pf0 +
219+
dataInterpreters[diIndexUpper + (diIndexLower >> 4)];
220+
samples[oi + j * 2 + 3] = (int16)Clamp(sample0f, -0x8000, 0x7FFF);
221+
}
222+
}
223+
224+
int32 compressionIterationsDone;
225+
float compressionNoiseLevel;
226+
int32 compressionSampleRate[3];
23227
break;
24-
case 106: // F1 2010-2015, Grid 2, Grid 2019
25-
byte data[88];
228+
case 1: // ulaw
229+
int32 compressedDataLength;
230+
byte compressedData[compressedDataLength];
231+
int32 compressionIterationsDone;
232+
float compressionNoiseLevel;
233+
int32 compressionSampleRate[3];
234+
break;
235+
case 2:
236+
byte unk3[24];
26237
break;
27238
}
28-
} bndlChunk;
29239

30-
while (FEof() == 0)
31-
{
240+
int32 numLoops;
32241
struct {
33-
char magic[4];
34-
uint version;
35-
36-
local uint fmt = 0;
37-
local uint rate = 48000;
38-
switch (version)
39-
{
40-
case 107: // Dirt 2/3
41-
byte data[36];
42-
uint numData2;
43-
byte data2[numData2];
44-
break;
45-
case 113: // F1 2010-2017, Grid 2
46-
case 114: // F1 2019, Grid 2019 -- has more numData2 21760 (vs 13472)
47-
byte data[40];
48-
uint format;
49-
uint sampleRate;
50-
float unknown[2];
51-
uint unknown2;
52-
uint numData2;
53-
byte data2[numData2];
54-
55-
fmt = format;
56-
break;
57-
byte data[40];
58-
uint format;
59-
uint sampleRate;
60-
float unknown[2];
61-
uint unknown2;
62-
uint numData2;
63-
byte data2[numData2];
64-
65-
fmt = format;
66-
break;
67-
}
242+
float rpm;
243+
int startZc;
244+
int endZc;
245+
int startXFade;
246+
int endXFade;
247+
int xFadePower;
248+
int loopStyle;
249+
char name[64];
250+
} loops[numLoops];
251+
} EngineSound;
68252

69-
switch (fmt)
70-
{
71-
case 0:
72-
byte unknown3[4];
73-
uint numUnk1;
74-
float unk1s[numUnk1];
75-
uint numUnk2;
76-
byte unk2s[numUnk2 * 8];
77-
uint size;
78-
local uint numBlocks = (size - 1152) / 19;
79-
float table1[16];
80-
float table2[16];
81-
float table3[256];
82-
struct {
83-
ubyte blockData[19];
84-
} adpcmBlock[numBlocks];
85-
byte unk3[20];
86-
break;
87-
case 1:
88-
byte unknown3[4];
89-
uint numUnk1;
90-
float unk1s[numUnk1];
91-
uint numUnk2;
92-
byte unk2s[numUnk2 * 8];
93-
uint size;
94-
byte audioData[size];
95-
byte unk3[20];
96-
break;
97-
case 2:
98-
uint32 numSamples;
99-
byte audioData[numSamples * 2];
100-
uint numUnk1;
101-
float unk1s[numUnk1];
102-
uint numUnk2;
103-
byte unk2s[numUnk2 * 8];
104-
byte unk3[24];
105-
break;
106-
}
253+
EngineSound throttle;
254+
EngineSound idle;
255+
EngineSound throttle;
256+
EngineSound idle;
107257

108-
uint numUnk4;
109-
byte unk4s[numUnk4 * 92];
110-
} egoeChunk;
258+
int32 Clamp(int32 val, int32 min, int32 max)
259+
{
260+
if (val < min)
261+
{
262+
return min;
263+
}
264+
265+
if (val > max)
266+
{
267+
return max;
268+
}
269+
270+
return val;
111271
}

0 commit comments

Comments
 (0)