Personal Computer News
1st September 1984
Author: John Lettice
Published in Personal Computer News #076
It's possible to print on the Spectrum screen's bottom two lines with John Lettice's program.
Full Display
It's possible to print on the Spectrum screen's bottom two lines with John Lettice's program
Every now and again you'll run across a problem that would be solved if you could print on the bottom two lines of the Spectrum's screen. You might, for example, be writing a graphics program, where you need the whole screen for drawing on, or you might just grudge losing the extra two lines space.
You can get an image on the bottom two lines of the screen by POKEing numbers into the relevant parts of the display file, so the logical way of dealing with the problem is to find some mechanism that allows you to do this. Try:
10 FOR N=16384 TO 22527
20 POKE N,255
30 NEXT N
As this one flashes by, you'll see the whole screen filled, then the INK on the bottom two lines will be wiped out by the appearance of the OK prompt. Add:
40 GO TO 40
and you should have proved to yourself that it's possible to get an image on the report lines.
The Spectrum's display file runs from memory locations 16384 tpo 22527, so what you're doing is POKEing 255 into each of these. But think about the disadvantage: run the program again, and you'll see that the screen is actually built up in a very bizarre way. First the top line of pixels in the first row of character positions is INKed in, then the top line of the second row, and so on until it doubles back to the second row of pixels, then onto the next part of the screen, and then the next.
POKEs
Line | Start of Line | End of Line |
---|---|---|
0 | 16384 | 16415 |
1 | 16416 | 16447 |
2 | 16448 | 16479 |
3 | 16480 | 16511 |
4 | 16512 | 16543 |
5 | 16544 | 16575 |
6 | 16576 | 16607 |
7 | 16608 | 16639 |
8 | 18432 | 18463 |
9 | 18464 | 18495 |
10 | 18496 | 18527 |
11 | 18528 | 18559 |
12 | 18560 | 18591 |
13 | 18592 | 18623 |
14 | 18624 | 18655 |
15 | 18656 | 18687 |
16 | 20480 | 20511 |
17 | 20512 | 20543 |
18 | 20544 | 20575 |
19 | 20576 | 20607 |
20 | 20608 | 20639 |
21 | 20640 | 20671 |
22 | 20672 | 20703 |
23 | 20704 | 20735 |
Table 1. Display Memory Map |
Table 1 illustrates the full awful truth about the Spectrum's screen layout, and shows you that using POKEs to print at any one character position isn't exactly straightforward.
Don't panic, though, because there's a system behind it, and all you need to do is work out the formula. The next thing you need to do is work out the dot patterns you POKE into the character positions using this formula. If you want to produce user-defined characters in the report lines, then you're pretty much on your own, although it would be fairly easy to copy user-defined graphics you'd already produced into the correct memory locations.
If you want to use the Spectrum's own character set, life's quite easy, as you just have to copy the dot patterns for the character set across from ROM into the screen locations. This is less of a headache, since the dot patterns for each character are held in eight consecutive addresses.
What we want, then, is a routine that will PEEK the values held in ROM for the character set dot patterns, then POKE them into the screen addresses for the relevant character position. The routine presented here is slower than printing on the screen normally, mainly because the program is in Basic, but it's quite adequate for static displays you're not likely to want to change too often.
Turning the text you want printed into DATA statements would be marginally faster, but would lose you the advantage of having a universally applicable formula. Another alternative would be to store the memory locations in DATA statements or in an array, then PEEK the ROM pattern and POKE that into the location, but although this would be faster, you'd lose the advantage of the formula.
If you want to put your own message at the bottom of the screen then it's just a matter of changing a$, making sure you use 64 characters for it.
Program Notes
10 | Dimensions an array of 64 characters |
20 | Defines the array |
30-90 | Main loop of the program |
40 | Defines B as the CODE of each of the characters in A$, one at a time |
50 | Determines the address of the first line of each character in ROM in the following way. The dot patterns of the character set start at 15360, and the CODEs of the characters increase in steps of 1, i.e. A is 65 and B is 66. As each character occupies eight addresses, its start address is 8* (its CODE). |
60 | Determines the address of the first line of each of the 64 character positions to be POKEd into |
80 | Loops through the eight pixel lines of each character position. Each character position's start address is 256 below the address of the line of pixels immediately below it, so 256*P gives you each address. It then PEEKs the address of the correct dot pattern and POKEs it in. |
Code
10 DIM A$(64)
20 LET A$="THE BOTTOM LINE IS THIS 12345678901234567890123456789012"
30 FOR N=1 TO 61
40 LET B=CODE A$(N)
50 LET C=15360+B*8
60 LET D=20671+N
70 FOR P=0 TO 7
80 POKE D+(256*P),PEEK (C+P)
90 NEXT P:NEXT N
100 PAUSE 0