.MoveHorizon LDA #60 \ Set A = 60 - horizonLine SEC \ SBC horizonLine \ So A is larger when the horizon is low (i.e. when we \ are cresting a hill), and smaller when the horizon is \ high (i.e. when we are in a dip) BPL hori1 \ If A >= 0, then horizonLine <= 60, so jump to hori1 CMP #&F5 \ If A >= -11, then horizonLine <= 71, so jump to hori2 BCS hori2 \ with the C flag set LDA #&F5 \ Otherwise set A = -11 and set the C flag, so A has a SEC \ minimum value of -11 BCS hori2 \ Jump to hori2 (this BCS is effectively a JMP as we \ just set the C flag) .hori1 \ If we get here then A >= 0, i.e. horizonLine <= 60 CMP #18 \ If A < 18, jump to hori2 to skip the following two BCC hori2 \ instructions LDA #18 \ Otherwise set A = 18 and clear the C flag, so A has a CLC \ maximum value of 18 .hori2 PHP \ Store the C flag on the stack, which will be clear if \ A >= 0, or set if A < 0 (so the C flag is effectively \ the sign bit of A) STA U \ Set (U A) = (A 0) LDA #0 \ = A * 256 \ \ where -11 <= A < 18 and the sign bit of A is in C ROR U \ Set (U A) = (U A) >> 1, inserting the sign bit from C ROR A \ into bit 7 PLP \ Set the C flag to the sign bit once again ROR U \ Set (U A) = (U A) >> 1, inserting the sign bit from C ROR A \ into bit 7 \ \ So by this point, we have: \ \ (U A) = A * 256 / 4 \ = A * 64 \ \ with the correct sign, so (U A) is in the range -704 \ to 1152, and is larger when the horizon is low (i.e. \ when we are cresting a hill), and smaller when the \ horizon is high (i.e. when we are in a dip) \ \ We now add this figure to screenTimer1, which \ determines the height of the horizon portion of the \ custom screen mode, i.e. where the palette switches \ from blue sky to the green ground \ \ So when we are cresting a hill, (U A) is large and so \ is timer 1, and therefore so is the size of the sky \ above the horizon in section 2 of the screen, so the \ horizon dips down \ \ Conversely, when we are in a dip, (U A) is small and \ so is timer 1, so the size of the sky section above \ the horizon is smaller, so the horizon rises up \ \ The range of screenTimer1 values from the following \ calculation is therefore: \ \ Minimum: &04D8 - 704 = &0218 (we are in a dip) \ \ Maximum: &04D8 + 1152 = &0958 (we are on a hill) SEI \ Disable interrupts so we can update the custom screen \ variables CLC \ Set screenTimer1 = (U A) + &04D8 ADC #&D8 \ STA screenTimer1 \ starting with the low bytes LDA #&04 \ And then the high bytes ADC U STA screenTimer1+1 CLI \ Re-enable interrupts RTS \ Return from the subroutineName: MoveHorizon [Show more] Type: Subroutine Category: Screen mode Summary: Move the position of the horizon palette switch up or down, depending on the current track pitch angle Deep dive: Hidden secrets of the custom screen modeContext: See this subroutine in context in the source code References: This subroutine is called as follows: * MainDrivingLoop (Part 2 of 5) calls MoveHorizon
[X]
Label hori1 is local to this routine
[X]
Label hori2 is local to this routine
[X]
Variable horizonLine in workspace Zero page
The track line number of the horizon
[X]
Variable screenTimer1 (category: Screen mode)
The screen timer offset between the start of section 2 and the start of section 3