Skip to navigation

Lander on the Acorn Archimedes

Drawing triangles: DrawTriangleToBuffer

Name: DrawTriangleToBuffer [Show more] Type: Subroutine Category: Drawing triangles Summary: Draw a coloured triangle into a slightly nearer graphics buffer, according to its distance Deep dive: Drawing 3D objects Depth-sorting with the graphics buffers Drawing triangles
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawObject (Part 5 of 5) calls DrawTriangleToBuffer

This command draws a triangle into a graphics buffer, with the buffer being chosen according to the distance of the triangle in the z-axis, plus one (so this routine draws the triangle into a slightly nearer graphics buffer than DrawTriangleShadowToBuffer, so shadows never overlap their corresponding triangles). This command is used for drawing triangles, while DrawTriangleShadowToBuffer is used to draw their shadows. The command number for drawing a triangle is 18, followed by seven parameter words that match the arguments for the DrawTriangle routine: * Command number (18) * Pixel coordinate of corner 1 (x1, y1) * Pixel coordinate of corner 2 (x2, y2) * Pixel coordinate of corner 3 (x3, y3) * Colour
Arguments: (R0, R1) Pixel coordinate of corner 1 (R2, R2) Pixel coordinate of corner 2 (R4, R5) Pixel coordinate of corner 4 R8 Colour R12 The address of the table of containing the end addresses of the graphics buffers (i.e. graphicsBuffersEnd)
Returns: R12 R12 is preserved
.DrawTriangleToBuffer STMFD R13!, {R9, R14} \ Store the registers that we want to use on \ the stack so they can be preserved LDR R14, [R11, #zObject] \ Set R14 to the z-coordinate of the \ triangle RSB R14, R14, #LANDSCAPE_Z \ Set R14 = landscape offset - R14 \ \ We use the top byte of this number as the \ number of the graphics buffer to draw into \ \ This ensures that more distant triangles \ are drawn into lower-numbered graphics \ buffers, so higher z-coordinates map to \ lower buffer numbers and vice versa (so \ buffer 0 is for objects that are far away \ and buffer 10 is for the closest objects \ to the viewer) ADD R14, R14, #TILE_SIZE \ Add the size of one tile to R14 so we draw \ the triangle one tile nearer than we would \ otherwise (i.e. one buffer nearer) CMP R14, #LANDSCAPE_Z_BEYOND \ If R14 is a z-distance beyond the back of MOVHS R14, #LANDSCAPE_Z_DEPTH \ the visible landscape, cap it to the depth \ of the landscape so it fits into the range \ of graphics buffers (as there is one \ buffer for each tile row, going into the \ screen) BIC R14, R14, #&00C00000 \ We are going to use the top byte of R14 as \ the buffer number, and we're going to look \ up the corresponding buffer address from a \ lookup table with four bytes per entry, so \ we clear bits 22 and 23 to ensure that \ R14 >> 22 contains the value of the top \ byte * 4, which we can then use as an \ offset into the lookup table to fetch the \ address of the end of the buffer, which is \ where we can store our triangle-drawing \ command LDR R9, [R12, R14, LSR #22] \ Set R9 to the address of the next free \ byte in the graphics buffer whose number \ matches the top byte of R14, fetching the \ address from the lookup table at R12 MOV R7, #18 \ The command number for drawing a triangle STR R7, [R9], #4 \ is 18, so we store a value of 18 in the \ graphics buffer and increment the address \ in R9 to point to the next word in the \ buffer (see bufferJump for a full list of \ drawing commands) STMIA R9!, {R0-R5, R8} \ Store the three pixel coordinates from R0 \ to R5, and then the colour in R8, in the \ buffer STR R9, [R12, R14, LSR #22] \ Update the end address in the table at R12 \ to point to the new end address of the \ graphics buffer LDMFD R13!, {R9, PC} \ Retrieve the registers that we stored on \ the stack and return from the subroutine