EUG #63 Opener Explained

By Chris Dewhurst

Originally published in EUG #63

Opening this EUG is a demo giving the appearance of someone running around the edges of your monitor screen, throwing pebbles into the centre. These pebbles land to form the words "Electron User Group 63".

First, the program calculates the co-ordinates of each pebble that makes up the letters of the message. This is done by examining the bits of the character definitions using OSWORD 10. PROCassem1 is the code for this. If you have seen my BBC Micro Demo 2, then STORE in PROCassem2 is just a faster equivalent of the Basic prodecure PROCstore(a$,ox%,oy%).

a$ is the string of characters whose bit definitions are to be converted into co-ordinates beginning at (ox%,oy%). It's stored at TEXT and TXTPTR, the text pointer, is the index into it. The X and Y registers point to location &80 in zero page, and a call to OSWORD with A=10 returns the eight lines of the character definition in &81-&88.

Each line is inspected by loading it into the Accumulator and shifting left the 8 bits in turn into the Carry. If C=1 the current x y co-ordinates are inserted into XTARG and YTARG, tables of the target x and y co-ordinates at pages &12 and &13, respectively. The index into the tables is held in location &72, and at the end of the routine this con- tains the total number of pebbles.

The values of each line of the character definition are multiplied by two and ANDed with the original value. This produces thin text, for the simple reason that it reduces the number of points that need to be stored. But this is not done if the character is a user-defined one, i.e. the ASCII code is <127 (a positive number in two's complement). So they can be used as they are. For example, The word "Electron" for instance, has to be defined in this way else it won't fit on the screen!

Note then, that normally you can only have up to 5 giant letters on each line of the screen. A pebble takes up 1 column (8 bytes) and the Mode 5 screen is 40 columns wide. Also, there mustn't be more than 255 pebbles as the animation routine can only address that number of bytes.

Once STORE has worked out the co-ordinates, it isn't needed any more so PROCassem2, the animation routine proper, overwrites it. Assembly starts at &1400, just after the end of the tables of the target co-ordinates. The idea behind this is that you can save out the entire demo as a *RUNnable machine code file later.

XPTS and YPTS are two more tables holding the initial co-ordinates of the pebbles before they start flying toward their target positions. Each entry is set to zero before anything happens (CLEAR), and LOOP initially sets the co-ordinates to a point on the edge of the screen. This point advances clockwise, going from (0,1) to (39,1); then (39,1) to (39,31); (39,31) to (0,31); (0,31) to (0,1); (0,1) to (39,1) etc.

The x co-ordinate, XSTART, is in columns, and the y co-ordinate, YSTART is the character row number. As we said, there are 40 columns across the Mode 5 screen, and one column is a stack of 8 bytes. (A normal-size text character occupies 2 columns so there are 20 characters across the screen.) The direction is held in DIR, which for labelling convenience is associated with the four compass points: 0=east, 1=south, 2=west, 3=north.

Every time a new pair of co-ordinates is initiated, PATH is called to animate that pebble and all other pebbles already in motion. Just before this, a call is made to Osbyte with A=19. It's the equivalent of *FX19 and waits for the start of the next screen refresh; helping smooth the animation. If the value at the current position in YPTS is 0, it means the pebble has not yet been set going. We need that zero to flag that this is the case, so that's why the y points going round the edges of the screen run from 1 to 31 and not 0 to 31.

If the pebble's y co-ordinate (we'll call it YPT) is equal to YTARG (the target y co-ordinate) and the x co-ordinate (XPT) is equal to XTARG then the pebble has reached its target position and the routine drops through to INPOS. If YPT <> YTARG and XPT <> XTARG, the pebble is erased and plotted at a new position.

This new position is worked out as follows. If XPT < XTARG, we branch to WESTOF because the pebble is to the west (left) of its target and is INCremented to move it to the east/right. On the other hand, if XPT > XTARG, it needs to be DECremented. If it's now 0, we drop through to WESTOF (which, as we just said, moves it to the right).

Similarly, if YPT < YTARG, it is to the north (top) of the target and needs to be INCremented. If YPT > YTARG and DECrementing it results in 0, we drop through to NORTHOF which INCrements it again. We now have reached INPOS which will print the pebble at its new co-ordinates.

The erasing and printing is done by ERASE and PRINT respectively. They both call CALC to calculate the screen address. CALC assumes that the X register holds the current pebble number as an index into the current y co-ordinate which itself becomes an index into SCRTAB. This is a table of addresses of the start of each of the 32 character lines. They are stored as 32 low bytes followed by 32 high bytes. This saves trying to multiply the index by 2 and using it to index into a table of 32 two-byte pointers stored low-byte high-byte fashion.

The column number (XPT) is multiplied by 8 to get the offset from the address obtained from SCRTAB. We only need the one ROL SCR+1 after three ASL As, because the maximum that the column number can be is 39. After one ASL A, this would become 78, which still can be contained in one byte. After the second ASL A, it becomes 156, again still a one-byte number. Only after the third ASL A would it reach 312 which is a two-byte number.

The pebble data is held at PEBDAT, and PEBBLE copies the 8 bytes into the screen RAM at the address in SCR. ERASE just overwrites eight bytes in the screen with zeros.

Now let's return from PATH to the main routine. It could be that all the pebbles have been set in motion by the time COUNT reaches zero, but not all of them have reached their target. The TIDY routine tidies up by calling PATH at least enough times to get all of the remaining pebbles to their targets. If you are trying your own message and find that some pebbles still haven't reached their finishing positions, just increase that 25 in line 560.

To save the demo as machine code, type: *SAVE DEMOMC 1200 173B 1400

&1200 is the start of the XTARG table. &173B is the value of PRINT~P%, which tells you where the next machine code instruction would be assembled to if you had any more machine code to assemble. If you get a different answer, substitute it for the &173B. &1400 is where execution starts (the value you should get if you type in PRINT~store).