Prev: C2E7 Up: Map Next: C8BE
C452: Draws the road
The main entry point for road drawing. It clears the on-dirt-track, tunnel visible and in-tunnel flags, sets the edge thickness to 3 and computes the initial horizon counter as 96 minus the second height table entry. The stripe phase comes from the lane data buffer offset: bit 0 gives the XOR base and bit 1 the initial stripe state. With the stripe parameters set it falls into dr_read_lanes to render the road row by row.
Used by the routines at main_loop, drive_attract_demo and escape_scene.
draw_road C452 LD ($C8A4),SP Self modify SP restore instruction
C456 XOR A Zero on_dirt_track
C457 LD ($A248),A
C45A LD ($C161),A Self modify 'LD A,x' @ C160 to load zero (in draw_tunnel, "tunnel visible")
C45D LD ($C890),A Self modify 'LD A,x' @ C88F to load zero (below, "in tunnel")
This affects the thickness of the road edges and lane markings with increasing distance. A larger value means lines remain thick into distance.
C460 LD A,$03 Self modify 'LD A,x' @ dr_edge_thickness to load 3 (below)
C462 LD ($C6D9),A
C465 LD IY,$E301 Load address of height table[1]
C469 LD A,$60 C = $60 - IY[0]
C46B SUB (IY+$00)
C46E LD C,A
Set initial road stripe state.
C46F LD A,($A240) Load road_buffer_offset.lo
C472 ADD A,$40 Add 64 so it's the lanes data offset
C474 LD IXl,A Load address of $EE00[A]
C476 LD IXh,$EE
C479 LD B,A Copy lanes data offset to B
C47A AND $01 Self modify 'LD A,x' @ dr_set_stripes (below) to load <lanes data offset> & 1
C47C LD ($C6B3),A
C47F RR B Shift bit 1 of <lanes data offset> into carry
C481 RR B
C483 LD HL,$D010 Set H to $D0 (table offset?); Set L to 16 (stripe height?)
C486 LD A,H Copy $D0 to A (XOR base)
Alter this and the landscape uses that fill pattern, but only half the time.
C487 LD B,$55 Set B to $55 -- "on" fill pattern?
C489 JR C,dr_stripe_state_set If B carried out (earlier) then jump
C48B LD HL,$0030 Set H to $00 (table offset?); Set L to 48
C48E LD B,H Copy $00 to B -- "off" fill pattern
dr_stripe_state_set C48F LD ($C6D4),A Self modify 'XOR x' @ C6D3 to be x = $D0
C492 LD A,H Self modify 'ADD A,x' @ C677 to be x = $D0 or $00
C493 LD ($C678),A
C496 LD A,L Self modify 'ADD A,x' @ C651 to be x = $10 or $30
C497 LD ($C652),A
C49A INC A Self modify 'ADD A,x' @ C698 to be x = $11 or $31
C49B LD ($C699),A
C49E LD HL,$C534 Self modify 'JP Z,x' @ C4B2 to be dr_four_lane_highway/dr_four_lane_highway
C4A1 LD ($C4B3),HL
C4A4 LD L,$FF Set L to $FF
C4A6 LD DE,$0100 Set DE to $0100
C4A9 LD A,B Self modify 'LD A,x' @ dr_flip_stripe_patterns to load on/off stripe fill pattern
C4AA LD ($C6BD),A
This entry point is used by the routine at dr_dispatch_filled.
dr_read_lanes C4AD LD A,(IX+$00) Load a lanes byte
C4B0 AND $03 Isolate bottom two bits (left hand position)
C4B2 JP Z,dr_four_lane_highway Jump to <self modified> if zero (e.g. dr_four_lane_highway)
Otherwise it's anything other than the zero case.
C4B5 EXX Bank
Sampled IX=$EEFD $EEFE $EEFF $EE00 .. etc.
C4B6 LD L,(IX+$00) Reload the lanes byte
C4B9 ADD A,$E7 Turn left hand road position (1..3) into table high byte ($E8..$EA)
C4BB LD ($C643),A Self modify 'LD H,x' @ C642
C4BE LD ($C5B4),A Self modify 'LD H,x' @ C5B3
C4C1 LD H,A Copy
C4C2 SLA L Shift bit 7 of lanes byte into carry. With bit 6 clear it means a 3-lane or 3/4-lane-change section; with bit 6 set it separates dirt track and forked road (bit 7 set) from tunnel (clear)
C4C4 BIT 7,L Test former bit 6; is set for tunnel or for dirt track (carry preserved)
C4C6 JR NZ,dr_special_road Jump to dr_special_road if set
If bit 6 was clear then it's a normal road (not tunnel, dirt track or forked road).
C4C8 JR NC,dr_two_lane Jump to dr_two_lane if bit 7 was clear (any of the two-lane roads or 2-to-3 narrowing/widening lane types)
If bit 7 was set then it's a 3-lane, 3-to-4 lane or 4-to-3 lane section.
C4CA ADD A,$03 $E8..$EA becomes $EB..$ED
C4CC LD C,$FD Set C to -3
C4CE JP dr_setup_scene_change Jump to dr_setup_scene_change
If bit 7 was clear then it's a 2-lane, 2-to-3 lane or 3-to-2 lane section.
dr_two_lane C4D1 ADD A,$02 $E8..$EA becomes $EA..$EC
C4D3 LD C,$FE Set C to -2
dr_setup_scene_change C4D5 LD ($C5DA),A Self modify 'LD H,x' @ C5D9
C4D8 LD ($C68B),A Self modify 'LD H,x' @ dr_c68a
C4DB LD A,C Set A to $FD or $FE (from C)
C4DC LD ($C5AD),A Self modify 'LD B,x' @ C5AC
C4DF JP draw_road_lanes_change Exit via draw_road_lanes_change/draw_road_lanes_change [this is its only caller]
If bit 6 was clear then it's a special road (tunnel, dirt track or forked road).
dr_special_road C4E2 JR C,dr_dirt_track Jump to dr_dirt_track if carry set (bit 7 of lanes byte - dirt track flag)
If bit 7 was clear then it's a tunnel section.
C4E4 LD C,$FF Set C to $FF
C4E6 LD H,$01 Set H to 1
C4E8 BIT 4,L Jump if former bit 3 of lanes byte set (tunnel exit)
C4EA JR NZ,dr_tunnel_transition
C4EC BIT 3,L Jump if former bit 2 of lanes byte clear (also tunnel exit... so that can't be right)
C4EE JR Z,dr_set_inside_flag
If bits 2 or 3 are set then it's a tunnel transition section.
dr_tunnel_transition C4F0 LD A,IYl Load IY.low (distance)
C4F2 LD ($C15E),A Self modify 'CP x' @ C15D (in draw_tunnel) - tunnel distance
C4F5 LD A,$01 Set A to 1 - tunnel visible
C4F7 INC C Set C to 0 - fill pattern
C4F8 BIT 5,L Jump if former bit 4 of lanes byte clear (tunnel entrance)
C4FA JR Z,dr_set_visible_flag
If bit 4 is set then it's a tunnel exit.
C4FC DEC C Set C to $FF -- fill pattern
C4FD INC A Set A to 2 -- tunnel visible
C4FE DEC H Set H to 0 -- in-tunnel flag
dr_set_visible_flag C4FF LD ($C161),A Self modify 'LD A,x' @ C160 (in draw_tunnel)
dr_set_inside_flag C502 LD A,H Set A to 0 (from H)
C503 LD ($C890),A Self modify 'LD A,x' @ C88F (inside tunnel flag)
C506 LD A,$EB Set A to $EB -- top byte of table?
C508 LD ($C5DA),A Self modify 'LD H,x' @ C5D9
C50B LD ($C68B),A Self modify 'LD H,x' @ dr_c68a
C50E LD A,$FF Set A to -1
C510 LD ($C5AD),A Self modify 'LD B,x' @ C5AC (-ve lane count)
C513 LD A,C A = C (fill pattern)
C514 EXX Bank/unbank
C515 LD B,A B = A (fill pattern)
C516 JP dr_dispatch_fill Jump
If bit 7 was set then it's a dirt track or forked road.
dr_dirt_track C519 BIT 6,L Jump to draw_forked_road if former bit 5 (not 6
If bit 5 was set then it's a forked road.
C51B JP NZ,draw_forked_road because shifted) of lanes byte is set}
If bit 5 was clear then it's a dirt track section.
C51E LD A,L Set flags of (L & 24)
C51F AND $18
C521 LD A,$00 Set new on_dirt_track value to 0 -- not self modified (why not XOR A?)
C523 JR NZ,dr_c526 Jump if flags non-zero
C525 INC A Set new on_dirt_track value to 1
dr_c526 C526 LD ($A248),A Set on_dirt_track to new value
C529 LD A,$FF Set A to -1
C52B LD ($C5AD),A Self modify 'LD B,x' @ C5AC (-ve lane count)
C52E LD HL,$C534 -> dr_four_lane_highway
C531 JP dr_set_lane_callback Jump forward
dr_four_lane_highway C534 EXX Bank
C535 LD A,$E8 Set A to $E8 -- set left hand road position to leftmost
C537 LD ($C643),A Self modify 'LD H,x' @ C642
C53A LD ($C5B4),A Self modify 'LD H,x' @ C5B3
C53D ADD A,$04 Set A to $EC -- set right hand road position to rightmost
C53F LD ($C68B),A Self modify 'LD H,x' @ dr_c68a
C542 LD ($C5DA),A Self modify 'LD H,x' @ C5D9
C545 LD A,$FC Set A to -4
C547 LD ($C5AD),A Self modify 'LD B,x' @ C5AC
C54A LD HL,$C551 -> dr_c551
This entry point is used by the routine at draw_road_lanes_change. Called for regular roads incl dirt track, but not tunnels or splits.
dr_set_lane_callback C54D LD ($C4B3),HL Self modify 'JP Z,x' @ C4B2
C550 EXX Bank/unbank
dr_dispatch_fill C551 LD A,B Copy fill pattern from B
C552 AND A
C553 JP NZ,dr_dispatch_filled Jump if non-zero
C556 EXX Bank
C557 LD HL,$C55F Self modify 'JP NZ,x' @ C6AD to be dr_advance_unfilled
C55A LD ($C6AE),HL
C55D EXX Unbank
C55E EX AF,AF'
Move to next scanline.
dr_advance_unfilled C55F LD A,D Save for checking in a moment
C560 DEC D Move to next scanline (visually upwards)
C561 AND $0F Would it have rolled over into the top nibble?
C563 JR Z,dr_rollover_unfilled Jump if zero
This entry point is used by the routine at dr_rollover_unfilled.
dr_write_scanline_unfilled C565 LD ($C56D),DE Self modify 'LD DE,x' @ C56C (below)
C569 LD B,$FF Set B to $FF
C56B EXX Bank/unbank
Calculate address of next bitmap scanline ??
C56C LD DE,$0000 DE = <self modified>
C56F LD A,E L = E + 31
C570 ADD A,$1F
C572 LD L,A
C573 LD H,D H = D
C574 LD SP,HL Put it in SP (so we can use PUSH for speed)
C575 LD HL,$0000 HL = 0 [not self modified apparently] -- fill value
C578 LD C,L C = 0
C579 JP dr_fill_left_stripe Jump into a sequence of 15 PUSH HLs
This is scanline/buffer pointer movement
dr_rollover_filled C57C LD A,E Move to next chunk of 16 scanlines
C57D SUB $20
C57F LD E,A
C580 JP C,dr_fill Carry set if CCC field was zero - don't compensate 1111 field and continue
C583 LD A,D Put back the bit stolen since BAAA field was zero
C584 ADD A,$10
C586 LD D,A
C587 JP dr_fill jump
This is scanline/buffer pointer movement
dr_rollover_unfilled C58A LD A,E Move to next chunk of 16 scanlines
C58B SUB $20
C58D LD E,A
C58E JP C,dr_write_scanline_unfilled Carry set if CCC field was zero - don't compensate 1111 field and continue
C591 LD A,D Put back the bit stolen since BAAA field was zero
C592 ADD A,$10
C594 LD D,A
C595 JP dr_write_scanline_unfilled jump
Road and backdrop plotting
dr_dispatch_filled C598 EXX Bank
C599 LD HL,$C5A1 Self modify 'JP NZ,x' @ C6AD to be dr_advance_filled
C59C LD ($C6AE),HL
C59F EXX Unbank
C5A0 EX AF,AF'
Move to next scanline.
dr_advance_filled C5A1 LD A,D Save for checking in a moment
C5A2 DEC D Move to next scanline (visually upwards)
C5A3 AND $0F Would it have rolled over into the top nibble?
C5A5 JR Z,dr_rollover_filled Jump if rolled over
This entry point is used by the routine at dr_rollover_filled.
dr_fill C5A7 LD ($C5FA),DE Self modify 'LD DE,x' @ C5F9
C5AB LD A,L A = L
C5AC LD B,$00 B = <self modified> e.g. $FC or $FD -- -ve lane count
C5AE EXX Bank
C5AF LD L,A L = A
C5B0 LD BC,$10F8 B = 16, C = $F8 (mask)
C5B3 LD H,$E8 Load <self modified> top byte of table left hand position
C5B5 LD A,(HL) Load from table
C5B6 AND A Set flags
C5B7 JP Z,dr_c5c4 Jump if zero
C5BA LD A,$00 A = 0 (not self modified)
C5BC JP M,dr_c5d3 Jump if negative
C5BF LD A,$0F A = 15
C5C1 JP dr_c5d3 Jump
Pattern
dr_c5c4 C5C4 DEC L Load HL[-1]
C5C5 LD A,(HL)
C5C6 INC L
C5C7 AND C A &= $F8 -- C is the mask $F8 here
C5C8 RRCA A >>= 3
C5C9 RRCA
C5CA RRCA
C5CB RRA A >>= 1
C5CC ADC A,$00 Add carry
C5CE CP B Jump if A < B
C5CF JP C,dr_c5d3
C5D2 DEC A A--
dr_c5d3 C5D3 LD E,A E = A
C5D4 CPL A = ~E + B -- B is 16
C5D5 ADD A,B
C5D6 LD ($C62D),A Self modify 'JR x' @ dr_lefthand_jumptable -- jump table target
C5D9 LD H,$EC Set high byte of table address to <self modified> e.g. $EC
C5DB LD A,(HL) Read from table -- is this 8-bit or a partial 16-bit value?
C5DC AND A Set flags
C5DD JP Z,dr_calc_righthand_width Jump if zero -- jump to calc bit
C5E0 LD A,$0F Set righthand jump table target to 15 (just plots 16 pixels?)
C5E2 JP P,dr_set_righthand_jump_table_target Jump if positive
C5E5 XOR A Otherwise set it to zero (plots 15*16 pixels?)
C5E6 JP dr_set_righthand_jump_table_target Jump
Same pattern again
dr_calc_righthand_width C5E9 DEC L L--
C5EA LD A,(HL) Read from table
C5EB AND C Mask with $F8 (C is the mask $F8 here)
C5EC RRCA A >>= 3
C5ED RRCA
C5EE RRCA
C5EF RRA A >>= 1
dr_set_righthand_jump_table_target C5F0 LD ($C60B),A Self modify 'JR x' @ dr_righthand_jumptable -- righthand jump table target
Calculate road jump table target.
C5F3 CPL A = ~A + B + E (== 15 - A + E)
C5F4 ADD A,B
C5F5 ADD A,E
C5F6 LD ($C61C),A Self modify 'JR x' @ dr_road_jumptable -- road jump table target
C5F9 LD DE,$0000 DE = <self modified by #$C5A7>
C5FC LD A,E L = E + 31
C5FD ADD A,$1F
C5FF LD L,A
C600 LD H,D H = D
C601 LD SP,HL Put it in SP (so we can use PUSH for speed)
C602 EX AF,AF' Unbank fill byte
C603 RLCA Rotate fill pattern so we checkerboard
C604 LD H,A Widen stripe fill byte to whole word
C605 LD L,A
C606 EX AF,AF' Bank fill byte
C607 LD BC,$0000 Set road fill to zero (but only when drawing stripes)
Fill right hand road stripes - starting from right hand side.
dr_righthand_jumptable C60A JR dr_righthand_jumptable Jump table (self modified)
C60C PUSH HL
C60D PUSH HL
C60E PUSH HL
C60F PUSH HL
C610 PUSH HL
C611 PUSH HL
C612 PUSH HL
C613 PUSH HL
C614 PUSH HL
C615 PUSH HL
C616 PUSH HL
C617 PUSH HL
C618 PUSH HL
C619 PUSH HL
C61A PUSH HL
Fill blank road surface - continuing from the right hand side.
dr_road_jumptable C61B JR dr_road_jumptable Jump table (self modified)
C61D PUSH BC
C61E PUSH BC
C61F PUSH BC
C620 PUSH BC
C621 PUSH BC
C622 PUSH BC
C623 PUSH BC
C624 PUSH BC
C625 PUSH BC
C626 PUSH BC
C627 PUSH BC
C628 PUSH BC
C629 PUSH BC
C62A PUSH BC
C62B PUSH BC
Fill left hand road stripes - continuing from the right hand side.
dr_lefthand_jumptable C62C JR dr_lefthand_jumptable Jump table (self modified)
This entry point is used by the routine at draw_road.
dr_fill_left_stripe C62E PUSH HL
C62F PUSH HL
C630 PUSH HL
C631 PUSH HL
C632 PUSH HL
C633 PUSH HL
C634 PUSH HL
C635 PUSH HL
C636 PUSH HL
C637 PUSH HL
C638 PUSH HL
C639 PUSH HL
C63A PUSH HL
C63B PUSH HL
C63C PUSH HL
...
C63D LD B,E B = E
C63E DEC C 0 -> 255
C63F LD H,$E4 Point HL at road edge/markings table at $E4xx
C641 EXX Bank/unbank
C642 LD H,$E8 Load <self modified> top byte of road left hand edge table ($E8/$E9/$EA for left/centre-left/centre)
C644 LD A,(HL) Read from left/centre-left/centre hand edge table at $E8xx/$E9xx/$EAxx
C645 AND A Jump if non-zero
C646 JR NZ,dr_road_lane_marking_loop
Otherwise zero.
C648 DEC L index = HL[-1] -- Load the byte prior
C649 LD A,(HL)
C64A INC L
C64B EXX Bank
Build address of road edge marking graphic.
C64C LD E,A Save index
C64D AND $07 Bottom three bits select the row number 0..7
C64F RLCA Turn into a scanline offset (4 bytes per row)
C650 RLCA
C651 ADD A,$00 Add offset of current edge marking graphic ($10,$30,$50,$70,$90,$B0)
C653 LD L,A Set HL to road edge marking address
The top five bits of the x position give the byte column within the 32-byte back buffer row, which is why breaking this only moves the left hand edge.
C654 LD A,E E = ((index >> 3) & 31) + B
C655 RRA
C656 RRA
C657 RRA
C658 AND $1F
C65A ADD A,B
C65B LD E,A
AND-OR masking here. DE is address of screen buffer byte. HL is address of mask byte, followed by bitmap byte [then again since the edges are 16x8]
C65C LD A,(DE) Read a screen buffer byte
C65D AND (HL) Apply the mask
C65E INC L Advance to bitmap byte
C65F OR (HL) Apply the bitmap
C660 LD (DE),A Write the new screen buffer byte
C661 INC L L += 2
C662 INC L
C663 INC E E++
C664 LDI *DE++ = *HL++, BC--
C666 EXX Unbank
Draw road lane markings.
dr_road_lane_marking_loop C667 INC B Increment counter
C668 JR Z,dr_c68a Exit loop if zero
C66A INC H H++
C66B LD A,(HL) Read from road left drawing table e.g $E89F
C66C AND A Set flags
C66D JR NZ,dr_road_lane_marking_loop Loop if non-zero
C66F DEC L A = HL[-1] (with wraparound?)
C670 LD A,(HL)
C671 INC L
C672 EXX Bank
C673 LD E,A E = A -- save A
C674 AND $07 L = ((A & 7) << 1) + <self modified>
C676 RLCA
C677 ADD A,$00
C679 LD L,A
C67A LD A,E E = ((E >> 3) & 31) + B
C67B RRA
C67C RRA
C67D RRA
C67E AND $1F
C680 ADD A,B
C681 LD E,A
C682 LDI *DE++ = *HL++, BC--
This reads an (unmasked) road lane marker bitmap byte from $E4D0+.
C684 LD A,(HL) Copy a byte from $E4D0+ to the buffer
C685 LD (DE),A
C686 EXX Unbank
C687 JP dr_road_lane_marking_loop Loop
dr_c68a C68A LD H,$00 Set high byte of table address to <self modified> e.g. $EC
C68C LD A,(HL) A = *HL
C68D DEC L L--
C68E AND A Set flags
C68F JR NZ,dr_c6ab Jump if non-zero
C691 LD A,(HL) A = *HL
C692 EXX Bank
C693 LD E,A E = A -- save A
Must be the right hand edge handling.
C694 AND $07 L = ((A & 7) << 2) + <self modified> -- as above but * 4
C696 RLCA
C697 RLCA
C698 ADD A,$11
C69A LD L,A
C69B LD A,E E = ((E >> 3) & 31) + B
C69C RRA
C69D RRA
C69E RRA
C69F AND $1F
C6A1 ADD A,B
C6A2 LD E,A
C6A3 LDI *DE++ = *HL++, BC--
AND-OR masking here. This affects road lines when altered.
C6A5 LD A,(DE) A = *DE & *HL
C6A6 AND (HL)
C6A7 INC L L++
C6A8 OR (HL) *DE = A | *HL
C6A9 LD (DE),A
C6AA EXX Unbank
dr_c6ab C6AB DEC L L--
C6AC DEC C C-- -- road row counter
C6AD JP NZ,$0000 Jump to <self modified> if non-zero
C6B0 EX AF,AF' Swap
C6B1 LD B,A B = A
This causes the alternating road stripes.
dr_set_stripes C6B2 LD A,$00 Load <self modified> -- loads (<lanes data offset> & 1)
C6B4 XOR $01 Toggle the road stripe state
C6B6 LD ($C6B3),A Write it back
C6B9 JP NZ,dr_edge_thickness Jump if non-zero
dr_flip_stripe_patterns C6BC LD A,$00 Load <self modified> fill pattern
C6BE XOR $55 Exclusive or with $55 -- flips the chequerboard fill pattern to its opposite phase
C6C0 LD ($C6BD),A Self modify above
C6C3 LD B,A Keep a copy of the stripe fill pattern for the rows drawn below
This causes the road edge stripes.
C6C4 LD A,($C652) Toggle bit 5 of x in 'ADD A,x' @ C651 -- switch between adjacent edge graphics (that are 32 bytes each)
C6C7 XOR $20
C6C9 LD ($C652),A
C6CC INC A The right hand edge reads the same 4-byte record one byte along: its solid byte comes first and its masked pair second, mirroring the left hand edge
C6CD LD ($C699),A Self modify 'ADD A,x' @ C698
C6D0 LD A,($C678) Toggle <self modified> bits of 'ADD A,x' @ C677
C6D3 XOR $00
C6D5 LD ($C678),A
dr_edge_thickness C6D8 LD A,$00 Load <self modified> edge width value
C6DA DEC A Decrement it
C6DB LD ($C6D9),A Self modify 'LD A' above @ dr_edge_thickness to be new A
C6DE JP NZ,dr_edge_width_handled Jump if non-zero
Otherwise edge width value was zero.
C6E1 LD A,($C6D4) Read 'XOR x' @ C6D3
C6E4 ADD A,$10 A += 16
C6E6 JR C,dr_edge_width_handled Jump if carried
C6E8 LD ($C6D4),A Self modify 'XOR x' @ C6D3 to be new A
C6EB LD C,A C = A
C6EC LD A,($C678) Read 'ADD A,x' @ C677
C6EF AND A Set flags
C6F0 JR Z,dr_c6f6 Jump if zero
C6F2 LD A,C A = C
C6F3 LD ($C678),A Self modify 'ADD A,x' @ C677
dr_c6f6 C6F6 LD A,($C652) Increment x in 'ADD A,x' @ C651 by 64 -- steps on to the next pair of edge variants, since C6C7 toggles between the two members of a pair
C6F9 ADD A,$40
C6FB LD ($C652),A
C6FE LD A,$05 Self modify 'LD A,x' @ dr_edge_thickness to be 5
C700 LD ($C6D9),A
Sampled IY = $E301..$E315
dr_edge_width_handled C703 LD A,(IY+$00) Load IY[0]
C706 INC IY Increment IY
Sampled IX = $EEC5..$EED9
C708 INC IXl IX.low++ -- wrapping around
C70A SUB (IY+$00) A -= IY[0]
C70D JR Z,dr_level_road Jump if zero
C70F JP P,dr_c794 Jump if positive
C712 JP dr_c746 Jump
dr_level_road C715 DEC L L -= 2
C716 DEC L
Sampled IX = $EE2C ... EE39 EE45
C717 LD C,(IX+$00) Load the lanes flags byte
C71A BIT 6,C Bit 6 indicates tunnel or dirt track
C71C JP Z,dr_set_stripes Jump (loop?) if clear (neither tunnel nor dirt track)
Tunnel or dirt track.
C71F BIT 7,C Bit 7 indicates dirt track
C721 JP NZ,dr_set_stripes Jump (loop?) if set (dirt track only)
Tunnel.
C724 LD B,$FF Load 255
C726 BIT 2,C Bit 2 indicates tunnel start
C728 LD A,$01 Load 1 -- value for (tunnel related)
C72A JR Z,dr_c740 Jump if clear (tunnel cont/end?)
C72C LD A,IYl Load IY.low (distance)
C72E LD ($C15E),A Self modify 'CP x' @ C15D [15 when tunnel is small, 6 when fills screen]
C731 LD A,$01 A = 1
C733 INC B 255 -> 0
C734 BIT 4,C Bit 4 of C set?
C736 LD C,A C = A
C737 JR Z,dr_c73c Jump if clear
C739 DEC B B--
C73A INC A A++
C73B DEC C C--
dr_c73c C73C LD ($C161),A Self modify 'LD A,x' @ C160 (in draw_tunnel)
C73F LD A,C A = C
dr_c740 C740 LD ($C890),A Self modify 'LD A,x' @ C88F (tunnel related)
C743 JP dr_set_stripes Jump
Variation:
dr_c746 C746 LD C,(IX+$00) C = IX[0]
C749 BIT 6,C Bit 6 of C set?
C74B JP Z,dr_c774 Jump if clear
C74E BIT 7,C Bit 7 of C set?
C750 JP NZ,dr_c774 Jump if set
C753 EX AF,AF' Swap
C754 LD B,$FF B = 255
C756 BIT 2,C Bit 2 of C set?
C758 LD A,$01 A = 1
C75A JR Z,dr_c770 Jump if clear
C75C LD A,IYl Load IY.low (distance)
C75E LD ($C15E),A Self modify 'CP x' @ C15D [15 when tunnel is small, 6 when fills screen]
C761 LD A,$01 A = 1
C763 INC B B++
C764 BIT 4,C Bit 4 of C set?
C766 LD C,A C = A
C767 JR Z,dr_c76c Jump if clear
C769 DEC B B--
C76A INC A A++
C76B DEC C C--
dr_c76c C76C LD ($C161),A Self modify 'LD A,x' @ C160 (in draw_tunnel)
C76F LD A,C A = C
dr_c770 C770 LD ($C890),A Self modify 'LD A,x' @ C88F (tunnel related)
C773 EX AF,AF' Swap
dr_c774 C774 LD C,A C = A
C775 LD A,(IY+$00) A = IY[0]
C778 INC IY IY++
C77A INC IXl IX.low++
C77C SUB (IY+$00) A -= IY[0]
C77F CP $E0 Compare to $E0
C781 JP NC,dr_c788 Jump if A >= $E0
C784 CP $50 Compare to $50
C786 JR NC,dr_start_backdrop_fill Jump if A >= $50
dr_c788 C788 DEC L L -= 2
C789 DEC L
C78A ADD A,C A += C
C78B JR Z,dr_c746 Jump if zero or negative
C78D JP M,dr_c746
C790 LD C,A C = A
C791 JP dr_read_lanes Jump
dr_c794 C794 LD C,A C = A
C795 CP $50 Compare to $50
C797 JP C,dr_read_lanes Jump if A < $50
This entry point is used by the routines at mystery_cba4 and backdrop_fill_dispatch.
dr_start_backdrop_fill C79A INC E E++
C79B LD HL,$C161 Load address of x in 'LD A,x' @ C160 (in draw_tunnel)
C79E LD A,($C890) Read 'LD A,x' @ C88F (tunnel related)
C7A1 OR (HL) A |= *HL
C7A2 RRA A >>= 1
C7A3 JP C,dr_start_sky_fill Jump if carry (bottom bit set)
C7A6 LD A,D C = D & 15
C7A7 AND $0F
C7A9 LD C,A
C7AA LD A,E B = ~((E >> 1) + C) + $80
C7AB SRL A
C7AD ADD A,C
C7AE CPL
C7AF ADD A,$80
C7B1 LD B,A
C7B2 LD HL,($A171) Load horizon_level
C7B5 LD C,$18 C = 24
C7B7 LD A,H A = H
C7B8 AND A Set flags
C7B9 JP M,dr_start_sky_fill Jump if negative
C7BC JR NZ,dr_c7ca Jump if non-zero
C7BE LD A,L A = L - B
C7BF SUB B
C7C0 JR NC,dr_c7ca Jump if A was >= B
C7C2 ADD A,C A += C
C7C3 JP NC,dr_start_sky_fill Jump if no carry
C7C6 JP Z,dr_start_sky_fill Jump if zero
C7C9 LD C,A C = A
dr_c7ca C7CA LD A,C A = C
C7CB LD ($C80C),A Self modify xx in 'LD BC,$xxyy' @ C80A
C7CE ADD A,B A += B
C7CF JP P,dr_c7db Jump if positive
C7D2 SUB $7F A = -(A - 127) + C
C7D4 NEG
C7D6 ADD A,C
C7D7 LD ($C80C),A Self modify xx in 'LD BC,$xxyy' @ C80A
C7DA LD C,A C = A
dr_c7db C7DB LD A,C BC = (24 - C) * 3 -- assuming no overflow from calc of C
C7DC CPL
C7DD ADD A,$19
C7DF RLCA
C7E0 LD C,A
C7E1 RLCA
C7E2 RLCA
C7E3 ADD A,C
C7E4 LD C,A
C7E5 LD B,$00
C7E7 LD A,$00 Load <self modified> horizon's horizontal shift value (ranges 0..19)
Decide whether to use the pre-shifted or the non-shifted version of the backdrop bitmap.
C7E9 RRA Shift bottom bit out to carry
C7EA LD HL,$5B00 Point at hill backdrop (pre-shifted version)
C7ED JR NC,dr_c7f2 Jump if no carry
C7EF LD HL,$5C00 Point at hill backdrop (non-shifted version)
dr_c7f2 C7F2 ADD HL,BC HL += BC
C7F3 EXX Bank/unbank
A is 0..9 here, turn it back to 0..18 and invert to make jump table target.
C7F4 ADD A,A A = 18 - A * 2
C7F5 CPL
C7F6 ADD A,$13
C7F8 LD ($C86D),A Self modify 'JR x' @ dr_c86c -- jump table target
C7FB LD E,A Set source address to backdrop_shifting_instrs[A]
C7FC LD D,$00
C7FE LD HL,$86F6
C801 ADD HL,DE
C802 LD BC,$0012 Copy 18 bytes
C805 LD DE,$C82D Set destination address to instruction stream
C808 LDIR Copy
C80A LD BC,$180A BC = $<self modified>0A
C80D EXX Bank/unbank
C80E LD A,L A = L
C80F EX AF,AF' Swap
C810 JP dr_c824 Jump
Scanline advance pattern.
dr_c813 C813 LD A,E E -= 32
C814 SUB $20
C816 LD E,A
C817 JP C,dr_c82a Jump if E < 32
C81A LD A,D D -= 16
C81B ADD A,$10
C81D LD D,A
C81E JP dr_c82a
dr_c821_apparent_loop_start C821 EXX Bank/unbank
C822 EX AF,AF' Swap
C823 LD E,A E = A
dr_c824 C824 LD A,D A = D
C825 DEC D D--
C826 AND $0F A &= 15
C828 JR Z,dr_c813 Jump if zero
This entry point is used by the routine at dr_c813.
dr_c82a C82A LD A,E A = E
C82B EX AF,AF' Swap
C82C LD L,A L = A
dr_c82d C82D NOP 18 instructions/lines filled in by earlier code
C82E NOP
C82F NOP
C830 NOP
C831 NOP
C832 NOP
C833 NOP
C834 NOP
C835 NOP
C836 NOP
C837 NOP
C838 NOP
C839 NOP
C83A NOP
C83B NOP
C83C NOP
C83D NOP
C83E NOP
C83F LDI
C841 LD L,A
C842 LDI
C844 LDI
C846 LDI
C848 LDI
C84A LDI
C84C LDI
C84E LDI
C850 LDI
C852 LDI
C854 LDI
C856 LD L,A
C857 LDI
C859 LDI
C85B LDI
C85D LDI
C85F LDI
C861 LDI
C863 LDI
C865 LDI
C867 LDI
C869 LDI
C86B LD L,A
dr_c86c C86C JR dr_c86c Self modified - jump table
C86E LDI
C870 LDI
C872 LDI
C874 LDI
C876 LDI
C878 LDI
C87A LDI
C87C LDI
C87E LDI
C880 EXX
C881 ADD A,C A += C
C882 DJNZ dr_c821_apparent_loop_start Loop?
C884 EXX Bank/unbank
C885 EX AF,AF' Swap
C886 LD E,A E = A
This entry point is used by the routine at dr_dispatch_filled.
dr_start_sky_fill C887 EX DE,HL Swap
C888 LD A,L L += 30
C889 ADD A,$1E
C88B LD L,A
C88C LD DE,$0000 Fill value for blank sky
The following value is tunnel related: 1 if in tunnel, 0 if not.
It alternates fast when there is a partial tunnel on screen.
C88F LD A,$00 A = <self modified>
C891 AND A Set flags
C892 JP Z,dr_chose_colour Jump if zero
In tunnel. Draw black scanlines for the sky instead of coloured.
C895 DEC DE $0000 -> $FFFF
dr_chose_colour C896 LD C,$0F Mask for later
Decrement the screen address.
dr_sky_fill_loop C898 LD A,H Save H in A
C899 DEC H Decrement row address
C89A AND C Extract low four bits of row address
C89B JR NZ,dr_sky_fill_scanline Jump to dr_sky_fill_scanline if non-zero (easy case)
Otherwise it was zero so will need extra work.
C89D LD A,L Decrement high three bits of the row address
C89E SUB $20
C8A0 LD L,A
C8A1 JR NC,dr_sky_fill_fix_address No carry, so ...
Exit.
C8A3 LD SP,$0000 Restore original SP (self modified)
C8A6 RET Return
dr_sky_fill_fix_address C8A7 LD A,H Didn't carry so fix H from earlier DEC H (1110xxxx -> 1111xxxx)
C8A8 ADD A,$10
C8AA LD H,A
Writes DE to HL 15 times filling the scanline. Draws the blank upper part of the sky. DE must always be zero? or what about tunnels?
dr_sky_fill_scanline C8AB LD SP,HL Put it in SP (so we can use PUSH for speed)
C8AC PUSH DE Write 30 bytes of sky pixels
C8AD PUSH DE
C8AE PUSH DE
C8AF PUSH DE
C8B0 PUSH DE
C8B1 PUSH DE
C8B2 PUSH DE
C8B3 PUSH DE
C8B4 PUSH DE
C8B5 PUSH DE
C8B6 PUSH DE
C8B7 PUSH DE
C8B8 PUSH DE
C8B9 PUSH DE
C8BA PUSH DE
C8BB JP dr_sky_fill_loop Loop
Prev: C2E7 Up: Map Next: C8BE