| Chase H.Q. | Routines |
| Prev: B8D2 | Up: Map | Next: BB69 |
|
Called once a frame from read_map. It scans up to 20 lane data entries looking for a fork marker, a byte where (byte & $E1) == $E1, and takes one of two paths.
No fork: build the curve table for a straight road, then fill 104 entries each of the centre, centre right and centre left x-position tables by interpolating between the left and right tables that are already populated.
Fork: record which fork the player is taking, start the chatter, advance the spawn accumulator and the fork distance, then build the curve table twice, once per half of the road, moving road_pos temporarily for each. The fork loop runs as many iterations as the height at the fork calls for and the remaining entries are filled by falling into the non-fork path.
|
||||
| layout_road | B9F4 | LD A,($A240) | Load road_buffer_offset.lo into A [as byte] | |
| B9F7 | ADD A,$40 | Add 64 so it's the lanes data offset (wrapping around) | ||
| B9F9 | LD E,A | Point DE at road buffer lanes data | ||
| B9FA | LD D,$EE | |||
|
Count the distance to the forked road.
|
||||
| B9FC | LD BC,$16E1 | B = 22 iterations, C = $E1 (a mask) [forked road is $ED] | ||
| B9FF | LD L,$00 | Counter | ||
| lr_loop1 | BA01 | LD A,(DE) | Load a lanes byte | |
| BA02 | AND C | Jump to lr_forked_road if (lanes byte & $E1) == $E1 | ||
| BA03 | CP C | |||
| BA04 | JP Z,lr_forked_road | |||
| BA07 | INC E | Advance to next lanes byte (wrapping around) | ||
| BA08 | INC L | Increment counter | ||
| BA09 | DJNZ lr_loop1 | Loop while B | ||
|
No forked road found.
The road is still rendered if the following call is nopped out, but it's in the wrong position.
|
||||
| lr_no_fork | BA0B | CALL build_curve_table | Call build_curve_table | |
| BA0E | LD ($BA4E),SP | Self modify 'LD SP' @ lr_exit to restore SP on exit | ||
| BA12 | LD SP,$EC30 | Put $EC30 (road right) in SP (so we can use POP for speed) | ||
| BA15 | LD A,$30 | Iterate from $30 to $00 in steps of 2 = 104 iterations | ||
|
Note that the fork case branches back here.
|
||||
| lr_calc_single_lane | BA17 | LD HL,$BA36 | Self modify BA35 to load $EA30 upwards (road centre) | |
| BA1A | LD DE,$BA40 | Self modify BA3F to load $EB30 upwards (road centre right) | ||
| BA1D | LD BC,$BA45 | Self modify BA44 to load $E930 upwards (road centre left) | ||
| lr_ba20 | BA20 | LD (HL),A | Self modify the locations setup above | |
| BA21 | LD (DE),A | |||
| BA22 | LD (BC),A | |||
| BA23 | LD ($BA29),A | Self modify BA27 (below) to load ($E800 | A) (road left) | ||
| BA26 | EXX | Bank | ||
|
Centre = Left + (Right - Left) / 2
|
||||
| BA27 | LD DE,($E800) | DE = *$E8xx (xx = self modified) (road left) | ||
| BA2B | POP HL | Read from $ECxx | ||
| BA2C | SBC HL,DE | HL = *$ECxx - *$E8xx [total width] | ||
| BA2E | SRA H | Divide HL by 2 [halve total width] | ||
| BA30 | RR L | |||
| BA32 | LD B,H | BC = HL [keep a copy] | ||
| BA33 | LD C,L | |||
| BA34 | ADD HL,DE | HL += DE == (*$ECxx - *$E8xx) / 2 + *$E8xx [calc centre from left] | ||
| BA35 | LD ($EA00),HL | *$EAxx = HL (xx = self modified) (road centre) [store centre pos] | ||
| BA38 | LD D,B | DE = BC [copy halved width again] | ||
| BA39 | LD E,C | |||
| BA3A | SRA B | Divide BC by 2 again for quarter width | ||
| BA3C | RR C | |||
| BA3E | ADD HL,BC | == [centre] + [quarter width] | ||
| BA3F | LD ($EB00),HL | *$EBxx = HL (xx = self modified) (road centre right) [store centre-right pos] | ||
| BA42 | SBC HL,DE | == [[centre] + [quarter width]] - [half total width] | ||
| BA44 | LD ($E900),HL | *$E9xx = HL (xx = self modified) (road centre left) [store centre-left pos] | ||
| BA47 | INC A | A += 2 [remember A's not banked by EXX] | ||
| BA48 | INC A | |||
| BA49 | EXX | Unbank | ||
| BA4A | JP NZ,lr_ba20 | Loop while A | ||
| lr_exit | BA4D | LD SP,$0000 | Restore original SP (self modified) | |
| BA50 | RET | Return | ||
|
Handle a forked road.
|
||||
| lr_forked_road | BA51 | LD A,L | ||
| BA52 | LD ($A266),A | fork_countdown = A | ||
| BA55 | LD H,$E3 | HL = $E3xx | ||
| BA57 | LD A,$60 | Set fork_visible | ||
| BA59 | LD ($A265),A | |||
| BA5C | SUB (HL) | A = 106 - (A - *HL) -- HL is $E3xx | ||
| BA5D | CPL | |||
| BA5E | ADD A,$69 | |||
| BA60 | PUSH AF | Preserve A | ||
| BA61 | LD HL,($A267) | Load fork_distance | ||
| BA64 | LD A,(DE) | A = *DE & 4 -- DE is the lanes byte ptr | ||
| BA65 | AND $04 | |||
| BA67 | JR NZ,lr_badf | Jump if non-zero | ||
|
Lanes byte & 4 is zero. Hit when the road forks (during the fork itself).
|
||||
| BA69 | LD A,($A269) | A = fork_in_progress - 1 | ||
| BA6C | DEC A | |||
| BA6D | JR Z,lr_check_spawning | Jump to lr_check_spawning if zero | ||
| BA6F | NEG | fork_in_progress = -A | ||
| BA71 | LD ($A269),A | |||
| BA74 | LD DE,($A26C) | Get road position | ||
| BA78 | LD A,$01 | A = 1 | ||
| BA7A | DEC D | D-- | ||
| BA7B | JP M,lr_check_correct_fork_taken | jump with A==1 => right fork | ||
| BA7E | JP NZ,lr_left_fork | jump with A==1 => left fork | ||
| BA81 | LD A,E | A = E -- E is bottom of road position | ||
| BA82 | CP $0C | Jump with A==1 if E < 12 | ||
| BA84 | LD A,$01 | |||
| BA86 | JR C,lr_check_correct_fork_taken | |||
| lr_left_fork | BA88 | DEC A | A should be 1, will become zero | |
| lr_check_correct_fork_taken | BA89 | LD ($A249),A | Set fork_taken to A | |
| BA8C | INC A | 0/1 -> 1/2 | ||
| BA8D | PUSH HL | Preserve HL (holds fork_distance) | ||
| BA8E | LD HL,$A226 | Load address of correct_fork | ||
| BA91 | CP (HL) | Match? | ||
| BA92 | LD HL,$9941 | -> Tony: "LET'S GO. MR. DRIVER." <STOP> | ||
| BA95 | JR Z,lr_chatter | Jump to lr_chatter if correct fork was taken | ||
|
Incorrect fork was taken.
|
||||
| BA97 | LD A,$5F | Set the speed of the perp's car to 95 (normally 60) | ||
| BA99 | LD ($A195),A | |||
|
Add a bonus of (40,000 + 10,000 * level number) for going the wrong way (eh?)
|
||||
| BA9C | LD A,($8007) | A = wanted_stage_number + 4 | ||
| BA9F | ADD A,$04 | |||
| BAA1 | LD D,A | Set top digits | ||
| BAA2 | XOR A | Clear low digit | ||
| BAA3 | LD E,A | Clear middle digits | ||
| BAA4 | CALL add_bonus | Call add_bonus | ||
| BAA7 | LD HL,$98D0 | -> Raymond: "WHAT ARE YOU DOING MAN!" / "THE BAD GUYS ARE GOING THE OTHER WAY." <STOP> | ||
| lr_chatter | BAAA | LD A,$14 | Call start_chatter (with priority 20) | |
| BAAC | CALL start_chatter | |||
| BAAF | POP HL | Restore HL (holds fork_distance) | ||
| lr_check_spawning | BAB0 | LD A,($A254) | Load allow_spawning (0/1/2) | |
| BAB3 | AND A | Jump to lr_no_car_spawning if zero | ||
| BAB4 | JR Z,lr_no_car_spawning | |||
|
allow_spawning is non-zero.
|
||||
| BAB6 | LD C,A | A = allow_spawning + spawn_accumulator | ||
| BAB7 | LD A,($A16D) | |||
| BABA | ADD A,C | |||
| BABB | LD C,A | C = A -- copy so we can destroy A | ||
| BABC | SUB $02 | A -= 2 | ||
| BABE | JR C,lr_set_var_a16d_from_c | Jump if A < 2 | ||
|
Otherwise clamp it to 2.
|
||||
| BAC0 | LD C,A | C = A | ||
|
Adjusting this delta will cause the forked road effect to proceed faster (higher values) or slower (lower values).
|
||||
| BAC1 | LD DE,$0010 | Increase fork_distance by 16 | ||
| BAC4 | ADD HL,DE | |||
| BAC5 | LD ($A267),HL | |||
| lr_set_var_a16d_from_c | BAC8 | LD A,C | spawn_accumulator = C | |
| BAC9 | LD ($A16D),A | |||
| lr_no_car_spawning | BACC | LD A,($A16D) | A = spawn_accumulator | |
| BACF | RRA | this must extract the bottom bit to carry | ||
| BAD0 | LD A,($A23F) | A = fast_counter | ||
| BAD3 | RLA | A = (A << 1) | carry | ||
| BAD4 | RLA | A = (...) | ||
| BAD5 | RLA | |||
| BAD6 | RLA | |||
| BAD7 | AND $0F | |||
| BAD9 | SUB $10 | A -= 16 -- sets top nibble to $F | ||
| BADB | LD E,A | DE = $FF00 | A -- ($FFF0..$FFFF) | ||
| BADC | LD D,$FF | |||
| BADE | ADD HL,DE | HL += DE -- fork_distance + DE | ||
|
Lanes byte & 4 is non-zero. Hit when the road forks (as it becomes visible).
|
||||
| lr_badf | BADF | PUSH HL | Preserve HL | |
| BAE0 | LD A,($A249) | Jump if fork_taken was 1 (right fork taken) | ||
| BAE3 | DEC A | |||
| BAE4 | JR Z,lr_right_fork_taken | |||
|
Left fork was taken.
|
||||
| lr_left_fork_taken | BAE6 | CALL build_curve_table | Call build_curve_table | |
| BAE9 | POP DE | Restore HL from earlier | ||
| BAEA | LD HL,($A26C) | Get road position | ||
| BAED | PUSH HL | Stack it | ||
| BAEE | ADD HL,DE | DE must be a road position delta? | ||
| BAEF | LD ($A26C),HL | Set road position | ||
| BAF2 | CALL build_curve_table_forked | Call build_curve_table_forked | ||
| BAF5 | JR lr_bb07 | |||
|
Right fork was taken.
|
||||
| lr_right_fork_taken | BAF7 | CALL build_curve_table_forked | Call build_curve_table_forked | |
| BAFA | POP DE | Pop result? | ||
| BAFB | LD HL,($A26C) | Get road position | ||
| BAFE | PUSH HL | Stack it | ||
| BAFF | SBC HL,DE | DE must be a road position delta? | ||
| BB01 | LD ($A26C),HL | Set road position | ||
| BB04 | CALL build_curve_table | Call build_curve_table | ||
| lr_bb07 | BB07 | POP HL | Unstack road position | |
| BB08 | LD ($A26C),HL | Set road position | ||
| BB0B | POP BC | B used as a counter in a moment | ||
| BB0C | LD ($BA4E),SP | Self modify 'LD SP' @ lr_exit to restore SP | ||
| BB10 | LD SP,$EC30 | Put $EC30 (road right) in SP (so we can use POP for speed) | ||
| BB13 | LD A,$30 | Iterate from $30 to $00 in steps of 2 = 104 iterations [CHECK] | ||
| BB15 | LD HL,$BB38 | Self modify 'LD ($EAxx),HL' @ BB37 to be $EA30 (road centre) | ||
| BB18 | LD DE,$BB40 | Self modify 'LD ($E9xx),HL' @ BB3F to be $E930 (road centre left) | ||
| lr_loop | BB1B | LD (HL),A | Self modify the locations setup above | |
| BB1C | LD (DE),A | |||
| BB1D | LD ($BB2F),A | Self modify 'LD DE,($E8xx)' @ BB2D to be $E830 (road left) | ||
| BB20 | LD ($BB44),A | Self modify 'LD DE,($EDxx)' @ BB42 to be $ED30 | ||
| BB23 | LD ($BB47),A | Self modify 'LD HL,($EB00)' @ BB46 to be $EB30 (road centre right) | ||
| BB26 | LD ($BB4F),A | Self modify 'LD ($EB00),HL' @ BB4E to be $EB30 (road centre right) | ||
| BB29 | LD ($BB57),A | Self modify 'LD ($EC00),HL' @ BB56 to be $EC30 (road right) | ||
| BB2C | EXX | Bank during inner loop | ||
| BB2D | LD DE,($E800) | DE = *$E8xx (xx = self modified) (road left) | ||
| BB31 | POP HL | Read from $ECxx | ||
| BB32 | ADD HL,DE | (Right + Left) / 2 == new road centre | ||
| BB33 | SRA H | |||
| BB35 | RR L | |||
| BB37 | LD ($EA00),HL | *$EAxx = HL (xx = self modified) (store road centre) | ||
| BB3A | ADD HL,DE | (Centre + Left) / 2 == new road centre left | ||
| BB3B | SRA H | |||
| BB3D | RR L | |||
| BB3F | LD ($E900),HL | *$E9xx = HL (xx = self modified) store (road centre left) | ||
| BB42 | LD DE,($ED00) | DE = *$EDxx (xx = self modified) (?) | ||
| BB46 | LD HL,($EB00) | HL = *$EBxx (xx = self modified) (road centre right) | ||
| BB49 | ADD HL,DE | (Centre-right + ?) / 2 == new road centre right | ||
| BB4A | SRA H | |||
| BB4C | RR L | |||
| BB4E | LD ($EB00),HL | *$EBxx = HL (xx = self modified) store (road centre right) | ||
| BB51 | ADD HL,DE | (Centre-right) + ?) / 2 == new road right | ||
| BB52 | SRA H | |||
| BB54 | RR L | |||
| BB56 | LD ($EC00),HL | *$ECxx = HL (xx = self modified) (road right) | ||
| BB59 | INC A | A += 2 | ||
| BB5A | INC A | |||
| BB5B | EXX | Unbank | ||
| BB5C | DJNZ lr_loop | Loop while B > 0 | ||
| BB5E | AND A | Jump to lr_exit if A is zero | ||
| BB5F | JP Z,lr_exit | |||
| BB62 | LD H,$EC | Point SP at $EC00 | A (road right) | ||
| BB64 | LD L,A | |||
| BB65 | LD SP,HL | |||
| BB66 | JP lr_calc_single_lane | Jump back to lr_calc_single_lane | ||
| Prev: B8D2 | Up: Map | Next: BB69 |