Skip to navigation

Revs on the BBC Micro

Screen buffer: DrawTrackView (Part 3 of 4)

Name: DrawTrackView (Part 3 of 4) [Show more] Type: Subroutine Category: Screen buffer Summary: Draw the part of the track view that fits around the dashboard and tyres Deep dive: Drawing around the dashboard Drawing the track view
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

This routine modifes the DrawTrackBytes routine so that it draws all the remaining lines in the track view so they fit around the shape of the dashboard and the tyres.
\ We get here with X = 28, as in part 1 we drew the \ lines specified by dash data offsets 79 to 44, and in \ part 2 we drew the lines specified by dash data \ offsets 43 to 28 \ \ In the following loop, we draw the lines specified by \ dash data offsets 27 to 3 .view7 DEX \ Decrement the dash data block pointer to point to \ the data for the next line LDY staDrawByte,X \ Set Y to the X-th entry in staDrawByte, which contains \ the low byte of the address of the STA (P),Y \ instruction in the DRAW_BYTE macro given in the \ table CPY view8+1 \ If the instruction at view8 has already been modified BEQ view10 \ to this address, jump to view10 to skip the following \ modifications, as they have already been done on the \ previous iteration of the loop LDA #&91 \ Set A to the opcode for the STA (P),Y instruction .view8 STA DrawTrackBytes+15 \ Modify the specified instruction back to STA (P),Y \ (the address of the modified instruction is set by the \ following, so the first time we run this line it has \ no effect) STY view9+1 \ Modify the instruction at view9 to change the low byte \ of the address to the X-th entry in staDrawByte, so \ the instruction at view9 changes the STA (P),Y \ instruction to an RTS in the DRAW_BYTE macro given \ in staDrawByte STY view8+1 \ Modify the instruction at view8 to change the low byte \ of the address to the X-th entry in staDrawByte, so \ the instruction at view8 changes the RTS instruction \ back to STA (P),Y when we loop back around LDA #&60 \ Set A to the opcode for the RTS instruction .view9 STA DrawTrackBytes \ Modify the specified instruction to an RTS so the next \ call to DrawTrackLine will return at that point (the \ address of the modified instruction is set above) .view10 \ The following code is normally run at the start of the \ DrawTrackLine routine, but we are going to call the \ DrawTrackBytes routine to draw our line instead, so \ we can skip the bytes that are hidden behind the left \ tyre \ \ So we repeat the code here, which increments the \ screen addresses in (Q P) and (S R) to point to the \ next pixel row down the screen LDY P \ Set Y = P + 1, which is the low byte of (Q P) + 1 INY TYA \ If Y mod 8 <> 0 then incrementing (Q P) will keep us AND #&07 \ within the current character block (i.e. the new pixel BNE view11 \ row will be 7 or less), so jump to view11 to store the \ incremented values \ Otherwise incrementing (Q P) will take us into the \ next character block (i.e. from pixel row 7 to pixel \ row 8), so we need to update the screen addresses to \ jump to the next character row TYA \ Set (Q P) = Y + &138 CLC \ ADC #&38 \ starting with the low bytes STA P STA R LDA Q \ And then the high bytes, so (Q P) points to start of ADC #&01 \ the character block on the next character row (i.e. STA Q \ the next pixel row down) ADC #&01 \ Set (S R) = (Q P) + &100 STA S BCC view12 \ Jump to view12 to skip the following .view11 \ If we get here then incrementing the screen addresses \ keeps us within the current character block, so we can \ store the incremented addresses in (Q P) and (S R) STY P \ Set the low bytes of (Q P) and (S R) to Y, so this STY R \ does: \ \ (Q P) = (Q P) + 1 \ \ (S R) = (S R) + 1 \ \ so they point to the next pixel row down the screen .view12 \ The staDrawByteTyre table contains the low byte offset \ of the address of the STA (P),Y instruction for the \ track line, which we convert into an RTS when drawing \ the track line up against the right tyre, so we stop \ in time (see the code that modifies view14 and view15 \ below) \ \ As the tyres are reflections of each other, we can \ also use this value to calculate the starting point \ for the line that starts at the left tyre, which is \ what we do now LDA #LO(byte3)+3 \ Set A = LO(byte3) + 3 - staDrawByteTyre SEC \ SBC staDrawByteTyre,X \ There are 14 instances of the DRAW_BYTE macro between \ byte2 and byte3, ranging from DRAW_BYTE 26 up to \ DRAW_BYTE 39 \ \ This calculation converts the low address byte from \ the staDrawByteTyre table so that instead of pointing \ to the LDA #0 instruction in the n-th DRAW_BYTE macro, \ it points to the LDA #0 instruction in the 14-n-th \ macro, as an offset from byte2 \ \ This effectively takes the end point given in the \ staDrawByteTyre table and returns the start point if \ the range DRAW_BYTE 26 to DRAW_BYTE 39 were \ "reflected" into DRAW_BYTE 39 to DRAW_BYTE 26 \ \ This enables us to calculate the offset of the start \ point's macro for the left tyre, as an offset from \ DrawTrackBytes, which is what we want STA view13+1 \ Modify the instruction at view13 to change the low \ byte of the address to A, so the instruction at view13 \ changes so it jumps to the LDA #0 instruction in the \ DRAW_BYTE macro specified in the table LDY tyreEdgeIndex,X \ Set Y to the index of the mask and pixel bytes for the \ tyre edge for this track line, so we can use it below \ to fetch the correct entries from leftTyreMask and \ leftTyrePixels LDA tyreRightEdge,X \ Fetch the track pixel byte that would be shown along \ the right edge of the left tyre, i.e. the leftmost \ byte of the track line, where the line meets the left \ tyre AND leftTyreMask,Y \ We now merge the track byte in A with the edge of the ORA leftTyrePixels,Y \ left tyre, by masking out the pixels in A that are \ hidden by the tyre (with AND leftTyreMask), and \ replacing them with the pixels from the edge of the \ left tyre (with ORA leftTyrePixels) TAY \ Copy the pixel byte into Y, because the following JSR \ jumps straight to the LDA #0 instruction within the \ DRAW_BYTE macro, and at that point the macro expects \ the pixel byte to be in Y rather than A .view13 JSR DrawTrackBytes \ Draw the left portion of this track line \ \ This routine was modified above to return from the \ subroutine at the STA instruction in the DRAW_BYTE \ macro specified in the staDrawByte table, so this \ returns the last pixel byte of this portion of the \ line in A, i.e. the rightmost byte of the left portion \ of the track line, where the line meets the left \ border of the central part of the dashboard AND leftDashMask,X \ We now merge the track byte in A with the left edge ORA leftDashPixels,X \ of the dashboard, by masking out the pixels in A that \ are hidden by the dashboard (with AND leftDashMask), \ and replacing them with the pixels from the left edge \ of the dashboard (with ORA leftDashPixels) STA (P),Y \ Write the merged pixel byte into screen memory LDY staDrawByteTyre,X \ Set Y to the X-th entry in staDrawByteTyre, which \ contains the low byte of the address of the STA (P),Y \ instruction in the DRAW_BYTE macro given in the \ table CPY view14+1 \ If the instruction at view14 has already been modified BEQ view16 \ to this address, jump to view16 to skip the following \ modifications, as they have already been done on the \ previous iteration of the loop LDA #&91 \ Set A to the opcode for the STA (P),Y instruction .view14 STA byte2+15 \ Modify the specified instruction back to STA (P),Y \ (the address of the modified instruction is set by the \ following, so the first time we run this line it has \ no effect) STY view15+1 \ Modify the instruction at view15 to change the low \ byte of the address to the X-th entry in \ staDrawByteTyre, so the instruction at view15 changes \ the STA (P),Y instruction to an RTS in the DRAW_BYTE \ macro given in staDrawByteTyre STY view14+1 \ Modify the instruction at view14 to change the low \ byte of the address to the X-th entry in \ staDrawByteTyre, so the instruction at view14 changes \ the STA (P),Y instruction to an RTS in the DRAW_BYTE \ macro given in staDrawByteTyre LDA #&60 \ Set A to the opcode for the RTS instruction .view15 STA byte2 \ Modify the specified instruction to an RTS so the next \ call to byte2 will return at that point (the address \ of the modified instruction is set above) .view16 LDY ldaDrawByte,X \ Set Y to the X-th entry in ldaDrawByte, which contains \ the low byte of the LDA #0 instruction in the specific \ DRAW_BYTE macro, as given in the table STY view17+1 \ Modify the instruction at view17 to change the low \ byte of the address to the X-th entry in ldaDrawByte, \ so the instruction at view17 changes so it jumps to \ the LDA #0 instruction in the DRAW_BYTE macro \ specified in the table LDA dashRightEdge,X \ Fetch the track pixel byte that would be shown along \ the right edge of the dashboard, i.e. the leftmost \ byte of the right portion of the track line, where the \ line meets the right border of the central part of the \ dashboard AND rightDashMask,X \ We now merge the track byte in A with the right edge ORA rightDashPixels,X \ of the dashboard, by masking out the pixels in A that \ are hidden by the dashboard (with AND rightDashMask), \ and replacing them with the pixels from the left edge \ of the dashboard (with ORA rightDashPixels) TAY \ Copy the pixel byte into Y, because the following JSR \ jumps straight to the LDA #0 instruction within the \ DRAW_BYTE macro, and at that point the macro expects \ the pixel byte to be in Y rather than A .view17 JSR byte2 \ Draw the right portion of this track line \ \ This JSR was modified above to jump to the LDA #0 \ instruction in the DRAW_BYTE macro specified in the \ ldaDrawByte table STY U \ Store Y in U so we can retrieve it below LDY tyreEdgeIndex,X \ Set Y to the index of the mask and pixel bytes for the \ tyre edge for this track line, so we can use it to \ fetch the correct entries from rightTyreMask and \ rightTyrePixels AND rightTyreMask,Y \ We now merge the track byte in A with the edge of the ORA rightTyrePixels,Y \ right tyre, by masking out the pixels in A that are \ hidden by the tyre (with AND rightTyreMask), and \ replacing them with the pixels from the edge of the \ right tyre (with ORA rightTyrePixels) LDY U \ Retrieve the value of Y that we stored above STA (R),Y \ Write the merged pixel byte into screen memory, using \ (S R) as the screen address as this is at the right \ end of the track line CPX #3 \ If we just drew the line at dash data entry 3, jump BEQ view18 \ to view18 to stop drawing track lines JMP view7 \ Loop back to keep drawing lines, working our way down \ through the dash data from entry 27 down to entry 3 .view18 JMP view19 \ Jump to part 4 to reverse our code modifications