1 /***************************************************************************
2     Collision & Crash Code.
3 
4     There are two types of collision: Scenery & Traffic.
5 
6     1/ Traffic: The Ferrari will spin after a collision.
7     2/ Scenery: There are three types of scenery collision:
8        - Low speed bump. Car rises slightly in the air and stalls.
9        - Mid speed spin. Car spins and slides after collision.
10        - High speed flip. If slightly slower, car rolls into screen.
11          Otherwise, grows towards screen and vanishes
12 
13     Known Issues With Original Code:
14     - Passenger sprites flicker if they land moving in the water on Stage 1
15 
16     The Ferrari sprite is used differently by the crash code.
17     As there's only one of them, I've rolled the additional variables into
18     this class.
19 
20     Copyright Chris White.
21     See license.txt for more details.
22 ***************************************************************************/
23 
24 #include "engine/oferrari.hpp"
25 #include "engine/oinputs.hpp"
26 #include "engine/olevelobjs.hpp"
27 #include "engine/outils.hpp"
28 #include "engine/ocrash.hpp"
29 
30 OCrash ocrash;
31 
OCrash(void)32 OCrash::OCrash(void)
33 {
34 }
35 
36 
~OCrash(void)37 OCrash::~OCrash(void)
38 {
39 }
40 
init(oentry * f,oentry * s,oentry * p1,oentry * p1s,oentry * p2,oentry * p2s)41 void OCrash::init(oentry* f, oentry* s, oentry* p1, oentry* p1s, oentry* p2, oentry* p2s)
42 {
43     spr_ferrari = f;
44     spr_shadow  = s;
45     spr_pass1   = p1;
46     spr_pass1s  = p1s;
47     spr_pass2   = p2;
48     spr_pass2s  = p2s;
49 
50     // Setup function pointers for passenger sprites
51     function_pass1 = &OCrash::do_crash_passengers;
52     function_pass2 = &OCrash::do_crash_passengers;
53 }
54 
is_flip()55 bool OCrash::is_flip()
56 {
57     return crash_counter && crash_type == CRASH_FLIP;
58 }
59 
enable()60 void OCrash::enable()
61 {
62     // This is called multiple times, so need this check in place
63     if (spr_ferrari->control & OSprites::ENABLE)
64         return;
65 
66     spr_ferrari->control |= OSprites::ENABLE;
67 
68     // Reset all corresponding variables
69     spinflipcount1 = 0;
70     spinflipcount2 = 0;
71     slide = 0;
72     frame = 0;
73     addr = 0;
74     camera_x_target = 0;
75     camera_xinc = 0;
76     lookup_index = 0;
77     frame_restore = 0;
78     shift = 0;
79     crash_speed = 0;
80     crash_zinc = 0;
81     crash_side = 0;
82 
83     spr_ferrari->counter = 0;
84 
85     outrun.ttrial.crashes++;
86 }
87 
88 // Source: 0x1128
clear_crash_state()89 void OCrash::clear_crash_state()
90 {
91     spin_control1 = 0;
92     coll_count1 = 0;
93     coll_count2 = 0;
94     olevelobjs.collision_sprite = 0;
95     crash_counter = 0;
96     crash_state = 0;
97     crash_z = 0;
98     spin_pass_frame = 0;
99     crash_spin_count = 0;
100     crash_delay = 0;
101     crash_type  = 0;
102     skid_counter = 0;
103 }
104 
tick()105 void OCrash::tick()
106 {
107     if (!outrun.tick_frame &&
108         oroad.get_view_mode() == ORoad::VIEW_INCAR &&
109         crash_type != CRASH_FLIP)
110         return;
111 
112     // Do Ferrari
113     if (spr_ferrari->control & OSprites::ENABLE)
114         if (outrun.tick_frame) do_crash();
115         else osprites.do_spr_order_shadows(spr_ferrari);
116 
117     // Do Car Shadow
118     if (spr_shadow->control & OSprites::ENABLE)
119         if (outrun.tick_frame) do_shadow(spr_ferrari, spr_shadow);
120         else osprites.do_spr_order_shadows(spr_shadow);
121 
122     // Do Passenger 1
123     if (spr_pass1->control & OSprites::ENABLE)
124         if (outrun.tick_frame) ((ocrash).*(function_pass1))(spr_pass1);
125         else osprites.do_spr_order_shadows(spr_pass1);
126 
127     // Do Passenger 1 Shadow
128     if (spr_pass1s->control & OSprites::ENABLE)
129         if (outrun.tick_frame) do_shadow(spr_pass1, spr_pass1s);
130         else osprites.do_spr_order_shadows(spr_pass1s);
131 
132     // Do Passenger 2
133     if (spr_pass2->control & OSprites::ENABLE)
134         if (outrun.tick_frame) ((ocrash).*(function_pass2))(spr_pass2);
135         else osprites.do_spr_order_shadows(spr_pass2);
136 
137     // Do Passenger 2 Shadow
138     if (spr_pass2s->control & OSprites::ENABLE)
139         if (outrun.tick_frame) do_shadow(spr_pass2, spr_pass2s);
140         else osprites.do_spr_order_shadows(spr_pass2s);
141 }
142 
143 // Source: 0x1162
do_crash()144 void OCrash::do_crash()
145 {
146     switch (outrun.game_state)
147     {
148         case GS_INIT_MUSIC:
149         case GS_MUSIC:
150             end_collision();
151             return;
152 
153         // Fall through to continue code below
154         case GS_ATTRACT:
155         case GS_INGAME:
156         case GS_BONUS:
157             break;
158 
159         default:
160             // In other modes render crashing ferrari if crash counter is set
161             if (crash_counter)
162             {
163                 if (oroad.get_view_mode() != ORoad::VIEW_INCAR || crash_type == CRASH_FLIP)
164                     osprites.do_spr_order_shadows(spr_ferrari);
165             }
166             // Set Distance Into Screen from crash counter
167             spr_ferrari->road_priority = spr_ferrari->counter;
168             return;
169     }
170 
171     // ------------------------------------------------------------------------
172     // cont1: Adjust steering
173     // ------------------------------------------------------------------------
174     int16_t steering_adjust = oinputs.steering_adjust;
175     oinputs.steering_adjust = 0;
176 
177     if (!oferrari.car_ctrl_active)
178     {
179         if (spin_control1 == 0)
180         {
181             uint16_t inc = ((oinitengine.car_increment >> 16) * 31) >> 5;
182             oinitengine.car_increment = (oinitengine.car_increment & 0xFFFF) | (inc << 16);
183             oferrari.car_inc_old = inc;
184         }
185         else
186         {
187             oinputs.steering_adjust = steering_adjust >> 1;
188         }
189     }
190 
191     // ------------------------------------------------------------------------
192     // Determine whether to init spin or crash code
193     // ------------------------------------------------------------------------
194     int16_t spin2_copy = spin_control2;
195 
196     // dec_spin2:
197     if (spin2_copy != 0)
198     {
199         spin2_copy -= 2;
200         if (spin2_copy < 0)
201             spin_control2 = 0;
202         else
203             spin_switch(spin2_copy);
204     }
205 
206     // dec_spin1:
207     int16_t spin1_copy = spin_control1;
208 
209     if (spin1_copy != 0)
210     {
211         spin1_copy -= 2;
212         if (spin1_copy < 0)
213             spin_control1 = 0;
214         else
215             spin_switch(spin1_copy);
216     }
217     // Not spinning, init crash code
218     else
219         crash_switch();
220 }
221 
222 // Source: 0x1224
spin_switch(const uint16_t ctrl)223 void OCrash::spin_switch(const uint16_t ctrl)
224 {
225     crash_counter++;
226     crash_z = 0;
227 
228     switch (ctrl & 3)
229     {
230         // No Spin - Need to init crash/spin routines
231         case 0:
232             init_collision();
233             break;
234         // Init Spin
235         case 1:
236             do_collision();
237             break;
238         // Spin In Progress - End Collision Routine
239         case 2:
240         case 3:
241             end_collision();
242             break;
243     }
244 }
245 
246 // Init Crash.
247 //
248 // Source: 0x1252
crash_switch()249 void OCrash::crash_switch()
250 {
251     crash_counter++;
252     crash_z = 0;
253 
254     switch (crash_state & 7)
255     {
256         // No Crash. Need to setup crash routines.
257         case 0:
258             init_collision();
259             break;
260         // Initial Collision
261         case 1:
262             if ((crash_type & 3) == 0) do_bump();
263             else do_collision();
264             break;
265         // Flip Car
266         case 2:
267             do_car_flip();
268             break;
269         // Horizontally Flip Car, Trigger Smoke Cloud
270         case 3:
271         case 4:
272             trigger_smoke();
273             break;
274         // Do Girl Pointing Finger Animation/Delay Before Pan
275         case 5:
276             post_flip_anim();
277             break;
278         // Pan Camera To Track Centre
279         case 6:
280             pan_camera();
281             break;
282         // Camera Repositioned. Prepare For Restart.
283         case 7:
284             end_collision();
285             break;
286     }
287 }
288 
289 // Init Collision. Used For Spin & Flip
290 //
291 // Source: 0x1962
init_collision()292 void OCrash::init_collision()
293 {
294     oferrari.car_state = OFerrari::CAR_ANIM_SEQ; // Denote car animation sequence
295 
296     // Enable crash sprites
297     spr_shadow->control |= OSprites::ENABLE;
298     spr_pass1->control  |= OSprites::ENABLE;
299     spr_pass2->control  |= OSprites::ENABLE;
300 
301     // Disable normal sprites
302     oferrari.spr_ferrari->control &= ~OSprites::ENABLE;
303     oferrari.spr_shadow->control  &= ~OSprites::ENABLE;
304     oferrari.spr_pass1->control   &= ~OSprites::ENABLE;
305     oferrari.spr_pass2->control   &= ~OSprites::ENABLE;
306 
307     spr_ferrari->x = oferrari.spr_ferrari->x;
308     spr_ferrari->y = 221;
309     spr_ferrari->counter = 0x1FC;
310     spr_ferrari->draw_props = oentry::BOTTOM;
311 
312     // Collided with another vechicle
313     if (spin_control2)
314         init_spin2();
315     else if (spin_control1)
316         init_spin1();
317     // Crash into scenery
318     else
319     {
320         skid_counter = 0;
321         uint16_t car_inc = oinitengine.car_increment >> 16;
322         if (car_inc < 0x64)
323             collide_slow();
324         else if (car_inc < 0xC8)
325             collide_med();
326         else
327             collide_fast();
328     }
329 }
330 
331 // This code also triggers a flip, if the crash_type is set correctly.
332 // Source: 0x138C
do_collision()333 void OCrash::do_collision()
334 {
335     if (olevelobjs.collision_sprite)
336     {
337         olevelobjs.collision_sprite = 0;
338         if (spin_control1 || spin_control2)
339         {
340             spin_control2 = 0;
341             spin_control1 = 0;
342             init_collision(); // Init collision with another sprite
343             return;
344         }
345 
346         // Road generator 1
347         if (oinitengine.car_x_pos - (oroad.road_width >> 16) >= 0)
348         {
349             if (slide < 0)
350             {
351                 slide = -slide;
352                 oinitengine.car_x_pos -= slide;
353                 osoundint.queue_sound(sound::CRASH2);
354             }
355         }
356         // Road generator 2
357         else
358         {
359             if (slide >= 0)
360             {
361                 slide = -slide;
362                 oinitengine.car_x_pos -= slide;
363                 osoundint.queue_sound(sound::CRASH2);
364             }
365         }
366     }
367     // 0x13F8
368     uint32_t property_table = addr + (frame << 3);
369     crash_z = spr_ferrari->counter;
370     spr_ferrari->zoom = 0x80;
371     spr_ferrari->priority = 0x1FD;
372     oinitengine.car_x_pos -= slide;
373     spr_ferrari->addr = roms.rom0p->read32(property_table);
374 
375     if (roms.rom0p->read8(4 + property_table))
376         spr_ferrari->control |= OSprites::HFLIP;
377     else
378         spr_ferrari->control &= ~OSprites::HFLIP;
379 
380     //spr_ferrari->pal_src = roms.rom0p->read8(5 + property_table);
381     spr_ferrari->pal_src = oferrari.ferrari_pal;
382     spin_pass_frame = (int8_t) roms.rom0p->read8(6 + property_table);
383 
384     if (--spinflipcount2 > 0)
385     {
386         done(spr_ferrari);
387         return;
388     }
389 
390     spinflipcount2 = crash_spin_count; // Expired: spinflipcount
391 
392     if (spinflipcount1)
393     {
394         frame++;
395 
396         // 0x1470
397         // Initialize Car Flip
398         if (!spin_control1 && !spin_control2 && frame == 2 && crash_type != CRASH_SPIN)
399         {
400             crash_state = 2; // flip
401             addr = outrun.adr.sprite_crash_flip;
402             spinflipcount1 = 3; // 3 flips remaining
403             spinflipcount2 = crash_spin_count;
404             frame = 0;
405 
406             // Enable passenger shadows
407             spr_pass1s->control |= OSprites::ENABLE;
408             spr_pass2s->control |= OSprites::ENABLE;
409             done(spr_ferrari);
410             return;
411         }
412         // Do Spin
413         else
414         {
415             if (slide > 0)
416                 slide -= 2;
417             else if (slide < -2)
418                 slide += 2;
419 
420             // End of frame sequence
421             if (!roms.rom0p->read8(7 + property_table))
422             {
423                 done(spr_ferrari);
424                 return;
425             }
426         }
427     }
428     // 0x14F4
429     frame = 0;
430 
431     // Last spin
432     if (--spinflipcount1 <= 0)
433     {
434         osoundint.queue_sound(sound::STOP_SLIP);
435         if (spin_control2)
436         {
437             spin_control2++;
438         }
439         else if (spin_control1)
440         {
441             spin_control1++;
442         }
443         // Init smoke
444         else
445         {
446             crash_state = 4; // trigger smoke
447             crash_spin_count = 1;
448             spr_ferrari->x += slide; // inc ferrari x based on slide value
449         }
450     }
451     else
452         crash_spin_count++;
453 
454     done(spr_ferrari);
455 }
456 
457 // Source: 0x1D0C
end_collision()458 void OCrash::end_collision()
459 {
460     // Enable 'normal' Ferrari object
461     oferrari.spr_ferrari->control |= OSprites::ENABLE;
462     oferrari.spr_shadow->control  |= OSprites::ENABLE;
463     oferrari.spr_pass1->control   |= OSprites::ENABLE;
464     oferrari.spr_pass2->control   |= OSprites::ENABLE;
465 
466     coll_count2 = coll_count1;
467     if (!coll_count2)
468         coll_count2 = coll_count1 = 1;
469 
470     crash_counter = 0;
471     crash_state = 0;
472     olevelobjs.collision_sprite = 0;
473 
474     oferrari.spr_ferrari->x = 0;
475     oferrari.spr_ferrari->y = 221;
476     oferrari.car_ctrl_active = true;
477     oferrari.car_state = OFerrari::CAR_NORMAL;
478     olevelobjs.spray_counter = 0;
479     crash_z = 0;
480 
481     if (spin_control1)
482         oferrari.car_inc_old = oinitengine.car_increment >> 16;
483     else
484         oferrari.reset_car();
485 
486     spin_control2 = 0;
487     spin_control1 = 0;
488 
489     spr_ferrari->control &= ~OSprites::ENABLE;
490     spr_shadow->control  &= ~OSprites::ENABLE;
491     spr_pass1->control   &= ~OSprites::ENABLE;
492     spr_pass1s->control  &= ~OSprites::ENABLE;
493     spr_pass2->control   &= ~OSprites::ENABLE;
494     spr_pass2s->control  &= ~OSprites::ENABLE;
495 
496     function_pass1 = &OCrash::do_crash_passengers;
497     function_pass2 = &OCrash::do_crash_passengers;
498     oinputs.crash_input = 0x10; // Set delay in processing steering
499 }
500 
501 // Low Speed Bump - Car Rises in air and sinks
502 // Source: 0x12BE
do_bump()503 void OCrash::do_bump()
504 {
505     oferrari.car_ctrl_active = false;   // Disable user control of car
506     spr_ferrari->zoom = 0x80;           // Set Entry Number For Zoom Lookup Table
507     spr_ferrari->priority = 0x1FD;
508 
509     int16_t new_position = (int8_t) roms.rom0.read8(DATA_MOVEMENT + (lookup_index << 3));
510 
511     if (new_position)
512         crash_z = spr_ferrari->counter;
513 
514     spr_ferrari->y = 221 - (new_position >> shift);
515 
516     uint32_t frames = addr + (frame << 3);
517     spr_ferrari->addr = roms.rom0p->read32(frames);
518 
519     if (roms.rom0p->read8(frames + 4))
520         spr_ferrari->control |= OSprites::HFLIP;
521     else
522         spr_ferrari->control &= ~OSprites::HFLIP;
523 
524     //spr_ferrari->pal_src = roms.rom0p->read8(frames + 5);
525     spr_ferrari->pal_src = oferrari.ferrari_pal;
526     spin_pass_frame = (int8_t) roms.rom0p->read8(frames + 6);
527 
528     if (++lookup_index >= 0x10)
529     {
530         addr += (frame_restore << 3);
531         spr_ferrari->addr = roms.rom0p->read32(addr);
532         spin_pass_frame = (int8_t) roms.rom0p->read8(addr + 6);
533         crash_state = 4;      // Trigger smoke cloud
534         crash_spin_count = 1; // Denote Crash
535     }
536 
537     done(spr_ferrari);
538 }
539 
540 // Source: 0x1562
do_car_flip()541 void OCrash::do_car_flip()
542 {
543     // Do this if during the flip, the car has recollided with a new sprite + slow crash (similar to spin_collide)
544     if (olevelobjs.collision_sprite && crash_speed == 1)
545     {
546         uint16_t car_inc16 = oinitengine.car_increment >> 16;
547 
548         // Road generator 1
549         if (oinitengine.car_x_pos - (oroad.road_width >> 16) >= 0)
550         {
551             // swap_slide_dir2
552             if (slide < 0)
553             {
554                 slide = -slide;
555                 oinitengine.car_increment = ((car_inc16 >> 1) << 16) | (oinitengine.car_increment & 0xFFFF);
556                 osoundint.queue_sound(sound::CRASH2);
557                 if (oinitengine.car_increment >> 16 > 0x14)
558                 {
559                     int16_t z = spr_ferrari->counter > 0x1FD ? 0x1FD : spr_ferrari->counter; // d3
560                     int16_t x_adjust = (0x50 * z) >> 9; // d1
561                     if (slide < 0) x_adjust = -x_adjust;
562                     oinitengine.car_x_pos -= x_adjust;
563                 }
564             }
565             // 0x15F6
566             else
567                 slide += (slide >> 3);
568         }
569         // Road generator 2
570         else
571         {
572             // swap_slide_dir2:
573             if (slide >= 0)
574             {
575                 slide = -slide;
576                 oinitengine.car_increment = ((car_inc16 >> 1) << 16) | (oinitengine.car_increment & 0xFFFF);
577                 osoundint.queue_sound(sound::CRASH2);
578                 if (oinitengine.car_increment >> 16 > 0x14)
579                 {
580                     int16_t z = spr_ferrari->counter > 0x1FD ? 0x1FD : spr_ferrari->counter; // d3
581                     int16_t x_adjust = (0x50 * z) >> 9; // d1
582                     if (slide < 0) x_adjust = -x_adjust;
583                     oinitengine.car_x_pos -= x_adjust;
584                 }
585             }
586             // 0x15F6
587             else
588                 slide += (slide >> 3);
589         }
590     }
591 
592     // flip_cont
593     olevelobjs.collision_sprite = 0; // Moved this for clarity
594     uint32_t frames = addr + (frame << 3);
595     spr_ferrari->addr = roms.rom0p->read32(frames);
596 
597     // ------------------------------------------------------------------------
598     // Fast Crash: Car Heads towards camera in sky, before vanishing (0x161E)
599     // ------------------------------------------------------------------------
600     if (crash_speed == 0)
601     {
602         spr_shadow->control &= ~OSprites::ENABLE; // Disable Shadow
603         spr_ferrari->counter += crash_zinc;       // Increment Crash Z
604         if (spr_ferrari->counter > 0x3FF)
605         {
606             spr_ferrari->zoom = 0;
607             spr_ferrari->counter = 0;
608             init_finger(frames);
609             done(spr_ferrari);
610             return;
611         }
612         else
613             crash_zinc++;
614     }
615     // ------------------------------------------------------------------------
616     // Slow Crash (0x1648 flip_slower)
617     // ------------------------------------------------------------------------
618     else
619     {
620         spr_ferrari->counter -= crash_zinc;       // Decrement Crash Z
621         if (crash_zinc > 2)
622             crash_zinc--;
623     }
624 
625     // set_crash_z_inc
626     // Note that we've set crash_zinc previously now for clarity
627 
628     // use ferrari_crash_z to set priority
629     spr_ferrari->priority = spr_ferrari->counter > 0x1FD ? 0x1FD : spr_ferrari->counter;
630 
631     int16_t x_diff = (slide * spr_ferrari->priority) >> 9;
632     oinitengine.car_x_pos -= x_diff;
633 
634     int16_t passenger_frame = (int8_t) roms.rom0p->read8(6 + frames);
635 
636     // Start of sequence
637     if (passenger_frame == 0)
638     {
639         slide >>= 1;
640         osoundint.queue_sound(sound::CRASH2);
641     }
642 
643     // Set Z during lower frames
644     if (passenger_frame <= 0x10 && spr_ferrari->counter <= 0x1FE)
645         crash_z = spr_ferrari->counter;
646 
647     // 0x16CC
648     passenger_frame = (passenger_frame * spr_ferrari->priority) >> 9;
649 
650     // Set Ferrari Y
651     int16_t y = -(oroad.road_y[oroad.road_p0 + spr_ferrari->priority] >> 4) + 223;
652     y -= passenger_frame;
653     spr_ferrari->y = y;
654 
655     // Set Ferrari Zoom from Z
656     spr_ferrari->zoom = (spr_ferrari->counter >> 2);
657     if (spr_ferrari->zoom < 0x40) spr_ferrari->zoom = 0x40;
658 
659     // Set Ferrari H-Flip
660     if (crash_side)
661         spr_ferrari->control |= OSprites::HFLIP;
662     else
663         spr_ferrari->control &= ~OSprites::HFLIP;
664 
665     // Palette Hack for recoloured cars. Original version was simply: spr_ferrari->pal_src = roms.rom0p->read8(4 + frames);
666     if (frame >= 7)
667         spr_ferrari->pal_src = oferrari.ferrari_pal;
668     else
669         spr_ferrari->pal_src = oferrari.ferrari_pal == OFerrari::PAL_RED ? roms.rom0p->read8(4 + frames) : oferrari.ferrari_pal + 4;
670 
671     if (--spinflipcount2 > 0)
672     {
673         done(spr_ferrari);
674         return;
675     }
676 
677     spinflipcount2 = crash_spin_count;
678 
679     // 0x1736
680     // Advance to next frame in sequence
681     if (spinflipcount1)
682     {
683         frame++;
684         // End of frame sequence
685         if ((roms.rom0p->read8(7 + frames) & BIT_7) == 0)
686         {
687             done(spr_ferrari);
688             return;
689         }
690     }
691 
692     frame = 0;
693 
694     if (--spinflipcount1 > 0)
695     {
696         crash_spin_count++;
697     }
698     else
699     {
700         init_finger(frames);
701     }
702     done(spr_ferrari);
703 }
704 
705 // Init Delay/Girl Pointing Finger
706 // Source: 0x175C
init_finger(uint32_t frames)707 void OCrash::init_finger(uint32_t frames)
708 {
709     crash_spin_count = 1;           // Denote Crash has taken place
710 
711     // Do Delay whilst girl points finger
712     if (crash_type == CRASH_FLIP)
713     {
714         oferrari.wheel_state = OFerrari::WHEELS_ON;
715         oferrari.car_state   = OFerrari::CAR_NORMAL;
716         slide = 0;
717         addr += frames;
718         crash_delay = 30;
719         crash_state = 5;
720     }
721     // Slide Car and Trigger Smoke Cloud
722     else
723     {
724         crash_state = 3;
725         frame = 0;
726         addr = outrun.adr.sprite_crash_man1;
727         crash_spin_count = 4;   // Denote third flip
728         spinflipcount2   = 4;
729     }
730 }
731 
732 // Post Crash: Slide Car Slightly, then trigger smoke
733 // Source: 0x17D2
trigger_smoke()734 void OCrash::trigger_smoke()
735 {
736     crash_z = spr_ferrari->counter;
737     int16_t slide_copy = slide;
738 
739     if (slide < 0)
740         slide++;
741     else if (slide > 0)
742         slide--;
743 
744     // Slide Car
745     oinitengine.car_x_pos -= slide_copy;
746 
747     spr_ferrari->addr = roms.rom0p->read32(addr);
748 
749     // Set Ferrari H-Flip
750     if (roms.rom0p->read8(4 + addr))
751         spr_ferrari->control |= OSprites::HFLIP;
752     else
753         spr_ferrari->control &= ~OSprites::HFLIP;
754 
755     //spr_ferrari->pal_src =     roms.rom0p->read8(5 + addr);
756     spr_ferrari->pal_src = oferrari.ferrari_pal;
757     spin_pass_frame = (int8_t) roms.rom0p->read8(6 + addr);
758 
759     // Slow Car
760     oinitengine.car_increment =
761         (oinitengine.car_increment - ((oinitengine.car_increment >> 2) & 0xFFFF0000))
762         | (oinitengine.car_increment & 0xFFFF);
763 
764     // Car stationary
765     if (oinitengine.car_increment >> 16 <= 0)
766     {
767         oinitengine.car_increment = 0;
768         oferrari.wheel_state = OFerrari::WHEELS_ON;
769         oferrari.car_state   = OFerrari::CAR_NORMAL;
770         slide = 0;
771         crash_delay = 30;
772         crash_state = 5; // post crash animation delay state
773     }
774 
775     done(spr_ferrari);
776 }
777 
778 // Source: 0x1870
post_flip_anim()779 void OCrash::post_flip_anim()
780 {
781     oferrari.car_ctrl_active = false;  // Car and road updates disabled
782     if (--crash_delay > 0)
783     {
784         done(spr_ferrari);
785         return;
786     }
787 
788     oferrari.car_ctrl_active = true;
789     crash_state = 6; // Denote pan camera to track centre
790 
791     int16_t road_width = oroad.road_width >> 16;
792     int16_t car_x_pos  = oinitengine.car_x_pos;
793     camera_xinc = 8;
794 
795     // Double Road
796     if (road_width >= 0xD7)
797     {
798         if (car_x_pos < 0)
799             road_width = -road_width;
800     }
801     else
802     {
803         road_width = 0;
804     }
805 
806     camera_x_target = road_width;
807 
808     // 1/ Car on road generator 1 (1 road enabled)
809     // 2/ Car on road generator 1 (2 roads enabled)
810     if (road_width < car_x_pos)
811     {
812         camera_xinc += (car_x_pos - road_width) >> 6;
813         camera_xinc = -camera_xinc;
814     }
815     else
816     {
817         camera_xinc += (road_width - car_x_pos) >> 6;
818     }
819 
820     done(spr_ferrari);
821 }
822 
823 // Pan Camera Back To Centre After Flip
824 // Source: 0x18EC
pan_camera()825 void OCrash::pan_camera()
826 {
827     oferrari.car_ctrl_active = true;
828 
829     oinitengine.car_x_pos += camera_xinc;
830 
831     int16_t x_diff = (oferrari.car_x_diff * spr_ferrari->counter) >> 9;
832     spr_ferrari->x += x_diff;
833 
834     // Pan Right
835     if (camera_xinc >= 0)
836     {
837         if (camera_x_target <= oinitengine.car_x_pos)
838             crash_state = 7; // Denote camera position and ready for restart
839     }
840     // Pan Left
841     else
842     {
843         if (camera_x_target >= oinitengine.car_x_pos)
844             crash_state = 7;
845     }
846 
847     done(spr_ferrari);
848 }
849 
850 // Source: 0x1C7E
init_spin1()851 void OCrash::init_spin1()
852 {
853     osoundint.queue_sound(sound::INIT_SLIP);
854     uint16_t car_inc = oinitengine.car_increment >> 16;
855     uint16_t spins = 1;
856     if (car_inc > 0xB4)
857         spins += outils::random() & 1;
858 
859     spinflipcount1 = spins;
860     crash_spin_count = 2;
861     spinflipcount2 = 2;
862 
863     slide = ((spins + 1) << 2) + (car_inc > 0xFF) ? 0xFF >> 3 : car_inc >> 3;
864 
865     if (skid_counter_bak < 0)
866         addr = outrun.adr.sprite_crash_spin1;
867     else
868     {
869         addr = outrun.adr.sprite_crash_spin1;
870         slide = -slide;
871     }
872 
873     spin_control1++;
874     frame = 0;
875     skid_counter = 0;
876     spr_ferrari->road_priority = spr_ferrari->counter;
877 }
878 
879 // Source: 0x1C10
init_spin2()880 void OCrash::init_spin2()
881 {
882     osoundint.queue_sound(sound::INIT_SLIP);
883     uint16_t car_inc = oinitengine.car_increment >> 16;
884     spinflipcount1 = 1;
885     crash_spin_count = 2;
886     spinflipcount2 = 8;
887 
888     slide = (car_inc > 0xFF) ? 0xFF >> 3 : car_inc >> 3;
889 
890     if (oinitengine.road_type != OInitEngine::ROAD_RIGHT)
891     {
892         addr = outrun.adr.sprite_crash_spin1;
893     }
894     else
895     {
896         addr = outrun.adr.sprite_crash_spin1;
897         slide = -slide;
898     }
899 
900     spin_control2++;
901     frame = 0;
902     skid_counter = 0;
903     spr_ferrari->road_priority = spr_ferrari->counter;
904 }
905 
906 // Collision: Slow
907 // Rebound and bounce car in air
908 // Source: 0x19EE
collide_slow()909 void OCrash::collide_slow()
910 {
911     osoundint.queue_sound(sound::REBOUND);
912 
913     // Setup shift value for car bump, based on current speed, which ultimately determines how much car rises in air
914     uint16_t car_inc = oinitengine.car_increment >> 16;
915 
916     if (car_inc <= 0x28)
917         shift = 6;
918     else if (car_inc <= 0x46)
919         shift = 5;
920     else
921         shift = 4;
922 
923     lookup_index = 0;
924 
925     // Calculate change in road y, so we can determine incline frame for ferrari
926     int16_t y = oroad.road_y[oroad.road_p0 + (0x3E0 / 2)] - oroad.road_y[oroad.road_p0 + (0x3F0 / 2)];
927     frame_restore = 0;
928     if (y >= 0x12) frame_restore++;
929     if (y >= 0x13) frame_restore++;
930 
931     // Right Hand Side: Increment Frame Entry By 3
932     if (oinitengine.car_x_pos < 0)
933         addr = outrun.adr.sprite_bump_data2;
934     else
935         addr = outrun.adr.sprite_bump_data1;
936 
937     crash_type = CRASH_BUMP; // low speed bump
938     oinitengine.car_increment &= 0xFFFF;
939 
940     // set_collision:
941     frame = 0;
942     crash_state = 1; // collision with object
943     spr_ferrari->road_priority = spr_ferrari->counter;
944 }
945 
946 // Collision: Medium
947 // Spin car
948 // Source: 0x1A98
collide_med()949 void OCrash::collide_med()
950 {
951     osoundint.queue_sound(sound::INIT_SLIP);
952 
953     // Set number of spins based on car speed
954     uint16_t car_inc = oinitengine.car_increment >> 16;
955     spinflipcount1 = car_inc <= 0x96 ? 1 : 2;
956     spinflipcount2 = crash_spin_count = 2;
957     slide = ((spinflipcount1 + 1) << 2) + ((car_inc > 0xFF ? 0xFF : car_inc) >> 3);
958 
959     // Right Hand Side: Increment Frame Entry By 3
960     if (oinitengine.car_x_pos < 0)
961     {
962         addr = outrun.adr.sprite_crash_spin1;
963         slide = -slide;
964     }
965     else
966         addr = outrun.adr.sprite_crash_spin1;
967 
968     crash_type = CRASH_SPIN;
969 
970     // set_collision:
971     frame = 0;
972     crash_state = 1; // collision with object
973     spr_ferrari->road_priority = spr_ferrari->counter;
974 }
975 
976 // Collision: Fast
977 // Spin, Then Flip Car
978 //
979 // Source: 0x1B12
collide_fast()980 void OCrash::collide_fast()
981 {
982     osoundint.queue_sound(sound::CRASH1);
983 
984     uint16_t car_inc = oinitengine.car_increment >> 16;
985     if (car_inc > 0xFA)
986     {
987         crash_zinc = 1;
988         crash_speed = 0;
989     }
990     else
991     {
992         crash_zinc = 0x10;
993         crash_speed = 1;
994     }
995 
996     spinflipcount1 = 1;
997     spinflipcount2 = crash_spin_count = 2;
998 
999     slide = (car_inc > 0xFF ? 0xFF : car_inc) >> 2;
1000     slide += (slide >> 1);
1001 
1002     if (oinitengine.road_type != OInitEngine::ROAD_STRAIGHT)
1003     {
1004         int16_t d2 = (0x78 - (oinitengine.road_curve <= 0x78 ? oinitengine.road_curve : 0x78)) >> 1;
1005 
1006         // collide_fast_curve:
1007         slide += d2;
1008         if (oinitengine.road_type == OInitEngine::ROAD_RIGHT)
1009             slide = -slide;
1010     }
1011     else
1012     {
1013         if (oinitengine.car_x_pos < 0) slide = -slide; // rhs
1014     }
1015 
1016     // set_fast_slide:
1017     if (slide > 0x78)
1018         slide = 0x78;
1019 
1020     if (oinitengine.car_x_pos < 0)
1021     {
1022         addr = outrun.adr.sprite_crash_spin2;
1023         crash_side = 0; // RHS
1024     }
1025     else
1026     {
1027         addr = outrun.adr.sprite_crash_spin1;
1028         crash_side = 1; // LHS
1029     }
1030 
1031     crash_type = CRASH_FLIP; // Flip
1032 
1033     // set_collision:
1034     frame = 0;
1035     crash_state = 1; // collision with object
1036     spr_ferrari->road_priority = spr_ferrari->counter;
1037 }
1038 
1039 // Source: 0x1556
done(oentry * sprite)1040 void OCrash::done(oentry* sprite)
1041 {
1042     osprites.map_palette(sprite);
1043 
1044     if (oroad.get_view_mode() != ORoad::VIEW_INCAR || crash_type == CRASH_FLIP)
1045         osprites.do_spr_order_shadows(sprite);
1046 
1047     sprite->road_priority = sprite->counter;
1048 }
1049 
1050 // ------------------------------------------------------------------------------------------------
1051 //                                      SHADOW CRASH ROUTINES
1052 // ------------------------------------------------------------------------------------------------
1053 
1054 // Render Shadow
1055 //
1056 // Disabled during fast car flip, when car rapidly heading towards screen
1057 //
1058 // Source: 0x1DF2
do_shadow(oentry * src_sprite,oentry * dst_sprite)1059 void OCrash::do_shadow(oentry* src_sprite, oentry* dst_sprite)
1060 {
1061     uint8_t shadow_shift;
1062 
1063     // Ferrari Shadow
1064     if (src_sprite == spr_ferrari)
1065     {
1066         dst_sprite->draw_props = oentry::BOTTOM;
1067         shadow_shift = 1;
1068     }
1069     else
1070     {
1071         shadow_shift = 3;
1072     }
1073 
1074     dst_sprite->x = src_sprite->x;
1075     dst_sprite->road_priority = src_sprite->road_priority;
1076 
1077     // Get Z from source sprite (stored in counter)
1078     uint16_t counter = (src_sprite->counter) >> shadow_shift;
1079     counter = counter - (counter >> 2);
1080     dst_sprite->zoom = (uint8_t) counter;
1081 
1082     // Set shadow y
1083     uint16_t offset = src_sprite->counter > 0x1FF ? 0x1FF : src_sprite->counter;
1084     dst_sprite->y = -(oroad.road_y[oroad.road_p0 + offset] >> 4) + 223;
1085 
1086     if (oroad.get_view_mode() != ORoad::VIEW_INCAR || crash_type == CRASH_FLIP)
1087         osprites.do_spr_order_shadows(dst_sprite);
1088 }
1089 
1090 // ------------------------------------------------------------------------------------------------
1091 //                                     PASSENGER CRASH ROUTINES
1092 // ------------------------------------------------------------------------------------------------
1093 
1094 // Flips & Spins Only
1095 //
1096 // Process passengers during crash scenario.
1097 //
1098 // Source: 0x1E66
do_crash_passengers(oentry * sprite)1099 void OCrash::do_crash_passengers(oentry* sprite)
1100 {
1101     // --------------------------------------------------------------------------------------------
1102     // Flip car
1103     // --------------------------------------------------------------------------------------------
1104     if (crash_state == 2)
1105     {
1106         // Update pointer to functions
1107         if (sprite == spr_pass1)
1108             function_pass1 = &OCrash::flip_start;
1109         else if (sprite == spr_pass2)
1110             function_pass2 = &OCrash::flip_start;
1111 
1112         // Crash Passenger Flip
1113         crash_pass_flip(sprite);
1114         return;
1115     }
1116 
1117     // --------------------------------------------------------------------------------------------
1118     // Non-Flip
1119     // --------------------------------------------------------------------------------------------
1120     if (crash_state < 5)
1121         crash_pass1(sprite);
1122     else
1123         crash_pass2(sprite);
1124 
1125     if (oroad.get_view_mode() != ORoad::VIEW_INCAR || crash_type == CRASH_FLIP)
1126     {
1127         osprites.map_palette(sprite);
1128         osprites.do_spr_order_shadows(sprite);
1129     }
1130 }
1131 
1132 // Position Passenger Sprites During Crash (But Not Flip)
1133 //
1134 // - Process passenger sprites in crash scenario
1135 // - Called separately for man and girl
1136 //
1137 // Source: 0x1EA6
crash_pass1(oentry * sprite)1138 void OCrash::crash_pass1(oentry* sprite)
1139 {
1140     uint32_t frames = (sprite == spr_pass1 ? outrun.adr.sprite_crash_man1 : outrun.adr.sprite_crash_girl1) + (spin_pass_frame << 3);
1141 
1142     sprite->addr    = roms.rom0p->read32(frames);
1143     uint8_t props   = roms.rom0p->read8(4 + frames);
1144     sprite->pal_src = roms.rom0p->read8(5 + frames);
1145     sprite->x       = spr_ferrari->x + (int8_t) roms.rom0p->read8(6 + frames);
1146     sprite->y       = spr_ferrari->y + (int8_t) roms.rom0p->read8(7 + frames);
1147 
1148     // Check H-Flip
1149     if (props & BIT_7)
1150         sprite->control |= OSprites::HFLIP;
1151     else
1152         sprite->control &= ~OSprites::HFLIP;
1153 
1154     // Test whether we should set priority higher (unused on passenger sprites I think)
1155     if (props & BIT_0)
1156         sprite->priority = sprite->road_priority = 0x1FE;
1157     else
1158         sprite->priority = sprite->road_priority = 0x1FD;
1159 
1160     sprite->zoom = 0x7E;
1161 }
1162 
1163 // Passenger animations following the crash sequence i.e. when car is stationary
1164 //
1165 // 3 = hands battering,
1166 // 2 = man scratches head, girl taps car
1167 // 1 = man scratch head & girl points
1168 // 0 = man subdued & girl points
1169 //
1170 // - Process passenger sprites in crash scenario
1171 // - Called separately for man and girl
1172 // - Selects which passenger animation to play
1173 //
1174 // Source: 0x1F26
crash_pass2(oentry * sprite)1175 void OCrash::crash_pass2(oentry* sprite)
1176 {
1177     uint32_t frames = (sprite == spr_pass1 ? outrun.adr.sprite_crash_man2 : outrun.adr.sprite_crash_girl2);
1178 
1179     // Use coll_count2 to select one of the three animations that can be played
1180     // Use crash_delay to toggle between two distinct frames
1181     frames += ((coll_count2 & 3) << 4) + (crash_delay & 8);
1182 
1183     sprite->addr    = roms.rom0p->read32(frames);
1184     uint8_t props   = roms.rom0p->read8(4 + frames);
1185     sprite->pal_src = roms.rom0p->read8(5 + frames);
1186     sprite->x       = spr_ferrari->x + (int8_t) roms.rom0p->read8(6 + frames);
1187     sprite->y       = spr_ferrari->y + (int8_t) roms.rom0p->read8(7 + frames);
1188 
1189     // Check H-Flip
1190     if (props & BIT_7)
1191         sprite->control |= OSprites::HFLIP;
1192     else
1193         sprite->control &= ~OSprites::HFLIP;
1194 
1195     // Test whether we should set priority higher (unused on passenger sprites I think)
1196     if (props & BIT_0)
1197         sprite->priority = sprite->road_priority = 0x1FF;
1198     else
1199         sprite->priority = sprite->road_priority = 0x1FE;
1200 
1201     sprite->zoom = 0x7E;
1202 
1203     // Man
1204     if (sprite == spr_pass1)
1205     {
1206         const int8_t XY_OFF[] =
1207         {
1208             -0xC, -0x1E,
1209             0x2,  -0x1B,
1210             0x4,  -0x1A,
1211             0x5,  -0x1E,
1212             0x11, -0x1B,
1213             0x0,  -0x1A,
1214             -0x1, -0x1B,
1215             -0xC, -0x1C,
1216             -0xE, -0x1B,
1217             -0xE, -0x1C,
1218             -0xE, -0x1D,
1219             -0xC, -0x1B,
1220             -0xC, -0x1C,
1221             -0xC, -0x1D,
1222         };
1223 
1224         sprite->x += XY_OFF[spin_pass_frame << 1];
1225         sprite->y += XY_OFF[(spin_pass_frame << 1) + 1];
1226     }
1227     // Woman
1228     else
1229     {
1230         const int8_t XY_OFF[] =
1231         {
1232             0xA,   -0x1A,
1233             0x0,   -0x1B,
1234             -0xF,  -0x1B,
1235             -0x15, -0x1B,
1236             -0x2,  -0x1E,
1237             0x7,   -0x1A,
1238             0x13,  -0x1D,
1239             0x9,   -0x1B,
1240             0x3,   -0x1B,
1241             0x3,   -0x1C,
1242             0x3,   -0x1D,
1243             0x7,   -0x1B,
1244             0x7,   -0x1C,
1245             0x7,   -0x1D,
1246         };
1247 
1248         sprite->x += XY_OFF[spin_pass_frame << 1];
1249         sprite->y += XY_OFF[(spin_pass_frame << 1) + 1];
1250     }
1251 }
1252 
1253 // Handle passenger animation sequence during car flip
1254 //
1255 // 3 main stages:
1256 // 1/ Flip passengers out of car
1257 // 2/ Passengers sit up on road after crash
1258 // 3/ Passengers turn head and look at car (only if camera pan)
1259 //
1260 // Source: 0x1FDE
1261 
crash_pass_flip(oentry * sprite)1262 void OCrash::crash_pass_flip(oentry* sprite)
1263 {
1264     // Some of these variable names really need refactoring
1265     sprite->reload        = 0;                      // clear passenger flip control
1266     sprite->xw1           = 0;
1267     sprite->x             = spr_ferrari->x;
1268     sprite->traffic_speed = crash_spin_count;
1269     sprite->counter       = 0x1FE;                  // sprite zoom
1270 
1271     // Set address of animation sequence based on whether male/female
1272     sprite->z = sprite == spr_pass1 ? outrun.adr.sprite_crash_flip_m1 : outrun.adr.sprite_crash_flip_g1;
1273 
1274     flip_start(sprite);
1275 }
1276 
1277 // Source: 0x201A
flip_start(oentry * sprite)1278 void OCrash::flip_start(oentry* sprite)
1279 {
1280     if (outrun.game_state != GS_ATTRACT && outrun.game_state != GS_INGAME)
1281     {
1282         osprites.do_spr_order_shadows(sprite);
1283         done(sprite);
1284         return;
1285     }
1286 
1287     switch (sprite->reload & 3) // check passenger flip control
1288     {
1289         // Flip passengers out of car
1290         case 0:
1291             pass_flip(sprite);
1292             break;
1293 
1294         // Passengers sit up on road after crash
1295         case 1:
1296             pass_situp(sprite);
1297             break;
1298 
1299         // Passengers turn head and look at car (only if camera pan)
1300         case 2:
1301         case 3:
1302             pass_turnhead(sprite);
1303             break;
1304     }
1305 }
1306 
1307 // Flip passengers out of car
1308 // Source: 0x2066
pass_flip(oentry * sprite)1309 void OCrash::pass_flip(oentry* sprite)
1310 {
1311     // Fast crash
1312     if (crash_speed == 0)
1313     {
1314         sprite->counter += (crash_zinc << 2);
1315 
1316         if (sprite->counter > 0x3FF)
1317         {
1318             sprite->reload = 1; // // Passenger Control: Passengers sit up on road after crash
1319 
1320             // Disable sprite and shadow
1321             sprite->control &= ~OSprites::ENABLE;
1322             if (sprite == spr_pass1)
1323                 spr_pass1s->control &= ~OSprites::ENABLE;
1324             else
1325                 spr_pass2s->control &= ~OSprites::ENABLE;
1326             return;
1327         }
1328     }
1329     // Slow crash
1330     else
1331     {
1332         int16_t zinc = crash_zinc >> 2;
1333 
1334         // Adjust the z position of the female more than the man
1335         if (sprite == spr_pass2)
1336         {
1337             zinc += (zinc >> 1);
1338         }
1339 
1340         sprite->counter -= zinc;
1341     }
1342 
1343     // set_z_lookup
1344     int16_t zoom = sprite->counter >> 2;
1345     if (zoom < 0x40) zoom = 0x40;
1346     sprite->zoom = (uint8_t) zoom;
1347 
1348     uint32_t frames = sprite->z + (sprite->xw1 << 3);
1349     sprite->addr = roms.rom0p->read32(frames);
1350 
1351     uint16_t offset = sprite->counter > 0x1FF ? 0x1FF : sprite->counter;
1352     int16_t y_change = (((int8_t) roms.rom0p->read8(6 + frames)) * offset) >> 9; // d1
1353 
1354     sprite->y = -(oroad.road_y[oroad.road_p0 + offset] >> 4) + 223;
1355     sprite->y -= y_change;
1356 
1357     // 2138
1358 
1359     sprite->priority = offset;
1360     if (crash_side)
1361         sprite->control |= OSprites::HFLIP;
1362     else
1363         sprite->control &= ~OSprites::HFLIP;
1364 
1365     sprite->pal_src = roms.rom0p->read8(4 + frames);
1366 
1367     // Decrement spin count
1368     // Increment frame of passengers for first spins
1369     if (--sprite->traffic_speed <= 0)
1370     {
1371         sprite->traffic_speed = crash_spin_count;
1372         sprite->xw1++; // Increase passenger frame
1373 
1374         // End of animation sequence. Progress to next sequnce of animations.
1375         if (roms.rom0p->read8(7 + frames) & BIT_7)
1376         {
1377             sprite->reload = 1; // Passenger Control: Passengers sit up on road after crash
1378             sprite->xw1    = 0; // Reset passenger frame
1379 
1380             // Update address of animation sequence to be used
1381             sprite->z      = sprite == spr_pass1 ? outrun.adr.sprite_crash_flip_m2 : outrun.adr.sprite_crash_flip_g2;
1382             frames         = sprite->z;
1383 
1384             // Set Frame Delay for this animation sequence from lower bytes
1385             sprite->traffic_speed = roms.rom0p->read8(7 + frames) & 0x7F;
1386 
1387             done(sprite);
1388             return;
1389         }
1390     }
1391 
1392     // set_passenger_x
1393     sprite->x =  spr_ferrari->x;
1394     sprite->x += ((int8_t) roms.rom0p->read8(5 + frames));
1395     done(sprite);
1396 }
1397 
1398 // Passengers sit up on road after crash
1399 // Source: 0x205A
pass_situp(oentry * sprite)1400 void OCrash::pass_situp(oentry* sprite)
1401 {
1402     // Update passenger x position
1403     int16_t x_diff = (oferrari.car_x_diff * sprite->counter) >> 9;
1404     sprite->x += x_diff;
1405 
1406     uint32_t frames = sprite->z + (sprite->xw1 << 3);
1407     sprite->addr    = roms.rom0p->read32(frames);
1408     sprite->pal_src = roms.rom0p->read8(4 + frames);
1409 
1410     // Decrement frame delay counter
1411     if (--sprite->traffic_speed <= 0)
1412     {
1413         sprite->traffic_speed = roms.rom0p->read8(0xF + frames) & 0x7F;
1414 
1415         // End of animation sequence. Progress to next sequnce of animations.
1416         if (roms.rom0p->read8(7 + frames) & BIT_7)
1417         {
1418             sprite->reload = 2; // Passenger Control: Passengers turn head and look at car
1419         }
1420         else
1421         {
1422             sprite->xw1++; // Increase passenger frame
1423 
1424             // If camera pan: Make passengers turn heads!
1425             if (crash_state == 6)
1426                     sprite->reload = 2;
1427         }
1428     }
1429     done(sprite);
1430 }
1431 
1432 // Passengers turn head and look at car (only if camera pan)
1433 // Source: 0x222C
pass_turnhead(oentry * sprite)1434 void OCrash::pass_turnhead(oentry* sprite)
1435 {
1436     // Update passenger x position
1437     int16_t x_diff = (oferrari.car_x_diff * sprite->counter) >> 9;
1438     sprite->x += x_diff;
1439 
1440     uint32_t frames = sprite->z + (sprite->xw1 << 3);
1441     sprite->addr    = roms.rom0p->read32(frames);
1442     sprite->pal_src = roms.rom0p->read8(4 + frames);
1443 
1444     // End of animation sequence.
1445     if (roms.rom0p->read8(7 + frames) & BIT_7)
1446     {
1447         done(sprite);
1448         return;
1449     }
1450 
1451     // Decrement frame delay counter
1452     if (--sprite->traffic_speed <= 0)
1453     {
1454         sprite->traffic_speed = roms.rom0p->read8(0xF + frames) & 0x7F;
1455         sprite->xw1++; // Increase passenger frame
1456     }
1457 
1458     done(sprite);
1459 }