Skip to navigation

Lander on the Acorn Archimedes

Landscape: DrawLandscapeAndBuffers (Part 2 of 4)

Name: DrawLandscapeAndBuffers (Part 2 of 4) [Show more] Type: Subroutine Category: Landscape Summary: Draw a row of landscape tiles Deep dive: Drawing the landscape Depth-sorting with the graphics buffers
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
\ We're now ready to iterate through the \ landscape, from left to right and back to \ front, looping back to land1 after \ processing each corner row .land1 LDRB R1, [R11, #tileCornerRow] \ Set R1 to the number of the tile corner \ row we are currently processing LDR R0, landscapeConfigAddr \ Set R0 to the address of the pair of ADD R0, R0, R1, LSL #1 \ bytes in the landscapeConfig table for the \ tile row number in R1 LDRB R10, [R0, #1] \ Set R10 to the second byte from the pair \ in landscapeConfig, which is the number \ of tile corners in the row \ \ We now use R10 as a loop counter when \ working our way along the row, counting \ tile corners as we progress LDRB R0, [R0] \ Set unusedConfig to the first byte from STRB R0, [R11, #unusedConfig] \ the pair in landscapeConfig, though this \ value is not used, so this has no effect ADD R0, R11, #xLandscapeRow \ Fetch the coordinate from (xLandscapeRow, LDMIA R0, {R0-R2} \ yLandscapeRow, zLandscapeRow) into \ (R0, R1, R2), so they contain the \ coordinates of the left end of the corner \ row that we need to process ADD R4, R11, #xLandscapeCol \ Store the coordinates in (xLandscapeCol, STMIA R4, {R0-R2} \ yLandscapeCol, zLandscapeCol) so we can \ start processing from the left end of this \ tile corner row, using these coordinates \ as we work through the columns, updating \ yLandscapeCol with the landscape height as \ we go LDR R8, [R11, #xCameraTile] \ Set R8 = xCameraTile - LANDSCAPE_X, so SUB R8, R8, #LANDSCAPE_X \ R8 is now the coordinate of the tile \ corner at the left end of the corner row, \ as subtracting the offset of the landscape \ effectively moves the camera to the left \ by that amount MOV R0, #&80000000 \ Set previousColumn = &80000000 to denote STR R0, [R11, #previousColumn] \ that we don't have corner coordinates from \ the previous column yet (as we are \ starting a new row) \ We now do the following loop R10 times, \ once for each of the tile corners in the \ row, looping back to land2 as we move \ right through the columns .land2 BL GetLandscapeAltitude \ Set R0 to the altitude of the landscape at \ coordinates (x, z) = (R8, R9), which is \ the current corner on this row LDR R14, [R11, #yCamera] \ Set yLandscapeCol = R0 - yCamera SUB R0, R0, R14 \ = altitude - yCamera STR R0, [R11, #yLandscapeCol] \ \ So this stores the y-coordinate of the \ landscape at this point, as we're seeing \ it from the point of view of the camera \ (so this will move it down the screen if \ the player is flying high, for example) ADD R0, R11, #xLandscapeCol \ Set R0 to the address of xLandscapeCol BL ProjectVertexOntoScreen \ Project (xLandscapeCol, yLandscapeCol, \ zLandscapeCol) onto the screen, returning \ the results in (R0, R1), so this projects \ the tile corner as it sits on the \ landscape \ \ This also sets the C flag if the vertex is \ too far away to draw BCS land4 \ If the vertex is too far away to draw then \ jump to land4 to skip the following STMIA R7!, {R0-R1} \ Store the corner coordinates in (R0, R1) \ in R7, updating R7 as we go, as R7 is \ where we store the tile corner pixel \ coordinates as we go (so this stores the \ corner coordinates in either cornerStore1 \ or cornerStore2, so we can fetch them when \ we process the next tile corner row) CMP R6, #0 \ If R6 = 0 then this is either the very BEQ land4 \ first tile corner row, or we have already \ fetched all the data for the previous row \ from the storage at R6 \ \ In either case, jump to land4 to skip \ drawing this tile as we can't draw tiles \ without the corresponding corner \ coordinates from the previous row and \ previous column LDMIA R6!, {R2-R3} \ Load the corner pixel coordinates from R6 \ into (R2, R3), updating R6 as we go, so \ this fetches the corresponding corner \ pixel coordinates from the previous tile \ corner row (i.e. from the opposite corner \ store to the one where we just stored this \ row's coordinate) CMP R2, #&80000000 \ If R2 = &80000000 then we have reached the MOVEQ R6, #0 \ end of the storage in R6, so set R6 = 0 BEQ land4 \ to prevent any more access attempts from \ the storage in R6, and jump to land4 to \ skip drawing this tile \ If we get here then we have the \ following pixel corner coordinates \ calculated: \ \ (R0, R1) = new corner from this row \ \ (R2, R3) = corresponding corner from \ previous row (i.e. the corner \ that's back by one row) STMFD R13!, {R6-R8} \ Store the registers that we want to use on \ the stack so they can be preserved ADD R14, R11, #previousColumn \ We now need to fetch the previous corners, LDMIA R14, {R4-R7} \ looking left along the tile row to the \ previous column of corners, so we can draw \ a tile from there to the new corner \ \ We will have stored these previous corners \ in the previousColumn table in the \ previous iteration, so fetch them into \ R4 to R7 like this: \ \ (R4, R5) = corner from the column to the \ left on this row \ \ (R6, R7) = corresponding corner from the \ previous row STMIA R14, {R0-R3} \ Store the new corners from this corner row \ in (R0, R1) and (R2, R3) in previousColumn \ so we can fetch them in the next iteration \ in the same way CMP R4, #&80000000 \ If R4 = &80000000 then this is actually BEQ land3 \ the first column of corner coordinates in \ this row, so we can't yet draw the tile, \ so jump to land3 to skip the drawing part \ If we get here then we actually have a \ tile to draw BL GetLandscapeTileColour \ Calculate the tile colour, depending on \ the slope, and return it in R8 BL DrawQuadrilateral \ Draw the tile by drawing a quadrilateral \ in colour R8 with corners at: \ \ (R0, R1) = the corner we're processing \ (R2, R3) = same corner in previous row \ (R4, R5) = previous column in this row \ (R6, R7) = previous row, previous column \ \ So this draws the tile we want on-screen .land3 LDMFD R13!, {R6-R8} \ Retrieve the registers that we stored on \ the stack .land4 SUBS R10, R10, #1 \ Decrement the loop counter in R10, which \ counts the number of tile corners in this \ row LDRNE R0, [R11, #xLandscapeCol] \ If we haven't yet processed all the tile ADDNE R0, R0, #TILE_SIZE \ corners in this row, add a tile's width to STRNE R0, [R11, #xLandscapeCol] \ xLandscapeCol and R8 to move them along ADDNE R8, R8, #TILE_SIZE \ the row to the next tile corner, and jump BNE land2 \ back to land2 to process the next corner \ By this point have drawn all the tiles in \ this row, so we now move on to the objects \ in the graphics buffers