Skip to navigation

Lander on the Acorn Archimedes

3D objects: DrawObjects (Part 1 of 3)

Name: 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 objects
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * LoseLife calls DrawObjects * MainLoop calls DrawObjects
.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 subroutine