Автор: Clyde W. Bish
Год: 1985
Издатели: ZX Computing
Языки:
Английский
Формат:
TZX лента
Требования:
ZX Spectrum 16K
Ссылки:
Страница на ZXArt
Страница на World Of Spectrum
Страница на Spectrum Computing
Скриншоты:
Год: 1985
Издатели: ZX Computing
Языки:
Формат:
Требования:
Ссылки:
Скриншоты:
A Present from Uncle
Our thanks to Psion for letting us use
their routine and to regular Exeter
contributor Clyde Bish for explaining
how to use it to the full.
[ As is clear from the first paragraph, this article, and
the set of programs that go with it, deals with a machine
code routine found on the Horizons tape. I have chosen
not to replicate that routine on the TZX that goes with
this text file. The Horizons tape itself can be found on
the internet - if nowhere else, certainly on World of
Spectrum and presumably on the TZX Vault.
Note that all but the first of these programs do require
the machine code routine to be present in memory to work,
and none of them except the second auto-load it. This is
as it was in the magazine listings. They're short enough
that it is possible to read through this whole article in
one sitting, so it should be no problem to load the
routine once and then load the Basic programs one after
another.
Richard Bos, March 2011 ]
Aren't we lucky having a kind Uncle - or should it be Sir
Uncle? - who gives us a present with our Spectrums! No, not
the "Horizons" tape per se, but a particularly useful
routine hidden within its bytes. If you'd like to have
titles and messages in large letters, Horizons style, then
read on. All will be revealed.
It's all done by a machine code routine LOADed to add-
ress 32256 (these are the bytes which autoLOAD before a
program RUNs). Like most presents you have to know just
what it will do before you can use it to best advantage.
Here are some ideas.
First things first. How does the routine work? I'm not
going to bore you with details about the mechanics of the
code. If you want to "dissect" it, a disassembly is given
in Table A. [This table has been omitted from this file.
These days you can get a better one from your emulator.]
Suffice it to say that information on width and height
multipliers (variables xs and yx respectively), codes of
characters to be PRINTed, vertical start position, and
horizontal start position (calculated by the program) are
fed into the printer buffer. This is simply used as a
convenient dump from where the routine will pick up the
information it needs. (If you've wondered why anything
LPRINTed after the print routine has been used is preceded
by a black band, this is the information still left in the
buffer.) The machine code routine searches the ROM charac-
ter table for the character to be printed, then produces a
pattern of pixels on screen which is xs times wider and ys
times taller than the original. If you want to see how this
works type in and RUN Program 1. This is a Basic simulation
of the routine. It's slow, but it will demonstrate the
principles. (Incidentally it does produce quite nice titles
in its own write (sic).) Try it and you'll see.
But more of the mechanics later. Let's see the routine
in action. First you need the routine in the machine.
Simply type
CLEAR 32255: LOAD "c"CODE 32256
Press ENTER and play Side B of your Horizons tape.
You'll get some programs and bytes listed first but after
about 2 minutes the code you need will LOAD in. When the OK
message appears, stop the tape, type in program 2, RUN it
and experiment. For example, try 2 for width and 3 for
height. You'll find that the letter H which appears will be
twice as wide and three times as tall as normal. Try 5 and
2. This time the H will be 5 times as wide and twice as
tall as usual. The width limit is 32. (Try answering the
INPUT prompts with 32 and 1!) Anything wider will "wrap".
Try a width of 40 to see what I mean. The height limit is
22. Anything larger will prove problematic!
When you've experimented for long enough, break out of
the INPUT with STOP, then LIST. The listing before you is
the most important you'll come across with regard to the
Print routine. It's the driver which supplies the routine
with the information it needs to operate. So, let's have a
close look. As you already know, xs is the width multiplier
and ys the height multiplier. Variable yy is the distance
down the screen (in pixels) - 0 is the top row, and p$ the
character(s) to be PRINTed. The subroutine to load this
information into the printer buffer starts at line 9998.
Variable xx - the start position across the screen - is
calculated first to ensure that the printing is central on
screen. We'll put this line to more effect (or over-ride
it!) later. The POKEs in line 9999 put the variables into
the buffer (along with an 8 and 255 as markers) before the
machine code routine is called by the USR command. After
printing, a return is made to the main program.
Before we leave the driver subroutine try the effect of
altering yy (edit line 30). Similarly p$ can be changed -
try more than once character. TO see the effect of line
9998 add lines
45 LET xx=(any value, try 0)
47 GO SUB 9999: GO TO 60
At this point, it would be a good idea to SAVE the BASIC
subroutine and code, ready to merge it with your programs
in the future, rather than having to keep finding it on the
Horizons tape. To do this, delete lines 1 to 70, leaving
just the subroutine, add line
9997 CLEAR 32255: LOAD ""CODE: STOP
then SAVE both program and code using
SAVE "print"LINE 9997: SAVE "c"CODE 32256,300
and VERIFY both program and code. [This is not on the TZX.
The problem of locating a bit of code on Horizons B.tzx is
not as time-consuming as doing so on the tape.]
O.K., you've seen the good news; now the bad. The prob-
lems. If you 48K owners have tried LOADing the code into a
high address, you will have discovered that calling it
causes a "crash". You'll find the reason staring you in the
face in the disassembly (Table A). Look at lines (addres-
ses) 32341, 32361 and 32409 and you'll see the letters (op
code) JP followed by a number. This is called an absolute
jump. It means that when the routine reaches this point it
will jump to the address given. This is correct if you've
loaded the code in at 32256 but start anywhere else, and
all the jumps will be wrong. Hence the crash. The answer -
alter the addresses. Program 3 (supplied by our illustrious
Editor [Ray Elder]) will do just that. In essence what it
does is to POKE new (corrected) values into those JP com-
mands, the values being calculated from where you start.
SAVE it with
SAVE "print"CODE (start address),300
and remember to CLEAR (start address - 1) before you LOAD
it back in as part of a program. One word of warning. Don't
answer the "Start address" prompt with a value greater than
65067 or you'll lose the end of the routine! [There are two
versions of this program on the TZX. "Program 3a" is as it
appeared in ZX Computing, but it contains an interesting
and ironic bug which I couldn't resist including for, ahem,
educational reasons. "Program 3b" includes the natural
bugfix.]
UDGs
That's relocation solved, now for problem two. Run Program
2, but first replace the "H" with a user-defined graphic
(UDG for short). Any letter will do. What appears on
screen? Nothing. The reason for this is again found in
Table A. Look at the line of op code at address 32272. The
number in brackets is the address of a system variable
called CHARS. This holds a two byte (number) value - nor-
mally 0 and 60 - which tells the computer where to look (in
the ROM) for the character set - the 8 x 8 pattern of pix-
els which make up each of the characters. The Print machine
code looks through this set to find a match for the charac-
ter you want printer. As /you/ design the UDGs no match is
found - hence the blank screen.
The solution to the problem is quite simple (although it
took me some time to fathom). What you have to do is con-
vince the machine that the character set it wants to look
at is not in the ROM but up in the UDG area. Look at Pro-
gram 4. Line 5 is there simply to make the UDGs different
from normal capitals (by underlining top and bottom). In
line 10 "ABCDE" must be entered in Graphics mode, although
they won't appear underlined until after the program is
RUN. The POKEs following it are the key. They tell the
machine that the set it wants begins at address 64216
(216 + (250 x 256)). USR "a", the first byte of the UDGs is
at 65368. The difference, 1152, divided by 8 (the number of
bytes/character) is 144, and 144 is the code of the first
UDG! If the logic of this has lost you, don't worry, just
POKE 216 and 250 (216 and 122 if you have a 16K machine).
The POKEs at the end of line 20 reset CHARS to its ori-
ginal position. Otherwise the error messages and listing
would be unreadable.
Rolling titles
So, now we can use UDGs what do we do with them! (Apart
from their straightforward use in titles). Here's a couple
of ideas. I call them rolling titles. They are interesting
in that they make use of the ROM character set to redesign
the UDGs.
Program 5 displays the word "SCROLL", then gradually
rolls it away leaving a blank space. This can be especially
effective if it appears in a window surrounded by a diffe-
rent colour background. The DATA line supplies the first
POKE within the loop in line 5, with the UDG to be altered,
then the start address in ROM where the pixel pattern for
the replacement letter begins. Refer to Table B [a simple
table of some characters and their charset addresses in
ROM - 15616 for space, 15880 for A, 15888 for B and so on.
I haven't replicated it, since it's easy to create your own
should anyone want it] and you will see that 16024 is the
start of S, 15896 of "C" and so on for the word SCROLL. The
reason for alternate UDGs being redefined becomes apparent
in the second POKE. This POKEs the unaltered UDGs between,
with 0 - a blank space. The letters for p$ in line 10 must
be entered as UDGs (as yet not redefined). When the program
RUNs, it displays the POKEd patterns, but moving up one
byte each time it loops in line 10 so that the top line is
lost and the blank lines of the redefined spaces move in to
take the place. The best way to understand how this program
(or any other) works is to put in a word of your own. (If
you want other than 6 letters then you will have to alter
the limit number in the f loop of line 5.) Use Table B to
get the DATA numbers you need, and remember, the UDGs must
be used alternately. Good luck.
Program 6 is an extension of this roller idea where,
instead of blanks, a second word (TITLES) is redefined. So,
as SCROLL rolls off, TITLES rolls on. Incidentally, if you
want to use a character set other than that in the ROM, you
can define your own in the RAM and point the machine code
routine to it by setting CHARS to 256 less than the start-
ing address. I'll leave designing the new set to you (or
you can crib it from an earlier mag).
Now for something easier. Obviously you can use the
routine for titles, Horizons style, but how about some ani-
mations? Programs 7, 8, 9 and 10 use the routine to produce
such effects.
Program 7 puts each successive word in the same place on
screen as the previous one, but makes it larger (and a dif-
ferent colour) so that the title "zooms in".
Program 8 reverses this procedure, so parts of previous
words remain giving a blocked effect.
Programs 9 and 10 are similar to Program 8 but also move
the print position so that the title shifts up or down the
screen giving a perspective effect.
Clearing the screen
And now for something completely different. Spaces. The
routine will quite happily print these and give interesting
CLS effect. Actually, it's more of a "wipe". Programs 11
and 12 will demonstrate. The former clears the screen in a
series of 8 left to right wipes starting at the top, where-
as the latter clears in a series of vertical lines starting
from the left. In each case line 10 just fills the screen
for wiping. Try experimenting with other values for xs and
ys. (xs must divide exactly into 32.) If you add a state-
ment such as PAPER 4 then you will clear and change the
screen colour at the same time.
You can also use the printing spaces technique to clear
just part of the screen (a window). Try Program 13. This
will produce a central cleared area 48 pixels down from the
top, with the window 16 characters wide and 8 deep. If you
want to clear a window to right or left of screen centre
then you will have to set variable xx as well and call the
routine at line 9999, not 9998 - see Program 14.
Computers normally print characters to screen by justi-
fying to the left - like a typewriter. That is they produce
a straight left-hand and a ragged right-hand margin. A book
(or this magazine) is printed with right and left justifi-
cation. Both margins are straight. [Note that, unlike the
original article, this plain-text file has a ragged right
margin.] A word processor does the same. Program 15 justi-
fies to centre, meaning that each line of print is balanced
about the mid line and so the left and right margins are
even [or rather, identically uneven]. This gives a pleasing
look to on-screen instructions. In outline, the program
takes the contents of the string held in a$, chops it
up into lines of maximum length 32 characters, without
chopping words, and then uses the machine code routine to
balance each of those lines centrally on screen. As print-
ed, the listing gives normal size characters, but you
could, for example, change to double size by altering ys
and xs to 2, and changing all 32s to 16 and 33s to 17.
To end, here is a Really Useful Program (as Pooh would
say). Program 16 will produce cassette lables if you have
a printer. The titles are printed twice normal print size,
and appear both on the spine and on the side of the lable.
The straight lines printed show you where to fold to fit
the box. If you want to make a complete cover for the side
(and can afford the paper) add some LPRINTs before COPY to
make it long enough.
Well, there are the ideas. From now on it's up to you.
Have fun with Uncle's present!
Our thanks to Psion for letting us use
their routine and to regular Exeter
contributor Clyde Bish for explaining
how to use it to the full.
[ As is clear from the first paragraph, this article, and
the set of programs that go with it, deals with a machine
code routine found on the Horizons tape. I have chosen
not to replicate that routine on the TZX that goes with
this text file. The Horizons tape itself can be found on
the internet - if nowhere else, certainly on World of
Spectrum and presumably on the TZX Vault.
Note that all but the first of these programs do require
the machine code routine to be present in memory to work,
and none of them except the second auto-load it. This is
as it was in the magazine listings. They're short enough
that it is possible to read through this whole article in
one sitting, so it should be no problem to load the
routine once and then load the Basic programs one after
another.
Richard Bos, March 2011 ]
Aren't we lucky having a kind Uncle - or should it be Sir
Uncle? - who gives us a present with our Spectrums! No, not
the "Horizons" tape per se, but a particularly useful
routine hidden within its bytes. If you'd like to have
titles and messages in large letters, Horizons style, then
read on. All will be revealed.
It's all done by a machine code routine LOADed to add-
ress 32256 (these are the bytes which autoLOAD before a
program RUNs). Like most presents you have to know just
what it will do before you can use it to best advantage.
Here are some ideas.
First things first. How does the routine work? I'm not
going to bore you with details about the mechanics of the
code. If you want to "dissect" it, a disassembly is given
in Table A. [This table has been omitted from this file.
These days you can get a better one from your emulator.]
Suffice it to say that information on width and height
multipliers (variables xs and yx respectively), codes of
characters to be PRINTed, vertical start position, and
horizontal start position (calculated by the program) are
fed into the printer buffer. This is simply used as a
convenient dump from where the routine will pick up the
information it needs. (If you've wondered why anything
LPRINTed after the print routine has been used is preceded
by a black band, this is the information still left in the
buffer.) The machine code routine searches the ROM charac-
ter table for the character to be printed, then produces a
pattern of pixels on screen which is xs times wider and ys
times taller than the original. If you want to see how this
works type in and RUN Program 1. This is a Basic simulation
of the routine. It's slow, but it will demonstrate the
principles. (Incidentally it does produce quite nice titles
in its own write (sic).) Try it and you'll see.
But more of the mechanics later. Let's see the routine
in action. First you need the routine in the machine.
Simply type
CLEAR 32255: LOAD "c"CODE 32256
Press ENTER and play Side B of your Horizons tape.
You'll get some programs and bytes listed first but after
about 2 minutes the code you need will LOAD in. When the OK
message appears, stop the tape, type in program 2, RUN it
and experiment. For example, try 2 for width and 3 for
height. You'll find that the letter H which appears will be
twice as wide and three times as tall as normal. Try 5 and
2. This time the H will be 5 times as wide and twice as
tall as usual. The width limit is 32. (Try answering the
INPUT prompts with 32 and 1!) Anything wider will "wrap".
Try a width of 40 to see what I mean. The height limit is
22. Anything larger will prove problematic!
When you've experimented for long enough, break out of
the INPUT with STOP, then LIST. The listing before you is
the most important you'll come across with regard to the
Print routine. It's the driver which supplies the routine
with the information it needs to operate. So, let's have a
close look. As you already know, xs is the width multiplier
and ys the height multiplier. Variable yy is the distance
down the screen (in pixels) - 0 is the top row, and p$ the
character(s) to be PRINTed. The subroutine to load this
information into the printer buffer starts at line 9998.
Variable xx - the start position across the screen - is
calculated first to ensure that the printing is central on
screen. We'll put this line to more effect (or over-ride
it!) later. The POKEs in line 9999 put the variables into
the buffer (along with an 8 and 255 as markers) before the
machine code routine is called by the USR command. After
printing, a return is made to the main program.
Before we leave the driver subroutine try the effect of
altering yy (edit line 30). Similarly p$ can be changed -
try more than once character. TO see the effect of line
9998 add lines
45 LET xx=(any value, try 0)
47 GO SUB 9999: GO TO 60
At this point, it would be a good idea to SAVE the BASIC
subroutine and code, ready to merge it with your programs
in the future, rather than having to keep finding it on the
Horizons tape. To do this, delete lines 1 to 70, leaving
just the subroutine, add line
9997 CLEAR 32255: LOAD ""CODE: STOP
then SAVE both program and code using
SAVE "print"LINE 9997: SAVE "c"CODE 32256,300
and VERIFY both program and code. [This is not on the TZX.
The problem of locating a bit of code on Horizons B.tzx is
not as time-consuming as doing so on the tape.]
O.K., you've seen the good news; now the bad. The prob-
lems. If you 48K owners have tried LOADing the code into a
high address, you will have discovered that calling it
causes a "crash". You'll find the reason staring you in the
face in the disassembly (Table A). Look at lines (addres-
ses) 32341, 32361 and 32409 and you'll see the letters (op
code) JP followed by a number. This is called an absolute
jump. It means that when the routine reaches this point it
will jump to the address given. This is correct if you've
loaded the code in at 32256 but start anywhere else, and
all the jumps will be wrong. Hence the crash. The answer -
alter the addresses. Program 3 (supplied by our illustrious
Editor [Ray Elder]) will do just that. In essence what it
does is to POKE new (corrected) values into those JP com-
mands, the values being calculated from where you start.
SAVE it with
SAVE "print"CODE (start address),300
and remember to CLEAR (start address - 1) before you LOAD
it back in as part of a program. One word of warning. Don't
answer the "Start address" prompt with a value greater than
65067 or you'll lose the end of the routine! [There are two
versions of this program on the TZX. "Program 3a" is as it
appeared in ZX Computing, but it contains an interesting
and ironic bug which I couldn't resist including for, ahem,
educational reasons. "Program 3b" includes the natural
bugfix.]
UDGs
That's relocation solved, now for problem two. Run Program
2, but first replace the "H" with a user-defined graphic
(UDG for short). Any letter will do. What appears on
screen? Nothing. The reason for this is again found in
Table A. Look at the line of op code at address 32272. The
number in brackets is the address of a system variable
called CHARS. This holds a two byte (number) value - nor-
mally 0 and 60 - which tells the computer where to look (in
the ROM) for the character set - the 8 x 8 pattern of pix-
els which make up each of the characters. The Print machine
code looks through this set to find a match for the charac-
ter you want printer. As /you/ design the UDGs no match is
found - hence the blank screen.
The solution to the problem is quite simple (although it
took me some time to fathom). What you have to do is con-
vince the machine that the character set it wants to look
at is not in the ROM but up in the UDG area. Look at Pro-
gram 4. Line 5 is there simply to make the UDGs different
from normal capitals (by underlining top and bottom). In
line 10 "ABCDE" must be entered in Graphics mode, although
they won't appear underlined until after the program is
RUN. The POKEs following it are the key. They tell the
machine that the set it wants begins at address 64216
(216 + (250 x 256)). USR "a", the first byte of the UDGs is
at 65368. The difference, 1152, divided by 8 (the number of
bytes/character) is 144, and 144 is the code of the first
UDG! If the logic of this has lost you, don't worry, just
POKE 216 and 250 (216 and 122 if you have a 16K machine).
The POKEs at the end of line 20 reset CHARS to its ori-
ginal position. Otherwise the error messages and listing
would be unreadable.
Rolling titles
So, now we can use UDGs what do we do with them! (Apart
from their straightforward use in titles). Here's a couple
of ideas. I call them rolling titles. They are interesting
in that they make use of the ROM character set to redesign
the UDGs.
Program 5 displays the word "SCROLL", then gradually
rolls it away leaving a blank space. This can be especially
effective if it appears in a window surrounded by a diffe-
rent colour background. The DATA line supplies the first
POKE within the loop in line 5, with the UDG to be altered,
then the start address in ROM where the pixel pattern for
the replacement letter begins. Refer to Table B [a simple
table of some characters and their charset addresses in
ROM - 15616 for space, 15880 for A, 15888 for B and so on.
I haven't replicated it, since it's easy to create your own
should anyone want it] and you will see that 16024 is the
start of S, 15896 of "C" and so on for the word SCROLL. The
reason for alternate UDGs being redefined becomes apparent
in the second POKE. This POKEs the unaltered UDGs between,
with 0 - a blank space. The letters for p$ in line 10 must
be entered as UDGs (as yet not redefined). When the program
RUNs, it displays the POKEd patterns, but moving up one
byte each time it loops in line 10 so that the top line is
lost and the blank lines of the redefined spaces move in to
take the place. The best way to understand how this program
(or any other) works is to put in a word of your own. (If
you want other than 6 letters then you will have to alter
the limit number in the f loop of line 5.) Use Table B to
get the DATA numbers you need, and remember, the UDGs must
be used alternately. Good luck.
Program 6 is an extension of this roller idea where,
instead of blanks, a second word (TITLES) is redefined. So,
as SCROLL rolls off, TITLES rolls on. Incidentally, if you
want to use a character set other than that in the ROM, you
can define your own in the RAM and point the machine code
routine to it by setting CHARS to 256 less than the start-
ing address. I'll leave designing the new set to you (or
you can crib it from an earlier mag).
Now for something easier. Obviously you can use the
routine for titles, Horizons style, but how about some ani-
mations? Programs 7, 8, 9 and 10 use the routine to produce
such effects.
Program 7 puts each successive word in the same place on
screen as the previous one, but makes it larger (and a dif-
ferent colour) so that the title "zooms in".
Program 8 reverses this procedure, so parts of previous
words remain giving a blocked effect.
Programs 9 and 10 are similar to Program 8 but also move
the print position so that the title shifts up or down the
screen giving a perspective effect.
Clearing the screen
And now for something completely different. Spaces. The
routine will quite happily print these and give interesting
CLS effect. Actually, it's more of a "wipe". Programs 11
and 12 will demonstrate. The former clears the screen in a
series of 8 left to right wipes starting at the top, where-
as the latter clears in a series of vertical lines starting
from the left. In each case line 10 just fills the screen
for wiping. Try experimenting with other values for xs and
ys. (xs must divide exactly into 32.) If you add a state-
ment such as PAPER 4 then you will clear and change the
screen colour at the same time.
You can also use the printing spaces technique to clear
just part of the screen (a window). Try Program 13. This
will produce a central cleared area 48 pixels down from the
top, with the window 16 characters wide and 8 deep. If you
want to clear a window to right or left of screen centre
then you will have to set variable xx as well and call the
routine at line 9999, not 9998 - see Program 14.
Computers normally print characters to screen by justi-
fying to the left - like a typewriter. That is they produce
a straight left-hand and a ragged right-hand margin. A book
(or this magazine) is printed with right and left justifi-
cation. Both margins are straight. [Note that, unlike the
original article, this plain-text file has a ragged right
margin.] A word processor does the same. Program 15 justi-
fies to centre, meaning that each line of print is balanced
about the mid line and so the left and right margins are
even [or rather, identically uneven]. This gives a pleasing
look to on-screen instructions. In outline, the program
takes the contents of the string held in a$, chops it
up into lines of maximum length 32 characters, without
chopping words, and then uses the machine code routine to
balance each of those lines centrally on screen. As print-
ed, the listing gives normal size characters, but you
could, for example, change to double size by altering ys
and xs to 2, and changing all 32s to 16 and 33s to 17.
To end, here is a Really Useful Program (as Pooh would
say). Program 16 will produce cassette lables if you have
a printer. The titles are printed twice normal print size,
and appear both on the spine and on the side of the lable.
The straight lines printed show you where to fold to fit
the box. If you want to make a complete cover for the side
(and can afford the paper) add some LPRINTs before COPY to
make it long enough.
Well, there are the ideas. From now on it's up to you.
Have fun with Uncle's present!