Prev: C0E1 Up: Map Next: C2E7
C15B: Tunnel entrance/interior/exit drawing code
Called by 8F82 etc. when that's self modified to call here.
It draws the entrance, the interior and the far wall into the back buffer for the current road scanline, in three fill phases from back to front, each using the PUSH table trick. The main body fills from the left edge and from the right; the transition rows fill from the right only, with C set to $0F so every row is masked; and the far wall fills from the right only, at a depth set by the far wall mode. The horizontal extents of the fills come from the centre right and left x-position tables, which give the columns of the two tunnel walls.
Input
IY e.g. $E315 buffer
draw_tunnel C15B LD A,IYl Load IY's low byte -- it's a size/distance value
This is set to ~20 then counts down to ~9 as the tunnel is entered. (I've noted 15..6 elsewhere).
C15D CP $00 Compare to <self modified>
C15F RET NZ Return if not equal
C160 LD A,$00 Load <self modified>
C162 LD D,$EE Set fill value to use for striped tunnel entrance to $EE
C164 DEC A Decrement A
C165 JR Z,dt_fill_chosen Jump if zero
C167 LD D,$FF Set fill value to use for (much of) tunnel interior to $FF
dt_fill_chosen C169 LD E,D Widen fill value to $EEEE or $FFFF
C16A LD ($C21D),DE Self modify 'LD DE,x' @ C21C
C16E LD ($C2E4),SP Save SP to restore on exit (self modify)
C172 LD A,(IY+$4E) L = ~((IY[$4E] - 2) << 1)
C175 SUB $02
C177 ADD A,A
C178 CPL
C179 LD L,A
C17A LD C,$00 Clear C
C17C LD H,$EB Set HL to $EBxx
C17E LD A,(HL) Load byte at $EBxx
C17F OR A Set flags
C180 JP Z,dt_c18e Jump if zero
This path is hit only when the tunnel is entered.
C183 LD D,$10 D = 16 = jump table target
C185 JP P,dt_c19c Jump if positive
dt_c188 C188 LD D,$16 D = 22 = jump table target
C18A LD L,$1F L = 31
C18C JR dt_c1c8 Jump
dt_c18e C18E DEC L A = HL[-1]
C18F LD A,(HL)
C190 INC L
C191 AND $F8 Divide by 8
C193 RRCA
C194 RRCA
C195 RRCA
C196 SRL A A >>= 1
C198 RR C Rotate C
C19A INC A A++
C19B LD D,A D = A
dt_c19c C19C LD H,$E8 H = $E8
C19E LD A,(HL) A = *HL
C19F OR A Set flags
C1A0 JR Z,dt_c1aa Jump if zero
C1A2 LD E,$10 E = 16
C1A4 JP M,dt_c1bc Jump if negative
C1A7 JP dt_c188 Jump
dt_c1aa C1AA DEC L L--
C1AB LD A,(HL) A = *HL + 8
C1AC ADD A,$08
C1AE JR C,dt_c188 Jump if carry
C1B0 AND $F8 Divide by 8
C1B2 RRCA
C1B3 RRCA
C1B4 RRCA
C1B5 LD B,A B = A
C1B6 SRL A E = 16 - (A >> 1)
C1B8 CPL
C1B9 ADD A,$11
C1BB LD E,A
dt_c1bc C1BC LD A,$20 A = 32 - B
C1BE SUB B
C1BF LD L,$20 L = 32
C1C1 RL C Rotate left
C1C3 JR C,dt_c1c7 Jump if carry
C1C5 DEC L L--
C1C6 DEC A A--
dt_c1c7 C1C7 LD C,A C = A
dt_c1c8 C1C8 LD A,D A = D
C1C9 LD ($C222),A Self modify 'JR x' @ dt_jump_table_1 -- jump table target
C1CC LD A,E A = E
C1CD LD ($C237),A Self modify 'JR x' @ dt_jump_table_2 -- jump table target
C1D0 LD A,(IY+$35) A = IY[$35]
C1D3 LD B,A B = A
C1D4 AND $0F H = (A & 15) + $F0
C1D6 ADD A,$F0
C1D8 LD H,A
C1D9 LD A,B A = ((B & $70) << 1) + L
C1DA AND $70
C1DC ADD A,A
C1DD ADD A,L
C1DE JR NC,dt_c1e1 Jump if no carry
C1E0 DEC A A--
dt_c1e1 C1E1 LD L,A L = A
C1E2 LD A,$80 A = 128 - B
C1E4 SUB B
C1E5 EX AF,AF' Bank/unbank
C1E6 LD A,($A23F) E = fast_counter & $E0
C1E9 AND $E0
C1EB LD E,A
C1EC RRC E E >>= 2
C1EE RRC E
C1F0 SUB E A -= E
C1F1 RRC E E >>= 2
C1F3 RRC E
C1F5 SUB E A -= E
C1F6 ADD A,IYl A += IY.low
C1F8 LD D,$E6 D = $E6
C1FA LD E,A E = A
C1FB LD A,(IY+$00) B = IY[0] - B
C1FE SUB B
C1FF LD B,A
C200 LD A,(DE) A = *DE
C201 LD E,A E = A
C202 LD A,IYl A = (16 - IY.low) + E
C204 CPL
C205 ADD A,$11
C207 ADD A,E
C208 EXX Bank/unbank
C209 LD B,A B = A
C20A EXX Bank/unbank
C20B SUB B A -= B
C20C LD D,A D = A
C20D EX AF,AF' Bank/unbank
C20E ADD A,D A = D
C20F JP P,dt_c21a Jump if positive
C212 LD E,A E = A
C213 SUB $81 A -= $81
C215 NEG A = -A
C217 ADD A,D A += D
C218 LD D,A D = A
C219 LD A,E A = E
dt_c21a C21A EX AF,AF' Bank/unbank
C21B LD B,D B = D
Pixels of tunnel loaded here. Top byte, D, seems to affect bottom row? Bottom byte, E, affects whole pattern. The LD E,D later would explain that.
C21C LD DE,$EEEE DE = <self modified> -- pixels of tunnel
Loop
dt_fill_loop C21F LD SP,HL Put destination in SP so we can use PUSH for speed
C220 LD A,L Preserve destination?
dt_jump_table_1 C221 JR dt_jump_table_1 Jump table (self modified)
C223 PUSH DE Store up to 16 words / 256 pixels
C224 PUSH DE
C225 PUSH DE
C226 PUSH DE
C227 PUSH DE
C228 PUSH DE
C229 PUSH DE
C22A PUSH DE
C22B PUSH DE
C22C PUSH DE
C22D PUSH DE
C22E PUSH DE
C22F PUSH DE
C230 PUSH DE
C231 PUSH DE
C232 PUSH DE
C233 SUB C A -= C
C234 LD L,A Restore destination?
C235 LD SP,HL Put destination in SP so we can use PUSH for speed
dt_jump_table_2 C236 JR dt_jump_table_2 Jump table (self modified)
C238 PUSH DE Store up to 16 words / 256 pixels
C239 PUSH DE
C23A PUSH DE
C23B PUSH DE
C23C PUSH DE
C23D PUSH DE
C23E PUSH DE
C23F PUSH DE
C240 PUSH DE
C241 PUSH DE
C242 PUSH DE
C243 PUSH DE
C244 PUSH DE
C245 PUSH DE
C246 PUSH DE
C247 PUSH DE
C248 ADD A,C A += C
C249 LD L,A L = A
Move to next scanline (shorter form).
C24A LD A,H Save for checking in a moment
C24B DEC H Move to next scanline (visually upwards)
C24C AND $0F Would it have rolled over into the top nibble?
C24E JP NZ,dt_c25b No - continue
It rolled over.
C251 LD A,L Move to next chunk of 16 scanlines
C252 SUB $20
C254 LD L,A
C255 JR C,dt_c25b Jump if carry
Otherwise have to compensate 1111 field.
C257 LD A,H Put back the bit stolen since BAAA field was zero
C258 ADD A,$10
C25A LD H,A
dt_c25b C25B RLC D
C25D LD E,D E = D
C25E DJNZ dt_fill_loop Loop
C260 EXX Bank/unbank
C261 SRL B B >>= 1
C263 LD A,B A = B
C264 SRL B B >>= 2
C266 SRL B
C268 SUB B A -= B
C269 LD B,A B = A
C26A EX AF,AF' Bank/unbank
C26B AND A Set flags
C26C JP M,dt_exit Jump if negative
C26F ADD A,B A += B
C270 JP P,dt_c27b Jump if positive
C273 LD E,A E = A
C274 SUB $81 A -= $81
C276 NEG A = -A
C278 ADD A,B A = B
C279 LD B,A B = A
C27A LD A,E A = E
dt_c27b C27B EX AF,AF' Bank/unbank
C27C LD A,B A = B
C27D EXX Bank/unbank
C27E LD B,A B = A
C27F LD A,L A = L
C280 AND $0F A &= 15
C282 JR NZ,dt_c285 Jump if non-zero
C284 DEC L L--
dt_c285 C285 LD C,$0F C = 15
Loop
dt_jump_table_3 C287 LD SP,HL Put it in SP (so we can use PUSH for speed)
C288 PUSH DE
C289 PUSH DE
C28A PUSH DE
C28B PUSH DE
C28C PUSH DE
C28D PUSH DE
C28E PUSH DE
C28F PUSH DE
C290 PUSH DE
C291 PUSH DE
C292 PUSH DE
C293 PUSH DE
C294 PUSH DE
C295 PUSH DE
C296 PUSH DE
Move to next scanline (shorter form).
C297 LD A,H Save for checking in a moment
C298 DEC H Move to next scanline (visually upwards)
C299 AND C Would it have rolled over into the top nibble? (C is a mask, 15, here)
C29A JP NZ,dt_c2a7 No - continue
It rolled over.
C29D LD A,L Move to next chunk of 16 scanlines
C29E SUB $20
C2A0 LD L,A
C2A1 JR C,dt_c2a7 Carry set if CCC field was zero - don't compensate 1111 field and continue
Otherwise have to compensate 1111 field.
C2A3 LD A,H Put back the bit stolen since BAAA field was zero
C2A4 ADD A,$10
C2A6 LD H,A
dt_c2a7 C2A7 RLC D
C2A9 LD E,D E = D
C2AA DJNZ dt_jump_table_3 Loop
C2AC EX AF,AF'
C2AD AND A Set flags
C2AE JP M,dt_exit Jump if negative
C2B1 CPL B = ~A + $82
C2B2 ADD A,$82
C2B4 LD B,A
C2B5 LD DE,$0000 DE = 0
C2B8 LD A,$00 A = <self modified>
C2BA AND A Set flags
C2BB JR Z,dt_jump_table_4 Jump if zero
C2BD DEC A A--
C2BE JR NZ,dt_exit Jump if non-zero
C2C0 DEC DE DE--
dt_jump_table_4 C2C1 LD SP,HL Put it in SP (so we can use PUSH for speed)
C2C2 PUSH DE
C2C3 PUSH DE
C2C4 PUSH DE
C2C5 PUSH DE
C2C6 PUSH DE
C2C7 PUSH DE
C2C8 PUSH DE
C2C9 PUSH DE
C2CA PUSH DE
C2CB PUSH DE
C2CC PUSH DE
C2CD PUSH DE
C2CE PUSH DE
C2CF PUSH DE
C2D0 PUSH DE
Move to next scanline (shorter form).
C2D1 LD A,H Save for checking in a moment
C2D2 DEC H Move to next scanline (visually upwards)
C2D3 AND C Would it have rolled over into the top nibble? (C is a mask, 15, here)
C2D4 JP NZ,dt_next No - continue
It rolled over.
C2D7 LD A,L Move to next chunk of 16 scanlines
C2D8 SUB $20
C2DA LD L,A
C2DB JR C,dt_next Carry set if CCC field was zero - don't compensate 1111 field and continue
Otherwise have to compensate 1111 field.
C2DD LD A,H Put back the bit stolen since BAAA field was zero
C2DE ADD A,$10
C2E0 LD H,A
dt_next C2E1 DJNZ dt_jump_table_4 Next scanline ?
dt_exit C2E3 LD SP,$0000 Restore original SP (self modified)
C2E6 RET Return
Prev: C0E1 Up: Map Next: C2E7