← Back to Courses
module
8

Reading the keyboard

Why this matters

Every program so far has been a monologue. It runs, it prints, it stops. The player has no say in it.

A game is the opposite: mostly it sits waiting to find out what the player wants, and everything it does follows from that. This section is where your programs start listening.

Two ways to read a key

The machine offers both, and the difference between them is the whole of this section.

Call 156 waits. Your program stops at the call until a key is pressed, then carries on with the code in A.

Call 181 checks. Officially named ZKSCAN. It looks at the keyboard, hands you a code if something is pressed and zero if nothing is, and returns immediately either way.

Waiting is what you want for a prompt. Checking is what you want for a game.

Waiting for a key

The shortest useful program in the course so far:

        ORG 256

        RST 8
        DEFB 156        ; ZKEYIN - wait for a key - its code comes back in A

        RST 8
        DEFB 158        ; ZOUTC - print it

        RET

Run it. Nothing happens - the machine is waiting for you. Press X and you get:

>X

Your program stopped mid-flight, waited for you, and carried on. Note how little work that took: the code arrives in A, which is exactly where the print call wants it, so the two calls sit back to back with nothing in between.

A key is already a character

Here is a trap worth stepping over carefully.

In S3 you printed the answer to a sum, and you had to add 48 first, because the number 8 and the character 8 are different things.

A key press is not a number in that sense. What comes back in A is already a character code: press 3 and you get 51, which is the code for 3. It has been converted for you before your program ever sees it.

So you do not add 48. If you do, you get this:

        RST 8
        DEFB 156        ; ZKEYIN - press 3 - A is now 51
        ADD A,48        ; A is now 99
        RST 8
        DEFB 158        ; ZOUTC - prints "c"

Press 3, get c. The rule is: add 48 to numbers you calculated, never to codes you were given.

Capitals

One more surprise before the interesting part. Press y, and the code you get back is 89 - which is 'Y'.

Letter keys come back as capitals whichever way you type them. Testing for a lower-case y never matches, so a program that does waits forever.

Always compare against the capital.

CP - comparing things

To act on a key you need to ask whether it is a particular one, and DEC and JR NZ from S6 only ever tested against zero. CP tests against anything:

        CP 'Y'

CP compares A with the value and sets the flags on the result - and crucially leaves A alone. If the two are equal, Z comes up set, and JR Z or JR NZ does the rest.

Think of it as a subtraction whose answer is thrown away and whose flags are kept. Equal values subtract to zero, and zero sets Z.

Putting that together with the keyboard:

        ORG 256

        RST 8
        DEFB 156        ; ZKEYIN - wait for a key

        CP 'Y'          ; was it Y?
        JR Z,yes

        LD A,'N'        ; anything else
        JR show

yes:    LD A,'Y'

show:   RST 8
        DEFB 158        ; ZOUTC
        RET

Press y and you get Y. Press anything else and you get N. That is a program making a decision about something outside itself, which nothing you have written before has done.

CP works against a register too - CP B compares A with B - which is how you will compare two things that both change.

Checking without waiting

Waiting is no good for a game. A game has to keep drawing, keep moving things, keep the clock running, and glance at the keyboard as it goes. If it stops at a DEFB 156, everything stops.

Call 181 is the one that glances:

        ORG 256

poll:   RST 8
        DEFB 181        ; ZKSCAN - look at the keyboard
        CP 0            ; nothing pressed?
        JR Z,poll       ; then look again

        RST 8
        DEFB 158        ; ZOUTC - something was pressed - print it
        RET

This spins in a tight loop until a key appears. In a game, that loop would be doing the rest of the frame's work rather than nothing - and that is the point of a call that does not wait. It hands the choice back to you.

The cost of call 181

Call 181 destroys BC, DE and HL.

This matters immediately, because it breaks the pattern you have been using since S6. Every counted loop so far has kept its count in C, on the grounds that the print call gives C back. The keyboard scan does not:

        LD C,26
loop:   CALL print
        RST 8
        DEFB 181        ; ZKSCAN - <- your counter is gone
        DEC C
        JR NZ,loop      ; counts an unknown number of times

That program will loop, and stop, and do neither thing you intended.

The fix is to keep the count somewhere the call does not touch - which for now means in memory rather than a register, and that is the next section. For this one, just know that you cannot assume a register survives a call, and that which registers survive differs from one call to the next. Call 156 leaves BC, DE and HL alone; call 181 does not.

That is not an inconsistency to be annoyed about. It is what happens when you use code somebody else wrote: you get their choices along with their work.

Change one thing

  • In the Y/N program, change CP 'Y' to CP 'y'. Press y. What happens, and why?
  • Change CP 'Y' to CP 121. Same question - and what is 121?
  • In the waiting program, press Enter instead of a letter. Then press the space bar. What codes do those turn out to be, and how could you find out for certain rather than guessing?
  • In the polling program, delete the CP 0 line. It still assembles. Does it still work, and if so, why - what did RST 8 leave the flags set to?
  • Put LD C,5 before the polling loop and DEC C inside it, then check C in the register line after a key press. Is it 4?

Exercises

8.1 - Echo until Escape. Keep waiting for a key and printing it until Escape is pressed. Escape's code is 27. You will need a loop and a CP.

8.2 - Yes or no. Wait for a key. Print YES if it was Y, NO if it was N, and nothing at all for any other key - keep waiting instead. Three letters means a subroutine per word, or a loop over stored text, and either is good practice.

8.3 - What code is that key? Write a program that waits for a key and prints its code as a two-digit number, not as a character. You already know how to turn a digit into a character; the new part is splitting a number into two digits. Use it to find out what Enter, Space and the arrow keys give you.

8.4 - A menu. Wait for 1, 2 or 3 and print a different word for each, ignoring everything else. This is the shape of every title screen ever written.

8.5 - Prove the register problem. Write two loops that both count down in C and print each time round: one that calls 156 and one that calls 181. Count the characters each prints. Then explain the difference to yourself without looking back at this section.

When it goes wrong

What you see What it means
The program prints nothing and never returns A DEFB 156 waiting for a key that has not been pressed. Press one.
c when you pressed 3 You added 48 to a key code. Keys arrive already converted.
The comparison never matches a letter You compared against lower case. Letter keys come back as capitals.
A loop that polls the keyboard runs a wild number of times Call 181 destroyed the counter. Keep counts out of BC, DE and HL across that call.
A key you press seems to be ignored With call 181, the key has to be down at the moment the call happens. A single quick tap can fall between two checks.

Summary

  • Call 156 waits for a key. Call 181 checks and returns zero if nothing is pressed. Both hand you the code in A.
  • Games need 181, because a game cannot afford to stop.
  • A key arrives as a character code already. Add 48 to numbers you worked out, never to codes you were given.
  • Letter keys come back as capitals. Compare against 'Y', not 'y'.
  • CP compares A with a value, sets the flags, and leaves A alone. With JR Z and JR NZ that gives you a program that can decide.
  • Call 181 destroys BC, DE and HL. Which registers a call preserves is a property of that particular call, and you have to know it before you rely on it.

Next

S9. Storing things. You now have a counter that a keyboard call keeps destroying, and an exercise that wants three letters printed from one place. Both need somewhere to keep data that is not a register - which means labels that name storage rather than code, and instructions that reach it.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.