Unix pages
Home -> UNIX software -> PSF Tools -> Amstrad Font Redefinition -> ALARM.BAS

ALARM.BAS by Pete Gerrard

ALARM.BAS is the last in a series of BASIC tutorials published in Amstrad PCW Magazine in 1990-91. This one was published in the March 1991 edition, pages 19-22 and 42. It replaces the standard character set with one of its own devising.

Notes

The program as written performs a read-modify-write on each character it defines: Line 100 (unnecessarily) reads the character, then lines 110-130 completely replace the bitmap with the new definition, and line 140 writes it back.

The machine-code section is specific to the PCW. Rather than use the XBIOS to switch to the appropriate memory bank, it writes directly to the hardware registers.

As listed, the secondary program (Create) is included twice in the article. Both copies seem to have some errors, so I have included a copy that works successfully. It is also worth noting that the "Going Loco" section where Mr Gerrard imports the .SEQ file written by Create into LocoScript and then exports it as ASCII is entirely pointless — the .SEQ file was already ASCII!

There are also some errors in the final section, where lower-case C is designed as an example. The bitmap is shown correctly, but the resulting DATA statement instead defines this pattern:

........ =  0
........ =  0
...####. = 30
..##.... = 48
...####. = 30
...####. = 30
..##.... = 48
........ =  0

Although the original font was only designed as a PCW 8x8 font, I have created a matching 8x5 font for the Spectrum +3, and this is also included.

Files

Fonts

The ALARM font replaces characters 91-95 ([ \ ] ↑ _) with the four playing card suits and a single-character "10". The Unicode tables in the below fonts have been updated accordingly, though there is no precise equivalent in Unicode for the "10" character.

FontPreviewDownload
Alarm font

Other files

  • ALARM.BAS: The font loader.
  • CREATE.BAS: BASIC program to convert a binary font file to a BASIC listing (as printed in the article).
  • CREFIX.BAS: A version of CREATE.BAS that has been successfully tested.

Article

Here is the original article in full:

Finishing Touches

Pete Gerrard comes to the end of his BASIC diary program saga with joined up writing and an excursion into LocoScript

Regular followers of this series of introductory articles on the Mallard version of the BASIC programming language will have all their patience rewarded this month, for this is the last article in the series.

If you take a glance at the listing you will see that it doesn't contain very much in the way of BASIC program instructions, but that was always my intention for the final article.

You may have idly wondered, from time to time, when you have been looking at the menu from which most of the programs in this series can be loaded, what was meant by the option "Alarm Set".

Was it some sort of clock? A way of flagging entries so that they might be printed on screen in, say, reverse field? Or perhaps a way of warning you whenever there was a birthday or important meeting within the next week?

"Alarm Set" refers to none of these things. The first two would require alterations to all the other programs that have been printed so far, while the last one could easily be achieved by yourself using, possibly, the Display Entry option. The program is on p.22.

Alarm Set is, in fact, a different character set for your PCW, it's name deriving from someone's first impression of it when they saw a screen of text displayed using this new character set. They rather unkindly thought it might be used for some kind of horror adventure game, and christened it the "Alarm" set, and the name has stuck.

As well as being alarming, it was also my aim, when designing the set, to produce a set of characters that had the appearance of being "joined-up", as that would be the sort of writing that I imagine most of us would use when putting entries into an ordinary diary.

The only unfortunate thing about it is that it cannot be printed out, which I leave as an exercise for anyone wanting to do so (not too difficult for 8000 series owners, rather more difficult for 9512 owners). However, I may come back to that at a later date.

When it came to preparing this article, one very important thing had to be done. The program, as it originally stood, read most of its data from a file on disk, and there isn't all that much room left on a standard A drive disk when all the rest of the diary programs are put there.

So I decided that adding yet another file would not be a very bright idea. Consequently the data in the file had to be turned into DATA statements within a program.

One simple way of doing this would be to list the contents of that file on to the printer, and then type them out as DATA statements in the conventional manner. Unfortunately this produces the very real possibility of introducing errors into the proceedings, and therefore there had to be some other way of doing things.

Getting Alarmed

With the aid of LocoScript I achieved success, and you might be interested to know how a wordprocessor came to fit into the scheme of things.

The first step along the way was to create a second file, a sequential one rather than the original random one this time, and this was done by using the small program called Create. Here it comes:

10 OPEN "r",1,"chars.fnt",1:FIELD 1,1 AS z$
15 OPEN "o",2,"chars.seq"
20 FOR q1=32 TO 122:PRINT USING "###";q1;:a$=MID$(STR$(q1-32)*10+1000)+"DATA "+MID$(STR$(q1),2):PRINT " ";FOR i=1 TO 8:GET 1,(q1-1)*i+i:PRINT USING "####";ASC(z$);:a$=a$+","+MID$(STR$(ASC(z$)),2):NEXT i:PRINT
25 PRINT #2,a$
26 NEXT q1
30 CLOSE
50 CLOSE 1:CLOSE 2

The random file opened in line 10 is the original one, the sequential file opened in line 15 is the new one, and line 20 does the donkey work by reading in eight numbers at a time (you'll see why later on) and storing them in the special string a$.

You will note that a$ starts off with a number, a space, the word DATA, another space, and then the number corresponding to the ASCII value of the character that we're currently looking at.

The 8 values for that character are tagged on to a$, and when we reach the end of the data for a character we store it in our sequential file in line 25. Line 26 continues the loop, and lines 30 and 50 go slightly mad by closing the files more times than is absolutely necessary!

Now, having created our sequential file, we can turn to LocoScript.

Going Loco

Having loaded LocoScript 1, I copied the sequential file (now called CHARS.SEQ) from group zero Drive A to group zero Drive M. I then created a dummy LocoScript document called CHARS.ASC, a document that was totally blank and devoice of any characters, and using the Insert Text option I slotted in the sequential file. The result was then saved to Drive M and turned into an ASCII file, and transported back to Group 0 on drive A.

Then it was back to BASIC, and the program that read in the character data from disk. All the disk parts of the program were removed and the rest of it renumbered so that I could now MERGE my ASCII file CHARS.ASC and fit it in at the end of the main listing. The whole program could then be renumbered, and saved as a BASIC program called ALARM.BAS.

Now you can all write in and tell me that there's a much easier way of doing this, but I don't care! At least it worked, and the resulting program works as well, which is the main point of it all.

Save before running

You can run this program on its own, but I'd advise you to save it before attempting to run it, because one of two things might happen. Number one, you've made a mistake somewhere (understandable when typing in huge amounts of data), or number two, the program works sucessfully and chains back to the menu program, thus removing the Alarm program from memory and destroying all your hard work.

When you do run it, a little message will appear at the top of the screen, and a figure will count down from 90 to 0. This is because we are changing the appearance of 91 characters in the standard character set, going from an ASCII value of 32 (a space, which doesn't really need changing) up to an ASCII value of 122, which is lower case Z.

When the count reaches zero the program will chain the menu option, and you will then get your first real chance to see the character set in action.

To get back to the original character set you'll have to re-boot CP/M and BASIC. It was either that or include another 91 data lines and incur the wrath of the editor for making the program immensely long.

If you look at the data lines, you will see that lines 290 to 320 are nothing to do with the characters. These set up a little machine code routine, so I'd advise you to take great care when entering them.

Mistakes are not so important with the character set DATA lines, as the only thing that will happen is that a character might look a little bit peculiar, but a mistake in the machine code part of the program would be a major disaster.

There are only 3 lines of data for the machine code routine, so it shouldn't prove too difficult to get it working correctly. If you want to test it, just enter the BASIC lines 10 to 280 (altering the end of line 40 for the moment so that instead of saying CHAIN "menu it says END instead), and enter DATA statements up to line 340. Then, change line 170 so that it reads FOR i=32 TO 33 instead of FOR i=32 TO 122, and save and then run the program.

Nothing happens

If all is well, nothing will appear to happen. But if you try to print character string 33, which is an exclamation mark, you should now see that it is a little different from its usual appearance. Having got this far successfully, you can now change the FOR ... NEXT loop back to its original format again and type in the rest of the DATA statements.

I would leave line 40 with just END instead of CHAIN "menu until you've got it all typed in, because you don't want to accidentally lose your work when you run the program. Change it back when you're happy that everything is working.

And how do you test that it has indeed worked correctly? Well, when it has finished running and you are back at the OK prompt, try entering this on one line in direct mode, in other words, without putting a program line number first:

FOR i=32 TO 122:PRINT CHR$(i);" ";:NEXT i

This will print out all 91 characters in their new format. If some look somewhat strange, then you can look at the ASCII value and find the listing. Let us suppose that lower case C has come out incorrectly. If you enter PRINT ASC("c") you will get the result 99. Now look for 99 in the DATA statements, and you;ll find it at the start of line 1000.

All the DATA statements run consecutively for each character, from character 32 in line 330 to character 122 in line 1230. Just multiply the ASCII value by 10 and add 10 to find the line number. Alternatively, just look for the ASCII value as the first number after the DATA statement.

When you find the line in question, you can check your version against mine and decide either that you've made a mistake, or you don't like the way I've drawn the character. In which case, change it!

That's the great fun with programs such as this. With the rest of the series you're more or less stuck with what I've given you, but this one can be changed to your heart's content.

Improving one's character

Let us, briefly, consider what is involved in altering one of the characters.

All characters on the PCW screen are designed on an 8 by 8 block basis, so that an exclamation mark might look like this:

...##...
...##...
...##...
...##...
...##...
........
...##...
...##...
........

I won't go into a lesson on hexadecimal numbers, but I will say that you're going to have to get used to numbers 128,64,32,16,8,4,2,1. The first row of the exclamation mark can be turned into (128*0+64*0+32*0+16*1+8*1+4*0+2*0+1*0), which gives a DATA value of 24.

So, wherever you want something to appear, multiply the number by 1, and wherever you want a blank, multiply by zero. An exclamation mark then ends up as the following 8 DATA statements, reading (as always) from top to bottom:

24,24,24,24,0,24,24,0

The two zeroes indicating the two blank lines. So your new lower case C might look like this:

........ =  0
........ =  0
...####. = 30
..##.... = 48
..##.... = 30 
..##.... = 30 
...####. = 48 
........ =  0

The calculation for line three (and the identical line 7) is:

128*0+64*0+32*0+16*1+8*1+4*1+2*1+1*0

And for lines four to six:

128*0+64*0+32*1+16*1+8*0+4*0+2*0+1*0

All of this gives the following DATA statement:

DATA 0,0,30,48,30,30,48,0

Now you could, if the fancy took you, go to line 1000 and alter it to contain the following nine values, the first being the decimal equivalent of ASCII for lower case C:

1000 DATA 99,0,0,30,48,30,30,48,0

Just remember to keep the first number after the DATA statement the same, so that we know which character we're dealing with, and you can alter the rest as much as you like. You won't be harming your PCW, because you can always get back to normal by re-booting CP/M and loading BASIC.

And that, as I keep saying, is that. Oh, apart from one thing. Line 950 in the DATA statements covers... well, I'll let you find out which character. In its original form, the character is designed like this:

950 DATA 94,24,60,126,24,24,24,24,0

This affects one program in the series. It doesn't stop it working, it just affects the screen display. Which one is it? If you keep line 950 as it is, you'll find it somewhere. Have fun, and bye for now!

The Alarm typeface program

10 REM ALARM for HANDY DIARY
20 COMMON date$
30 GOSUB 230:GOSUB 160
40 MEMORY &HF605:CHAIN "menu
50 c=&HC070
60 GOSUB 90
70 MEMORY &HF4F7
80 RETURN
90 POKE &HC099,i
100 POKE &HC089,0:CALL c:POKE &HC089,&HEB
110 FOR j=1 TO 8
120 READ a:POKE &HC099+j,a
130 NEXT
140 CALL c
150 RETURN
160 PRINT CHR$(27)+"E"+CHR$(27)+"H":PRINT "Creating the Alarm Set ... counting down to zero"
170 FOR i=32 TO 122:READ cn:ok=FRE(""):PRINT CHR$(27)+"Y"+CHR$(34)+CHR$(32);:PRINT USING "###";122-cn
180 i$=MID$(STR$(i),2)
190 MEMORY &HBFFE
200 GOSUB 50
210 NEXT i
220 RETURN
230 MEMORY &HBFFE
240 FOR i=&HC070 TO &HC098
250 READ d8
260 POKE i,d8
270 NEXT
280 RETURN
290 DATA 243,62,129,211,241,62,130,211,242,175,95,103
300 DATA 22,184,58,153,192,111,41,41,41,25,17,154
310 DATA 192,235,1,8,0,237,176,62,133,211,241,62
320 DATA 134,211,242,251,201
330 DATA 32,0,0,0,0,0,0,0,0
340 DATA 33,12,12,12,24,24,0,24,0
350 DATA 34,54,108,108,0,0,0,0,0
360 DATA 35,108,108,254,108,254,108,108,0
370 DATA 36,12,31,44,30,26,124,24,0
380 DATA 37,0,198,204,24,48,102,198,0
390 DATA 38,56,108,56,118,220,204,118,0
400 DATA 39,24,24,24,0,0,0,0,0
410 DATA 40,6,12,24,48,48,24,12,0
420 DATA 41,24,12,6,6,12,24,48,0
430 DATA 42,0,51,30,127,60,102,0,0
440 DATA 43,0,12,12,63,24,24,0,0
450 DATA 44,0,0,0,0,0,24,24,48
460 DATA 45,0,0,0,126,0,0,0,0
470 DATA 46,0,0,0,0,0,12,24,0
480 DATA 47,3,6,12,24,48,96,192,0
490 DATA 48,28,54,103,222,230,108,56,0
500 DATA 49,12,28,12,12,24,24,126,0
510 DATA 50,30,51,3,62,96,102,126,0
520 DATA 51,30,51,6,28,6,102,60,0
530 DATA 52,14,30,54,108,254,12,30,0
540 DATA 53,63,49,48,60,6,102,60,0
550 DATA 54,30,51,48,124,102,102,60,0
560 DATA 55,63,51,6,12,24,24,24,0
570 DATA 56,30,51,51,62,102,102,60,0
580 DATA 57,30,51,51,30,6,102,60,0
590 DATA 58,0,0,12,12,0,24,24,0
600 DATA 59,0,0,12,12,0,24,24,48
610 DATA 60,6,12,24,48,48,24,12,0
620 DATA 61,0,0,63,0,252,0,0,0
630 DATA 62,48,24,12,12,24,48,96,0
640 DATA 63,30,51,54,12,24,0,24,0
650 DATA 64,124,198,222,222,222,192,124,0
660 DATA 65,12,30,50,100,124,100,100,0
670 DATA 66,126,50,52,124,102,102,252,0
680 DATA 67,30,51,96,192,192,102,60,0
690 DATA 68,126,50,100,100,100,104,248,0
700 DATA 69,126,50,52,120,104,98,254,0
710 DATA 70,127,49,52,120,104,96,240,0
720 DATA 71,30,51,96,192,206,102,62,0
730 DATA 72,50,50,50,124,100,100,100,0
740 DATA 73,63,8,8,24,24,24,126,0
750 DATA 74,15,6,6,12,204,204,120,0
760 DATA 75,114,50,52,60,108,102,230,0
770 DATA 76,120,48,48,96,96,100,252,0
780 DATA 77,98,118,126,252,212,196,196,0
790 DATA 78,98,114,122,220,204,196,196,0
800 DATA 79,62,98,98,196,196,196,124,0
810 DATA 80,126,50,50,62,96,96,240,0
820 DATA 81,62,98,98,196,216,204,118,0
830 DATA 82,126,50,50,62,108,102,230,0
840 DATA 83,30,50,48,30,6,102,60,0
850 DATA 84,63,45,12,24,24,24,60,0
860 DATA 85,50,50,50,100,100,100,60,0
870 DATA 86,50,50,50,100,100,56,24,0
880 DATA 87,98,98,98,212,252,236,196,0
890 DATA 88,98,52,24,56,104,196,196,0
900 DATA 89,50,50,50,60,24,24,60,0
910 DATA 90,127,98,68,28,50,102,254,0
920 DATA 91,24,60,126,255,126,60,24,0
930 DATA 92,24,24,102,102,24,24,60,0
940 DATA 93,54,127,127,127,62,28,8,0
950 DATA 94,24,60,126,126,126,24,60,0
960 DATA 95,70,201,75,75,77,73,230,0
970 DATA 96,48,24,12,0,0,0,0,0
980 DATA 97,0,0,60,102,68,205,247,0
990 DATA 98,112,48,62,102,102,231,220,0
1000 DATA 99,0,0,30,51,48,231,189,0
1010 DATA 100,14,6,62,102,204,205,119,0
1020 DATA 101,0,0,30,51,126,225,62,0
1030 DATA 102,15,25,25,51,54,255,49,48
1040 DATA 103,0,0,31,51,51,223,102,252
1050 DATA 104,112,48,62,51,102,231,102,0
1060 DATA 105,12,0,24,24,24,153,102,0
1070 DATA 106,3,0,7,3,3,199,102,60
1080 DATA 107,112,48,51,54,120,237,231,0
1090 DATA 108,14,22,22,12,24,60,231,0
1100 DATA 109,0,0,54,127,207,215,199,0
1110 DATA 110,0,0,110,51,51,227,198,0
1120 DATA 111,0,0,30,51,102,231,60,20
1130 DATA 112,0,0,110,51,115,191,48,96
1140 DATA 113,0,0,59,102,102,191,205,30
1150 DATA 114,0,0,110,59,51,227,96,0
1160 DATA 115,0,0,30,48,254,131,60,0
1170 DATA 116,24,24,62,24,48,247,221,0
1180 DATA 117,0,0,51,51,102,231,60,0
1190 DATA 118,0,0,51,51,51,253,153,0
1200 DATA 119,0,0,99,107,107,255,109,0
1210 DATA 120,0,0,99,54,28,237,199,0
1220 DATA 121,0,0,51,51,115,223,150,28
1230 DATA 122,0,0,62,68,136,17,62,0

John Elliott 2020-12-21