Skip to navigation

Lander on the Acorn Archimedes

Drawing lines: DrawHorizontalLine

Name: DrawHorizontalLine [Show more] Type: Subroutine Category: Drawing lines Summary: Draw a horizontal line Deep dive: Drawing triangles
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawFuelLevel calls DrawHorizontalLine * DrawTriangle (Part 4 of 11) calls DrawHorizontalLine * DrawTriangle (Part 11 of 11) calls DrawHorizontalLine

Arguments: R8 Line colour (in the form of a four-pixel colour word) R10 Line length R11 Screen address of the left end of the line
.DrawHorizontalLine CMP R10, #18 \ If R10 < 18 then set the flags so the next \ set of instructions are run (so for lines \ of length 17 pixels and fewer, we jump to \ the relevant routine in the lineJump to \ draw the line ] varOffset = P% + 8 - lineJump \ Set labOffset to the offset back to the \ lineJump table from the next instruction [ OPT pass% ADDLO R0, PC, R10, LSL #2 \ If R10 < 18, jump to the address in entry LDRLO PC, [R0, #-varOffset] \ R10 in the lineJump table, which will draw \ a horizontal line R10 pixels long and \ return from the subroutine using a tail \ call \ If we get here then we need to draw a line \ of 18 pixels or more ADD R10, R11, R10 \ Set R10 to the screen address of the right \ end of the line (i.e. the address of the \ left end in R11 plus the width in R10) BIC R0, R10, #%00000011 \ Set R0 to the screen address with bits 0 \ and 1 cleared, so R0 points to the word in \ screen memory that contains the right end \ of the line (the "right cap") \ So by this point R11 points to the word in \ screen memory that contains the left cap \ of the line (which is the word containing \ the left end of the line), and R0 points \ to the right cap \ \ The caps can contain 1, 2, 3 or 4 pixels, \ as each 32-bit word contains four one-byte \ pixels \ \ If a cap contains four pixels, then bits 0 \ and 1 of the cap address will be zero, so \ in the following we draw the line as \ follows: \ \ * If the left cap contains 1, 2 or 3 \ pixels, draw those pixels \ \ * Draw the portion of the line between \ the left and right caps, drawing it \ one word (four pixels) at a time \ \ * If the right cap contains 1, 2 or 3 \ pixels, draw those pixels \ \ We start with the left cap at screen \ address R11 TST R11, #%00000011 \ If R11 is not a multiple of 4 then one or STRNEB R8, [R11], #1 \ both of bits 0 and 1 will be non-zero, so \ set the pixel at R11 to the colour in R8 \ and increment R11 \ \ So this draws the pixel at the end of the \ line, and it increments R11 so R11 now \ points to the next pixel along TSTNE R11, #%00000011 \ If R11 is still not a multiple of 4 then STRNEB R8, [R11], #1 \ bits 0 and 1 will still be non-zero, so \ set the pixel at R11 to the colour in R8 \ and increment R11 \ \ So this draws the second pixel in the line \ if drawing the first one didn't take us to \ a word boundary, and it increments R11 so \ R11 now points to the next pixel along TSTNE R11, #%00000011 \ If R11 is still not a multiple of 4 then STRNEB R8, [R11], #1 \ bits 0 and 1 will still be non-zero, so \ set the pixel at R11 to the colour in R8 \ and increment R11 \ \ So this draws the third pixel in the line \ if drawing the first two didn't take us to \ a word boundary, and it increments R11 so \ R11 now points to the next pixel along \ By this point R11 will definitely be on a \ word boundary and we have successfully \ drawn the left cap of the line, so now we \ draw the centre portion of the line, all \ the way to the right cap \ \ We do this in a loop that is unrolled once \ to speed things up a little but .hlin1 STR R8, [R11], #4 \ Draw a full word (four pixels) in the \ colour in R8 at screen address R11 and \ increment R11 by 4 to move on to the next \ word CMP R11, R0 \ If R11 < R0 then we have not yet reached STRLO R8, [R11], #4 \ the right cap, so draw another word in \ memory and increment R11 again CMPLO R11, R0 \ If R11 < R0 then we have still not reached BLO hlin1 \ the right cap, so loop back to hlin1 to \ keep drawing the centre portion of the \ line until we do reach the right cap CMP R11, R10 \ If R11 < R10 then we have not yet reached STRLOB R8, [R11], #1 \ the end of the line, so we draw up to CMPLO R11, R10 \ three pixels in the final word of the line STRLOB R8, [R11], #1 \ by simply drawing each pixel, incrementing CMPLO R11, R10 \ R11 and then re-checking whether R11 has STRLOB R8, [R11], #1 \ reached R10 (and drawing the next pixel if \ it hasn't) MOV PC, R14 \ Return from the subroutine