Subversion Repositories Games.Carmageddon

Rev

Rev 18 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include "piping.h"
20 pmbaty 2
#include "brender/brender.h"
1 pmbaty 3
#include "car.h"
4
#include "crush.h"
5
#include "errors.h"
6
#include "globvars.h"
7
#include "globvrpb.h"
8
#include "graphics.h"
9
#include "harness/trace.h"
10
#include "oil.h"
11
#include "opponent.h"
12
#include "pedestrn.h"
13
#include "replay.h"
14
#include "skidmark.h"
15
#include "sound.h"
16
#include "spark.h"
17
#include "sys.h"
18
#include "utility.h"
19
#include "world.h"
20
#include <stdlib.h>
21
#include <string.h>
22
 
23
tU8* gPipe_buffer_start = NULL;
24
int gDisable_sound = 0;
25
int gDisable_advance = 0;
26
int gMax_rewind_chunks = 1000;
27
float gWall_severity = 0.f;
28
tPipe_reset_proc* gReset_procs[32] = {
29
    NULL,
30
    NULL,
31
    NULL,
32
    NULL,
33
    NULL,
34
    NULL,
35
    NULL,
36
    NULL,
37
    NULL,
38
    NULL,
39
    NULL,
40
    ResetAllPedestrians,
41
    NULL,
42
    NULL,
43
    NULL,
44
    NULL,
45
    NULL,
46
    ResetAllPedGibs,
47
    NULL,
48
    ResetSparks,
49
    ResetShrapnel,
50
    ResetScreenWobble,
51
    NULL,
52
    NULL,
53
    ResetSmoke,
54
    NULL,
55
    NULL,
56
    NULL,
57
    NULL,
58
    NULL,
59
    ResetProxRay,
60
    NULL,
61
};
62
tPiped_registration_snapshot gRegistration_snapshots[5];
63
tPipe_smudge_data* gSmudge_space;
64
tU32 gOldest_time;
65
int gCurrent_snapshot_registration_index;
66
tPipe_chunk* gMr_chunky;
67
tCar_spec* gCar_ptr;
68
br_vector3 gZero_vector;
69
tPipe_chunk_type gReentrancy_array[5];
70
tU32 gLast_time;
71
tPipe_model_geometry_data* gModel_geometry_space;
72
tU32 gEnd_time;
73
tU32 gTrigger_time;
74
int gReentrancy_count;
75
br_vector3 gCar_pos;
76
br_vector3 gReference_pos;
77
br_scalar gMax_distance;
78
tU32 gLoop_abort_time;
79
br_vector3 gWall_impact_point;
80
tU8* gPipe_buffer_working_end;
81
tU32 gYoungest_time;
82
tU8* gPipe_buffer_phys_end;
83
tU8* gLocal_buffer_record_ptr;
84
tU8* gPipe_play_ptr;
85
tU8* gEnd_of_session;
86
tU8* gPipe_record_ptr;
87
tU8* gPipe_buffer_oldest;
88
tU32 gPipe_buffer_size;
89
tU8* gLocal_buffer;
90
tU32 gLocal_buffer_size;
91
tPipe_chunk* gIncidentChunk; // FIXME: added by DethRace (really needed?)
92
 
93
#define LOCAL_BUFFER_SIZE 15000
94
 
95
#if defined(DETHRACE_REPLAY_DEBUG)
96
#define REPLAY_DEBUG_CHUNK_MAGIC1 0x1ed6ef85
97
#define REPLAY_DEBUG_SESSION_MAGIC1 0x617bbc04
98
#define REPLAY_DEBUG_ASSERT(test) assert(test)
99
#include <assert.h>
100
#else
101
#define REPLAY_DEBUG_ASSERT(test)
102
#endif
103
 
104
#if defined(DETHRACE_FIX_BUGS)
105
#define PIPE_ALIGN(V) (((V) + sizeof(void*) - 1) & ~(sizeof(void*) - 1))
106
#endif
107
 
108
// IDA: void __usercall GetReducedPos(br_vector3 *v@<EAX>, tReduced_pos *p@<EDX>)
109
void GetReducedPos(br_vector3* v, tReduced_pos* p) {
110
    LOG_TRACE("(%p, %p)", v, p);
111
 
112
    v->v[0] = p->v[0] / 800.f;
113
    v->v[1] = p->v[1] / 800.f;
114
    v->v[2] = p->v[2] / 800.f;
115
    BrVector3Accumulate(v, &gProgram_state.current_car.car_master_actor->t.t.translate.t);
116
}
117
 
118
// IDA: void __usercall SaveReducedPos(tReduced_pos *p@<EAX>, br_vector3 *v@<EDX>)
119
void SaveReducedPos(tReduced_pos* p, br_vector3* v) {
120
    br_vector3 tv;
121
    LOG_TRACE("(%p, %p)", p, v);
122
 
123
    BrVector3Sub(&tv, v, &gProgram_state.current_car.car_master_actor->t.t.translate.t);
124
    p->v[0] = tv.v[0] * 800.f;
125
    p->v[1] = tv.v[1] * 800.f;
126
    p->v[2] = tv.v[2] * 800.f;
127
}
128
 
129
// IDA: int __cdecl PipeSearchForwards()
130
int PipeSearchForwards(void) {
131
    LOG_TRACE("()");
132
 
133
    if (gPipe_play_ptr == gPipe_record_ptr) {
134
        return 0;
135
    }
136
    if (gPipe_play_ptr == gPipe_buffer_oldest) {
137
        return 1;
138
    }
139
    if (GetReplayRate() == 0.f) {
140
        return GetReplayDirection() > 0;
141
    } else {
142
        return GetReplayRate() > 0.f;
143
    }
144
}
145
 
146
// IDA: int __cdecl IsActionReplayAvailable()
147
int IsActionReplayAvailable(void) {
148
    LOG_TRACE("()");
149
 
150
    return gPipe_buffer_start != NULL;
151
}
152
 
153
// IDA: int __cdecl SomeReplayLeft()
154
int SomeReplayLeft(void) {
155
    LOG_TRACE("()");
156
 
157
    return ((GetReplayDirection() >= 1 && gPipe_play_ptr != gPipe_record_ptr) || (GetReplayDirection() <= -1 && gPipe_play_ptr != gPipe_buffer_oldest));
158
}
159
 
160
// IDA: void __cdecl DisablePipedSounds()
161
void DisablePipedSounds(void) {
162
    LOG_TRACE("()");
163
 
164
    gDisable_sound = 1;
165
}
166
 
167
// IDA: void __cdecl EnablePipedSounds()
168
void EnablePipedSounds(void) {
169
    LOG_TRACE("()");
170
 
171
    gDisable_sound = 0;
172
}
173
 
174
// IDA: tU32 __usercall LengthOfSession@<EAX>(tPipe_session *pSession@<EAX>)
175
tU32 LengthOfSession(tPipe_session* pSession) {
176
    int i;
177
    tU32 running_total;
178
    tPipe_chunk* the_chunk;
179
    LOG_TRACE("(%p)", pSession);
180
 
181
#define SIZEOF_CHUNK(MEMBER) (offsetof(tPipe_chunk, chunk_data) + sizeof(pSession->chunks.chunk_data.MEMBER))
182
#define ROUND_UP(V, M) (((V) + (M)-1) & (~((M)-1)))
183
 
184
    REPLAY_DEBUG_ASSERT(pSession->pipe_magic1 == REPLAY_DEBUG_SESSION_MAGIC1);
185
 
186
    switch (pSession->chunk_type) {
187
    case ePipe_chunk_actor_rstyle:
188
        running_total = SIZEOF_CHUNK(actor_rstyle_data) * pSession->number_of_chunks;
189
        break;
190
    case ePipe_chunk_actor_translate:
191
        running_total = SIZEOF_CHUNK(actor_translate_data) * pSession->number_of_chunks;
192
        break;
193
    case ePipe_chunk_actor_transform:
194
        running_total = SIZEOF_CHUNK(actor_transform_data) * pSession->number_of_chunks;
195
        break;
196
    case ePipe_chunk_actor_create:
197
        running_total = 0;
198
        break;
199
    case ePipe_chunk_actor_destroy:
200
        running_total = 0;
201
        break;
202
    case ePipe_chunk_actor_relink:
203
        running_total = SIZEOF_CHUNK(actor_relink_data) * pSession->number_of_chunks;
204
        break;
205
    case ePipe_chunk_actor_material:
206
        running_total = SIZEOF_CHUNK(actor_material_data) * pSession->number_of_chunks;
207
        break;
208
    case ePipe_chunk_face_material:
209
        running_total = SIZEOF_CHUNK(face_material_data) * pSession->number_of_chunks;
210
        break;
211
    case ePipe_chunk_material_trans:
212
        running_total = SIZEOF_CHUNK(material_trans_data) * pSession->number_of_chunks;
213
        break;
214
    case ePipe_chunk_material_pixelmap:
215
        running_total = SIZEOF_CHUNK(material_pixelmap_data) * pSession->number_of_chunks;
216
        break;
217
    case ePipe_chunk_model_geometry:
218
        running_total = 0;
219
        for (i = 0; i < pSession->number_of_chunks; i++) {
220
            the_chunk = (tPipe_chunk*)&((tU8*)&pSession->chunks)[running_total];
221
            running_total += the_chunk->chunk_data.model_geometry_data.vertex_count * sizeof(tChanged_vertex) + offsetof(tPipe_model_geometry_data, vertex_changes) + offsetof(tPipe_chunk, chunk_data);
222
        }
223
        break;
224
    case ePipe_chunk_pedestrian:
225
        running_total = 0;
226
        for (i = 0; i < pSession->number_of_chunks; i++) {
227
            the_chunk = (tPipe_chunk*)&(((tU8*)&pSession->chunks)[running_total]);
228
            if (the_chunk->chunk_data.pedestrian_data.hit_points <= 0) {
229
                running_total += SIZEOF_CHUNK(pedestrian_data);
230
            } else {
231
                running_total += offsetof(tPipe_pedestrian_data, spin_period) + offsetof(tPipe_chunk, chunk_data);
232
            }
233
        }
234
        break;
235
    case ePipe_chunk_frame_boundary:
236
        running_total = SIZEOF_CHUNK(frame_boundary_data);
237
        break;
238
    case ePipe_chunk_car:
239
        running_total = SIZEOF_CHUNK(car_data) * pSession->number_of_chunks;
240
        break;
241
    case ePipe_chunk_sound:
242
        running_total = SIZEOF_CHUNK(sound_data) * pSession->number_of_chunks;
243
        break;
244
    case ePipe_chunk_damage:
245
        running_total = SIZEOF_CHUNK(damage_data);
246
        break;
247
    case ePipe_chunk_special:
248
        running_total = SIZEOF_CHUNK(special_data) * pSession->number_of_chunks;
249
        break;
250
    case ePipe_chunk_ped_gib:
251
        running_total = SIZEOF_CHUNK(ped_gib_data) * pSession->number_of_chunks;
252
        break;
253
    case ePipe_chunk_incident:
254
        running_total = SIZEOF_CHUNK(incident_data) * pSession->number_of_chunks;
255
        break;
256
    case ePipe_chunk_spark:
257
        running_total = SIZEOF_CHUNK(spark_data) * pSession->number_of_chunks;
258
        break;
259
    case ePipe_chunk_shrapnel:
260
        running_total = 0;
261
        for (i = 0; i < pSession->number_of_chunks; i++) {
262
            the_chunk = (tPipe_chunk*)&((tU8*)&pSession->chunks)[running_total];
263
            if (the_chunk->subject_index & 0x8000) {
264
                running_total += SIZEOF_CHUNK(shrapnel_data);
265
            } else {
266
                running_total += offsetof(tPipe_shrapnel_data, age) + offsetof(tPipe_chunk, chunk_data);
267
            }
268
        }
269
        break;
270
    case ePipe_chunk_screen_shake:
271
        running_total = SIZEOF_CHUNK(screen_shake_data) * pSession->number_of_chunks;
272
        break;
273
    case ePipe_chunk_groove_stop:
274
        running_total = SIZEOF_CHUNK(groove_stop_data) * pSession->number_of_chunks;
275
        break;
276
    case ePipe_chunk_non_car:
277
        running_total = SIZEOF_CHUNK(non_car_data) * pSession->number_of_chunks;
278
        break;
279
    case ePipe_chunk_smoke:
280
        running_total = SIZEOF_CHUNK(smoke_data) * pSession->number_of_chunks;
281
        break;
282
    case ePipe_chunk_oil_spill:
283
        running_total = SIZEOF_CHUNK(oil_data) * pSession->number_of_chunks;
284
        break;
285
    case ePipe_chunk_smoke_column:
286
        running_total = ROUND_UP(SIZEOF_CHUNK(smoke_column_data), 4) * pSession->number_of_chunks;
287
        break;
288
    case ePipe_chunk_flame:
289
        running_total = SIZEOF_CHUNK(flame_data) * pSession->number_of_chunks;
290
        break;
291
    case ePipe_chunk_smudge:
292
        running_total = 0;
293
        for (i = 0; i < pSession->number_of_chunks; i++) {
294
            the_chunk = (tPipe_chunk*)&((tU8*)&pSession->chunks)[running_total];
295
            running_total += the_chunk->chunk_data.smudge_data.vertex_count * sizeof(tSmudged_vertex) + offsetof(tPipe_smudge_data, vertex_changes) + offsetof(tPipe_chunk, chunk_data);
296
        }
297
        break;
298
    case ePipe_chunk_splash:
299
        running_total = SIZEOF_CHUNK(splash_data) * pSession->number_of_chunks;
300
        break;
301
    case ePipe_chunk_prox_ray:
302
        running_total = SIZEOF_CHUNK(prox_ray_data) * pSession->number_of_chunks;
303
        break;
304
    case ePipe_chunk_skid_adjustment:
305
        running_total = SIZEOF_CHUNK(skid_adjustment) * pSession->number_of_chunks;
306
        break;
307
    default:
308
        running_total = 0;
309
        break;
310
    }
311
    running_total += offsetof(tPipe_session, chunks) + sizeof(tU16);
312
    if (running_total % 2 != 0) {
313
        FatalError(kFatalError_PipingSystem);
314
    }
315
    return running_total;
316
}
317
 
318
// IDA: void __usercall StartPipingSession2(tPipe_chunk_type pThe_type@<EAX>, int pMunge_reentrancy@<EDX>)
319
void StartPipingSession2(tPipe_chunk_type pThe_type, int pMunge_reentrancy) {
320
    LOG_TRACE("(%d, %d)", pThe_type, pMunge_reentrancy);
321
 
322
    if (gPipe_buffer_start != NULL && !gAction_replay_mode && gProgram_state.racing) {
323
        if (pMunge_reentrancy) {
324
            if (gReentrancy_count != 0) {
325
                gReentrancy_array[gReentrancy_count - 1] = ((tPipe_session*)gLocal_buffer)->chunk_type;
326
                EndPipingSession2(0);
327
            }
328
            gReentrancy_count++;
329
        }
330
        ((tPipe_session*)gLocal_buffer)->chunk_type = pThe_type;
331
        ((tPipe_session*)gLocal_buffer)->number_of_chunks = 0;
332
#if defined(DETHRACE_REPLAY_DEBUG)
333
        ((tPipe_session*)gLocal_buffer)->pipe_magic1 = REPLAY_DEBUG_SESSION_MAGIC1;
334
#endif
335
        gLocal_buffer_size = offsetof(tPipe_session, chunks);
336
        gMr_chunky = &((tPipe_session*)gLocal_buffer)->chunks;
337
    }
338
}
339
 
340
// IDA: void __usercall StartPipingSession(tPipe_chunk_type pThe_type@<EAX>)
341
void StartPipingSession(tPipe_chunk_type pThe_type) {
342
    LOG_TRACE("(%d)", pThe_type);
343
 
344
    StartPipingSession2(pThe_type, 1);
345
}
346
 
347
// IDA: void __usercall EndPipingSession2(int pMunge_reentrancy@<EAX>)
348
void EndPipingSession2(int pMunge_reentrancy) {
349
    int a;
350
    LOG_TRACE("(%d)", pMunge_reentrancy);
351
 
352
    if (gPipe_buffer_start != NULL && !gAction_replay_mode && gProgram_state.racing) {
353
        // Each session ends with a tU16, containing the session size
354
        *(tU16*)&gLocal_buffer[gLocal_buffer_size] = gLocal_buffer_size;
355
        a = gLocal_buffer_size;
356
        gLocal_buffer_size += sizeof(tU16);
357
        REPLAY_DEBUG_ASSERT(LengthOfSession((tPipe_session*)gLocal_buffer) == gLocal_buffer_size);
358
#if defined(DETHRACE_FIX_BUGS)
359
        gLocal_buffer_size = PIPE_ALIGN(gLocal_buffer_size);
360
        *(tU16*)&gLocal_buffer[gLocal_buffer_size - sizeof(tU16)] = gLocal_buffer_size - sizeof(tU16);
361
#endif
362
        if (((tPipe_session*)gLocal_buffer)->number_of_chunks != 0 && (gLocal_buffer_size < LOCAL_BUFFER_SIZE || a == LOCAL_BUFFER_SIZE - 2)) {
363
            if (gPipe_buffer_phys_end < gPipe_record_ptr + gLocal_buffer_size) {
364
                // Put session at begin of pipe, as no place at end
365
                gPipe_buffer_working_end = gPipe_record_ptr;
366
                gPipe_buffer_oldest = gPipe_buffer_start;
367
                gPipe_record_ptr = gPipe_buffer_start;
368
            }
369
            while (gPipe_record_ptr <= gPipe_buffer_oldest && gPipe_buffer_oldest < gPipe_record_ptr + gLocal_buffer_size) {
370
                // Remove older sessions
371
#if defined(DETHRACE_FIX_BUGS)
372
                gPipe_buffer_oldest += PIPE_ALIGN(LengthOfSession((tPipe_session*)gPipe_buffer_oldest));
373
#else
374
                gPipe_buffer_oldest += LengthOfSession((tPipe_session*)gPipe_buffer_oldest);
375
#endif
376
                if (gPipe_buffer_working_end <= gPipe_buffer_oldest) {
377
                    gPipe_buffer_working_end = gPipe_buffer_phys_end;
378
                    gPipe_buffer_oldest = gPipe_buffer_start;
379
                }
380
            }
381
            if (gPipe_buffer_oldest == NULL) {
382
                gPipe_buffer_oldest = gPipe_record_ptr;
383
            }
384
            memcpy(gPipe_record_ptr, gLocal_buffer, gLocal_buffer_size);
385
            gPipe_record_ptr += gLocal_buffer_size;
386
            if (gPipe_buffer_working_end < gPipe_record_ptr) {
387
                gPipe_buffer_working_end = gPipe_record_ptr;
388
            }
389
        }
390
        if (pMunge_reentrancy) {
391
            if (gReentrancy_count != 0) {
392
                gReentrancy_count--;
393
                if (gReentrancy_count != 0) {
394
                    StartPipingSession2(gReentrancy_array[gReentrancy_count - 1], 0);
395
                }
396
            }
397
        }
398
    }
399
}
400
 
401
// IDA: void __cdecl EndPipingSession()
402
void EndPipingSession(void) {
403
    LOG_TRACE("()");
404
 
405
    EndPipingSession2(1);
406
}
407
 
408
// IDA: void __usercall AddDataToSession(int pSubject_index@<EAX>, void *pData@<EDX>, tU32 pData_length@<EBX>)
409
void AddDataToSession(int pSubject_index, void* pData, tU32 pData_length) {
410
    tU32 temp_buffer_size;
411
    //int variable_for_breaking_on; // Pierre-Marie Baty -- unused variable
412
    LOG_TRACE("(%d, %p, %d)", pSubject_index, pData, pData_length);
413
 
414
    if (gPipe_buffer_start != NULL && !gAction_replay_mode && gProgram_state.racing) {
415
        temp_buffer_size = gLocal_buffer_size + offsetof(tPipe_chunk, chunk_data) + pData_length;
416
        if (temp_buffer_size >= LOCAL_BUFFER_SIZE) {
417
            return;
418
        }
419
        REPLAY_DEBUG_ASSERT(((tPipe_session*)gLocal_buffer)->pipe_magic1 == REPLAY_DEBUG_SESSION_MAGIC1);
420
        ((tPipe_session*)gLocal_buffer)->number_of_chunks++;
421
        gMr_chunky->subject_index = pSubject_index;
422
#if defined(DETHRACE_REPLAY_DEBUG)
423
        gMr_chunky->chunk_magic1 = REPLAY_DEBUG_CHUNK_MAGIC1;
424
#endif
425
        memcpy(&gMr_chunky->chunk_data, pData, pData_length);
426
        gMr_chunky = (tPipe_chunk*)(((tU8*)&gMr_chunky->chunk_data) + pData_length);
427
        gLocal_buffer_size = temp_buffer_size;
428
    }
429
}
430
 
431
// IDA: void __usercall AddModelGeometryToPipingSession(tU16 pCar_ID@<EAX>, int pModel_index@<EDX>, int pVertex_count@<EBX>, tChanged_vertex *pCoordinates@<ECX>)
432
void AddModelGeometryToPipingSession(tU16 pCar_ID, int pModel_index, int pVertex_count, tChanged_vertex* pCoordinates) {
433
    tU32 data_size;
434
    LOG_TRACE("(%d, %d, %d, %p)", pCar_ID, pModel_index, pVertex_count, pCoordinates);
435
 
436
    if (gModel_geometry_space != NULL) {
437
        if (pVertex_count > 600) {
438
            pVertex_count = 600;
439
        }
440
        data_size = offsetof(tPipe_model_geometry_data, vertex_changes) + pVertex_count * sizeof(tChanged_vertex);
441
        gModel_geometry_space->vertex_count = pVertex_count;
442
        gModel_geometry_space->model_index = pModel_index;
443
        memcpy(gModel_geometry_space->vertex_changes, pCoordinates, pVertex_count * sizeof(tChanged_vertex));
444
        AddDataToSession(pCar_ID, gModel_geometry_space, data_size);
445
    }
446
}
447
 
448
// IDA: void __usercall AddSmudgeToPipingSession(tU16 pCar_ID@<EAX>, int pModel_index@<EDX>, int pVertex_count@<EBX>, tSmudged_vertex *pCoordinates@<ECX>)
449
void AddSmudgeToPipingSession(tU16 pCar_ID, int pModel_index, int pVertex_count, tSmudged_vertex* pCoordinates) {
450
    tU32 data_size;
451
    LOG_TRACE("(%d, %d, %d, %p)", pCar_ID, pModel_index, pVertex_count, pCoordinates);
452
 
453
    if (gSmudge_space != NULL) {
454
        if (pVertex_count > 600) {
455
            pVertex_count = 600;
456
        }
457
        gSmudge_space->vertex_count = pVertex_count;
458
        gSmudge_space->model_index = pModel_index;
459
        memcpy(gSmudge_space->vertex_changes, pCoordinates, pVertex_count * sizeof(tSmudged_vertex));
460
        data_size = offsetof(tPipe_smudge_data, vertex_changes) + pVertex_count * sizeof(tSmudged_vertex);
461
        AddDataToSession(pCar_ID, gSmudge_space, data_size);
462
    }
463
}
464
 
465
// IDA: void __usercall AddPedestrianToPipingSession(int pPedestrian_index@<EAX>, br_matrix34 *pTrans@<EDX>, tU8 pAction_index@<EBX>, tU8 pFrame_index@<ECX>, tS8 pHit_points, int pDone_initial, tU16 pParent_ID, float pSpin_period, br_scalar pJump_magnitude, br_vector3 *pOffset)
466
void AddPedestrianToPipingSession(int pPedestrian_index, br_matrix34* pTrans, tU8 pAction_index, tU8 pFrame_index, tS8 pHit_points, int pDone_initial, tU16 pParent_ID, float pSpin_period, br_scalar pJump_magnitude, br_vector3* pOffset) {
467
    tPipe_pedestrian_data data;
468
    tU32 data_size;
469
    LOG_TRACE("(%d, %p, %d, %d, %d, %d, %d, %f, %f, %p)", pPedestrian_index, pTrans, pAction_index, pFrame_index, pHit_points, pDone_initial, pParent_ID, pSpin_period, pJump_magnitude, pOffset);
470
 
471
    if (pFrame_index == 0xff) {
472
        pFrame_index = 0;
473
    }
474
    data.action_and_frame_index = (pDone_initial ? 1 : 0) << 7 | pAction_index << 4 | pFrame_index;
475
    data.hit_points = pHit_points;
476
    data.new_translation.v[0] = pTrans->m[3][0];
477
    data.new_translation.v[1] = pTrans->m[3][1];
478
    data.new_translation.v[2] = pTrans->m[3][2];
479
    data.parent = pParent_ID;
480
    if (pHit_points <= 0) {
481
        data.spin_period = pSpin_period;
482
        data.parent_actor = GetPedestrianActor(pPedestrian_index)->parent;
483
        BrVector3Copy(&data.offset, pOffset);
484
        data.jump_magnitude = pJump_magnitude;
485
        data_size = sizeof(tPipe_pedestrian_data);
486
    } else {
487
        data_size = offsetof(tPipe_pedestrian_data, spin_period);
488
    }
489
    AddDataToSession(pPedestrian_index, &data, data_size);
490
}
491
 
492
// IDA: void __usercall AddSparkToPipingSession(int pSpark_index@<EAX>, br_vector3 *pPos@<EDX>, br_vector3 *pV@<EBX>)
493
void AddSparkToPipingSession(int pSpark_index, br_vector3* pPos, br_vector3* pV) {
494
    tPipe_spark_data data;
495
    LOG_TRACE("(%d, %p, %p)", pSpark_index, pPos, pV);
496
 
497
    BrVector3Copy(&data.pos, pPos);
498
    BrVector3Copy(&data.v, pV);
499
    AddDataToSession(pSpark_index, &data, sizeof(tPipe_spark_data));
500
}
501
 
502
// IDA: void __usercall AddShrapnelToPipingSession(int pShrapnel_index@<EAX>, br_vector3 *pPos@<EDX>, tU16 pAge@<EBX>, br_material *pMaterial@<ECX>)
503
void AddShrapnelToPipingSession(int pShrapnel_index, br_vector3* pPos, tU16 pAge, br_material* pMaterial) {
504
    tPipe_shrapnel_data data;
505
    tU32 data_size;
506
    LOG_TRACE("(%d, %p, %d, %p)", pShrapnel_index, pPos, pAge, pMaterial);
507
 
508
    BrVector3Copy(&data.pos, pPos);
509
    if ((pShrapnel_index & 0x8000) != 0) {
510
        data.age = pAge;
511
        data.material = pMaterial;
512
        data_size = sizeof(tPipe_shrapnel_data);
513
    } else {
514
        data_size = offsetof(tPipe_shrapnel_data, age);
515
    }
516
    AddDataToSession(pShrapnel_index, &data, data_size);
517
}
518
 
519
// IDA: void __usercall AddScreenWobbleToPipingSession(int pWobble_x@<EAX>, int pWobble_y@<EDX>)
520
void AddScreenWobbleToPipingSession(int pWobble_x, int pWobble_y) {
521
    tPipe_screen_shake_data data;
522
    LOG_TRACE("(%d, %d)", pWobble_x, pWobble_y);
523
 
524
    data.wobble_x = pWobble_x;
525
    data.wobble_y = pWobble_y;
526
    AddDataToSession(0, &data, sizeof(tPipe_screen_shake_data));
527
}
528
 
529
// IDA: void __usercall AddGrooveStopToPipingSession(int pGroove_index@<EAX>, br_matrix34 *pMatrix@<EDX>, int pPath_interrupt@<EBX>, int pObject_interrupt@<ECX>, float pPath_resumption, float pObject_resumption)
530
void AddGrooveStopToPipingSession(int pGroove_index, br_matrix34* pMatrix, int pPath_interrupt, int pObject_interrupt, float pPath_resumption, float pObject_resumption) {
531
    tPipe_groove_stop_data data;
532
    LOG_TRACE("(%d, %p, %d, %d, %f, %f)", pGroove_index, pMatrix, pPath_interrupt, pObject_interrupt, pPath_resumption, pObject_resumption);
533
 
534
    BrMatrix34Copy(&data.matrix, pMatrix);
535
    data.path_interrupt = pPath_interrupt;
536
    data.object_interrupt = pObject_interrupt;
537
    data.path_resumption = pPath_resumption;
538
    data.object_resumption = pObject_resumption;
539
    AddDataToSession(pGroove_index, &data, sizeof(tPipe_groove_stop_data));
540
}
541
 
542
// IDA: void __usercall AddNonCarToPipingSession(int pIndex@<EAX>, br_actor *pActor@<EDX>)
543
void AddNonCarToPipingSession(int pIndex, br_actor* pActor) {
544
    tPipe_non_car_data data;
545
    LOG_TRACE("(%d, %p)", pIndex, pActor);
546
 
547
    BrMatrix34Copy(&data.mat, &pActor->t.t.mat);
548
    data.actor = pActor;
549
    AddDataToSession(pIndex, &data, sizeof(tPipe_non_car_data));
550
}
551
 
552
// IDA: void __usercall AddSmokeToPipingSession(int pIndex@<EAX>, tU8 pType@<EDX>, br_vector3 *pPos@<EBX>, br_scalar pRadius, br_scalar pStrength)
553
void AddSmokeToPipingSession(int pIndex, tU8 pType, br_vector3* pPos, br_scalar pRadius, br_scalar pStrength) {
554
    tPipe_smoke_data data;
555
    LOG_TRACE("(%d, %d, %p, %f, %f)", pIndex, pType, pPos, pRadius, pStrength);
556
 
557
    SaveReducedPos(&data.pos, pPos);
558
    data.type = pType;
559
    data.radius = pRadius * 1024.f;
560
    data.strength = pStrength * 255.f;
561
    AddDataToSession(pIndex, &data, sizeof(tPipe_smoke_data));
562
}
563
 
564
// IDA: void __usercall AddSmokeColumnToPipingSession(int pIndex@<EAX>, tCar_spec *pCar@<EDX>, int pVertex@<EBX>, int pColour@<ECX>)
565
void AddSmokeColumnToPipingSession(int pIndex, tCar_spec* pCar, int pVertex, int pColour) {
566
    tPipe_smoke_column_data data;
567
    LOG_TRACE("(%d, %p, %d, %d)", pIndex, pCar, pVertex, pColour);
568
 
569
    data.car_ID = pCar->car_ID;
570
    data.vertex = pVertex;
571
    AddDataToSession(pColour << 14 | pIndex, &data, sizeof(tPipe_smoke_column_data));
572
}
573
 
574
// IDA: void __usercall AddFlameToPipingSession(int pIndex@<EAX>, int pFrame_count@<EDX>, br_scalar pScale_x, br_scalar pScale_y, br_scalar pOffset_x, br_scalar pOffset_z)
575
void AddFlameToPipingSession(int pIndex, int pFrame_count, br_scalar pScale_x, br_scalar pScale_y, br_scalar pOffset_x, br_scalar pOffset_z) {
576
    tPipe_flame_data data;
577
    LOG_TRACE("(%d, %d, %f, %f, %f, %f)", pIndex, pFrame_count, pScale_x, pScale_y, pOffset_x, pOffset_z);
578
 
579
    data.frame_count = pFrame_count;
580
    data.scale_x = pScale_x;
581
    data.scale_y = pScale_y;
582
    data.offset_x = pOffset_x;
583
    data.offset_z = pOffset_z;
584
    AddDataToSession(pIndex, &data, sizeof(tPipe_flame_data));
585
}
586
 
587
// IDA: void __usercall AddSplashToPipingSession(tCollision_info *pCar@<EAX>)
588
void AddSplashToPipingSession(tCollision_info* pCar) {
589
    tPipe_splash_data data;
590
    LOG_TRACE("(%p)", pCar);
591
 
592
    if (pCar->driver >= eDriver_oppo) {
593
        data.d = pCar->water_d;
594
        BrVector3Copy(&data.normal, &pCar->water_normal);
595
        AddDataToSession(pCar->car_ID, &data, sizeof(tPipe_splash_data));
596
    }
597
}
598
 
599
// IDA: void __usercall AddOilSpillToPipingSession(int pIndex@<EAX>, br_matrix34 *pMat@<EDX>, br_scalar pFull_size, br_scalar pGrow_rate, tU32 pSpill_time, tU32 pStop_time, tCar_spec *pCar, br_vector3 *pOriginal_pos, br_pixelmap *pPixelmap)
600
void AddOilSpillToPipingSession(int pIndex, br_matrix34* pMat, br_scalar pFull_size, br_scalar pGrow_rate, tU32 pSpill_time, tU32 pStop_time, tCar_spec* pCar, br_vector3* pOriginal_pos, br_pixelmap* pPixelmap) {
601
    tPipe_oil_spill_data data;
602
    LOG_TRACE("(%d, %p, %f, %f, %d, %d, %p, %p, %p)", pIndex, pMat, pFull_size, pGrow_rate, pSpill_time, pStop_time, pCar, pOriginal_pos, pPixelmap);
603
 
604
    BrMatrix34Copy(&data.mat, pMat);
605
    data.full_size = pFull_size;
606
    data.grow_rate = pGrow_rate;
607
    data.spill_time = pSpill_time;
608
    data.previous_stop_time = pStop_time;
609
    data.car = pCar;
610
    BrVector3Copy(&data.original_pos, pOriginal_pos);
611
    data.pixelmap = pPixelmap;
612
    AddDataToSession(pIndex, &data, sizeof(tPipe_oil_spill_data));
613
}
614
 
615
// IDA: void __usercall AddFrameFinishToPipingSession(tU32 pThe_time@<EAX>)
616
void AddFrameFinishToPipingSession(tU32 pThe_time) {
617
    tPipe_frame_boundary_data data;
618
    LOG_TRACE("(%d)", pThe_time);
619
 
620
    data.time = pThe_time;
621
    AddDataToSession(0, &data, sizeof(tPipe_frame_boundary_data));
622
}
623
 
624
// IDA: void __usercall AddCarToPipingSession(int pCar_ID@<EAX>, br_matrix34 *pCar_mat@<EDX>, br_vector3 *pCar_velocity@<EBX>, float pSpeedo_speed, float pLf_sus_position, float pRf_sus_position, float pLr_sus_position, float pRr_sus_position, float pSteering_angle, br_scalar pRevs, int pGear, int pFrame_coll_flag)
625
void AddCarToPipingSession(int pCar_ID, br_matrix34* pCar_mat, br_vector3* pCar_velocity, float pSpeedo_speed, float pLf_sus_position, float pRf_sus_position, float pLr_sus_position, float pRr_sus_position, float pSteering_angle, br_scalar pRevs, int pGear, int pFrame_coll_flag) {
626
    tPipe_car_data data;
627
    LOG_TRACE("(%d, %p, %p, %f, %f, %f, %f, %f, %f, %f, %d, %d)", pCar_ID, pCar_mat, pCar_velocity, pSpeedo_speed, pLf_sus_position, pRf_sus_position, pLr_sus_position, pRr_sus_position, pSteering_angle, pRevs, pGear, pFrame_coll_flag);
628
 
629
    BrMatrix34Copy(&data.transformation, pCar_mat);
630
    BrVector3Copy(&data.velocity, pCar_velocity);
631
    data.speedo_speed = pSpeedo_speed * 32767.f / 0.07f;
632
    data.lf_sus_position = pLf_sus_position * 127.f / .15f;
633
    data.rf_sus_position = pRf_sus_position * 127.f / .15f;
634
    data.lr_sus_position = pLr_sus_position * 127.f / .15f;
635
    data.rr_sus_position = pRr_sus_position * 127.f / .15f;
636
    data.steering_angle = pSteering_angle * 32767.f / 60.f;
637
    data.revs_and_gear = (pGear + 1) << 12 | (pFrame_coll_flag ? 0 : 1) << 11 | ((((int)pRevs) / 10) & 0x7ff);
638
    AddDataToSession(pCar_ID, &data, sizeof(tPipe_car_data));
639
}
640
 
641
// IDA: void __usercall AddSoundToPipingSession(tS3_outlet_ptr pOutlet@<EAX>, int pSound_index@<EDX>, tS3_volume pL_volume@<EBX>, tS3_volume pR_volume@<ECX>, tS3_pitch pPitch, br_vector3 *pPos)
642
void AddSoundToPipingSession(tS3_outlet_ptr pOutlet, int pSound_index, tS3_volume pL_volume, tS3_volume pR_volume, tS3_pitch pPitch, br_vector3* pPos) {
643
    tPipe_sound_data data;
644
    LOG_TRACE("(%d, %d, %d, %d, %d, %p)", pOutlet, pSound_index, pL_volume, pR_volume, pPitch, pPos);
645
 
646
    data.pitch = pPitch;
647
    if (pPos == NULL) {
648
        BrVector3Set(&data.position, 0.f, 0.f, 0.f);
649
    } else {
650
        BrVector3Copy(&data.position, pPos);
651
    }
652
    data.volume = (pR_volume << 8) | (pL_volume << 0);
653
    data.outlet_index = GetIndexFromOutlet(pOutlet);
654
    AddDataToSession(pSound_index, &data, sizeof(tPipe_sound_data));
655
}
656
 
657
// IDA: void __usercall AddDamageToPipingSession(int pCar_ID@<EAX>, tS8 *pDifferences@<EDX>)
658
void AddDamageToPipingSession(int pCar_ID, tS8* pDifferences) {
659
    tPipe_damage_data data;
660
    int i;
661
    LOG_TRACE("(%d, %p)", pCar_ID, pDifferences);
662
 
663
    for (i = 0; i < COUNT_OF(data.damage_delta); i++) {
664
        data.damage_delta[i] = pDifferences[i];
665
    }
666
    AddDataToSession(pCar_ID, &data, sizeof(tPipe_damage_data));
667
}
668
 
669
// IDA: void __usercall AddSpecialToPipingSession(tSpecial_type pType@<EAX>)
670
void AddSpecialToPipingSession(tSpecial_type pType) {
671
    tPipe_special_data data;
672
    LOG_TRACE("(%d)", pType);
673
 
674
    AddDataToSession(pType, &data, sizeof(tPipe_special_data));
675
}
676
 
677
// IDA: void __usercall AddPedGibToPipingSession(int pIndex@<EAX>, br_matrix34 *pTrans@<EDX>, int pSize@<EBX>, int pGib_index@<ECX>, int pPed_index)
678
void AddPedGibToPipingSession(int pIndex, br_matrix34* pTrans, int pSize, int pGib_index, int pPed_index) {
679
    tPipe_ped_gib_data data;
680
    LOG_TRACE("(%d, %p, %d, %d, %d)", pIndex, pTrans, pSize, pGib_index, pPed_index);
681
 
682
    data.ped_parent_index = pPed_index;
683
    data.size = pSize;
684
    data.gib_index = pGib_index;
685
    BrMatrix34Copy(&data.transform, pTrans);
686
    AddDataToSession(pIndex, &data, sizeof(tPipe_ped_gib_data));
687
}
688
 
689
// IDA: void __cdecl AddCarIncidentToPipingSession(float pSeverity, tCar_spec *pCar, br_vector3 *pImpact_point)
690
void AddCarIncidentToPipingSession(float pSeverity, tCar_spec* pCar, br_vector3* pImpact_point) {
691
    tPipe_incident_data data;
692
    LOG_TRACE("(%f, %p, %p)", pSeverity, pCar, pImpact_point);
693
 
694
    data.severity = pSeverity;
695
    data.info.car_info.car_ID = pCar->car_ID;
696
    BrVector3Copy(&data.info.car_info.impact_point, pImpact_point);
697
    AddDataToSession(1, &data, sizeof(tPipe_incident_data));
698
}
699
 
700
// IDA: void __usercall AddPedIncidentToPipingSession(int pPed_index@<EAX>, br_actor *pActor@<EDX>)
701
void AddPedIncidentToPipingSession(int pPed_index, br_actor* pActor) {
702
    tPipe_incident_data data;
703
    LOG_TRACE("(%d, %p)", pPed_index, pActor);
704
 
705
    data.severity = 0.f;
706
    data.info.ped_info.ped_index = pPed_index;
707
    data.info.ped_info.actor = pActor;
708
    AddDataToSession(0, &data, sizeof(tPipe_incident_data));
709
}
710
 
711
// IDA: void __cdecl AddWallIncidentToPipingSession(float pSeverity, br_vector3 *pImpact_point)
712
void AddWallIncidentToPipingSession(float pSeverity, br_vector3* pImpact_point) {
713
    tPipe_incident_data data;
714
    LOG_TRACE("(%f, %p)", pSeverity, pImpact_point);
715
 
716
    data.severity = pSeverity;
717
    BrVector3Copy(&data.info.wall_info.pos, pImpact_point);
718
    AddDataToSession(2, &data, sizeof(tPipe_incident_data));
719
}
720
 
721
// IDA: void __usercall AddProxRayToPipingSession(int pRay_index@<EAX>, tCar_spec *pCar@<EDX>, tU16 pPed_index@<EBX>, tU32 pTime@<ECX>)
722
void AddProxRayToPipingSession(int pRay_index, tCar_spec* pCar, tU16 pPed_index, tU32 pTime) {
723
    tPipe_prox_ray_data data;
724
    LOG_TRACE("(%d, %p, %d, %d)", pRay_index, pCar, pPed_index, pTime);
725
 
726
    data.ped_index = pPed_index;
727
    data.car_ID = pCar->car_ID;
728
    data.time = pTime;
729
    AddDataToSession(pRay_index, &data, sizeof(tPipe_prox_ray_data));
730
}
731
 
732
// IDA: void __usercall AddSkidAdjustmentToPipingSession(int pSkid_num@<EAX>, br_matrix34 *pMatrix@<EDX>, int pMaterial_index@<EBX>)
733
void AddSkidAdjustmentToPipingSession(int pSkid_num, br_matrix34* pMatrix, int pMaterial_index) {
734
    tPipe_skid_adjustment adjustment;
735
    LOG_TRACE("(%d, %p, %d)", pSkid_num, pMatrix, pMaterial_index);
736
 
737
    BrMatrix34Copy(&adjustment.matrix, pMatrix);
738
    adjustment.material_index = pMaterial_index;
739
    AddDataToSession(pSkid_num, &adjustment, sizeof(tPipe_skid_adjustment));
740
}
741
 
742
// IDA: void __usercall PipeSingleModelGeometry(tU16 pCar_ID@<EAX>, int pModel_index@<EDX>, int pVertex_count@<EBX>, tChanged_vertex *pCoordinates@<ECX>)
743
void PipeSingleModelGeometry(tU16 pCar_ID, int pModel_index, int pVertex_count, tChanged_vertex* pCoordinates) {
744
    LOG_TRACE("(%d, %d, %d, %p)", pCar_ID, pModel_index, pVertex_count, pCoordinates);
745
 
746
    StartPipingSession(ePipe_chunk_model_geometry);
747
    AddModelGeometryToPipingSession(pCar_ID, pModel_index, pVertex_count, pCoordinates);
748
    EndPipingSession();
749
}
750
 
751
// IDA: void __usercall PipeSinglePedestrian(int pPedestrian_index@<EAX>, br_matrix34 *pTrans@<EDX>, tU8 pAction_index@<EBX>, tU8 pFrame_index@<ECX>, tS8 pHit_points, int pDone_initial, tU16 pParent_ID, float pSpin_period, br_scalar pJump_magnitude, br_vector3 *pOffset)
752
void PipeSinglePedestrian(int pPedestrian_index, br_matrix34* pTrans, tU8 pAction_index, tU8 pFrame_index, tS8 pHit_points, int pDone_initial, tU16 pParent_ID, float pSpin_period, br_scalar pJump_magnitude, br_vector3* pOffset) {
753
    LOG_TRACE("(%d, %p, %d, %d, %d, %d, %d, %f, %f, %p)", pPedestrian_index, pTrans, pAction_index, pFrame_index, pHit_points, pDone_initial, pParent_ID, pSpin_period, pJump_magnitude, pOffset);
754
 
755
    StartPipingSession(ePipe_chunk_pedestrian);
756
    AddPedestrianToPipingSession(pPedestrian_index, pTrans, pAction_index,
757
        pFrame_index, pHit_points, pDone_initial, pParent_ID, pSpin_period,
758
        pJump_magnitude, pOffset);
759
    EndPipingSession();
760
}
761
 
762
// IDA: void __usercall PipeSingleCar(int pCar_ID@<EAX>, br_matrix34 *pCar_mat@<EDX>, br_vector3 *pCar_velocity@<EBX>, float pSpeedo_speed, float pLf_sus_position, float pRf_sus_position, float pLr_sus_position, float pRr_sus_position, float pSteering_angle, br_scalar pRevs, int pGear, int pFrame_coll_flag)
763
void PipeSingleCar(int pCar_ID, br_matrix34* pCar_mat, br_vector3* pCar_velocity, float pSpeedo_speed, float pLf_sus_position, float pRf_sus_position, float pLr_sus_position, float pRr_sus_position, float pSteering_angle, br_scalar pRevs, int pGear, int pFrame_coll_flag) {
764
    LOG_TRACE("(%d, %p, %p, %f, %f, %f, %f, %f, %f, %f, %d, %d)", pCar_ID, pCar_mat, pCar_velocity, pSpeedo_speed, pLf_sus_position, pRf_sus_position, pLr_sus_position, pRr_sus_position, pSteering_angle, pRevs, pGear, pFrame_coll_flag);
765
 
766
    StartPipingSession(ePipe_chunk_car);
767
    AddCarToPipingSession(pCar_ID, pCar_mat, pCar_velocity, pSpeedo_speed,
768
        pLf_sus_position, pRf_sus_position, pLr_sus_position, pRr_sus_position,
769
        pSteering_angle, pRevs, pGear, pFrame_coll_flag);
770
    EndPipingSession();
771
}
772
 
773
// IDA: void __usercall PipeSingleSound(tS3_outlet_ptr pOutlet@<EAX>, int pSound_index@<EDX>, tS3_volume pL_volume@<EBX>, tS3_volume pR_volume@<ECX>, tS3_pitch pPitch, br_vector3 *pPos)
774
void PipeSingleSound(tS3_outlet_ptr pOutlet, int pSound_index, tS3_volume pL_volume, tS3_volume pR_volume, tS3_pitch pPitch, br_vector3* pPos) {
775
    LOG_TRACE("(%d, %d, %d, %d, %d, %p)", pOutlet, pSound_index, pL_volume, pR_volume, pPitch, pPos);
776
 
777
    if (!gAction_replay_mode && gProgram_state.racing) {
778
        StartPipingSession(ePipe_chunk_sound);
779
        AddSoundToPipingSession(pOutlet, pSound_index, pL_volume, pR_volume, pPitch, pPos);
780
        EndPipingSession();
781
    }
782
}
783
 
784
// IDA: void __usercall PipeSingleOilSpill(int pIndex@<EAX>, br_matrix34 *pMat@<EDX>, br_scalar pFull_size, br_scalar pGrow_rate, tU32 pSpill_time, tU32 pStop_time, tCar_spec *pCar, br_vector3 *pOriginal_pos, br_pixelmap *pPixelmap)
785
void PipeSingleOilSpill(int pIndex, br_matrix34* pMat, br_scalar pFull_size, br_scalar pGrow_rate, tU32 pSpill_time, tU32 pStop_time, tCar_spec* pCar, br_vector3* pOriginal_pos, br_pixelmap* pPixelmap) {
786
    LOG_TRACE("(%d, %p, %f, %f, %d, %d, %p, %p, %p)", pIndex, pMat, pFull_size, pGrow_rate, pSpill_time, pStop_time, pCar, pOriginal_pos, pPixelmap);
787
 
788
    StartPipingSession(ePipe_chunk_oil_spill);
789
    AddOilSpillToPipingSession(pIndex, pMat, pFull_size, pGrow_rate,
790
        pSpill_time, pStop_time, pCar, pOriginal_pos, pPixelmap);
791
    EndPipingSession();
792
}
793
 
794
// IDA: void __usercall PipeSingleDamage(int pCar_ID@<EAX>, tS8 *pDifferences@<EDX>)
795
void PipeSingleDamage(int pCar_ID, tS8* pDifferences) {
796
    LOG_TRACE("(%d, %p)", pCar_ID, pDifferences);
797
 
798
    StartPipingSession(ePipe_chunk_damage);
799
    AddDamageToPipingSession(pCar_ID, pDifferences);
800
    EndPipingSession();
801
}
802
 
803
// IDA: void __usercall PipeSingleSpecial(tSpecial_type pType@<EAX>)
804
void PipeSingleSpecial(tSpecial_type pType) {
805
    LOG_TRACE("(%d)", pType);
806
 
807
    StartPipingSession(ePipe_chunk_special);
808
    AddSpecialToPipingSession(pType);
809
    EndPipingSession();
810
}
811
 
812
// IDA: void __usercall PipeSinglePedGib(int pIndex@<EAX>, br_matrix34 *pTrans@<EDX>, int pSize@<EBX>, int pGib_index@<ECX>, int pPed_index)
813
void PipeSinglePedGib(int pIndex, br_matrix34* pTrans, int pSize, int pGib_index, int pPed_index) {
814
    LOG_TRACE("(%d, %p, %d, %d, %d)", pIndex, pTrans, pSize, pGib_index, pPed_index);
815
 
816
    StartPipingSession(ePipe_chunk_ped_gib);
817
    AddPedGibToPipingSession(pIndex, pTrans, pSize, pGib_index, pPed_index);
818
    EndPipingSession();
819
}
820
 
821
// IDA: void __cdecl PipeSingleCarIncident(float pSeverity, tCar_spec *pCar, br_vector3 *pImpact_point)
822
void PipeSingleCarIncident(float pSeverity, tCar_spec* pCar, br_vector3* pImpact_point) {
823
    LOG_TRACE("(%f, %p, %p)", pSeverity, pCar, pImpact_point);
824
 
825
    StartPipingSession(ePipe_chunk_incident);
826
    AddCarIncidentToPipingSession(pSeverity, pCar, pImpact_point);
827
    EndPipingSession();
828
}
829
 
830
// IDA: void __usercall PipeSinglePedIncident(int pPed_index@<EAX>, br_actor *pActor@<EDX>)
831
void PipeSinglePedIncident(int pPed_index, br_actor* pActor) {
832
    LOG_TRACE("(%d, %p)", pPed_index, pActor);
833
 
834
    StartPipingSession(ePipe_chunk_incident);
835
    AddPedIncidentToPipingSession(pPed_index, pActor);
836
    EndPipingSession();
837
    gWall_severity = 0.f;
838
}
839
 
840
// IDA: void __cdecl PipeSingleWallIncident(float pSeverity, br_vector3 *pImpact_point)
841
void PipeSingleWallIncident(float pSeverity, br_vector3* pImpact_point) {
842
    LOG_TRACE("(%f, %p)", pSeverity, pImpact_point);
843
 
844
    if (pSeverity > gWall_severity) {
845
        gWall_severity = pSeverity;
846
        BrVector3Copy(&gWall_impact_point, pImpact_point);
847
    }
848
}
849
 
850
// IDA: void __usercall PipeSingleScreenShake(int pWobble_x@<EAX>, int pWobble_y@<EDX>)
851
void PipeSingleScreenShake(int pWobble_x, int pWobble_y) {
852
    LOG_TRACE("(%d, %d)", pWobble_x, pWobble_y);
853
 
854
    StartPipingSession(ePipe_chunk_screen_shake);
855
    AddScreenWobbleToPipingSession(pWobble_x, pWobble_y);
856
    EndPipingSession();
857
}
858
 
859
// IDA: void __usercall PipeSingleGrooveStop(int pGroove_index@<EAX>, br_matrix34 *pMatrix@<EDX>, int pPath_interrupt@<EBX>, int pObject_interrupt@<ECX>, float pPath_resumption, float pObject_resumption)
860
void PipeSingleGrooveStop(int pGroove_index, br_matrix34* pMatrix, int pPath_interrupt, int pObject_interrupt, float pPath_resumption, float pObject_resumption) {
861
    LOG_TRACE("(%d, %p, %d, %d, %f, %f)", pGroove_index, pMatrix, pPath_interrupt, pObject_interrupt, pPath_resumption, pObject_resumption);
862
 
863
    StartPipingSession(ePipe_chunk_groove_stop);
864
    AddGrooveStopToPipingSession(pGroove_index, pMatrix, pPath_interrupt,
865
        pObject_interrupt, pPath_resumption, pObject_resumption);
866
    EndPipingSession();
867
}
868
 
869
// IDA: void __cdecl PipeFrameFinish()
870
void PipeFrameFinish(void) {
871
    LOG_TRACE("()");
872
 
873
    if (gWall_severity != 0.f) {
874
        StartPipingSession(ePipe_chunk_incident);
875
        AddWallIncidentToPipingSession(gWall_severity, &gWall_impact_point);
876
        EndPipingSession();
877
        gWall_severity = 0.f;
878
    }
879
    StartPipingSession(ePipe_chunk_frame_boundary);
880
    AddFrameFinishToPipingSession(GetTotalTime());
881
    EndPipingSession();
882
}
883
 
884
// IDA: void __cdecl PipingFrameReset()
885
void PipingFrameReset(void) {
886
    int i;
887
    LOG_TRACE("()");
888
 
889
    for (i = 0; i < COUNT_OF(gReset_procs); i++) {
890
        if (gReset_procs[i] != NULL) {
891
            gReset_procs[i]();
892
        }
893
    }
894
}
895
 
896
// IDA: void __usercall PipeSingleSkidAdjustment(int pSkid_num@<EAX>, br_matrix34 *pMatrix@<EDX>, int pMaterial_index@<EBX>)
897
void PipeSingleSkidAdjustment(int pSkid_num, br_matrix34* pMatrix, int pMaterial_index) {
898
    LOG_TRACE("(%d, %p, %d)", pSkid_num, pMatrix, pMaterial_index);
899
 
900
    StartPipingSession(ePipe_chunk_skid_adjustment);
901
    AddSkidAdjustmentToPipingSession(pSkid_num, pMatrix, pMaterial_index);
902
    EndPipingSession();
903
}
904
 
905
// IDA: void __cdecl ResetPiping()
906
void ResetPiping(void) {
907
    LOG_TRACE("()");
908
 
909
    gWall_severity = 0.f;
910
    gPipe_buffer_oldest = NULL;
911
    gPipe_record_ptr = gPipe_buffer_start;
912
    gPipe_buffer_working_end = gPipe_buffer_phys_end;
913
    gReentrancy_count = 0;
914
}
915
 
916
// IDA: void __cdecl InitialisePiping()
917
void InitialisePiping(void) {
918
    LOG_TRACE("()");
919
 
920
    if (!gAusterity_mode && gNet_mode == eNet_mode_none) {
921
        PDAllocateActionReplayBuffer((char**)&gPipe_buffer_start, &gPipe_buffer_size);
922
        gPipe_buffer_phys_end = gPipe_buffer_start + gPipe_buffer_size;
923
        gSmudge_space = BrMemAllocate(offsetof(tPipe_smudge_data, vertex_changes) + sizeof(tSmudged_vertex) * 2400, kMem_pipe_model_geometry);
924
        // DAT_00532008 = 0;
925
        BrVector3SetFloat(&gZero_vector, 0.f, 0.f, 0.f);
926
        gModel_geometry_space = (tPipe_model_geometry_data*)gSmudge_space;
927
        gLocal_buffer = BrMemAllocate(LOCAL_BUFFER_SIZE, kMem_pipe_model_geometry);
928
    } else {
929
        gPipe_buffer_start = NULL;
930
        gLocal_buffer = NULL;
931
        gModel_geometry_space = NULL;
932
        gSmudge_space = NULL;
933
    }
934
    ResetPiping();
935
}
936
 
937
// IDA: void __cdecl DisposePiping()
938
void DisposePiping(void) {
939
    LOG_TRACE("()");
940
 
941
    if (gPipe_buffer_start != NULL) {
942
        PDDisposeActionReplayBuffer((char*)gPipe_buffer_start);
943
    }
944
    gPipe_buffer_start = NULL;
945
    if (gModel_geometry_space != NULL) {
946
        BrMemFree(gModel_geometry_space);
947
        gModel_geometry_space = NULL;
948
    }
949
    if (gLocal_buffer != NULL) {
950
        BrMemFree(gLocal_buffer);
951
        gLocal_buffer = NULL;
952
    }
953
}
954
 
955
// IDA: void __cdecl InitLastDamageArrayEtc()
956
void InitLastDamageArrayEtc(void) {
957
    int i;
958
    int j;
959
    int cat;
960
    int car_count;
961
    tCar_spec* car;
962
    LOG_TRACE("()");
963
 
964
    for (cat = eVehicle_self; cat <= eVehicle_not_really; cat++) {
965
        if (cat == eVehicle_self) {
966
            car_count = 1;
967
        } else {
968
            car_count = GetCarCount(cat);
969
        }
970
        for (i = 0; i < car_count; i++) {
971
            if (cat == eVehicle_self) {
972
                car = &gProgram_state.current_car;
973
            } else {
974
                car = GetCarSpec(cat, i);
975
            }
976
            if (cat != eVehicle_not_really) {
977
                for (j = 0; j < COUNT_OF(car->frame_start_damage); j++) {
978
                    car->frame_start_damage[j] = 0;
979
                }
980
            }
981
            car->car_ID = (cat << 8) | i;
982
        }
983
    }
984
}
985
 
986
// IDA: void __cdecl ResetCars()
987
void ResetCars(void) {
988
    tCar_spec* car;
989
    int cat;
990
    int i;
991
    int car_count;
992
    LOG_TRACE("()");
993
 
994
    for (cat = eVehicle_self; cat < eVehicle_not_really; cat++) {
995
        if (cat == eVehicle_self) {
996
            car_count = 1;
997
        } else {
998
            car_count = GetCarCount(cat);
999
        }
1000
        for (i = 0; i < car_count; i++) {
1001
            if (cat == eVehicle_self) {
1002
                car = &gProgram_state.current_car;
1003
            } else {
1004
                car = GetCarSpec(cat, i);
1005
            }
1006
            car->active = 0;
1007
        }
1008
    }
1009
}
1010
 
1011
// IDA: void __cdecl PipeCarPositions()
1012
void PipeCarPositions(void) {
1013
    tCar_spec* car;
1014
    int cat;
1015
    int i;
1016
    int j;
1017
    int car_count;
1018
    int session_started;
1019
    int difference_found;
1020
    tS8 damage_deltas[12];
1021
    LOG_TRACE("()");
1022
 
1023
    StartPipingSession(ePipe_chunk_car);
1024
    for (cat = eVehicle_self; cat < eVehicle_not_really; cat++) {
1025
        if (cat == eVehicle_self) {
1026
            car_count = 1;
1027
        } else {
1028
            car_count = GetCarCount(cat);
1029
        }
1030
        for (i = 0; i < car_count; i++) {
1031
            if (cat == eVehicle_self) {
1032
                car = &gProgram_state.current_car;
1033
            } else {
1034
                car = GetCarSpec(cat, i);
1035
            }
1036
            AddCarToPipingSession((cat << 8) | i,
1037
                &car->car_master_actor->t.t.mat, &car->v, car->speedo_speed,
1038
                car->lf_sus_position, car->rf_sus_position, car->lr_sus_position, car->rr_sus_position,
1039
                car->steering_angle, car->revs, car->gear, car->frame_collision_flag);
1040
        }
1041
    }
1042
    EndPipingSession();
1043
    session_started = 0;
1044
    for (cat = eVehicle_self; cat < eVehicle_net_player; cat++) {
1045
        if (cat == eVehicle_self) {
1046
            car_count = 1;
1047
        } else {
1048
            car_count = GetCarCount(cat);
1049
        }
1050
        for (i = 0; i < car_count; i++) {
1051
            if (cat == eVehicle_self) {
1052
                car = &gProgram_state.current_car;
1053
            } else {
1054
                car = GetCarSpec(cat, i);
1055
            }
1056
            if (car->active) {
1057
                difference_found = 0;
1058
                for (j = 0; j < COUNT_OF(car->damage_units); j++) {
1059
                    damage_deltas[j] = car->damage_units[j].damage_level - car->frame_start_damage[j];
1060
                    difference_found |= damage_deltas[j];
1061
                    car->frame_start_damage[j] = car->damage_units[j].damage_level;
1062
                }
1063
                if (difference_found) {
1064
                    if (!session_started) {
1065
                        StartPipingSession(ePipe_chunk_damage);
1066
                        session_started = 1;
1067
                    }
1068
                    AddDamageToPipingSession((cat << 8) | i, damage_deltas);
1069
                }
1070
            }
1071
        }
1072
    }
1073
    if (session_started) {
1074
        EndPipingSession();
1075
    }
1076
}
1077
 
1078
// IDA: void __cdecl ResetPipePlayToEnd()
1079
void ResetPipePlayToEnd(void) {
1080
    LOG_TRACE("()");
1081
 
1082
    gPipe_play_ptr = gPipe_record_ptr;
1083
}
1084
 
1085
// IDA: void __cdecl ResetPipePlayToStart()
1086
void ResetPipePlayToStart(void) {
1087
    LOG_TRACE("()");
1088
 
1089
    gPipe_play_ptr = gPipe_buffer_oldest;
1090
}
1091
 
1092
// IDA: tU8* __cdecl GetPipePlayPtr()
1093
tU8* GetPipePlayPtr(void) {
1094
    LOG_TRACE("()");
1095
 
1096
    return gPipe_play_ptr;
1097
}
1098
 
1099
// IDA: void __usercall SetPipePlayPtr(tU8 *pPtr@<EAX>)
1100
void SetPipePlayPtr(tU8* pPtr) {
1101
    LOG_TRACE("(%p)", pPtr);
1102
 
1103
    gPipe_play_ptr = pPtr;
1104
}
1105
 
1106
// IDA: void __usercall AdvanceChunkPtr(tPipe_chunk **pChunk@<EAX>, tChunk_subject_index pType@<EDX>)
1107
void AdvanceChunkPtr(tPipe_chunk** pChunk, tChunk_subject_index pType) {
1108
    tPipe_chunk* old_chunk;
1109
    LOG_TRACE("(%p, %d)", pChunk, pType);
1110
 
1111
    old_chunk = *pChunk;
1112
    if (gDisable_advance) {
1113
        return;
1114
    }
1115
    switch (pType) {
1116
    case ePipe_chunk_model_geometry:
1117
        *(tU8**)pChunk += offsetof(tPipe_model_geometry_data, vertex_changes) + (*pChunk)->chunk_data.model_geometry_data.vertex_count * sizeof(tChanged_vertex);
1118
        break;
1119
    case ePipe_chunk_pedestrian:
1120
        *(tU8**)pChunk += (((*pChunk)->chunk_data.pedestrian_data.hit_points <= 0) ? sizeof(tPipe_pedestrian_data) : offsetof(tPipe_pedestrian_data, spin_period));
1121
        break;
1122
    case ePipe_chunk_frame_boundary:
1123
        *(tU8**)pChunk += sizeof(tPipe_frame_boundary_data);
1124
        break;
1125
    case ePipe_chunk_car:
1126
        *(tU8**)pChunk += sizeof(tPipe_car_data);
1127
        break;
1128
    case ePipe_chunk_sound:
1129
        *(tU8**)pChunk += sizeof(tPipe_sound_data);
1130
        break;
1131
    case ePipe_chunk_damage:
1132
        *(tU8**)pChunk += sizeof(tPipe_damage_data);
1133
        break;
1134
    case ePipe_chunk_special:
1135
        *(tU8**)pChunk += sizeof(tPipe_special_data);
1136
        break;
1137
    case ePipe_chunk_ped_gib:
1138
        *(tU8**)pChunk += sizeof(tPipe_ped_gib_data);
1139
        break;
1140
    case ePipe_chunk_incident:
1141
        *(tU8**)pChunk += sizeof(tPipe_incident_data);
1142
        break;
1143
    case ePipe_chunk_spark:
1144
        *(tU8**)pChunk += sizeof(tPipe_spark_data);
1145
        break;
1146
    case ePipe_chunk_shrapnel:
1147
        *(tU8**)pChunk += (((*pChunk)->subject_index & 0x8000) ? sizeof(tPipe_shrapnel_data) : offsetof(tPipe_shrapnel_data, age));
1148
        break;
1149
    case ePipe_chunk_screen_shake:
1150
        *(tU8**)pChunk += sizeof(tPipe_screen_shake_data);
1151
        break;
1152
    case ePipe_chunk_groove_stop:
1153
        *(tU8**)pChunk += sizeof(tPipe_groove_stop_data);
1154
        break;
1155
    case ePipe_chunk_non_car:
1156
        *(tU8**)pChunk += sizeof(tPipe_non_car_data);
1157
        break;
1158
    case ePipe_chunk_smoke:
1159
        *(tU8**)pChunk += sizeof(tPipe_smoke_data);
1160
        break;
1161
    case ePipe_chunk_oil_spill:
1162
        *(tU8**)pChunk += sizeof(tPipe_oil_spill_data);
1163
        break;
1164
    case ePipe_chunk_smoke_column:
1165
        *(tU8**)pChunk += sizeof(tPipe_smoke_column_data);
1166
        break;
1167
    case ePipe_chunk_flame:
1168
        *(tU8**)pChunk += sizeof(tPipe_flame_data);
1169
        break;
1170
    case ePipe_chunk_smudge:
1171
        *(tU8**)pChunk += offsetof(tPipe_smudge_data, vertex_changes) + (*pChunk)->chunk_data.smudge_data.vertex_count * sizeof(tSmudged_vertex);
1172
        break;
1173
    case ePipe_chunk_splash:
1174
        *(tU8**)pChunk += sizeof(tPipe_splash_data);
1175
        break;
1176
    case ePipe_chunk_prox_ray:
1177
        *(tU8**)pChunk += sizeof(tPipe_prox_ray_data);
1178
        break;
1179
    case ePipe_chunk_skid_adjustment:
1180
        *(tU8**)pChunk += sizeof(tPipe_skid_adjustment);
1181
        break;
1182
    }
1183
    *(tU8**)pChunk += offsetof(tPipe_chunk, chunk_data);
1184
 
1185
    /* Fail-safe to avoid reading junk data from the session after */
1186
    if (*(tU8**)pChunk == gEnd_of_session) {
1187
        *pChunk = old_chunk;
1188
    } else if (*(tU8**)pChunk > gEnd_of_session) {
1189
        *pChunk = old_chunk;
1190
    }
1191
}
1192
 
1193
// IDA: void __usercall ApplyModelGeometry(tPipe_chunk **pChunk@<EAX>)
1194
void ApplyModelGeometry(tPipe_chunk** pChunk) {
1195
    int i;
1196
    br_model* model_ptr;
1197
    tCar_spec* car;
1198
    LOG_TRACE("(%p)", pChunk);
1199
 
1200
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1201
        car = &gProgram_state.current_car;
1202
    } else {
1203
        car = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0xff);
1204
    }
1205
    model_ptr = car->car_model_actors[(*pChunk)->chunk_data.model_geometry_data.model_index].actor->model;
1206
    for (i = 0; i < (*pChunk)->chunk_data.model_geometry_data.vertex_count; i++) {
1207
        BrVector3Accumulate(&model_ptr->vertices[(*pChunk)->chunk_data.model_geometry_data.vertex_changes[i].vertex_index].p,
1208
            &(*pChunk)->chunk_data.model_geometry_data.vertex_changes[i].delta_coordinates);
1209
    }
1210
    SetModelForUpdate(model_ptr, car, 0);
1211
    AdvanceChunkPtr(pChunk, ePipe_chunk_model_geometry);
1212
}
1213
 
1214
// IDA: void __usercall DoSmudge(tPipe_chunk **pChunk@<EAX>, int pDir@<EDX>)
1215
void DoSmudge(tPipe_chunk** pChunk, int pDir) {
1216
    int i;
1217
    int v;
1218
    tU8 inc;
1219
    br_model* model_ptr;
1220
    tCar_spec* car;
1221
    //int group; // Pierre-Marie Baty -- unused variable
1222
    LOG_TRACE("(%p, %d)", pChunk, pDir);
1223
 
1224
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1225
        car = &gProgram_state.current_car;
1226
    } else {
1227
        car = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0xff);
1228
    }
1229
    model_ptr = car->car_model_actors[(*pChunk)->chunk_data.smudge_data.model_index].actor->model;
1230
    for (i = 0; i < (*pChunk)->chunk_data.smudge_data.vertex_count; i++) {
1231
        v = (*pChunk)->chunk_data.smudge_data.vertex_changes[i].vertex_index;
1232
        inc = (*pChunk)->chunk_data.smudge_data.vertex_changes[i].light_index * pDir;
1233
        V11MODEL(model_ptr)->groups->vertex_colours[v] = ((V11MODEL(model_ptr)->groups->vertex_colours[v] >> 24) + inc) << 24;
1234
        if (model_ptr->flags & BR_MODF_UPDATEABLE) {
1235
            model_ptr->vertices[V11MODEL(model_ptr)->groups->vertex_user[v]].index = (V11MODEL(model_ptr)->groups->vertex_colours[v] >> 24) + inc;
1236
        }
1237
    }
1238
}
1239
 
1240
// IDA: void __usercall ApplySmudge(tPipe_chunk **pChunk@<EAX>)
1241
void ApplySmudge(tPipe_chunk** pChunk) {
1242
    LOG_TRACE("(%p)", pChunk);
1243
 
1244
    DoSmudge(pChunk, 1);
1245
    AdvanceChunkPtr(pChunk, ePipe_chunk_smudge);
1246
}
1247
 
1248
// IDA: void __usercall ApplyPedestrian(tPipe_chunk **pChunk@<EAX>)
1249
void ApplyPedestrian(tPipe_chunk** pChunk) {
1250
    LOG_TRACE("(%p)", pChunk);
1251
 
1252
    AdjustPedestrian(
1253
        (*pChunk)->subject_index,
1254
        ((*pChunk)->chunk_data.pedestrian_data.action_and_frame_index & 0x70) >> 4,
1255
        (*pChunk)->chunk_data.pedestrian_data.action_and_frame_index & 0x0f,
1256
        (*pChunk)->chunk_data.pedestrian_data.hit_points,
1257
        (*pChunk)->chunk_data.pedestrian_data.action_and_frame_index >> 7,
1258
        (*pChunk)->chunk_data.pedestrian_data.parent,
1259
        (*pChunk)->chunk_data.pedestrian_data.parent_actor,
1260
        (*pChunk)->chunk_data.pedestrian_data.spin_period,
1261
        (*pChunk)->chunk_data.pedestrian_data.jump_magnitude,
1262
        &(*pChunk)->chunk_data.pedestrian_data.offset,
1263
        &(*pChunk)->chunk_data.pedestrian_data.new_translation);
1264
    AdvanceChunkPtr(pChunk, ePipe_chunk_pedestrian);
1265
}
1266
 
1267
// IDA: void __usercall ApplySpark(tPipe_chunk **pChunk@<EAX>)
1268
void ApplySpark(tPipe_chunk** pChunk) {
1269
    LOG_TRACE("(%p)", pChunk);
1270
 
1271
    AdjustSpark((*pChunk)->subject_index,
1272
        &(*pChunk)->chunk_data.spark_data.pos,
1273
        &(*pChunk)->chunk_data.spark_data.v);
1274
    AdvanceChunkPtr(pChunk, ePipe_chunk_spark);
1275
}
1276
 
1277
// IDA: void __usercall ApplyShrapnel(tPipe_chunk **pChunk@<EAX>)
1278
void ApplyShrapnel(tPipe_chunk** pChunk) {
1279
    LOG_TRACE("(%p)", pChunk);
1280
 
1281
    AdjustShrapnel((*pChunk)->subject_index,
1282
        &(*pChunk)->chunk_data.shrapnel_data.pos,
1283
        (*pChunk)->chunk_data.shrapnel_data.age,
1284
        (*pChunk)->chunk_data.shrapnel_data.material);
1285
    AdvanceChunkPtr(pChunk, ePipe_chunk_shrapnel);
1286
}
1287
 
1288
// IDA: void __usercall ApplyScreenWobble(tPipe_chunk **pChunk@<EAX>)
1289
void ApplyScreenWobble(tPipe_chunk** pChunk) {
1290
    LOG_TRACE("(%p)", pChunk);
1291
 
1292
    SetScreenWobble((*pChunk)->chunk_data.screen_shake_data.wobble_x,
1293
        (*pChunk)->chunk_data.screen_shake_data.wobble_y);
1294
    AdvanceChunkPtr(pChunk, ePipe_chunk_screen_shake);
1295
}
1296
 
1297
// IDA: void __usercall ApplyGrooveStop(tPipe_chunk **pChunk@<EAX>)
1298
void ApplyGrooveStop(tPipe_chunk** pChunk) {
1299
    LOG_TRACE("(%p)", pChunk);
1300
 
1301
    SetGrooveInterrupt((*pChunk)->subject_index,
1302
        &(*pChunk)->chunk_data.groove_stop_data.matrix,
1303
        (*pChunk)->chunk_data.groove_stop_data.path_interrupt,
1304
        (*pChunk)->chunk_data.groove_stop_data.object_interrupt,
1305
        (*pChunk)->chunk_data.groove_stop_data.path_resumption,
1306
        (*pChunk)->chunk_data.groove_stop_data.object_resumption);
1307
    AdvanceChunkPtr(pChunk, ePipe_chunk_groove_stop);
1308
}
1309
 
1310
// IDA: void __usercall ApplyNonCar(tPipe_chunk **pChunk@<EAX>)
1311
void ApplyNonCar(tPipe_chunk** pChunk) {
1312
    LOG_TRACE("(%p)", pChunk);
1313
 
1314
    AdjustNonCar((*pChunk)->chunk_data.non_car_data.actor,
1315
        &(*pChunk)->chunk_data.non_car_data.mat);
1316
    AdvanceChunkPtr(pChunk, ePipe_chunk_non_car);
1317
}
1318
 
1319
// IDA: void __usercall ApplySmoke(tPipe_chunk **pChunk@<EAX>)
1320
void ApplySmoke(tPipe_chunk** pChunk) {
1321
    br_vector3 pos;
1322
    LOG_TRACE("(%p)", pChunk);
1323
 
1324
    GetReducedPos(&pos, &(*pChunk)->chunk_data.smoke_data.pos);
1325
    AdjustSmoke((*pChunk)->subject_index,
1326
        (*pChunk)->chunk_data.smoke_data.type,
1327
        &pos,
1328
        (*pChunk)->chunk_data.smoke_data.radius / 1024.f,
1329
        (*pChunk)->chunk_data.smoke_data.strength / 256.f);
1330
    AdvanceChunkPtr(pChunk, ePipe_chunk_smoke);
1331
}
1332
 
1333
// IDA: void __usercall ApplySmokeColumn(tPipe_chunk **pChunk@<EAX>)
1334
void ApplySmokeColumn(tPipe_chunk** pChunk) {
1335
    LOG_TRACE("(%p)", pChunk);
1336
 
1337
    AdjustSmokeColumn((*pChunk)->subject_index & 0x3fff,
1338
        ((((*pChunk)->chunk_data.smoke_column_data.car_ID) >> 8) == 0) ? &gProgram_state.current_car : GetCarSpec((*pChunk)->chunk_data.smoke_column_data.car_ID >> 8, (*pChunk)->chunk_data.smoke_column_data.car_ID & 0xff),
1339
        (*pChunk)->chunk_data.smoke_column_data.vertex,
1340
        (*pChunk)->subject_index >> 14);
1341
    AdvanceChunkPtr(pChunk, ePipe_chunk_smoke_column);
1342
}
1343
 
1344
// IDA: void __usercall ApplyFlame(tPipe_chunk **pChunk@<EAX>)
1345
void ApplyFlame(tPipe_chunk** pChunk) {
1346
    LOG_TRACE("(%p)", pChunk);
1347
 
1348
    AdjustFlame((*pChunk)->subject_index,
1349
        (*pChunk)->chunk_data.flame_data.frame_count,
1350
        (*pChunk)->chunk_data.flame_data.scale_x,
1351
        (*pChunk)->chunk_data.flame_data.scale_y,
1352
        (*pChunk)->chunk_data.flame_data.offset_x,
1353
#if DETHRACE_FIX_BUGS
1354
        (*pChunk)->chunk_data.flame_data.offset_z);
1355
#else
1356
        (*pChunk)->chunk_data.flame_data.offset_x);
1357
#endif
1358
    AdvanceChunkPtr(pChunk, ePipe_chunk_flame);
1359
}
1360
 
1361
// IDA: void __usercall ApplySplash(tPipe_chunk **pChunk@<EAX>)
1362
void ApplySplash(tPipe_chunk** pChunk) {
1363
    tCar_spec* c;
1364
    LOG_TRACE("(%p)", pChunk);
1365
 
1366
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1367
        c = &gProgram_state.current_car;
1368
    } else {
1369
        c = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0xff);
1370
    }
1371
    c->water_d = (*pChunk)->chunk_data.splash_data.d;
1372
    BrVector3Copy(&c->water_normal, &(*pChunk)->chunk_data.splash_data.normal);
1373
    AdvanceChunkPtr(pChunk, ePipe_chunk_splash);
1374
}
1375
 
1376
// IDA: void __usercall ApplyOilSpill(tPipe_chunk **pChunk@<EAX>, tU32 pStop_time@<EDX>)
1377
void ApplyOilSpill(tPipe_chunk** pChunk, tU32 pStop_time) {
1378
    LOG_TRACE("(%p, %d)", pChunk, pStop_time);
1379
 
1380
    AdjustOilSpill((*pChunk)->subject_index,
1381
        &(*pChunk)->chunk_data.oil_data.mat,
1382
        (*pChunk)->chunk_data.oil_data.full_size,
1383
        (*pChunk)->chunk_data.oil_data.grow_rate,
1384
        (*pChunk)->chunk_data.oil_data.spill_time,
1385
        pStop_time,
1386
        (*pChunk)->chunk_data.oil_data.car,
1387
        &(*pChunk)->chunk_data.oil_data.original_pos,
1388
        (*pChunk)->chunk_data.oil_data.pixelmap);
1389
    AdvanceChunkPtr(pChunk, ePipe_chunk_oil_spill);
1390
}
1391
 
1392
// IDA: void __usercall ApplyFrameBoundary(tPipe_chunk **pChunk@<EAX>)
1393
void ApplyFrameBoundary(tPipe_chunk** pChunk) {
1394
    //tU32 result; // Pierre-Marie Baty -- unused variable
1395
    LOG_TRACE("(%p)", pChunk);
1396
 
1397
    gLast_replay_frame_time = (*pChunk)->chunk_data.frame_boundary_data.time;
1398
    // DAT_0054b244 = PDGetTotalTime();
1399
    AdvanceChunkPtr(pChunk, ePipe_chunk_frame_boundary);
1400
}
1401
 
1402
// IDA: void __usercall ApplySound(tPipe_chunk **pChunk@<EAX>)
1403
void ApplySound(tPipe_chunk** pChunk) {
1404
    LOG_TRACE("(%p)", pChunk);
1405
 
1406
    if (!gDisable_sound) {
1407
        if ((*pChunk)->chunk_data.sound_data.volume == 0) {
1408
            DRS3StartSound2(GetOutletFromIndex((*pChunk)->chunk_data.sound_data.outlet_index),
1409
                (*pChunk)->subject_index,
1410
                1,
1411
                -1,
1412
                -1,
1413
                65535.f * GetReplayRate(),
1414
                0x10000);
1415
        } else if (BrVector3LengthSquared(&(*pChunk)->chunk_data.sound_data.position) == 0) {
1416
            DRS3StartSound2(GetOutletFromIndex((*pChunk)->chunk_data.sound_data.outlet_index),
1417
                (*pChunk)->subject_index,
1418
                1,
1419
                (*pChunk)->chunk_data.sound_data.volume & 0xff,
1420
                (*pChunk)->chunk_data.sound_data.volume >> 8,
1421
                (float)(*pChunk)->chunk_data.sound_data.pitch * fabsf(GetReplayRate()),
1422
                0x10000);
1423
        } else {
1424
            DRS3StartSound3D(GetOutletFromIndex((*pChunk)->chunk_data.sound_data.outlet_index),
1425
                (*pChunk)->subject_index,
1426
                &(*pChunk)->chunk_data.sound_data.position,
1427
                &gZero_vector,
1428
                1,
1429
                (*pChunk)->chunk_data.sound_data.volume,
1430
                (float)(*pChunk)->chunk_data.sound_data.pitch * fabsf(GetReplayRate()),
1431
                0x10000);
1432
        }
1433
    }
1434
    AdvanceChunkPtr(pChunk, ePipe_chunk_sound);
1435
}
1436
 
1437
// IDA: void __usercall ApplyCar(tPipe_chunk **pChunk@<EAX>)
1438
void ApplyCar(tPipe_chunk** pChunk) {
1439
    tCar_spec* car;
1440
    br_vector3 com_offset_c;
1441
    br_vector3 com_offset_w;
1442
    LOG_TRACE("(%p)", pChunk);
1443
 
1444
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1445
        car = &gProgram_state.current_car;
1446
    } else {
1447
        car = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0x00ff);
1448
    }
1449
    BrMatrix34Copy(&car->car_master_actor->t.t.mat, &(*pChunk)->chunk_data.car_data.transformation);
1450
    BrVector3Copy(&car->v, &(*pChunk)->chunk_data.car_data.velocity);
1451
    BrMatrix34TApplyV(&car->velocity_car_space, &car->v, &car->car_master_actor->t.t.mat);
1452
    BrVector3InvScale(&car->velocity_car_space, &car->velocity_car_space, WORLD_SCALE);
1453
    if (BrVector3LengthSquared(&car->velocity_car_space) >= .0001f) {
1454
        BrVector3Normalise(&car->direction, &car->v);
1455
    } else {
1456
        BrVector3Negate(&car->direction, (br_vector3*)car->car_master_actor->t.t.mat.m[2]);
1457
    }
1458
    BrVector3Copy(&car->pos, &car->car_master_actor->t.t.translate.t);
1459
    BrVector3InvScale(&com_offset_c, &car->cmpos, WORLD_SCALE);
1460
    BrMatrix34ApplyV(&com_offset_w, &com_offset_c, &car->car_master_actor->t.t.mat);
1461
    BrVector3Accumulate(&car->pos, &com_offset_w);
1462
    car->speedo_speed = .07f * (*pChunk)->chunk_data.car_data.speedo_speed / 32767.f;
1463
    car->lf_sus_position = 0.15f * (*pChunk)->chunk_data.car_data.lf_sus_position / 127.f;
1464
    car->rf_sus_position = 0.15f * (*pChunk)->chunk_data.car_data.rf_sus_position / 127.f;
1465
    car->lr_sus_position = 0.15f * (*pChunk)->chunk_data.car_data.lr_sus_position / 127.f;
1466
    car->rr_sus_position = 0.15f * (*pChunk)->chunk_data.car_data.rr_sus_position / 127.f;
1467
    car->steering_angle = 60.f * (*pChunk)->chunk_data.car_data.steering_angle / 32767.f;
1468
    car->revs = 10 * ((*pChunk)->chunk_data.car_data.revs_and_gear & 0x7ff);
1469
    car->gear = ((*pChunk)->chunk_data.car_data.revs_and_gear >> 12) - 1;
1470
    car->frame_collision_flag = ((*pChunk)->chunk_data.car_data.revs_and_gear >> 11) & 0x1;
1471
    AdvanceChunkPtr(pChunk, ePipe_chunk_car);
1472
}
1473
 
1474
// IDA: void __usercall ApplyDamage(tPipe_chunk **pChunk@<EAX>)
1475
void ApplyDamage(tPipe_chunk** pChunk) {
1476
    tCar_spec* car;
1477
    int i;
1478
    LOG_TRACE("(%p)", pChunk);
1479
 
1480
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1481
        car = &gProgram_state.current_car;
1482
    } else {
1483
        car = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0x00ff);
1484
    }
1485
    for (i = 0; i < COUNT_OF(car->damage_units); i++) {
1486
        car->damage_units[i].damage_level += (*pChunk)->chunk_data.damage_data.damage_delta[i];
1487
    }
1488
    AdvanceChunkPtr(pChunk, ePipe_chunk_damage);
1489
}
1490
 
1491
// IDA: void __usercall ApplySpecial(tPipe_chunk **pChunk@<EAX>)
1492
void ApplySpecial(tPipe_chunk** pChunk) {
1493
    LOG_TRACE("(%p)", pChunk);
1494
 
1495
    switch ((*pChunk)->subject_index) {
1496
    case 0:
1497
        if (fabsf(GetReplayRate()) <= 1.f) {
1498
            FadePaletteDown();
1499
        }
1500
        break;
1501
    case 1:
1502
        gPed_scale_factor = 2.0f;
1503
        break;
1504
    case 2:
1505
        gPed_scale_factor = 1.0f;
1506
        break;
1507
    case 3:
1508
        gPed_scale_factor = 0.5f;
1509
        break;
1510
    case 4:
1511
        gPed_scale_factor = 1.0f;
1512
        break;
1513
    }
1514
    AdvanceChunkPtr(pChunk, ePipe_chunk_special);
1515
}
1516
 
1517
// IDA: void __usercall ApplyPedGib(tPipe_chunk **pChunk@<EAX>)
1518
void ApplyPedGib(tPipe_chunk** pChunk) {
1519
    LOG_TRACE("(%p)", pChunk);
1520
 
1521
    AdjustPedGib((*pChunk)->subject_index,
1522
        (*pChunk)->chunk_data.ped_gib_data.size,
1523
        (*pChunk)->chunk_data.ped_gib_data.gib_index,
1524
        (*pChunk)->chunk_data.ped_gib_data.ped_parent_index,
1525
        &(*pChunk)->chunk_data.ped_gib_data.transform);
1526
    AdvanceChunkPtr(pChunk, ePipe_chunk_ped_gib);
1527
}
1528
 
1529
// IDA: void __usercall ApplyProxRay(tPipe_chunk **pChunk@<EAX>)
1530
void ApplyProxRay(tPipe_chunk** pChunk) {
1531
    LOG_TRACE("(%p)", pChunk);
1532
 
1533
    AdjustProxRay(
1534
        (*pChunk)->subject_index,
1535
        (*pChunk)->chunk_data.prox_ray_data.car_ID,
1536
        (*pChunk)->chunk_data.prox_ray_data.ped_index,
1537
        (*pChunk)->chunk_data.prox_ray_data.time);
1538
    AdvanceChunkPtr(pChunk, ePipe_chunk_prox_ray);
1539
}
1540
 
1541
// IDA: void __usercall ApplySkidAdjustment(tPipe_chunk **pChunk@<EAX>)
1542
void ApplySkidAdjustment(tPipe_chunk** pChunk) {
1543
    LOG_TRACE("(%p)", pChunk);
1544
 
1545
    AdjustSkid((*pChunk)->subject_index,
1546
        &(*pChunk)->chunk_data.skid_adjustment.matrix,
1547
        (*pChunk)->chunk_data.skid_adjustment.material_index);
1548
    AdvanceChunkPtr(pChunk, ePipe_chunk_skid_adjustment);
1549
}
1550
 
1551
// IDA: int __usercall ApplyPipedSession@<EAX>(tU8 **pPtr@<EAX>)
1552
int ApplyPipedSession(tU8** pPtr) {
1553
    int i;
1554
    int return_value;
1555
    tPipe_chunk* chunk_ptr;
1556
    tPipe_chunk_type chunk_type;
1557
    LOG_TRACE("(%p)", pPtr);
1558
 
1559
    if (*pPtr == gPipe_record_ptr) {
1560
        return 1;
1561
    }
1562
    gEnd_of_session = *pPtr + (LengthOfSession((tPipe_session*)*pPtr) - sizeof(tU16));
1563
    REPLAY_DEBUG_ASSERT(((tPipe_session*)*pPtr)->pipe_magic1 == REPLAY_DEBUG_SESSION_MAGIC1);
1564
    chunk_ptr = (tPipe_chunk*)(*pPtr + offsetof(tPipe_session, chunks));
1565
    return_value = 0;
1566
    chunk_type = ((tPipe_session*)*pPtr)->chunk_type;
1567
    for (i = 0; i < ((tPipe_session*)*pPtr)->number_of_chunks; i++) {
1568
        switch (chunk_type) {
1569
        case ePipe_chunk_model_geometry:
1570
            ApplyModelGeometry(&chunk_ptr);
1571
            break;
1572
        case ePipe_chunk_pedestrian:
1573
            ApplyPedestrian(&chunk_ptr);
1574
            break;
1575
        case ePipe_chunk_frame_boundary:
1576
            ApplyFrameBoundary(&chunk_ptr);
1577
            return_value = 1;
1578
            break;
1579
        case ePipe_chunk_car:
1580
            ApplyCar(&chunk_ptr);
1581
            break;
1582
        case ePipe_chunk_sound:
1583
            ApplySound(&chunk_ptr);
1584
            break;
1585
        case ePipe_chunk_damage:
1586
            ApplyDamage(&chunk_ptr);
1587
            break;
1588
        case ePipe_chunk_special:
1589
            ApplySpecial(&chunk_ptr);
1590
            break;
1591
        case ePipe_chunk_ped_gib:
1592
            ApplyPedGib(&chunk_ptr);
1593
            break;
1594
        case ePipe_chunk_incident:
1595
            AdvanceChunkPtr(&chunk_ptr, ePipe_chunk_incident);
1596
            break;
1597
        case ePipe_chunk_spark:
1598
            ApplySpark(&chunk_ptr);
1599
            break;
1600
        case ePipe_chunk_shrapnel:
1601
            ApplyShrapnel(&chunk_ptr);
1602
            break;
1603
        case ePipe_chunk_screen_shake:
1604
            ApplyScreenWobble(&chunk_ptr);
1605
            break;
1606
        case ePipe_chunk_groove_stop:
1607
            ApplyGrooveStop(&chunk_ptr);
1608
            break;
1609
        case ePipe_chunk_non_car:
1610
            ApplyNonCar(&chunk_ptr);
1611
            break;
1612
        case ePipe_chunk_smoke:
1613
            ApplySmoke(&chunk_ptr);
1614
            break;
1615
        case ePipe_chunk_oil_spill:
1616
            ApplyOilSpill(&chunk_ptr, 0);
1617
            break;
1618
        case ePipe_chunk_smoke_column:
1619
            ApplySmokeColumn(&chunk_ptr);
1620
            break;
1621
        case ePipe_chunk_flame:
1622
            ApplyFlame(&chunk_ptr);
1623
            break;
1624
        case ePipe_chunk_smudge:
1625
            ApplySmudge(&chunk_ptr);
1626
            break;
1627
        case ePipe_chunk_splash:
1628
            ApplySplash(&chunk_ptr);
1629
            break;
1630
        case ePipe_chunk_prox_ray:
1631
            ApplyProxRay(&chunk_ptr);
1632
            break;
1633
        case ePipe_chunk_skid_adjustment:
1634
            ApplySkidAdjustment(&chunk_ptr);
1635
            break;
1636
        default:
1637
            break;
1638
        }
1639
    }
1640
#if defined(DETHRACE_FIX_BUGS)
1641
    *pPtr += PIPE_ALIGN(LengthOfSession((tPipe_session*)*pPtr));
1642
#else
1643
    *pPtr += LengthOfSession((tPipe_session*)*pPtr);
1644
#endif
1645
    if (*pPtr >= gPipe_buffer_working_end && *pPtr != gPipe_record_ptr) {
1646
        *pPtr = gPipe_buffer_start;
1647
    }
1648
    return return_value;
1649
}
1650
 
1651
// IDA: int __usercall MoveSessionPointerBackOne@<EAX>(tU8 **pPtr@<EAX>)
1652
int MoveSessionPointerBackOne(tU8** pPtr) {
1653
    LOG_TRACE("(%p)", pPtr);
1654
 
1655
    if (*pPtr == gPipe_buffer_oldest && *pPtr != gPipe_record_ptr) {
1656
        return 1;
1657
    }
1658
    if (*pPtr == gPipe_buffer_start) {
1659
        *pPtr = gPipe_buffer_working_end;
1660
    }
1661
    *pPtr -= sizeof(tU16);
1662
    REPLAY_DEBUG_ASSERT(*(tU16*)*pPtr != 0);
1663
    *pPtr -= *(tU16*)*pPtr;
1664
    REPLAY_DEBUG_ASSERT(((tPipe_session*)*pPtr)->pipe_magic1 == REPLAY_DEBUG_SESSION_MAGIC1);
1665
    return 0;
1666
}
1667
 
1668
// IDA: int __usercall MoveSessionPointerForwardOne@<EAX>(tU8 **pPtr@<EAX>)
1669
int MoveSessionPointerForwardOne(tU8** pPtr) {
1670
    LOG_TRACE("(%p)", pPtr);
1671
 
1672
    REPLAY_DEBUG_ASSERT(((tPipe_session*)*pPtr)->pipe_magic1 == REPLAY_DEBUG_SESSION_MAGIC1);
1673
#if defined(DETHRACE_FIX_BUGS)
1674
    *pPtr += PIPE_ALIGN(LengthOfSession((tPipe_session*)*pPtr));
1675
#else
1676
    *pPtr += LengthOfSession((tPipe_session*)*pPtr);
1677
#endif
1678
    if (*pPtr >= gPipe_buffer_working_end && *pPtr != gPipe_record_ptr) {
1679
        *pPtr = gPipe_buffer_start;
1680
    }
1681
    return *pPtr == gPipe_record_ptr;
1682
}
1683
 
1684
// IDA: tPipe_chunk* __usercall FindPreviousChunk@<EAX>(tU8 *pPtr@<EAX>, tPipe_chunk_type pType@<EDX>, tChunk_subject_index pIndex@<EBX>)
1685
tPipe_chunk* FindPreviousChunk(tU8* pPtr, tPipe_chunk_type pType, tChunk_subject_index pIndex) {
1686
    tU8* ptr;
1687
    int i;
1688
    int reached_end;
1689
    int chunk_counter;
1690
    tPipe_chunk* mr_chunky;
1691
    tChunk_subject_index masked_index;
1692
    LOG_TRACE("(%p, %d, %d)", pPtr, pType, pIndex);
1693
 
1694
    ptr = pPtr;
1695
    chunk_counter = 0;
1696
    masked_index = pIndex & 0x0fff;
1697
    while (1) {
1698
        if (!MoveSessionPointerBackOne(&ptr)) {
1699
            reached_end = chunk_counter >= gMax_rewind_chunks;
1700
            chunk_counter++;
1701
        } else {
1702
            reached_end = 1;
1703
        }
1704
        if (!reached_end) {
1705
            gEnd_of_session = ptr + LengthOfSession((tPipe_session*)ptr) - sizeof(tU16);
1706
            mr_chunky = &((tPipe_session*)ptr)->chunks;
1707
            for (i = 0; i < ((tPipe_session*)ptr)->number_of_chunks && ((tPipe_session*)ptr)->chunk_type == pType; i++) {
1708
                if ((mr_chunky->subject_index & 0xfff) == masked_index) {
1709
                    return mr_chunky;
1710
                }
1711
                AdvanceChunkPtr(&mr_chunky, pType);
1712
            }
1713
        }
1714
        if (reached_end) {
1715
            return NULL;
1716
        }
1717
    }
1718
}
1719
 
1720
// IDA: void __usercall UndoModelGeometry(tPipe_chunk **pChunk@<EAX>)
1721
void UndoModelGeometry(tPipe_chunk** pChunk) {
1722
    int i;
1723
    br_model* model_ptr;
1724
    tCar_spec* car;
1725
    LOG_TRACE("(%p)", pChunk);
1726
 
1727
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1728
        car = &gProgram_state.current_car;
1729
    } else {
1730
        car = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0x00ff);
1731
    }
1732
    model_ptr = car->car_model_actors[(*pChunk)->chunk_data.model_geometry_data.model_index].actor->model;
1733
    for (i = 0; i < (*pChunk)->chunk_data.model_geometry_data.vertex_count; i++) {
1734
        BrVector3Sub(&model_ptr->vertices[(*pChunk)->chunk_data.model_geometry_data.vertex_changes[i].vertex_index].p,
1735
            &model_ptr->vertices[(*pChunk)->chunk_data.model_geometry_data.vertex_changes[i].vertex_index].p,
1736
            &(*pChunk)->chunk_data.model_geometry_data.vertex_changes[i].delta_coordinates);
1737
    }
1738
    SetModelForUpdate(model_ptr, car, 0);
1739
    AdvanceChunkPtr(pChunk, ePipe_chunk_model_geometry);
1740
}
1741
 
1742
// IDA: void __usercall UndoSmudge(tPipe_chunk **pChunk@<EAX>)
1743
void UndoSmudge(tPipe_chunk** pChunk) {
1744
    //int i; // Pierre-Marie Baty -- unused variable
1745
    //br_model* model_ptr; // Pierre-Marie Baty -- unused variable
1746
    //tCar_spec* car; // Pierre-Marie Baty -- unused variable
1747
    LOG_TRACE("(%p)", pChunk);
1748
 
1749
    DoSmudge(pChunk, -1);
1750
    AdvanceChunkPtr(pChunk, ePipe_chunk_smudge);
1751
}
1752
 
1753
// IDA: void __usercall UndoPedestrian(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1754
void UndoPedestrian(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1755
    tPipe_chunk* temp_prev_chunk;
1756
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1757
 
1758
    temp_prev_chunk = pPrev_chunk;
1759
    if (pPrev_chunk == NULL) {
1760
        ApplyPedestrian(pChunk);
1761
    } else {
1762
        gDisable_advance = 1;
1763
        ApplyPedestrian(&temp_prev_chunk);
1764
        gDisable_advance = 0;
1765
        AdvanceChunkPtr(pChunk, ePipe_chunk_pedestrian);
1766
    }
1767
}
1768
 
1769
// IDA: void __usercall UndoFrameBoundary(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1770
void UndoFrameBoundary(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1771
    //tPipe_chunk* temp_prev_chunk; // Pierre-Marie Baty -- unused variable
1772
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1773
 
1774
    ApplyFrameBoundary(pChunk);
1775
    AdvanceChunkPtr(pChunk, ePipe_chunk_frame_boundary);
1776
}
1777
 
1778
// IDA: void __usercall UndoCar(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1779
void UndoCar(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1780
    tPipe_chunk* temp_prev_chunk;
1781
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1782
 
1783
    temp_prev_chunk = pPrev_chunk;
1784
    if (pPrev_chunk == NULL) {
1785
        ApplyCar(pChunk);
1786
    } else {
1787
        gDisable_advance = 1;
1788
        ApplyCar(&temp_prev_chunk);
1789
        gDisable_advance = 0;
1790
        AdvanceChunkPtr(pChunk, ePipe_chunk_car);
1791
    }
1792
}
1793
 
1794
// IDA: void __usercall UndoSound(tPipe_chunk **pChunk@<EAX>)
1795
void UndoSound(tPipe_chunk** pChunk) {
1796
    LOG_TRACE("(%p)", pChunk);
1797
 
1798
    AdvanceChunkPtr(pChunk, ePipe_chunk_sound);
1799
}
1800
 
1801
// IDA: void __usercall UndoDamage(tPipe_chunk **pChunk@<EAX>)
1802
void UndoDamage(tPipe_chunk** pChunk) {
1803
    tCar_spec* car;
1804
    int i;
1805
    LOG_TRACE("(%p)", pChunk);
1806
 
1807
    if (((*pChunk)->subject_index & 0xff00) == 0) {
1808
        car = &gProgram_state.current_car;
1809
    } else {
1810
        car = GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0xff);
1811
    }
1812
    for (i = 0; i < COUNT_OF(car->damage_units); i++) {
1813
        car->damage_units[i].damage_level -= (*pChunk)->chunk_data.damage_data.damage_delta[i];
1814
    }
1815
    AdvanceChunkPtr(pChunk, ePipe_chunk_damage);
1816
}
1817
 
1818
// IDA: void __usercall UndoSpecial(tPipe_chunk **pChunk@<EAX>)
1819
void UndoSpecial(tPipe_chunk** pChunk) {
1820
    LOG_TRACE("(%p)", pChunk);
1821
 
1822
    if ((*pChunk)->subject_index == 0) {
1823
        ApplySpecial(pChunk);
1824
    } else {
1825
        switch ((*pChunk)->subject_index) {
1826
        case 1:
1827
            gPed_scale_factor = 1.0f;
1828
            break;
1829
        case 2:
1830
            gPed_scale_factor = 2.0f;
1831
            break;
1832
        case 3:
1833
            gPed_scale_factor = 1.0f;
1834
            break;
1835
        case 4:
1836
            gPed_scale_factor = 0.5f;
1837
            break;
1838
        }
1839
        AdvanceChunkPtr(pChunk, ePipe_chunk_special);
1840
    }
1841
}
1842
 
1843
// IDA: void __usercall UndoPedGib(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1844
void UndoPedGib(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1845
    tPipe_chunk* temp_prev_chunk;
1846
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1847
 
1848
    temp_prev_chunk = pPrev_chunk;
1849
    gDisable_advance = 1;
1850
    if (pPrev_chunk != NULL) {
1851
        ApplyPedGib(&temp_prev_chunk);
1852
    }
1853
    gDisable_advance = 0;
1854
    AdvanceChunkPtr(pChunk, ePipe_chunk_ped_gib);
1855
}
1856
 
1857
// IDA: void __usercall UndoSpark(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1858
void UndoSpark(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1859
    tPipe_chunk* temp_prev_chunk;
1860
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1861
 
1862
    temp_prev_chunk = pPrev_chunk;
1863
    gDisable_advance = 1;
1864
    if (pPrev_chunk != NULL) {
1865
        ApplySpark(&temp_prev_chunk);
1866
    }
1867
    gDisable_advance = 0;
1868
    AdvanceChunkPtr(pChunk, ePipe_chunk_spark);
1869
}
1870
 
1871
// IDA: void __usercall UndoShrapnel(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1872
void UndoShrapnel(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1873
    tPipe_chunk* temp_prev_chunk;
1874
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1875
 
1876
    temp_prev_chunk = pPrev_chunk;
1877
    gDisable_advance = 1;
1878
    if (pPrev_chunk != NULL) {
1879
        ApplyShrapnel(&temp_prev_chunk);
1880
    }
1881
    gDisable_advance = 0;
1882
    AdvanceChunkPtr(pChunk, ePipe_chunk_shrapnel);
1883
}
1884
 
1885
// IDA: void __usercall UndoScreenWobble(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1886
void UndoScreenWobble(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1887
    tPipe_chunk* temp_prev_chunk;
1888
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1889
 
1890
    temp_prev_chunk = pPrev_chunk;
1891
    gDisable_advance = 1;
1892
    if (pPrev_chunk == NULL) {
1893
        SetScreenWobble(0, 0);
1894
    } else {
1895
        ApplyScreenWobble(&temp_prev_chunk);
1896
    }
1897
    gDisable_advance = 0;
1898
    AdvanceChunkPtr(pChunk, ePipe_chunk_screen_shake);
1899
}
1900
 
1901
// IDA: void __usercall UndoGrooveStop(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1902
void UndoGrooveStop(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1903
    tPipe_chunk* temp_prev_chunk;
1904
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1905
 
1906
    temp_prev_chunk = pPrev_chunk;
1907
    gDisable_advance = 1;
1908
    if (pPrev_chunk != NULL) {
1909
        ApplyGrooveStop(&temp_prev_chunk);
1910
    }
1911
    gDisable_advance = 0;
1912
    AdvanceChunkPtr(pChunk, ePipe_chunk_groove_stop);
1913
}
1914
 
1915
// IDA: void __usercall UndoNonCar(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1916
void UndoNonCar(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1917
    tPipe_chunk* temp_prev_chunk;
1918
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1919
 
1920
    temp_prev_chunk = pPrev_chunk;
1921
    gDisable_advance = 1;
1922
    if (pPrev_chunk != NULL) {
1923
        ApplyNonCar(&temp_prev_chunk);
1924
    }
1925
    gDisable_advance = 0;
1926
    AdvanceChunkPtr(pChunk, ePipe_chunk_non_car);
1927
}
1928
 
1929
// IDA: void __usercall UndoSmoke(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1930
void UndoSmoke(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1931
    tPipe_chunk* temp_prev_chunk;
1932
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1933
 
1934
    temp_prev_chunk = pPrev_chunk;
1935
    gDisable_advance = 1;
1936
    if (pPrev_chunk != NULL) {
1937
        ApplySmoke(&temp_prev_chunk);
1938
    }
1939
    gDisable_advance = 0;
1940
    AdvanceChunkPtr(pChunk, ePipe_chunk_smoke);
1941
}
1942
 
1943
// IDA: void __usercall UndoSmokeColumn(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1944
void UndoSmokeColumn(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1945
    //tPipe_chunk* temp_prev_chunk; // Pierre-Marie Baty -- unused variable
1946
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1947
 
1948
    ApplySmokeColumn(pChunk);
1949
}
1950
 
1951
// IDA: void __usercall UndoFlame(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1952
void UndoFlame(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1953
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1954
 
1955
    ApplyFlame(pChunk);
1956
}
1957
 
1958
// IDA: void __usercall UndoSplash(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1959
void UndoSplash(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1960
    tPipe_chunk* temp_prev_chunk;
1961
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1962
 
1963
    temp_prev_chunk = pPrev_chunk;
1964
    gDisable_advance = 1;
1965
    if (pPrev_chunk == NULL) {
1966
        ((((*pChunk)->subject_index & 0xff00) == 0) ? &gProgram_state.current_car : GetCarSpec((*pChunk)->subject_index >> 8, (*pChunk)->subject_index & 0xff))->water_d = 10000.f;
1967
    } else {
1968
        ApplySplash(&temp_prev_chunk);
1969
    }
1970
    gDisable_advance = 0;
1971
    AdvanceChunkPtr(pChunk, ePipe_chunk_splash);
1972
}
1973
 
1974
// IDA: void __usercall UndoOilSpill(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1975
void UndoOilSpill(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1976
    tPipe_chunk* temp_prev_chunk;
1977
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1978
 
1979
    temp_prev_chunk = pPrev_chunk;
1980
    gDisable_advance = 1;
1981
    if (pPrev_chunk != NULL) {
1982
        ApplyOilSpill(&temp_prev_chunk, (*pChunk)->chunk_data.oil_data.previous_stop_time);
1983
    }
1984
    gDisable_advance = 0;
1985
    AdvanceChunkPtr(pChunk, ePipe_chunk_oil_spill);
1986
}
1987
 
1988
// IDA: void __usercall UndoProxRay(tPipe_chunk **pChunk@<EAX>)
1989
void UndoProxRay(tPipe_chunk** pChunk) {
1990
    LOG_TRACE("(%p)", pChunk);
1991
 
1992
    ApplyProxRay(pChunk);
1993
}
1994
 
1995
// IDA: void __usercall UndoSkidAdjustment(tPipe_chunk **pChunk@<EAX>, tPipe_chunk *pPrev_chunk@<EDX>)
1996
void UndoSkidAdjustment(tPipe_chunk** pChunk, tPipe_chunk* pPrev_chunk) {
1997
    LOG_TRACE("(%p, %p)", pChunk, pPrev_chunk);
1998
 
1999
    gDisable_advance = 1;
2000
    if (pPrev_chunk == NULL) {
2001
        HideSkid((*pChunk)->subject_index);
2002
    } else {
2003
        ApplySkidAdjustment(&pPrev_chunk);
2004
    }
2005
    gDisable_advance = 0;
2006
    AdvanceChunkPtr(pChunk, ePipe_chunk_skid_adjustment);
2007
}
2008
 
2009
// IDA: int __usercall UndoPipedSession@<EAX>(tU8 **pPtr@<EAX>)
2010
int UndoPipedSession(tU8** pPtr) {
2011
    tPipe_chunk* chunk_ptr;
2012
    tPipe_chunk* prev_chunk;
2013
    tU8* temp_ptr;
2014
    tU8* pushed_end_of_session;
2015
    int i;
2016
    tPipe_chunk_type chunk_type;
2017
    LOG_TRACE("(%p)", pPtr);
2018
 
2019
    if (MoveSessionPointerBackOne(pPtr)) {
2020
        return 1;
2021
    }
2022
    REPLAY_DEBUG_ASSERT(((tPipe_session*)*pPtr)->pipe_magic1 == REPLAY_DEBUG_SESSION_MAGIC1);
2023
    gEnd_of_session = *pPtr + LengthOfSession((tPipe_session*)*pPtr) - sizeof(tU16);
2024
    chunk_ptr = &((tPipe_session*)*pPtr)->chunks;
2025
    chunk_type = ((tPipe_session*)*pPtr)->chunk_type;
2026
    pushed_end_of_session = gEnd_of_session;
2027
    for (i = 0; i < ((tPipe_session*)*pPtr)->number_of_chunks; i++) {
2028
        if (!(chunk_type == ePipe_chunk_model_geometry || chunk_type == ePipe_chunk_sound || chunk_type == ePipe_chunk_damage || chunk_type == ePipe_chunk_special || chunk_type == ePipe_chunk_incident || chunk_type == ePipe_chunk_prox_ray || chunk_type == ePipe_chunk_smudge)) {
2029
            prev_chunk = FindPreviousChunk(*pPtr, ((tPipe_session*)*pPtr)->chunk_type, chunk_ptr->subject_index);
2030
        }
2031
        REPLAY_DEBUG_ASSERT(((tPipe_chunk*)chunk_ptr)->chunk_magic1 == REPLAY_DEBUG_CHUNK_MAGIC1);
2032
        gEnd_of_session = pushed_end_of_session;
2033
        switch (chunk_type) {
2034
        case ePipe_chunk_model_geometry:
2035
            UndoModelGeometry(&chunk_ptr);
2036
            break;
2037
        case ePipe_chunk_pedestrian:
2038
            UndoPedestrian(&chunk_ptr, prev_chunk);
2039
            break;
2040
        case ePipe_chunk_frame_boundary:
2041
            UndoFrameBoundary(&chunk_ptr, prev_chunk);
2042
            break;
2043
        case ePipe_chunk_car:
2044
            UndoCar(&chunk_ptr, prev_chunk);
2045
            break;
2046
        case ePipe_chunk_sound:
2047
            UndoSound(&chunk_ptr);
2048
            break;
2049
        case ePipe_chunk_damage:
2050
            UndoDamage(&chunk_ptr);
2051
            break;
2052
        case ePipe_chunk_special:
2053
            UndoSpecial(&chunk_ptr);
2054
            break;
2055
        case ePipe_chunk_ped_gib:
2056
            UndoPedGib(&chunk_ptr, prev_chunk);
2057
            break;
2058
        case ePipe_chunk_incident:
2059
            AdvanceChunkPtr(&chunk_ptr, ePipe_chunk_incident);
2060
            break;
2061
        case ePipe_chunk_spark:
2062
            UndoSpark(&chunk_ptr, prev_chunk);
2063
            break;
2064
        case ePipe_chunk_shrapnel:
2065
            UndoShrapnel(&chunk_ptr, prev_chunk);
2066
            break;
2067
        case ePipe_chunk_screen_shake:
2068
            UndoScreenWobble(&chunk_ptr, prev_chunk);
2069
            break;
2070
        case ePipe_chunk_groove_stop:
2071
            UndoGrooveStop(&chunk_ptr, prev_chunk);
2072
            break;
2073
        case ePipe_chunk_non_car:
2074
            UndoNonCar(&chunk_ptr, prev_chunk);
2075
            break;
2076
        case ePipe_chunk_smoke:
2077
            UndoSmoke(&chunk_ptr, prev_chunk);
2078
            break;
2079
        case ePipe_chunk_oil_spill:
2080
            UndoOilSpill(&chunk_ptr, prev_chunk);
2081
            break;
2082
        case ePipe_chunk_smoke_column:
2083
            UndoSmokeColumn(&chunk_ptr, prev_chunk);
2084
            break;
2085
        case ePipe_chunk_flame:
2086
            UndoFlame(&chunk_ptr, prev_chunk);
2087
            break;
2088
        case ePipe_chunk_smudge:
2089
            UndoSmudge(&chunk_ptr);
2090
            break;
2091
        case ePipe_chunk_splash:
2092
            UndoSplash(&chunk_ptr, prev_chunk);
2093
            break;
2094
        case ePipe_chunk_prox_ray:
2095
            UndoProxRay(&chunk_ptr);
2096
            break;
2097
        case ePipe_chunk_skid_adjustment:
2098
            UndoSkidAdjustment(&chunk_ptr, prev_chunk);
2099
            break;
2100
        default:
2101
            break;
2102
        }
2103
    }
2104
    temp_ptr = *pPtr;
2105
    if (MoveSessionPointerBackOne(&temp_ptr)) {
2106
        return 1;
2107
    }
2108
    return ((tPipe_session*)temp_ptr)->chunk_type == ePipe_chunk_frame_boundary;
2109
}
2110
 
2111
// IDA: tU32 __usercall FindPrevFrameTime@<EAX>(tU8 *pPtr@<EAX>)
2112
tU32 FindPrevFrameTime(tU8* pPtr) {
2113
    tU8* temp_ptr;
2114
    LOG_TRACE("(%p)", pPtr);
2115
 
2116
    temp_ptr = pPtr;
2117
    do {
2118
        if (MoveSessionPointerBackOne(&temp_ptr)) {
2119
            return 0;
2120
        }
2121
    } while (((tPipe_session*)temp_ptr)->chunk_type != ePipe_chunk_frame_boundary);
2122
    return ((tPipe_session*)temp_ptr)->chunks.chunk_data.frame_boundary_data.time;
2123
}
2124
 
2125
// IDA: void __usercall ScanBuffer(tU8 **pPtr@<EAX>, tPipe_chunk_type pType@<EDX>, tU32 pDefault_time@<EBX>, int (*pCall_back)(tPipe_chunk*, int, tU32)@<ECX>, int (*pTime_check)(tU32))
2126
void ScanBuffer(tU8** pPtr, tPipe_chunk_type pType, tU32 pDefault_time, int (*pCall_back)(tPipe_chunk*, int, tU32), int (*pTime_check)(tU32)) {
2127
    //tPipe_chunk* chunk_ptr; // Pierre-Marie Baty -- unused variable
2128
    tU32 the_time;
2129
    LOG_TRACE("(%p, %d, %d, %p, %p)", pPtr, pType, pDefault_time, pCall_back, pTime_check);
2130
 
2131
    the_time = pDefault_time;
2132
    while (1) {
2133
        if (PipeSearchForwards() ? MoveSessionPointerForwardOne(pPtr) : MoveSessionPointerBackOne(pPtr)) {
2134
            return;
2135
        }
2136
        gEnd_of_session = *pPtr + LengthOfSession((tPipe_session*)*pPtr) - sizeof(tU16);
2137
        if (((tPipe_session*)*pPtr)->chunk_type == ePipe_chunk_frame_boundary) {
2138
            the_time = ((tPipe_session*)*pPtr)->chunks.chunk_data.frame_boundary_data.time;
2139
        } else if (((tPipe_session*)*pPtr)->chunk_type == pType) {
2140
            if (pCall_back(&((tPipe_session*)*pPtr)->chunks, ((tPipe_session*)*pPtr)->number_of_chunks, the_time)) {
2141
                return;
2142
            }
2143
        }
2144
        if (pTime_check != NULL) {
2145
            if (!pTime_check(the_time)) {
2146
                return;
2147
            }
2148
        }
2149
    }
2150
}
2151
 
2152
// IDA: int __usercall CheckSound@<EAX>(tPipe_chunk *pChunk_ptr@<EAX>, int pChunk_count@<EDX>, tU32 pTime@<EBX>)
2153
int CheckSound(tPipe_chunk* pChunk_ptr, int pChunk_count, tU32 pTime) {
2154
    //int i; // Pierre-Marie Baty -- unused variable
2155
    //int sound_length; // Pierre-Marie Baty -- unused variable
2156
    //tPipe_chunk* temp_ptr; // Pierre-Marie Baty -- unused variable
2157
    LOG_TRACE("(%p, %d, %d)", pChunk_ptr, pChunk_count, pTime);
2158
 
2159
    STUB_ONCE();
2160
    return 1;
2161
}
2162
 
2163
// IDA: int __usercall SoundTimeout@<EAX>(tU32 pTime@<EAX>)
2164
int SoundTimeout(tU32 pTime) {
2165
    LOG_TRACE("(%d)", pTime);
2166
    NOT_IMPLEMENTED();
2167
}
2168
 
2169
// IDA: void __usercall ScanAndPlaySoundsToBe(tU8 *pPtr@<EAX>, tU32 pOldest_time@<EDX>, tU32 pYoungest_time@<EBX>)
2170
void ScanAndPlaySoundsToBe(tU8* pPtr, tU32 pOldest_time, tU32 pYoungest_time) {
2171
    //tU8* temp_ptr; // Pierre-Marie Baty -- unused variable
2172
    LOG_TRACE("(%p, %d, %d)", pPtr, pOldest_time, pYoungest_time);
2173
    NOT_IMPLEMENTED();
2174
}
2175
 
2176
// IDA: int __usercall CheckCar@<EAX>(tPipe_chunk *pChunk_ptr@<EAX>, int pChunk_count@<EDX>, tU32 pTime@<EBX>)
2177
int CheckCar(tPipe_chunk* pChunk_ptr, int pChunk_count, tU32 pTime) {
2178
    int i;
2179
    tCar_spec* car;
2180
    br_vector3 com_offset_c;
2181
    br_vector3 com_offset_w;
2182
    br_vector3 difference;
2183
    tPipe_chunk* temp_ptr;
2184
    LOG_TRACE("(%p, %d, %d)", pChunk_ptr, pChunk_count, pTime);
2185
 
2186
    temp_ptr = pChunk_ptr;
2187
    if (PipeSearchForwards()) {
2188
        if (pTime <= gOldest_time) {
2189
            return 0;
2190
        }
2191
    } else {
2192
        if (pTime >= gOldest_time) {
2193
            return 0;
2194
        }
2195
    }
2196
    for (i = 0; i < pChunk_count; i++) {
2197
        if ((temp_ptr->subject_index & 0xff00) == 0) {
2198
            car = &gProgram_state.current_car;
2199
        } else {
2200
            car = GetCarSpec(temp_ptr->subject_index >> 8, temp_ptr->subject_index & 0xff);
2201
        }
2202
        if (car == gCar_ptr) {
2203
            BrVector3Copy(&gCar_pos, (br_vector3*)temp_ptr->chunk_data.car_data.transformation.m[3]);
2204
            BrVector3InvScale(&com_offset_c, &car->cmpos, WORLD_SCALE);
2205
            BrMatrix34ApplyV(&com_offset_w, &com_offset_c, &temp_ptr->chunk_data.car_data.transformation);
2206
            BrVector3Accumulate(&gCar_pos, &com_offset_w);
2207
            BrVector3Sub(&difference, &gCar_pos, &gReference_pos);
2208
            if (BrVector3LengthSquared(&difference) <= gMax_distance) {
2209
                gTrigger_time = pTime;
2210
                return 0;
2211
            } else {
2212
                gTrigger_time = pTime;
2213
                return 1;
2214
            }
2215
        }
2216
        AdvanceChunkPtr(&temp_ptr, ePipe_chunk_car);
2217
    }
2218
    return 0;
2219
}
2220
 
2221
// IDA: int __usercall CarTimeout@<EAX>(tU32 pTime@<EAX>)
2222
int CarTimeout(tU32 pTime) {
2223
    LOG_TRACE("(%d)", pTime);
2224
 
2225
    if (PipeSearchForwards()) {
2226
        if (pTime > gYoungest_time) {
2227
            return 0;
2228
        }
2229
    } else {
2230
        if (pTime < gYoungest_time) {
2231
            return 0;
2232
        }
2233
    }
2234
    return 1;
2235
}
2236
 
2237
// IDA: void __usercall ScanCarsPositions(tCar_spec *pCar@<EAX>, br_vector3 *pSource_pos@<EDX>, br_scalar pMax_distance_sqr, tU32 pOffset_time, tU32 pTime_period, br_vector3 *pCar_pos, tU32 *pTime_returned)
2238
void ScanCarsPositions(tCar_spec* pCar, br_vector3* pSource_pos, br_scalar pMax_distance_sqr, tU32 pOffset_time, tU32 pTime_period, br_vector3* pCar_pos, tU32* pTime_returned) {
2239
    tU8* temp_ptr;
2240
    LOG_TRACE("(%p, %p, %f, %d, %d, %p, %p)", pCar, pSource_pos, pMax_distance_sqr, pOffset_time, pTime_period, pCar_pos, pTime_returned);
2241
 
2242
    temp_ptr = gPipe_play_ptr;
2243
    gTrigger_time = 0;
2244
    gMax_distance = pMax_distance_sqr;
2245
    BrVector3Copy(&gReference_pos, pSource_pos);
2246
    gCar_ptr = pCar;
2247
 
2248
    if (PipeSearchForwards()) {
2249
        gOldest_time = GetTotalTime() + pOffset_time;
2250
        gYoungest_time = gOldest_time + pTime_period;
2251
    } else {
2252
        gOldest_time = GetTotalTime() - pOffset_time;
2253
        gYoungest_time = gOldest_time - pTime_period;
2254
    }
2255
 
2256
    ScanBuffer(&temp_ptr, ePipe_chunk_car, GetTotalTime(), CheckCar, CarTimeout);
2257
    BrVector3Copy(pCar_pos, &gCar_pos);
2258
    if (pCar_pos->v[0] > 500.f) {
2259
        Vector3AddFloats(pCar_pos, pCar_pos, -1000.f, -1000.f, -1000.f);
2260
    }
2261
    *pTime_returned = gTrigger_time;
2262
}
2263
 
2264
// IDA: int __usercall CheckIncident@<EAX>(tPipe_chunk *pChunk_ptr@<EAX>, int pChunk_count@<EDX>, tU32 pTime@<EBX>)
2265
int CheckIncident(tPipe_chunk* pChunk_ptr, int pChunk_count, tU32 pTime) {
2266
    LOG_TRACE("(%p, %d, %d)", pChunk_ptr, pChunk_count, pTime);
2267
 
2268
    if (PipeSearchForwards()) {
2269
        if (pTime <= gOldest_time) {
2270
            return 0;
2271
        }
2272
    } else {
2273
        if (gOldest_time <= pTime) {
2274
            return 0;
2275
        }
2276
    }
2277
    gIncidentChunk = pChunk_ptr;
2278
    gTrigger_time = pTime;
2279
    return 1;
2280
}
2281
 
2282
// IDA: int __usercall GetNextIncident@<EAX>(tU32 pOffset_time@<EAX>, tIncident_type *pIncident_type@<EDX>, float *pSeverity@<EBX>, tIncident_info *pInfo@<ECX>, tU32 *pTime_away)
2283
int GetNextIncident(tU32 pOffset_time, tIncident_type* pIncident_type, float* pSeverity, tIncident_info* pInfo, tU32* pTime_away) {
2284
    tU8* temp_ptr;
2285
    LOG_TRACE("(%d, %p, %p, %p, %p)", pOffset_time, pIncident_type, pSeverity, pInfo, pTime_away);
2286
 
2287
    temp_ptr = gPipe_play_ptr;
2288
    gTrigger_time = 0;
2289
    if (PipeSearchForwards()) {
2290
        gOldest_time = GetTotalTime() + pOffset_time;
2291
    } else {
2292
        gOldest_time = GetTotalTime() - pOffset_time;
2293
    }
2294
    ScanBuffer(&temp_ptr, ePipe_chunk_incident, GetTotalTime(), CheckIncident, NULL);
2295
    if (gTrigger_time != 0) {
2296
        *pTime_away = gTrigger_time - GetTotalTime();
2297
        *pIncident_type = gIncidentChunk->subject_index;
2298
        *pSeverity = gIncidentChunk->chunk_data.incident_data.severity;
2299
        if (*pIncident_type == eIncident_ped) {
2300
            pInfo->ped_info.ped_actor = GetPedestrianActor(gIncidentChunk->chunk_data.incident_data.info.ped_info.ped_index);
2301
            pInfo->ped_info.murderer_actor = gIncidentChunk->chunk_data.incident_data.info.ped_info.actor;
2302
        } else if (*pIncident_type == eIncident_car) {
2303
            if ((gIncidentChunk->chunk_data.incident_data.info.car_info.car_ID & 0xff00) == 0) {
2304
                pInfo->car_info.car = &gProgram_state.current_car;
2305
            } else {
2306
                pInfo->car_info.car = GetCarSpec(gIncidentChunk->chunk_data.incident_data.info.car_info.car_ID >> 8,
2307
                    gIncidentChunk->chunk_data.incident_data.info.car_info.car_ID & 0xff);
2308
            }
2309
            BrVector3Copy(&pInfo->car_info.impact_point, &gIncidentChunk->chunk_data.incident_data.info.car_info.impact_point);
2310
        } else if (*pIncident_type == eIncident_wall) {
2311
            BrVector3Copy(&pInfo->wall_info.pos, &gIncidentChunk->chunk_data.incident_data.info.wall_info.pos);
2312
        }
2313
    }
2314
    return gTrigger_time;
2315
}
2316
 
2317
// IDA: tU32 __cdecl GetARStartTime()
2318
tU32 GetARStartTime(void) {
2319
    tU8* temp_ptr;
2320
    LOG_TRACE("()");
2321
 
2322
    temp_ptr = gPipe_buffer_oldest;
2323
    do {
2324
        if (MoveSessionPointerForwardOne(&temp_ptr)) {
2325
            return 0;
2326
        }
2327
    } while (((tPipe_session*)temp_ptr)->chunk_type != ePipe_chunk_frame_boundary);
2328
    return ((tPipe_session*)temp_ptr)->chunks.chunk_data.frame_boundary_data.time;
2329
}