; m4key/asm ; GETKEY EQU $ LD HL,(KEYPOS) ;Get the buffered keys address GETKEY_0 EQU $ LD A,(HL) ;Get the key there IFZ GETKEY_1 ;Jump if no key available INC HL ;Point to next LD (KEYPOS),HL ;Save the new pointer CP A ;Set Z status RET ;Return the key ; ; Here, we must change the current string pointer back to a KNOWN ; zero byte. Otherwise the next defintion may move non-zero data ; underneath the pointer and result in garbage being retrieved on ; the next call to GETKEY. ; GETKEY_1 EQU $ LD HL,ATNULL ;Replace current string pointer LD (KEYPOS),HL CALL TRMIN ;Get a key from *SI RET NZ ;Return if nothing there LD (SAVEDKEY),A ;Save it for later use CALL KEYTRANS ;Get the address from the table OR H ;A holds L, OR in H to check JR NZ,GETKEY_0 ;Jump if string is present LD A,(SAVEDKEY) ;Get the real key back CP A ;Set Z status RET ;Return the key ; ; Store a key definition into the table ; DEFKEY EQU $ LD (KEYSTRING),HL ;Save the pointer to the data LD (KEYNUMBER),A ;Save the key to be replaced PUSH AF LD A,B ;Get the number of bytes in (HL) LD (STRINGLEN),A ;Store it POP AF CALL KEYTRANS ;Get the address of the current OR H ;definition and see if one exists CALL NZ,DELETEKEY ;If so, then remove it LD A,(STRINGLEN) ;Get the length OR A ;Is there a string there? RET Z ;Return if none. Old was deleted LD HL,DEFTABLE+DEFTLEN-1;Get the top of the table LD DE,(TOPADDR) ;Get the start of available OR A ;Reset carry SBC HL,DE ;Compute available number bytes LD C,A ;Get the request size as 16 bits LD B,0 OR A ;Reset the carry SBC HL,BC ;Compute the remaining after use JR NC,DEFKEY_1 ;Jump if there is room for it LD DE,NOSPACE ;Print the error message CALL PRTSTR RET ;Return without defining it DEFKEY_1 EQU $ LD HL,(KEYSTRING) ;Get the new definition PUSH DE ;Save the address to store at LDIR ;Move the string EX DE,HL ;Get the ending address LD (HL),0 ;Put a NULL in INC HL ;Point to next available LD (TOPADDR),HL ;Save the new available address POP DE ;Restore the definition address LD HL,(TABLEADDR) ;Get the address in the table LD (HL),E ;Store the LSB INC HL ;Point to the MSB LD (HL),D ;Save the MSB RET ;Return to the caller ; ; Get the address of the string corresponding to the key number ; in A. A holds the value of H on return. HL is zero if no ; definition exists. HL is the address of the string that is ; defined for the key if it is non-zero. The last byte in the ; string is followed by a zero byte. ; KEYTRANS EQU $ LD HL,KEYTABLE ;Get the pointer table LD C,A ;Put it into C LD B,0 ;Set B to zero initially RLC C ;C = C * 2 JR NC,KEYTRANS_1 ;If carry on shift then c > 127, INC B ;so increment B to recover bit 7 KEYTRANS_1 EQU $ RES 0,C ;Reset the LSB of C. ADD HL,BC ;Compute the table address LD (TABLEADDR),HL ;Save the address of the key def LD A,(HL) ;Get the LSB INC HL ;Point to the MSB LD H,(HL) ;Get it LD L,A ;Get the LSB RET ;Return to caller ; ; Delete a key definition from the table. No parameters are ; needed. The key to undefine is pointed to by (TABLEADDR). ; Thus, you must call KEYTRANS with the key number in A and then ; call DELETEKEY to delete the key. ; DELETEKEY EQU $ LD HL,(TABLEADDR) ;Get the addr of the definition LD E,(HL) ;Get the LSB of the string XOR A ;Clear A LD (HL),A ;Zap the LSB INC HL ;Point to the MSB LD D,(HL) ;Get the MSB LD (HL),A ;Zap the MSB LD (CMPADDR),DE ;Save the address for compares LD H,D ;Copy DE to HL LD L,E ; XOR A ;A is already zero (what we seek) CPIR ;Look for it PUSH HL ;Save the ending address OR A ;Reset the carry SBC HL,DE ;Compute the difference LD (MOVEDIFF),HL ;Save the difference LD HL,(TOPADDR) ;Get the end of the table POP BC ;Get the end of string to delete OR A ;reset the carry SBC HL,BC ;Calculate number bytes to move PUSH BC ;Exchange HL and BC PUSH HL POP BC POP HL LD A,B ;Check for zero length OR C JR Z,DELETEKEY_1 ;Don't move 65536 bytes LDIR ;Adjust the strings down DELETEKEY_1 EQU $ LD (TOPADDR),DE ;Set the new top address LD HL,KEYTABLE ;Get start of table LD B,0 ;Check 256 entrys DELETEKEY_2 EQU $ PUSH BC ;Save the counter LD C,(HL) ;Get the table value LSB INC HL ;Point to MSB LD B,(HL) ;Get the MSB DEC HL ;Back to original address LD A,B ;Check for any definition OR C ;Set the flags JR Z,DELETEKEY_4 ;Skip this entry PUSH HL ;Save the table address LD HL,(CMPADDR) ;Get the address to check against OR A ;Reset the carry SBC HL,BC ;Compute the difference JP P,DELETEKEY_3 ;Jump if no adjust needed LD H,B ;Copy BC to HL LD L,C LD BC,(MOVEDIFF) ;Get the difference OR A ;Reset the carry SBC HL,BC ;Adjust the pointer LD C,L ;Copy HL to BC LD B,H ;Get the MSB POP HL ;Get the destination address LD (HL),C ;Store the LSB back INC HL ;Point to MSB LD (HL),B ;Store the MSB JR DELETEKEY_5 ;Join other code DELETEKEY_3 EQU $ POP HL ;Get the table address back DELETEKEY_4 EQU $ INC HL ;Point to next table pos DELETEKEY_5 EQU $ INC HL ;One more increment POP BC ;Get the counter back DJNZ DELETEKEY_2 ;Loop until done RET ;end of file