MULTI-SCROLL by Alan Davis from ZX Computing June 1987 Alan Davis presents an all-purpose scrolling utility. [NOTE: The file "SourceCode" in MULTSCRL.TAP is an assembler source] [file which I created with the OCP Editor/Assembler. JimG] Broadly speaking, I suppose there are really only two ways of presenting text on screen in an adventure game. Probably the simplest is to use straightforward PRINT statements in which strings of text are printed from some specified screen line downwards. This is a method more commonly encountered in older games, perhaps. There's nothing actually wrong with it as a system, except for the (relatively minor) disadvantage that the relevant part of the screen needs to be cleared completely before each fresh printing - obliterating whatever went before, of course. The alternative method - and the one almost universally used these days in commercial games - is the continuous scrolling one. With this system, text is printed one line at a time to a particular screen position, and the screen is scrolled upwards by one line between each printing. In a text-only adventure this isn't difficult to achieve because the well-known USR call to the Spectrum ROM (3582) can be used to scroll the entire screen in between the printing of each line of text. However, suppose you're writing a graphic adventure in which the picture forms part of the permanent display - with the text scrolling continuously in a window underneath it. Unfortunately, the ROM can't help you much here. On the other hand, perhaps you're looking for a different style of presentation altogether? One (rather controversial) game in the role-playing mould is "Out of the Shadows", in which a small map forms a permanent part of the display, with text continually scrolling in a narrow column up the right hand side of the screen. You really can't attempt this sort of thing in BASIC, can you? There's a lot to be said for trying out unusual methods of on-screen presentation, in fact. There's a tendency for some adventure authors to settle on one particular style and then stick with it, but if this is overdone it isn't long before a certain monotony sets in. The player begins to feel that the the adventure is just another "production-line" effort - and you don't have to look far to find examples. The old "Mysterious Adventures" series had a strong tendency in this direction, and some of the more recent releases by US Gold show all the signs of heading the same way. So it isn't only the Quilled and GAC'd games which fall into stereotyping trap. Of course we all know that mere appearance isn't the be-all and end-all of adventure writing, but there's no doubt that it can help to offset that "seen it all before" impression. Wouldn't it be useful to have an off-the-shelf utility which could cater for all likely styles of presentation? For a long time I've tended to take a short term view, writing printing and scrolling routines specifically for the job currently in hand - consoling myself that "one of these days" I'd get around to writing a suitable "all-purpose" utility that could be used for all conceivable situations. Well, "one of these days" has arrived at last; "Multi-Scroll" is about to be launched upon an astonished world. What we want, essentially, is to be able to define a "window" of any size, anywhere on the screen, so that text can be printed to the bottom of the window and scrolled continuously upwards until it disappears at the top of the window. If we could define INK and PAPER colours for the window, independently of the screen colours elsewhere on the screen, then that would be useful, and it might also be handy to have a simple method for clearing the window completely. Finally, we want to be able to do the actual text printing from BASIC without worrying about whether the individual text lines fit the window, and so we need a suitable word-wrapping routine as well. Available Services All these facilities are available with Multi-Scroll, and at your service. Listing 1 [see MULTSCRL.ASM] is the assembly program - and as always, I strongly recommend that you use this in conjunction with an assembler - but Listing 2 [see below] provides a decimal dump of the machine code (for those who've not yet seen the light). As you'll see, the code is stored from address 64800 onwards, and is 474 bytes long. You'll need a BASIC loader program if you're using the decimal dump, but if you rifle through some back issues of ZXC you'll find something suitable that you can modify (don't forget to CLEAR 64799 before you start). I've annotated the assembler listing in plenty of detail, so I'll confine my remarks here to a general outline of Multi-Scroll, and how to use it. The machine code consists of essentially four separate routines, each of which can be used from within a BASIC program as required: 1) SCROLL (USR 64825). This scrolls the chosen window upwards by one line. There are several ways of tackling this, and the method I've adopted here uses a table of screen line addresses to minimise the complexities brought about by the Spectrum's eccentric display file. (You can find a more detailed discussion of this approach in Pete Cooke's article in the March issue.) 2) ATTR (USR 64933). This washes the window with the chosen INK and PAPER colours. Note that it doesn't clear the window - it only changes the colours for whatever is already there, and for any subsequent printing. 3) CLEAR (USR 65010). This performs as many scrolls as there are lines of characters in the window; in other words, everything previously printed in the window will be scrolled upwards and off the top, leaving the window clear. 4) WRAP (USR 65084). Regular readers will have encountered similar routines to this in one or two of my previous articles but we require greater flexibility here, and this one represents (I hope!) my last word on the topic. Its purpose is to print text held in the BASIC variable z$ in the window, scrolling the lines and word-wrapping as necessary - so you don't need to worry about padding your text with spaces to make it fit the window; this routine will sort all that out for you. The only limitation is that LEN z$ should not exceed 255 (which means that for really long chunks of text, you'll need to break it into separate sections - and you'd probably do this anyway to avoid textual claustrophobia on-screen.) This, then, is what Multi-Scroll does - but how do we control it from BASIC? Very simple. There are six addresses whose contents determine the behaviour of the routines, and these should be POKED with suitable values before the routines are used. Four control the size and position of the window, and two control the colours as follows: 1) The limits of the window are defined using the four addresses from 65025 to 65028 inclusive (labels TOP, BOT, LEFT, and RIGHT respectively - see Listing 1). Think in terms of the Spectrum's normal system of identifying character squares, and set the limits accordingly. For example, if you POKE 65025,19: POKE 65026,21 then your window will be three lines high (with line 21 the bottom line to which printing is done). POKE 65027,0: POKE 65028,31 will set the left and right limits so that your window will occupy the whole width of the screen (from character square 0 to character square 31). Incidentally, no check is made for invalid screen positions within the routines, so don't go poking any old numbers in here! 2) The colours (from 0 to 7 inclusive, as usual) are defined using addresses 65029 and 65030 (INK and PAPER respectively). Again, no check is made for invalid colours. Other uses Although the most obvious use for Multi-Scroll is in a graphic adventure game, with text scrolling continuously below an illustration of some kind, there's nothing to stop you from using it in other contexts, perhaps with several windows on screen at once, by setting up a small number of BASIC subroutines to define them. To show how this can be done, and to illustrate all the things we've been talking about, I've given in Listing 3 a short demonstration program which will put Multi-Scroll through its paces for you. Notice that the various USR call and POKE addresses are allocated to suitably named variables in lines 30 to 50; this makes for improved readability, and saves you looking up the numbers each time. Save the demonstration program to auto-run from line 1 - if you're working from tape rather than microdrive, you'll need to change the LOAD instruction in line 10, and save the machine code block immediately after the BASIC. If you follow what's happening on screen, comparing it carefully with the listing, you should rapidly get the hang of things. Have fun ... = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Listing 2 [NOTE: The last number on each line is a checksum. JimG] 64800 58 1 254 71 58 2 64805 2 254 144 60 50 10 64810 10 254 58 3 254 71 64815 71 58 4 254 144 60 64820 60 50 9 254 201 205 64825 205 32 253 33 12 254 64830 254 237 75 1 254 6 64835 6 0 9 9 34 7 64840 7 254 42 7 254 94 64845 94 35 86 229 42 3 64850 3 254 38 0 25 235 64855 235 225 58 10 254 61 64860 61 254 0 202 141 253 64865 253 50 10 254 35 34 64870 34 7 254 78 35 70 64875 70 42 3 254 38 0 64880 0 9 6 8 197 237 64885 237 75 9 254 6 0 64890 0 229 213 237 176 225 64895 225 209 1 0 1 9 64900 9 235 9 193 16 234 64905 234 195 74 253 6 8 64910 8 197 213 58 9 254 64915 254 71 175 18 19 16 64920 16 252 209 1 0 1 64925 1 235 9 235 193 16 64930 16 235 201 205 32 253 64935 253 58 6 254 7 7 64940 7 7 71 58 5 254 64945 254 128 50 11 254 33 64950 33 0 88 17 32 0 64955 0 58 1 254 71 175 64960 175 184 202 202 253 5 64965 5 25 195 192 253 237 64970 237 91 3 254 22 0 64975 0 25 34 7 254 58 64980 58 10 254 71 197 58 64985 58 9 254 71 58 11 64990 11 254 119 35 16 252 64995 252 42 7 254 17 32 65000 32 0 25 34 7 254 65005 254 193 16 231 201 205 65010 205 32 253 58 10 254 65015 254 71 197 205 57 253 65020 253 193 16 249 201 0 65025 0 21 0 31 0 7 65030 7 0 0 0 0 0 65035 0 0 64 32 64 64 65040 64 64 96 64 128 64 65045 64 160 64 192 64 224 65050 224 64 0 72 32 72 65055 72 64 72 96 72 128 65060 128 72 160 72 192 72 65065 72 224 72 0 80 32 65070 32 80 64 80 96 80 65075 80 128 80 160 80 192 65080 192 80 224 80 205 32 65085 32 253 42 75 92 126 65090 126 254 90 202 79 254 65095 254 205 184 25 235 195 65100 195 66 254 35 126 50 65105 50 246 254 35 35 34 65110 34 248 254 205 150 254 65115 254 254 1 202 200 254 65120 254 205 174 254 205 200 65125 200 254 42 248 254 237 65130 237 91 247 254 22 0 65135 0 25 34 248 254 58 65140 58 247 254 71 58 246 65145 246 254 144 50 246 254 65150 254 42 248 254 126 254 65155 254 32 194 89 254 35 65160 35 34 248 254 58 246 65165 246 254 61 50 246 254 65170 254 195 127 254 58 9 65175 9 254 198 1 71 58 65180 58 246 254 184 218 165 65185 165 254 175 201 58 246 65190 246 254 50 247 254 62 65195 62 1 201 42 248 254 65200 254 58 9 254 95 22 65205 22 0 25 126 254 32 65210 32 194 195 254 123 50 65215 50 247 254 201 27 43 65220 43 195 184 254 205 57 65225 57 253 58 142 92 245 65230 245 62 63 50 142 92 65235 92 62 2 205 1 22 65240 22 62 22 215 58 2 65245 2 254 215 58 3 254 65250 254 215 237 91 248 254 65255 254 237 75 247 254 6 65260 6 0 205 60 32 241 65265 241 50 142 92 201 0 65270 0 0 0 0 0 0 CHECKSUM 67338 -- Another Fine Product transcribed by: Jim Grimwood, Weardale, England (http://www.users.globalnet.co.uk/~jimg/) --