Maya Grab [Day 7] – Custom input routine

Before doing anything today I wanted to write couple of commands to setup the screen and print available basic memory. And there I’ve encountered the first problem – my already defined variable names. If names are longer then 2 characters, conflicts can happen like described here.

10 GCB=12: GCF=0
20 PRINT GCB: PRINT GCF

Like shown on the first screenshot, this program will output for both variables 0, even if GCB is defined as 12. It took me quite some time to figure out that this is caused how the C64 is storing variable names. To be sure that every value is stored ok, I’ve redefined all variable names to max. two characters and added one more, that I’ve forgot, for counting player progress in the game.

10500 :
10505 REM – INIT SCREEN —————
10510 :
10515 PRINT CHR$(147)
10520 POKE 53280,CB: POKE 53281,CF
10525 RETURN

This is the routine for setting up the screen. I’m first printing a character with the ASCII code 147 which is for clearing the screen. Then I’m writing our predefined border color to address 53280 and foreground color to address 53281. Since I’m going to change the colors only once, I’m not going to keep those addresses in separate variables.

19500 :
19505 REM – PRINT FREE MEMORY ———
19510 :
19515 PRINT FRE(0)65536*(FRE(0)<0)
19520 END

Not sure how this work, I’ve found it on the internet. The FRE command outputs free bytes and the rest is just for normalizing negative numbers.

Now finally we’re going to checkout the routine how user input is read. On the C64 that could be easily achieved by simply typing this:

INPUT A$

The code waits for the user to type something and press the RETURN key. After that the string (in this case) is stored into variable A$. The problem with this command is that we don’t know which keys the user is pressing before pressing the RETURN key. Meaning, the user can press anything, for example characters that we want to filter out or keys for moving the cursor; therefore he can alter the screen contents and make a complete mess.

Solution for this is to make a custom input routine with the command GET, which waits for only one key to be pressed. Then we can check if we’re going to accept this key or just ignore it and wait for the next one until RETURN is pressed. Here’s the code:

14500 :
14505 REM – WAIT FOR INPUT ————
14510 :
14515 A$=“”: X$=“”: Y$=” “
14520 A=402LEN(“? “)
14525 PRINT “? “;
14530 POKE 204,0
14535 :
14600 GET X$: IF X$=“” THEN 14600
14605 X=ASC(X$)
14610 IF X=13 THEN 14900
14615 IF X=20 AND LEN(A$)>0 THEN 14700
14620 IF X=32 AND ASC(Y$)<>32 THEN 14800
14625 IF X>=65 AND X<=90 THEN 14800
14630 GOTO 14600
14635 :
14700 A$=LEFT$(A$,LEN(A$)-1)
14705 Y$=X$
14710 PRINT X$;
14715 GOTO 14600
14720 :
14800 IF LEN(A$)=A THEN 14600
14805 A$=A$+X$
14810 Y$=X$
14815 PRINT X$;
14820 GOTO 14600
14825 :
14900 PRINT ” “
14905 POKE 204,255
14910 RETURN

First some common variables are initialized; A$ for holding the result string, X$ for current char, Y$ for last char and Y for total string length allowed for typing. Currently only “? ” is printed, but I’ll replace this later with a localized string. Since the cursor is only shown when using the INPUT command, we have to show it manually by writing 0 to address 204. Everything is setup now for the loop which waits for a key press and that’s happening in line 14600. Then we take the ASCII value of the pressed key and check if it is RETURN (code 13), DELETE (code 20), SPACE (code 32) or a letter (codes from 65 to 90). Additional checks are made that we can’t delete a character if string length is 0 and that we can’t type two spaces in a row or begin input with a space. If none of these allowed characters match we jump back to the wait for key loop. Deleting a character is handled from line 14700; with the left command we’re taking the whole string with the last character removed. Of course we have to store last char to Y$ and print it out on screen. Other allowed characters are added to the string (if the length is in defined range) at line 14800. Last but not least, the RETURN key is handled from line 14900. Since we have enabled the cursor we have to print a additional space to clear it at the end of the output and disable it again by writing 255 again to address 204.

Program size: 5494 bytes, on disk 5080 bytes or 22 blocks
Free BASIC memory: 33417 bytes
Used BASIC commands: FRE, GET, IF, THEN, ASC, CHR$, AND, LEN, LEFT$, GOTO, PRINT, POKE, RETURN

Source code

* * * * *