BBC DEMO 5



This is the fifth demonstration in a series to show off the speed of machine code graphics on the BBC Micro and Electron. You will need a sample Mode 5 screen but if you haven't got one, program B.SCREEN will generate one for you. There is a short pause while the code is assembled and then just can sit back and enjoy the show. It looks like someone is pouring grains of sand from the top of the screen, and the picture is gradually built up as each grain lands at the bottom.
   The program makes use of a hidden screen, or screen cache. Various manipulations can be carried out on the cache before copying it to normal area of memory occupied by the screen RAM.
   The Mode 5 screen takes up &2800 bytes of memory, starting at &5800 and running up to &7FFF. These values are different in other Modes, but let's concentrate on Mode 5. We can store a complete copy of the Mode 5 screen at &3000, i.e. &2800 bytes below the start of the screen RAM.
   DEMO5 starts by loading in the screen file using OSCLI with the X and Y registers pointing to a command line at COMMAND.
   It proceeds by copying the very last row of pixels in the screen cache to every row in the screen RAM. The address of the last row of pixels in the cache is given by multiplying the width of the image in columns by the depth of the image in pixels minus 8, then adding 7 and adding the result on to the address of the cache. I've called this constant SOURCEROW in line 100. There are 40 columns across the screen Mode 5, and there are 256 rows of pixels down the screen in all Modes, declared as WIDTH and DEPTH in lines 70 and 80.
   The bottom-most row of pixels on the Mode 5 screen is at address &7EC7, called TARGETROW. If you are wondering why we didn't work out the address like this for the cache, well, I have tried to make it easier for you to adapt the program for images of different sizes and possibly in different Modes, as will be discussed later. For now, the only other information needed is the number of bytes per character row (BPR, line 90) which is &140 for Mode 5.
   SOURCEROW and TARGETROW are stored at &7C/&7D and &7A/&7B respectively. Location &7E is the DEPTH counter which begins equal to the depth of the image in pixels. &7E actually starts as zero because DECrementing a single location whose starting value is zero results in 255, then 254 and so on. When we reach zero again, we will have counted 256.
   In loop L3, the outermost loop, copies are made of all these addresses in locations &75-&79. Loop L2 copies one row of pixels and it needs its own copies of SOURCEROW and TARGET row to work on (locations &70-&73). The Y register holds the offset from SOURCEROW and TARGETROW, and is increased by 8 each time round the loop because there are eight bytes per column.
   When the WIDTH counter at &74 has reached zero, we have copied one row and been round loop L1 once. TARGETROW needs to be moved to point to the row above. Due to the perculiar layout of the screen RAM it's not just a matter of subtracting one from TARGETROW. If TARGETROW is the top of a character row, &140 (the number of bytes per character row, remember) less 7 needs to be subtracted so that we are at the bottom pixel row in the character row above.
   To find if we are at the top of a character row, we AND the low byte of the address with 7 to give a result between one and seven, which tells us the pixel row within the character row. If the result is zero, we are at the top. Now, if we subtracted BPR from the address we would be at the top of the character row above, and we need to be at the bottom - on the line of pixels immediately above the previous one - which is why we use BPR minus seven.
   Once 256 copies of SOURCEROW have been made, we are ready to move SOURCEROW to the row of pixels above. The same procedure as discussed above is used for checking whether one or BPR-7 needs to be subtracted from SOURCEROW - using the relevant addresses, of course. DEPTH is decreased by one. Thus, next time round the loop 255 copies of row 254 are made, then 254 copies of row 253, 253 of row 252 and so on until only one copy of row 0 of the cache is written to the screen RAM.
   Finally, the machien code waits a certain amount of time for a key press before returning to Basic. OSBYTE 129 with X and Y holding a 16-bit delay value, 500 centiseconds = 5 seconds in this instance.

Suggestions


Try altering the program so that the picture is built from the top down; that is, so it looks lasers are being fired from the foot of the screen. No ideas? Then see program DEMO5B for how it can be done.
   Currently, a full-size screen image is used. If you want smaller images, set WIDTH and DEPTH accordingly. You must to do this if you want to adapt the program to run in Modes 0 to 2. In Mode 1, for instance, there just isn't enough memory in the whole machine to store a copy of the screen RAM - which is a massive &5000 bytes. However, you can circumvent this by using half (or smaller) sized images. You could even use some of the normal screen RAM as the cache provided you hide it from view by altering the screen registers as discussed in the DIY SCREENS article.

Christopher Dewhurst
Witham, 28 December 2002

Omnibus Edition Note:


Listing E.DEMO5B are the lines of DEMO5 that need to be altered to give the 'laser' effect.