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 |