1. BASIC editing
If you are editing a BASIC program, you can find out what is the last line
number in the program as follows:
Hold down <SHIFT> and <CTRL> together, press
<ESCAPE> twice in succession, and finally release <SHIFT> and <CTRL>.
This even works on an Archimedes/A3000!
2. Listings
To stop listings and any other screen output* whizzing past too quickly,
hold <SHIFT> and <CTRL> down together. Alternatively, from the BASIC
prompt, press <CTRL> <N> to engage paged mode, and press <SHIFT> to continue
scrolling. Cancel with <CTRL> <O>. This also works fine on an Archimedes.
* eg packet messages!
3. Filling up strings
It is sometimes necessary to fill-up or 'pad' out strings to a fixed length.
For example, you may want numbers to print out as 0045, 0001 etc., or you may
want to add leading or trailing spaces onto character strings.
The first
example gives the obvious method, whereas the second shows a more elegant
method which avoids the use of an IF statement. The third example shows a
similar method in the form of a Function, with the addition that you can
specify the amount of padding and the padding character to be used - it
doesn't have to be a number.
30 IF LEN(X$)=4 THEN X$="0"+X$:GOTO 30
30 X$=STRING$(4-LEN(X$),"0")+X$
10 INPUT"Enter up to 5 digits "A$
20 A$=FNpad(A$,5,"0"):PRINT A$:END
30 :
100 DEFFNpad(st$,len%,char$):=STRING$(len%-LEN(st$),char$)+st$
4. Randomize
To 'scramble' the Beeb's random number generator properly, you can simulate
the RANDOMIZE function of some other BASICs. Incorporate the dummy expression
randomize=RND(-TIME) at the beginning of your program. This also works on an
Arc/A3000.
5. Self-validating input
Try incorporating this sort of input routine into your own program. There is
nothing special about the particular line numbers used.
1000 PRINT"Do you want another game ? ";
1010 ON INSTR("YyNn",GET$) GOTO 1020,1020,1030,1030 ELSE 1010
1020 REM Back to start of program.
1030 END
6. Shortened 'IF' statement
In most cases, the statement IF A=0 THEN etc. can be shortened to just IF A
etc. The "=0" is implied, provided A can only be zero, or +1 or more, or -1
or less. In the 'before' and 'after' example below, note the space after the
variable "A" in the second version. This space would be unnecessary if the
variable were "A%" instead.
100 IF A=0 THEN G=5:GOTO 70
100 IF A G=5:GOTO 70 (Note the space after the A!)
7. Simple bleep
If you want a short 'bleep' in your program, you can use VDU7 or PRINT
CHR$(7) instead of a SOUND statement. VDU7,7 etc would give a longer bleep.
8. VDU7 bleep
You can alter the nature of the VDU7 'bleep' as follows. *FX210,1 turns it off, and *FX210 turns it on again. You can alter the pitch with *FX213,P where "P" is a number from 0 to 255, (default value is about 100). Similarly,
you can alter the duration with *FX214,D (default value about 7). You can
change sound channel or 'voice' with *FX211,N where "N" is 0 to 3, (normally
3). Thus, if you try *FX211,0 you will get a sort of explosion noise, and
*FX211,3 will restore it to a bleep. You can test the bleep by pressing
<CTRL>+<G> ; quicker than typing VDU7.
9. Key-pressed check
You can check to see if a specific key is being pressed at a particular
instant with a negative INKEY statement. For example, you can test the
space-bar with IF INKEY(-99) THEN...
However, if you want to see if ANY key is being pressed, (though not the red keys or <CTRL> or <SHIFT>), then use this command. It works in the opposite
sense to the other negative INKEY commands, hence the inclusion of the word"NOT". IF NOT INKEY(-129) THEN ...
10. Input line
An ordinary INPUT statement will strip any leading spaces off strings, and
will not accept commas within a string. The latter is because you can use
commas to separate your replies, instead of pressing <RETURN> each time, eg
BLOGGS,45,MALE <RETURN>. You are reminded that the alternative command
INPUTLINE will accept commas and leading spaces. You can easily strip the
leading spaces off afterwards, if they are a problem.
11. String input function
This Function is an alternative to using a conventional INPUT statement for
strings. You specify the minimum and maximum number of characters in the
string, and the Function does the rest. The example given is for 2 and 6
characters respectively, whereas an INPUT statement is effectively for 0 and
255. You will find that you cannot press <RETURN> until you have typed in the
minimum number of characters, and that you cannot type more than the maximum.
Full use of the 'Delete' and 'Copy' keys is allowed.
This Function is quite tricky to type in without errors, so take care.
I've only put spaces in for clarity, and you can omit them all except
immediately before the word "ELSE". If you want the cursor to remain on the
same line after <RETURN> is pressed on a valid string, then omit the final
PRINT: in line 140, so that you have just ELSE =I$.
10 PRINT"Enter Name ";:name$=FNinp(2,6):GOTO 10
100 DEFFNinp(min%,max%):LOCALG%,G$,I$:*FX21,0
110 PRINT G$;
120 G$=GET$:G%=ASC(G$)
130 IF(LEN(I$)=max% AND G%<>13 AND G%<>127)OR(((LEN(I$)=0
AND(G%<33 OR G%>126))OR(LEN(I$)<min% AND G%=13))AND(min%>0
OR G%<>13))THEN VDU7:GOTO 120
140 IF G%>31 AND G%<127 THEN I$=I$+G$:GOTO 110 ELSE IF G%=127
THEN I$=LEFT$(I$,LEN(I$)-1):GOTO 110 ELSE IF G%<>13 THEN
VDU7:GOTO 120 ELSE PRINT:=I$
12. Number input function
This is a similar sort of Function for validating numbers which may be more
than just a single digit. If the number entered doesn't fall within the
required limits, the incorrect entry is erased ready for another try. If you
are only interested in integers, then alter the variables figure, min and max
by adding a "%" sign on the end. Wierd things happen if you muck about with
the cursor editing keys, but you can easily temporarily disable them with
*FX4,1 or *FX4,2. Like the previous Function, it really pays off in larger
programs, as it saves you having to write separate validation routines for
each and every input. You could save the Function with the *SPOOL facility,
and *EXEC it into new programs as required. Again, you can omit spaces if you
want.
10 CLS:PRINTTAB(7,10)"Enter Width ";:width=FNnumber(18.2,65.7)
20 END
100 DEFFNnumber(min,max):LOCAL P%,V%,figure
110 P%=POS:V%=VPOS:PRINT:REPEAT REPEAT VDU127:UNTIL POS=P% AND
VPOS=V%:INPUT""figure:UNTIL figure>=min AND figure<=max:
=figure
13. Status functions
The first is a useful Function which can be used to test the status of
various aspects of the VDU drivers. For example, to check if the screen is in
paged mode, then use IF FNstatus(2)=TRUE THEN... To check whether there is a
text window defined, then use IF FNstatus(3)=TRUE THEN..., and so on. You can
achieve the same result, though not in a proper Tube-compatible way, by
Peeking location &D0. Indeed, the only way I know of disabling scrolling,
(bit 1), is to directly Poke &D0 with ?&D0=?&D0 OR 2. (Enable it again with
?&D0=?&D0 AND 253.) The second Function returns the current graphic Mode
number, and the third Function returns the ASCII code of the character at the
present cursor position. You can move the cursor to the required position
with PRINTTAB(x,y); or VDU31,x,y.
100 REM ** Returns TRUE if Bit is Set **
110 :
120 REM 0 - Printer enabled by VDU2
130 REM 1 - Scrolling disabled
140 REM 2 - Page Mode enabled by VDU14
150 REM 3 - Text Window defined by VDU28
160 REM 4 - Not used
170 REM 5 - Text/Graphics cursors joined by VDU5
180 REM 6 - Edit cursor in use
190 REM 7 - VDU drivers disabled by VDU21
200 :
210 DEF FNstatus(bit%):LOCAL A%
220 A%=&75:=-(((USR&FFF4 AND &FF00)DIV&100)AND2^bit%)DIV2^bit%
100 REM ** Returns Graphic Mode **
110 :
120 DEF FNmode:LOCAL A%
130 A%=&87:=(USR&FFF4 AND &FF0000)DIV &10000
100 REM ** Returns Character at
110 REM flashing cursor position **
120 :
130 DEF FNchar:LOCAL A%
140 A%=&87:=(USR&FFF4 AND &FF00)DIV &100
14. Star commands in a program
It is sometimes useful to be able to use the 'Star' Machine Operating
System's commands from inside a program; eg *KEY, *DISC, *CAT etc.
These routines, written as Procedures, will allow you to do just that. Line
10 is only to demonstrate the Procedure, which you would call from your main
program. (The best way to do this to test for the '*' key being pressed. The
Procedure itself does not require this, as "CAT" is assumed to be "*CAT".) If
you want to *CAT a cassette, then you would have to press <Escape> to finish,
so you need to use ON ERROR GOTO to avoid coming out of the program
altogether. The LOCAL statement is so that you can use the variables X%, Y%
and Z% in the rest of your program, without any clash. However, it might be
wise to avoid them anyway, as Escaping from the Procedure could cause odd
things to happen. You could substitute any integer variable for Z%, but you
must use X% and Y%. The Procedure as it stands works on all BASIC versions,
except BAS128 *, and with the alterations shown to the right, it works on all
BASIC versions except BASIC-1.
* NB: BAS128 is for the B+/Master/Compact only.
10 PROCcommand:PRINT"Done it!":END
20 :
1000 DEFPROCcommand:LOCAL X%,Y%,Z% DEFPROCcommand:LOCAL C$
1010 DIM Z%-1:PRINT"Enter MOS command" PRINT"Enter MOS command"
1020 INPUT"*"$Z% INPUT"*"C$
1030 X%=Z%:Y%=Z%DIV256:CALL &FFF7 OSCLI(C$)
1040 ENDPROC ENDPROC
15. Alphabetic sort
This is a very fast BASIC Sort Procedure, known as a Shell-Metzner Sort. It
is far faster than a simple Bubble Sort on long lists, and can sort a several
hundred names in only a few seconds. It can just be beaten by the Quicksort
published in the November 1982 Beebug. However, the Quicksort uses recursion,
which means you can't easily add any bits of your own in the Procedure
without the routine hanging up, so I prefer to stick with this one. It
assumes that you have a list of names, or whatever, in an array called file$,
(or A$ etc. if you prefer).
If you have DIMensioned the array as file$(300), and it's always full up,
then you would use PROCsort(300), otherwise substitute a variable giving the
last element with anything in it. If you want the list in descending
alphabetical order, then change the "<=" in line 160 to ">=". As usual, all
the variables except file$ itself are LOCAL, so can be used elsewhere without
any clash.
Unless you 'fill up' the whole array initially with strings of the maximum
length likely to be encountered, then the Sort is bound to gobble up memory
in use. This isn't the fault of the Procedure, but is a quirk of BBC BASIC,
known as poor 'Garbage Collecting'. The Procedure can easily be adapted to
sort numbers instead of strings, in which case this problem doesn't arise.
100 DEFPROCsort(extent%)
110 LOCAL I%,J%,K%,L%,M%,swap$:M%=extent%
120 M%=M%DIV2:IF M%=0 THEN 200
130 K%=extent%-M%:J%=1
140 I%=J%
150 L%=I%+M%
160 IF file$(I%)<=file$(L%) THEN 190
170 swap$=file$(I%):file$(I%)=file$(L%):file$(L%)=swap$
180 I%=I%-M%:IF I%>0 THEN 150
190 J%=J%+1:IF J%>K% THEN 120 ELSE 140
200 ENDPROC
16. Program size
To see how long your BASIC program, excluding variable space etc., type
PRINT TOP-PAGE <RETURN>, or PRINT~TOP-PAGE <RETURN> if you want it in Hex.
This also works on an Arc, with the addition that you can use END-PAGE if you
want to include any variable space used by the program after it has been run.
17. Program string search
This is a very useful routine to assist in writing and debugging programs.
When you need to search for a character or string of characters in your main
program, just press a red user key, enter the string you are looking for, and
the routine will immediately tell you all the line numbers where that string
occurs, taking only 3 seconds to search an 11k program. (It is very similar
to the *FIND facility in Disc Doctor.) It is a greatly improved version of a
program originally published in Beebug magazine. This version occupies only
256 bytes of memory, hides away out of sight, and will even survive pressing
of the <BREAK> key. You can just forget all about it while you use your Micro
for BASIC programs. The only limitation is that you cannot use it with
relocated programs, but it works with or without a DFS.
First, press <Break> and then type in the program exactly as shown, even if
it does look rather weird. However, you absolutely MUST omit ALL spaces,
with the sole exception of the space inside the quotes in line 40. I have
only inserted spaces after the line numbers for clarity, so don't put them in
yourself. When you've done that, type PRINT~TOP-PAGE, and check that the
answer is "FF". It it isn't, then look again!
If all is well, you can SAVE it first, and then type RUN. As soon as the"Enter String" prompt appears, press <Escape> and then type NEW again. You
can then LOAD or type in another BASIC program, and use the micro in the
usual way. The only thing is that you should make sure that the red user keys
'f9' and 'f10' are not redefined. When you need to search, press 'f9' and
enter the search string. You can search for any character, variable name,
Procedure or Function name, punctuation etc., (hence the use of INPUTLINE
instead of INPUT, to permit commas). You may get the occasional spurious find
for a single character, due to it being confused with tokens.
The only thing you cannot search for is a BASIC keyword such as PROC, FOR, IF
etc., but you can search for *FX, *OPT etc.. If you do need to search for a
keyword, then look up the appropriate Hex token on page 483 of the User
Guide. Instead of typing in the keyword itself in response the the prompt,
press <SHIFT> and <f9>, which will move the cursor one space to the right,
and then type in the token exactly as given in the User Guide. For example,"COLOUR" has the token FB, so this is what you type in; no more, no less. If
you have Teletext Mode 7 colour codes inside PRINT or REM statements, then
these can occasionally be mistaken for tokens, but this isn't a big problem.
The program works in all modes, and is unaffected by <BREAK>. After pressing
<BREAK>, both SEARCH and your main program will still be present; just type
NEW if you want to type in another program. If you press <CTRL+BREAK>, then
you will need to type OLD, and RUN again as if you had just started.
10 ONERRORGOTO100
20 *KEY9PAGE=PAGE-&100|MRUN|M
30 *KEY10OLD|MPAGE=PAGE+&100|M
40 B%=PAGE+&101:T%=&A00:INPUTLINE"Enter String",$T%
50 IF?T%=&89THEN$T%=CHR$EVAL("&"+$(T%+1))
60 REPEATN%=&100*?B%+B%?1:P%=B%+3:B%=P%+P%?-1-3
70 IFLEN$T%>LEN$P%THEN90
80 IFINSTR($P%,$T%)THENPRINTN%;
90 UNTIL?B%=&FF
100 PRINT:PAGE=PAGE+&100
18. Wacky error message
For an error message straight out of Monty Python, try to renumber a program
by typing RENUMBER 1000,1000 <RETURN> .
Another good one happens in VIEW, if you type the command...
=>FIELD 27 <RETURN>
19. Lock out lower-case
On occasions, it can be useful for lower-case letters to be treated the same
as upper-case in GET$ statements, to avoid having to test for "Y" and "y" for"YES", etc.. This Function will always return upper-case letters, even if the
'Caps Lock' isn't on. It is written as a Function, which you use:
1000 DEFFNget:=CHR$(GET AND &DF)
20. Pressing user keys in a program
You can effectively 'press' a red key on exit from a program, by inserting
the right code into the keyboard buffer. In this example, 128 corresponds to
key 'f0', 129 would be 'f1' etc.. The <BREAK> key is code 138, and note that
this method does not actually cause a Break; this would require the key to be
physically pressed by hand.
10 *KEY0 LIST|M
20 *FX138,0,128
30 PRINT"Here is a Listing..."
40 END
21. Press space-bar to continue
There are various ways of doing this. The first method looks at the keyboard
buffer, so if the Space-bar has been pressed just before the message, it will
carry straight on. If this is a problem, then either use the second variant
with the *FX21,0 buffer clear command, or use the third version. This will
still cause a Space to enter the keyboard buffer, so this is cleared with
*FX21,0 to avoid problems later.
Although written as Procedures, they don't have to be.
Call them with PROCspace.
1000 DEFPROCspace:REPEAT UNTIL GET=32:ENDPROC
1000 DEFPROCspace:*FX21,0
1010 REPEAT UNTIL GET=32:ENDPROC
1000 DEFPROCspace:REPEAT UNTIL INKEY(-99):*FX21,0
1010 ENDPROC
22. Time delays
Apart from using a dummy FOR-NEXT loop, there are two main ways to put a time
delay in programs. The first is to use the TIME facility, and the other is to
use INKEY. The first TIME routine resets the TIME to zero on each occasion.
If you wish to avoid this, then the second routine will overcome the problem.
The INKEY routine will give a similar delay, except that the delay terminates
on pressing any key. The example provides a 2 second delay, (200
centiseconds). Call them with PROCdelay.
1000 DEFPROCdelay:TIME=0:REPEAT UNTIL TIME=200:ENDPROC
1000 DEFPROCdelay:LOCAL now%: REPEAT UNTIL TIME=now%+200: ENDPROC
1000 DEFPROCdelay:LOCAL pause%:pause%=INKEY(200):ENDPROC
Another way is to call up whatever length delay you want, but still only
using one Procedure. You can call up delays with PROCdelay(100), or
PROCdelay(200) etc. as follows:-
1000 DEF PROCdelay(wait%):TIME=0:REPEAT UNTIL TIME=wait%:ENDPROC
TIME=now%+wait%:ENDPROC
1000 DEF PROCdelay(wait%):LOCAL pause%:pause%=INKEY(wait%):ENDPROC
Note the use of Integer variables for accuracy. The variable pause% is a
dummy, to satisfy the INKEY syntax. The variable wait% is an implied LOCAL
variable, so can be used elsewhere in the program quite independently,
without any clash.
23. Printer output only
Sometimes it is handy to be able to send text to the printer only, without it
appearing on the VDU screen at the same time. This can be done by using
VDU2,21 to activate the printer, and VDU6,3 to turn it off again and to
restore the VDU drivers. This can cause problems if you try to send anything
other than normal text or figures. Control codes or graphic data may be
corrupted due to the filtering of the "printer ignore character" specified by
*FX6. *FX3,10 and *FX3,0 have a similar effect to these VDU commands.
24. Simulated duff TV
This routine gives the fairly convincing impression that your TV or monitor
has gone duff, especially if you turn the brightness up a bit. If you have a
Master or Compact, then the ",0;0;0;" bit can be replaced by the single
character '|'. Someone suggested hiding it somewhere in a program, as a booby
trap for your mates....
10 VDU23,0,RND(255),RND(255),0;0;0;: GOTO 10
25. Cube roots
A reminder for those of us who aren't too hot at Maths. In BBC BASIC, a
square root can be obtained with A=SRQ(B), but how to get the cube root?
The answer is that SQR is unnecessary, as you could use A=B^(1/2) instead.
Thus the cube root is given by A=B^(1/3) etc.
26. Integer variables
Programs can be speeded up by using Integer variables where possible. Try
running this program first using X, and then using X% instead. Using NEXT
rather than NEXT X or NEXT X% makes it even faster; try it.
10 TIME=0:FOR X=1 TO 5000:NEXT X:PRINT TIME
27. Disc relocate
This routine, sometimes referred to rather confusingly as a 'downloader',
enables programs to be run which are normally too large for use with a DFS
fitted. It switches off the DFS with *TAPE, and shifts the whole program down
to &E00 before running it. The screen output is temporarily inhibited with
VDU21 during relocation, and reactivated afterwards with |F (VDU6), to give a
tidy appearance. For debugging, the VDU21 may be omitted initially, as it
also inhibits useful error messages! The routine will relocate BASIC
programs, including those containing assembler. If there is also 'hidden'
data and/or machine code, then it is easiest to alter the TOP in line 1 to
HIMEM, although this makes the routine rather slower. Spaces are shown for
clarity only, line 1 is split at a convenient point for the same reason.
0 IF PAGE=&E00 THEN 10
1 VDU21:*KEY9 *TAPE|M FOR I%=0 TO TOP-PAGE STEP 4:
I%!&E00=I%!PAGE:NEXT|M PAGE=&E00|M NEW|M OLD|M RUN|F|M
2 *FX138,0,137
3 END : REM Most Important!
10 REM Start of your Program.
28. User port experimenting (1)
The User Port is controlled by a very versatile little chip called a 6522
VIA, (Versatile Interface Adapter), which also looks after the Centronics
printer port. You have 20 connector pins available, consisting of 8 connected
to 0 Volts, 2 connected to +5 Volts, 2 handshake lines, (CB1 and CB2), and
the 8 Input/Output lines PB0 to PB7. These lines default as inputs fairly
similar to the 74L series low-power TTL gates. If you check them with a
multimeter, you will find that they float high to about +3 Volts, just like a
TTL input.
The status of these 8 lines is read into location &FE60, so if you
interrogate it with PRINT ?&FE60, you will get 255 Decimal, which is FF in
Hex and 11111111 in Binary. If you were to short-circuit PB0 to 0 Volts, then
you would get 254 Decimal, or 11111110 Binary. Similarly, if you short PB1
instead, you get 253 or 11111101, and if you short the lot together, you get
0, or 00000000 in Binary. It will be obvious by now that it is convenient to
'look' at &FE60 in Binary, as it gives a direct representation of what is
happening on the pins.
If you wish to test the status of one particular pin, ie one binary bit, then
use the logical AND to 'mask' out the other bits, and then divide it by
itself to turn it into a 1 or 0. Thus, to test PB1, use PRINT (?&FE60 AND
2)DIV2. More generally, to test pin PBn%, where n% is 0 to 7, use
p%=2^n%:PRINT (?&FE60 AND p%)DIV p%. If you stick a minus sign in front of
the expression (?&FE60 etc...), then it will return the value TRUE for logic
high, and FALSE for 0. Always use integer variables to avoid silly rounding
errors, and to increase speed.
This short program displays the status of the pins in Decimal, Hex and
Binary, enabling you to watch what happens when you pull various inputs low.
You can also drive them up to +5 Volts like any TTL gate, and they source
only 0.8 mA when low, so you can drive them from +5 Volt CMOS logic if you
want. If you do have an accident, a new 6522 VIA isn't too expensive!
10 MODE 7:VDU23,1,0;0;0;0;:REM * Cursor off *
20 PRINT TAB(5,8)"Decimal"TAB(16,8)"Hex"TAB(25,8)"Binary"
30 REPEAT port%=?&FE60:REM * Read Port *
40 PRINT TAB(7,10);port%" "TAB(16,10);~port%" "TAB(24,10);
50 FOR pb%=7 TO 0 STEP-1
60 power%=2^pb%:REM * Read each bit *
70 PRINT;(port% AND power%)DIV power%;
80 NEXT:UNTIL FALSE
29. User port experimenting (2)
The previous program examines the User Port inputs via location &FE60.
However, by writing to &FE62 you can nominate pins as outputs instead, and
they will default to logic LO, which you can check with the previous program,
and confirm with a multimeter. This program asks you which bits are to be
outputs, so enter 0237 or 134 or whichever bits you want, in any order. If
you just press <RETURN> without entering anything, all pins will be reset as
inputs. Strangely, so it might seem, you alter the output states by writing
to &FE60; the pins set as inputs will ignore this, so no need to worry on
that score. In other words, ?&FE60=255 would set all outputs to logic HI
without affecting the inputs, and so if you PRINT ?&FE60 afterwards, you will
see the effect. Try combining the two programs, and add a few bits of your
own to make a more complete experimenting program.
10 PRINT ?&FE62:INPUT"Which ones for output? " output$
20 FOR pb%=0 TO 7:power%=2^pb%
30 IF INSTR(output$,STR$(pb%))=0 THEN ?&FE62=?&FE62 OR power%
ELSE ?&FE62=?&FE62 AND (255-power%)
40 NEXT:PRINT ?&FE62
30. Program verify
To see if a BASIC program has been successfully SAVEd to tape, without losing
the current program from memory, type *LOAD "" 8000 <RETURN>, (note the empty
quotes). This works well for programs of not more than 16k in length, as it
is simply trying to 'write' into the BASIC ROM, which it cannot do. However,
all the normal error-checking of the tape data takes place, accompanied by
the usual "Searching" and "Loading" messages. If you have sideways RAM, then
you should operate the write-protect switch to avoid garbage being written
into the RAM.
31. Tape reset
If you have a DFS fitted, then pressing <Tab+Break> will cause a "warm" reset to the cassette filing system. This is quicker than pressing <Break>
followed by typing *T. <RETURN>. The cursor will step a few spaces to the
right, but this is harmless; press <RETURN> if it bothers you.
32. Unwanted spaces
It is all too easy to leave unwanted spaces in listings, especially by "overshooting" the ends of lines when using the 'Copy' key. If you are short
of memory, it is worthwhile editing out those spaces.
You can spot them by redefining them as white blobs, and then using any Mode
except 7, (6 is ideal). When you wish to remove spaces, type the following
in directly in Mode 7, and then change mode. When you've edited out any
unwanted spaces, change back to Mode 7 and SAVE the program. To restore
normal spaces, type *FX20 <RETURN>.
VDU23,32,126,126,126,126,126,126,126,0
33. Basic-1 and Basic-2
In order to be able to check compatibility of programs, you may wish to
retain the BASIC-1 ROM in your machine after obtaining BASIC-2. Simply put
the old ROM in a lower-priority ROM socket, and switch to it when required
with *FX142,n where 'n' is the socket number, (0 to 15). If you have a
program in memory, then type OLD to recover it. Pressing <Break> will not
cancel the change, but switching the machine off, pressing <Ctrl+Break>, or
typing *BASIC will return to BASIC-2. Alternatively, you can use *FX142 to
switch back to BASIC-2.
34. Lower-case commands
You will know that whereas VDU and PRINT are BASIC keywords, vdu and print
are not. However, with the MOS 'Star' commands, *FX, *SAVE, *DELETE etc.,
lower-case is treated the same as upper-case. Thus *fx0 and oPt1,2 are valid
commands. Further to this, disc filenames, though not cassette filenames, are
treated in a similar fashion. Thus if you save a program as "sneaky", it
appears in lower-case in the catalogue, but you can reload it as "SNEAKY" if
you wish, and any attempt to save a program called "SNEAKY" would overwrite
the lower-case one.
35. Saving memory
When you are writing very large programs, or ones that need a lot of variable
space, every byte can count to squeeze as much as possible into memory. All
BASIC keywords are 'tokenised' into just one byte each, so "RESTORE" only
occupies the same amount of memory as "TO", ie one byte. However, this is not
true of the MOS 'star' commands. Thus *O. occupies 3 bytes, whereas *OPT occupies 4, and so on. You can abbreviate words like *KEY, *DELETE etc also.
However, it is wise not to abbreviate *DISC or *TAPE, as this does not not
work on all versions of Operating System.
36. Simplified commands
In the case of operations starting with a '*', you can omit the quotes round
a filename. Thus you must have LOAD "name", but *LOAD name is OK. In the same
way, you must have CHAIN "name", but *RUN name or just *RUN is OK. You can
use the abbeviation */ for *RUN, eg */ Myprog.
37. Tidy menus
A tidy way of producing a program 'menu', without a lot of repetition, is to
use DATA lists. In the example below, the GOTOs in line 130 are just for
demonstration purposes. You would obviously put in the line numbers
appropriate to your own program. The line number after RESTORE is the one
where the DATA list is stored. You can actually put the DATA list anywhere
you like in the program, even in the first line, as long as the RESTORE
statement points accordingly. Don't be tempted to write this in the form of a
Procedure, as the GOTOs will cause nasty things to happen!
100 CLS:PRINT'TAB(18)"MENU"'TAB(18)"----"'
110 RESTORE 2000:FOR A%=1 TO 5:READ A$:PRINT
TAB(4);A%"........."A$:NEXT
120 PRINT'"Select desired option No. ";
130 ON VAL(GET$) GOTO 200,300,350,400,480 ELSE 130
2000 DATA Start Again,Exit Program,Change Details,Display Details,
Action Replay
38. Double-height input
This is a Function which enables you to INPUT strings in two-tone
double-height lettering. You have to pass the following variables into the
Function: The prompt or question word(s), the first letters of the top and
bottom colours, the X and Y tab positions you want it to start from, and the
maximum length. You must enter at least one character before pressing
<RETURN>, but if you don't like this restriction, then omit the "OR g%=13" from line 160. The space available for the input is shown by a dotted line.
If you don't want this, then omit both STRING$ statements from line 130, and
change the 46 to 32 in line 170. The example in lines 10 and 20 gives a good
demonstration of this nice little routine, which was adapted from an original
passed on by Andrew G8YHI. You may omit all spaces from the listing to save
memory space, if you wish.
10 MODE7:N$=FNdhin("Name ? ","G","M",5,10,15)
20 PRINT''''N$:END
30 :
100 DEF FNdhin(prompt$,top$,bot$,x%,y%,len%)
110 LOCAL a$,g%,top%,bot%
120 top%=128+INSTR("RGYBMCW",top$): bot%=128+INSTR("RGYBMCW",bot$)
130 VDU31,x%,y%,top%,141:PRINT prompt$;STRING$(len%,"."):
VDU31,x%,y%+1,bot%,141:PRINT prompt$;STRING$(len%,".")
TAB(x%+LEN(prompt$)+2,y%);
140 REPEAT
150 g%=GET
160 IF (g%=32 OR g%=13 OR g%=127) AND LEN(a$)=0 THEN VDU7:GOTO 150
170 IF g%=127 THEN a$=LEFT$(a$,LEN(a$)-1):VDU127,10,46,8,11:GOTO 200
IF g%=13 THEN VDU7:GOTO 150
190 VDUg%,10,8,g%,11
200 UNTIL g%=13: =a$
39. Input with timeout
In some applications, especially Educational programs, it is useful to have
an input routine which "times-out" if no key is pressed for a certain number
of seconds. This is possible for single-character routines like INKEY, but
not with INPUT. This Function solves the problem, and also enables you to set
limits on the string size. You must pass the minimum and maximum lengths
allowed, and also the number of seconds for timeout after the last key was
pressed. If the routine times-out before you press <RETURN>, then it will act
as if it had pressed <RETURN> for you. If, however, you would rather that it
returned the null, (or empty), string instead, then see the REM statement.
The example in line 10 allows a minimum of 1 character, and maximum of 12,
with a 5-second timeout. You may omit all spaces in the listing, if you wish,
except those inside quotes. Thanks to Brian Parker G6JPZ for suggesting the
idea, which has been incorporated into the routine given in the Golden Oldie
Tip #11.
10 PRINT"Enter name ? ";:A$=FNinp(1,12,5):PRINT A$':GOTO 10
20 :
100 DEFFNinp(min%,max%,secs%):LOCAL G%,G$,GI$:*FX15,1
110 TIME=0:PRINT G$;
120 G$=INKEY$(0):G%=ASC(G$)
130 IF TIME>secs%*100 THEN PRINT:VDU7:=GI$ ELSE IF G%=-1 THEN 120
140 REM Alter the =GI$ in line 130 to ="" if string is to be null on
timeout
150 IF (LEN(GI$)=max% AND G%<>13 AND G%<>127) OR (((LEN(GI$)=0 AND
(G%<33 OR G%>126)) OR (LEN(GI$)<min% AND G%=13)) AND (min%>0 OR
G%<>13)) THEN VDU7:GOTO 120
160 IF G%>31 AND G%<127 THEN GI$=GI$+G$:GOTO 110 ELSE IF G%=127 THEN
GI$=LEFT$(GI$,LEN(GI$)-1):GOTO 110 ELSE IF G%<>13 THEN VDU7:
GOTO 120 ELSE PRINT:=GI$
40. Date input routine
This is a reasonably 'intelligent' Procedure for entering the date in a
program. It checks for sensible days, months and years, (1984 to 1999), takes
account of the different number of days in each month, and allows for Leap
Years. The original was written by a chap called Tim Davies, but I've altered
it a bit! You can enter the date in many forms, eg. 27.08.84 or 27-8-84 or
27/8/1984 or 27 8 84 or 27,08,84 and so on. The result is a string, date$,
which holds the date in the form 27-AUG-1984, and also three integer
variables, d%, m% and y%, which represent the day, month and year. If you do
not want the string date$, then change line 1070 to ENDPROC. If you do not
want to use the integer variables, then add them to the list of LOCAL
variables in line 1000. If you enter an invalid date, a beep will sound, and
you will be invited to try again. Note the use of INPUTLINE rather than
INPUT, in order to permit commas in the date.
10 PROCdate:PRINT'"Todays Date is "date$'d%,m%,y%'
20 GOTO10
1000 DEFPROCdate: LOCALmx%,I%,d$,m$,y$:*FX21,0
1010 PRINT:REPEAT: REPEATVDU127: UNTILPOS=0:INPUTLINE"Please submit
date as DD.MM.YY "date$
1020 d$=LEFT$(date$,2) :IFASC(RIGHT$(d$,1))<48THENm$=MID$(date$,3,2)
ELSEm$=MID$(date$,4,2)
1030 y$=RIGHT$(date$,2): d%=VAL(d$): m%=VAL(m$):y%=VAL(y$)+1900
1040 RESTORE1080: FORI%=1TOm%MOD13 :READm$,mx%:NEXT
1050 IFy%MOD4=0 AND m%=2 THENmx%=29
1060 VDU7:UNTILd%>0 ANDd%<=mx% AND m%>0 AND m%<13AND y%>1983:*FX21,7
1070 date$=STR$(d%)+"-"+m$+"-"+STR$(y%): ENDPROC
1080 DATA JAN,31,FEB,28,MAR,31 ,APR,30 ,MAY,31,JUN ,30,JUL,31,
AUG,31,SEP,30,OCT, 31,NOV, 30,DEC, 31
41. User key editor
This is a short program which lists all the current user-key definitions, and not just the red ones. You can then edit them, if you wish, using the cursor
and 'Copy' keys as usual. The number of bytes used up by the definitions is
displayed; 239 is the maximum available. This was adapted from an original
which I think was published in "Acorn User". You can omit all spaces in the
listing, if you wish, except those inside quotes. This applies to the BBC B
(& B+ ?) but not the Master or Compact.
100 MODE7:@%=&902:M%=0: PRINT'"Keylist":FOR K%=0 TO 15
110 PRINT'" *KEY"K%" ";: A%=K%?&B00:B%=256 :FOR T%=0 TO 15
120 S%=T%?&B00:IF S%>A% AND S%<=B% THEN B%=S%
130 NEXT:IF B%=256 THEN 170
140 FOR G%=A% TO B%-1:H%=G%?&B01:M%=M%+1
150 IF H%>31 THEN VDU H% ELSE VDU 124,H%+64
160 NEXT
170 NEXT:@%=&90A: PRINT'';M%;" bytes used." :REM max is 239
42. User key definitions
Some members may not know that, having programmed the red 'soft' keys, you
can SAVE the definitions directly with the command *SAVE KEYS B00 C00 or
*SAVE KEYS B00+100. The definitions can then be reLOADed at any time, (even
if you have a BASIC program in memory, or if you are using View or Wordwise),
with *LOAD KEYS. Disc users can conveniently incorporate this command in the
!BOOT file. This applies to the BBC B (& B+ ?) but not the Master or Compact.
43. Wordwise and the user keys
When you exit from Wordwise with *BASIC, you will find that the red keys do
not work properly. You can cure this by pressing <BREAK>, but you can also
restore normal key operation with *FX225,1 followed by *FX227,144. <SHIFT>
plus red keys seems to work normally on current versions, but just as a
precaution, you could also use *FX226,128 to ensure that everything is back
to normal.
44. Multiple menu technique
If you have a program involving lots of different menus, it's very tedious
writing them all. Here is a fiendishly clever way of making the job easier,
courtesy of Tim Davies. Just put the heading and contents of each menu in
DATA statements, ending each menu with a "#". You can then call up the first
menu with FNmenu(1), the second with FNmenu(2) and so on. The Function
returns the number of choice you made from the menu. You can use this in
various ways, such as ON FNmenu(2) GOTO 100,110,120 etc.. , or
CHOICE%=FNmenu(3):IF CHOICE%=1 THEN ... ELSE .... The number in line 5910
must point to the first of the DATA statements, which must be numbered in
steps of 10. If you renumber the program, remember to alter line 5910, (or
whatever it becomes), as it won't be done automatically. You can of course
pretty the menus up with nice colours etc., but this should at least inspire
your ideas. The easiest way to test this Function without having to write a
short program is to simply type PRINT FNmenu(2) <RETURN> etc..
5900 DEF FNmenu(num%):LOCAL text$,get%:num%=(num%-1)*10
5910 RESTORE num%+6000:CLS :REM 6000 is 1st DATA statement
5920 item%=1:READ text$:PRINT'TAB(12)text$''
5930 READ text$:IF text$<>"#" THEN PRINT TAB(4);item%" .....
..... "text$:item%=item%+1:GOTO 5930
5940 PRINT'"Select desired Option No. ";:REPEAT get%=GET-48:UNTIL
get%>0 AND get%<item%
5950 =get%
6000 DATA MENU ONE,Do This,Do That,Do the Other,Do Nothing,#
6010 DATA MENU TWO,First Item,Second Item,Third Item,#
6020 DATA MENU THREE,Item One,Item Two,Item Three,#
6030 DATA MENU FOUR,Choice One,Choice Two,Choice Three,
Choice Four,#
45. ULTRA-SIMPLE DISC MENU
This is a very simple but effective program for CHAINing your programs off a
disc. The TAB(40) may look a little eccentric, but in combination with the
VDU11, it wipes the previous line. Miss them out, and you'll see what I
mean. You should set the disc to CHAIN "MENU" when BOOTed up, and put your
program names into the DATA list, finishing with "END". You could of course
add pretty colours and so on to make it more interesting.
10 CLS:PRINT'':A%=0:REPEAT:READ N$:A%=A%+1:PRINT;A%" "N$:UNTIL
N$="END"
20 RESTORE:VDU11:A%=0:INPUTTAB(40)"Enter Choice "B%:REPEAT:READ
N$:A%=A%+1:UNTIL A%=B% OR N$="END"
30 IF N$="END" THEN CHAIN N$ ELSE RUN
40 DATA MEMDUMP,SHACK3,TERMIN,ROMPEEP,END
46. Extra-large printing
This is a demonstration program which creates attractive enlarged characters
very simply. It makes use of a look-up table in the 1.20 Operating System
ROM, which the machine normally uses in Modes 0 to 6. This particular example
uses the table to create attractive block characters in teletext Mode 7. You
could modify this for inclusion into your own programs, to create special
headings. This is based on ideas from "Acorn User" and "Micro Programmer".
10 MODE7:E%=144:REPEAT:PRINT"Press a Key...":A%=&C000+8*(GET-32)
20 E%=145+(E%-144)MOD7:FORB%=A%TOA%+7:C%=?B%
30 PRINTCHR$(E%)CHR$(154);:FORD%=7TO0STEP-1
40 IF(2^D%ANDC%)THENPRINTCHR$(255);ELSEPRINT" ";
50 NEXT:PRINT:NEXT:UNTILFALSE
47. Mode 7 box
This is a very handy little Procedure for drawing a box around text in Mode
7. You can print the text before or after drawing the box. You call the
Procedure by giving the 4 co-ordinates in the same order as in the VDU28
command, (see User Guide page 387). You also give the first letter of the
colour required, such as "G" for green. In order to leave room for control
codes, you must not print any text within one space to the left or right of
each vertical line, but you can print text immediately above or below the
horizontal lines. For the same reasons, X1% must be at least 1, and X2% must
be less than 38, but Y1% can be as low as 0, and Y2% can be as high as 24. Do
not try to make the box very small, or strange things may happen! In this
example, I have defined the entire usable space inside the box as a text
window, so try LISTing the program as soon as you have run it. Thanks to
Andrew G8YHI for bringing the original of this Procedure to my attention.
10 MODE7:PROCbox(5,12,34,6,"G")
20 PRINTTAB(13,9)"THIS IS A BOX"
30 VDU28,7,11,32,7:END
100 DEF PROCbox(X1%,Y1%,X2%,Y2%,C$):LOCAL C%,Y%:X1%=X1%-1
110 C%=144+INSTR("RGYBMCW",C$):VDU31,X1%,Y2%,C%,55
120 REPEAT VDU96:UNTIL POS=X2%:VDU107,135
130 FOR Y%=Y2%+1 TO Y1%-1
140 VDU31,X1%,Y%,C%,53,135,31,X2%-1,Y%,C%,106,135:NEXT
150 VDU31,X1%,Y1%,C%,117:REPEAT VDU112:UNTIL POS=X2%
160 VDU122,135:ENDPROC
48. Centred text
This is a Procedure for automatically centering a short piece of text on a
line, without having to figure out what value TAB to use. You call it with
PROCcentre(40,"HELLO THERE") or PROCcentre(80,A$) and so on, where the figure
is the width of the screen in the current Mode; 20, 40 or 80.
100 DEFPROCcentre(width%,text$)
110 PRINTTAB((width%-LEN(text$))DIV2)text$
120 ENDPROC
49. Screen border
As an alternative to using teletext Mode 7, try the following at the start of
your program. Using Mode 1 or 4, it selects yellow text on a blue background,
draws a neat border round the edge of the screen, and protects it with text
and graphics windows. This still leaves you almost the full screen free to
use. Of course, there won't be as much free user memory as in Mode 7, so you
can't use this for very large programs. In Mode 1, you could in fact have a
red border, blue background, yellow text and white graphics if you wanted to
be very flash.
10 MODE 1 :REM or Mode 4
20 VDU19,0,4,0,0;19,3,3,0,0; :REM select yellow/blue
30 MOVE 0,0:DRAW 0,1023:DRAW 1279,1023 :REM draw border
40 DRAW 1279,0:DRAW 0,0 :REM draw border
50 VDU 28,1,30,38,1 :REM set up text window
60 VDU 24,8;8;1271;1015; :REM set up graphics window
50. Novel screen clearing
These two procedures give different ways of clearing the screen of text and
graphics in Modes 0,1,2,4 & 5. The first wipes from the borders inwards,
rather like a fadeout on TV or films. The second clears the screen in a way
similar to curtains closing. You must alter line 110 slightly for Mode 0,
which will clear more slowly than the others. You can speed up the second
procedure, but not the first, in Modes 2 & 5 if you wish; see the REM
statement. Simply use PROCclearscreen or PROCclosescreen instead of CLS or
CLG.
100 DEFPROCclearscreen:LOCAL t%:GCOL0,0
110 FOR t%=0 TO 512 STEP 4:REM Use STEP 2 in Mode 0
120 MOVE t%,t%:DRAW t%,1023-t%:DRAW 1279-t%,1023-t%
130 DRAW 1279-t%,t%:DRAW t%,t%:NEXT:GCOL0,7:ENDPROC
100 DEFPROCclosescreen:LOCAL t%:GCOL0,0
110 FOR t%=0 TO 640 STEP 4:REM Use STEP 2 in Mode 0,
and STEP 8 in Modes 2 & 5
120 MOVE t%,0:DRAW t%,1023:MOVE 1279-t%,0:DRAW 1279-t%,1023
130 NEXT:GCOL0,7:ENDPROC
51. Reverse colour text
It is useful to be able to print certain words in reverse colours, ie. black
on white. This is very easy on a Commodore or Sinclair, but not so easy on
the BBC micro. Here are two sets of Functions to achieve this; the first pair
is for Mode 7 only, and the second pair is for all other Modes. Note that in
Mode 7 there are unavoidable spaces just before and after the lettering,
which is actually blue on white. Also, you must use FNrevr again on each new
line, but these problems do not arise in the other Modes. The second pair of
Functions is used like Procedures, hence the rather odd looking :="" purely
to satisfy the syntax.
10 PRINT "NORMAL" FNrevr "REVERSE" FNnorm "NORMAL":END
20 DEF FNrevr:=CHR$(135)+CHR$(157)+CHR$(132):REM Mode 7 only
30 DEF FNnorm:=CHR$(135)+CHR$(32)+CHR$(156)
20 DEF FNrevr:COLOUR 0:COLOUR 135:="":REM Modes 0 to 6
30 DEF FNnorm:COLOUR 7:COLOUR 128:=""
52. Drawing circles and discs
This is a Procedure for drawing circles or solid discs of any size, anywhere
on the screen. You call the Procedure by specifying the X co-ordinate,
(0-1279), and the Y co-ordinate, (0-1023), of the centre, plus the radius,
and lastly a "C" for circle or "D" for disc. The graphics origin is set back
to 0,0 after the circle is drawn, but you can stop this by omitting the VDU29
statement in line 150, if you wish. The example uses Mode 4, but any graphic
Mode is suitable.
10 MODE4:PROCcircle(639,511,400,"C"):PROCcircle(639,511,300,"D")
20 END
100 DEFPROCcircle(X%,Y%,R%,T$):LOCAL Q
110 VDU29,X%;Y%;:FORQ=0 TO PI*41/20 STEP PI/20
120 X%=R%*COS(Q):Y%=R%*SIN(Q)
130 IF Q=0 THEN MOVE X%,Y% ELSE IF T$="C" THEN DRAW X%,Y%
ELSE MOVE 0,0:PLOT 85,X%,Y%
140 NEXT:VDU29,0;0;:ENDPROC
(NB: The Master/Compact have ready-made circle/disc routines)
53. String formatting
A statement such as ' PRINT A$, ' doesn't do what you would expect, and that
' PRINT A$,; ' is needed to prevent an unwanted linefeed. If you try the
first program below, you will see that this only works for 27 passes of a
FOR-NEXT loop, after which odd things happen. The simplest cure is probably
to pad the string out with spaces, and not use commas at all. Note that two
line 100's are given, and they each give a slightly different effect,
depending on whether you want to pad the string at the beginning or the end.
You can change the figure 10 in line 100 to 4,5,10,20 etc., ie. something
that will divide into the screen width of 20,40 or 80.
10 A$="ABCD":FOR S%=1 TO 60:PRINT A$,;:NEXT:PRINT
10 A$="ABCD":FOR S%=1 TO 60:PRINT FNpad(A$);:NEXT:PRINT:END
100 DEF FNpad(x$):=x$+STRING$(10-LEN(x$)," ")
100 DEF FNpad(x$):=STRING$(10-LEN(x$)," ")+x$
54. Capitals conversion
This is a Function for converting a string to all upper-case letters; figures
and punctuation are not affected. This saves you having to test for, say,"YES" and "yes", in response to a keyboard input. To make sure a string is
all capitals, just use A$=FNcaps(A$) . By making the alterations suggested in
the REM statement, you can make it change to lower-case instead.
100 DEF FNcaps(text$):LOCAL letter%,char%,result$
110 FOR letter%=1 TO LEN(text$)
120 char%=ASC(MID$(text$,letter%,1))
130 IF char%>96 AND char%<123 THEN char%=char%-32
140 REM change 96 to 64, 123 to 91, and -32 to +32
150 result$=result$+CHR$(char%):NEXT:=result$
55. Tab command
When you are using the simple TAB(X) command, you will find that items
already printed to the left are liable to be blanked out. This is a mixed
blessing, and can be avoided by using the full TAB(X,Y) syntax. However, this
can be inconvenient at times, but you will find that using TAB(X,VPOS) can be
used instead in most cases. Try using TAB(20,VPOS) instead of TAB(20) in the
example.
10 PRINT"HELLO":pause=INKEY(200):VDU11
20 PRINT TAB(20)"THERE"
56. Altering the cursor
It is possible to alter the size and flash rate of the cursor in all screen
Modes, and to turn it off, with the command:
VDU23;10,N,0;0;0;
where N is made up by adding together two numbers. The first controls the
flashrate, and you must pick one of the following...
0=steady 32=invisible 64=fast_flash 96=slow_flash (default is 96)
The second controls the size, and you may have anything from a thick block,
which is 0 in all Modes, to a thin line, which is 7 in Modes 0,1,2,4 & 5,
9 in Modes 3 & 6, and 18 in Mode 7, (default is 7 in Modes 0-6, and 18 in
Mode 7). ie.
0=thick block in all modes
7=thin line in modes 0,1,2,4,5 (default 7)
9=thin line in modes 3,6 (default 7)
8=thin line in mode 7 (default 18)
Thus N=105 (96+9) would give you a thinner cursor in Modes 3 & 6, and N=0
would give you a non-flashing solid block in all Modes. A Mode change will
reset the cursor, and it can still be turned on and off with the usual
commands.
57. Reversing flags
It is often necessary to use "flags" in a program. Eg.
IF male%=TRUE THEN PRINT "Hello Sir" ELSE PRINT "Hello Madam"
where male% is a flag to indicate the sex of the user. If you need to
reverse the polarity of the flag, (ie change it from TRUE to FALSE and
vice-versa), you could use:
IF flag%=TRUE THEN flag%=FALSE ELSE flag%=TRUE
However, this can be done much more simply, with:
flag%=NOT(flag%)
58. While...do structure
You may have missed the presence of a WHILE-DO or WHILE-ENDWHILE in BBC Basic
(it's in version5 as per the Arc). Eg.
WHILE X%<100 DO X%=X%+1:A%=A%*B%
or
WHILE X%<100:X%=X%+1:A%=A%*B%:ENDWHILE (as on BBC BASIC V)
REPEAT-UNTIL and FOR-NEXT loops have a disadvantage compared to WHILE-DO or
WHILE-ENDWHILE loops in that they always execute at least once, whether they
need to or not. In the examples above, the loop would not execute at all if
X% was >=100.
Well, you can imitate WHILE-DO or WHILE-ENDWHILE with the following:
REPEAT IF X%<100 THEN X%=X%+1:A%=A%*B%:UNTIL FALSE ELSE UNTIL TRUE
It may not look very elegant, but it avoids GOTOs, so that makes it
structured in my book! (Source ... Beebug).
59. Variable names
When people start programming in Basic, there is a tendency for them to
stick to variable names like A$, B%, FRED etc.. This has three drawbacks.
First, it is not very easy to pick out variables from keywords like FOR,
TO, PRINT etc., as everything is in capitals. Second, it is easy to
accidentally use a reserved word as part of a variable; TODAY is the
classic mistake, as it starts with TO. Third, when you return to the
program after a few days or weeks break, you will find it hard to remember
just what A$ meant. The solution is to use lower-case variables whenever
possible, and use long, meaningful variable names like "name$", year%","degrees" etc.. If you are really pushed for memory space, then using the
single-letter integer variables A% to Z% can help, as can shorter variable
names such as "nd$" instead of "newdate$", but by and large you will not
need to resort to that.
60. Opening disc files
When you open files on a disc for input, using the commands OPENIN or OPENUP,
the syntax is basically chan=OPENIN("myfile"). The first file to be opened is
allocated a channel number like 1, (ie. the variable 'chan' becomes 1), and
if you open another file without closing the first, it is allocated the next
channel number, (eg 2), and so on. The numbers don't necessarily start at 1;
that's just an example.
On most DFSs and ADFS, an interesting thing happens when using OPENIN or
OPENUP, where the filename should already exist on disc, but cannot be found,
either because you have put the wrong disc in, or maybe because you have
mistyped the filename. Instead of causing an error, as you might expect, it
simply allocates channel number zero. Thus, you have a very useful way of
trapping the mistake before it actually causes an error. Eg. you could add
something like:
IF chan=0 THEN PRINT "Oops!":GOTO 200
There is no need to use CLOSE#, as the file hasn't been opened in the first
place. Only when you attempt to use INPUT#/PRINT#/BGET#/BPUT# on this
non-existent file, does the DFS return the error "Channel", (ERR=222).
61. Restore statement
It is wise always to use the full RESTORE (+ line number) syntax in programs
containing DATA statements, even if they theoretically don't need them. If
you don't, then rather strange things can happen if you change screen Mode in
between reading DATA statements. This is because the Basic stack is stored
immediately below HIMEM, and is therefore lost when you change Mode. For the
same reason, you must not use MODE or CLEAR within Functions and Procedures,
as the program will 'forget' where it has come from! Using MODE will give an
error message, but using CLEAR will not, and it can cause all sorts of
infuriating and unpredictable errors!
62. Abbreviations
You can replace PRINT:PRINT:PRINT with PRINT'' . In fact, an apostrophe will
force a new line at any time; try typing PRINT"HELLO"'"FRED" and see what
happens. (See User Guide, bottom of page 324.) You can also replace
NEXT A:NEXT B:NEXT C with NEXT A,B,C and NEXT:NEXT:NEXT with NEXT,, .
63. Underlining in Wordwise
Owners of many types of printer may experience problems when centering
underlined text in WORDWISE. The underlining tends to extend all the way to
the left margin, instead of starting at the beginning of the heading. This
effect also be seen if you are using the 'ds' and 'de' codes in Wordwise
Plus, and are previewing in 80 column mode. The cure for this is to insert
one space after the centering code, but before the underline code. If exact
centering is vital, then an additional space after the final white control
code would "balance" the first space. Better still, use the pad character,
("|" by default), instead of a space, so that it is clearly visible in Edit
Mode. The {G} and {W} represent the green and white control codes
respectively, and the printer codes used are for Epson-type printers. (You
can substitute 'ds' and 'de' if you have Wordwise-Plus.)
Before: {G}ce{G}oc27,45,1{W}THIS IS A HEADING{G}oc27,45,0{W}
After : {G}ce{W}|{G}oc27,45,1{W}THIS IS A HEADING{G}oc27,45,0{W}|
^ pad character or space ^
64. Error reporting
This is a little routine which not only reports errors in your programs, but
also lists the offending line ready for you to edit. The first listing given
only works on Basic version 2 and later, including BAS128, so if you aren't
sure which you've got, press <BREAK>, and then type REPORT <RETURN>. Version
1 is copyright 1981, and version 2 is copyright 1982, etc.. If you have
version 1, or you want the program to be compatible with versions 1 as well
as later ones, then alter the two lines shown underneath, (10025 is an extra
one), and it will then work OK on them all, though not on BAS128. All you
have to do is add the routine before debugging your program, and make the
very first line ON ERROR GOTO 10000. Of course, there is nothing magic about
line 10000, so you can renumber the routine higher if you wish.
In the example below, you should get the error "No such variable at line
100", as A$ hasn't been defined. Be very careful not to make mistakes when
typing the routine; the listing should be copied exactly as shown, even if it
looks rather odd, but you may omit all spaces if you wish. If you are
debugging a listing from a magazine, miss out any other ON ERROR statements
until you have finished. If you get into trouble, then press <BREAK>, type
OLD <RETURN>, and you should get your program back. If you don't want to exit
from the program when <ESCAPE> is pressed, then alter the number 10050 in
line 10000 to the line where you do want the program to got to. You will find
that this routine can save you a great deal of time in the long run.
10 ON ERROR GOTO 10000
100 PRINT A$:END:REM (Spot the deliberate mistake!)
10000 IF ERR=17 THEN 10050:REM (or other line number)
10010 MODE7:REPORT:PRINT" at line ";ERL':*FX15,0
10020 err$="L."+STR$(ERL)+CHR$(11)+CHR$(13)
10030 FOR bit%=1 TO LEN(err$)
10040 OSCLI("FX138,0,"+STR$(ASC(MID$(err$,bit%,1)))):NEXT
10050 END
Make the following changes only if compatibility with Basic-I is important.
10025 DIM X% 12:Y%=X% DIV 256:REM For Basic-1
10040 $X%="FX138,0,"+STR$(ASC(MID$(err$,bit%,1))):CALL &FFF7:NEXT
65. Error calls
Here is a selection of interesting calls into ROM, suggested by Dave
Woodhead. Most of them differ between Basic-1 and Basic-2, so Basic-1
addresses are given first, then Basic-2 addresses are in brackets. You can
use them to deliberately generate errors inside a program, and they can be
trapped in the usual way with ON ERROR GOTO, except for "fatal" ones such as
<BREAK>, and 'Silly'. Note that the calls for <BREAK> and 'Locked' are into
the OS ROM, and apply to version 1.20 only. There must be all sorts of
devious uses for these calls, especially the ones for <ESCAPE>, <BREAK> and
'Locked'. The syntax is simply CALL &D9CD, CALL &F1F9, and so on.
D9CD=Soft Break D9DA=Hard Break
F1F9=Locked 9839(982A)=Syntax error,
9848(9838)=Escape 97F0(9821)=Mistake
A677(A66C)=Too big AA45(AA38)=Accuracy lost
AE72(AE43)=No such variable B1B9(B18A)=Bad call,
8F2F(8FDF)=Silly 99A6(99A7)=Division by zero
98DD(9C03)=String too long AED9(AEAA)=Bad HEX.
66. Storing mode 7 screen
It can sometimes be useful to be able to store a screenful of information
within a program, and to be able to recall it at will, without having to
store all the appropriate variables. This is especially easy and quick with
Mode 7 screens, although it can be done on others. The example below stores
just one screenful at a time, but you could DIM extra space to save several
screens at once, eg. DIM screen1% 1000,screen2% 1000,......
If you only want to save part of the screen, then reduce the upper and lower
limits of the FOR-NEXT loop. The cursor is also returned to its original
position on the screen. To prevent corruptions, it is a good idea to disable
the Escape key while the screen is being loaded or saved, using the
appropriate *FX command*. This will only correctly save a screen which hasn't
been scrolled since the last MODE or CLS command. For this reason, it may
also be necessary to use CLS before reloading a screen. Note that unlike
true variables such as mem%, it is essential for HIMEM to be in brackets,
due to a Basic interpreter quirk. PAGE and TOP, which are similar
pseudo-variables, do not suffer from this problem.
NB:
*FX229,1 inhibits the Escape action
*FX229 enables the Escape action
10 DIM screen% 1000:REM have this early in program
1000 DEF PROCsavescreen:LOCAL mem%
1010 FOR mem%=0 TO 996 STEP 4:mem%!screen%=mem%!(HIMEM)
1020 NEXT:vpos%=VPOS:pos%=POS:ENDPROC
2000 DEF PROCloadscreen:LOCAL mem%
2010 FOR mem%=0 TO 996 STEP 4:mem%!(HIMEM)=mem%!screen%
2020 NEXT:VDU31,pos%,vpos%:ENDPROC
67. Sideways ROM search
This is an interesting little program, adapted from one supplied by Dave
Woodhead. It searches sideways ROMs, looking for words of more than one
letter, and it then prints them on the screen. You get a lot of garbage also,
but it's fun looking at all the commands and error messages. The ROM number
will be 0 to 3 on a standard machine, and up to 15 if you have an expansion
board. The Basic ROM is a good starting point, and this is usually in socket
0 on a standard machine. The program expects a 16k ROM, eg Basic or Watford
DFS, but if the ROM is only 8k, as many are, then the search will run through
twice. You can limit the search to 8k by altering the &BFFF to &9FFF in line
20.
Please note that the use of Y% in line 10 is essential, even though it
doesn't seem to do anything! If nothing appears on the screen within a few
seconds, then the socket is empty. The Operating System ROM is NOT a sideways
ROM, and so cannot be searched with this program, unless you have, say, an
old OS 0.10 chip to plug into a spare sideways socket.
10 INPUT "ROM Number ",Y%
20 FOR !&F6=&8000 TO &BFFF
30 C%=USR(&FFB9) AND &FF
40 IF (C%>64 AND C%<91) OR (C%>96 AND C%<123) THEN VDU C%
ELSE IF POS=1 THEN VDU 13 ELSE IF POS>1 THEN PRINT
50 NEXT:PRINT'"End of Search"
68. Secure cipher code
One of the most fascinating stories of World War II concerns how British
Intelligence were able to crack the codes generated by the German "Enigma" cipher machines. Thanks to a simple but elegant idea from James Slater, you
too can produce very secure code using your Beeb. The method relies on the
fact that you can "seed" the random number generator to start at different
points in the pseudo-random sequence, and the message can't be decoded unless
you know the "key" integer number used to seed the generator in the first
place. The ASCII code is shifted by a random amount each time, and if you
type a continuous string of A's, you will see the result!
Note that the random number generator on the Master/Compact is coded
differently from that on a BBC B/B+, so there is no compatibility between
them when using this technique.
The more digits you use in your key number, the harder it will be to crack
the code by chance. The message may contain any keyboard character, including
<SPACE>, but not <RETURN>. I am sure this cipher would not be considered
secure in the context of giant business computers, which can try umpteen
millions of combinations in a short time, but I reckon it could be a useful
way of protecting private data on micros.
If you make the alterations shown underneath, only capitals will be allowed,
and the test is forced into 5-letter groups for extra security.
Try it, it's great fun, but NOT over the air - it's strictly against the
rules!
100 MODE6:INPUT''"Enter CODE KEY... "n%
110 randomize=RND(-(ABS(n%)))
120 PRINT'"Decipher or Encipher (D/E) ? ";
130 REPEATg$=CHR$(GETAND&DF):c%=INSTR("DE",g$)*2-3:UNTILc%<>-3
140 PRINTg$''"Please type your MESSAGE"'
150 REPEAT:REPEATg%=GET:UNTILg%>31ANDg%<127
160 IFPOS>38THENPRINT''
170 k%=g%-32+c%*(RND(95)-1):VDUg%,10,8(k%+95)MOD95+32,11
180 UNTILFALSE
Alternative lines for 5-letter groups, capitals only:
150 REPEAT:REPEATg%=GET:UNTILg%>64ANDg%<91
160 IFPOS>35THENPRINT'''" ";ELSEIFPOS MOD6=0 THEN PRINT" ";
170 k%=g%-65+c%*(RND(25)-1):VDUg%,10,8(k%+25)MOD25+65,11
69. Ignoring shift/caps lock
Simple routines which GET a character from the keyboard can be defeated by
the CAPS and SHIFT LOCK settings. For example, if you are supposed to be
answering "Y" or "N" to a question, then a "y" or "n" may confuse matters.
Alternatively, if you are selecting from a menu, and should be entering a
number from "1" to "5", then "!" or "%" will not do. If you have Wordwise,
try using the main menu with the SHIFT LOCK set, and you'll see what I mean.
You could overcome this by setting the required shift, from inside the
program, with *FX202. A better way is to use AND and OR to ignore the effect
of any binary bits which alter with the shift settings.
This exploits the fact that "A" in binary ASCII is 01000001 and "a" is
01100001, and so on. Only the 3rd most significant bit is different, (bit 5),
and we need to make sure it is always 0. The binary number 11011111 is DF in
Hex, so, instead of A$=GET$ to get a "Y" or "N" answer, use A$=CHR$(GET AND &DF), which will always return capital letters. This can conveniently be used
in a Function; ie A$=FNget, where the Function is defined as
DEFFNget:=CHR$(GET AND &DF).
In a similar fashion, a "1" in binary ASCII is 00110001, and a "!" is
00100001. Only bit 4 differs, and this time we want to make sure it is always
a 1, and 00010000 is 10 in Hex. So, for numbers, instead of using A=VAL(GET$)
or A=GET-48, you can use A=(GET OR &10)-48. Again, it is handy to use a
Function; ie A=FNnum, which is defined as DEFFNnum:=(GET OR &10)-48.
Letters (capitals) - DEF FNget:=CHR$(GET AND &DF)
Numbers (digits) - DEF FNnum:=(GET OR &10)-48
70. Caps lock and shift lock
If you use the keyboard with the <CAPS LOCK> off, then you have to press
<SHIFT> to get upper-case letters. As an alternative, you can hold down
<SHIFT>, press and release <CAPS LOCK>, and then release <SHIFT>. You will
now find that you will get upper-case normally, but lower-case if you hold
<SHIFT>. The effect is cancelled by pressing <CAPS LOCK> or <SHIFT LOCK>.
This can also be achieved from within a program with *FX202,160 , normal
<CAPS LOCK> is *FX202,32 , normal Shift Lock is *FX202,16 , and no lock at
all is *FX202,48 . You should really follow these calls with *FX118 , to make
sure the keyboard LEDs change, but it doesn't seem to be necessary.
*FX202,160 - Reverse Caps Lock
*FX202,48 - No Lock at all
*FX202,32 - Normal Caps Lock
*FX202,16 - Normal Shift Lock
71. Acorn DFS 0.90 and 1.20 (DNFS) workspace
** GENERAL ALLOCATION **
Memory Locations Function
~~~~~~~~~~~~~~~~ ~~~~~~~~
&D00- DFF General Workspace
E00- EFF Copy of Track-0 Sector-0 (with variations)
F00- FFF Copy of Track-0 Sector-1
1000-10FF General Workspace
1100-11FF Parameter Blocks for Files
1200-12FF 1st File Buffer + SPOOL/EXEC
1300-13FF 2nd File Buffer
1400-14FF 3rd File Buffer
1500-15FF 4th File Buffer
1600-16FF 5th File Buffer
1700-18FF Further Workspace
** USEFUL LOCATIONS **
{A} means ascii code {N} means literal number
&E00-E07 {A} First 8 bytes of disc Title, (see &F00-&F03).
E08-E0E {A} First Filename, (7 bytes, padded with spaces).
E0F {A} First Directory, (00 if same as current directory).
NB: MSB of directory will be set if file is locked. You should
AND this byte with 127 to get directory, and AND it with 128 to
detect if it is locked.
E10-E16 {A} Second Filename
E17 {A} Second Directory
E18-E1E {A} Third Filename
E1F {A} Third Directory
E20-E26 {A} Fourth Filename
E27 {A} Fourth Directory
etc..
EF8-EFE {A} Thirty-First Filename
EFF {A} Thirty-First Directory
F00-F03 {A} Last 4 bytes of disc Title
(If less than 12 characterss, title is terminated with 00 on
0.90, but padded with spaces on 1.20.)
F04 {N} Number of writes to the Catalogue. (Hex number which appears
after disc Title)
F05 {N} Number of files on disc, multiplied by 8.
F06 {N} !BOOT file *OPT4 Option number. (eg 3 for EXEC).
0.90 1.20
&10CA &10C9 {A} Current Directory
10CB 10CA {N} Current Drive number
10CC 10CB {A} Library Directory
10CD 10CC {N} Library Drive number
72. Top 10 speed techniques
Here is a list of techniques to increase the speed of your programs, courtesy
of Bob Horne. Some are fairly well known, others may be new to you. The
amount of improvement can vary from dramatic to marginal, but small
improvements here and there can add up to substantial increases in speed. You
should use the TIME facility to measure which parts of the program are
slowest, and to assess the effect of using these techniques. You should
initially concentrate your attentions on statements inside loops, whether
they be FOR-NEXT loops, REPEAT-UNTIL or IF-THEN-GOTO loops, as this is where
small delays tend to add up. ie. pay special attention to lines which are
executed most often. By all means do break these rules if it improves clarity
without slowing things down, so use your common sense!
1. Use integer variables, (especially the resident A%-Z%), and integer arrays
where possible, including loop-counter variables. (ie. FOR A%=1 TO 10.)
2. When graphics are drawn with a FOR-NEXT loop, use the largest STEP
size the Mode resolution will allow. (ie. 4 vertically, and 2, 4 or 8
horizontally.)
3. Miss off the loop-counter variables in NEXT statements. (ie. use NEXT
rather than NEXT A%.)
4. Ensure that all unnecessary calculations are done outside loops.
(eg. X*3*PI/2 inside a loop is slower than X*p, where p=3*PI/2 before the
loop is entered.)
Use REMs where they will be executed, then put them on the end of an
existing line, rather than separately. eg b=RAD(b):REM convert to radians.
5. Don't put REMs or blank lines where they will be executed often; even
though they don't actually do anything, they will slow things down. They
are harmless if the program jumps round them, but don't go putting in
GOTOs specially, as that's just as bad. If you must use REMs where they
will be executed, then put them on the end of an existing line rather than
separately. Eg: 10 b=RAD(b):REM convert to radians
6. Use multistatement lines; the fewer line numbers that are involved, the
faster the program works.
7. Procedures/Functions may sometimes be faster than GOSUBs, (but you never
use GOSUBS anyway, do you?)
8. Use short Procedure/Function names, try to have them all start with a
different letter, and put the DEF of the Procedures called most often
before the others, (ie. at a lower line number).
9. Use short variable names, and try to start them with different letters, as
for Procedures.
10.FOR-NEXT loops are faster than REPEAT-UNTIL or IF-THEN-GOTO loops.
73. Interlacing in modes 0-6
Turning the interlacing off can produce a much steadier picture. This is done
using the *TV command, which is only partly explained on page 23 of the User
Guide. The full syntax is *TV A,B , where A determines how many lines up or
down the display is moved, and B determines whether the i/l is turned on or
off.
Thus, to leave the picture as it is, but to turn the i/l off, you use *TV0,1.
To move the picture down one line as well, you use *TV255,1. To move the
display, but keep the i/l on, you would use *TV255,0 , which can be shortened
to the familiar *TV255. To restore the display to normal, ie. i/l on and no
shift, you use *TV0,0, which can be shortened to just *TV. Don't forget that
the commands will have no effect until you change Mode, and that the
interlacing always stays on in Mode 7.
74. Interlacing in mode 7
Having just told you that you cannot turn the interlacing off in Mode 7, here
is a way of doing just that! This idea was passed on by Dave G4IAU, who
thinks that it may have originated from Belfast University. It eliminates the
classic Mode 7 'shake', which can be especially bad on some samples of
Microvitec monitors.
It is a three-part VDU23 statement. The first part turns the i/l off, and the
second halves the number of scan lines per character to correct for the lack
of interlacing. I stuck the final part on to halve the number of scan lines
before the cursor starts, otherwise it gets lost. The commands alter
registers 8,9 and 10 of the 6845 CRT controller, and this is explained on
pages 364-367 of the Advanced User Guide. The command takes effect
immediately, and is reset by a Mode change. It is very effective on block
graphics and double-height characters, but you lose the rounding on
normal-height characters, with interesting results!
I/L off:- VDU23;8,144,0;0;0;23;9,9,0;0;0;23;10,105,0;0;0;
I/L on :- VDU23;8,147,0;0;0;23;9,18,0;0;0;23;10,114,0;0;0;
75. Random numbers not including zero
There are times when you may want to generate a random number, which can be
positive or negative, but which must not include zero. Alternatively, you may
wish to multiply something by -1 or +1 at random, perhaps to determine which
way a monster will turn in a maze etc..
An easy way to generate -1 or +1 is with Z=SGN(RND) , (the brackets are
optional). RND on its own generates a number between -2147483648 and
+2147483647, so its SGN can only be -1, 0 or +1. Since the likelihood of RND
generating zero is about one in 4000 million, the result for all practical
purposes is always -1 or +1! To generate a random number between say, -9 and
+9 , but not including zero, you could use Z=RND(9)*SGN(RND). Thanks to
James Slater for passing this idea on.
76. Jumping out of loops, procedures etc.
As you know, it is very risky to use GOTOs to jump out of FOR-NEXT and
REPEAT-UNTIL loops, or out of Functions and Procedures. Sooner or later you
will get an error message along the lines of "Too many FORs", or else various
odd things will start to happen. However, if your program has error-trapping
with ON ERROR GOTO, you may have noticed that it doesn't seem to matter how
many times you jump out of whatever the program is doing, to go back to the
main menu, nothing untoward happens. Thus, if you could generate an Escape
from within the program, you could happily jump out of anything, provided
that you didn't jump into the middle of something else.
This is possible in various "dirty" ways, such as CALL &9848 (Basic-1), CALL&9838 (Basic-2), and CALL &F9AB (OS 1.20). These are very naughty, as they
vary with Basic or Operating System versions, and are not Tube compatible.
The tidy way is with *FX153,0,27 and this works very well. *FX153 is very
similar to *FX138, which some of you may know, but it accepts the Escape
character as an error, and not just as an ASCII code like any other key.
When jumping out of Procedures or Functions, the micro will not release
LOCAL variables, so they may clash if used in the main body of the program,
(ie. with Global variables). This call will not work if you have disabled
the Escape key with *FX200 or *FX229, so if you really must do it like that,
then CALL &F9AB is the best of the dirty methods.
77. *FX lookalike
You cannot use variables or Hex numbers in *FX calls, and they must go at the
end of a line. This Procedure performs a *FX call; you can use variables or
Hex numbers, and it can go anywhere on a line. Call it with PROCfx(a,x,y)
where a,x & y are the three normal parameters, (use zeroes if there are less
than three). Eg, *FX5,1 would be equivalent to PROCfx(5,1,0) . Note that
A%,X% & Y% are implied LOCAL variables, so will not clash if used elsewhere
in the program.
1000 DEFPROCfx(A%,X%,Y%):CALL&FFF4:ENDPROC
78. Reading *FX calls
*FX, (Osbyte), calls 156 and 165 upwards, are special read/write ones. (See
the Advanced User Guide for full details.) You may write to them from BASIC
with *FXa,x where a is the call number, and x is the new value to be
written, eg *FX229,3 . You can also read the existing value, without altering
it, using FNfx(a). Eg value=FNfx(229) . Note that strictly speaking, you
should add X%=0 to line 2000, but defining LOCAL variables automatically sets
them to zero, so you need not bother.
2000 DEFFNfx(A%):LOCALX%,Y%:Y%=&FF
2010 =(USR(&FFF4)AND&FF00)DIV&100
79. User port experimenting (3)
Here is a little program to enable you to use your micro as an AF signal
generator. The tone is emitted as a 5 Volt p-p squarewave on pin PB7 of the
User Port. I suggest you connect a 0.1uF capacitor and a 10k resistor in
series with the output, to protect the 6522 VIA chip. The program initially
generates 1000 Hz, and you then enter the frequency required. The timing
increments available are fairly coarse, especially near the 25kHz end, so the
frequency you actually get will not be exactly what you asked for. The
maximum frequency possible is 250kHz, but the next increment down is 167kHz,
which isn't very helpful! You can hear the tone by connecting a CRYSTAL
earphone or microphone insert across the output, or by feeding it into an
amplifier.
10 ON ERROR GOTO 80
20 ?&FE6B=&C0:?&FE64=&F2:?&FE65=1:freq%=1000
30 REPEAT:F%=10^6/freq%/2-1.5:?&FE66=F% MOD 256:?&FE67=F% DIV 256
40 actual%=10^6/((F%+2)*2)+0.5
50 PRINT"Generating: ";actual%" Hz"'
60 REPEAT:INPUT"Frequency ? "freq%:UNTIL freq%>49 AND freq%<25001
70 UNTIL FALSE
80 REPORT:PRINT" at line ";ERL:?&FE6B=0
80. Text screen dump
This Procedure enables you to dump the entire text from the screen onto your
printer. It will work in any Mode from 7 up to 0, and is called by specifying
the number of columns and lines; eg. PROCdump(40,25) for Modes 6 and 7. Any
Mode 7 teletext control codes will be printed as blank spaces, and graphics
in other Modes will be ignored. Only text which has been printed in normal
character positions will be printed; any which was printed with the aid of
VDU5 and MOVE will not show. If your printer has an enlarged-print facility,
you might like to insert the appropriate control code in lines 1015 and 1055
for dumping Modes 2 and 5; the code is VDU14 for the Epsons.
If you want to be very posh, you can extend the Procedure so that it sorts
out what screen Mode is in use automatically, with the aid of the Function
given in an earlier tip. Note that you should omit line 1050 if your printer
does auto linefeeds after a carriage return, and that the setting of the *FX6
option has no effect on the dump Procedure. The little FNpeep at the end may
be used independently if required; it returns the ASCII code of the character
at screen position X,Y. Eg. A$=CHR$(FNpeep(12,15)) would make A$ equal to
whatever character was in column 12 of line 15, and would leave the cursor at
that position.
1000 DEF PROCdump(width%,depth%):LOCAL X%,Y%,ascii%
1010 VDU6,26,4,2
1020 FOR Y%=0 TO depth%-1:FOR X%=0 TO width%-1
1030 ascii%=FNpeep(X%,Y%):IF ascii%<32 OR ascii%>126 THEN ascii%=32
1040 VDU1,ascii%:NEXT X%:VDU1,13
1050 VDU1,10:REM Omit if printer has auto linefeed option.
1060 NEXT Y%:VDU3,30
1070 ENDPROC
1080:
1090 DEF FNpeep(X%,Y%):LOCAL A%
1100 VDU31,X%,Y%:A%=&87:=(USR&FFF4 AND &FF00)DIV &100
81. Booting up secondary drives
It is very simple to Boot up disc drive 0, by pressing <SHIFT> <BREAK>, but
you cannot usually do this with, say, drive 1. (Some independent DFSs do
allow this, but not Acorn ones.) However, there is a way, which works as long
as you have a disc in drive 0 as well. Just insert this routine at the start
of whatever program the !BOOT file CHAINs - eg a menu utility. All you do to
Boot up drive 1 is to Boot up drive 0 as normal, but hold onto the <SHIFT>
key just a little longer than usual, until you see drive 1 start up. Do
release the <SHIFT> key as soon as drive 1 starts up, or it may go into a
harmless loop until you do let go. Needless to say, if you have a
double-sided drive, then this works just as well for drive 2 instead of 1.
95 IF INKEY(-1)=0 THEN 100:REM Test for <SHIFT>.
96 *DR.1
97 *EXEC !BOOT
98 END:REM You need this!
100 REM Start of main program.
82. Building !BOOT file
Those of you with disc drives will know that it is sometimes not possible to
use *BUILD without the "disc full" message being issued, even though the disc
still has quite a bit of room on it. This is because the DFS, not being
telepathic, has no advance knowledge of how long the file will be, (only you
know that), and tends to assume that it will need lots of space on the disc.
One way round this problem is to *BUILD the file on a spare disc, and then
*COPY it across. A more convenient method is to save a dummy !BOOT file onto
the disc first. The most convenient and safe way of doing this is to use
*SAVE !BOOT 0 1. This saves a dummy file of length one byte onto the disc, so
as to get the filename "!BOOT" onto the catalogue. You should then have no
difficulty in *BUILDing your !BOOT file afterwards, in the normal way. Note
that this method will not corrupt any files in memory, and it can safely be
used from BASIC, View, Wordwise etc.. This technique works equally well when
you wish to use the commands *SPOOL or OPENOUT/UP, but get "Disc full" messages.
83. Can't-extend errors
The annoying message "Can't extend" is sometimes issued by the DFS when
replacing an existing file with a longer version of the same name. This is
because the file is 'sandwiched' in by others on the disc, and can't 'grow'
any further. You can often overcome this by using *DELETE to remove the
existing file, and then Saving the new version. The reason for this is that
the DFS now puts the file after all the others on the disc, instead of trying
to put in back in the original 'slot'. However, if you get the message "Disc
full", you will have to save the file on a spare disc, *COMPACT the original
one, and then try and fit the file back on with *COPY. Yes, the Beeb DFS
really is rather thick I'm afraid; intelligent DFS's take care of all this
disc 'Housekeeping' automatically.
84. *SAVE bug
It is useful to be able to save very long dummy files when reserving disc
space for random access files, (or for other purposes), as recommended in the
Acorn DFS User Guide. The syntax is *SAVE 0 N or *SAVE 0+N, where N is the
length in Hex. This is very fast, and works fine on the 1.20 Acorn DFS,
(DNFS). However, on the 0.90 Acorn DFS, horrible things happen as soon as N
exceeds &FF00, (just under 64k), and the disc tends to be corrupted. The
alternative is use OPENOUT, and advance PTR# to the required length. In the
example below, an 88k file can be reserved, albeit very slowly. The DNFS is
much faster than the 0.90 all round, but the difference is particularly
noticeable when you are using Random Access Filing, and it's worth upgrading
if you can get hold of the EPROM.
The Acorn 1770/1772 DFS does not suffer from this problem.
Remember that 1k is 1024 bytes, so PRINT &16000/1024 gives the answer 88k.
10 chan=OPENOUT("name"):PTR#chan=&16000:CLOSE#chan
85. Disc drive hints
*BACKUP produces a duplicate of the original disc, with all the files,
(programs), in the same order on the disc. *COPY, on the other hand, reverses
the order on the disc. The catalogue will not show this up, as it is always
in alphabetical order, but you can tell if you use *COMPACT or *INFO.
If you use a '*' command which none of the ROMs recognize, then the Acorn
DFS's will attempt to *RUN a file of that name. If the file is not a
machine-code routine, then the attempt will fail. However, the Watford
DFS's go one step further, because they will *EXEC the file if it is text,
(ie if it has been SPOOLed onto disc).
This was written before the Master and the 1770 DFS came out. I think
that they too are semi-intelligent in this situation.
86. Formatted disc speed
You can get faster response times from your disc just by using the right
formatting program. Each floppy has a small index hole near the large centre
hole. Some formatters put sector 0 after the index hole on every track. The
effect of this is that each time the head steps from one track to the next,
it misses the start of sector 0, causing a delay until the index hole comes
round again. The better formatters provide an offset of several sectors
between each track to allow the head to settle after stepping. The following
program was used to compare different formatters.
10 *CAT Return Head to Track 0 and spin disc.
20 TIME=0
30 *VERIFY Must have Watford DFS or Disc Doctor.
40 PRINT TIME
The Watford DFS formatter is one of the slowest, somewhat surprisingly being
beaten by a BASIC program available free on Micronet. Disc Doctor has a very
fast formatter, and the Cumana program is also good.
Further improvements in speed can be achieved by moving frequently accessed
small files to the outer edge of the disc, i.e. nearer to the catalogue.
The prime candidates for this treatment are the !BOOT and MENU files. These
files are usually added as an afterthought when the disc is complete, thus
placing them near the centre of the disc. This results in much tracking
noise, wasted time and head wear each time the disc is booted. Far better
to put dummy !BOOT and MENU files on the disc immediately after formatting
it, ensuring that these vital files reside (mostly) on track 0.
(One way to save a dummy file is to use *SAVE !BOOT 0 1, but this only
reserves one sector of 256 bytes, but you can use *SAVE MENU 0 n00, where n
is the number of sectors to be reserved.)
NB: This was written before the Acorn 1770 DFS was released; this does of
course support the *VERIFY command.
87. Acorn DFS page setting
The normal setting of PAGE with the Acorn DFS 0.90 and 1.20, (DNFS), is&1900. It is possible to set it at a lower value, in order to gain valuable
memory space, but only at a price. Here is a list of the possible PAGE
values, together with a note of the facilities available. The limitation
revolves around the number of files which can be simultaneously open, and
whether you can use *SPOOL and *EXEC, which is a type of file. Note that
LOAD/SAVE also refers to all the similar commands CHAIN, *LOAD, *RUN etc..
It is interesting to note that a PAGE value of &1700 would appear to be just
a good as &1900, and that &1100 is just as good as &1200. &1100 is the
absolute minimum value possible without nasty things happening if you access
the disc drive(s), even just to do a *CAT. For those of you who are
interested in making use of the information contained in the disc workspace,
details were given in tip #71.
In order to get most of the information into the workspace, the disc must
have been accessed at least once; just a *CAT will do. If you don't actually
want the catalogue to come up on the screen, then precede the *CAT with
VDU21, and follow it with VDU6 on the next line. This will temporarily
inhibit the screen.
PAGE VALUE FACILITIES
&1900 5 Files + LOAD/SAVE + SPOOL/EXEC
1800 5 Files + LOAD/SAVE + SPOOL/EXEC
1700 5 Files + LOAD/SAVE + SPOOL/EXEC
1600 4 Files + LOAD/SAVE + SPOOL/EXEC
1500 3 Files + LOAD/SAVE + SPOOL/EXEC
1400 2 Files + LOAD/SAVE + SPOOL/EXEC
1300 1 File + LOAD/SAVE + SPOOL/EXEC
1200 0 Files + LOAD/SAVE
1100 0 Files + LOAD/SAVE
less than 1100 No disc operations possible
88. Auto-loading of disc files
When using programs that save and load data files frequently, care has to be
taken to load the most recently saved file. If files are saved with numbers
as filenames which are increased by one each time, the procedure will load
the file with the highest number. The example below assumes that the highest
possible number is 10, but the lowest can be 0 or 1.
LISTING-1:
100 file%=11:REPEAT:file%=file%-1:REM start with highest possible plus 1.
110 chan%=OPENIN(STR$(file%)):REM Use OPENUP on Basic 2.
120 UNTIL chan%=0 OR file%=0
130 IF chan% THEN 200
140 PRINT"No file found":*CAT
150 STOP:REM This bit is up to you.
200 PRINT"Found file number ";file%
210 REM INPUT#chan% can now be used in normal way.
220 CLOSE#chan%:REM Tidy up afterwards.
230 REM Rest of the program.
LISTING-2:
100 FOR file%=0 TO 9:REM Save dummy files to disc.
110 chan%=OPENOUT(STR$(file%))
120 CLOSE#chan%:NEXT
In listing 1, Line 110 converts file% to a string and attempts to open a file
of that name on the disc for input. A number is allocated to chan% for this
operation, but this is 0 if the file is not found. The program loops between
lines 100 and 120 until either chan% is not 0 or file% has reached 0. To test
this, write some dummy files to disc as shown in listing 2, and then try the
example in listing 1. Rather than have just numbers as the filenames, you
could save files as "data1", "data2" etc., by modifying the (STR$(file%)) to
("data"+STR$(file%)). Note that this technique can be adapted to
automatically load a series of files in turn, performing a search or other
operation on each one.
89. Moving text (1)
This is a very simple routine which 'assembles' text from the right-hand
margin. It is an example of moving graphics at the very simplest level, and
illustrates the use of *FX19 to create smooth movement. It is written for a
40-column mode, but can be modified for 80 if required. You can omit any
spaces, which are shown only for clarity.
10 MODE 7:VDU23,1,0;0;0;0;
20 PROCmove("HELLO THERE!!",12,10)
30 PRINT'':VDU23,1,1;0;0;0;:END
40 :
100 DEFPROCmove(text$,pos%,vpos%)
110 FOR let%=1 TO LEN(text$)
120 FOR p%=37 TO pos%+let%-1 STEP-1
130 PRINT TAB(p%,vpos%) MID$(text$,let%,1)" ";:*FX19
140 NEXT:NEXT:ENDPROC
90. Moving text (2)
Here is another short demonstration of moving text. It uses MID$ in a rather
cunning way to achieve the movement very simply. If you omit the CLS from
line 10, then you get quite a different effect. The routine repeats until you
press any key.
10 MODE2:VDU23,1,0;0;0;0;:COLOUR1:COLOUR131:CLS
20 ME$=STRING$(20," ")+"******* THIS PROGRAM HAS BEEN BROUGHT TO YOU
BY COURTESY OF THE WAKEFIELD BBC MICRO USER GROUP *******"
30 REPEATa%=0:REPEATa%=a%+1:PRINTTAB(0,29)MID$(ME$,a%,20):
b%=INKEY(15):UNTILa%=LEN(ME$)ORNOTb%:UNTILNOTb%
40 MODE7:END
91. Shadow printing
Text printing on the screen looks far bolder and nicer if it appears to cast
a slight shadow. This is used to good effect in the titles to a number of
commercial programs. Here is a very useful procedure to produce this in any
mode with 4 or more colours; ie Modes 1,2 and 5. You must specify the two
colours to be used, and these must not be the same as the current background
colour. In the example below, colours 1 and 2 are used, and you can alter the
MODE statement to either 1 or 5 to see how the function utomatically adjusts
to cater for the different graphic resolution. If you are sticking to just
one mode, then you can simplify the function by getting rid of line 110,
removing all references to A%, mode% and fact%, and substituting 32 or 64 for
the variable fact% in lines 130 and 140. (The expression fact%DIV32 will of
course also simplify to just 1 or 2.) If you do not want to have to specify
the colours in the FN brackets, then you can omit them, remove all reference
to c1% and c2% in the program, and merely substitute the required numbers in
line 130 and 140. This will simplify the procedure even further, at the
expense of versatility.
A very pleasing effect can be produced by running the program below in Mode
2, after adding :COLOUR132:CLS: immediately after the MODE statement in line
10. You can alter the position of the shadow by trying different combinations
of +4, 0 and -4 in place of the two -4's in line 130. Ie the shadow can fall
above, below, to the right, left or centre of the text.
Do remember that the Function is only for Modes 1,2 and 5; it simply won't
work in the others.
10 MODE2:PRINTTAB(0,9)"WAKEFIELD "FNshad(1,2,"BBC")" MICROS"
30 END
40 :
100 DEFFNshad(c1%,c2%,text$):LOCALA%,mode%,fact%,v%,p%
110 A%=&87:mode%=(USR(&FFF4)AND&FF0000)DIV&10000
120 p%=POS:v%=VPOS:IFmode%=1THENfact%=32ELSEfact%=64
130 VDU5:GCOL0,c2%:MOVEp%*fact%-4*(fact%DIV32),((32-v%)*32-1)-4
140 PRINTtext$:GCOL0,c1%:MOVEp%*fact%,(32-v%)*32-1:PRINTtext$
150 VDU4,31,p%+LEN(text$),v%:=""
92. Graphics demo
This is a short demonstration of an interesting undocumented feature of the
BBC Operating System on the BBC B, B+, Master, Arc etc.. It's a weird graphic
effect that is easier to demonstrate than describe, so get typing!
Make sure you type it in very carefully, and save it before you run it. If
you make any mistakes, the machine might 'hang up'.
10 REPEAT:READ A$:A%=EVAL("&"+A$):CALL 65518:UNTIL A%=&15
20 DATA 16,7,1F,C,C,88,83,41,70,72,69,6C,86,46,6F,6F,6C,1E,15
93. Exploring fractals
Fractals is an odd branch of mathematics, only discovered within the last
decade or so. If you keep 'zooming in' to a plot or graph produced by a
mathematical equation, you usually expect to end up with a straight line, or
something equally unexciting. With Fractals, yet more detail is resolved each
time you zoom in on any part of the plot. It reminds me of the witty rhyme "Great Fleas have Little Fleas, upon their backs to bite 'em, and Little Fleas
have Lesser Fleas, and so ad infinitum...".
In this equation, known as the Mandelbrot Set after its discoverer, the
horizontal axis is effectively scaled from -2.25 on the left to +0.75 on the
right, whilst the vertical axis is scaled from -1.5 at the bottom to +1.5 at
the top. If you wish to examine any part of the plot in more detail, ie to
'zoom in', then just choose a narrower range of values, and edit line 10
appropriately. For example, you could use -1.5 to -1.0 instead of -2.25 to
+0.75, and +0.9 to +1.4 instead of -1.5 to +1.5. Note that the second number
of each pair should be more positive than the first, and that you should zoom
in equally in both axes to keep the right proportions. In the first example,
the total range was 3.0 for both axes, ie +0.75-(-2.25)=3.0 and
+1.5-(-1.5)=3.0, whereas in the second example it was 0.5 for both axes, ie
-1.0-(-1.5)=0.5 and +1.4-(+0.9)=0.5 .
The plots take a very, very long time indeed, but the results are rather
beautiful. The first plot may start off fairly rapidly, as it is drawing
large areas of solid colour, but once it gets onto the intricate bits the
speed drops dramatically, and you may even think the program has 'hung-up' if
it happens to be plotting black on a black background at the time. The
current plotting position is marked with a small dot, which also flashes in
Mode 2. You can save the screen afterwards, to avoid having to wait all that
time again, and this is done in line 110, using the filename "Screen1". To
reload the display at a later date, just use the one-line program underneath.
Save subsequent plots under "Screen2" etc.. If you are using cassette, you
will have to suppress screen messages with *OPT1,0 before each *LOAD or
*SAVE, so see page 398 of the BBC User Guide.
The speed and resolution of the Beeb are barely good enough to even hint at
the real detail and beauty of fractals; you need very large mainframe
computers for that. (Or an Archimedes!) However, by using MODE1, or even
MODE0 in line 20, more detail can be resolved at the expense of speed and
colours. If you do try these modes, then alter the STEP 8 in line 40 to STEP
4 for Mode 1, and STEP 2 for Mode 0. The STEP4 in the second part of the
line should not be changed.
The idea for this program came from an article "Frontiers of Chaos" in The
Guardian newspaper, long before all the computing magazines jumped on the
bandwagon!
10 limit%=48:Xmin=-2.25:Xmax=0.75:Ymin=-1.5:Ymax=1.5
20 MODE2:VDU5
30 Horiz=(Xmax-Xmin)/1279:Vert=(Ymax-Ymin)/1023
40 FOR Xcoord%=0 TO 1280 STEP 8:FOR Ycoord%=0 TO 1024 STEP 4
45 GCOL0,11:PLOT69,Xcoord%,Ycoord%
50 M=Xmin+Xcoord%*Horiz:N=Ymin+Ycoord%*Vert:colour%=0:X=0:Y=0
60 REPEAT:R%=X*X+Y*Y:T=X*X-Y*Y+M:Y=2*X*Y+N:X=T:colour%=colour%+1
70 UNTIL R%>100 OR colour%=limit%
80 colour%=colour% MOD limit%
90 GCOL0,colour% MOD 8:PLOT69,Xcoord%,Ycoord%
100 NEXT:NEXT
110 *SAVE Screen1 FFFF3000+5000
10 REM Program to reload screen display
20 MODE2:VDU5:*LOAD Screen1 3000
(This was written in early 1985 - fractals have come on since then!)
94. Blanking the screen
It might sometimes be useful if you could blank the screen with a command,
but turn it back on again, revealing all the original text/graphics
unchanged. You can do this with the command VDU23,0,R,V,0;0;0; This is a
general command to write value V into register R of the 6845 CRT controller
chip. If you make R=0, then V=0 will blank the screen, and V=127 will turn it
back on again in modes 0 to 3, and V=63 should be used for modes 4 to 7. It
would be interesting to write an Event-driven routine which blanked the
screen if none of the keys have been touched for more than a minute or so,
and restored the screen as soon as a key is pressed, checking to see which
mode is in use.
95. Auto screen-off
Further to the previous tip, Adrian Botham has written a machine-code routine
which turns the screen display off if no key has been pressed within the
previous minute. As soon as a key is pressed, the screen display magically
reappears with its contents preserved. This helps to lengthen the useful life
of the cathode ray tube by preventing 'phosphor burns'. The code occupies 88
bytes, and I have used the cassette/RS423 input buffer area at &A00. If this
interferes with any of your other software, then you can try putting it
somewhere else.
After running the program, you can load other programs in, switch to Wordwise
etc., and as long as you don't press <BREAK>, then the 'auto screen-off' will
operate.
Any of you who want to figure out how it works should read chapter 12 of the
Advanced User Guide for the BBC Micro, and also chapter 9.5 and 9.6.
The only spaces in the listing are absolutely essential, and note that the
underline character is used in some variable names, and should not be
confused with the minus sign, which looks very similar in mode 7. (The
underline character is on the same key as the Pound sign.) After typing in
the listing, save the program before attempting to RUN it.
100 osword=&FFF1:osbyte=&FFF4:evntv=&220
110 clock_pars=&A00:code%=clock_pars+5
120 FORpass%=0TO1:P%=code%
130 [OPTpass%*2
140 PHP:CMP#2:BEQkey_pressed
150 CMP#5:BEQminute_up:PLP:RTS
160 .key_pressed PHA:TXA:PHA:TYA:PHA
170 LDA#0:STA&FE00:LDA&FE01:BEQturn_screen_on
180 .set_time LDX#clock_pars MOD256:LDY#clock_pars DIV256
190 LDA#4:JSRosword:JMPexit
200 .turn_screen_on LDA#132:JSRosbyte
210 CPY#&41:BPLfour_seven
220 .zero_three LDA#127:STA&FE01:JMPset_time
230 .four_seven LDA#63:STA&FE01:JMPset_time
240 .minute_up PHA:TXA:PHA:TYA:PHA
250 LDA#0:STA&FE00:STA&FE01
260 .exit PLA:TAY:PLA:TAX:PLA:PLP:RTS
270 ]NEXT
280 ?evntv=code%MOD256: evntv?1=code%DIV256
290 !clock_pars=&FFFFE890:clock_pars?4=&FF
300 *FX14,2
310 *FX14,5
320 CALLcode%
96. Printer pound/hash sign fix
On all Epson-compatible printers, there is a discrepancy between the keyboard
Pound currency sign, and the printer Pound sign. Character 96 on the keyboard
is a Pound sign, but the printer prints a sort of ‘ sign - like a
lefthanded apostrophe. The Pound sign on the printer is shared with character
35, the "#" (Hash or Sharp symbol), depending on whether you are using the
American or English character set. However, those of you with an Epson FX80
and some other printers can use a more elegant solution. It is possible to
redefine the printer character set, and thus turn character 96 to
a proper Pound sign, (dipswitch 2-3 on the NLQ's and 1-4 on the FX80 must be
"off").
This little program must be run with the printer "ON LINE", and could
conveniently be CHAINed as part of a disc !BOOT file. Those of you who are
more cunning can spool the bytes off directly onto disc, and can then *EXEC
them instead of CHAINing. As it stands, this program has no effect in the
NLQ mode of a Canon/Kaga printer, as a PCG RAM expansion is needed. The DATA
list has only been split for clarity, and to allow me to insert REM
statements, so you can type it all in on one line if you like.
NB: Many newer Epson printers only allow a limited range of characters to be
redefined, so this may not work.
100 VDU2:REPEAT:REM Send data to printer only.
110 READ data%:IF data%>=0 THEN VDU1,data%
120 UNTIL data%= -1:VDU3:END
130 DATA 27,82,0:REM Esc "R" - Select American characters.
140 DATA 27,58,0,0,0:REM Esc ":" - Download from ROM to RAM.
150 DATA 27,38,0,96,96:REM Esc "&" - Specify character 96.
160 DATA 139,18,0,126,128,18,128,2,128,66,0,0:REM Data for sign.
170 DATA 27,38,0,224,224:REM Esc "&" - Repeat for Italic version.
180 DATA 139,18,0,30,96,18,128,18,128,64,0,0:REM Data for Italic.
190 DATA 27,37,1,0:REM Esc "%" - Select RAM for printing.
200 DATA -1:REM Terminator for data.
97. Printing listings (1)
Here is a handy little routine, for using a red key to LIST your programs
without fuss. It is particularly useful if you want to LIST a number of
programs one after another. The routine selects LISTO7 to format the listing
nicely, cancels paged mode, switches the printer on, LISTs the program,
switches the printer off, re-engages paged mode, and then cancels the LISTO.
Please note that the spaces are for clarity only, and should be omitted, even
though it looks mighty odd!
*KEY1 LISTO7|M |O |B L.|M |C |N LISTO0|M
98. Printing listings (2)
Here is another handy little routine from Peter Osborn, using the Perforation
Skipover facility in your printer. This leaves a few blank lines at the top
and bottom of each fanfold sheet, thus avoiding listing lines being bisected
by the perforations. It is shown as a string of VDU codes on KEY0, and the
cancel code is on KEY1. I have assumed that the formlength has first been set
to 11", (the norm), or 12", either on the printer dipswitches or by the
Esc"C" command.
The procedure is to set your paper up so that the print head is approximately
N/2 lines from the top of a sheet, where N is the total number of blank lines
to be skipped. (Ie if you want 3 blank lines at the top and bottom of the
pages, then N=6.) Now switch your printer on, press <f0>, and then LIST your
programs as normal, using <Ctrl+B> and <Ctrl+C> to switch the printer on
and off. You can cancel the skipover with <f1>, to avoid odd things happening
with, say, Wordwise, which can set its own top and bottom spaces. This
routine apparently works on all Epson-compatible printers, and also on the
Star Gemini 10-X.
*KEY0 VDU2,1,27,1,78,1,N,3|M (Enable P-S)
*KEY1 VDU2,1,27,1,79,3|M (Disable P-S)
99. GREEK CHARACTERS
Many printers do not have Greek characters available, and this can be a
nuisance when printing physical, electrical or mathematical formulae. Peter
Osborn and his colleague B.Frere sent in some useful Wordwise codes to print
some of the Greek alphabet on printers using Epson commands. I've improved
some of them a bit, and added a few more; you might find them handy now and
again. If you have Wordwise Plus then you can replace the initial oc27,75 or
oc27,76 with es"K" and es"L" respectively.
The character is sent to the printer only in bit-image mode, and is not
allowed for by any justification or tabbing routine; you'll see what I mean
if you try it. Either avoid these situations, or else try playing about
with pad characters in the text. You can also print the characters from
Basic, by replacing the initial oc with VDU, and preceding each byte with a
1, eg VDU1,27,1,75,1, etc., which is rather tedious. You could 'cheat' by
using *FX3,10 , but there are snags, so I suggest you avoid it.
Incidentally, these codes confuse my machine-code Pound/# sign fix, so avoid
using that too!
Alpha oc27,75,6,0,28,34,34,28,34,0
Beta oc27,75,6,0,127,146,146,108,0,0
Gamma oc27,75,6,0,32,64,63,64,0,0
Delta oc27,75,6,0,108,82,82,12,0,0
Delta (cap) oc27,76,12,0,2,6,10,18,34,66,34,18,10,6,2,0,0
Epsilon oc27,75,6,0,28,42,42,34,0,0
Zeta oc27,75,6,0,184,68,69,67,0,0
Eta oc27,75,6,0,32,30,32,32,31,0
Theta oc27,75,6,0,124,146,146,124,0,0
Kappa oc27,75,6,0,62,8,20,34,0,0
Lambda oc27,75,6,0,2,4,72,60,2,0
Mu oc27,75,6,0,1,62,4,4,62,0
Xi oc27,75,6,0,84,42,43,35,0,0
Pi oc27,75,6,0,32,62,32,62,32,0
Rho oc27,75,6,0,62,73,72,48,0,0
Sigma oc27,75,6,0,24,36,255,36,24,0
Sigma (cap) oc27,75,6,0,130,198,170,146,198,0
Tau oc27,75,6,0,16,32,62,32,32,0
Phi oc27,75,6,0,28,34,34,60,32,0
Psi oc27,75,6,0,56,4,255,4,56,0
Omega oc27,75,6,0,28,34,12,34,28,0
Omega (cap) oc27,75,6,0,26,38,32,38,26,0
100. Printer routine snag
If you wish to send text to the printer only, (ie with nothing appearing on
the screen), there are two simple ways of doing it. You can precede the text
with VDU2,21 , and follow it with VDU6,3 . Alternatively, you can precede it
with *FX3,10 , (or *FX3,9 in the case of RS423 printers), and follow it with
*FX3,0 , (or simply *FX3). In the latter case no VDU2 or VDU3 is necessary,
and in both cases the character set by *FX6,- is not sent to the printer.
This character is ASCII code 10, (linefeed), by default, and is usually set
to 0 with *FX6,0 if your printer doesn't do auto-linefeeds.
This is fine until you try sending a string of VDU codes, such as for the
Greek characters shown earlier. Depending on the setting of *FX6,- , either
10's or 0's will not be sent to the printer, with all sorts of unpredictable
and horrible results. Eg VDU27,10,3,4,0,0,3 would effectively be sent as
VDU27,3,4,0,0,3 or VDU27,10,3,4,3 ! Now since 0's tend to appear much more
often than 10's in VDU statements, those of you with printers doing
auto-linefeeds are less likely to have trouble, but even so, this can be a
considerable nuisance.
There is a further snag with using VDU2,21 , and that is that if a 6 should
appear in the VDU codes, then the VDU drivers are turned back on again too
early, nasty things will happen on the screen, and the whole thing will
probably seize up. The safe solution is to use VDU2 and VDU3 as normal, and
precede each byte by 1; eg VDU1,27,1,45,1,1 , even though it is rather
tedious. What would be nice would be to tell the Beeb to send all characters
to the printer, but unfortunately, *FX6,- does not allow this to be done.
101. Second processor hints
When you are using the 6502 2nd processor, in BASIC or with View, Wordwise
etc., you can safely use the disc commands *BACKUP, *COMPACT and *COPY
without overwriting a file in memory. This is because the DFS uses the Beeb
RAM for these operations, whereas your file is safely tucked away out of
reach in the 2nd processor's RAM.
102. Speech procedure
For those of you with an Acorn Speech system, here is a procedure to
conveniently call up speech, without using a clumsy string of SOUND
statements or DATA lists. Note that the word numbers must be passed as one
long string, with separating commas if necessary. Actually, you can use this
technique whenever you wish to pass varying length lists of parameters, to a
procedure or function. You would simply use num% for something else other
than SOUND in line 1030.
100 PROCspeak("241,246,252"):REPEATUNTILGET=13:REM Now press <Return>
110 PROCspeak("265,275,128,266,209,230,211"):END
120 :
1000 DEFPROCspeak(data$):LOCALcom%,num%:REPEAT:com%=INSTR(data$,",")
1020 num%=VAL(LEFT$(data$,com%-1)):data$=RIGHT$(data$,LEN(data$)-com%)
1030 SOUND-1,num%,0,0:UNTILcom%=0:ENDPROC
103. Super-fast relocate
We published a very simple and effective relocate for disc users back in
September 1983. This was added to your Basic program, and automatically moved
it down to a lower value of PAGE. For those who don't know, the Beeb DFS
'pinches' some user memory as workspace for itself, and these relocate
programs are to claim it back again after the program is loaded. This
overcomes the problem of some long programs only running on Cassette-based
Beebs.
The only drawback is that the published relocate is a trifle slow, and can
take up to 5 seconds on very long programs. My new routine below uses
machine-code for the critical section, with a bit of Basic for economy of
programming. It can relocate a 25k program in less than 0.4 seconds, which is
fast enough for anyone! It is written in the form of a dummy Procedure, which
tacks onto the end of your program, and is called by line 0. The line numbers
used have been chosen so as not to clash with line numbers in your own
program. Your program can start anywhere after line 0, and must finish before
line 32000. Be sure to add an END to stop the program running into the
Procedure by accident. A convenient way to add this routine is to *SPOOL it
off onto disc, and then *EXEC it back in again to merge with your own
program. Those of you with utilities like *MERGE will find life made even
easier. This routine automatically switches the DFS off if you try to
relocate below &1100, which is the lowest value of PAGE where limited use of
the DFS is possible. You simply set the variable D% in line 0 to the address
you want PAGE resetting to; &E00 in this example.
Please note that the Procedure is a dummy one, and is terminated with END,
rather than ENDPROC. This is quite deliberate, so don't change it back again.
The routine uses integer variables D%, (for Destination), and P%, (for
Program counter). If you want to avoid using D% for any reason, then change
it to a different resident integer variable. You cannot substitute for P% in
this way, but it is quite OK to use it in your own program as well, without
any clash. Some workspace on Zero Page is used, from &70 up to &8C, as this
area isn't used by Basic, and is in any case freed again as soon as the
program has been relocated.
There are no spaces within the listing, and you can omit the ones
immediately after the line numbers. To those of you not familiar with
machine-code, this must look very weird indeed, but just type it in very
carefully, exactly as it is, but note that the two blank lines with colons
are only to make the listing more clear. If you want to relocate a program
which has data or machine code stored in memory locations above TOP, then you
can substitute the length of the whole file in place of TOP-PAGE on line
32010; eg. &4B53+256. This Hex number can be found by using *INFO on the
file, after you have added this routine. (Put any 4-digit Hex number in at
first, just to simulate the true length.)
0 D%=&E00:IFPAGE>D%THENPROCmove
10 :
20 REM Your program goes somewhere about here.
5000 END:REM Most important.
5010 :
32000 DEFPROCmove:IFD%<&1100THEN*TAPE
32010 !&70=D%:!&72=PAGE:!&74=TOP-PAGE+256
32020 P%=&76:[OPT2:LDX&74:LDY#0
32030 LDA(&72),Y:STA(&70),Y:INY:BNE&85:INC&71:INC&73
32040 DEX:BNE&7A:DEC&75:BNE&7A:RTS:]
32050 VDU21:*KEY9CALL&76|MPAGE=D%|MNEW|MOLD|MRUN|F|M
32060 *FX138,0,137
32070 END
104. Controlling shift/caps lock in a program
It can sometimes be useful to control the Shift or Caps Lock from within a
program, to ensure that the machine is set correctly for the next INPUT or
GET statement. This can be done with the command *FX202,n, where n is as
follows:-
16 - Shift Lock On 144 - Reverse Shift Lock On
32 - Caps Lock On 160 - Reverse Caps Lock On
48 - Both Locks Off
105. GOTO/GOSUB line tokens
If you examine the structure of a BASIC program listing in memory, you will
see that the line numbers are stored as two bytes; low followed by high. The
low byte is given by linenumber MOD 256, and the high byte is given by
linenumber DIV 256. However, the line numbers following a GOSUB, GOTO, or
implied GOTO, (ie IF A=5 THEN 550), are tokenised in a weird way. They are
stored as 4 bytes; the first byte always being &8D to indicate that a line
number follows in the next three bytes, which I shall call b1, b2 and b3.
To decode this, you must shift b1 up 2 bits, (the same as multiplying by 4 in
BASIC, or doing two ASL's in machine code), mask off the bottom 6 bits, (same
as ANDing it with &C0), then EOR it with b2, and this gives you the low byte
of the line number. Now shift the original b1 up 4 bits, mask off the bottom
6 bits, and EOR it with b3, which gives you the high byte.
Try running the program below, from line 200, (ie type GOTO200 rather than
RUN), enter A4,68,43 (separate with commas; no need to prefix with '&'), and
you should get "line 1000". Note how the Hex numbers are entered as strings,
and turned into numeric variables with EVAL; you can't do it directly.
Encoding the line numbers is a bit more hairy; the first part of the program
below demonstrates this, and you can enter the results into the second part,
to confirm that the encoding works OK.
100 REM Encode tokenised line numbers.
110 INPUT"Enter Decimal Line No.... "line%
120 lobyt%=line%MOD256:hibyt%=line%DIV256
130 b2%=&40+(lobyt%AND&3F):b3%=&40+(hibyt%AND&3F)
140 lobyt%=(lobyt%AND&C0)DIV4:b1%=(&80+lobyt%)EOR&10
150 hibyt%=(hibyt%AND&C0)DIV16:b1%=(b1%+hibyt%)EOR4
160 PRINT~&8D,~b1%,~b2%,~b3%
170 :
200 REM Decode tokenised line numbers.
210 INPUT"Enter three Hex bytes.... 8D,"b1$,b2$,b3$
220 b1%=EVAL("&"+b1$):b2%=EVAL("&"+b2$):b3%=EVAL("&"+b3$)
230 lobyt%=((b1%*4)AND&C0)EORb2%:hibyt%=((b1%*16)AND&C0)EORb3%
240 PRINT"Line Number = ";hibyt%*256+lobyt%
106. Pretty VDU7 bell
If you are tired of the boring VDU7 bleep, and fancy something more
interesting, then Andrew G8YHI has the answer. The following commands
redefine the bleep as a nice typewriter-style "Ting"! The effect is cancelled
on <BREAK>, although you only need to execute the *FX calls again to restore
it, as the envelope parameters are not lost. Once you've RUN the program, you
can type NEW or whatever, as it isn't needed any more. You could, of course,
simply tack it onto your own program as a Procedure.
10 ENVELOPE1,1,0,0,0,0,0,0,127,-4,-2,-1,126,90
20 *FX212,0
30 *FX213,170
107. Key-pressed bleep
This is a routine passed on by Andrew G8YHI, and causes a short bleep every
time a key is pressed, rather like a supermarket till. It works by
intercepting the current input stream vector, (the current input being
keyboard). You'll either love or hate it!
10 A%=!&210 AND &FFFF:*FX213,200
20 *FX214,1
30 P%=&D50:[OPT2:PHA:LDA#7:JSR&FFEE:PLA:JMP A%:]
40 *KEY10 ?&210=&50:?&211=&D|M*FX213,200|M*FX214,1|M|LNEW|M
50 *FX138,0,138
108. Wordwise pad character snag
You cannot normally program the character "|" to appear on a red
user-definable key. The "|" is taken to stand for <CTRL>, so "|L" is
interpreted as <Ctrl+L>, which is ASCII code 12 decimal and clears the
screen. What you cannot do is program the keys to actually hold "|" as a
separate printable character. This can be a bit of a nuisance on Wordwise,
where you might want to hold a useful document heading on a red key, (or on
the cursor and <Copy> keys), and the "|" is needed as the default pad
character to make sure a centred heading comes out correctly. You could get
round this in several ways. First, you could redefine the pad character at
the beginning of the document or key definition, and I often use the
backslash "\", which looks like "1/2" in mode 7. Ie, you could put pc\,
(pc"\" on Wordwise Plus), and then use "\" as the pad character from then on.
Alternatively, you could use something like "\" on your red keys, but before
you print or save the document, use Search-and-Replace to change the "\"s to"|"s. Finally, as a more permanent solution, you can define the keys(s) using"\" as the temporary pad character. When you've finished, use Disc Doctor or
ADT etc. to edit the memory to change the temporary character to "|", using
*MZAP B00 (or MEDIT B00 or whatever command is appropriate), and then save the
definitions with *SAVE Keys B00 C00. You can reload the keys at any time with
*LOAD Keys, including from the Wordwise menu, or in your disc !BOOT file. If
you haven't got Disc Doctor etc., then you can achieve the same effect with
the routine below, which can be typed in direct mode if you wish, rather than
RUN as a program.
NB: If you have a 6502 2nd Processor, then edit and save your key definitions
with the Processor switched off, and put leading "F"s on the Hex addresses so
that you can successfully reload them when the 2nd Processor is in use. ie.
*SAVE Keys FFFF0B00 FFFF0C00.
FOR m%=&B00 TO &BFF:IF ?m%=ASC("\") THEN ?m%=ASC("|"):NEXT ELSE NEXT
Addendum
~~~~~~~~
The above dealt with the problem of not being able to directly program the"|" character, (which looks like two vertical parallel bars in Mode 7), onto
the red keys. Normally the "|" is used to represent "Ctrl", so "|M" is
equivalent to Ctrl-M, ie a CR.
Dave G7FHJ has pointed out there is a very simple way round this, which I
was blissfully unaware of back in 1985! All you have to do is double-up on
the character. Eg if you wanted a red key to produce the actual characters"|M" instead of a CR, then try using "||M" instead.
109. Disabling ROMS
There are times when it is useful to suppress a resident ROM temporarily,
even if <BREAK> or <CTRL+BREAK> is pressed. You can do this by Poking the
ROM private workspace table with 64, ie setting bit 6. Eg., if your DFS ROM
is in socket 3, then you can kill it by typing ?&DF3=64, and then pressing
<BREAK>. If you want to kill the ROM in socket 5, then use ?&DF5, and in
socket 15, (&F), you use ?&DFF.
To enable the ROM again, either switch off for a few seconds, or else Poke
the original value back. For example, if PRINT ?&DF3 <RETURN> normally gives
151, then replacing 64 with this original value will restore the ROM after a
<BREAK>. Many thanks to Nick Davison of Calverley, Leeds, for this
information.
110. Slowing down programs
Brian Smith points out that if you type ?&FE45=1:?&FE46=0 then all subsequent
programs will run super-slow. You can try this out most easily by loading in
program, typing in the slowing-down command, and then typing LIST. To
restore normality, do the same again but with the original values in place of
1 and 0. (Obviously, you will have to find them out with PRINT?&FE45,?&FE46
before you start.)
On my Beeb they are both 14, but I think it depends on what options are
fitted. I'm not sure exactly how this works, but you are messing about with
the internal 6522 VIA timer registers. This evidently fools the computer into
spending too much time looking for interrupts, and not enough time getting on
with processing.
111. Tube indicator
This short Function will return TRUE if a 6502 2nd processor is active, and
FALSE if it is not. It is a useful way of either warning the user to switch
the processor off, or of making other decisions within the program. Note that
X% is effectively set to zero simply by being made LOCAL; do not omit it,
even though it apparently does nothing.
10 IF FNtube=TRUE THEN PRINT "2nd Processor is active"
20 END
1000 DEFFNtube:LOCAL A%,X%,Y%
1010 A%=&EA:Y%=&FF:IF USR(&FFF4)AND&FF00 THEN =TRUE ELSE =FALSE
112. Use for EVAL
People often get confused between VAL and EVAL on the Beeb. VAL simply tries
to treat a string as a number, so PRINT VAL("4*3+1") would give the answer 4.
The asterisk is a non-numeric character, so it and anything after it are
ignored. However, EVAL goes a step further, by attempting to evaluate the
string as a valid numeric expression, and would give the answer 13. It is
therefore possible to write a program which accepts an equation as a string,
thus opening up some interesting possibilities. Anyway, here is a more
down-to-earth use for EVAL, for which I claim no originality. If you think
about it, there isn't any obvious way to INPUT a number in Hex format; only
in Decimal. You can overcome this with the technique below.
10 INPUT"Hex number :&" A$:A=EVAL("&"+A$)
You can also use this technique in conjunction with READ and DATA to enable
you to put Hex numbers in data statements, without bothering with the
ampersands, eg DATA 5B,3C,20,FF instead of DATA &5B,&3C,&20,&FF etc.
113. Altering the RS423 format
If you are experimenting with the RS423 serial port, and need to alter the
data format, then you can do so with the command *FX156,X,227 . The value of
X can be looked up in the table below, where X is 4*n. The default value on
the Beeb is n=5, corresponding to *FX156,20,227 .
DATA BITS PARITY STOP BITS n X
--------- ------ --------- - --
7 even 2 0 0
7 odd 2 1 4
7 even 1 2 8
7 odd 1 3 12
8 none 2 4 16
8 none 1 5 20
8 even 1 6 24
8 odd 1 7 28
You can read the current value of n using the following function. If you want
to read the value of X rather than of n, then change the &400 in line 1020 to&100. Note the comment in tip #111 about X% being LOCAL.
1000 DEF FNstatus:LOCAL A%,X%,Y%
1010 A%=156:Y%=255
1020 =(USR(&FFF4) AND &1C00) DIV &400
114. Another relocate program
Earlier, I gave a Procedure for tacking onto the end of a Basic program, so
that long programs could be run off disc, with a PAGE value down to &E00.
This works fine, but there are times when this is not convenient. If you are
adapting a very long and complex program from cassette to disc, it may not be
safe to go tacking procedures on the end. This is especially true if there is
data after the visible Basic part of the program, as any additions are likely
to overwrite it. A typical example would be a text adventure game like Castle
of Riddles, which is 65 blocks long, over half of which is data. This is too
long to even LOAD into memory with PAGE set at &1900.
The solution is to make the program a 2-part one, with the relocate routine
in the 1st half, thus avoiding any need to tamper with the main program. If
the program is short enough to run with PAGE at &1100, then the 1st program
need consist only of one line, ie 10 PAGE=&1100:CHAIN "Dragon2" . If the
program must run with PAGE lower than that, eg &E00, then the program below
will do the trick. It is so fast that it doesn't bother to work out the
length of the program, (tricky if you have to allow for any hidden data), but
simply relocates all available memory in 1/3 second. In line 10 you specify
the new value of PAGE, eg &E00, and the name of the main program. You could
of course replace the final term with an INPUT N$ statement, in which case
the one relocator will run any named program. PAGE is initially set to &1100
in line 10, in case the main program is too long to even LOAD with PAGE at &1900. This doesn't affect the relocator itself, which churns on merrily,
blissfully unaware that PAGE has been altered, but it does define where the
main program will LOAD. In many cases, this 1st term in line 10 can be
omitted, but it doesn't do any harm to leave it in, (with the Acorn 8271
DFS's at any rate).
The program may already have a first part, which just sets up some of the
character shapes, and displays a logo on the screen. You could easily add
this routine in place of the CHAIN "Dragon2" type of command, followed by END
if necessary. Ignore any corruption of the logo; if you're clever enough,
you'll know how to preserve it!
This program looks rather weird, and it can be hard to spot mistakes. Try
missing out the VDU21 in line 60 at first, otherwise useful error messages
are suppressed.
10 PAGE=&1100:D%=&E00:N$="Dragon2"
20 !&70=D%:!&72=PAGE:!&74=HIMEM-PAGE
30 P%=&76:[OPT2:LDX&74:LDY#0
40 LDA(&72),Y:STA(&70),Y:INY:BNE&85:INC&71:INC&73
50 DEX:BNE&7A:DEC&75:BNE&7A:RTS:]
60 VDU21:*KEY9LOADN$|M*TAPE|MCALL&76|MPAGE=D%|MNEW|MOLD|MRUN|F|M
70 *FX138,0,137
115. Saving Files
If you are using a program which saves files onto disc, (sequential files
that is, not random-access ones), then you can come up against a snag. If the
file is 'sandwiched' in between other files on the disc, and you attempt to
save an amended version of that file under the same name, then you may run
into trouble if the new version is longer than the old. You can get the error
message "Can't extend", which means that the new version won't fit in the
space available.
If this happens, and you are able to enter "*" commands without quitting the
program, then *DELETE the file on the disc, and then save the new version
again. This time, the file will not be put back in the same place, but will
be put after all the other files on the disc. If there isn't room there
either, then you will get the message "Can't extend", or much more likely,"Disc full". If this is the case, then you will have no option but to save
your file on a separate disc, and *COPY it back onto the original after
using *COMPACT.
Note that you do not get "Can't extend" errors with Wordwise-Plus, which in
effect uses *SAVE rather than OPENOUT, but I seem to remember that you can
get it with some if not all versions of Wordwise.
116. Comparing disc files (B/B+/Master)
It is useful if you can compare different files to see if any of them are the
same. I often seem to end up with different versions of a program or file on
different discs, but under the same filename. At other times, I find the
exact same program saved under two different names. It can help to use *INFO,
but this will only tell you whether or not the files are of the same length.
This short program will compare any two named files, whether BASIC,
machine-code, text files etc., and check that they are of the same length,
and that they are byte-for-byte identical. The first filename prompt will
repeat until a valid filename is found on the appropriate disc, and then the
second filename prompt is repeated until a valid but different filename is
found. Obviously, the two filenames must be different, and they can be
different in actual name, directory, or in drive. If you have two drives,
then the two names might be "FRED" and ":1.FRED". If the two files are both
on the same disc, then the names might be "FRED" and "A.FRED", or "FRED" and"FRED1", or "FRED" and "JOE". If a filename prompt keeps reappearing after
you type a name in, then either that filename cannot be found on the disc,
or else you are are typing in two identical filenames. The routine is
compatible with the 6502 2nd processor.
The length of the file is displayed in Hex after each filename is entered. If
the two files are not of the same length, then the program only takes a few
seconds to run, otherwise it may take quite a bit longer if the files are
large ones, and if any differences are not found until near the end of the
files, if at all. Many of the spaces in the listing, but by no means all, can
be omitted. If in doubt, type them all in at first. Note that there is a
tilde in lines 130 and 160, looking like "~", and this is easily overlooked.
100 CLOSE#0:same=FALSE:ON ERROR GOTO 230
110 REPEAT:INPUT "1st Filename : " file1$
120 ch1=OPENUP(file1$):UNTIL ch1>0
130 PRINT TAB(6) "Length : &";~EXT#ch1
140 REPEAT:INPUT "2nd Filename : " file2$
150 ch2=OPENUP(file2$):UNTIL ch2>0
160 PRINT TAB(6) "Length : &";~EXT#ch2
170 IF EXT#ch1<>EXT#ch2 THEN 200
180 REPEAT UNTIL BGET#ch1<>BGET#ch2 OR EOF#ch1
190 IF EOF#ch1 THEN same=TRUE
200 PRINT "These files are ";
210 IF same THEN PRINT "identical" ELSE PRINT "different"
220 PRINT:CLOSE#0:END
230 IF ERR=194 THEN 140 ELSE CLOSE#0:REPORT:PRINT " at line ";ERL
NB: I have also written a version for BASIC programs only, which actually
checks line-by-line, and tells you the line number(s) where the first
difference is found. The difference may be in the contents of the line, or
the actual line numbers themselves. It is too long to print here, but is
available as two UUcode files entitled "BASIC COMPARE UTILITY"
117. Comparing programs with memory
This is a routine along the same lines as the previous one, but is for
comparing a purely BASIC program in memory with a named program on disc. (It
does not work with cassette.) BASIC in this context also included programs
containing assembler code.
Since it is for comparing a program in memory with one on disc, the routine
cannot conveniently be in the the form of a program itself. So, it is stored
on a red function key ready for calling at any time. Before programming the
key, (I have used *KEY0 in this example), you should type *FX18 to clear all
the keys, as the routine takes up most of the available space on a B/B+. The
key definition can be saved on a B/B+ with *SAVE name FFFF0B00+100, and
reloaded at any time with *LOAD name . On a Master/Compact, save the
definition as a one-line program, and simply CHAIN it to redefine the key
when required. The routine is compatible with the 6502 2nd processor.
When called, the routine first prints out the length of the program in
memory, and then prompts for a filename. This will repeat until a valid
filename is found, and then the length of the disc file is also printed
before a byte-for-byte check is carried out. There is a similar routine in
BEEBUG, but it doesn't check for different lengths before laboriously
comparing byte-for-byte, and with BASIC-I it is liable to try and lengthen
the file if it is shorter than the program in memory!
Note that in order to squeeze everything on to one key definition, I have
had to use many abbreviations, and only vital spaces have been retained. I
have split the lines at convenient colons, but the definition is actually
typed in as one continuous line. It may help to omit the first term VDU21|M
initially, otherwise it tends to suppress any syntax error messages if you
make a typing mistake. When the routine is debugged, you can restore the
first term to give a neater effect on the screen.
*K.0VDU21|MCLO.#0:P." Length : &";~TOP-PA.:REP.I."Filename : "f$:
ch=OP.f$:U.ch:P." Length : &";~EXT#ch:M%=-1:
REP.M%=M%+1:U.EXT#ch=TOP-PA. ORBGET#ch=M%?PA. OR EOF#ch:
IF EOF#ch TH.P."Identical"ELSEP."Different":CLO.#0|F|M
118. !BOOT file hint
Editing a !BOOT or other file which is to be *EXECed is rather tedious. If
you want to alter it, you have to retype the lot, or else *TYPE or *LIST the
old version, and then use the <Copy> and cursor keys. It is much easier to
simply load it into WORDWISE or VIEW, edit it as required, and then save it
in the normal way. Do not insert any embedded codes, and do not attempt to
add the line numbers which *BUILD gives you. If you load an existing !BOOT
file first, you will see how simple the format is. With Wordwise, leave one
blank line under the last command, but do not with VIEW, or you will get an
extra carriage return which may cause problems.
119. *RUN hint
You may abbreviate the command *RUN to just */ , saving two bytes of memory
in the process. For example, with a DFS fitted, the command *FORM40 would
attempt to *RUN a program called FORM40 off disc. However, in all
probability, a utility ROM such as Disc Doctor, or maybe even the DFS itself,
may assume you are attempting to use the resident FORMat facility with the
wrong syntax. However, using the command */FORM40 instead would ensure that
this doesn't happen.
120. *EXEC file nesting
You cannot 'nest' *EXEC files. You can have an *EXEC file calling another,
which in turn may call another, but you can never return. Ie if an *EXEC file
*EXECs another, then it must be in the final statement.
121. Merging BASIC programs
There is no single command which will merge a program on tape or disc with
one in memory. This is a shame, as it is useful to be able to tack Procedures
from a 'library' onto new programs being written. Some utility ROMs such as
Beebug Toolkit incorporate a merge facility, but there are ways round the
problem.
Method 1 is considered 'dirty' by the purists, but is very effective.
Assuming that the main program is in memory, and that the Procedure or
routine which you wish to add is on tape or disc, under the filename "fname".
Type PRINT~TOP-2 , and note the 3 or 4 digit Hex number which is printed; I
shall represent this as 'nnnn'. Now type *LOAD fname nnnn , followed by OLD ,
(vital), and the merge is complete.
This method adds the Procedure onto the end of the program, regardless of the
line numbers. For example, your program may use lines 100-2500, and your
Procedure may appear as lines 1000-1050 after line 2500. This looks weird,
but can be cured simply by RENUMBERing the program.
This oddity is actually very useful, because you don't have to worry about
the line numbers in the Procedure clashing with those in the main program
but if you don't want to renumber the program, then try method 2.
Method 2 is more tedious, but may be better on some occasions. First, load
your Procedure or routine into memory. It is a good idea to renumber it at
this stage, so that the line numbers will not clash with those in the main
program. Now save it as a straight ASCII file, ie character-by-character
rather than in compressed BASIC keyword token form.
TYPE *SPOOL fname followed by LIST . When the listing stops, type *SPOOL on
its own to close the file. If you are saving only one part of a longer
program, then type LIST 1000,1050 etc instead of just LIST .
Now load your main program into memory and add the Procedure with *EXEC name.
You will actually see the lines being added on the screen, together with a
couple of "Syntax error" messages, which you may ignore. The lines are being
added as if typed very quickly on the keyboard, so any common line numbers
will be overwritten and the new lines will appear in the correct order.
There is no need to subsequently renumber the program, unless you
particularly want to. You can keep a library of these Procedures already in
ASCII format, so you don't need to use *SPOOL every time. You can then just
*EXEC them into your programs as required, which is fairly convenient. You
could store them, each with a different set of lines numbers, but this would
be hard to keep track of. Alternatively, store them all with high line
numbers, say 30000 upwards and every time you add one to a program, renumber
the program so that the highest line number becomes relatively low. In that
case, you may find method-1 more suitable.
122. REM alternative
The characters "*|" have the same effect as a REM statement, and can
conveniently be incorporated in *EXEC files etc.
Eg. *| This is my !BOOT file
123. VDU code reminder
You may not be aware that VDU codes may be used in place of some PRINT
statements. For example, the term VDU(n) is directly equivalent to the term
PRINT CHR$(n); . Note that the brackets are optional in both cases and that
there is a semicolon after the latter term. Also, VDU31,x,y is directly
equivalent to PRINT TAB(x,y);
Thus, the two statements below are directly equivalent, but the second one is
shorter and tidier. This will not necessarily save much memory space as the
second line is only one byte shorter than the first but even if you don't
save any memory space, a shorter listing is an advantage in itself.
10 PRINTTAB(10,12)CHR$136;CHR$131;:INPUT"Name ? "N$
10 VDU31,10,12,136,131:INPUT"Name ? "N$
124. VDU oddities
VDU19, which chooses foreground and background colours from the palette, is
equivalent to pressing <Ctrl+S> . I shall represent it by |S, since this is
how you would store it on a red key.
To select a foreground colour of Green in Mode 0, you could use
VDU19,1,2,0,0,0 or press |S followed by the keys 1 2 0 0 0 in turn.
To send a zero byte in this way properly involves pressing |@. By pressing
the 0 key directly, you are actually sending ASCII code 48. Thus you have
sent the equivalent of VDU19,49,50,48,48,48 and in fact it does work
perfectly as a VDU command; try it and see! You can do it 'properly' by
pressing |S |A |B |@ |@ |@
I'm not quite sure what practical use you can put this new-found knowledge
to, but there it is for what it's worth!
125. DIM oddity
If you have already dimensioned a numeric or string array in a program, such
as A$(100), FRED(55) or mem%(300), then any attempt to redimension it will
result in the error message "Bad DIM". In some versions of BASIC, though
sadly not BBC BASIC, you can legally redimension an array, or reclaim the
memory it occupies, provided you 'kill' it first, eg KILL A$ , ERASE A$ etc,
(the syntax varies).
However, if you dimension an area of memory with the syntax DIM mem% 100 , as
one might do if reserving memory for some data or machine code, then it can
be redimensioned without killing it first, and without generating any error
message. If this sounds too good to be true, then you're dead right!
Every time you redimension the area, even if you are reserving the same or
less space than before, the old area is 'thrown away', and new space
reserved. If you don't do this too often, then it may be useful to you, but
try the short program below and see how it rapidly gobbles up all the memory.
This applies equally to all versions of BBC BASIC that I have come across.
10 REPEAT:DIM A% 50:UNTIL FALSE
20 END
126. Alphabetic comparison
ALPHABETIC COMPARISON. Most of you will be familiar with the use of the < and > operators to compare numbers, but not everyone may be aware that it
can be used on strings, thus forming the basis of an alphabetic sort. It is
quite legitimate to use an expression like IF A$>B$ THEN GOTO 240
This can be used to compare "SMITH" with "BROWN", and it will decide that"BROWN" is less than "SMITH", because it comes sooner in alphabetical order.
Lower case comes after upper, so "SMITH" is less than "Smith" for example.
In other words, the comparison is made in ASCII code order. This does mean
that when you compare numbers in the form of strings, you get odd results if
they do not both contain the same number of digits in front of the decimal
point. For example "12" is less than "3" because it starts with a "1" rather
than a "3", but "03" will correctly be found to be less than "12".
Similarly, ".2" will be less than "0.1", because a fullstop comes before "0" in ASCII code order, but "0.2" rather than ".2" will be compared correctly.
127. ON-ERROR tip
An ON-ERROR statement can take several forms other than just simply ON ERROR
GOTO . Here are a few ideas:
10 ON ERROR GOTO 140
10 ON ERROR RUN (or END or STOP)
10 ON ERROR PROCboob:GOTO 550
10 ON ERROR IF ERR=17 THEN 140 ELSE REPORT:PRINT" at line ";ERL:END
128. Date compression
When large numbers of dates need to be stored in a database, file space can
very quickly be used up unless some economies are made. The first Function
below accepts a date as its input, in the form of a six-character string, (eg
230286 for 23rd Feb 1986), checks that the date is valid, and compresses it
to an integer. The Function returns the value zero (or FALSE) if an
impossible date is entered, (eg 310985 or 290286), and this should be tested
by the program.
If the date is OK the resulting integer can be stored in just two bytes, (it
ranges from 33 to 51103), and can easily be sorted chronologically. (NB This
routine does not do this conversion for you.) The date as a string needs six
bytes, and would not sort properly unless it had been entered backwards! (eg
860225.) The second Function converts the stored integer back to a
six-character string.
1000 DEFFNdate_to_number(Z$):LOCAL D%,M%,Y%,N%
1010 IF LEN(Z$)<>6 THEN=FALSE
1020 D%=VAL(LEFT$(Z$,2)):M%=VAL(MID$(Z$,3,2)):Y%=VAL(RIGHT$(Z$,2))
1030 IF M%>12 OR M%<1 THEN=FALSE
1040 N%=30-(M%<8)*(M%MOD2)-(M%>7)*((M%+1)MOD2)
1050 IF M%=2 THEN N%=28-(Y%MOD4=0)
1060 IF D%<1 OR D%>N% THEN=FALSE ELSE=D%+32*M%+512*Y%
1070 :
2000 DEF FNnumber_to_date(Z%):LOCAL D%,M%,Y%
2010 D%=Z%MOD32:Z%=Z%DIV32:M%=Z%MOD16:Y%=Z%DIV16:Z%=D%*10000+M%*100+Y%
2020 =RIGHT$("0"+STR$(Z%),6)
129. Number compression
Further to tip 128, here is a way of storing that compressed date as a 2-byte
integer. You must dimension some memory space twice the size of the number of
dates to be stored. In the example below, I have assumed that 1000 dates are
to be stored.
The first Procedure places the already compressed date Z% in position N% out
of the list of 1000. Eg PROCstore(44119,500) actually places 23rd Feb 1986 in
position 500 out of 1000. To read a stored date, the Function will return the
compressed date stored at position N%. Eg PRINT FNfind(450) will print the
compressed date stored in position 450 out of 1000. You can then use the
second Function to turn it into a sensible date string. Using these Functions
and Procedures as building blocks, you can incorporate them into your own
programs.
100 DIM array% 2000
200 REM Program somewhere here.
3000 DEFPROCstore(Z%,N%)
3010 array%?(N%*2-1)=Z%:array%?(N%*2)=Z%DIV256:ENDPROC
3020 :
4000 DEFFNfind(N%):=array%?(N%*2-1)+(array%?(N%*2))*256
130. Coloured text and backgrounds
Changing colours using BASIC is a simple operation; the statement
VDU19,1,2,0,0,0 will change the text colour to green in all modes except Mode
7. The same effect can be achieved by holding down the <CTRL> key and typing
S12000 . When using VIEW the VDU command is not available, although the
<CTRL> sequence will work. Neither of these methods will work in THE Watford
Electronics Disc Sector Editor, for example; the only way to change colours
here is by the *FX155,X operating system command which is rather complex.
*FX155,X writes to register 1 (palette) of the video ULA, but in two-colour
modes the command must be used 8 times with different values of X, just to
change the text colour, and a further 8 times to change the background
colour. (See The Advanced User Guide sections 19 and 22.)
The program below calculates the values of X for each foreground and
background colour and transfers them onto disc as files. Before running the
program make sure there is space for 16 small files on the disc; 8 files will
be named as in the DATA statement in line 30, and 8 with the same names
prefixed with the letter B. You can then delete any files that you feel you
will not need. When using VIEW for example, entering *EXEC BLUE followed by
*EXEC WHITEB will give blue text on a white background.
If you are NOT using the old BASIC-I on a BBC B, you can omit lines 500-530
and replace the PROCoscli in lines 40 and 80 with the keyword OSCLI .
10 DIM colour$(7)
20 FORI%=0 TO 7: READ colour$(I%): NEXT
30 DATA BLACK,RED,GREEN,YELLOW,BLUE,PURPLE,CYAN,WHITE
40 FORI%=0 TO 7: PROCoscli("SPOOL "+colour$(I%))
50 FORJ%=8 TO 15: PRINT"*FX155,";16*J%+I%: NEXTJ%
60 *SPOOL
70 NEXT
80 FORI%=0 TO 7: PROCoscli("SPOOL "+colour$(I%)+"B")
90 FORJ%=0 TO 7: PRINT"*FX155,";16*J%+I%: NEXTJ%
100 *SPOOL
110 NEXT
120 END
500 DEFPROCoscli(Z$)
510 $&C00=Z$
520 X%=0:Y%=&C:CALL&FFF7
530 ENDPROC
131. Stripey background hint
Modes 3 and 6 are text-only modes, with 25 rather than 32 lines per screen.
This is achieved by leaving gaps between the lines, and is clearly
illustrated by VDU19,0,4,0;0;0; which sets a coloured background. This gives
a stripey appearance, which can be used to good effect. However, you are
stuck with the black gaps between lines, and any user-defined characters on
adjacent lines will never join up. In the case of Mode 3, you may as well use
Mode 0 instead, as they both occupy 20k of memory. However, Mode 6 takes up
8k as against the 10k of Mode 4, so it might be better on some occasions,
unless you have Shadow RAM.
A clever chap called Cad Delworth, writing to Acorn User, has found that you
can close up the gaps completely with VDU23,0,9,7,0;0;0; and to prevent any
tendency for the picture to 'roll', you should follow this with
VDU23,0,5,8,0;0;0; On the Master/Compact, these can be shortened to
VDU23,0,9,7|23,0,5,8| The resulting screen has bigger margins at the top and
bottom than normal, but this may be a small price to pay for being able to
use a Mode which needs 2k less memory.
132. SPEECH! hint
The Superior Software SPEECH! software has two main commands, *SAY and
*SPEAK. The former tries to pronounce the words phonetically, whereas the
latter enables you to manipulate more subtly the pronunciation and pitch by
building up words from 'phonemes'.
You may be very interested to know that when you use *SAY, the program
translates this into *SPEAK format, and stores it in the cassette input
buffer at memory location &A00. Thus, if you type *SAY HELLO FRED and then
type PRINT $&A00 you will see "/HEHLOW FREHD". Now try *SPEAK /HEHLOW FREHD
to prove the point. Similarly, *SAY MASTER 128 gives the result "MAA6STER
WO5NTUH4WAY5T". This should help you in making up your own words, by seeing
how the computer makes up similar ones.
133. ROM/RAM board 'fix'
Ever had problems with wobbly expansion boards, and that sort of thing? The
effective low-technology solution is to apply a bit of the magic BLU-TACK in
strategic places. With a Solidisk RAM board, try using it to stick the rear
end to the UHF modulator can. It's so simple it's brilliant!
134. Writing 'legal' programs
Now that the BBC Micro 'family' includes the Model B, the B+, Master and the
new Compact, it is all the more important to use 'legal' programming
techniques, in order to reduce compatibility problems.
PS: There is now the Archimedes in the family of course!
135. Wordwise cursor hint
When printing or previewing with Wordwise or Wordwise-Plus, odd things
sometimes happen if the cursor is not 'homed' to the start of the text first.
I don't know if this has been cured on later versions.
136. Wordwise margin tips
This applies equally to Wordwise-Plus, of course. When mixing different
character sizes on a printer, you have a problem. You must decide on the
necessary Line Length and Left Margin settings in order to achieve
approximately the same apparent left and right margins. Here, therefore, is a
list of the Line Lengths and Left Margin settings I use for each character
size. I have an Epson-compatible printer, but I imagine most dot matrix
printers will be much the same in this respect. You cannot do condensed
enlarged text to match these margins, but you should be able to manage it
with condensed Elite on an Epson LX80.
SIZE STYLE COLUMNS SETTINGS
Enlarged Pica/NLQ 40 LL36 LM2
Standard Pica/NLQ 80 LL72 LM4
Standard Elite 96 LL86 LM5
Condensed Pica 132 LL123 LM7
Further to this, when changing from one character size to another, I find it
best to issue the printer command first, (terminated in a White code), and
then change the Line Length etc on the next line. It doesn't matter if you
start your text on the same line as the Line Length command, but if the
printer command is on the same line, or if it is on the previous line but not
terminated in a White code, then the first line of new text tends to have the
wrong left margin.
Below are five examples of changing to Elite text using ordinary Wordwise
commands, (if you have Wordwise-Plus then OC27,77 becomes ES"M"). The first
three tend to give odd results, but the last two are OK. In both of these,
the printer command is not on the same line as the start of the text, and the
line that it is on is properly terminated in a White code. I usually use the
last method, but everyone to their own.
This demonstrates the point that if you don't at first get the result you
expect from Wordwise, then try a slightly different way. Certainly, I find
that mixing printer codes which change character size, with text on the same
line, is almost guaranteed to cause trouble. This doesn't apply to commands
for emphasized, double-strike, italic etc, nor to most of the other embedded
commands.
WRONG: {G}OC27,77{G}LL86{G}LM5{W}This is your text.
WRONG: {G}OC27,77{G}LL86{G}LM5
This is your text.
WRONG: {G}OC27,77
{G}LL86{G}LM5{W}This is your text.
RIGHT: {G}OC27,77{G}LL86{G}LM5{W}
This is your text.
RIGHT: {G}OC27,77{W}
{G}LL86{G}LM5{W}This is your text.
137. Wordwise-plus line tip
A very simple way of drawing a straight, unbroken horizontal line across the
paper is to use the commands {G}us{G}fi{G}ue{W}, where the {G} and the {W}
represent the Green and White embedded codes respectively. The line will
conform to the current Line Length and Left Margin settings, and of course
the printer must already be in a suitable print mode. Sadly, this does not
work properly on all versions of Wordwise-Plus.
138. Wordwise-plus bug
After acquiring version 1.4E of this splendid program, I found that
unfortunately a bug has crept into the Full Indent facility. This bug was not
present on my earlier version, and unfortunately 1.4E is actually on a ROM
rather than on EPROM. This means any corrections can be expensive for
Computer Concepts, and slow to be implemented. The irony is that I was
perfectly satisfied with the version I had before, but it wasn't compatible
with my new Master 128!
The bug appears in two situations. First, I showed you in the previous tip
how you can easily draw a horizontal line across the page. Well, this no
longer works, so you have to remove the "fi" term, and stick in the
appropriate number of spaces or Pad characters. The second problem occurs if
you use Full Indent when in the Double Strike mode; ie you have issued a "ds" somewhere prior to the "fi", but haven't cancelled it. The indent simply
doesn't work in this situation. The solution is to use "de" just before the "fi", and then use "ds" again just after. I'm a great fan of Computer
Concepts, but they are definitely getting a raspberry from me this time! I've
since acquired InterWord, and happily it doesn't appear to have similar bugs,
(so far).
NB: The bugs have been cleared in version 1.4F!
139. Wordwise-plus paging hints
Three things occurred to Richard Hare after the group meeting in July 1986,
when Wordwise-Plus was discussed, and here they are:-
1.
"Somebody said he wasted the first sheet of tractor-feed paper every time he
used his Epson printer. This can be avoided if you pull the scale-bar towards
you and only let it go back onto the paper after the first few lines have
been printed. Better still, if the individual texts are short enough to allow
quite a large top space, you can start printing with the perforation line
along the top of the scale-bar ready for tear-off; use a top space of zero
(TS0) and the first line of printing will come at line 6 in the case of an
Epson FX80. Use HP0 if you are using a header, and TS4; the text will then
start four lines below the header. Use BS10 and that will give you an actual
bottom space of 4. Footers should be at FP2 or FP3; if the FP number is
greater than 4 the footer will be beyond the perforation, at the top of the
next page."
2.
"Somebody else mentioned that to get the paper to the start of the next page,
when one text has been printed, he uses the operating control code for
form-feed, OC12. That is fine, but if you are using a footer it will not be
printed on the last page of your text. If you have a footer you should finish
with a green BP, with no white afterwards and no carriage return. This will
effectively do a form-feed at the end of the text and print the footer. If
you press do <RETURN> or <f2> after the green BP it will line-feed the number
of lines in your top-space for the next page as well, and the header will be
printed at the top. This is not desirable."
3.
"If you are defining the character strings while using WORDWISE-PLUS remember
that it is fatal to define F$. F$ is used in the program, and if you try to
use it yourself you will screw the whole thing up!"
140. ADFS filename snag
If you are using an Acorn ADFS, you must avoid using fullstops anywhere in
filenames. Whereas an 'ordinary' DFS will accept "VIEW2.1" as a valid
filename, the ADFS will treat this as filename "1" in directory "VIEW2".
Since it is unlikely that you have such a directory on the disc, you will get
the message "Not found".
I ran foul of this when using the Copyfiles utility to transfer files from a
DFS formatted disc to an ADFS formatted disc. I had to *RENAME any offending
filenames to get rid of the fullstops. You should also avoid using hyphens,
as these are used in the syntax of a filename/filing-system path on a
Master/Compact.
141. Reset to ADFS
There are occasions when you may wish to enter the ADFS filing system,
without causing the disc drive to start up and look for a directory. You may
have an 'ordinary' DFS disc in drive 0, and wish to *MOUNT an ADFS disc in
drive 1. The behaviour of the ADFS in this situation does depend on the
*CONFIGURE DIR (or NODIR) option. However, regardless of this, you can select
ADFS without the drive starting up, by either pressing <Ctrl+F+Break>, or
by typing *FADFS . The ADFS is a bit hard going at first, but by jove it's
worth persisting!
142. Language problems
Some language ROMs will not work on the Master, (eg Commstar), as they give a"This is not a language" error. You can cure this by editing an 'image' of
the ROM. Look through the first few bytes, and see if the 7th along, (address&8006), is &82. If so, edit this to &C2 and save the image. This should then
enable the ROM to work, though not necessarily in SRAM if write-protection is
needed. It doesn't mean that the ROM will necessarily be compatible with the
Master, but it will at least be correctly recognized. Commstar, for example,
does work fine after editing.
143. *MOVE syntax
The syntax of this useful command can be a bit tricky. It is used for moving
individual files between filing systems, eg transferring from DFS to ADFS
discs. To transfer a file from a DFS disc in drive 0 to an ADFS disc in
drive/mount 1, use the form *MOVE -DISC-:0.name -ADFS-:1.newname Note the
rather unfamiliar use of hyphens in the syntax. Directory names can be
included where appropriate, and the drive specification could be omitted if
the currently selected ADFS drive was 1 and the currently selected DFS drive
was 0.
This is easily overlooked, in which case "Disc error" messages occur, so use
the full syntax. To copy several files, it is better to use the Copyfiles
ADFS utility program on the Welcome disc. Incidentally, if you specify the
same filing system and drive for both source and destination, but specify a
different directory or filename, then this a convenient way of duplicating a
file on the same disc, without deleting the original as would happen with
*RENAME.
73 Rick G4BLT @ GB7WRG
144. ADFS *COPY Syntax
The *COPY syntax on the ADFS is different from that on the DFS, and is a bit
obscure. You must specify the filename to be copied, including the directory
and/or drive specification if they are not current, and then the directory
and/or drive specification of the destination, (ie just the pathname).
For example, suppose I want to copy a file called "Fred" from the current
drive (0) and directory to the root directory on the other drive (1). This
would be achieved with *COPY Fred :1 If I needed to include full pathnames,
and I was copying from a sub-directory "NAMES" on drive 0 to a sub-directory"PEOPLE" on drive 1, then it might look something like
*COPY :0.$.NAMES.Fred:1.$.PEOPLE .
You can of course include the wildcard characters "#" and "*" in the
filename if you are copying a group of files.
You cannot change the filename when copying in this way, but you can by using
the same syntax with *MOVE, and adding the new filename after the destination
pathname. *MOVE also has the advantage that you can add -ADFS-, -DISC- etc at
the beginning of the pathnames to copy between filing systems, but it has the
disadvantage of being appallingly slow. For copying between filing systems,
those of you with the Advanced Disc Toolkit are better off using *XFER
instead, as it is far faster.
145. Plotting ellipses
By referring to the list of PLOT commands on page 232 of the Master Welcome
guide, you can easily work out how to draw rectangles etc., using similar
methods to drawing triangles. However, drawing ellipses is a bit more tricky.
You must first 'visit' the dead centre of the ellipse, as you might expect.
You must then visit the point where the ellipse cuts a horizontal line drawn
through the centre. Since the Y-coordinate of this point is by definition the
same as that of the centre, it doesn't matter what Y-coordinate you put in
the MOVE, DRAW or PLOT command you use to visit the point, as the true value
is assumed automatically. The horizontal line cuts the ellipse twice, but it
doesn't matter which of the two points you choose.
Finally, you should use the ellipse PLOT command, eg 197, to specify the
highest point of the ellipse, ie the point with greatest Y-coordinate.
(Alternatively, it can be the lowest point of the ellipse.) Anyone with
access to the Acorn GXR manual should find no difficulty with the Master's
extra PLOT commands, otherwise you need to see the Master Reference Manual
part 1, which is at last available.
146. VDU terminator
There is a new terminator for the VDU commands, which sends 9 zero bytes.
Thus, VDU23,1,0;0;0;0; can be replaced with VDU23,1| . It doesn't matter if
too many zeros are sent, as they will have no effect.
147. Character founts
If you insert the ADFS Welcome disc and type *thin, *Italic or *7by8 , the
screen ASCII character set is modified with interesting results in Modes 0 to
6; Cancel with *FX20 . For a comparison of all 3 of these founts, enter Mode
3, (but not Mode 131 or SHADOW modes), and type *LOAD LIBRARY.Fonts 4000
You can also modify some of the ASCII characters from 128 to 255, so try
typing FORc%=128TO255:VDUc%,32:NEXT both before and after typing
*EXEC LIBRARY.Pfont
148. ROM sockets
In addition to the two external cartridge sockets, which can support 4 ROMs,
there are 3 spare internal ROM sockets. The only one which works initially is
the centre one, (labelled IC27), and this corresponds to ROM slot 8. The
rearmost socket, labelled IC37, corresponds to ROM slot 7, but this is
normally configured as sideways RAM, (SRAM). To use if for a ROM, shift the
nearby link LK19 to the right. The remaining socket at the front is labelled
IC41, and corresponds to ROM slot 5, which is also normally configured as
SRAM. To bring this into use, shift the nearby link LK18 to the right. Note
that in gaining slot 7 as ROM, you lose SRAM slots 6 and 7. Similarly, in
gaining ROM slot 5, you lose SRAM slots 4 and 5. This because each slot
supports up to 16k, but ROMs can be from 8k up to 32k, and might need to
occupy two slots. This means that you won't be able to run BAS128, which
needs all 4 slots as SRAM. I've had Disc Doctor, Wordwise-Plus and
Printmaster all happily installed and working. When the plug-in cartridges
are used, slots 0 to 3 are available for ROMs, so there should be no need to
sacrifice SRAM.
149. When is a 1770 FDC not a 1770?
When it's a 1772! My Master would not work properly with an old Teac
full-height drive. I tried using both *CONFIGURE FDRIVE and *FX255 to select
30ms head-step time to suit the slow drive, but that made matters worse. On
examining the FDC, (Floppy Disc Controller), chip in my Master, I discovered
it was a 1772 and not a 1770. Page C.5-4 of Part 1 of the Reference Manual
has a little table relating to the *CO. FDRIVE parameter:-
Value Head Step Time Precompensation
(WD1770) (WD1772) (ADFS only)
0 or 4 6ms 6ms yes
1 or 5 6ms 6ms no
2 or 6 30ms 3ms yes
3 or 7 30ms 3ms no
The normal values to use are 0 or 2, but instead of increasing the step time
from 6ms to 30ms, I was actually decreasing it to 3ms! Most 80-track drives
will work fine on 6ms, and many are OK on 3ms, though not when switched to
40-track mode, (due to the double-stepping), but many older 40-drives won't
work on either. This is a bit naughty of Acorn, as it could force Master
buyers to change their drives. Whilst there are considerable advantages in
upgrading to double-sided 80-track drives, people ought to be able to do this
when they are good and ready! If you want to check which FDC chip is fitted,
take the lid off, and peer under the back of the keyboard, more-or-less under
the red <f5> key. You'll need a torch, and the keyboard ribbon cable does get
in the way a bit!
150. Incorrect capacitors
On the Master, the capacitors C85 and C86 are located either side of IC43,
near the UHF modulator can. They should be 10nF, (same as 0.01uF or 10,000pF)
and may be marked "103". Some machines were accidentally fitted with 100pF
capacitors, which may be marked "101". These cause overheating problems when
a Turbo 2nd processor board is fitted, and should be changed.
151. Interword tab hint
The manual tells you that you can delete TAB markers from a ruler, (as
opposed to the TAB codes in the text), using <Delete>, <Copy> or <Ctrl+A>.
What it does not tell you is that you can also add them with the <Tab> key,
after positioning the cursor at the desired place on the ruler.
152. InterWord line hint
With Wordwise-Plus, (though not version 1.4E), you could draw an unbroken
horizontal line across the page with {G}us{G}fi{G}ue{W}, which would
automatically conform to any changes in margins and line length.
NB: {G} & {W} represent Green and White codes.
You can achieve a similar result in InterWord as follows. Make sure the line
to be used is blank, and that there is, (temporarily at least), a blank line
immediately above and below it. (It helps to have the RETURN and TAB codes
visible, ie Screen codes ON.) Press <f3> Insert Marker, <Tab>, <f6> Align
Right, <f3> Insert Marker, Cursor Left one space, <Shift+f4> Underline. You
can now remove the blank lines above and below if you wish.
153. View extended highlights
Within VIEW there are two commands known as Highlight-1 and Highlight-2,
which are used to mark parts of the text to be printed in a special way. The
printer is controlled by a printer driver routine within View, which
interprets the Highlight commands and converts them into codes which the
particular type of printer in use can understand.
Normally, Highlight-1 inserts an underline "_" character into the screen text
and sends a code 128 to the printer driver, which in turn produces underlined
text on the printer. Similarly, Highlight-2 inserts an asterisk, sends code
129 and produces bold printed text.
To improve on this limited situation, use can be made of what Acorn call
Extended Highlights. By resetting Highlight-2 to produce code 130, and
loading one of the Acorn Printer Driver routines from disc, (costs about
#10-00), various printer effects can be called upon by using combinations of
Highlights 1 and 2. For example, italics can be created using Highlights
2+1+2, which would appear as "*_*" on the screen. The Acorn Printer Driver
disc contains routines for most common printers, and a program is available
to create your own if you wish. Highlight 2 is reset by entering as the first
line on the edit screen:- 'Edit Command' HT <RETURN> 2 <SPACE> 130 .
The function keys, in conjunction with <CTRL> and <SHIFT>, can be used to
provide the appropriate codes, which can be installed using a !BOOT setup;
*FX228,1 enables the <Ctrl+Shift> facility. For further explanation of the
facilities, refer to the Printer Driver User Guide and your Printer User
Guide. Remember to include all the spaces when typing in, as they are vital,
and don't confuse "!" with "|". For clarity, spaces are shown as a "-", and
note that some definitions have a space at the END, not just in the middle.
*WORD
*FX228,1
*KEY0|!|-
*KEY1|!!|!!|!!
*KEY2|!!
*KEY3|!!|!|-
*KEY4|!!|!!
*KEY5|!!|!!|!|-
*KEY6|!!|!|-|!|-
*KEY7|!!|!|-|!!
*KEY8|!!|!|-|!|-|!|-
The facilities created using <Shift+Ctrl> + Function keys are:-
f0 f1 f2 f3 f4 f5
Under- Bold Next character Begin Begin Cancel Sub
line On/Off to extension Subscript Superscript or Super-
set script
f6 f7 f8
Alternative Italics Reset
Font on/off on/off
154. !BOOT file for ViewSpell
During a demonstration of 3 spelling checker packages, ViewSpell by Acorn
came out as the worst, mainly because there was a lot of work involved for
the user with originally generating the text in View, calling up ViewSpell,
doing a disc change, making the ROM work, another disc change, then back
into View for the results of the check!
Yes, done this way it can be a nightmare! I have only a single 80 track
double-sided Cumana drive, hooked up to an Electron with 1770 DFS, (you may
snigger but PAGE is always E00), and have configured my !BOOT file, placed
on the master dictionary disc, to do most of the work, including searching
a number of user dictionaries. The disc is set up in the following way.
Place all the dictionaries on side 2 and the text file to be checked as"text" on side 0. You will tell the ViewSpell system where all these bits are
by the use of the PREFIX statements in the software when setting up the !BOOT
file. The 'line' numbers below are the ones which appear when you are
*BUILDING the !BOOT file, so don't type them in!
NB: Lines 10 and 11 refer to user dictionaries; yours will no doubt differ.
Make sure you are able to call both View and ViewSpell from the existing
system.
Line 12 is a blank. This is where the system asks for a user dictionary, and
if using the keyboard one would only press <RETURN>. The !BOOT file therefore
does it for you. Also, the statement in line 16 sets View into Format and
Insert modes; your version may differ and may need a small change.
After you have built your !BOOT file, save your text as described above,
and then !BOOT the disc. When the system has finished you will be presented
with the 1st item of your document which is spelt incorrectly. This is
where you take over again after all the hard work has been done!
1 *BASIC
2 MODE 6 (or MODE 7, but then leave out line 3 for text colour)
3 VDU 19,1,3,0,0,0
4 *SPELL
5 PREFIX M :2.
6 PREFIX U :2.
7 PREFIX T :0.
8 LOAD TEXT
9 CHECK
10 OTHERS
11 BAD
12 (Just press <RETURN> here)
13 MARK MARKER
14 MODE 3
15 *W.
16 SET FI
17 LOAD MARKER
18 SEARCH #!
155. Splitting large files
This program was written in order to split a very large word-processing file
that was too big to fit into memory. (Any type of file can be split; not just
text files.) This may happen if the micro which saved the data had a 6502 2nd
processor, Shadow RAM, or some other means of gaining memory, whereas yours
may not. The program splits large files into smaller ones, whose length in
bytes is determined by the variable max% in line 10. You should substitute
the name of the large file for "oldname", and the name of the smaller
subfiles for "newname". The subfile names will be suffixed by "1", "2" etc,
so you will be limited to 6 characters on an ordinary DFS.
This program will split a file in mid-word, so if you don't want it to do
that, you can replace the expression PTR#c2=max% in line 40 with
(PTR#c2>=max%ANDg%=32) ; the brackets are very important. This will split
the file at the first available Space, but if you put 13 instead of 32, the
file will be split at the first available Carriage Return, which would
usually be at the end of a paragraph. Many refinements could be added, and
the program is rather slow, but it does the job.
10 max%=15000:f%=1:c1=OPENIN("oldname")
20 REPEAT:c2=OPENOUT("newname"+STR$(f%))
30 REPEAT:g%=BGET#c1:BPUT#c2,g%
40 UNTIL PTR#c2=max% OR EOF#c1:CLOSE#c2:f%=f%+1
50 UNTIL EOF#c1:CLOSE#c1
156. INKEY(-256) command
This command does not appear to be documented in any of the official Acorn
manuals. Instead of checking for a key being pressed, it returns a number
which indicates the type of machine in use. This can be handy when writing
programs which are to be used in several different types of machine. Eg, to
avoid the *SHADOW command upsetting a standard Electron or BBC model B,
whilst executing it on a B+ or Master/Compact, you could use
IF INKEY(-256)>1 THEN *SHADOW1 The numbers are:-
BBC B with new 1.00+ OS -1 (including 1.20)
BBC B with old 0.10 OS 0 (obsolete!)
Electron 1
BBC B+ 64/128 251
Master 128 253
Compact 245
and now:
Archimedes (Arthur OS) 160 (obsolete)
Archimedes/A3000 (RiscOS) 161
Acoen A5000 ???
157. Calendar functions
The first of these, FNnumdays at line 1040, is derived from a short Function
I saw on Micronet, credited to Frank McAree. It returns the number of days in
month m% in year y%; eg PRINT FNnumdays(7,1987) would print the number of
days in July 1987. It takes account of all Leap Years, which the original
didn't. Years divisible by 4 are Leap years, except for those divisible by
100 but not by 400. Eg the year 1900 wasn't a Leap year, but 2000 will be.
The present Gregorian calendar system dates from 1752 in most countries;
before that it was chaos!
The second, FNday at line 1070, is one refined from an Acorn User program by
Robin Newman. It returns the day of the week on the date d%,m%,y%; eg PRINT
FNday(22,3,1986) would print the day of the week on 22nd March 1986 as a
string, "Sat". If however, you want the day as a complete word string, eg"Saturday" rather than "Sat", then put the full words in line 1050, padded
with trailing spaces to 9 characters each, ie"Saturday-Sunday---Monday---Tuesday--WednesdayThursday-Friday---", ("-"
represents a space), and alter both the figures "3" to "9". If you would
rather it returned the day of the week as a number, then alter line 1050 to
=day% . This gives 0 for Saturday, 1 for Sunday and so forth, so if you would
prefer 7 for Saturday instead of 0, then alter line 1050 to
=day%-(day%MOD7=0)*7 . (This is more elegant and structured than using
IFday%=0THEN=7 ELSE=day% .)
These two Functions can be used quite independently, but the Procedure
PROCcalendar at line 1000 shows just one way in which they might be used
together. It displays a crude calendar for month m% in year y%, eg
PROCcalendar(7,1987) for July 1987.
1000 DEFPROCcalendar(m%,y%):LOCALd%
1010 FORd%=1TOFNnumdays(m%,y%):PRINTFNday(d%,m%,y%)" ";d%:NEXT
1020 ENDPROC
1030 :
1040 DEFFNnumdays(m%,y%)
1050 =30+ABS((m%>7)+(m%MOD2))+(m%=2)*
(2+(((y%MOD4)=0AND(y%MOD100)>0)OR((y%MOD400)=0)))
1060 :
1070 DEFFNday(d%,m%,y%):LOCALday%
1080 IFm%<3THENm%=m%+12:y%=y%-1
1090 day%=d%+2*m%+INT(0.61*(m%+1))+y%+y%DIV4-y%DIV100+y%DIV400+2
1100 day%=day%MOD7
1110 =MID$("SatSunMonTueWedThuFri",day%*3+1,3)
158. Multiple windows
It is possible to give the illusion that there are several independent text
windows defined on the screen simultaneously. As soon as you define a new
text window, the previous one is 'forgotten'. However, as long as the program
'remembers' where the cursor was, the same window can be redefined later, and
the cursor put back in its original position. The short demonstration program
below displays two independently scrolling windows on the screen. VDU31,x,y
is equivalent to PRINTTAB(x,y); and the term FSGNRND=1THEN is used to make
the two windows scroll at different, varying rates. Omit this term, leaving
just VDURND(95)+31 to see what I mean.
100 p1%=0:v1%=0:p2%=0:v2%=0:MODE7:VDU23,1,0;0;0;0;
110 REPEAT:PROCwindow1:PROCvdu:PROCwindow2:PROCvdu:UNTILFALSE
120 :
1000 DEFPROCwindow1:p2%=POS:v2%=VPOS
1010 VDU28,0,11,18,0:VDU31,p1%,v1%:ENDPROC
1020 :
1030 DEFPROCwindow2:p1%=POS:v1%=VPOS
1040 VDU28,21,24,39,13:VDU31,p2%,v2%:ENDPROC
1050 :
1060 DEFPROCvdu:IFSGNRND=1THENVDURND(95)+31
1070 ENDPROC
159. Accelerating step rate
This is a simple program by Andrew G8YHI, to demonstrate an idea. If you
press and hold either the Up or Down cursor key, a number on the screen will
be incremented or decremented accordingly. The longer you hold the key down,
the faster the number changes. This would enable values to be altered by
large amounts easily and quickly, whilst still allowing 'fine tuning'.
Perhaps some enterprising person could tidy this up into a more
general-purpose procedure?
10 CLS:X=33:VDU23,1,0;0;0;0;
20 REPEAT:PROCchange:UNTILFALSE
30 :
100 DEFPROCchange:TIME=0:REPEAT
110 IF INKEY(-58) THEN X=X+(TIME/2000)
ELSE IF INKEY(-42) THEN X=X-(TIME/2000)
120 Y=INT(X):PRINTTAB(10,10)Y:UNTILINKEY(-129):ENDPROC
160. Killing ROMS
I suppose that most Beeb users who have fitted extra ROMs have had problems
with clashing "*" commands. When I first got my Beeb, I bought Computer
Concepts Disc Doctor. I still have it fitted and it is arguably still the
best standard utility ROM available for a Beeb that has an 8271 disc
controller.
One of its commands is *MENU, which presents a pleasant uncluttered menu
screen, enabling both BASIC and Machine-Code programs to be run by pressing a
single key. It will even automatically handle downloading of programs to a
PAGE value of say, &E00. Since it was so easy to use, I built the *MENU
command into the !BOOT file on many of my discs. You can imagine how annoyed
I was when later having fitted another utility ROM, Enigma, I found that it
clashed with the *MENU command in Disc Doctor. All my discs wouldn't boot up,
despite the fact that Enigma didn't even have a *MENU command among its own
list of routines!
The time had come to temporarily immobilise the offending ROM. But how best?
There is a command within Enigma that will turn off any ROM including itself,
but when the <BREAK> key is pressed, as with <Shift+Break> to boot up a
disc, the ROMs are reactivated. The switch-off command can be built into the
!BOOT file on the disc, but you get a messy screen as the routine is
implemented, and of course it only works if you happen to have Enigma. What
is required is a simple method of switching off any offending ROM to allow
the "*" Command to be acted upon by the required ROM.
Now on start up, <BREAK> or <CTRL+BREAK>, the OS copies the ROM type code
for each of the ROMs that are fitted, down to page 2 for its own use. The
table starts at &2A1; the 1st location corresponds to socket 0, the second to
socket 1 etc.. If the value zero is placed in the table, then the OS will not
recognise the ROM in the associated socket and will not offer it any "*" commands. Thus the solution is to 'poke' a zero into the correct address from
the !BOOT file. The address in hex can be calculated by entering:-
PRINT~&2A1+(n) , where (n) = the socket number.
So to turn off any ROM, first find the socket number (n) of the ROM to be
disabled, 2nd Calculate the address to be poked and then build up the !BOOT
file. Since Enigma in my machine is in socket 7, the !BOOT file is built up
as follows.
*BUILD !BOOT <RETURN>
1 ?&2A8=0 <RETURN>
2 *MENU <RETURN>
3 <ESCAPE>
*OPT 4,3 <RETURN>
Pressing <Shift+Break> should now boot up the disc with no problems. If you
don't have a routine to find out which socket your ROMs are in, then the
following program will show you what you have fitted and where. For a
shortened printout which will fit across a Mode 7 screen, omit line 1020 and
alter the MODE statement in line 100 from 3 to 7. Note that ROM images in
SRAM will not be shown until initialised, ie <CTRL+BREAK>.
10 REM ROM Identifier by R.Sterry 09.06.85 modified 14.09.87
20 :
100 MODE3:@%=&902:FORY%=0TO15:PRINTY%,~Y%" "FNrom:NEXT:@%=&90A:END
110 :
1000 DEFFNrom:LOCALstring$,off%,off1%,byte%
1010 off%=FNpeep(7):IFY%?&2A1=0ORoff%=&80THEN="EMPTY"
1020 REPEAT:off%=off%+1:byte%=FNpeep(off%):UNTILbyte%<32ORbyte%>126
1030 FORoff1%=9TOoff%-1:byte%=FNpeep(off1%):IFbyte%<32THENbyte%=32
1040 string$=string$+CHR$(byte%):NEXT
1050 =string$
1060 :
2000 DEFFNpeep(mem%):!&F6=&8000+mem%:=USR(&FFB9)AND&FF
161. Instant migraine
A rather sadistic Marcus Wilson from Harrogate sent in the following one-line
program, which is guaranteed to make you feel queasy very quickly! Master& Compact users can substitute VDU19| for the last statement (ie the vertical
bar symbol).
10 MODE2:?&360=255:VDU19,0,0,0;0;0;
162. High-quality audio output
If you want to feed audio from a BBC B into an external amplifier, you can
use the loudspeaker output, but there is a better-quality output available.
Locate the point where the purple -5v supply wire from the front right of the
PSU connects to the circuit board, and then look slightly nearer the front,
just underneath the rear edge of the keyboard. You should find two solder
pads marked "PL16"; the rear (North) pad is Ground (0v), and the front
(South) pad is the output. This output is connected to the input of the
internal volume control "VR1", and is at a level suitable for feeding into a
hi-fi amplifier. There is a similar output marked on the BBC B+ circuit
diagram as "S21", and apart from surmising that it will be close to the
internal volume control "VR2", I have no other details.
163. BASIC program format
This is how a BASIC program is actually stored in memory. The program starts
at the current value of PAGE, which denotes the lower edge of available
memory. If you PRINT~PAGE you should get something like E00 or 1900,
depending on whether or not you have a DFS etc fitted. The value ('byte')
stored in this 1st location, is &D (Hex) or 13 (Dec), which is the code for a
Carriage Return (CR). Whenever a program is present, then PRINT~?(PAGE)
should indeed give "D". (If you have a utility ROM like Disc Doctor, then you
have a much easier way of examining memory.) The next byte is the Most
Significant Byte (MSB) of the 1st linenumber, and the one after is the LSB.
You can check this as follows: Suppose the 1st linenumber is 100. The MSB is
given by PRINT~100DIV256 , and the LSB is given by PRINT~100MOD256 . This
should give you 00 and 64 respectively, (note the convention of expressing
Hex bytes as 2 digits). Thus PRINT~?(PAGE+1),~?(PAGE+2) should indeed give
you 00 and 64. Note that the MSB is always 00 for a linenumber of 255 or
less; more about that later.
The next byte, ie at (PAGE+3), is the total length of the 1st line of the
program, including the two linenumber bytes, including the length byte
itself, and including the Carriage Return (0D) byte at the end of the line.
Note that BASIC keywords such as REM and PRINT are stored as just 1 byte
each, and that some also include the opening bracket, eg MID$( . You can
look up these single-byte 'tokens' in your User Guide, indexed under"Tokens" or "Basic Tokens". For example, the keyword NEXT is tokenised as
ED. As a simple example, the basic line 110NEXT would be coded as
00 6E 05 ED 0D. Note that there would be another 0D immediately before the
00 in the unlikely event of this being the 1st line in the program, but the
length byte would remain as 5.
The following lines are coded in exactly the same way, and the end of the
program is indicated by an FF immediately following the 0D at the end of
the final program line. (Do not confuse this FF with the keyword token for
the BASIC word END, which happens to be E0.) The very next location after
this, which is the 1st 'free' one after the program, is denoted by TOP .
Thus if you PRINT~?(TOP-1) you always get FF. As a practical example, here
is a simple 2-line program fully tokenised, with a 'translation'
underneath. You will notice that the code for a Space is 20 in Hex, and
this is very commonly found in programs!
10REM HI
PAGE 20PRINT"LO" TOP-1
v v
0D 00 0A 08 F4 20 48 49 0D 00 14 09 F1 22 4C 4F 22 0D FF
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
R Line Line R S H I R Line Line P " L O " R End
e 10 Len E p e 20 Len R e
t 8 M a t 9 I t
u c u N u
r e r T r
n n n
Cynics among you will point out that there doesn't seem to be any memory
saving as a result of tokenising. However, you must remember that each line
takes up at least 4 bytes before you've started, ie the linenumber bytes, the
length byte, and the 0D at the end. Thus, for very short lines such as I have
used in the example, there is little or no saving in memory space,
particularly as I have only used 2 keywords. The more you cram onto one line,
and hence the fewer linenumbers you use in the program, the better the
economy. Typically, a tokenised program contains about 70% of the characters
counted in a listing.
There is just one little complication, and that is when a GOTO or GOSUB or
THEN (implied GOTO) destination linenumber is encountered. You might expect
to find the appropriate token, E5 E4 or 8C, followed by 2 bytes for the
destination. In fact, the linenumber appears as 4 bytes; the 1st is always
8D as an indicator, followed by 3 bytes which are encoded in a really weird
way.
One final little quirk. When you press <BREAK> or type NEW, the 2nd byte of
the program at PAGE+1 is changed to FF. This tells the computer to ignore
the program, which is still intact, and pretend there is nothing there.
When you type OLD, the byte is changed back to 00, and the program
'reappears'. Now, it so happens that this byte is also the MSB of the 1st
linenumber, and since it is reset to 00 rather than to whatever it was
before, odd things happen if the 1st linenumber is greater than 255. Try
typing in a two-line program with 1000 as the 1st line, and 1010 as the
2nd. Now type NEW followed by OLD, and then LIST, and see what happens to
line 1000! The linenumber has been changed to 1000MOD256, which is 232. In
other words, the linenumber bytes have been changed from 03 E8 to 00 E8.
Although this is quite harmless, it is more than a little disconcerting to
the uninitiated!
164. "HARD" BREAK/RESET
This can be achieved in software with the statement ?&FE4E=&7F:CALL !-4 (or
CALL !&FFFC). Without the ?&FE4E=&7F, it is only a soft break.
165. Date-stamping discs
It is easy to overlook the important task of regularly backing-up your discs.
This is all the more important when using double-density DFSs, as so much
information can be carried on just one disc, (up to 640k with Acorn ADFS). As
a record of when a disc was last backed-up, you could save a dummy file of
zero length, with the date as the filename, eg *SAVE !7thDec 0 0 . The form
of the date doesn't really matter, but the use of a "!" prefix followed by a
number as the next character, will make the file appear first in the
catalogue, even before !BOOT. Users of the Master 128 can automate this
procedure to some extent, as shown in the next hint. Another way of
subsequently altering this dummy date file is to simply *RENAME it.
166. Date-stamping discs (for Master)
The routine below, shown as a red key definition, will automatically save the
current date as a dummy file of zero length, eg "!28Nov86". The use of a red
key is handy if you are going to back up several discs in one session. If
using the ordinary 1770 DFS, you are limited to 7 characters per filename, so
you will have to omit the "!", or perhaps the "8" from "86".
The idea is to *MOUNT the source disc, *DELETE the old date file, *SAVE the
new date with this routine, and then *BACKUP the disc. Alternatively, you can
*RENAME an existing dummy date file. Thus, you know exactly when the disc was
last backed-up, so there is no excuse for forgetting!
If you have a Utility ROM with *BACKUP on it, such as the Advanced Disc
Toolkit, then you can make this whole operation very simple using the red
keys. If not, then you could perhaps incorporate this routine on a line of
BASIC in the BACKUP program provided on the Welcome disc. Abbreviations have
been used, which is why some brackets appear to be missing. When typed as a
line of BASIC, (without the *K.0) the keywords will appear in full when
LISTED, and all will be clear.
*K.0 OS.("SA. !"+M.TI.$,5,2)+M.TI.$,8,3)+M.TI.$,14,2)+" 0 0")|M
167. Auto-date function (for Master/Archimedes)
This Function is for adding to programs which expect a date entry of the form
dd.mm.yy , eg 25.05.86 . The date is automatically extracted from the
internal TIME$ function, thus saving the bother of manually entering it. Eg
D$=FNdate .
This Function occupies much less memory, and uses far fewer variables, than
a version published in a recent issue of Beebug. If you want to save even
more memory, then add lines 2010 and 2020 onto the end of line 2000. Note
that in line 2030, m% is the month number 1-12, and the RIGHT$ statement is
to format it as a string, with a leading zero if it is less than 10.
2000 DEFFNdate:LOCALm%
2010 m%=INSTR("JanFebMarAprMayJunJulAugSepOctNovDec",MID$(TIME$,8,3))
2020 m%=(m%-1)DIV3+1
2030 =MID$(TIME$,5,2)+"."+RIGHT$("0"+STR$(m%),2)+"."+MID$(TIME$,14,2)
168. Drawing text boxes (for Master/Compact)
This Procedure makes use of the extra characters built-in to the Master. It
enables you to draw a neat box round text, without resorting to graphics
commands such as MOVE and DRAW. You specify the Left, Bottom, Right and Top
TAB X-Y co-ordinates of the box, just as if defining a text window. The VDU28
command in line 1040 defines a text window inside the box, and can be omitted
if not required. The example shown is in Mode 0, but it works in any 32-line
Mode, ie 0/1/2/4/5, but will not look very nice in Modes 3 & 6 unless you
make use of the "STRIPEY BACKGROUND" hint given in the 1986 tips compilation.
10 MODE0:PROCbox(20,20,60,10):END
20 :
1000 DEFPROCbox(L%,B%,R%,T%):LOCALV%
1010 PRINTTAB(L%,T%)CHR$(163)STRING$(R%-L%-1,CHR$(166))CHR$(165)
1020 FORV%=T%+1TOB%-1:VDU31,L%,V%,169,31,R%,V%,169:NEXT
1030 PRINTTAB(L%,B%)CHR$(170)STRING$(R%-L%-1,CHR$(166))CHR$(172);
1040 VDU28,L%+1,B%-1,R%-1,T%+1:REM Omit if not required
1050 ENDPROC
169. !BOOTing convert (for Master)
If you have some programs which will only run after you have used the CONVERT
program off the Welcome disc, you can put them together on one disc, with the
following !BOOT file:- IF INKEY(-256)=-1 THEN CHAIN "CONVERT" ELSE CHAIN "MENU" . This will run the CONVERT program if necessary, so that next time
you boot the disc, the main menu or other selected program will be run
instead. When transferring CONVERT from the Welcome disc, use *COPY or *MOVE
rather than LOAD and SAVE, as it consists of a few lines of BASIC, followed
by some 'hidden' machine code to be loaded into SRAM.
170. Composite video colour (for Master)
To get a colour signal from the CV output socket, I hear that you can solder
a 470pF ceramic capacitor between the emitter (right leg) of transistor Q12
and the base (centre leg) of Q13. These are located between the CV and RGB
sockets, and although it is a slightly delicate soldering job, it is nowhere
near as tricky as the equivalent modification on an early BBC B.
73 Rick G4BLT @ GB7WRG
171. Negative INKEY code (for Master)
The code numbers for negative INKEY commands are given on pages D.2-39 and
D.2-40 of the Master Reference Manual Part I. The list given omits to tell
you that the code for the decimal point is -77 on the keypad, (-104 on the
keyboard).
172. Another calendar function
This Function will calculate the Julian Day Number which starts at midday on
the Gregorian date specified, eg PRINT Njulian(25,12,1987). Keen astronomers
will know the significance of the Julian Day Number, but it has a more
mundane use too. It provides a very simple way of calculating the exact
number of days between two dates, taking full account of all Leap Years; you
simply subtract the two Julian Day Numbers. eg:
PRINT FNjulian(25,12,1987)-FNjulian(28,5,1951) .
One small point; 1987 had a 'Leap Second' added to it to allow for the fact
the Earth's rotation has slowed very slightly. Do not throw your Quartz
watches away!
Note that I have split line 1010 to make it look tidier; it is actually all
one continuous line.
1000 DEFFNjulian(d%,m%,y%)
1010 =367*y%-7*(y%+(m%+9)DIV12)DIV4-3*((y%+(m%-9)DIV7)DIV100+1)DIV4
+275*m%DIV9+d%+1721029
173. ROM problems
This is a fairly typical tale, and illustrates how careful you have to be in
solving strange compatibility problems, and how careful you have to be in
fitting upgrades. Ray Chand upgraded his BBC B with a Watford solderless ROM
Socket Board, (very similar to the ATPL Sidewise board). First, the
connections on the underside of the board contacted the top of the metal
crystal sticking up near the rear of the BBC main board. PVC tape didn't help
too much, as the sharp connections soon punctured it. I suggested using a
double-sided sticky pad on the top of the crystal, with the protective strip
left on the upper surface. Secondly, the leads to the S21 link pins stuck up
too high, preventing the ROM board from seating properly; no choice here but
to bend them out of the way. Finally, when the OS ROM was transferred to the
ROM board, it prevented the keyboard from seating properly; spacing washers
under the keyboard can help here. I have had similar problems with various
makes of ROM boards on certain versions of the BBC - component heights and
layouts do vary between production sub-contractors and between board version
numbers.
After overcoming the physical problems, Ray found that several discs,
including Mini-Office II wouldn't behave unless either Wordwise-Plus or
SpellMaster was removed. The reason is that SpellMaster 'grabs' one page of
memory, when it detects WordWise or View - ie PAGE goes up by &100 (256)
bytes. The solution was to type *WORKOFF followed by <BREAK> to disable
SpellMaster. An ATS ROM was causing similar problems for much the same
reason. All was then well until he swapped the Acorn 1.20 DFS ROM for a
Watford 1.42 DFS. *WORKOFF produced an error message, and so did *CWORKOFF,
(you can prefix Computer Concepts' commands with a C, and Beebug's with a B,
to avoid clashes with other ROMs). This still didn't work, but putting the
DFS ROM in a lower priority socket to SpellMaster did cure the problem. It
appears that the Watford DFS *WORK command was clashing, though it strictly
speaking shouldn't have done. The lesson to be learned from this tale must be
that patience and a methodical approach will usually overcome such problems
in the end, and that it is worth persisting.
174. Decimal-Hex-Binary converter
This is a simple program which enables you to enter a decimal, hexadecimal or
binary number, and it then prints out the same number in all three formats.
It is intended for decimal numbers from 0 to 255, hex numbers from &00 to&FF, (just prefix the number with "&"), and binary numbers from 00000000 to
11111111, (you must type 8 digits). Thus, typing in "70", "&46" and "01000110" should all produce exactly the same results, but note that there
is little trapping against silly inputs.
A nice refinement of the program would be for it to also print out the
equivalent ASCII character, and to allow a single ASCII character input as an
alternative to the ASCII code. There isn't enough space here, and anyway you
can do that for yourself, CAN'T YOU?
10 REPEAT
20 INPUT"Number : "A$:IFLENA$<4THENA%=EVAL(A$)ELSEA%=FNbindec(A$)
30 PRINT;A%" &";~A%" ";FNdecbin(A%)'
40 UNTILFALSE
50 :
100 DEFFNbindec(A$):LOCALA%:IFLEN(A$)<8THENRUN
110 FORB%=7TO0STEP-1:A%=A%+VAL(MID$(A$,8-B%,1))*2^B%:NEXT
120 =A%
130 :
200 DEFFNdecbin(A%):LOCALA$
210 FORB%=7TO0STEP-1:A$=A$+STR$((A%AND2^B%)DIV2^B%):NEXT
220 =A$
175. TRACE
An associate had cause to use this rarely-needed command. Having checked down
the screen, a point was reached at which he was sure his program worked, so
he knew the error was further down. Looking at the TRACE command he observed
that:
TRACE 'line num.'
caused the computer to report only line numbers below 'line num.'.
However, on entering the command he found that only lines ABOVE 'line num.'
were reported. He had interpreted "BELOW" as meaning BELOW in the listing;
ie HIGHER line numbers. Evidently the message intended was that TRACE 'line
num.' would cause the computer to report only line numbers LESS than 'line
num.'. - Work this one out!!
176. Simple menu selection
When selecting one item from a screen menu, there is no need for each menu
option to be tagged with a number; it could just as easily be a letter.
Eg L = LOAD, S = SAVE, X = EXIT, etc.. You can then easily translate this
into a number, so that you can use ON ... GOTO/GOSUB . A useful refinement
would be to replace the GET$ with CHR$(GETAND&DF) , so that the Caps/Shift
Lock state wouldn't matter.
10 REPEAT:G%=INSTR$("LSX...etc.",GET$):UNTILG%
20 ON G% GOTO 110,180,250 etc.
177. Remarks & all that
Have you tried putting remarks in your programs without REM....; it can be
done if you slot them in between ENDPROC and DEFPROCabc after the END of
your program, e.g.
Lines 10 to 240 Program
Line 250 END
Line 500 DEFROCxyz
Line 620 ENDPROC
Line 700 This is a sample of what you can
Line 710 do, with no REM's required.
Line 800 DEFPROCefg, etc, etc
178. Discy flopps
Virtually all floppy discs come with glowing reassurances like 'Life-Time
Guarantee' or 'Fully Certified', so why do some discs cost many times the
price of others? Floppy discs have a surface noise factor, rather like the
hiss on an ordinary audio tape which can, under some circumstances create
errors and make the disc unreadable as the computer cannot distinguish
between noise and data.
Data pulses are inevitably recorded at different levels and the clipping
level is the lowest level of a data pulse compared to the level of the
average pulse; the normal standard is 40% which should work well provided the
read/write head is exactly centred on the recorded track. This is because a
data pulse whose strength is 40% of the average pulse will be well above the
disc noise or 'hiss'. However, when a different drive is used, which may have
different head alignment, the head may veer off the track. When this happens
the pulse strength falls but the noise remains constant; some of the lowest
recorded pulses may become dangerously close to the strength of the noise and
become indistinguishable and even lost, causing an error. The best discs use
a clipping level of 75% which keeps the lower pulses well away from the noise
even when the head is off track.
When manufacturers talk of certification they ought to point out that there
are two ways of certifying a disc; full surface and track only. The American
National Standards Institute (ANSI) specification only calls for track
certification but ideally the disc should be certified on and between the
tracks to prevent an unrevealed flaw growing into the track and ruining the
data. The best discs are full surface certified. Finally, discs are coated
with millions of tiny particles of metal oxide and ideally that is where they
should stay; on the disc. Disc manufacturers coat the discs with a protective
layer but with wear and ageing this can break up leading to the oxide
depositing itself onto the drive heads. On some of the best discs the
manufacturers try to coat even individual particles which leads to a more
durable and reliable disc.
When discs can be bought so cheaply it's easy to think "if it fails just
replace it", but a failed disc can mean an awful lot of lost data. Lifetime
Guarantees should and can mean just that, otherwise they are just about as
useful as a warranty on a parachute!
179. Reading/writing registers using OSBYTE
There are many Osbyte calls, (*FX calls if you like), which can read from and
write to various registers. The format given is a bit daunting to the
unitiated:-
<New Value>=(<Old Value> AND Y) EOR X
What it means is that the new value you are putting into the register is made
up of the original value, after logical ANDing it with the contents of Y, and
then Exclusive ORing the result with the contents of X. Why bother with all
this complication; why not just stick the new value in and have done? Well,
you can, but there's more to it than that.
If you want to READ the register without altering the contents, then simply
make the appropriate call with X=0 and Y=255, and the current value in the
register will usually be in X on exit. The contents will be ANDed with 255,
which is 11111111 binary, and will thus be unchanged. Then, they will be
Exclusive ORed with 0, which is 00000000 in binary, which also leaves them
unchanged. So, nothing is altered. You can do this from BASIC with the
command:-
10 A%=156:X%=0:Y%=255:PRINT~(USR&FFF4 AND&FF00)DIV&100
If you want to write a specific value to the register, then you can make Y=0
and X=<New Value>. Thus, ANDing with 0 clears all the bits, and EORing them
with X writes X into the register. Eg:- *FX4,2,0 (the ",0" may be omitted),
writes 2 into the register; in this case it affects the action of the cursor
keys. Using 4 as the osbyte number in the USR call above should return 0 to
2 depending on what setting of *FX4 is current.
It may well be that you want to alter only certain bits in a register, but
you don't know exactly what the contents of the other bits will be at the
time. For example, with *FX156, bits 5 and 6 affect the status of the RTS
line on the RS423 port. I may wish to alter these bits, without knowing the
contents of, and without wishing to alter, bits 7 and 0 to 4. This is where
the apparent complicated way of doing things comes into its own. The method
is:-
1. Set only the bits in Y which you do NOT wish to be affected in any way.
2. Set only the bits in X that you wish to be set to 1 in the register, and
leave the rest as 0.
3. Make the appropriate osbyte call.
In the example above, if I wished to set bits 5 and 6 to 1, without altering
the other bits, then X=&60 and Y=&9F. If I wished to set bit 5 to 0 and bit
6 to 1, then X=&40 and Y=&9F.
180. Printer snag
Several people have come up against an unexpected snag with some of the newer
Epson printers such as the LX80 and LX800, as well as the Citizen 120D when
in Epson-compatible mode. After having problems trying to redefine the draft
character set, they read the small print in the manuals to find that you are
only able to redefine the 6 characters ":;<=>?". Some earlier Epsons, and
printers like the Canon PW-1080A and Taxan-Kaga KP810, allow you to redefine
ALL the characters if you wish. This seems a curiously retrograde step by
Epson, and you should take care when choosing a printer, if this is a
facility you particularly need.
181. Friangle
The inspiration for this program came to Bob G3WWF whilst watching a
programme on Channel 4. The theme was concerned with how simple rules are
able to define quite complex structures, such as a fern leaf. To illustrate
this, a simple method of plotting a sort of Fractal Triangle, (hence"Friangle"), was briefly described. In Bob's words:-
"Three points of an equilateral triangle are stated, and then a random
initial point. A point is then plotted which is half way from the initial
point to one of the three triangle tips, chosen at random. From this new
point another point is plotted, again halfway to one of the triangle tips at
random, and so on. One's first assumption is surely that the points will fill
the triangle randomly, but not so!"
The program is very simple indeed, and has been further simplified and
speeded up by Rick G4BLT. An additional 20% increase in speed can be achieved
by using Integer arithmetic; change X to X%, Y to Y% and replace "/" with "DIV". The result is surprising and pleasing; a recursive pattern in fact. A
few apparently 'stray' points will sometimes appear; see if you can work out
why this happens!
10 MODE0:X=RND(1182)-1:Y=RND(1024)-1:MOVEX,Y
20 REPEAT:ONRND(3)GOSUB100,110,120:PLOT69,X,Y:UNTILFALSE
30 :
100 X=X/2:Y=Y/2:RETURN
110 X=(X+1181)/2:Y=Y/2:RETURN
120 X=(X+590)/2:Y=(Y+1023)/2:RETURN
182. Stripes in Wordwise Plus
A simple OS command will produce vertical stripes in preview mode so that
along with the LNS command, it would be quite easy to align characters either
vertically or horizontally.
There are two ways in which vertical stripes can be displayed; either
projected in between characters or running through the middle of a character.
An added bonus is that stripes could be in any of the BBC colours including
flashing ones! The green embedded command is: OS"FX155,n" where the value of
n=1 for red stripes between characters or n=17 for red stripes through the
middle of characters. Obviously values n=2 & n=18 would give green stripes,
3 & 19 yellow and so on. Curious effects can be achieved if for example two
OS commands are issued with say n=1 & 18 respectively. Stripes in two colours
viz red (between characters) and green (through characters) are obtained. The
possibilities are endless! Have fun!
NB: It is said that these effects can be generated in the later versions of
WORDWISE but it does not work on mine. (Ed: I have tried it on version 1.4E
and it works. TRY flashing colours - you go cross eyed!)
183. View text ruler
One of the nice things about Interword is the text ruler which shows the
column numbers, and therefore lets you know exactly where your text will be
printed on the paper. An easy way to recreate this in View is to include a
dummy ruler on a Comment line showing text positions, with the actual Ruler
'floating' underneath. If markers 1 and 2 are placed at each end of the
comment line the 'dummy' ruler can be copied anywhere into the document by
pressing the COPY key with the current ruler being copied using SHIFT and
COPY.
CO |....:..10....:...20....:...30.. etc ... 110....:..120....:..130.|
.. >...........*...............*..............<
184. Master ADFS compacting routine
If you try a *MAP command after *COMPACT, you will often find that only
partial compaction has taken place. If fuller compaction is required, you
have to try again. The short program below can be kept in the root "$" directory of all your discs, and when CHAINed will carry out several
'passes' until there is only one gap when *MAP is issued. Each pass takes
less time than the previous one, even if the same number of gaps result.
Occasionally, a disc can be very reluctant to compact below 2 gaps, though it
will make it eventually. The program therefore prompts you after 10 passes,
in case you don't want to bother to go the whole way. Typically, I found that
between 1 and 4 passes were needed with most discs.
You can alter the maximum number of passes via the variable T% in line 10,
and you can alter the number of gaps it will attempt to compact down to, via
the variable N% in line 10. (You will save a lot of time by increasing this
to 2, as long as this is sufficient for your purposes.) Do not alter the
variable A%. The program keeps you informed about how many passes it has
made, and shows the free space on the disc when it has finished. Note the
*COMPACT start page of 0F in line 20 to avoid corrupting the program itself,
which should reside at the normal PAGE setting of &E00. Therefore, if you do
add anything to the listing, even just a few extra spaces, then just check
that PRINT~TOP gives a Hex number starting with an E and not an F. The spaces
after the line numbers are shown for clarity only, and should be omitted.
10 T%=10:N%=1:A%=0:REPEAT:MODE135:*MAP
20 V%=VPOS-1:A%=A%+1:IFV%>N%ANDA%<=T%THENPRINT'"Pass ";A%:*COMPACT 0F 71
30 UNTILV%<=N%ORA%>T%
40 IFV%>N%THENPRINT'"Another try? ";:IFCHR$(GETAND&DF)="Y"THENRUN
50 PRINT''"Compacted"':*FREE
185. Master battery pack + internal modem
The early type of Lithium 'incendiary device' was replaced by a rather bulky
pack of 3 'AA' size 1.5v Duracell batteries, which occupied the space
intended for the internal modem. Despite the warning on the pack, I see no
reason why the owner should not replace the individual cells when necessary.
The positive lead has an 'idiot diode' in series, to prevent damage to the
computer if the batteries are inserted wrongly, and to prevent the computer
from attempting to charge 'flat' batteries. There is also a 100 Ohm resistor
in series with the negative lead, which prevents damage to the batteries if
the output is accidentally short-circuited. When plugging the pack back into
the main PCB, note that the black lead goes to the North pin, (nearest the
rear), the red lead goes to the central pin, and the South pin is
unconnected. Hold down the "R" key whilst turning the power back on, so as
to reset the RAM ready for you to enter the *CONFIGURE options. (The latter
are best held on disc as a *SPOOLed file, ready to *EXEC back in when
required.) Finally, you should reset the internal real-time clock/calendar.
The current type of battery pack still uses 3 Duracells, but they are in a
shrink-wrap plastic covering, which makes it much more compact. It fits
neatly down the small slot immediately to the left of the keyboard PCB, and
immediately in front of the PSU. This frees the internal modem space for
whatever you want to put there, including a modem of course. Replacing the
individual cells oneself is not as easy as with the older pack, but it is by
no means impossible. The pack costs 3-68 from Beebug, (3-50 to Beebug
members), plus 1 pp, and the part number is "0807B - Master Battery Pack".
Beebug also do an internal modem, which frees the RS423 port for other uses,
including software on ROM, for 119, (113-05 to Beebug members), plus 3-75
pp. The modem is multi-standard, with auto-dial, auto-answer, and various
other bells and whistles. The part number is "0759E - Master Internal Modem".
186. Master 128 power supply tip
The power supply unit is marked "No user serviceable parts inside" - but
there are two fuses within this unit, and replacements of a similar type can
be purchased from TANDY. If you get intermittent faults, it may indicate a
dry joint on the main power transistor. (You must use your own discretion
with regard to these two hints - liability cannot be accepted for damage to
your computer.).
187. Hashing around
There are occasions, in programming, when you need to need to scan down a
list and find if there is a match with a particular string. The string might
be a name, a radio callsign in my case, or a number of some sort, or a mixed
string of numbers letters and punctuation. If your program has to scan down
a long list, then this can be very slow indeed. This is because the string
might not have any obvious location in the list, so the lot has to be
searched.
There is a way round this, called 'hashing', whereby the program calculates
a definite location in the list for a particular string, which is ALMOST
unique. If the location in question is found, as happens occasionally, to
already contain a different string, then the next free location is used for
the new string, which hardly slows things down at all. The theory behind the
technique is too involved to be covered in a short article like this, but
here is a ready-to-use Function to try it out.
The variable as% at the beginning of line 10 should be set to a size larger
than the maximum expected length of the list. 50% larger is fine, but you can
get away with as low as 20% with a slight reduction is speed, but smaller
margins will cause a drastic reduction in speed as the list fills up. The
string array list$ contains the list of strings, and the integer array list%
is used to keep track of how many times each string has been searched for.
The latter can be useful for statistical purposes, but if you aren't
interested, then simply omit all terms involving list%.
Lines 20 to 30 form a simple demonstration program, using a list of length
100. (Well you shouldn't fill it up completely, as I implied above, so the
real maximum is in the region of 65-80.) The Function FNlist() does two
things. First, it checks the list to see if the string passed in brackets is
already on the list, and adds it if necessary. It then increments the count
by one for that string, and returns this number. So, if a string was not
already on the list, then "1" is returned. The second time you search for
that string, "2" would be returned, as so on. Thus "1" implies "not already
on list", "2" and above implies it was found, the number being the total
number of times it was searched for, including the very first time.
Obviously, a list as short as 100 doesn't take long to scan from top to
bottom anyway, but with much larger lists it's a different story. This
Function takes no more time to search in a list 1000 long as it does one 100
long, and a 10-character string takes only about 6/100 of a second to check
for on a Master.
10as%=100:DIMlist$(as%),list%(as%)
20REPEAT:INPUT"Type in a string "s$
30PRINT"Searched ";FNlist(s$);" times"
40UNTILFALSE
50:
100DEFFNlist(n$):LOCALh%,j%
110FORj%=1TOLEN(n$):h%=h%+j%*ASC(MID$(n$,j%,1)):NEXT
120h%=RND(-h%):h%=RND(2):h%=RND(as%)-1
130REPEAT:h%=(h%MODas%)+1:UNTILlist$(h%)=""ORlist$(h%)=n$
140list$(h%)=n$:list%(h%)=list%(h%)+1
150=list%(h%)
188. Master/Arc scroll quirk
This tip applies to a Master/Compact and the Archimedes, but it has a nasty
'twist' on the Arc in particular.
If you set *CONFIGURE NOSCROLL, ie enable the scroll-protect option, and
print a character on the last position (column) of a line on the screen, a
LineFeed is not generated in the usual way. Instead, the cursor sits under
the last character on the line until you print another character, in which
case it moves down to the next line as normal. When the cursor is 'hanging'
in this way, it returns a POS of 20/40/80 etc. depending on the screenmode,
rather than 0 or 19/39/79 etc.. As soon as another character is printed, POS
becomes 1 (not 0) as the cursor has moved down onto the next line.
This can produce some strange results on programs written under the
assumption that the cursor behaves as on a BBC B and B+. The cure is to set
*CONFIGURE SCROLL, ie scroll protect is disabled.
OK, now the booby-trap for Arc-lovers. You may have disabled the scroll
protect on your Arc, but the desktop enables it again when called up, and it
stays on. Thus when you run a program after using the desktop, the scroll
protect is enabled whether you like it or not!
On both machines, using VDU23,16| once in a program will disable the scroll
protect, and VDU23,16,1| will enable it; problem solved. (Note the "|".)
Just for fun, load any BASIC program, and then try LISTing it after first
typing VDU23,16,n| , where n is 2/3/4 etc.. The results are MOST
entertaining!
189. Master/Compact/ARC printer ignore character
On the Master/Compact, if you configure the machine to send LFs to the
printer with the command *CONFIGURE IGNORE, the previous ignore character is
stored, though not active. If this previous character is 10 for example, some
applications like InterWord will fail to send LFs because they read the
character value with OSBYTE &F6, but don't check to see it the character is
active with OSBYTE &B6. I had to use the command *FX6,0 in the !BOOT file to
overcome this, until I realised what the root cause was.
You can avoid this problem by typing the following commands, followed by
<CTRL+BREAK>...
*CO. IGNORE 0 (Set ignore character to zero)
*CO. IGNORE (Deactivate ignore character)
On the Archimedes, typing *CO. IGNORE also sets the character to zero, which
is sensible, but the !Configure utility on the Applications-1 disc does allow
you to leave the character set to 10, though deactivated. If using this
utility, I advise setting the ignore character value to zero as well as
toggling the little asterisk off.
The PC emulator (and 512 board) sends LFs anyway, so I advise against setting
auto linefeeds on the printer. I curse the day Acorn chose *FX6,10 as the
default on the model B; Think of all the hassle it has caused over the years!
190. Rescuing files with "E" attribute on ADFS
I recently made a serious error. I intended to set the file attributes of a
whole directory of InterWord files to "RL", using *ACCESS RL as usual. In a
moment of carelessness, my finger missed the "R" key and hit the "E" instead;
what a calamity! Once a file has the "E" attribute set, you cannot change it
back again using the *ACCESS command. The file can only be executed, not
LOADed or changed in any way. I was unable even to load my files into
InterWord, as I got a spurious "File too long!" error message when I tried.
I was more than a little dismayed, as although I had backup copies, they were
not 100% up to date. I remembered reading in a magazine that it was possible
to 'rescue' the files using a disc sector editor, but I couldn't find any
trace of the article. I had no option but to figure it out for myself, and
happily I was successful, after a bit of 'safe' fiddling about with a spare
backup copy of the affected disc. Here's what to do:
First, you need a disc sector editor, and I thoroughly recommend the one
contained in the Advanced Disc Toolkit (ADT). Make a backup of the affected
disc, as you cannot copy individual "E" files, and work on this disc, NOT
the original! Next, you need to know the sector number of the catalogue
containing the affected file(s). If it is the Root ($) directory, then it is
always sector 2 (&02), ie track 0 sector 2. If it not the root directory,
then move to the parent of that directory, ie the directory containing the
directory containing the affected file. Eg if an affected file is called
$.MYPROGS.FUN.DUMMY, then move to the $.MYPROGS directory. Type *INFO
<DirectoryName>, where <DirectoryName> is the name of the directory
containing the affected files, eg FUN in the example above. The result will
be the 2-digit Hex sector number you need.
Now enter the sector editor at the appropriate sector number, eg DEX 2 for
the Root and DEX nn in the case of another directory if using the ADT. It is
best to enter from an 80-column mode if possible, to avoid having to carry
out scrolling to 'see' the whole sector. You will see the start of the
catalogue for the directory containing the affected file. Now simply step
through it and the next few sectors until you see the affected filename.
Count along the filename to the 5th character from the start, eg "Y" if the
filename was "DUMMY". If the filename is LESS than 5 characters, you must
still look at whatever is in that 5th position. The first Hex digit of this
character should be in the range 0-7, ie the 8th bit is set to 0, but when
the "E" attribute is set, the 8th bit is set to 1, so the first digit is in
the range 8-F. For example, the "Y" of "DUMMY" should show as &59, but if
the attribute is "E" then the "Y" will show as &D9 instead. In the case the
ADT, the "Y" still looks normal on the screen, even though the Hex code is
wrong, but it might look different on other editors. If the filename is
shorter than 5 characters, you may often find the 5th character is "&8D",
which is a CR (&0D) with the "E" set.
To get rid of the "E", simply alter the Hex code to the 'normal' value.
Rather than calculate the code and enter in Hex, use the editor in ASCII
mode, (the default with ADT), and overtype the appropriate character, eg "Y" in my example, or just <RETURN> to change &8D to &0D. If that looks ok, then
exit from the editor, saying Yes to any Save option. If you catalogue the
affected directory, and the "E" is still present, DO NOT PANIC, but simply
*MOUNT the disc again, or type *DIR followed by the full directory pathname,
eg *DIR $.MYPROGS.FUN, so as to update the catalogue in memory, as this
isn't necessarily done automatically by the editor. If the "E" has gone, the
final thing to do is set the "WR" attributes, or "RL" etc. as necessary.
If you have to enter values in Hex, the correct code can be found from the
expression PRINT ~'&oldhex' AND &7F, eg for the "Y" in my example type PRINT
~&D9 AND &7F, and the result is &59. If the character is a normal 'visible'
character, such as "Y", then PRINT~ASC"Y" would suffice, but otherwise use
the first expression.
In summary, locate the sector number of the catalogue of the directory
containing the affected file(s). Enter the disc sector editor, locate the
5th character from the start of the filename(s), and overtype it with the
correct character, or enter the correct Hex code, as convenient. The first
digit in Hex should change from 8-F to 0-7. Exit from the editor, saving the
changes, and if the "E" attribute hasn't gone, remount the disc or reselect
the directory with the full pathname.
Although it sounds complicated, after a couple of practice goes on a spare
disc and a dummy file, you can correct an "E" attribute in well under a
minute!
191. Uses of *SRWRITE on Master
The *SRWRITE command is officially for the purpose of moving blocks of main
memory into Sideways RAM slots. The complementary command is *SRREAD. Well,
you can indeed use it in this way, but it can also be used for moving blocks
of data around in main memory. The real advantage of using *SRWRITE is that
apart from being a very simple command, it is very fast indeed. The syntax
takes either of the two forms:-
*SRWRITE <start> <finish> <sideways start> <slot number> or..
*SRWRITE <start> + <length> <sideways start> <slot number>
Note that in fact "finish" is actually the address of the first location
AFTER the last byte to be moved, rather than of the last byte itself.
You could, for example, move up to 16k of screen memory into sideways RAM,
and then move it back again to restore the original screen contents. If you
were using Mode 4, (not Shadow mode), then the command
*SRWRITE 5800 8000 8000 5 will save the screen to bank 5. The command could
also be used in the form *SRWRITE 5800+2800 8000 5 and the result would be
identical. Personally I generally prefer this latter syntax. To restore the
screen contents later, you would use the command *SRREAD with the identical
syntax. There is yet another syntax form for these commands, but I won't go
into them now.
You couldn't save a 20k Mode 0 screen in one RAM bank, but you could save
16k of it, at the beginning, middle or end of the screen memory, or you
could easily split it between two RAM banks, and use the spare 12k for
something else.
If you wished to move the screen memory into a reserved area of main memory,
then you substitute the appropriate address for the final "8000" in the
command examples given, and then the RAM slot number would be a dummy simply
to satisfy the syntax - zero would be as good as any. To move the memory
bank into the screen memory area, you use *SRWRITE again, not *SRREAD, and
interchange the addresses as appropriate. I couldn't move a 16k Mode 4
screen into main memory, as I would have less than 16k free to start with,
so here is an example with an 8k Mode 6 screen, to be stored at address&3000.
*SRWRITE 6000+2000 3000 0 (copy screen memory to address &3000)
*SRWRITE 3000+2000 6000 0 (copy original contents back to screen memory)
alternatively:
*SRWRITE 6000 8000 3000 0 and:
*SRWRITE 3000 5000 6000 0 (See how the above syntax is simpler)
192. *EXEC files on Master
Just a reminder that if you try and *RUN files which have no
sensible execution and/or load addresses, both DFS and ADFS on the Master
will attempt to *EXEC them. Thus if you were running a DFS disc on drive 1,
and wished to boot the disc, (you cannot use <Shift+Break> as it would boot
drive 0), you could simply type *!BOOT instead of *EXEC !BOOT.
This applies to any EXEC files, including *SPOOLed listings. Oh, if the
filename clashes with a ROM command, then you can use *RUN <filename>
instead, but this can be abbreviated to */<filename>. So, these are
equivalent, but the last 2 options avoid clashes with ROMs:-
*MYFILE
*/MYFILE
*RUN MYFILE
193. Making the most of View (1)
Expanding your Macros! by Andrew G8YHI If you need to print a block of text more than once in a document then View
offers you the facility to define it at the beginning and then recall it as and when needed. The idea of this is similar to using a procedure from
within BASIC and the defined text is known as a macro. Each macro is given a
two letter code which can be anything that is not already used by View, so AA
would be fine but CE wouldn't.
To define a macro press <EDIT COMMAND> followed by DM and <RETURN> and then
type in the two letter code; for example AA. Then type in your text making
sure you start on the next line down and include any rulers or commands such
as CE or RJ that you want. When completed move onto the next line down and
press <EDIT COMMAND> followed by EM and <RETURN>. So the start of your
document might look like this;
DM AA
This bit of useful text is a macro.
EM
Wherever you wish to recall the defined text move the cursor to the
appropriate line in your document and press <EDIT COMMAND> AA and then
<RETURN> so that AA now appears in the margin. When the document is printed
wherever AA has been set the text will appear. You can define as many macros
as you wish and might store some on disc to be added to other documents using
the READ command. Scientific formulae using complex sub and super-scripts are
one possibility or perhaps a set of different rulers.
Try out this simple macro technique for yourself and next I will show you how
to use macros with parameters, which makes personalised mail-shots easy.
194. Making the most of VIEW (2) by Andrew G8YHI
Following on from the last tip we can use the macro to make the sending of
standard but personalised letters a little easier. View allows up to 10
parameters to be passed to each macro and within these parameters we can
introduce the words that make each document different. Suppose we wished to
send a number of letters of thanks in which the different wording was the
persons name, their address and the amount of money they had sent. We first
have to define our standard letter as a macro but where each of the
different words or groups of words appear we insert a symbol. Each of these
parameters, as they are known are given symbols from @0, @1 etc ...up to @9
and so our letter might look like this.
DM AA
@0
@1
@2
Dear @3,
Thank you for your kind donation of `@4 in response to my recent
begging letter. The villa in Marbella will do my sick grandmother
the world of good.
Yours sincerely,
EM
We now list the parameters as we wish them to be printed with each parameter
separated by a comma, the macro name (in this case AA) being inserted in the
margin using the EDIT COMMAND key.
AA 1 Sandal Lane,Wakefield,WF4 5AF,Mr Sperry,25.00
AA 24 Ferry Drive,Wakefield,WF5 2AZ,Mr Woolhead,2.00
AA 16 Sunset Boulevard,New York,NY 13245,Mr Lane,0.50
When the documents are printed the parameters will be inserted in the
appropriate positions. All parameters must be entered on one line (which can
be up to 132 chracters long) and if any parameter includes a comma, the
parameter must be enclosed within angle brackets. This is a useful but
limited facility in that although text is inserted, the document is not
reformatted before printing so careful thought has to be given to how each
parameter will affect the final layout. Try it out and next I'll show you
how to make the most of the function keys. de Andrew G8YHI
195. Making the most of VIEW (3) by Andrew G8YHI
One of the nice things about View is that in common with Wordwise+ the most
used editing commands are available from the function keys, either on their
own or in conjunction with SHIFT or CTRL. But unlike Wordwise Plus there is
no mention in the manual of how to program the function keys yourself and
yet the facility is available, albeit after entering *FX228,1 and by using
the function keys in conjunction with CTRL and SHIFT.
The facility is available from both command and edit mode and so might be
used to insert often used phrases. eg *KEY0 COUNT |M or *KEY1 Wakefield BBC
Micro User Group|M
The keys can also be programmed to insert View's stored commands, which
means that some quite complex composite commands can be created. To do this
we need to know the Ascii codes for the View function keys and the characters
for the definitions that will produce them. Placing |! before a character
adds 128 to its Ascii value and a '|' before a character reduces its Ascii
value by 64. As an example the View stored command EDIT COMMAND has an Ascii
code of 164 which corresponds to |!$. The |! adds 128 to the Ascii value of
36 for the $ character which adds up to 164. The codes for all the View
stored commands are set out on the next page.
f0 f1 f2 f3 f4
--------------------------------------------------------------
Delete Next Formatting Justify Insert/
Block Match Overwrite Ctrl
172 |!, 173 |!- 174 |!. 175 |!/ 176 |!0
____________ ____________ ____________ ____________ ____________
Move Swap Margins Delete up Highlight
Block Case to char. 1 Shift
156 |!|\ 157 |!|} 158 |!|^ 159 |!|_ 160 |!
____________ ____________ ____________ ____________ ____________
Format Top Of Bottom Of Delete End Beginning
Text Text Of Line Of Line
140 |!|L 141 |!|M 142 |!|N 143 |!|O 144 |!|P
____________ ____________ ____________ ____________ ____________
f5 f6 f7 f8 f9
--------------------------------------------------------------
Ruler Split Join Mark As
Line Lines Ruler Ctrl
177 |!1 178 |!2 179 |!3 180 |!4
____________ ____________ ____________ ____________ ____________
Highlight Go to Set Edit Delete
2 marker marker Command Command Shift
161 |!! 162 |!" 163 |!# 164 |!$ 165 |!%
____________ ____________ ____________ ____________ ____________
End Of Insert Delete Insert Delete
Line Line Line Character Character
145 |!|Q 146 |!|R 147 |!|S 148 |!|T 149 |!|U
____________ ____________ ____________ ____________ ____________
Other useful commands are;
136 |!|H ESCAPE 137 |!|I RETURN 138 |!|J DELETE
139 |!|K TAB 152 |!|X Left arrow 153 |!|Y Right arrow
154 |!|Z Down arrow 155 |!|[ Up arrow
167 |!' Copy current ruler to cursor
168 |!( SHIFT
169 |!) SHIFT
170 |!* SHIFT
171 |!+ SHIFT < Up Arrow >
Try and work out some useful definitions. Here are a few suggestions to get
you started.
*KEY 0 PO Box65 |!$ RJ |M |M Wakefield |!$ RJ |M |M WF2 6YZ |!$ RJ |M|
( Inserts address, EDIT COMMAND, Right Justify, Next Line etc)
*KEY 1 ...>.............*.......................*.....< |!4 |M|
( Insert ruler details, MARK AS RULER, Next Line )
NOTE:- For 160 (highlight one) the |! is actually |! followed by a space.
Not easy to show!
196. Making the most of VIEW (4)
View has 26 number registers which are labelled A to Z. All of them can be
set from within the document but two are used by View to hold the page
number (P) and number of lines (L). To set a register press <EDIT COMMAND>
and enter SR followed by <RETURN> and then the register and the number you
wish to set it to.
For example
SR A 20 which would set register A to a value of 20
Printing out number register values is achieved by placing their symbols (A
to Z) after either the DH DF CE RJ or LJ commands although they
must be preceded by the symbol.
For example
<EDIT COMMAND> LJ L
would print out the number of lines in the current page
<EDIT COMMAND> DF <RETURN> //Page P//
would print the page number each time a footer is printed.
Instead of a number you can use an expression such as A=A+2, which must be
entered as
SR A A+2
Not the most exciting of the View facilities although the value L (number of
lines) is useful when placed at the bottom of the document and in conjunction
with SCREEN, used to show how many lines of the page are left.
ie SR A 66- L
LJ A where 66 is the page length
Finally if you have a Master then D and T are not available as they are
used for printing the date and time respectively. de Andrew G8YHI
197. Disc hint
If you are using discs that have previously been formatted on a 40-Track
drive, you can sometimes have problems using them on an 80-track drive.
Theoretically, this shouldn't happen, but apparently it does. The cure is to
'wipe' the disc using a bulk eraser electromagnet, or a powerful permanent
magnet, and then reformat it.
This same technique is also useful when saving files onto 40T discs using a
40/80 switchable drive set to 40. If the disc has previously been formatted
and used on a true 40T drive, wipe the disc with a magnet first and reformat
it as 40T on the switchable drive. The files should be copied off this disc
as soon as possible, and then the discs reformatted on a true 40T drive.
198. High-density floppy discs
From time to time, you may come across 5.25" discs referred to as "High
Density". After "Single", "Double" and "Quad" density, you may be fooled into
thinking that "High" density must be a good thing. Think again!
Single, and double density discs, whether single or double-sided, single or
double-density, 40 or 80-Track, tend to be made on much the same production
lines. After testing, the best discs can be certified as 80T (96 tpi)
double-sided double-density, and lesser ones as perhaps single-sided, or
single-density, and so on. Obviously, manufacturers cannot conveniently
arrange exactly the right failure rates to achieve the exact mix of quality
of discs required to satisfy the demand, so quite often discs are of better
quality than officially certified.
Quad density discs tend to be made on separate production lines, and are of
higher quality. Nonetheless, they are basically made of the same materials,
and it would do no harm to use them if they were cheaply available.
High-density discs, on the other hand, are a very different thing altogether.
They are intended for systems which pack 1.2 Mbytes onto one disc, (usually
superior IBM compatibles), and the magnetic material is different. A crude
comparison might be that between ordinary ferric audio cassettes and chrome
cassettes. A much stronger magnetic field is required to magnetise the
material properly, and only drives intended to do this are suitable. They
sense whether the disc is 'ordinary' or high-density, via an extra notch, and
alter the head current accordingly.
What this boils down to in practice, is that High Density discs can be very
unreliable and unpredictable when used with 'ordinary' drives such as one
has connected to a BBC Micro. Frequently, they do not even format properly,
or if they do, funny things happen later. In other words, DO NOT USE THEM!!
The situation with 3.5" discs is similar, though apparently many modern
drives normally used in a double-density mode will happily cope with
high-density discs. This applies to later Arcs, though I am not sure about
the earlier 440s amd 300 series. However since High Density discs are VERY
expensive, there seems little point in finding out!
199. Disc backups
This is a sorry story but also a reminder. During the very hot weather,
someone was working on a Master using the DFS and WORDWISE PLUS, they loaded
a text file into Wordwise to amend and then to save the new version to a
different disc. But unfortunately when they saved the file to the new disc
it also saved the previous disc's catalogue information to the new disc
including the other disc's start of file info, resulting in two files being
split into FOUR. The person concerned unfortunately had not been keeping a
backup copy of the discs but had luckily got printed copies of his files. So
the moral is ALWAYS make backups regularly of your files or the unwanted will
happen one day. Oh, by the way, the apparent reason for this unusual event on
a Master was the heat. The Machine should normally operate at a temp. between
75 and 90 degrees F but was working at well over 100 degrees F!
200. !BOOT & MOSPLUS hint
An interesting command provided by the MOS-PLUS ROM from Dabs Press, is
*CONFIGURE START. If used in a !BOOT file, it can be used as part of a
startup routine for loading one or more sideways ROM images, then doing a
<CTRL+BREAK> followed by loading a menu. It can be done on the Master 128
only, by *BUILDing the following !BOOT file....
1 *CON. START CHAIN "MENU"|M
2 *SRLOAD ATSv31M 8000 4 Q
3 *FX200,2
4 CALL!-4
Note that you can of course use your own choice of ROM in line 2, (I have
just used the new ATS ROM as an example), and your own filename in line 1.
You should include in your menu program the command *CONFIGURE NOSTART in
order to turn the command off when you exit from your menu program. (That's
if you want to; otherwise every time you turn your machine on it will attempt
to load your menu program.)
201. Configuring Escape key
Have you ever wanted to disable <ESCAPE>, or totally clear the BASIC program
in memory if Break is pressed? If you have, then the *FX200 command is what
you want. There are four variations on the command:
Command Action
------- ------
*FX200,0 Enable Escape, do not clear memory
contents on Break (default setting)
*FX200,1 Disable Escape
*FX200,2 Clear memory on pressing Break
*FX200,3 This combines the effects of *FX200,1
and *FX200,2
Don't forget to make sure your program works before you include these
commands in it, otherwise you could lose valuable data, etc.. We hate to see
grown men and women crying!
202. Beeb composite video output
The BBC Micro composite video output (BNC Socket) only gives out a monochrome
signal. This is quite deliberate policy by Acorn, as the RGB output is best
for high-resolution colour, and the absence of colour information on the
composite signal ensures the best possible quality on a monochrome monitor.
However, quite a few people do require a colour composite video output, and
this can be achieved fairly easily. On early model Bs you need to solder a
470pF ceramic capacitor between the emitter of transistor Q9 (BC239) and the
base of Q7 (BC309). These components are located a little to the left, and in
front of, the ASTEC UHF modulator 'can'. This is a very cramped area of the
circuit board, which makes soldering very tricky.
On later Bs, there is provision for soldering this capacitor onto the board
at the position marked C58; if you're lucky the capacitor may already be
fitted. To complete the circuit, you then only need to link the solder pads
marked S39. If you have a circuit diagram, such as the one provided with the
Advanced User Guide, then look at the bottom right corner, just to the left
of the UHF Modulator. The link S39 may be marked as LK39 on the diagram. On
the BBC B+, all you have to do is 'make' link 26 on the main board. I imagine
the link position will be somewhere fairly close to the UHF modulator can.
On the Master 128, you can solder a 470pF ceramic capacitor between the
emitter (right leg) of transistor Q12 and the base (centre leg) of Q13. These
are located between the CV and RGB sockets, and although it is a slightly
delicate soldering job, it is nowhere near as tricky as the equivalent
modification on an early BBC B.
Note:
~~~~~
Since producing this tip, I have been told that the circuit diagram, supplied
with the Watford Master reference Manual, shows that you can apparently
simply 'make' link LK11 on the PCB to get colour on the CV socket.
Whether this is correct, and whether this has always been so right from the
start of the production run of the Master, I cannot say. I don't even know
where this link is, or whether any pins are fitted, or whether it's just a
pair of solder pads on the PCB. However, it's certainly worth looking into
before you start splashing solder all over the PCB!
203. Master/BBC 1772 DFS chip snag
There are two possible FDC (Floppy Disc Controller) chips which may be fitted
to a Master, or to later Acorn DFS upgrade kits for a BBC B. (BBC B DFS
upgrade kits originally used an 8271 chip.) There is the 1770, and the
similar 1772. With the 1772, you can have problems using older drives (mainly
40T ones), or 80T drives when used in 40T mode.
The configuration command *CON. FDRIVE 0 gives 6 milliseconds track-to-track
head-step time on a Master with a 1770 or 1772, whereas *CON. FDRIVE 2 gives
30ms with a 1770 and only 3ms with a 1772! Many older 40T drives are too slow
to step the head at 6ms, so cannot be used at all with a Master fitted with
the 1772. If an older drive fails to work with your Master, no matter how you
configure it, but works on another Master or BBC B/B+, it may be because your
machine has a 1772 fitted. (The Master Compact has a 1772 fitted as standard
I believe.) 80T drives used in 40T mode, (either by being switched or by
fancy software), will not work at 3ms (or possibly not even at 6), as they
have to step twice each time, thus effectively trying to step at 1.5ms! See
the table on the next page for a summary of the timings. The new alternative
MOS ROM for the Master now has additional software delays built-in, and so
can effectively handle step times of 3ms right up to 32 ms with a 1772, and
6ms up to 50ms with a 1770. Better late than never I suppose!
Acorn now fit the 1772 to their official DFS upgrade kits for the BBC B. With
the 8271 and 1770 chips, keeping keyboard links 3/4 'Open' sets the slowest
head-step time, but this is not the case with the 1772. The slowest step time
available with the 1772 is 12ms, and even this may be too fast for some old
40T drives. Here is a list of link settings for the various Acorn DFS chips;
a '0' means 'Open' (OFF) whereas a '1' means 'Closed' (ON). Confusingly,
Acorn appear to have transposed all the '0's and '1's in the 1770/2 DFS User
Guide Addendum 1, and also in the new supplement sheet 0433,080 Issue 1, the
latter kindly supplied to me by Arc Electronics in Wakefield. Trust Acorn!
BBC B MASTER 128
Link 3 Link 4 Step Time *CONFIGURE Step Time
8271 1770 1772 FDRIVE 1770 1772
1 1 4ms 6ms 6ms 0 or 1* 6ms 6ms
0 1 6* 12 12 2 or 3* 30 3
1 0 6 20 2
0 0 24 30 3
* without pre-compensation (ADFS) - seems to make little or no difference.
* Note that the two settings of the links which set 6ms with the 8271 are not
actually identical; the one starred has much longer settle and head load
times, and is therefore effectively slower. I can supply further detailed
information about the practical aspects of setting these links on request.
In summary, a setting of 6ms should be suitable for most modern drives,
including switchable ones. However, older drives may require 12ms or more,
but modern 3.5" drives will operate happily at 3ms, as on the Arc/A3000. Some
modern 80T 5.25" drives will also operate at 3ms, though not when used in 40T
mode. In any case, there seems little point in trying to 'push' 5.25" drives
beyond 6ms, nor 3.5" drives beyond 3ms.
204. Attractive menu boxes for the BBC Master
If, like me, you go green with envy at the attractive menus on the
Archimedes, and would like to produce something similar on your BBC Master,
then this simple routine may go some way towards helping you.
DEFPROCfill produces the patterned background, using VDU23,2 to define the
pattern which GCOL16,1 constructs. After MOVEing to the screen origin, the
whole screen is covered using PLOT 101 (Rectangle Fill). DEFPROCbox just
draws two areas; one in the background colour (in this case black) and one
in the foreground colour (white) with the latter offset a little to the left
and upwards. The screen might be coloured suitably using VDU19,0,5,0,0,0 and
text is best written at the graphics cursor, so a VDU5 and GCOL0,0 (black)
will have to be included. OK not quite an Archimedes, but now at least it's
the screen that's green, (or blue, or ....).
10 REM Smarten up your Master, by Andrew G8YHI
20 MODE128
30 PROCfill
40 PROCbox(40,700,240,1000)
50 END
100 DEFPROCfill
110 VDU23,2,170,85,170,85,170,85,170,85
120 GCOL16,1
130 MOVE0,0:PLOT101,1280,1024
140 ENDPROC
200 DEFPROCbox(left%,bottom%,right%,top%)
210 GCOL0,0
220 VDU25,4,left%;bottom%;:VDU25,101,right%;top%;
230 GCOL0,1
240 VDU25,4,left%10;bottom%+10;:VDU25,101,right%-10;top%+5;
250 ENDPROC
205. Master VIEW/VIEWsheet hint
This applies if you use View or Viewsheet, and your Master normally starts
up in Mode 7, but you use View or Viewsheet in Mode 0 or 3. It is useful to
enter Mode 0 or 3 before starting View or Viewsheet; this helps set them up
correctly to use 80 columns. In Viewsheet you get the correct default Printer
windows, while in View the ruler starts in 80 columns instead of 40. If you
do it after entering View or Viewsheet, you have to correct the ruler in
View, and edit the windows in Viewsheet.
206. Wordwise-Plus string bug
It appears that all versions of Wordwise Plus, up to and including version
1.4F, contain a bug. This prevents strings from being compared correctly
under certain conditions. This affects segment programs, and can cause them
to execute incorrectly for no apparent reason. To see this bug for yourself,
assuming you have Wordwise Plus, try:
CLS
A$=""
B$="ANYTHING"
REPEAT
A$=A$+""
UNTIL B$=B$
PRINT "Bug! Press a key"
x%=GET
This bug affects a number of the Wordwise support ROMs from various people,
so beware. A firm called IFEL of Plymouth on 0752-847286 have a version of
Wordwise Plus called WW+2 for #56-35, which has not got the bug, but does
have a number of nice new features. You can also upgrade from earlier
versions of Wordwise Plus at a reduced price. I do not yet know if this bug
exists in the Arc versions of Wordwise Plus. The WW+2 from IFEL is fully
approved by Computer Concepts.