Skip to navigation

Lander on the Acorn Archimedes

Drawing triangles: DrawTriangle (Part 11 of 11)

Name: DrawTriangle (Part 11 of 11) [Show more] Type: Subroutine Category: Drawing triangles Summary: Draw a triangle, clipping it to the screen as we go Deep dive: Drawing triangles
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.trin45 \ We call this part of the routine as a \ subroutine, so returning from the \ subroutine in this context means returning \ to the main triangle code above \ \ We call it with the following values: \ \ R4 = x-coordinate of the left end of the \ horizontal line to draw \ \ R5 = x-coordinate of the right end of \ the horizontal line to draw \ \ R6 = left edge slope \ \ R7 = right edge slope \ \ R8 = four-pixel colour word \ \ R9 = the delta y-coordinate between \ (x1, y1) and (x2, y2), which \ defines the height of the triangle \ to draw \ \ R11 = y1, so that's the y-coordinate of \ the bottom point of the triangle \ to draw \ \ R12 = screen address of the start of the \ pixel row containing (x1, y1) CMP R9, #256 \ If R9 >= 256 then the triangle to draw is MOVHS PC, R14 \ taller than the screen, which is just too \ big, so return from the subroutine without \ drawing this triangle STMFD R13!, {R14} \ Store the return address on the stack \ We now draw the triangle from bottom to \ top, keeping track of the y-coordinate of \ the current pixel row in R11 and counting \ down the pixel rows in R9 .trin46 ADD R4, R4, R6 \ Set R4 = R4 + R6 \ = R4 + slope of left edge \ \ So this moves the x-coordinate of the left \ edge by the correct slope as we move up by \ one pixel row ADD R5, R5, R7 \ Set R5 = R5 + R7 \ = R5 + slope of right edge \ \ So this moves the x-coordinate of the \ right edge by the correct slope as we move \ up by one pixel row CMP R11, #0 \ If R11 < 0 then we are already off the top LDMMIIA R13!, {PC} \ of the screen, so return from the \ subroutine CMP R11, #239 \ If R11 >= 239 then we are off the bottom BHS trin48 \ of the screen, so jump to trin48 to move \ on to the next row above in the triangle, \ so the triangle is clipped to the bottom \ of the screen STMFD R13!, {R11} \ Store the y-coordinate of the current row \ on the stack so we can retrieve it below ADD R11, R11, R11, LSL #2 \ Set R11 = R11 + R11 * 4 \ = y-coord of row * 5 ADD R11, R12, R11, LSL #6 \ Set R11 = R12 + R11 * 64 \ = screen address + 320 * y-coord \ \ So R11 points to the start of the pixel \ row in screen memory CMP R4, #&01400000 \ If R4 > &01400000, then the left end of BPL trin47 \ the line is greater than &140 (as the \ fractional number &01400000 represents the \ integer &0140), so it is greater than 320 \ and past the right edge of the screen \ \ This means the whole line is off-screen, \ so jump to trin47 to move on to the next \ row above in the triangle CMP R5, #0 \ If R5 < 0, then the right end of the line BMI trin47 \ is off the left edge of the screen, so \ jump to trin47 to move on to the next row \ above in the triangle CMP R4, #0 \ If the left end of the line is positive, MOVPL R0, R4, LSR #16 \ then it's on-screen, so set: \ \ R0 = R4 >> 16 \ = x-coordinate of left end of line \ \ The shift removes the fractional part from \ R4 ADDPL R11, R11, R4, LSR #16 \ If the left end of the line is positive, \ set R11 = R11 + R4 >> 16 \ = screen address of row + x1 \ \ So R11 contains the screen address of the \ left end of the line to draw MOVMI R0, #0 \ If the left end of the line is negative, \ i.e. off the left edge of the screen, then \ set R0 = 0 \ So R0 is set to the x-coordinate of the \ left end of the line we want to draw CMP R5, #&01400000 \ If R5 < &01400000, then the right end of RSBLO R10, R0, R5, LSR #16 \ the line is less than &140 (as the \ fractional number &01400000 represents the \ integer &0140), so it is less than 320 \ and is not past the right edge of the \ screen, so set: \ \ R10 = R5 >> 16 - R0 \ = x-coordinate of right end of line \ - x-coordinate of left end of line RSBHS R10, R0, #320 \ If the right end of the line is off the \ right side of the screen, set: \ \ R10 = 320 - x-coordinate of left end of \ line \ So R10 contains the length of the line \ from the left edge to the right edge CMP R10, #0 \ If R10 is positive then we draw a line BLPL DrawHorizontalLine \ from the left edge to the right edge, \ using the four-pixel colour word that was \ passed to the DrawTriangle routine in R8 .trin47 LDMFD R13!, {R11} \ Retrieve the y-coordinate of the current \ row from the stack, which we stored above, \ and put it into R11 once more .trin48 SUB R11, R11, #1 \ Decrement R11 so we move one pixel line up \ the screen SUBS R9, R9, #1 \ Decrement the triangle height counter in \ R9 BNE trin46 \ Loop back to draw the next line in the \ triangle until we have drawn all R9 \ horizontal lines LDMFD R13!, {PC} \ Return from the subroutine (and rejoin the \ main triangle routine)