| Chase H.Q. | Routines | 
| Prev: B8D2 | Up: Map | Next: BB69 | 
|  | ||||
| layout_road | B9F4 | LD A,($A240) | Load road_buffer_offset into A [as byte] | |
| B9F7 | ADD A,$40 | Add 64 so it's the lanes data offset | ||
| 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 = 20 iterations, C = $E1 (a mask) | ||
| B9FF | LD L,$00 | Counter | ||
| 
Q. Lanes bytes are pairs of bytes (count,data), so how does looking for $E1 help?
 | ||||
| layout_road_0 | 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 layout_road_0 | 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 sub_cbce_non_fork | Call sub_cbce_non_fork | |
| 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_ba17 | 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 [divide 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 | ||
| 
Otherwise A has 255? NEG turns that back to zero. Why not XOR A which is shorter?
 | ||||
| BA6F | NEG | fork_in_progress = -fork_in_progress + 1 = ~fork_in_progress | ||
| 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 ? | ||
| 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 | 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 (accel?) of the perp's car to $5F -- reducing accel so we can catch up? | ||
| 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 bonus | Call 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 + var_a16d | ||
| 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 | var_a16d = C | |
| BAC9 | LD ($A16D),A | |||
| lr_no_car_spawning | BACC | LD A,($A16D) | A = var_a16d | |
| BACF | RRA | Getting carry? | ||
| BAD0 | LD A,($A23F) | A = (fast_counter >> 4) | ||
| BAD3 | RLA | |||
| BAD4 | RLA | |||
| 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 sub_cbce_non_fork | Call sub_cbce_non_fork | |
| 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 sub_cbce_fork | Call sub_cbce_fork | ||
| BAF5 | JR lr_bb07 | |||
| 
Right fork was taken.
 | ||||
| lr_right_fork_taken | BAF7 | CALL sub_cbce_fork | Call sub_cbce_fork | |
| 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 sub_cbce_non_fork | Call sub_cbce_non_fork | ||
| 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_ba17 | Jump back to lr_ba17 | ||
| Prev: B8D2 | Up: Map | Next: BB69 |