Subversion Repositories Games.Carmageddon

Rev

Rev 1 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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