Prev: C15B Up: Map Next: C452
C2E7: Subroutine of draw_road
Fills the road edge position tables for a section where the road is narrowing or widening, interpolating the edge x positions between two height table entries in Bresenham fashion and writing them through an SP-based pointer.
It is called around changes in lanes, e.g. at the start of a level, after a split, before a tunnel, after a tunnel or when the final loop restarts.
Used by the routine at draw_road.
Input
IX ... sampled: $EE60.. (road buffer lane data pointer)
IY ... sampled: $E301..E315 (height table pointer)
draw_road_lanes_change C2E7 LD A,IYl Load IY.low (distance)
C2E9 CP $13 Compare to 19
C2EB JP NC,drlc_16 Jump to exit if >= 19
C2EE EX AF,AF' Bank distance
C2EF LD A,(IX+$00) Load lane flags from IX[0]
C2F2 LD L,A Copy to L
C2F3 AND $0C Mask with 0b00001100
C2F5 JP Z,drlc_16 Jump to exit if zero
Otherwise ...
C2F8 DEC IY Decrement height table pointer
C2FA BIT 5,L Bit 5 of L set?
C2FC JR Z,drlc_1 Jump if clear
C2FE BIT 7,L Bit 7 of L set?
C300 LD H,$EC H = $EC -- must be a top byte of address
C302 JR NZ,drlc_1 Jump if set
C304 DEC H H = $EB
drlc_1 C305 BIT 4,L Bit 4 of L set?
C307 JP Z,drlc_4 Jump if clear
C30A EX AF,AF' Unbank distance / bank masked-lane-flags
C30B CP $02 Compare to 2
C30D JP NC,drlc_3 Jump if >= 2
C310 EX AF,AF' Bank distance again / unbank masked-lane-flags
C311 CP $04 Compare to 4
C313 LD A,$20 A = 32
C315 LD C,(IY+$01) C = IY[1]
C318 JR NZ,drlc_2 Jump if != 4
C31A XOR A A = 0
C31B LD C,(IY+$02) C = IY[2]
drlc_2 C31E LD ($C346),A Self modify 'ADD A,x' @ C345
C321 LD A,(IY+$00) A = IY[0] - C
C324 SUB C
C325 JP C,drlc_15 Jump if A was <= C
C328 JP Z,drlc_15
C32B LD C,A C = A
C32C ADD A,A B = A * 2
C32D LD B,A
C32E LD A,$60 L = ~(($60 - IY[0]) << 1)
C330 SUB (IY+$00)
C333 ADD A,A
C334 CPL
C335 LD L,A
C336 LD SP,HL -- why are we copying to SP with no push/pop nearby?
C337 LD D,(HL) DE = wordat(HL - 1);
C338 DEC L
C339 LD E,(HL)
C33A SUB B L = A - B
C33B LD L,A
C33C DEC H H--
C33D LD A,($A23F) A = (fast_counter ROR 3) & 0b00011100
C340 RRA
C341 RRA
C342 RRA
C343 AND $1C
C345 ADD A,$00 A += <self modified>
C347 LD ($C352),HL Self modify 'LD HL,x' @ C351 below -- stash left hand table ptr
C34A EX DE,HL Swap
C34B LD E,A DE = A
C34C LD D,$00
C34E SBC HL,DE HL -= DE
C350 EX DE,HL Swap
C351 LD HL,$0000 HL = <self modified>
C354 JP drlc_7 Jump
Another case.
drlc_3 C357 EX AF,AF' Bank
C358 CP $04 Compare to 4
C35A JP NZ,drlc_15 Jump if non-zero
C35D LD A,(IY+$00) A = IY[0] - IY[2]
C360 SUB (IY+$02)
C363 JP C,drlc_15 Jump if IY[0] was <= IY[2]
C366 JP Z,drlc_15
C369 LD C,A C = A
C36A ADD A,A B = A * 2
C36B LD B,A
C36C LD A,$60 L = ~(($60 - IY[0]) << 1)
C36E SUB (IY+$00)
C371 ADD A,A
C372 CPL
C373 LD L,A
C374 LD SP,HL -- this pattern again
C375 LD D,(HL) D = *HL
C376 DEC L L--
C377 LD E,(HL) E = *HL
C378 SUB B L = A - B
C379 LD L,A
C37A DEC H H--
C37B JP drlc_7 Jump
drlc_4 C37E EX AF,AF' Bank/unbank
C37F CP $02 Compare to 2
This entry point is used by the routine at diamond_transition_mask. (PHANTOM)
C381 JP NC,drlc_6 Jump if A >= 2
C384 EX AF,AF' Bank/unbank
C385 CP $04 Compare to 4
C387 LD A,$20 A = 32
C389 LD C,(IY+$01) C = IY[1]
C38C JR NZ,drlc_5 Jump if non-zero
C38E XOR A A = 0
C38F LD C,(IY+$02) C = IY[2]
drlc_5 C392 LD ($C3BE),A Self modify 'ADD A,x' @ C3BD below
C395 LD A,(IY+$00) A = IY[0]
C398 SUB C A -= C
C399 JP C,drlc_15 Jump if A was <= C
C39C JP Z,drlc_15
C39F LD C,A C = A << 1
C3A0 ADD A,A
C3A1 LD B,A B = A
C3A2 LD A,$60 L = ~(($60 - IY[0]) << 1)
C3A4 SUB (IY+$00)
C3A7 ADD A,A
C3A8 CPL
C3A9 LD L,A
C3AA LD SP,HL -- this pattern again (2)
C3AB DEC H H--
C3AC LD D,(HL) D = *HL
C3AD DEC L L--
C3AE LD E,(HL) E = *HL
C3AF SUB B L = A - B
C3B0 LD L,A
C3B1 INC H H++
C3B2 LD ($C3C5),HL Self modify 'LD HL,x' @ C3C4 below
C3B5 LD A,($A23F) A = (fast_counter ROR 3) & 0b00011100
C3B8 RRA
C3B9 RRA
C3BA RRA
C3BB AND $1C
C3BD ADD A,$00 A += <self modified>
C3BF LD L,A HL = A
C3C0 LD H,$00
C3C2 ADD HL,DE HL += DE
C3C3 EX DE,HL Swap
C3C4 LD HL,$0000 HL = <self modified>
C3C7 JP drlc_7 Jump
drlc_6 C3CA EX AF,AF' Swap
C3CB CP $04 Compare to 4
C3CD JR NZ,drlc_15 Jump if non-zero
C3CF LD A,(IY+$00) A = IY[0] - IY[2]
C3D2 SUB (IY+$02)
C3D5 JP C,drlc_15 Jump if IY[0] was <= IY[2]
C3D8 JP Z,drlc_15
C3DB LD C,A C = A
C3DC ADD A,A A <<= 1
C3DD LD B,A B = A
C3DE LD A,$60 L = ~(($60 - IY[0]) << 1)
C3E0 SUB (IY+$00)
C3E3 ADD A,A
C3E4 CPL
C3E5 LD L,A
C3E6 LD SP,HL -- this pattern again (3)
C3E7 DEC H H--
C3E8 LD D,(HL) D = *HL
C3E9 DEC L L--
C3EA LD E,(HL) E = *HL
C3EB SUB B L = A - B
C3EC LD L,A
C3ED INC H H++
Continuation point.
drlc_7 C3EE LD A,(HL) HL = wordat(HL); L--
C3EF DEC L
C3F0 LD L,(HL)
C3F1 LD H,A
C3F2 AND A Set/clear flags before SBC
C3F3 SBC HL,DE HL -= DE
C3F5 LD A,L A = L
C3F6 JP M,drlc_8 Jump if negative
C3F9 AND A Set flags from A
C3FA JP P,drlc_9 Jump if positive
C3FD LD A,$7F A = 127
C3FF JR drlc_9 Jump
Negative case.
drlc_8 C401 AND A Set flags
C402 JP M,drlc_9 Jump if negative
C405 LD A,$81 A = -127
Positive case.
drlc_9 C407 INC SP SP++
C408 BIT 5,(IX+$00) Bit 5 of IX[0] set?
C40C JR Z,drlc_10 Jump if clear
C40E LD HL,$FF00 Move SP 256 bytes back
C411 ADD HL,SP
C412 LD SP,HL
drlc_10 C413 LD L,A L = A
C414 LD B,C B = C
C415 LD A,C A = C
C416 BIT 7,L Bit 7 of L set?
C418 JR Z,drlc_11 Jump if clear
Otherwise negative
C41A LD A,L L = -L
C41B NEG
C41D LD L,A
C41E LD A,B A = B
C41F CP L Compare to L
C420 LD A,$1B Load opcode of 'DEC DE'
C422 JR C,drlc_alt_bresenham Jump if prev A was < L
C424 JR drlc_self_modify Jump
drlc_11 C426 CP L Compare to L
C427 LD A,$13 Load opcode of 'INC DE'
C429 JR C,drlc_alt_bresenham Jump if prev A was < L
drlc_self_modify C42B LD ($C435),A Self modify instruction at C435 below
C42E LD A,B A = B >> 1
C42F RRA
drlc_bresenham_loop C430 ADD A,L A = L
C431 CP C Compare to C
C432 JR C,drlc_14 Jump if A < C
C434 SUB C A -= C
C435 INC DE <self modified instruction> DE++ or DE--
drlc_14 C436 PUSH DE Stack DE
C437 DJNZ drlc_bresenham_loop Loop
drlc_15 C439 INC IY IY++
Four lane highway?
drlc_16 C43B LD HL,$C534 Set instruction C4B2 to call dr_four_lane_highway/dr_four_lane_highway
C43E JP dr_set_lane_callback Jump
drlc_alt_bresenham C441 LD ($C445),A Self modify instruction at drlc_alt_bresenham_loop
C444 XOR A A = 0 -- init counter
drlc_alt_bresenham_loop C445 INC DE <self modified instruction> DE++ or DE--
C446 ADD A,C A += C
C447 JR C,drlc_19 Jump if carry
C449 CP L Compare to L
C44A JR C,drlc_alt_bresenham_loop Loop if A < L
drlc_19 C44C SUB L A -= L
C44D PUSH DE Stack DE
C44E DJNZ drlc_alt_bresenham_loop Loop
C450 JR drlc_15 Jump to exit
Prev: C15B Up: Map Next: C452