1 /*************************************************************************** 2 Ferrari Rendering & Handling Code. 3 4 Much of the handling code is very messy. As such, the translated code 5 isn't great as I tried to focus on accuracy rather than refactoring. 6 7 A good example of the randomness is a routine I've named 8 do_sound_score_slip() 9 which performs everything from updating the score, setting the audio 10 engine tone, triggering smoke effects etc. in an interwoven fashion. 11 12 The Ferrari sprite has different properties to other game objects 13 As there's only one of them, I've rolled the additional variables into 14 this class. 15 16 Copyright Chris White. 17 See license.txt for more details. 18 ***************************************************************************/ 19 20 #pragma once 21 22 #include "outrun.hpp" 23 24 class OFerrari 25 { 26 public: 27 // Ferrari Sprite Object 28 oentry *spr_ferrari; 29 30 // Passenger 1 Sprite Object 31 oentry *spr_pass1; 32 33 // Passenger 2 Sprite Object 34 oentry *spr_pass2; 35 36 // Ferrari Shadow Sprite Object 37 oentry *spr_shadow; 38 39 // ------------------------------------------------------------------------- 40 // Ferrari Colours 41 // ------------------------------------------------------------------------- 42 43 // Palette to use (change Ferrari colours) 44 uint16_t ferrari_pal; 45 46 const static uint16_t PAL_RED = 2; 47 const static uint16_t PAL_BLUE = 256; 48 const static uint16_t PAL_YELLOW = 261; 49 const static uint16_t PAL_GREEN = 266; 50 const static uint16_t PAL_CYAN = 271; 51 52 // ------------------------------------------------------------------------- 53 // Main Switch Variables 54 // ------------------------------------------------------------------------- 55 56 enum 57 { 58 // Initialise Intro Animation Sequences 59 FERRARI_SEQ1 = 0, 60 61 // Tick Intro Animation Sequences 62 FERRARI_SEQ2 = 1, 63 64 // Initialize In-Game Logic 65 FERRARI_INIT = 2, 66 67 // Tick In-Game Logic 68 FERRARI_LOGIC = 3, 69 70 // Ferrari End Sequence Logic 71 FERRARI_END_SEQ = 4, 72 }; 73 74 // Which routine is in use 75 uint8_t state; 76 77 // Unused counter. Implemented on original game so could be useful for debug. 78 uint16_t counter; 79 80 int16_t steering_old; 81 bool car_ctrl_active; 82 83 // Car State 84 // 85 // -1 = Animation Sequence (Crash / Drive In) 86 // 0 = Normal 87 // 1 = Smoke from wheels 88 int8_t car_state; 89 90 enum { CAR_ANIM_SEQ = -1, CAR_NORMAL = 0, CAR_SMOKE = 1}; 91 92 // Auto breaking for end sequence 93 bool auto_brake; 94 95 // Torque table index lookup 96 // 97 // 00 = Start line only 98 // 10 = Low gear 99 // 1F = High gear 100 // 101 // Increments between the values 102 // 103 // Gets set based on what gear we're in 104 uint8_t torque_index; 105 int16_t torque; 106 int32_t revs; 107 108 // Rev Shift Value. Normal = 1. 109 // Higher values result in reaching higher revs faster! 110 uint8_t rev_shift; 111 112 // State of car wheels 113 // 114 // 0 = On Road 115 // 1 = Left Wheel Off-Road 116 // 2 = Right Wheel Off-Road 117 // 3 = Both Wheels Off-Road 118 uint8_t wheel_state; 119 120 enum 121 { 122 WHEELS_ON = 0, 123 WHEELS_LEFT_OFF = 1, 124 WHEELS_RIGHT_OFF = 2, 125 WHEELS_OFF = 3 126 }; 127 128 // Wheel Traction 129 // 130 // 0 = Both Wheels Have Traction 131 // 1 = One Wheel Has Traction 132 // 2 = No Wheels Have Traction 133 uint8_t wheel_traction; 134 135 enum 136 { 137 TRACTION_ON = 0, 138 TRACTION_HALF = 1, 139 TRACTION_OFF = 2, 140 }; 141 142 // Ferrari is slipping/skidding either after collision or round bend 143 uint16_t is_slipping; 144 145 // Slip Command Sent To Sound Hardware 146 uint8_t slip_sound; 147 148 // Stores previous value of car_increment 149 uint16_t car_inc_old; 150 151 // Difference between car_x_pos and car_x_old 152 int16_t car_x_diff; 153 154 // ------------------------------------------------------------------------- 155 // Engine Stop Flag 156 // ------------------------------------------------------------------------- 157 158 // Flag set when switching back to in-game engine, to be used with revs_post_stop 159 // This is used to adjust the rev boost when returning to game 160 int16_t rev_stop_flag; 161 162 // Rev boost when we switch back to ingame engine and hand user control. 163 // Set by user being on revs before initialization. 164 int16_t revs_post_stop; 165 166 int16_t acc_post_stop; 167 168 // ------------------------------------------------------------------------- 169 // Engine Sounds. Probably needs to be moved 170 // ------------------------------------------------------------------------- 171 172 // Sound: Adjusted rev value (to be used to set pitch sound fx) 173 uint16_t rev_pitch1; 174 175 uint16_t rev_pitch2; 176 177 // ------------------------------------------------------------------------- 178 // Ferrari Specific Values 179 // ------------------------------------------------------------------------- 180 181 // *22 [Word] AI Curve Counter. Increments During Curve. Resets On Straight. 182 int16_t sprite_ai_counter; 183 184 // *24 [Word] AI Curve Value. 0x96 - curve_next. 185 int16_t sprite_ai_curve; 186 187 // *26 [Word] AI X Position Adjustment 188 int16_t sprite_ai_x; 189 190 // *28 [Word] AI Steering Adjustment 191 int16_t sprite_ai_steer; 192 193 // *2A [Word] Car X Position Backup 194 int16_t sprite_car_x_bak; 195 196 // *2C [Word] Wheel State 197 int16_t sprite_wheel_state; 198 199 // *2E [Word] Ferrari Slipping (Copy of slip counter) 200 int16_t sprite_slip_copy; 201 202 // *39 [Byte] Wheel Palette Offset 203 int8_t wheel_pal; 204 205 // *3A [Word] Passenger Y Offset 206 int16_t sprite_pass_y; 207 208 // *3C [Word] Wheel Frame Counter Reset 209 int16_t wheel_frame_reset; 210 211 // *3E [Word] Wheel Frame Counter Reset 212 int16_t wheel_counter; 213 214 215 OFerrari(void); 216 ~OFerrari(void); 217 void init(oentry*, oentry*, oentry*, oentry*); 218 void reset_car(); 219 void init_ingame(); 220 void tick(); 221 void set_ferrari_x(); 222 void set_ferrari_bounds(); 223 void check_wheels(); 224 void set_curve_adjust(); 225 void draw_shadow(); 226 void move(); 227 void do_sound_score_slip(); 228 void shake(); 229 void do_skid(); 230 231 private: 232 // Max speed of car 233 const static uint32_t MAX_SPEED = 0x1260000; 234 235 // Car Base Increment, For Movement 236 const static uint32_t CAR_BASE_INC = 0x12F; 237 238 // Maximum distance to allow car to stray from road 239 const static uint16_t OFFROAD_BOUNDS = 0x1F4; 240 241 // Used by set_car_x 242 int16_t road_width_old; 243 244 // ------------------------------------------------------------------------- 245 // Controls 246 // ------------------------------------------------------------------------- 247 248 int16_t accel_value; 249 int16_t accel_value_bak; 250 int16_t brake_value; 251 bool gear_value; 252 bool gear_bak; 253 254 // Trickle down adjusted acceleration values 255 int16_t acc_adjust1; 256 int16_t acc_adjust2; 257 int16_t acc_adjust3; 258 259 // Trickle down brake values 260 int16_t brake_adjust1; 261 int16_t brake_adjust2; 262 int16_t brake_adjust3; 263 264 // Calculated brake value to subtract from acc_burst. 265 int32_t brake_subtract; 266 267 // Counter. When enabled, acceleration disabled 268 int8_t gear_counter; 269 270 // Previous rev adjustment (stored) 271 int32_t rev_adjust; 272 273 // ------------------------------------------------------------------------- 274 // Smoke 275 // ------------------------------------------------------------------------- 276 277 // Counter for smoke after changing gear. Values over 0 result in smoke 278 int16_t gear_smoke; 279 280 // Similar to above 281 int16_t gfx_smoke; 282 283 // Set to -1 when car sharply corners and player is steering into direction of corner 284 int8_t cornering; 285 int8_t cornering_old; 286 287 static uint16_t torque_lookup[]; 288 static const uint8_t rev_inc_lookup[]; 289 290 void logic(); 291 void ferrari_normal(); 292 void setup_ferrari_sprite(); 293 void setup_ferrari_bonus_sprite(); 294 void init_end_seq(); 295 void do_end_seq(); 296 void tick_engine_disabled(int32_t&); 297 void set_ferrari_palette(); 298 void set_passenger_sprite(oentry*); 299 void set_passenger_frame(oentry*); 300 void car_acc_brake(); 301 void do_gear_torque(int16_t&); 302 void do_gear_low(int16_t&); 303 void do_gear_high(int16_t&); 304 int32_t tick_gear_change(int16_t); 305 int32_t get_speed_inc_value(uint16_t, uint32_t); 306 int32_t get_speed_dec_value(uint16_t); 307 void set_brake_subtract(); 308 void finalise_revs(int32_t&, int32_t); 309 void convert_revs_speed(int32_t, int32_t&); 310 void update_road_pos(); 311 int32_t tick_smoke(); 312 void set_wheels(uint8_t); 313 inline void draw_sprite(oentry*); 314 }; 315 316 extern OFerrari oferrari;