.ProcessTileData STA processAction \ Store the action in processAction for later \ We now loop through all the tiles in the landscape \ \ The landscape consists of 31x31 square tiles, like a \ chess board that's sitting on a table in front of us, \ going into the screen \ \ The landscape is defined by the altitudes of the \ corners of each of the tile, so that's a 32x32 grid of \ altitudes \ \ The x-axis is along the front edge, from left to \ right, while the z-axis goes into the screen, away \ from us \ \ We iterate through the tile corners with a nested \ loop, with zTile going from 31 to 0 (so that's from \ back to front) \ \ For each zTile, xTile also goes from 31 to 0, so \ that's from right to left \ \ So we work through the landscape, starting with the \ row of tile corners at the back (which we work through \ from right to left), and then doing the next row \ forward, looping until we reach the front row LDA #31 \ Set zTile = 31 so we start iterating from the back row STA zTile \ (so zTile iterates from 31 to 0 in the outer loop) .proc1 LDA #31 \ Set xTile = 31 so we start iterating from the right STA xTile \ end of the current row (so xTile iterates from 31 to 0 \ in the inner loop) .proc2 JSR GetTileData \ Set A to the tile data for the tile anchored at \ (xTile, zTile), which we ignore, but this also sets \ the tile page in tileDataPage and the index in Y, so \ tileDataPage+Y now points to the tile data entry in \ the tileData table LDA processAction \ Set A to the argument that was passed to the routine \ and which we stored in processAction, \ \ This specifies how we process the tile data BEQ proc8 \ If processAction = 0 then jump to proc8 to zero the \ tile data for the tile anchored at (xTile, zTile) BMI proc7 \ If processAction = &80 then jump to proc7 to set the \ tile data for the tile anchored at (xTile, zTile) to \ the next number from the landscape's sequence of seed \ numbers \ If we get here then processAction must be 1 or 2 (as \ the routine is only ever called with A = 0, 1, 2 or \ &80) LSR A \ If processAction = 1 then this sets the C flag, \ otherwise processAction = 2 and this clears the C flag LDA (tileDataPage),Y \ Set A to the tile data for the tile anchored at \ (xTile, zTile) BCS proc3 \ If the C flag is set then processAction = 1, so jump \ to proc3 \ If we get here then processAction = 2, so now we swap \ the high and low nibble of the tile data LSR A \ Set bits 0-3 of T to the high nibble (bits 4-7) of the LSR A \ tile data in A LSR A LSR A STA T LDA (tileDataPage),Y \ Set A once again to the tile data for the tile \ anchored at (xTile, zTile) ASL A \ Set bits 4-7 of A to the low nibble (bits 0-3) of the ASL A \ tile data in A ASL A ASL A ORA T \ Merge A and T, so A now contains its original high \ nibble in bits 0-3 (from T) and its original low \ nibble in bits 4-7 (from A) \ \ So this swaps the high and low nibbles around in the \ tile data in A JMP proc8 \ Jump to proc8 to store A as the tile data for the tile \ we are processing .proc3 \ If we get here then processAction = 1, so we now do \ various manipulations, including multiplying the \ tile data by the multiplier in tileDataMultiplier \ and capping the result to a positive number between \ 1 and 11 \ \ At this point the tile data contains a seed number, \ so this process converts it into a value that we can \ use as the altitude of the tile corner SEC \ Set A = tile data - 128 SBC #128 PHP \ Store the flags from the subtraction, so we can set \ the sign of the scaled altitude below BPL proc4 \ If the result of the subtraction in A is positive, \ skip the following as A is already positive EOR #%11111111 \ The result in A is negative, so negate it using two's CLC \ complement, so we have: ADC #1 \ \ A = |tile data - 128| \ \ This negation reflects negative altitudes from below \ sea level to the equivalent altitude above sea level .proc4 STA U \ Set U = A \ = |tile data - 128| LDA tileDataMultiplier \ Set A to the multiplier that we need to apply to the \ tile data, which is in the range 14 to 36 JSR Multiply8x8 \ Set (A T) = A * U \ = tileDataMultiplier * |tile data - 128| PLP \ Restore the flags from the subtraction above, so \ the N flag contains the sign of (tile data - 128) \ (clear if it is positive, set if it is negative) JSR Absolute16Bit \ Set the sign of (A T) to match the result of the \ subtraction above, so we now have: \ \ (A T) = tileDataMultiplier * (tile data - 128) \ So if the original tile data represents a landscape \ altitude, with "sea level" at altitude 128, then the \ high byte of this calculation in A represents a \ scaling of the altitude by tileDataMultiplier / 256, \ with the scaling centred around sea level \ \ This means that mountain peaks get higher and marine \ trenches get deeper, stretching away from sea level \ at altitude 128 in the original data \ \ As tileDataMultiplier is in the range 14 to 36, this \ transforms the tile data values as follows: \ \ * Values start out in the range 0 to 255 \ \ * Converting to |tile data - 128| translates them \ into values in the range 0 to 127, representing \ magnitudes of altitude (0 = sea level, 127 = top \ of Everest or bottom of Mariana Trench, stack \ contains flags denoting high altitude or murky \ depths) \ \ * Multiplying by 14/256 (the minimum multiplier) \ changes the range into 0 to 6 \ \ * Multiplying by 36/256 (the maximum multiplier) \ changes the range into 0 to 17 \ \ * Reapplying the sign converts the magnitudes back \ into depths or heights \ \ So the above takes the seed numbers in the original \ tile data and transforms then into values of A with a \ maximum range of -17 to +17 (for higher multipliers) \ or -6 to +6 (for lower multipliers) \ \ We now take this result and do various additions and \ cappings to change the result into a positive number \ between 1 and 11 CLC \ Set A = A + 6 ADC #6 \ \ So the ranges for A are now: \ \ * Minimum multiplier range is -1 to +13 \ \ * Maximum multiplier range is -11 to +23 BPL proc5 \ If A is positive then jump to proc5 to skip the \ following LDA #0 \ Otherwise A is negative, so set A = 0 .proc5 \ By this point A is a positive number and the ranges \ for A are now: \ \ * Minimum multiplier range is 0 to 13 \ \ * Maximum multiplier range is 0 to 23 CLC \ Set A = A + 1 ADC #1 \ By this point A is a positive number and the ranges \ for A are now: \ \ * Minimum multiplier range is 1 to 14 \ \ * Maximum multiplier range is 1 to 24 CMP #12 \ If A < 12 then jump to proc6 to skip the following BCC proc6 LDA #11 \ Otherwise A >= 12, so set A = 11 .proc6 \ By this point, A is a positive number between 1 and 11 \ \ For minimum values of the multiplier we have only lost \ the very low and very high values in the range \ \ For maximum values of the multiplier we have lost \ around one-third at the top end and one-third at the \ bottom end \ \ We can now use this as the altitude of the tile \ corner, which we can feed into the smoothing routines \ to generate a gently rolling landscape that is \ suitable for the game JMP proc8 \ Jump to proc8 to store A as the tile data for the tile \ we are processing .proc7 \ If we get here then the argument in A is &80, so we \ fill the tile data table with seed numbers JSR GetNextSeedNumber \ Set A to the next number from the landscape's sequence \ of seed numbers .proc8 STA (tileDataPage),Y \ Store A as the tile data for the tile anchored at \ (xTile, zTile) DEC xTile \ Decrement the tile x-coordinate in the inner loop BPL proc2 \ Loop back until we have processed all the tiles in the \ tile row at z-coordinate zTile, working from right to \ left DEC zTile \ Decrement the outer loop counter BPL proc1 \ Loop back until we have processed all the tile rows in \ the landscape, working from the back row of the \ landscape all the way to the front row \ Note that by this point the N flag is set, which means \ a BMI branch would be taken (this is important when \ analysing the intentionally confusing flow of the main \ title loop created by the stack modifications in the \ GenerateLandscape, SmoothTileCorners and JumpToPreview \ routines) RTS \ Return from the subroutineName: ProcessTileData [Show more] Type: Subroutine Category: Landscape Summary: Process the tile data for all tiles in the landscapeContext: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawTitleScreen calls ProcessTileData * GenerateLandscape calls ProcessTileData
Arguments: A Controls what we do to the tile data: * 0 = zero all the tile data * 1 = scale all the tile data by the multiplier in tileDataMultiplier before capping it to a value between 1 and 11 * 2 = swap the high and low nibbles of all the tile data * &80 = set the tile data to the next set of numbers from the landscape's sequence of seed numbers
Returns: N flag The N flag is set (so a BMI branch will be taken)
[X]
Subroutine Absolute16Bit (category: Maths (Arithmetic))
Calculate the absolute value (modulus) of a 16-bit number
[X]
Subroutine GetNextSeedNumber (category: Maths (Arithmetic))
Set A to a seed number
[X]
Subroutine GetTileData (category: Landscape)
Get the tile data and tile data address for a specific tile
[X]
Subroutine Multiply8x8 (category: Maths (Arithmetic))
Calculate (A T) = T * U
[X]
Label proc1 is local to this routine
[X]
Label proc2 is local to this routine
[X]
Label proc3 is local to this routine
[X]
Label proc4 is local to this routine
[X]
Label proc5 is local to this routine
[X]
Label proc6 is local to this routine
[X]
Label proc7 is local to this routine
[X]
Label proc8 is local to this routine
[X]
Variable processAction in workspace Zero page
Defines the following
[X]
Variable tileDataMultiplier in workspace Main variable workspace
A multiplier that we apply to the altitudes of the tile corners to alter the steepness of the landscape during landscape generation
[X]
Variable tileDataPage in workspace Zero page
The address of the tileData page containing the current tile's data