.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. 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.
| 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. 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.