.DrawObjects STMFD R13!, {R5-R12, R14} \ Store the registers that we want to use on \ the stack so they can be preserved \ We are going to loop through every tile on \ the screen to check whether there are any \ corresponding objects in the object map, \ so we start by working out which entry in \ the object map corresponds to the far left \ corner at the back of the on-screen \ landscape view \ \ We work from back to front so that objects \ get drawn in that order, to ensure that \ distant objects always appear behind \ closer objects LDR R0, [R11, #xCamera] \ Set R0 to the x-coordinate of the camera, \ which is at the back of the landscape and \ in the middle AND R8, R0, #&FF000000 \ Zero the bottom three bytes of R0 and \ store in R8, so R8 contains the \ x-coordinate of the tile below the camera, \ in the middle of the landscape LDR R1, [R11, #zCamera] \ Set R1 to the z-coordinate of the camera AND R9, R1, #&FF000000 \ Zero the bottom three bytes of R1 and \ store in R9, so R9 contains the \ z-coordinate of the tile below the camera, \ at the back of the landscape SUB R8, R8, #LANDSCAPE_X \ Set xCameraTile = R8 - LANDSCAPE_X STR R8, [R11, #xCameraTile] \ \ We already rounded xCamera down to the \ nearest tile, so this moves us to the \ coordinate of the tile corner at the left \ end of the corner row, as subtracting the \ landscape offset effectively moves the \ camera to the left by that amount \ \ We store the result in xCameraTile, so \ this is set to the x-coordinate of the \ left end of the tile row \ \ As we only take the top byte of the \ x-coordinate when reading the object map, \ this moves us to the front-left corner of \ the on-screen landscape, so we can now \ work along the x-axis in the object map \ from left to right in the following loop \ We are now ready to loop through the \ object map, so we set up the loop counters \ for two loops - an outer loop with R7 as \ the counter to work through the z-axis \ from back to front, and an inner loop with \ R6 as the counter to work through the \ x-axis for each row from left to right MOV R7, #TILES_Z \ Set R7 = TILES_Z to act as a loop counter \ as we work our way along the tiles on the \ z-axis (i.e. from back to front on the \ screen) .dobs1 MOV R6, #TILES_X \ Set R6 = TILES_X to act as a loop counter \ as we work our way along the tiles on the \ x-axis (i.e. from left to right on the \ screen) LDR R8, [R11, #xCameraTile] \ Set R8 = xCameraTile, so R8 contains the \ x-coordinate of the leftmost tile of the \ visible landscape \ We now have the coordinates of the far \ left tile in (R8, R9), so we can start to \ iterate through the object map one row at \ a time, checking each tile to see if there \ is an object there (so we can draw it) .dobs2 ADD R14, R11, #objectMap \ Set R14 to the address of the object map ADD R14, R14, R8, LSR #24 \ Set R14 = R6 + (R8 >> 24) + (R9 >> 16) ADD R14, R14, R9, LSR #16 \ \ R8 is shifted into the bottom byte of R14, \ so that's the x-coordinate, and R9 is \ shifted into the second byte of R14, so \ that's the z-coordinate, so R14 points to \ the object map entry for coordinate \ (R8, R9) LDRB R0, [R14] \ Set R0 to the byte in the object map at \ the coordinate (R8, R9) CMP R0, #&FF \ If the object map entry is not &FF, then BNE dobs4 \ there is an object at this point, so jump \ to dobs4 to consider drawing the object .dobs3 ADD R8, R8, #TILE_SIZE \ Step along the x-axis by one whole tile, \ going from left to right SUBS R6, R6, #1 \ Decrement the x-axis loop counter in R6 BNE dobs2 \ Loop back to check the next tile until we \ have checked along the whole x-axis SUB R9, R9, #TILE_SIZE \ Step along the z-axis by one whole tile, \ going from back to front SUBS R7, R7, #1 \ Decrement the z-axis loop counter in R6 BNE dobs1 \ Loop back to check the next tile until we \ have checked along the whole z-axis LDMFD R13!, {R5-R12, PC} \ Retrieve the registers that we stored on \ the stack and return from the subroutineName: DrawObjects (Part 1 of 3) [Show more] Type: Subroutine Category: 3D objects Summary: Draw all the objects in the visible portion of the object map, starting by working our way through the map looking for objects Deep dive: Drawing 3D objectsContext: See this subroutine in context in the source code References: This subroutine is called as follows: * LoseLife calls DrawObjects * MainLoop calls DrawObjects
[X]
Configuration variable LANDSCAPE_X = LANDSCAPE_X_WIDTH / 2
The x-coordinate of the landscape offset, which is set to the whole number of tiles that fit into the half the width of the landscape, so we end up looking at the middle point of the landscape
[X]
Configuration variable TILES_X = 13
The number of tile corners in a landscape row from left to right (i.e. 12 tiles)
[X]
Configuration variable TILES_Z = 11
The number of tile corners in a landscape row from front to back (i.e. 10 tiles)
[X]
Configuration variable TILE_SIZE = &01000000
The length of one side of a square landscape tile in 3D coordinates
[X]
Label dobs1 is local to this routine
[X]
Label dobs2 is local to this routine
[X]
Label dobs4 in subroutine DrawObjects (Part 2 of 3)
[X]
Configuration variable objectMap = &4400 + STORE * 2
The object map determines which objects appear on the landscape, where objects are trees, buildings, rockets and so on (size of object map is 256 * 256 bytes = &10000)
[X]
Configuration variable xCamera = &13C
The 3D x-coordinate of the camera position (though note that the camera position is actually at the back of the on-screen landscape, not the front)
[X]
Configuration variable xCameraTile = &148
The 3D x-coordinate of the camera, clipped to the nearest tile
[X]
Configuration variable zCamera = &144
The 3D z-coordinate of the camera position (though note that the camera position is actually at the back of the on-screen landscape, not the front, so the camera's z-coordinate is larger than it would be for a more traditional camera position; it is more like the camera's focal point than position, in a sense)