Prev: ACFB Up: Map Next: AE36
AD32: Handler: User Input
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