Skip to navigation

Revs on the BBC Micro

Drawing objects: DrawObject

Name: DrawObject [Show more] Type: Subroutine Category: Drawing objects Summary: Draw an object of a specific type
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawCarOrSign calls DrawObject * DrawCornerMarkers calls DrawObject

This routine is used to draw objects such as road signs, corner markers and cars.
Arguments: objectType The type of object to draw (0 to 12) scaleUp The scale factor for this object (i.e. its size) colourPalette The colour palette to use for drawing the object X Driver number: * 0-19 = map logical colour 1 according to the driver number in X: * Drivers 0, 4, 8, 12, 16 map to colour 0 (black) * Drivers 1, 5, 9, 13, 17 map to colour 1 (red) * Drivers 2, 6, 10, 14, 18 map to colour 2 (white) * Drivers 2, 7, 11, 15, 19 map to colour 3 (green) * 20-22 = this is the four-object car, which is the closest car in front of us, so map logical colour 1 according to the number of the driver in front of us (using the same logic as above) * 23 = stick with the palette in colourPalette
Returns: colourPalette Gets reset back to the default palette
.DrawObject STX T \ Store the driver number in T \ We start by copying the four bytes from the standard \ colour palette in colourPalette to the object colour \ palette in objectPalette, as we use the latter to draw \ the object LDX #3 \ Set up a counter in X for copying the four palette \ bytes .dobj1 LDA colourPalette,X \ Copy the X-th byte of colourPalette to the X-th byte STA objectPalette,X \ of objectPalette DEX \ Decrement the loop counter BPL dobj1 \ Loop back until we have copied all four bytes LDA #%11110000 \ Map logical colour 2 in the colour palette to physical STA colourPalette+2 \ colour 1 (white in the track view), which sets it back \ to the default value \ \ This only has an effect when we call DrawObject from \ DrawCornerMarkers, which changes the value of colour 2 \ in colourPalette (all other calls to DrawObject leave \ the colour palette alone) \ We now set the palette differently, depending on the \ driver number in A: \ \ * 0-19 = map logical colour 1 to physical colour \ A mod 4 \ \ * 20-22 = map logical colour 1 to physical colour \ (number of the driver in front) mod 4 \ \ * 23 = don't change the palette, i.e. use the \ palette from colourPalette LDA T \ Set A = T, so A contains the driver number CMP #23 \ If A = 23, jump to dobj3 to skip the following palette BEQ dobj3 \ changes CMP #20 \ If A < 20, jump to dobj2 to map logical colour 1 to BCC dobj2 \ physical colour A mod 4, in other words: \ \ * Drivers 0, 4, 8, 12, 16 map to colour 0 (black) \ * Drivers 1, 5, 9, 13, 17 map to colour 1 (red) \ * Drivers 2, 6, 10, 14, 18 map to colour 2 (white) \ * Drivers 2, 7, 11, 15, 19 map to colour 3 (green) \ If we get here then A is 20, 21 or 22, which is the \ four-object car, so we map logical colour 1 to the \ number of the driver in front of us, mod 4 LDX positionAhead \ Set X to the position of the driver in front of us LDA driversInOrder,X \ Set A the number of the driver in front of us, so we \ map logical colour 1 to physical colour A mod 4 .dobj2 AND #3 \ Set X = A mod 4 TAX LDA colourPalette,X \ Map logical colour 1 in the object palette to logical STA objectPalette+1 \ colour X from the colour palette .dobj3 LDX #0 \ Set scaleDown = 0, so the object's scaffold is not STX scaleDown \ scaled down (as 2^scaleDown = 2^0 = 1) LDA scaleUp \ Set A = scaleUp, so A contains the object size, which \ we can also interpret as the object distance CMP horizonTrackWidth \ If A >= horizonTrackWidth, then the object is closer BCS dobj4 \ than the horizon line, so jump to dobj4 to skip the \ following instruction and set lowestTrackLine to 0 (so \ the whole object is drawn) LDX horizonLine \ Otherwise the object is further away than the horizon \ line, so set X to the track line number of the \ horizon, so the parts of the object below this line do \ not get drawn (as they are below the horizon line, so \ presumably hidden by a hill) .dobj4 STX lowestTrackLine \ Set lowestTrackLine = X, so the object gets cut off at \ the horizon line when scaleUp < horizonTrackWidth CMP #64 \ If A >= 64, i.e. scaleUp >= 64, jump to dobj5 to skip BCS dobj5 \ the following \ Otherwise we can alter the values of scaleUp and \ scaleDown to be more accurate but without fear of \ overflow, by multiplying both scale factors by 4 \ (as we know 4 * scaleUp is < 256) ASL A \ Set scaleUp = A * 4 ASL A \ = scaleUp * 4 STA scaleUp LDA #2 \ Set scaleDown = 2, so the object's scaffold is scaled STA scaleDown \ down by 2^scaleDown = 2^2 = 4 \ \ So the overall scaling of the scaffold is the same, \ but we retain more accuracy .dobj5 LDX objectType \ Set X to the type of object we're going to draw \ If the object type is 10, 11 or 12, then it's one of \ the turn signs (chicane, left or right turn), so we \ draw this as two objects, starting with a blank white \ sign (object type 9) and then the sign contents \ (object 10, 11 or 12) \ \ We only draw the sign contents if our car is facing \ forwards, so the back of the sign is blank CPX #10 \ If X < 10, jump to dobj6 to skip the following BCC dobj6 \ instruction LDX #9 \ Set X = 9, so we first draw an object of type 9 for \ the blank white sign, before drawing another object of \ type objectType .dobj6 STX thisObjectType \ Store X in thisObjectType, so we can check it again \ below in case we need to draw two objects LDA scaffoldIndex,X \ Set QQ to the index of the first scaffold entry in STA QQ \ objectScaffold for object type X LDA scaffoldIndex+1,X \ Set II to the index of the first scaffold entry in STA II \ objectScaffold for object type X + 1 (so the last \ entry for object type X will be index II - 1) LDA objectIndex,X \ Set QQ to the index of the first entry in the object STA MM \ data tables for object type X (so MM will point to the \ first entry for this object in the objectTop, \ objectBottom, objectLeft, objectRight and objectColour \ tables) JSR ScaleObject \ Scale the object's scaffold by the scaleUp and \ scaleDown factors, storing the results in the \ scaledScaffold table BCS dobj7 \ If the call to ScaleObject set the C flag then the \ scaling process overflowed, in which case we do not \ draw the object, so jump to dobj7 to return from the \ subroutine JSR DrawObjectEdges \ Draw the scaled object in the screen buffer by drawing \ all the object's edges LDX objectType \ Set X to the type of object we are drawing, in case we \ need to draw a second object LDA thisObjectType \ If the object we just drew is not an object of type 9, CMP #9 \ then this is not a two-part road sign object, so jump BNE dobj7 \ to dobj7 to return from the subroutine \ Otherwise we just drew an object of type 9, for the \ blank white sign, so now we draw a second object for \ the sign's contents, but only if our car is facing \ forwards (if we are facing backwards, then we see the \ back of the sign, which is blank) LDA directionFacing \ If bit 7 of directionFacing is clear, then our car is BPL dobj6 \ facing forwards, so loop back to draw the contents of \ the sign in object type objectType .dobj7 RTS \ Return from the subroutine