Prev: 8A36 Up: Map Next: 8C3A
8A57: Handle perp caught
This handles slowing cars down to a stop when the perp has been caught. It also calculates and displays the bonus score.
handle_perp_caught 8A57 LD A,($A230) Return if perp_caught_phase is zero
8A5A AND A
8A5B RET Z
8A5C DEC A Jump to hpc_move_perp if it's currently one
8A5D JP Z,hpc_move_perp
8A60 DEC A Jump to hpc_phase2 if it's currently two
8A61 JR Z,hpc_phase2
8A63 DEC A Jump to hpc_phase3 if it's currently three
8A64 JR Z,hpc_phase3
8A66 DEC A Jump to hpc_phase4 if it's currently four
8A67 JR Z,hpc_phase4
Otherwise it's five or six.
8A69 EX AF,AF' Bank
8A6A LD A,($A231) Return if transition_control != 0
8A6D AND A
8A6E RET NZ
8A6F EX AF,AF' Unbank
8A70 DEC A Jump to hpc_phase5 if perp_caught_phase is currently five
8A71 JR Z,hpc_phase5
Otherwise all of the perp caught phases are complete and we can move on to the next stage.
8A73 POP HL Throw away the return address. This causes the remainder of main_loop to be bypassed
8A74 CALL silence_audio_hook Call silence_audio_hook
8A77 LD HL,$8007 Increment wanted_stage_number
8A7A INC (HL)
8A7B JP main_loop Exit via main_loop
hpc_phase5 8A7E LD A,$06 perp_caught_phase = 6
8A80 LD ($A230),A
8A83 LD A,$08 Forward transition
8A85 JP setup_transition Exit via setup_transition
This phase moves the car upwards and makes it pull to the left so that it appears to pull in in front of the perp's car.
hpc_phase2 8A88 LD A,($A22A) Fetch car_y
8A8B CP $10 Jump to hpc_start_phase_3 if car_y >= 16
8A8D JR NC,hpc_start_phase_3
Move the car up and left.
8A8F ADD A,$04 car_y += 4
8A91 LD ($A22A),A
8A94 LD HL,($A26C) HL = road_pos + 12 -- move the car left by 12
8A97 LD DE,$000C
8A9A ADD HL,DE
8A9B PUSH HL Preserve HL
8A9C LD DE,$0126 HL -= $126 -- are we at $126 yet?
8A9F SBC HL,DE
8AA1 POP HL Restore HL
8AA2 JR C,hpc_set_road_pos Jump to hpc_set_road_pos if HL < $126
Otherwise the car's in the correct position now.
8AA4 EX DE,HL Move $126 in DE to HL
hpc_set_road_pos 8AA5 LD ($A26C),HL road_pos = HL
Not sure why we're changing fast_counter here.
8AA8 LD A,($A23F) A = fast_counter + 32
8AAB ADD A,$20
8AAD RET C Return if result > 255
8AAE LD ($A23F),A fast_counter = A
8AB1 RET Return
hpc_start_phase_3 8AB2 LD A,$03 perp_caught_phase = 3
8AB4 LD ($A230),A
8AB7 INC A Self modify the 'LD A,x' at hpc_phase3 below to load 4
8AB8 LD ($8ABF),A
8ABB JP fill_attributes Exit via fill_attributes
hpc_phase3 8ABE LD A,$00 Self modified by 8AB8 above -- meaning?
8AC0 DEC A A--
8AC1 LD ($8ABF),A Self modify 'LD A' at hpc_phase3 to load A
8AC4 RET NZ Return if A != 0
8AC5 LD A,$04 perp_caught_phase = 4
8AC7 LD ($A230),A
8ACA LD HL,($5D06) Point HL at addrof_arrest_messages
8ACD LD A,$01 Set transition_control to 1 (draw mugshots)
8ACF JP setup_overlay_messages_with_A Exit via setup_overlay_messages_with_A
hpc_phase4 8AD2 LD A,($A139) Call relocated handle_perp_caught_128k if in 128K mode
8AD5 AND A
8AD6 CALL NZ,$8193
8AD9 LD A,($A231) Return if transition_control != 0
8ADC AND A
8ADD RET NZ
8ADE LD A,($A139) Call relocated handle_perp_caught_128k if in 128K mode
8AE1 AND A
8AE2 CALL NZ,$8193
8AE5 LD A,$05 perp_caught_phase = 5
8AE7 LD ($A230),A
Calculate level clear bonus (<stage number> * 100,000 points for the first try, 10,000 on retries).
8AEA LD H,$30 '0' (second digit)
8AEC LD A,($8007) D = wanted_stage_number
8AEF LD D,A
8AF0 ADD A,H L = wanted_stage_number + '0'
8AF1 LD L,A
Completing the level on the first try awards <stage number> * 100,000 points.
8AF2 LD A,($8006) Jump to hpc_set_score if retry_count is zero
8AF5 AND A
8AF6 JR Z,hpc_set_score
Divide bonus by 10 if stage was retried.
8AF8 RLC D Neutralise the upcoming shift so bonus is divided by 10
8AFA RLC D
8AFC RLC D
8AFE RLC D
8B00 LD H,L H = L -- becomes second ASCII digit
8B01 LD L,$20 L = ' ' -- first ASCII digit replaced with space
hpc_set_score 8B03 LD ($8C6F),HL Set first two digits of the clear bonus to HL, "LH0,000"
Set score increment to (<stage number> * 100,000).
8B06 RLC D Move wanted_stage_number to first digit
8B08 RLC D
8B0A RLC D
8B0C RLC D
8B0E XOR A Zero other digits
8B0F LD E,A
8B10 CALL increment_score Call increment_score (with D,E,A)
Calculate time remaining bonus.
8B13 LD A,($A17E) Get time remaining (BCD)
8B16 LD ($8C8A),A Set A in "TIME BONUS Ax X 5000" as a temporary location
8B19 LD C,A Copy time remaining (BCD)
8B1A RLCA Extract high digit
8B1B RLCA
8B1C RLCA
8B1D RLCA
8B1E AND $0F
8B20 JR NZ,hpc_have_high_digit Jump if it's non-zero
Otherwise write out a space character.
hpc_no_high_digit 8B22 LD A,$20 Put a space character in A'
8B24 EX AF,AF'
8B25 JR hpc_store_time_bonus_high Jump to store
hpc_have_high_digit 8B27 LD B,A Multiplier (high digit)
8B28 ADD A,$30 Make it ASCII
8B2A EX AF,AF' Bank it
8B2B LD DE,$0500 DE = $0500 (this is 50,000 here because we're doing the tens)
hpc_increment_score_loop_1 8B2E XOR A Clear A since increment_score will corrupt it
8B2F CALL increment_score Call increment_score (with D,E,A)
8B32 DJNZ hpc_increment_score_loop_1 Loop while B > 0
hpc_store_time_bonus_high 8B34 EX AF,AF' Unbank ASCII of high digit
8B35 LD ($8C8A),A Store as x in "TIME BONUS xy X 5000"
8B38 LD A,C Copy time remaining (BCD)
8B39 AND $0F Extract low digit
8B3B JR Z,hpc_store_time_bonus_low Jump if zero
Bug: This banks the low digit in A which the LD B,A then expects to be able to use. To fix this transpose the next two instructions. (Credit: Russell Marks)
hpc_have_low_digit 8B3D EX AF,AF' Bank low digit
8B3E LD B,A Multiplier (should be low digit but bugged)
8B3F LD DE,$0050 DE = $0050 (this is 5,000 here because we're doing the ones)
hpc_increment_score_loop_2 8B42 XOR A Clear A since increment_score will corrupt it
8B43 CALL increment_score Call increment_score (with D,E,A)
8B46 DJNZ hpc_increment_score_loop_2 Loop while B > 0
hpc_store_time_bonus_low 8B48 EX AF,AF' Unbank low digit
8B49 ADD A,$30 Make it ASCII
8B4B LD ($8C8B),A Store as y in "TIME BONUS xy X 5000"
Display score.
8B4E LD BC,$0400 Iterations = 4; Clear C flag byte (set if seen a digit?)
8B51 LD DE,$8005 Point DE at last digit of score_bcd (big end)
8B54 LD HL,$8CA8 Point HL at x in "SCORE x " - the ten millions?
hpc_score_loop 8B57 LD A,(DE) Fetch a pair of digits from score_bcd
8B58 RLCA Extract the high digit
8B59 RLCA
8B5A RLCA
8B5B RLCA
8B5C AND $0F
8B5E JR NZ,hpc_score_have_high_digit Jump if it's non-zero
hpc_score_zero_high_digit 8B60 RLC C Seen a digit yet?
8B62 JR C,hpc_score_have_high_digit Jump if so
8B64 LD A,$20 Space
8B66 JR hpc_score_store_high Jump to store
hpc_score_have_high_digit 8B68 LD C,$FF Set "saw a digit" flag
8B6A ADD A,$30 Make it ASCII
hpc_score_store_high 8B6C LD (HL),A Store ASCII high digit
8B6D INC HL
8B6E LD A,(DE) Extract the low digit
8B6F AND $0F
8B71 JR NZ,hpc_score_have_low_digit Jump if it's non-zero
hpc_score_zero_low_digit 8B73 RLC C Seen a digit yet?
8B75 JR C,hpc_score_have_low_digit Jump if so
8B77 LD A,$20 Space
8B79 JR hpc_score_store_low Jump to store
hpc_score_have_low_digit 8B7B LD C,$FF Set "saw a digit" flag
8B7D ADD A,$30 Make it ASCII
hpc_score_store_low 8B7F LD (HL),A Store ASCII low digit
8B80 INC HL
8B81 DEC DE Advance (backwards) to next digits of score_bcd
8B82 DJNZ hpc_score_loop Loop hpc_score_loop while B > 0
8B84 DEC HL Terminate the string
8B85 SET 7,(HL)
8B87 LD HL,$8C58 Point at "CLEAR BONUS ..." "TIME BONUS ..." "SCORE ..." messages
8B8A JP setup_overlay_messages Call setup_overlay_messages
This is phase 1 of the caught process. Set the perp's horizontal position.
hpc_move_perp 8B8D LD A,($A18D) Load the perp car's horizontal position (as byte)
8B90 LD C,$23 Compare it to 35 (left hand side of road)
8B92 CP C
8B93 LD B,$05 Change by 5
8B95 JR Z,hpc_assign_perp_pos Jump if no change required
8B97 JR C,hpc_change_perp_pos Jump to increase by 5 if pos < 35
8B99 LD B,$FB Otherwise decrease by 5
hpc_change_perp_pos 8B9B ADD A,B new pos = old pos + delta
8B9C LD C,A
hpc_assign_perp_pos 8B9D LD A,C Set the perp car's horizontal position (as byte)
8B9E LD ($A18D),A
Now move the hero car. This section is similar to code in cpu_driver.
8BA1 LD HL,($A26C) Get road position
If we're on the left, go right.
8BA4 PUSH HL Subtract centre-left edge. Carry flag will be set if we're on the right hand side of it
8BA5 LD DE,$0105
8BA8 SBC HL,DE
8BAA POP HL
8BAB LD A,$09 Set input ACCELERATE + RIGHT
8BAD JR NC,hpc_assign_hero_pos Jump to hpc_assign_hero_pos if we're on the left
If we're on the right, go left.
8BAF LD DE,$00F5 Subtract centre-right edge. Carry flag will be set if we're on the right hand side of it
8BB2 SBC HL,DE
8BB4 LD A,$0A Set input ACCELERATE + LEFT
8BB6 JR C,hpc_assign_hero_pos Jump to hpc_assign_hero_pos if we're on the right
Otherwise we're in the centre zone.
8BB8 LD A,$08 Set input ACCELERATE
hpc_assign_hero_pos 8BBA LD C,A Move input into C for the moment
8BBB AND $03 Mask off LEFT and RIGHT flags
8BBD JR NZ,hpc_perp_too_far_away Jump to hpc_perp_too_far_away if either is set
Not turning. Are we within distance?
hpc_check_distance 8BBF LD A,($A189) Load perp's distance (low byte)
8BC2 CP $03 Jump if distance >= 3
8BC4 JR NC,hpc_perp_too_far_away
Count down while we're within distance of the perp.
8BC6 LD HL,$A173 Decrement perp_halt_counter
8BC9 DEC (HL)
8BCA JR NZ,hpc_perp_too_far_away Jump if countdown is non-zero
Countdown hit zero: stop.
8BCC XOR A speed = 0
8BCD LD D,A
8BCE LD E,A
8BCF LD ($A24A),DE
8BD3 LD ($A18C),A *$A18C = 0 -- distance related? [reset by set_up_stage]
8BD6 INC A Set perp's distance to 1
8BD7 LD ($A189),A
8BDA INC A Set perp_caught_phase to 2
8BDB LD ($A230),A
8BDE INC A Set smoke to 3
8BDF LD ($A24F),A
8BE2 JP hpc_set_perp_pos_or_accel Jump to hpc_set_perp_pos_or_accel (with DE = 0)
HL = 350 - (16 - <distance related>) * 20 -- compared to speed later Arrive here if we're turning or the perp is too far away.
hpc_perp_too_far_away 8BE5 LD A,($A189) Load perp's distance
8BE8 LD HL,$015E HL = 350 -- compared to speed later
8BEB CP $0F Jump if distance >= 15
8BED JR NC,hpc_perp_far
8BEF CPL A = 16 - distance
8BF0 ADD A,$0F
Calculate 350 - A * 20.
8BF2 LD DE,$0014 DE = 20
8BF5 LD B,A B = A -- iterations
hpc_subtract_loop 8BF6 SBC HL,DE HL -= DE
8BF8 DJNZ hpc_subtract_loop Loop while B > 0
hpc_perp_far 8BFA EX DE,HL Put result in DE
8BFB LD HL,($A24A) Load speed
8BFE PUSH HL Preserve speed
8BFF SBC HL,DE Jump if speed < DE -- DE is e.g. 350
8C01 JR C,hpc_set_gear
Slow down to match the perp. C is a user input here.
8C03 RES 3,C Clear input ACCELERATE
8C05 LD DE,$0032 Jump if HL < 50
8C08 SBC HL,DE
8C0A JR C,hpc_set_gear
8C0C SET 2,C Set input BRAKE
hpc_set_gear 8C0E POP HL Restore speed
8C0F LD DE,$0096 Calculate speed - 150
8C12 SBC HL,DE
8C14 LD A,($A253) Load gear
8C17 SBC A,$00 Set gear to low if speed < 150, otherwise high
8C19 JR NZ,hpc_assign_user_input
8C1B SET 4,C Set input GEAR
hpc_assign_user_input 8C1D LD A,C Set user input
8C1E LD ($A0D5),A
hpc_check_perp_accel 8C21 LD HL,($A195) Load the (accel?) of the perp's car into HL
8C24 PUSH HL Compare it to 70
8C25 LD DE,$0046
8C28 SBC HL,DE
8C2A POP HL
8C2B JR Z,hpc_set_perp_pos_or_accel Jump to hpc_set_perp_pos_or_accel if result <= 70, with DE = 70
8C2D JR C,hpc_set_perp_pos_or_accel
8C2F LD DE,$0005 Otherwise reduce it by 5 with result in DE
8C32 SBC HL,DE
8C34 EX DE,HL
This entry point is used by the routine at fully_smashed.
hpc_set_perp_pos_or_accel 8C35 LD ($A195),DE Set the horizontal position (or accel?) of the perp's car to DE -- and it's writing A196 too is that the high byte?
8C39 RET Return
Prev: 8A36 Up: Map Next: 8C3A