.png)
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.
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.
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.
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.
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.
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.
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.
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.
Y/N program, change CP 'Y' to CP 'y'. Press y. What happens, and why?CP 'Y' to CP 121. Same question - and what is 121?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?CP 0 line. It still assembles. Does it still work, and if so, why - what did RST 8 leave the flags set to?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?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. That needs a way to ask whether a value is still ten or more, and CP with JR Z can only ask whether two values are equal - so you will have to look up one more condition than this section has given you. That is part of the exercise. Use the finished program to find out what Enter, Space, the three keys marked with arrows and the two grey cursor keys give you; at least one of them will surprise you. In MAME the arrow-marked keys are your Left, Right and Up arrows, and the cursor keys are Tab and the Down arrow.
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. Ask each for five characters. One of them gives you five; the other will not stop at all, so have Restart ready. Then explain the difference to yourself without looking back at this section.
| 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. |
A.'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.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.S9. Reading a Whole Line. 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. Next you reserve a block of memory, let the machine fill it with a whole typed line, and walk through it a byte at a time.
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.