Prev: B059 Up: Map Next: B318
B063: Hero car jumps; gear changing; turbos; off road checks; speed adjustment; turning
Used by the routines at main_loop and cpu_driver.
move_hero_car B063 LD A,$00 Load jump counter. Self modified by 8827 and B965. Highest is 8.
B065 AND A Jump to mhc_not_jumping if the jump counter is zero
B066 JR Z,mhc_set_jump_offset
Hero car is jumping.
mhc_jumping B068 DEC A Decrement the jump counter in (self modified) move_hero_car
B069 LD ($B064),A
B06C JR NZ,mhc_midair Jump to mhc_midair if we're still jumping
Hero car has landed.
mhc_landed B06E LD A,$03 smoke = 3
B070 LD ($A24F),A
B073 LD BC,$0203 Effect 2 (car landing), Priority 3
B076 CALL start_sfx Call start_sfx
Hero car is in mid-air, or has just landed.
mhc_midair B079 LD HL,$0000 Point HL at entry in jump table. Self modified by B96C and B092. Default is $B055.
B07C XOR A off_road = 0
B07D LD ($A23E),A }
B080 LD A,($A0D5) Clear up/down/left/right bits of user input (stop the player from turning when in mid-air)
B083 AND $F0
B085 LD ($A0D5),A
The low bytes of the hero_car_jump_table entries are the car's pitch (0/3/6).
B088 LD A,(HL) Self modify the 'ADD A,x' at #$B5AF to load the car's pitch
B089 LD ($B5B0),A
B08C INC HL
The high bytes of the entries are the car's jump offset (-13..13).
B08D LD A,($B5AB) A = *$B5AB + *HL++ -- Self modified value in draw_car
B090 ADD A,(HL)
B091 INC HL
B092 LD ($B07A),HL Update HL jump table entry address above @ mhc_midair
mhc_set_jump_offset B095 LD ($B5AB),A Self modify 'SUB x' @ B5AA to be the new car jump offset
B098 LD HL,$A24E Address of boost timer
B09B LD A,(HL) Jump to mhc_smoke if a turbo boost is not in effect
B09C AND A
B09D JR Z,mhc_smoke
B09F DEC (HL) Decrement boost timer
B0A0 JR NZ,mhc_smoke Jump to mhc_smoke if boost timer is non-zero
B0A2 LD A,($A170) Decrement turbo boost count [POKE $B0A5,0 for Infinite turbos]
B0A5 DEC A
B0A6 LD ($A170),A
Handle smoke effect.
mhc_smoke B0A9 INC HL HL now points at smoke
B0AA LD A,(HL) Jump if smoke is zero
B0AB AND A
B0AC JR Z,mhc_gear_change
B0AE DEC (HL) Decrement smoke
Handle gear changes.
mhc_gear_change B0AF LD A,($A0D5) Read user input
B0B2 LD C,A Preserve it in C
B0B3 LD A,($B326) Read from the 'LD A,x' @ ahc_check_crashed (crashed flag)
B0B6 AND A Jump if zero
B0B7 JR Z,mhc_b0bd
Otherwise the crashed flag is set.
B0B9 LD A,C Change user input to be ONLY the fire/gear flag (if set)
B0BA AND $10
B0BC LD C,A
mhc_b0bd B0BD LD A,C A = C
B0BE PUSH AF Preserve the modified user input for later
B0BF BIT 4,A Test fire/gear flag
B0C1 LD HL,$A253 Address of gear flag
B0C4 LD A,($A252) Load gear_lockout
B0C7 JR Z,mhc_b0d7 Jump if fire/gear is unset
Fire/gear was set.
B0C9 AND A Jump if gear_lockout is set -- lock out gear changes while set
B0CA JR NZ,mhc_b0d7
B0CC LD A,(HL) Toggle gear flag
B0CD XOR $01
B0CF LD (HL),A
B0D0 LD A,$04 Smoke time remaining
B0D2 JR Z,mhc_b0d7 Jump if low gear
B0D4 LD ($A24F),A Set smoke counter
mhc_b0d7 B0D7 SUB $01 Decrement A [why write it as a SUB 1?]
B0D9 JR C,mhc_b0de Jump if positive result
B0DB LD ($A252),A gear_lockout = A
mhc_b0de B0DE LD A,(HL) Read current gear flag
B0DF EX AF,AF' Bank it
B0E0 LD HL,($A24A) Read current speed
B0E3 PUSH HL Stack current speed
B0E4 LD DE,$0078 Jump if speed >= 120
B0E7 SBC HL,DE
B0E9 JR NC,mhc_done_idle
Going slowly here (<120).
mhc_going_slow B0EB LD A,($A230) Jump if perp_caught_phase > 0 -- Don't do idle handling if we're slowing while catching the perp
B0EE AND A
B0EF JR NZ,mhc_done_idle
Handle idle timer.
mhc_idle_timer B0F1 LD HL,$A16E Address of idle timer
B0F4 DEC (HL) Decrement idle timer
B0F5 JR NZ,mhc_done_idle Jump if non-zero
mhc_reset_idle_timer B0F7 LD (HL),$64 Reset idle timer to 100
B0F9 LD A,$0A Set priority to 10
B0FB LD HL,$98F8 Point HL at get_moving_chatter (Raymond: "LET'S GET MOVIN' MAN!")
B0FE CALL start_chatter Call start_chatter (priority 10)
mhc_done_idle B101 POP HL Pop current speed
B102 LD D,H Save current speed in DE for later
B103 LD E,L
B104 LD A,($A23E) Load the off-road flag
B107 AND A Jump if zero (fully on-road)
B108 JR Z,mhc_done_offroad
Handle off-road (A can be 1 or 2 here).
mhc_offroad B10A LD BC,$0078 Set max speed for when one wheel off-road (120 => ~100?)
B10D DEC A Jump if off-road was one
B10E JR Z,mhc_chose_offroad_speed
B110 LD BC,$006E Set max speed for when both wheels off-road (110 => ~90?)
mhc_chose_offroad_speed B113 AND A Clear carry
B114 SBC HL,BC 16-bit subtract only for result in flags
B116 LD H,D Restore current speed saved earlier
B117 LD L,E
B118 JR C,mhc_done_offroad Jump if current speed (HL) < max speed (DE) -- don't reduce speed?
This seems to be reducing the speed by a pseudorandom value when we're off-road. If it's NOPped out then going offroad will cause max speed.
mhc_offroad_reduce_speed B11A LD A,L Current speed low byte
B11B RR H Bottom bit of H moves to carry
B11D RLA A <<= 4 -- 9 bit rotate left through carry
B11E RLA
B11F RLA
B120 RLA
B121 AND $0F A = -((A & $0F) | 1) -- top four bits of speed... at least one
B123 OR $01
B125 NEG
B127 LD C,A BC = $FF00 | A -- speed delta (slowing)
B128 LD B,$FF
B12A JP mhc_check_brake Jump to mhc_check_brake
mhc_done_offroad B12D LD A,($A24E) Load turbo boost time remaining (60..0)
B130 AND A Test
B131 EX AF,AF' Bank with flags
B132 AND A Test previously banked copy of gear flag
B133 JR NZ,mhc_high_gear Jump if in high gear
mhc_low_gear B135 LD BC,$01D6 BC = 470 -- max speed?
B138 EX AF,AF' Unbank turbo boost with flags
B139 JR NZ,mhc_low_gear_slowing Jump if turbo boost in effect -- Uses banked flags
No turbo boost.
B13B LD BC,$00E6 BC = 230 -- max speed?
mhc_low_gear_slowing B13E SBC HL,BC HL -= BC
B140 JP NC,mhc_low_gear_accelerating Jump if HL was >= BC -- speed > limit value
B143 LD A,L BC = ~HL + 1 = -HL
B144 CPL
B145 LD C,A
B146 LD A,H
B147 CPL
B148 LD B,A
B149 INC BC
B14A LD A,C A = C
B14B SRL B Shift a bit out of B into A?
B14D RRA
B14E SRL B and again -- B must now be zero
B150 RRA
B151 RRA Then divide by 4?
B152 RRA
B153 AND $3F C = (A & $3F) | 1
B155 OR $01
B157 LD C,A
B158 JR mhc_check_brake Jump to mhc_check_brake
mhc_low_gear_accelerating B15A LD A,L A = L
B15B SRL H A = HL >> 4
B15D RRA
B15E SRL H
B160 RRA
B161 RRA
B162 RRA
B163 AND $1F A = -((A & $1F) | 1)
B165 OR $01
B167 NEG
B169 LD C,A BC = $FF00 | A -- speed delta (slowing)
B16A LD B,$FF
B16C JR mhc_check_brake Jump to mhc_check_brake
mhc_high_gear B16E LD BC,$00DC BC = 220 -- max speed?
B171 SBC HL,BC 16-bit subtract only for result in flags
B173 LD H,D Restore current speed saved earlier
B174 LD L,E
B175 JR NC,mhc_high_gear_accelerating Jump if current speed (HL) < max speed (DE)
mhc_high_gear_slowing B177 LD BC,$01D6 BC = 470 -- max speed?
B17A EX AF,AF' Unbank turbo boost with flags
B17B JR NZ,mhc_low_gear_slowing Jump if turbo boost in effect -- Uses banked flags
mhc_something2 B17D LD A,E A = DE >> 4
B17E LD B,D
B17F SRL B
B181 RRA
B182 SRL B
B184 RRA
B185 RRA
B186 RRA
B187 OR $01 C = (A | 1) & $1F
B189 AND $1F
B18B LD C,A
B18C JR mhc_check_brake Jump to mhc_check_brake
mhc_high_gear_accelerating B18E LD BC,$02B7 BC = 695 -- max speed?
B191 EX AF,AF' Unbank turbo boost with flags
B192 JR NZ,mhc_low_gear_slowing Jump if turbo boost in effect -- Uses banked flags
B194 LD BC,$0168 BC = 360 -- max speed?
B197 JP mhc_low_gear_slowing Use mhc_low_gear_slowing
mhc_check_brake B19A POP AF Get modified user input (stored by B0BE)
B19B PUSH AF
B19C RRA Is BRAKE pressed? (bit 2 / down)
B19D RRA
B19E RRA
B19F JR NC,mhc_not_braking Jump to mhc_not_braking if not pressed
Braking
B1A1 LD BC,$FFEC Speed delta is -20 to slow down
B1A4 JR mhc_calc_speed Jump to mhc_calc_speed
mhc_not_braking B1A6 RRA Is ACCELERATE pressed? (bit 3 / up)
B1A7 JR C,mhc_calc_speed Jump if so {what's in BC? must be the speed delta from earlier}
Not accelerating
B1A9 LD BC,$FFF6 Speed delta is -10 to gradually slow
mhc_calc_speed B1AC LD H,D Copy speed from DE
B1AD LD L,E
B1AE AND A Clear carry
B1AF ADC HL,BC Change speed
B1B1 JP P,mhc_speed_set Jump if still positive or zero
Cope with speed going negative
B1B4 LD HL,$0000 HL = $0000
HL = new speed
mhc_speed_set B1B7 LD A,($A24C) A = inclined - 1 (hasn't used DEC A here... possibly left for tweaking)
B1BA SUB $01
B1BC JR NC,mhc_set_inclined Jump if A is now >= 0
"inclined" counter went -ve
B1BE LD A,($B5B0) A = $B5B0 -- read self modified value in draw_car that sets the car's pitch (0/3/6)
B1C1 AND A Jump if zero (pitch is level)
B1C2 JR Z,mhc_set_inclined
B1C4 LD C,A C = A -- temp save A
B1C5 LD A,H Jump if HL (new speed) is zero
B1C6 OR L
B1C7 JR Z,mhc_set_inclined
new speed is non-zero
B1C9 LD A,C BC = (C - 5) | 1 -- 0/3/6 in C => -5/-1/1 in BC
B1CA SUB $05
B1CC OR $01
B1CE LD C,A
B1CF LD B,$00
B1D1 JP P,mhc_positive Jump if result is positive
B1D4 DEC B BC = $FF00 | A -- otherwise widen as negative
mhc_positive B1D5 LD D,H Copy speed from HL to DE
B1D6 LD E,L
B1D7 ADD HL,BC Increment speed ... by a value computed from car's pitch ... eh?
B1D8 LD BC,$02B7 Speed threshold 695
B1DB PUSH HL Save it
B1DC SBC HL,BC Reduce speed by threshold
B1DE POP HL Restore it
B1DF JR C,mhc_b1e2 Jump if speed < 695 -- surely always the case?!
B1E1 EX DE,HL
mhc_b1e2 B1E2 LD A,$03 A = 3 -- reset A24C to 3
mhc_set_inclined B1E4 LD ($A24C),A inclined = A
B1E7 LD A,H A = H
B1E8 CP $02 CP 2
B1EA JR C,mhc_b1ef
B1EC LD HL,$01FF Cap speed to $1FF
mhc_b1ef B1EF LD ($A24A),HL Set speed to HL
B1F2 POP HL Restore HL [likely to be the user input?]
B1F3 LD A,($A263) B = right_turn
B1F6 LD B,A
B1F7 LD A,($A264) C = left_turn
B1FA LD C,A
B1FB LD A,($B064) A = *$B064 -- Jump counter [self modified]
B1FE AND A Jump to mhc_b253 if non-zero
B1FF JP NZ,mhc_b253
Is this checking input flags in H?
B202 RR H Shift LSB out of H
B204 JR C,mhc_b21a Jump to mhc_b21a if set
B206 RR H Shift new LSB out of H
B208 JR C,mhc_b22c Jump to mhc_b22c if set
Reduce left turning force A = ((C >= 9) ? C - 9 : 0) = MAX(C - 9, 0) This instr is hit continuously
B20A LD A,C A = C - 9 -- left turning force from earlier
B20B SUB $09
B20D JR NC,mhc_store_left_turning_force Jump if C >= 9
B20F XOR A A = 0 -- clamp
mhc_store_left_turning_force B210 LD C,A C = A
Reduce right turning force A = ((B >= 9) ? B - 9 : 0) = MAX(B - 9, 0)
B211 LD A,B A = B - 9 -- right turning force from earlier
B212 SUB $09
B214 JR NC,mhc_store_right_turning_force Jump to mhc_b217 if B >= 9
B216 XOR A A = 0 -- clamp
mhc_store_right_turning_force B217 LD B,A B = A
B218 JR mhc_handle_speed Jump to mhc_handle_speed
B = ((B + 4 >= 36) ? 36 : B + 4) = MIN(36, B + 4) -- 36 is the max turning force
mhc_b21a B21A LD A,B A = B + 4
B21B ADD A,$04
B21D LD B,$24 Jump if A >= 36
B21F CP B
B220 JR NC,mhc_b223
B222 LD B,A B = A
C = ((C >= B) ? C - B : 0) = MAX(C - B, 0)
mhc_b223 B223 LD A,C C -= B
B224 SUB B
B225 LD C,A
B226 JR NC,mhc_handle_speed Jump to mhc_handle_speed if C >= B
B228 LD C,$00 C = 0
B22A JR mhc_handle_speed Jump to mhc_handle_speed
C = ((C + 4 >= 36) ? 36 : C + 4) = MIN(36, C + 4)
mhc_b22c B22C LD A,C A = C + 4
B22D ADD A,$04
B22F LD C,$24 C = 36
B231 CP C Jump to mhc_b235 if A >= 36
B232 JR NC,mhc_b235
B234 LD C,A C = A
B = ((B >= C) ? B - C : 0) = MAX(B - C, 0)
mhc_b235 B235 LD A,B B -= C
B236 SUB C
B237 LD B,A
B238 JR NC,mhc_handle_speed Jump to mhc_handle_speed if B >= C
B23A LD B,$00 B = 0
mhc_handle_speed B23C LD HL,($A24A) Load speed into HL
B23F LD A,L Speed low byte
B240 RR H Bottom bit of H moves to carry (H now unused)
B242 RRA Halve speed, shifting carry in as MSB
Divide by 2.666 but not quite right?
B243 SRL A A >>= 2
B245 SRL A
B247 LD L,A L = A
B248 SRL L L >>= 1
B24A ADD A,L A += L
B24B CP B Jump if A >= B
B24C JR NC,mhc_b24f
B24E LD B,A B = A
mhc_b24f B24F CP C Jump if A >= C
B250 JR NC,mhc_b253
B252 LD C,A C = A
mhc_b253 B253 PUSH BC Store turning forces for later mhc_reset_turning_forces
B254 LD BC,$0000 BC = $0000
B257 LD E,B E = B, i.e. zero
B258 LD A,($A25C) Load current_curvature
B25B OR A Set flags
B25C JP Z,mhc_straight_road Jump to mhc_straight_road if zero
B25F JP P,mhc_scroll_horizon Jump to mhc_scroll_horizon if positive
Negative scroll => scroll horizon right.
mhc_scroll_right B262 INC E E++ -- i.e. 1
B263 NEG A = -A
Positive scroll => scroll horizon left.
mhc_scroll_horizon B265 LD HL,$B827 16 word horizon table at horizon_table
B268 LD C,A BC = A -- B is zero at this point
B269 ADD HL,BC HL += BC
B26A LD A,($A261) A = var_a261
B26D LD C,A C = A
B26E EX AF,AF'
B26F LD A,($A23F) A = fast_counter - C
B272 SUB C
B273 AND A Set flags
B274 JR Z,mhc_straight_road Jump if zero
B276 LD C,(HL) C = *HL
mhc_b277 B277 SUB C A -= C
B278 JR C,mhc_b280 Jump if carry
B27A INC B B++
B27B EX AF,AF'
B27C ADD A,C A += C
B27D EX AF,AF'
B27E JR mhc_b277 Jump to mhc_b277 (above) -- loop?
mhc_b280 B280 LD A,B A = B
B281 AND A Jump to mhc_b295 if A is zero
B282 JR Z,mhc_b295
B284 LD HL,$A262 HL = var_a262
B287 ADD A,(HL) A += *HL
B288 LD (HL),A *HL = A
B289 LD A,B A = B * 3
B28A ADD A,A
B28B ADD A,B
B28C LD B,$00 B = 0
B28E RR E Bottom bit of E moves to carry
B290 JR NC,mhc_b295 Jump if clear
B292 DEC B B--
B293 NEG A = -A
mhc_b295 B295 LD C,A C = A
B296 EX AF,AF'
B297 LD ($A261),A var_a261 = A
No curvature - No scroll required?
mhc_straight_road B29A LD HL,($A25F) HL = horizontal_adjust + BC
B29D ADD HL,BC
B29E LD DE,$0000 horizontal_adjust = 0
B2A1 LD ($A25F),DE
B2A5 LD A,($B326) A = *$B326 -- Read self modified op in animate_hero_car -- crashed flag
B2A8 AND A Set flags
B2A9 JR Z,mhc_reset_turning_forces Jump to mhc_b2ad if zero
B2AB EX DE,HL DE <> HL
B2AC LD D,H D = H [must be a delta]
mhc_reset_turning_forces B2AD POP BC Restore turning forces
B2AE LD A,B right_turn = B
B2AF LD ($A263),A
B2B2 LD A,C left_turn = C
B2B3 LD ($A264),A
B2B6 SUB B A -= B
B2B7 JP P,mhc_b2bb Jump to mhc_b2bb if positive
B2BA DEC D Otherwise decrement D
mhc_b2bb B2BB LD E,A E = A >> 1
B2BC SRA E
B2BE ADD HL,DE HL += DE
B2BF OR A Set flags
B2C0 JR Z,mhc_set_cornering Jump to mhc_set_cornering if zero
B2C2 JP P,mhc_check_cornering Jump if positive
B2C5 NEG A = -A
mhc_check_cornering B2C7 CP $11 Compare A to 17
B2C9 LD A,$00 A = 0 -- cornering = 0
B2CB JR C,mhc_set_cornering Jump to mhc_set_cornering if A < 17
B2CD BIT 7,H Jump if H bit 7 clear
B2CF JR Z,mhc_b2db
B2D1 BIT 7,D Jump to mhc_set_cornering if D bit 7 set
B2D3 JR NZ,mhc_set_cornering
B2D5 BIT 7,H Jump to mhc_set_cornering if H bit 7 clear -- bug? already tested above
B2D7 JR Z,mhc_set_cornering
B2D9 JR mhc_is_cornering Jump to mhc_is_cornering
mhc_b2db B2DB BIT 7,D Jump to mhc_set_cornering if D bit 7 clear
B2DD JR Z,mhc_set_cornering
B2DF BIT 7,H Jump to mhc_set_cornering if H bit 7 set
B2E1 JR NZ,mhc_set_cornering
mhc_is_cornering B2E3 LD A,$01 A = 1
mhc_set_cornering B2E5 LD ($A24D),A cornering = A
B2E8 LD BC,($A26C) road_pos += HL [must be a delta]
B2EC ADD HL,BC
B2ED LD ($A26C),HL
B2F0 LD D,$01 D = 1 -- flip flag
B2F2 LD A,E A = E -- E is?
B2F3 OR A Set flags [why are some ORs and some ANDs?]
B2F4 JP P,mhc_decide_turn_speed Jump if positive
B2F7 DEC D D-- -- flip flag -> 0
B2F8 NEG A = -A
mhc_decide_turn_speed B2FA CP $0C Compare A to 12
B2FC LD B,$02 2 => Turn hard
B2FE JR NC,mhc_exit Jump to mhc_exit if A >= 12
B300 DEC B 1 => Turn
B301 CP $06 Compare A to 6
B303 JR NC,mhc_exit Jump to mhc_exit if A >= 6
B305 DEC B 0 => Straight
mhc_exit B306 LD A,B turn_speed = B -- should be 0/1/2
B307 LD ($A250),A
B30A LD A,D flip_car = D -- should be 0/1
B30B LD ($A251),A
B30E LD A,($B064) A = *$B064 -- Jump counter [self modified]
B311 AND A Return if zero
B312 RET Z
B313 XOR A cornering = 0 -- reset cornering if not jumping
B314 LD ($A24D),A
B317 RET Return
Prev: B059 Up: Map Next: B318