Classic Computer Magazine Archive COMPUTE! ISSUE 76 / SEPTEMBER 1986 / PAGE 65

PowerKey for Apple

Patrick Parrish, Programming Supervisor

This valuable utility puts 52 customized strings or keywords instantly at your fingertips. You can even create several sets of custom commands for use with different applications. For all Apple II series computers with DOS 3.3 or ProDOS.


Using an Apple II computer usually involves a considerable amount of typing, and most of usógood typists or notówould be happy to automate the process of communicating with our machine. Have you ever wished you could just strike one key and produce a directory, run a program, or perform some common task?

"PowerKey" provides a selection of 52 different one-touch keywords which you can customize to your own liking. It lets you access up to 52 keywords or other strings of your own by pressing either the Open Apple or Solid Apple key (or paddle buttons for those who have an Apple II+, which lacks these keys) along with one of the letter keys (A-Z). Although the program relies on a short machine language routine, you can use it without understanding machine language at all.

Entering The Program

This utility is written in three parts. Program 1, POWERKEY.CUSTOM, is a BASIC program that lets you create and save tables of your custom strings or keywords to disk. Program 2, POWERKEY.LOADER, is a BASIC loader which POKEs the machine language driver routine into memory and saves a copy of this code to disk in the form of a binary file. (Since Program 2 uses the name POWERKEY.BINARY for the file it creates, you must not use that name for Program 2 itself. If you do, you'll get a FILE TYPE MISMATCH error when Program 2 is run.) Program 3, POWERKEY.SYSTEM, is a short BASIC program which loads both the keyword table and the driver routine, and then activates PowerKey. Before going any further, carefully type in these three programs and save a copy of each to disk.

Creating Customized Keys

After entering Programs 1-3, load and run Program 1, which creates a customized table of keywords and strings. The first prompt asks if you want to load a keyword table from disk. Since this is the first time you've run the program, no tables yet exist, so you should press N for no. In the future, after creating one or more tables, you could also press Y to gain access to a preexisting table. If you press Y, the program displays a directory and asks you to enter the filename of the table to load. If you press RETURN at this prompt without entering a name, PowerKey looks for a default file named TABLE.

If you've specified that no keyword table is to be loaded, Program 1 reads in its 52 default keywords (see lines 910-960). The first 26 keywords can be accessed with the Open Apple key (or the paddle 0 button), and the second 26 keywords by the Solid Apple key (or the paddle 1 button). You can change or rearrange the keywords in the DATA statements if you like, but make sure not to add or delete any keywords. You'll get an OUT OF DATA error if there aren't at least 52 DATA items.

Now PowerKey displays keywords 1-26 on the screen. To the left of each keyword is the letter that will access it. For instance, the keyword AND is represented by A. Each keyword or string in the table can be up to 16 characters long, but they can be combined for longer commands. A table can occupy a maximum of 832 bytes and unused characters are signified by dots.

At the bottom of the screen, you are given three options. You can press A to Alter a keyword, the Solid Apple key (or paddle 1 button) to look at the second 26-keyword set, or W to write the completed table to a disk file. You can switch back and forth between keyword sets by pressing the Solid Apple key (or paddle 1 button) and Open Apple key (or paddle 0 button).

For practice, let's change CATALOG, the current default keyword accessed with Open Apple-C. Select the Open Apple keyword set, then press A and the program prompts you for the letter of the keyword you wish to change. Enter C for the keyword CATALOG. Let's add a carriage return to this keyword so that you'll be able to examine the disk directory from immediate mode with only one keystroke. Type CATALOG followed by a backslash ( \), then press RETURN. The backslash always stands for a carriage return character.

The screen should now reflect the change you've made. Notice that the backslash is shown as a control character (CTRL-M is equivalent to RETURN). Other keywords or strings in the table can be altered in the same manner. In fact, if you anticipate repeatedly using a phrase longer than 16 characters in your programming, stretch it out over two or more 16-character strings.

Once the table suits you, press W (for Write) to save it to disk. At this point, the 52 strings in your table are converted to their ASCII equivalents and POKEd into memory at 37376. To distinguish a string from the one that follows, the last character of each string has its high bit set (128 is added to its ASCII value). Before the program saves the table, you are allowed once more to look at the directory on the target disk. After this, a filename for your table is requested. Again, if you strike RETURN, the default filename TABLE is chosen for you. Before the program ends, you are given a chance to put a copy of this file on other disks as well.

Installing The Driver

With the keyword table safely on disk as well as in memory, run Program 2. Line 110 of this program POKEs the PowerKey ML driver routine into memory at 768. This area is safe from BASIC, so PowerKey should not interfere with, or be overwritten by, most programs. Line 130 saves a copy to disk using the filename POWERKEY.BINARY.

PowerKey is now ready to be activated. Type CALL -768 and press RETURN. Then, press Open Apple (or paddle button 0) along with the A key. The keyword AND should appear on the screen. Press RETURN and try another one. Hit Open Apple and C for CATALOG. Immediately, a directory of your disk appears on the screen (recall that we added a carriage return to CATALOG).

Try out some more keywords, using the Solid Apple (paddle button 1) set as well. The computer recognizes your keywords and strings from immediate and program mode as well as from the monitor.

Putting It All Together

Because PowerKey is on your disk as a binary file, it can easily be loaded and run by other programs. In fact, this is just what Program 3 does. It sets HIMEM to protect the reserve space for the keyword table, then asks you to specify the name of the table to be loaded from disk (press RETURN alone at the prompt to load the default file TABLE). The POWERKEY.BINARY machine language file created by Program 2 is loaded into memory, and activated with the appropriate CALL. You can even have PowerKey automatically loaded when you boot your disk if you use DOS 3.3. Simply save Program 3 as the HELLO file on the desired disk.

You can also load PowerKey from immediate mode. With DOS 3.3, type in the following line (substitute the appropriate table filename for TABLE):

HIMEM:37376:PRINT CHR$(4)"BLOAD TABLE,A37376":PRINT CHR$(4)"BLOAD POWERKEY.BINARY":CALL 768

If you are using ProDOS, substitute this line:

HIMEM:36352:PRINT CHR$(4)"BLOAD TABLE,A37376":PRINT CHR$(4)"BLOAD POWERKEY.BINARY":CALL 768

How It Works

PowerKey works basically the same whether you are using DOS 3.3 or ProDOS. In either operating system, it relies on a method known as a wedge. The input vector that normally points to the keyboard input subroutine (KEYIN) at $FD1B, is rerouted to point instead to the starting location of our machine language code. Once this is done, the program checks a flag to see whether it is already in the process of printing a keyword. If not, it checks the Open and Solid Apple keys. The routine also responds to paddle button presses, since the Open and Solid Apple keys are read by the same circuitry that reads the buttons.

If one of the special keys is pressed, PowerKey begins printing the one-touch keyword. First, the relative number (0-51) of the desired keyword is determined, a flag is set, and the keyword is located in the table. The first character of the word is then put in the accumulator, the table location is updated, and we return to BASIC. The operating system then prints the character in the accumulator and returns to the program for another character. The next time through the program, another character is loaded into the accumulator since the flag is set. This process continues until the last character of the keyword or phrase is detected (this character has the high bit set). The flag is then set to zero and we're returned to BASIC.

Before all this can happen, however, the program must go through a short initialization routine to determine which operating system is installed. This is done by looking at the starting location for ProDOS's global page ($BF). When ProDOS has been booted, the value in location $BF00 is always 76 (representing the JMP command). If this is the case, then the vector that points to KEYIN (CHINI at $BE32-$BE33) is loaded in low-byte/high-byte format with the starting address for our routine, and the program returns to BASIC.

If the value at $BF00 is some other value, then the program assumes we are in DOS 3.3. In this case, the input vectors (KSW for KeySWitch) at $38-$39, which normally point to KEYIN, are loaded in a likewise manner with the starting address of our program. We then jump to a routine at $3EA which updates the input pointers with these new values, reconnects DOS, and returns us to BASIC. Henceforth, with either operating system, our routine gets called so we can print our keywords.

Program 1: Keyword Table Customizer

For instructions on entering these listings, please refer to "COMPUTE!'s Guide to Typing In Programs" in this issue of COMPUTE!.

FC 100 REM POWERKEY.CUSTOM
C6 110 TEXT:TL=37376
9A 120 HIMEM:TL:IF PEEK(48896)=76 THEN HIMEM:TL-1024:REM TL IS TABLE LOCATION;
       IF PRODOS, HIMEM IS MOVED DOWN 1K MORE
2B 130 FOR I=768 TO 777:READ A:POKE I,A:NEXT:
       DATA 104,168,104,166,223,154,72,152,72,96: REM ONERR FIX
09 140 DIM A$(52):F$= "................":R$(0)="OPEN-APPLE":R$(1)="SOLID-APPLE":
       P=0:REM APPLE KEYS CORRESPOND TO PADDLE BUTTONS
D5 150 HOME:HTAB 11:VTAB 6:INVERSE:PRINT "KEYWORD CUSTOMIZER":NORMAL
C1 160 VTAB 10:PRINT "WANT TO LOAD A TABLE FROM DISK";:GOSUB 790
F9 170 IF X<>89 THEN 200
55 180 GOSUB 830
E7 190 W=0:V=13:GOSUB 480:GOTO 210
7F 200 FOR I=1 TO 52:READ A$(I):NEXT
4C 210 GOSUB 280
5D 220 X=PEEK(-16384):Y=PEEK(-16287):Z=PEEK(-16286):IF X<=127 AND Y<=127 AND Z<=127 THEN 220
5A 230 POKE -16368,0:X=X-128:IF X=87 THEN 570
94 240 IF Z>127 AND P=0 THEN P=1:GOTO 210
B6 250 IF Y>127 AND P=1 THEN P=0:GOTO 210
9D 260 IF X=65 THEN 360
1C 270 GOTO 220
30 280 HOME:VTAB 2:HTAB 11:INVERSE:PRINT R$(P);:NORMAL:PRINT " KEYWORDS:":PRINT
9A 290 PRINT:L=1:H=13:FOR J=1 TO 22 STEP 21:FOR I=L TO H:INVERSE:HTAB J:
       PRINT CHR$(64+I);:NORMAL:PRINT " ";
C4 300 D$=A$(I+(P=1)*26):FOR Z=1 TO LEN(D$):X=ASC(MID$(D$,Z,1)):
       IF X<32 THEN INVERSE:PRINT CHR$(X+64);:NORMAL:GOTO 320
98 310 PRINT CHR$(X);
5A 320 NEXT Z:PRINT MID$(F$,1,16-LEN(A$(I+(P=1)*26))):NEXT:L=14:H=26:VTAB 5:NEXT
FA 330 VTAB 20:PRINT "PRESS: ";:INVERSE:PRINT "A";:NORMAL:PRINT " TO ";:INVERSE:
       PRINT "ALTER";:NORMAL:PRINT " A KEYWORD,"
BA 340 VTAB 21:HTAB 8:INVERSE:PRINT R$(P=0);:NORMAL:PRINT " FOR ";:INVERSE:
       PRINT R$(P=0);:NORMAL:PRINT " SET,":HTAB 8:INVERSE:PRINT "W";:NORMAL:
       PRINT " TO ";:INVERSE:PRINT "WRITE";:NORMAL:PRINT " TABLE TO DISK."
1F 341 RETURN
68 350 REM INPUT KEYWORD
91 360 VTAB 20:HTAB 28:PRINT " ":HTAB 8:PRINT "{32 SPACE}": HTAB 8:PRINT "{32 SPACE}"
28 370 VTAB 20:PRINT "ENTER KEY(A-Z) TO CHANGE ";:INPUT L$:L=ASC(L$)-64:
       IF L<0 OR L>26 OR LEN(L$)>1 THEN 370
71 380 VTAB 22:PRINT "NEW KEYWORD FOR ";:INVERSE:PRINT L$;:NORMAL:PRINT " ?";:PRINT F$
80 390 VTAB 24:PRINT "('\' WILL EMBED A CARRIAGE RETURN)";:HTAB 20:VTAB 22:C=0:D$=""
C7 400 X=PEEK(-16384):IF X<=127 THEN 400
5B 410 POKE -16368,0:X=X-128:IF X=13 THEN 460
B0 420 IF X=92 THEN X=13
09 430 C=C+1:D$=D$+CHR$(X):IF X<32 THEN INVERSE:PRINT CHR$(X+64);:NORMAL:GOTO 450
9F 440 PRINT CHR$(X);
D7 450 IF C<16 THEN 400
B8 460 A$(L+(P=1)*26)=D$:FOR I=1 TO 400:NEXT:GOTO 210
92 470 REM LOAD TABLE
C2 480 ONERR GOTO 750
47 490 HOME:HTAB 6:VTAB 10:GOSUB 690:PRINT:PRINT CHR$(4)"BLOAD "FL$:POKE 216,0
57 500 VTAB 16:HTAB 10:PRINT "READING TABLE..."
74 510 C=0:FOR I=1 TO 52:EF=0
E9 520 A=PEEK(TL+C):IF A>127 THEN A=A-128:EF=1
3E 530 A$(I)=A$(I)+CHR$(A):C=C+1:IF EF THEN NEXT I
37 540 IF I<53 THEN 520
1F 550 RETURN
63 560 REM SAVE TABLE
EF 570 HOME:VTAB 7:HTAB 9:NORMAL:PRINT "...SETTING UP TABLE"
2F 580 C=0:A=0:FOR I=1 TO 52:C=C+A:A=LEN(A$(I)):FOR J=1 TO A-1
2E 590 G=ASC(MID$(A$(I),J,1))::IF G=92 THEN G=13
EA 600 POKE TL+C+J-1,G:NEXT J
6D 610 B=ASC(RIGHT$(A$(I),1))+128:IF B=220 THEN B=141
19 620 POKE TL+C+A-1,B:NEXT I
54 630 VTAB 10:HTAB 6:PRINT "READY TO SAVE TABLE TO DISK.":GOSUB 830:W=1:HOME
BC 640 ONERR GOTO 750
B1 650 VTAB 10:HTAB 6:V=13:GOSUB 690:PRINT:PRINT CHR$(4)"BSAVE "FL$",A"
       STR$(TL)",L832":POKE 216,0
55 660 VTAB 16:HTAB 6:PRINT "ANOTHER COPY";:GOSUB 790
F8 670 IF X=89 THEN HOME:GOTO 640
9E 680 END
58 690 PRINT "TABLE FILENAME: ";:INPUT FL$:IF FL$="" THEN FL$="TABLE"
CA 700 VTAB V:PRINT "PUT PROPER DISK IN DRIVE & HIT <RETURN>.";
0E 710 X=PEEK(-16384):IF X<=127 THEN 710
2E 720 POKE -16368,0:X=X-128:IF X<>13 THEN 710
1D 730 RETURN
C7 740 REM DISK ERROR ROUTINE
9F 750 PRINT:HTAB 8:PRINT "DISK ERROR #" STR$(PEEK(222))"."
FD 760 CALL 768:VTAB 18:VTAB 20:HTAB 8:PRINT "TYPE 'C' TO CONTINUE";:GET S$:IF W=0 THEN 480
42 770 IF W=1 THEN HOME:GOTO 640
1B 780 HOME:V=15:GOTO 840
DD 790 PRINT " (";:INVERSE:PRINT "Y";:NORMAL:PRINT"/";:INVERSE:PRINT "N";:NORMAL:PRINT ")?"
CC 800 X=PEEK(-16384):IF X<=127 THEN 800
25 810 GET S$:POKE -16368,0:X=X-128:IF X<>78 AND X<>89 THEN 800
1C 820 RETURN
11 830 V=16:VTAB 13:PRINT "NEED A LOOK AT THE CATALOG FIRST";:GOSUB 790:IF X=78 THEN RETURN
22 840 W=2:ONERR GOTO 750
4F 850 GOSUB 700
B6 860 POKE 34,0:HOME:HTAB 12:PRINT "DISK CATALOG:":HTAB 8:PRINT "{20 -}"
DE 870 POKE 34,2:PRINT:PRINT CHR$(4)"CATALOG":POKE 216,0
76 880 HTAB 8:PRINT:PRINT "CATALOG ANOTHER DISK";:GOSUB 790:IF X=89 THEN V=23:GOTO 850
33 890 PRINT:PRINT "PRESS RETURN TO CONTINUE":GOSUB 710
43 900 POKE 34,0:RETURN
C5 910 REM PADDLE 0 OR OPEN APPLE KEY WORDS
90 920 DATA AND,BLOAD ,CATALOG,DATA ,END,FOR,GOSUB,HOME,INPUT,GET,READ,LOAD ,MID$(
A3 930 DATA NEXT,OR,PRINT,STOP,RUN ,SAVE ,THEN,TEXT,VTAB,WRITE,PEEK,REM,CONT
26 940 REM PADDLE 1 OR CLOSED APPLE KEY WORDS
02 950 DATA ASC(,BRUN ,CLOSE,DEL,DIM,FLASH,GOTO,HTAB,INVERSE,RESTORE,NORMAL,LIST
FA 960 DATA LEFT$(,NEW,OPEN,POKE,RIGHT$(,RETURN,STR$(,STEP,TAB(,VERIFY,INT(,CALL,LEN(,CLEAR

Program 2:PowerKey Binary File Creator

17 100 REM POWERKEY.LOADER
D3 110 FOR I=768 TO 939:READ A:POKE I,A:X=X+A:NEXT
A2 120 IF X<>18010 THEN PRINT "ERROR IN DATA STATEMENTS.":STOP
DF 130 PRINT CHR$(4)"BSAVE POWERKEY.BINARY,A768,L172"
81 140 DATA 162,146,134,7,160,0,132,6
A4 150 DATA 162,33,160,3,173,0,191,201
06 160 DATA 76,208,7,142,50,190,140,51
1F 170 DATA 190,96,134,56,132,57,76,234
1A 180 DATA 3,44,169,3,48,94,32,27
28 190 DATA 253,72,32,74,255,173,97,192
A3 200 DATA 16,7,169,0,141,170,3,240
FA 210 DATA 10,173,98,192,16,65,169,26
F7 220 DATA 141,170,3,104,56,233,193,48
C1 230 DATA 55,201,26,176,51,24,109,170
4A 240 DATA 3,141,170,3,169,255,141,169
F9 250 DATA 3,173,170,3,240,38,160,0
F4 260 DATA 162,0,230,6,208,2,230,7
91 270 DATA 177,6,48,2,16,244,232,236
1D 280 DATA 170,3,208,238,32,63,255,230
DB 290 DATA 6,208,9,230,7,208,5,104
0F 300 DATA 32,63,255,96,160,0,177,6
6C 310 DATA 141,171,3,230,6,208,2,230
88 320 DATA 7,173,171,3,48,4,24,105
57 330 DATA 128,96,169,0,141,169,3,133
23 340 DATA 6,169,146,133,7,173,171,3
11 350 DATA 96,0,0,0

Program 3: PowerKey Loader

B8 100 REM POWERKEY.SYSTEM
C6 110 TEXT:TL=37376
1A 120 HIMEM:TL:IF PEEK(48896)=76 THEN HIMEM:TL-1024
AA 130 HOME:PRINT "ENTER KEYWORD TABLE NAME";:INPUT N$:IF N$="" THEN N$="TABLE"
A5 140 PRINT CHR$(4)"BLOAD "N$",A" STR$(TL)
E5 150 PRINT CHR$(4)"BLOAD POWERKEY.BINARY"
68 160 CALL 768:PRINT:PRINT "POWERKEY IS ACTIVATED.":END