in BASIC ROM:
|List of all BASIC keywords|
Type: Command General Programming-Syntax: WAIT <Memoryaddress>,<and-mask>[,<flip-mask>]
WAIT is a keyword in the built-in BASIC interpreter, which waits for a given memory location to match specific bit constellations. The parameter values are specified as a bit mask, so WAITing on a value of 32 will cause the program to continue when bit 5 changes to 1. WAITing on 3 will cause it to continue when either bit 1 or 2 is set. The optional 3rd parameter enables a check for unset bits by inverting the locations bits.
Syntax[edit | edit source]
- address is a 16-bit unsigned integer value in range from 0 to 65535 which designats the address of the location the wait condition is acting on.
- and-mask and flip-mask are unsigned byte values in range from 0 to 255, together comprising the wait condition the command is waiting for.
Values outside the given ranges result in the BASIC error.
Operation[edit | edit source]
WAIT is performed by a loop in ROM address 47166–47175/$B83E–$B847, which first reads the contents of the given address, then does a bit-wise exclusive-or with the flip-mask parameter (if given, otherwise it defaults to 0 which leaves the value unchanged), and finally a bit-wise and with the and-mask parameter. The loop will run as long as the result of these operation sequence yields a zero byte.
Examples[edit | edit source]
Keyboard checks[edit | edit source]
This will wait for the Commodore key to be pressed — until that happens, the "least drastic" way out of this, is to press + . The three least significant bits in address 653 turn "on" (1) if Shift keys, the Commodore key or the Ctrl keys are pressed down at the moment; you may change the "2" at the end of the WAIT instruction to a "1" to wait for Shift keys, or a "4" to wait for the Ctrl key to be pressed.
Try this one in direct mode: When pressing after typing the command, hold the Return key down for a while, and notice how the "Ready." prompt and cursor doesn't reappear before you release. Address 203 holds the keyboard code for the key currently being pressed, or the value 64/$40 if none are pressed.
Since the keyboard codes for all keys are less than 64, bit 6 basically indicate that no key is currently pressed. To wait for a key to be pressed, this example uses the extra mask2 parameter to "invert" that bit, and wait for this "inverted" bit to indicate that a key was pressed.
If this example is given in direct mode, be sure to press and release the Return key very rapidly after typing in the command — otherwise the WAIT command will find the Return key still pressed down as it does it's loop the first time.
POKE 198,0: WAIT 198,1
The C64 wait until a key is pressed on the keyboard.
Miscellaneous checks[edit | edit source]
WAIT 1, 32, 32
(The C64 wait until a button is pressed on the datassette.)
WAIT 53273, 6, 6
(The C64 wait until a sprite has got a collision with a char.)
WAIT 36868, 144, 16
(The C64 wait until at the memory address 36868 the 4th bit is deleted or
the 7th bit is set.)
Time delays[edit | edit source]
A simple approach:
The system's internal clock is stored in location 162 (the low significant byte, and 161, the middle significant and 160, the high significant byte of the 24-bit counter) and is incremented every jiffy, 1/60th of a second. Because WAIT is looking at bits, not the decimal value, this instruction means "wait until bit 6 changes". That will happen after 64 jiffies, or 64/60ths of a second, slightly more than one second.
You cannot wait one second by using 60 as the value, as this will occur if any of the bits change in 60 = 32 + 16 + 8 + 4. This means it will continue after 4 jiffies, not what might be expected. To wait for a specific number of jiffies you have to use several WAIT instructions in a row:
POKE 162,0:WAIT 162,32:WAIT 162,16:WAIT 162,8:WAIT 162,4
will wait exactly one second because it will first wait 32/60ths, then 16, 8 and 4 = 60/60ths.
An easier way to achieve random values with just one WAIT:
T=90 POKE 162,128-T:WAIT 162,128
This works for values in variable T from 1 to 128 (up to 2.13 seconds).
This scheme can be extended to 16 bit, covering a time range up to 9 minutes, 6 seconds and 8 1/60th seconds:
A more general approach:
To wait for a flexible time (in opposite to the above hard-coded wait sequence):
100 T=90: REM WAIT 1,5 SECONDS 110 TI$="000000": REM TO ENSURE A USABLE TI$ 120 GOSUB 900 130 PRINT TI 140 END 900 WT=162: REM LOW BYTE 24-BIT TIMER 910 POKE WT,0: REM RESET TIMER 920 WAIT WT, 128, NOT(T) AND 128 921 WAIT WT, 64, NOT(T) AND 64 922 WAIT WT, 32, NOT(T) AND 32 923 WAIT WT, 16, NOT(T) AND 16 924 WAIT WT, 8, NOT(T) AND 8 925 WAIT WT, 4, NOT(T) AND 4 926 WAIT WT, 2, NOT(T) AND 2 927 WAIT WT, 1, NOT(T) AND 1 930 RETURN
The subroutine starting at line 900 waits for multiples of 1/60th of a second as given by variable T. The run-time behavior leads to some blurring effect.
Even it would be sufficient to wait just for set bits this subroutine waits for 0 bit flipping it my means of the 3rd parameter before the logic-AND masking is enforced.
Operator NOT() needs the parenthesis to prevent to tokenizer from recognizing the token TAN in
NOT TAND 1 (possibly also a turn around of the expression to
1 AND T helps).
Note: This implementation suffers from the relatively slow processing of BASIC code. It takes a significant time to reach the bit with value 1, so it might happen that this bit's change has been missed and the WAIT catches the bit 1, 2, 4 or 8 jiffies later. This could be mitigated by using variable instead of constants for numbers and compact the code into long lines.
The following table shows a comparison of the waiting time to the real elapsed time for a value range from 1 to 100:
Delay Elapsed Difference 1 9 8 2 6 4 3 11 8 4 6 2 8 10 2 12 14 2 16 18 2 17 18 1 20 22 2 24 26 2 28 30 2 32 36 4 33 37 4 36 38 2 40 42 2 44 46 2 48 50 2 49 50 1 52 54 2 56 58 2 60 62 2 64 68 4 65 69 4 66 68 2 68 70 2 72 74 2 76 78 2 80 82 2 84 85 1 88 90 2 92 93 1 96 100 4 97 101 4 100 101 1