Skip to navigation

Lander on the Acorn Archimedes

Particles: DrawParticleToBuffer

Name: DrawParticleToBuffer [Show more] Type: Subroutine Category: Particles Summary: Draw a large coloured particle into a slightly nearer graphics, buffer according to its distance Deep dive: Depth-sorting with the graphics buffers
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MoveAndDrawParticles (Part 4 of 4) calls DrawParticleToBuffer

This command draws a large coloured particle into a graphics buffer, with the buffer being chosen according to the distance of the particle in the z-axis, plus one (so this routine draws the particle into a slightly nearer graphics buffer than DrawParticleShadowToBuffer, so shadows never overlap their corresponding particles). This command is used for drawing particles, while DrawParticleShadowToBuffer is used for drawing their shadows. The command numbers for drawing large particles are 0 to 8, with higher numbers giving smaller particles (so particles are smaller when they are further away, as the command number is based on the z-coordinate). This is followed by the pixel coordinates, composed into one 32-bit parameter word as follows: #20-31 #12-19 #8-11 #0-7 019876543210 98765432 1098 76543210 ^ ^ ^ ^ | | | | Pixel x-coord Colour Unused Pixel y-coord (0-319) (0-255) (0-255)
Arguments: (R0, R1) The pixel coordinate of the particle R7 The particle colour R8 The 3D z-coordinate of the particle R12 The address of the table of containing the end addresses of the graphics buffers (i.e. graphicsBuffersEnd)
.DrawParticleToBuffer STMFD R13!, {R9, R14} \ Store the registers that we want to use on \ the stack so they can be preserved RSB R14, R8, #LANDSCAPE_Z \ Set R14 = landscape offset - R8 \ \ We use the top byte of this number as the \ number of the graphics buffer to draw into \ \ This ensures that more distant particles \ are drawn into lower-numbered graphics \ buffers, so higher z-coordinates map to \ lower buffer numbers and vice versa (so \ buffer 0 is for objects that are far away \ and buffer 10 is for the closest objects \ to the viewer) ADD R14, R14, #TILE_SIZE \ Add the size of one tile to R14 so we draw \ the particle one tile nearer than we would \ otherwise (i.e. one buffer nearer) BIC R14, R14, #&00C00000 \ We are going to use the top byte of R14 as \ the buffer number, and we're going to look \ up the corresponding buffer address from a \ lookup table with four bytes per entry, so \ we clear bits 22 and 23 to ensure that \ R14 >> 22 contains the value of the top \ byte * 4, which we can then use as an \ offset into the lookup table to fetch the \ address of the end of the buffer, which is \ where we can store our particle-drawing \ command LDR R9, [R12, R14, LSR #22] \ Set R9 to the address of the next free \ byte in the graphics buffer whose number \ matches the top byte of R14, fetching the \ address from the lookup table at R12 MOV R8, R8, LSR #25 \ Scale R8 from a 3D z-coordinate into a CMP R8, #8 \ number between 0 and 8, which we can use MOVHS R8, #8 \ as the drawing command number, as drawing \ commands 0 to 8 draw particles with higher \ numbers giving smaller particles (see \ bufferJump for a full list of drawing \ commands) AND R7, R7, #&FF \ Encode the two pixel coordinates in R0 and ADD R1, R1, R7, LSL #12 \ R1 and the colour in R7 into one parameter ADD R1, R1, R0, LSL #20 \ word in R1, by inserting the value of R0 \ into bits 20-31 of R1 and the value of R7 \ into bits 12-19 STR R8, [R9], #4 \ Store the drawing command number in the \ graphics buffer and increment the address \ in R9 to point to the next word in the \ buffer STR R1, [R9], #4 \ Store the parameter word in R1 in the \ graphics buffer and increment the address \ in R9 to point to the next word in the \ buffer STR R9, [R12, R14, LSR #22] \ Update the end address in the table at R12 \ to point to the new end address of the \ graphics buffer LDMFD R13!, {R9, PC} \ Retrieve the registers that we stored on \ the stack and return from the subroutine