Skip to navigation

Lander on the Acorn Archimedes

Drawing triangles: DrawTriangle (Part 2 of 11)

Name: DrawTriangle (Part 2 of 11) [Show more] Type: Subroutine Category: Drawing triangles Summary: Calculate the slope of (x1, y1) to (x2, y2) 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
\ We now calculate the slope of the first \ side of the triangle, from (x1, y1) to \ (x2, y2), as follows: \ \ R6 = (y1 - y2) / (x2 - x1) SUBS R9, R1, R3 \ Set R9 = R1 - R3 \ = y1 - y2 \ \ So this is the vertical distance between \ (x1, y1) and (x2, y2), i.e. the delta \ y-coordinate between the two points \ \ We know this is positive because y1 >= y2 BEQ trin16 \ If (x1, y1) and (x2, y2) share the same \ y-coordinate then the triangle has a \ horizontal edge between (x1, y1) and \ (x2, y2), so jump to part 5 to process \ this special case STMFD R13!, {R4-R5} \ Store the third corner's coordinates in \ (x3, y3) on the stack to we can retrieve \ them later SUBS R14, R2, R0 \ Set R14 = R2 - R0 \ = x2 - x1 \ \ So this is the vertical distance between \ (x1, y1) and (x2, y2), i.e. the delta \ x-coordinate between the two points \ \ This will be positive if the line from \ (x1, y1) to (x2, y2) slopes up and to the \ right, or negative if the line slopes up \ and to the left RSBMI R14, R2, R0 \ If R14 is negative, set R14 = x1 - x2, so \ we have the following: \ \ R14 = |x2 - x1| CMP R14, #64 \ If either R14 >= 64 or R9 >= 64, then at CMPLO R9, #64 \ least one of these is true: BHS trin4 \ \ R14 = |x2 - x1| >= 64 \ \ R9 = (y1 - y2) >= 64 \ \ so jump to trin4 to calculate the slope \ using the shift-and-subtract algorithm LDR R10, divisionTableAddr \ Set R10 to the address of the division \ tables ADD R10, R10, R14, LSL #8 \ Set R10 to the address of the division \ table containing n / R14, for n = 0 to 63 \ \ This works because each division table \ contains 64 words, or 256 bytes, so the \ address of table n / d is: \ \ divisionTable + d * 256 LDR R6, [R10, R9, LSL #2] \ Set R6 to the R9-th word in the division \ table containing n / R14, so this \ calculates the following: \ \ R6 = R9 / R14 \ \ = (y1 - y2) / |x2 - x1| B trin6 \ Jump to trin6 to skip the following and \ keep going .trin4 \ If we get here then at least one of these \ is true: \ \ R14 = |x2 - x1| >= 64 \ \ R9 = (y1 - y2) >= 64 \ \ We now calculate R2 = R9 / R14 using the \ shift-and-subtract division algorithm MOV R9, R9, LSL #16 \ First we scale R9 up as far as we can, to \ make the result as accurate as possible MOV R6, #0 \ Set R6 = 0 to contain the result MOV R10, #&80000000 \ Set bit 31 of R10 so we can shift it to \ the right in each iteration, using it as a \ counter .trin5 MOVS R14, R14, LSL #1 \ Shift R14 left, moving the top bit into \ the C flag CMPCC R14, R9 \ If we shifted a 0 out of the top of R14, \ test for a possible subtraction SUBCS R14, R14, R9 \ If we shifted a 1 out of the top of R14 or ORRCS R6, R6, R10 \ R14 >= R9, then do the subtraction: \ \ R14 = R14 - R9 \ \ and set the relevant bit in the result \ (i.e. apply the set bit in R10 to the \ result in R6) MOVS R10, R10, LSR #1 \ Shift R10 to the right, moving bit 0 into \ the C flag BCC trin5 \ Loop back until we shift the 1 out of the \ right end of R10 (after 32 shifts) \ So we now have the following result: \ \ R6 = R9 / R14 \ \ = (y1 - y2) / |x2 - x1| .trin6 CMP R2, R0 \ If R2 - R0 < 0 then: RSBMI R6, R6, #0 \ \ x2 - x1 < 0 \ \ so negate R6 to give R6 the correct sign \ for the following calculation: \ \ R6 = (y1 - y2) / (x2 - x1) \ \ So R6 contains the slope of the first side \ of the triangle, from (x1, y1) to (x2, y2)