![]()  | 
Routines | 
| Prev: ACFB | Up: Map | Next: AE36 | 
| 
 
Used by the routine at GameLoop.
 
Handles keyboard input, tokenises commands and validates the vocabulary.
 
 | 
||||
| 
 
Reset the screen position to defaults.
 
 | 
||||
| Handler_UserInput | AD32 | CALL SetDefaultScreenPosition | Call SetDefaultScreenPosition. | |
| AD35 | CALL PrintInputPrompt | Call PrintInputPrompt. | ||
| 
 
Initialise the command buffer.
 
 | 
||||
| AD38 | LD HL,$A7F2 | HL=CommandBuffer. | ||
| AD3B | LD B,$00 | Initialise a letter counter in B. | ||
| AD3D | JR UserInput_Next | Jump to UserInput_Next. | ||
| 
 
Main input loop - process each keypress.
 
 | 
||||
| UserInput_Loop | AD3F | INC HL | Move to the next byte of the command buffer. | |
| AD40 | INC B | Increment the letter counter by one. | ||
| UserInput_Next | AD41 | CALL Print_Cursor | Call Print_Cursor. | |
| AD44 | CALL GetUserInput | Call GetUserInput. | ||
| AD47 | CP $0C | Jump to ValidateUserInput if "DELETE" was not pressed. | ||
| AD49 | JR NZ,ValidateUserInput | |||
| 
 
The user pressed "DELETE".
 
 | 
||||
| AD4B | XOR A | Jump back to UserInput_Next if there hasn't been any input yet (nothing to delete). | ||
| AD4C | OR B | |||
| AD4D | JR Z,UserInput_Next | |||
| 
 
There is input which can be deleted, so action a delete!
 
 | 
||||
| AD4F | EX DE,HL | Temporarily stash the command buffer pointer in DE. | ||
| 
 
Print "SPACE BACKSPACE BACKSPACE SPACE BACKSPACE" to move the current print position on the screen to the previous character, and to delete the character present using a space.
 
 | 
||||
| AD50 | LD HL,$ACC6 | HL=Messaging_SpaceBackspaceBackspaceSpaceBackspace. | ||
| AD53 | CALL PrintString | Call PrintString. | ||
| 
 
Adjust the command buffer position and letter counter.
 
 | 
||||
| AD56 | EX DE,HL | Restore the command buffer pointer from DE. | ||
| AD57 | DEC HL | Decrease the command buffer pointer by one. | ||
| AD58 | DEC B | Decrease the letter counter by one. | ||
| AD59 | JR UserInput_Next | Jump to UserInput_Next. | ||
| 
 
Check which key the user pressed:
 
 | 
||||
| ValidateUserInput | AD5B | LD C,A | Jump to UserInput_WriteKeypress if "ENTER" was pressed. | |
| AD5C | CP $0D | |||
| AD5E | JR Z,UserInput_WriteKeypress | |||
| AD60 | CP $20 | If the keypress was any other control key (the value being under 20 ASCII "SPACE"), it's not valid input so jump back to UserInput_Next. | ||
| AD62 | JR C,UserInput_Next | |||
| AD64 | CP $80 | If the keypress was higher than 80 it's also not valid input so jump back to UserInput_Next. | ||
| AD66 | JR NC,UserInput_Next | |||
| 
 
Is the command buffer full?
 
 | 
||||
| AD68 | LD A,B | Jump to UserInput_Next if the letter counter is 31 (so the buffer is full). | ||
| AD69 | CP $31 | |||
| AD6B | JR Z,UserInput_Next | |||
| 
 
Writes the keypress into the command buffer and print it to the screen.
 
 | 
||||
| UserInput_WriteKeypress | AD6D | LD A,C | Write the user input key to *HL. | |
| AD6E | LD (HL),A | |||
| AD6F | CALL Print_UserInputToScreen | Call Print_UserInputToScreen. | ||
| 
 
Did the user press "ENTER"?
 
 | 
||||
| AD72 | LD A,C | Jump to UserInput_Loop if "ENTER" was not pressed. | ||
| AD73 | CP $0D | |||
| AD75 | JR NZ,UserInput_Loop | |||
| 
 
The player pressed "ENTER" so begin to process the user input.
 
Clear down the user input tokens.
 
 | 
||||
| AD77 | LD HL,$A824 | HL=UserInput_Token_1. | ||
| AD7A | LD B,$0A | Set a counter in B for all 0A user input tokens. | ||
| EmptyUserInputTokens_Loop | AD7C | LD (HL),$FF | Write a termination byte (FF) to *HL. | |
| AD7E | INC HL | Increment HL by one. | ||
| AD7F | DJNZ EmptyUserInputTokens_Loop | Decrease the user input tokens counter by one and loop back to EmptyUserInputTokens_Loop until all the tokens have been set to termination bytes (FF). | ||
| 
 
Set up pointers for the command buffer, the user input tokens and the count of the number of user input tokens.
 
 | 
||||
| AD81 | LD HL,$A7F2 | HL=CommandBuffer. | ||
| AD84 | LD IX,$A824 | IX=UserInput_Token_1. | ||
| AD88 | LD C,$0A | Set a counter in C for the 0A user input tokens. | ||
| AD8A | JR EmptyFourLetterBuffer | Jump to EmptyFourLetterBuffer. | ||
| 
 
What's been entered isn't parsable.
 
Print "I don't understand.".
 
 | 
||||
| Response_NotUnderstood | AD8C | LD HL,$A84F | HL=Messaging_IDontUnderstand. | |
| AD8F | CALL PrintStringAndNewline | Call PrintStringAndNewline. | ||
| AD92 | JP Handler_UserInput | Jump to Handler_UserInput. | ||
| 
 
Process found word into user input token.
 
 | 
||||
| ProcessFoundWord | AD95 | PUSH HL | Stash the command buffer pointer, DE and user input tokens counter on the stack. | |
| AD96 | PUSH DE | |||
| AD97 | PUSH BC | |||
| AD98 | LD HL,($ACC2) | HL=*TempStore_CommandBufferPointer. | ||
| AD9B | LD DE,$A82F | DE=FourLetterBuffer. | ||
| 
 
Ensure that the length is not more than 04.
 
 | 
||||
| AD9E | LD BC,$0004 | BC=0004. | ||
| ADA1 | LD A,($ACC4) | Jump to CopyWordToBuffer if *TempStore_CommandBufferCount is greater than or equal to 04. | ||
| ADA4 | CP C | |||
| ADA5 | JR NC,CopyWordToBuffer | |||
| 
 
The length is less than 04 so no need to copy 04 bytes.
 
 | 
||||
| ADA7 | LD C,A | Copy the actual length of the word into C. | ||
| 
 
Copy the word (up to 04 characters in length) into the four letter buffer.
 
 | 
||||
| CopyWordToBuffer | ADA8 | LDIR | Copy the "up-to-04" letters from the command buffer into the four-letter buffer. | |
| ADAA | POP BC | Restore the user input token counter, DE and command buffer pointer from the stack. | ||
| ADAB | POP DE | |||
| ADAC | POP HL | |||
| ADAD | PUSH HL | Stash the command buffer pointer back on the stack. | ||
| 
 
Stash the vocabulary pointer for a separate check...
 
 | 
||||
| ADAE | LD HL,($A7C6) | Stash *Pointer_Vocabulary on the stack. | ||
| ADB1 | PUSH HL | |||
| 
 
Ignore any usage of "THE" - this is a very good idea! If the player enters: "EXAMINE THE SKULL", this ensures it's evaluated in the exact same way as "EXAMINE SKULL" (or really, "EXAM SKUL").
 
 | 
||||
| ADB2 | LD HL,$A667 | Write Table_Vocabulary_The to *Pointer_Vocabulary. | ||
| ADB5 | LD ($A7C6),HL | |||
| ADB8 | CALL Handler_MatchItem | Call Handler_MatchItem. | ||
| 
 
Do nothing with with this match - just restore the vocabulary pointer from the stack.
 
 | 
||||
| ADBB | POP HL | Restore *Pointer_Vocabulary from the stack and write it back to *Pointer_Vocabulary. | ||
| ADBC | LD ($A7C6),HL | |||
| ADBF | POP HL | Restore HL from the stack. | ||
| ADC0 | JR C,EmptyFourLetterBuffer | Jump to EmptyFourLetterBuffer if "THE" was successfully found. | ||
| ADC2 | CALL Handler_MatchItem | Call Handler_MatchItem. | ||
| ADC5 | JR C,StoreTokenAndContinue | Jump to StoreTokenAndContinue if an item was successfully found. | ||
| 
 
Nothing matched ... Inform the player.
 
Print "I don't know the word:-".
 
 | 
||||
| ADC7 | LD HL,$A863 | HL=Messaging_IDontKnowTheWord. | ||
| ADCA | CALL PrintStringAndNewline | Call PrintStringAndNewline. | ||
| 
 
Print a double quote character: " 
"".
 | 
||||
| ADCD | LD A,$22 | Call PrintCharacter to print a double quote character (ASCII 22). | ||
| ADCF | CALL PrintCharacter | |||
| ADD2 | LD HL,($ACC4) | HL=*TempStore_CommandBufferCount. | ||
| ADD5 | LD DE,($ACC2) | HL+=*TempStore_CommandBufferPointer. | ||
| ADD9 | ADD HL,DE | |||
| ADDA | LD (HL),$FF | Write FF to *HL. | ||
| ADDC | EX DE,HL | Exchange the DE and HL registers. | ||
| ADDD | CALL PrintString | Call PrintString. | ||
| 
 
Print a double quote character: " 
"".
 | 
||||
| ADE0 | LD A,$22 | Call PrintCharacter to print another double quote character (ASCII 22). | ||
| ADE2 | CALL PrintCharacter | |||
| 
 
Print ".".
 
 | 
||||
| ADE5 | LD HL,$AA15 | HL=Messaging_FullStop. | ||
| ADE8 | CALL PrintStringAndNewline | Call PrintStringAndNewline. | ||
| ADEB | JP Handler_UserInput | Jump to Handler_UserInput. | ||
| 
 
The word in the four-letter buffer was matched!
 
Store the found token and check if we can continue parsing.
 
 | 
||||
| StoreTokenAndContinue | ADEE | LD (IX+$00),A | Write the token to the current token slot. | |
| ADF1 | INC IX | Move to the next token slot. | ||
| ADF3 | DEC C | Decrease the token counter by one. | ||
| ADF4 | JR Z,CheckVerbToken | Jump to CheckVerbToken if all token slots are filled. | ||
| 
 
Token matching only uses four letters of every word so a buffer is used for processing.
 
Start by clearing the buffer.
 
 | 
||||
| EmptyFourLetterBuffer | ADF6 | PUSH HL | Stash the command buffer pointer and user input tokens counter on the stack. | |
| ADF7 | PUSH BC | |||
| ADF8 | LD HL,$A82F | Load FourLetterBuffer into HL. | ||
| ADFB | LD B,$04 | Set a counter in B for the 04 letters in the buffer. | ||
| EmptyFourLetterBuffer_Loop | ADFD | LD (HL),$20 | Write ASCII "SPACE" (20) to *HL. | |
| ADFF | INC HL | Increment HL by one. | ||
| AE00 | DJNZ EmptyFourLetterBuffer_Loop | Decrease the letter buffer counter by one and loop back to EmptyFourLetterBuffer_Loop until all four letters have been cleared. | ||
| AE02 | POP BC | Restore the user input tokens counter and command buffer pointer from the stack. | ||
| AE03 | POP HL | |||
| AE04 | PUSH DE | Stash DE on the stack. | ||
| AE05 | JR FindWordStart | Jump to FindWordStart. | ||
| 
 
Skip delimiter characters to find the next word.
 
 | 
||||
| SkipDelimiters | AE07 | INC HL | Move to the next byte of the command buffer. | |
| FindWordStart | AE08 | LD A,(HL) | Fetch a character from the command buffer. | |
| AE09 | CP $0D | Jump to EndWordParsing if the character is "ENTER" (ASCII 0D). | ||
| AE0B | JR Z,EndWordParsing | |||
| AE0D | CALL IsDelimiter | Call IsDelimiter. | ||
| AE10 | JR Z,SkipDelimiters | Jump to SkipDelimiters if the character is a delimiter. | ||
| 
 
The character is not a delimiter.
 
 | 
||||
| AE12 | LD ($ACC2),HL | Store the starting address of this new word in *TempStore_CommandBufferPointer. | ||
| AE15 | LD DE,$0000 | Initialise DE to 0000 to count the number of letters in the word. | ||
| 
 
Just keep looping and moving across the command buffer until we hit a delimiter or an "ENTER" character.
 
 | 
||||
| CountWordLength | AE18 | INC HL | Move to the next byte of the command buffer. | |
| AE19 | INC DE | Increment the letter counter by one. | ||
| AE1A | LD A,(HL) | Fetch a character from the command buffer. | ||
| AE1B | CP $0D | Jump to StoreWordLength if the character is "ENTER" (ASCII 0D). | ||
| AE1D | JR Z,StoreWordLength | |||
| AE1F | CALL IsDelimiter | Call IsDelimiter. | ||
| AE22 | JR NZ,CountWordLength | Jump to CountWordLength if the character was not a delimiter. | ||
| 
 
This is the end of the word, so store the word length.
 
 | 
||||
| StoreWordLength | AE24 | LD ($ACC4),DE | Write the letter counter to *TempStore_CommandBufferCount. | |
| AE28 | SCF | Set the carry flag to indicate that a word was successfully found. | ||
| EndWordParsing | AE29 | POP DE | Restore DE from the stack. | |
| AE2A | JP C,ProcessFoundWord | Jump to ProcessFoundWord if a word was found. | ||
| 
 
Check to see if any of the user input tokens have been populated, and if not, print "I don't understand.".
 
 | 
||||
| CheckVerbToken | AE2D | LD A,($A824) | Jump to Response_NotUnderstood if *UserInput_Token_1 hold the terminator byte (FF). | |
| AE30 | CP $FF | |||
| AE32 | JP Z,Response_NotUnderstood | |||
| AE35 | RET | Return. | ||
| 
 
View the equivalent code in The Jewels Of Babylon.
 
 | 
||||
| Prev: ACFB | Up: Map | Next: AE36 |