\ If we get here then bit 6 of processAction is set, so \ we smooth the tile strip by moving each outlier tile \ to the altitude of its closest immediate neighbour (in \ terms of altitude) \ \ This smoothes out single-point spikes or troughs LDX #31 \ We now work our way along the strip, smoothing the \ altitudes of tiles 1 to 32, so set a tile counter in X \ \ Note that we smooth tiles 1 to 32 rather than tiles \ 0 to 31 (tile 0 remains unchanged by the smoothing \ process) .stri4 \ In the following, we are processing the tile at \ position X + 1, i.e. stripData+1,X \ \ We smooth a tile by looking at the altitudes of the \ two tiles either side of that tile, i.e. stripData,X \ and stripData+2,X \ \ We are smoothing from high values of X to low values, \ so by this point the tile at stripData+2,X has already \ been smoothed \ \ Let's name the tiles as follows: \ \ * stripData+2,X = "previous tile" (as it has already \ been smoothed) \ \ * stripData+1,X = "this tile" (as this is the tile \ we are smoothing) \ \ * stripData,X = "next tile" (as this is the tile \ we will be smoothing next) \ \ The smoothing algorithm is implemented as follows, \ where we are comparing the altitude of each tile (as \ at this stage tileData only contains tile altitudes): \ \ * If this = previous, do nothing \ \ * If this < previous and this >= next, do nothing \ \ * If this < previous and this < next, set \ this = min(previous, next) \ \ * If this > previous and this <= next, do nothing \ \ * If this > previous and this > next, set \ this = max(previous, next) \ \ Or to simplify: \ \ * If this tile is higher than both its neighbours, \ move it down until it isn't \ \ * If this tile is lower than both its neighbours, \ move it up until it isn't \ \ So this algorithm smoothes the landscape by squeezing \ the landscape into a flatter shape, moving outlier \ tiles closer to the landscape's overall line LDA stripData+1,X \ If this tile is at the same altitude as the previous CMP stripData+2,X \ tile, jump to stri9 to move on to smoothing the next BEQ stri9 \ tile, as the transition from the previous tile to this \ tile is already flat BCS stri5 \ If this tile is higher than the previous tile, jump to \ stri5 \ If we get here then this tile is lower than the \ previous tile CMP stripData,X \ If this tile is at the same altitude or higher than BEQ stri9 \ the next tile, jump to stri9 to move on to smoothing BCS stri9 \ the next tile \ If we get here then this tile is lower than the \ previous tile and lower than the next tile LDA stripData+2,X \ Set the flags from comparing the previous and next CMP stripData,X \ tiles (so in stri6, tile A is the previous tile and \ tile B is the next tile) JMP stri6 \ Jump to stri6, so that: \ \ * If previous < next, set this = previous \ \ * If previous >= next, set this = next \ \ In other words, set: \ \ this = min(previous, next) \ \ before moving on to the next tile .stri5 \ If we get here then this tile is higher than the \ previous tile CMP stripData,X \ If this tile is at the same altitude or lower than the BEQ stri9 \ next tile jump to stri9 to move on to smoothing the BCC stri9 \ next tile \ If we get here then this tile is higher than the \ previous tile and this tile is higher than the next \ tile LDA stripData,X \ Set the flags from comparing the next and previous CMP stripData+2,X \ tiles (so in stri6, tile A is the next tile and \ tile B is the previous tile) \ Fall through into stri6, so that: \ \ * If next < previous, set this = previous \ \ * If next >= previous, set this = next \ \ In other words, set: \ \ this = max(previous, next) \ \ before moving on to the next tile .stri6 \ We get here after comparing two tiles; let's call them \ tile A and tile B BCC stri7 \ If tile A is lower than tile B, jump to stri7 to set \ the altitude of this tile to the altitude of the \ previous tile LDA stripData,X \ Set A to the altitude of the next tile and jump to JMP stri8 \ stri8 to set the altitude of this tile to the altitude \ of the next tile .stri7 LDA stripData+2,X \ Set A to the altitude of the previous tile .stri8 STA stripData+1,X \ Set the altitude of this tile to the value in A .stri9 DEX \ Decrement the strip tile counter in X BPL stri4 \ Loop back until we have worked our way through the \ whole strip BIT doNotPlayLandscape \ If bit 7 of doNotPlayLandscape is set then we do not BMI stri10 \ want to play the landscape after generating it, so \ jump to stri10 to skip the following, leaving the \ stack unmodified \ \ This means that the JSR GenerateLandscape instruction \ that got us here will return normally, so the RTS at \ the end of the GenerateLandscape routine will behave \ as expected, like this: \ \ * If we called GenerateLandscape from the \ MainTitleLoop routine, then we return there to \ fall through into SecretCodeError, which displays \ the "WRONG SECRET CODE" error message for when the \ player enters an incorrect secret code \ \ * If we called GenerateLandscape from the \ FinishLandscape routine, then we return there to \ display the landscape's secret entry code \ on-screen, for when the player completes a level \ \ If bit 7 of doNotPlayLandscape is clear then we keep \ going to modify the return address on the stack, so \ that the RTS at the end of the GenerateLandscape takes \ us to the PreviewLandscape routine \ The above loop ended with X set to &FF, so &0100 + X \ in the following points to the top of the stack at \ &01FF LDA #HI(JumpToPreview) \ Set the return address on the bottom of the stack at STA &0100,X \ (&01FE &01FF) to JumpToPreview DEX \ LDA #LO(JumpToPreview) \ Note that when an RTS instruction is executed, it pops STA &0100,X \ the address off the top of the stack and then jumps to \ that address + 1, so putting the JumpToPreview address \ on the stack means that the RTS at the end of the \ GenerateLandscape routine will actually send us to \ address JumpToPreview+1 \ \ This is intentional and is intended to confuse any \ crackers who might have reached this point, because \ the JumpToPreview routine not only contains a JMP \ instruction at JumpToPreview, but it also contains a \ BMI instruction at JumpToPreview+1, if our crackers \ forgot about this subtlety of the RTS instruction, \ they might end up going down a rabbit hole .stri10 JMP stri16 \ Jump to stri16 to copy the tile data for the smoothed \ strip back into the tileData tableName: SmoothTileCorners (Part 2 of 4) [Show more] Type: Subroutine Category: Landscape Summary: Smooth a strip by moving each outlier tile corner to the altitude of its closest immediate neighbour (in terms of altitude)Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
This part smoothes the strip by working along the strip and applying the following algorithm: * If this tile corner is higher than both its neighbours, move it down * If this tile corner is lower than both its neighbours, move it up In each case, we move the tile corner until it is level with the closest one to its original altitude. This has the effect of smoothing out single-point spikes or troughs in the strip.
[X]
Subroutine JumpToPreview (category: Cracker protection)
An intentionally confusing jump point for controlling the main title loop flow when returning from the GenerateLandscape routine
[X]
Variable doNotPlayLandscape in workspace Main variable workspace
A flag that controls whether we preview and play the landscape after generating it
[X]
Label stri10 is local to this routine
[X]
Label stri16 in subroutine SmoothTileCorners (Part 4 of 4)
[X]
Label stri4 is local to this routine
[X]
Label stri5 is local to this routine
[X]
Label stri6 is local to this routine
[X]
Label stri7 is local to this routine
[X]
Label stri8 is local to this routine
[X]
Label stri9 is local to this routine
[X]
Variable stripData (category: Landscape)
Storage for tile data when smoothing strips of tiles during the landscape generation process