Skip to navigation

Lander on the Acorn Archimedes

Drawing triangles: DrawTriangle (Part 1 of 11)

Name: DrawTriangle (Part 1 of 11) [Show more] Type: Subroutine Category: Drawing triangles Summary: Draw a triangle, starting by ordering the coordinates and jumping to the relevant part of the routine Deep dive: Drawing triangles
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawQuadrilateral calls DrawTriangle * DrawTriangleFromBuffer calls DrawTriangle

Arguments: (R0, R1) Pixel coordinate of corner 1 in (x1, y1) (R2, R3) Pixel coordinate of corner 2 in (x2, y2) (R4, R5) Pixel coordinate of corner 3 in (x3, y3) R8 Colour
.DrawTriangle CMP R0, #320 \ Check to see whether any of the triangle CMPLO R1, #239 \ corners are off-screen, in which case at CMPLO R2, #320 \ least one of x1 to x3 will be >= 320, or CMPLO R3, #239 \ at least one of y1 to y3 will be >= 239 CMPLO R4, #320 \ (the y-coordinate is checked against 239 CMPLO R5, #239 \ rather than 255 as the top 16 pixel lines \ of the 320x256 screen are taken up by the \ score bar) \ \ This also catches any negative pixel \ coordinates, as they will be treated as \ extremely large positive values in the \ comparisons (as the LO condition is used \ for unsigned comparisons) BHS trin23 \ If any of the corners are off-screen, jump \ to part 6 to draw a clipped triangle STMFD R13!, {R14} \ Store the return address on the stack LDR R12, screenAddr \ Set R12 to the address of the screen bank \ we are drawing in, pointing just below \ the two lines of text at the top of the \ screen \ We start by ordering the triangle corners \ by y-coordinate, so (x1, y1) is the \ furthest down the screen with the highest \ y-coordinate, followed by (x2, y2) then \ (x3, y3), at the same or higher level, and \ in that order CMP R1, R3 \ If R1 >= R3, jump to trin1 to skip the BHS trin1 \ following, as y1 >= y2 already MOV R6, R0 \ Swap (x1, y1) and (x2, y2), so we now have MOV R0, R2 \ y1 >= y2 MOV R2, R6 MOV R6, R1 MOV R1, R3 MOV R3, R6 .trin1 CMP R1, R5 \ If R1 >= R5, jump to trin2 to skip the BHS trin2 \ following, as y1 >= y3 already MOV R6, R0 \ Swap (x1, y1) and (x3, y3), so we now have MOV R0, R4 \ y1 >= y3 MOV R4, R6 MOV R6, R1 MOV R1, R5 MOV R5, R6 .trin2 CMP R3, R5 \ If R3 >= R5, jump to trin3 to skip the BHS trin3 \ following, as y2 >= y3 already MOV R6, R2 \ Swap (x2, y2) and (x3, y3), so we now have MOV R2, R4 \ y2 >= y3 MOV R4, R6 MOV R6, R3 MOV R3, R5 MOV R5, R6 \ So the triangle coordinates are ordered \ like this on-screen: \ \ (x3, y3) \ (x2, y2) \ (x1, y1) .trin3 ADD R11, R1, R1, LSL #2 \ Set R11 = R1 + R1 * 4 \ = 5 * y1 ADD R12, R12, R11, LSL #6 \ Set R12 = R12 + R11 * 64 \ = screenAddr + 5 * y1 * 64 \ = screenAddr + 320 * y1 \ \ So R12 is the screen address of the start \ of the pixel row containing (x1, y1), at \ the bottom of the triangle on-screen