Prev: B8D2 Up: Map Next: BB69
B9F4: Lays out the road
Used by the routines at main_loop, cpu_driver and escape_scene.
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