;
; *****************************************************************************
;
;				 H O T K E Y S
;				    v. 1.01
;			      (c) 1988 J.W. Olsen
;		                  15 May 1988
;
;	   May be used for noncommercial purposes without permission
; 			Inquire for all other purposes
; If given or sold with any other product, the price for which is more than $10
; inclusive of all charges, including but not limited to "shipping & handling,"
; such gift or sale is considered commercial use for purposes of the above.
;
; *****************************************************************************
;
; Allows redefintion of arrow and numeric-keypad keys. Two sets of redefinition
; are permitted in a single, assembled HK program. A run-time, command-line
; toggle key determines which redefinition will be activated. You may freely
; switch between the two configurations at any time. 

; HK simply pokes the copy of CP/M in memory. Thus, it's transitory and won't
; affect disk copies. When you turn off the computer or press the reset button,
; the effects of HK are gone until you run the program again.
;
; HK is run by typing its name, followed by a "toggle" key of your choice, as
; in "HK W" (e.g., I use "HK B" to run my BBS, "HK W" for word processing with
; with  WordStar or VDE.) You may want to set one configuration for "vanilla" 
; CP/M--info to do so is provided.
;
; This version works on CP/M Kaypros, except those with U-ROMS. Users with
; U-ROMs should use HKxxx-U.ASM. For other machines, see HKxxx.INF file.
;
; When invoked, HK first installs single-byte values for each of the 4 arrow 
; keys and the 14 numeric-keypad keys.
;
; Later Kaypros also permit assignment of 4-character strings to any or all of
; the arrow/numeric-keypad keys, activated if the "normal" byte for a given
; key is set to a null (00H). You'll have to see if this applies to you. My
; '83 Kaypro II (CP/M 2.2) doesn't permit this. My '84 Kaypro 10 (CP/M 2.2G) 
; does. If in doubt, first try it with the STRINGS equate set to YES. If the 
; strings work when you press corresponding keys, you're in business. If not, 
; RESET YOUR MACHINE BEFORE USING AGAIN. (An unintended area in high memory 
; will have been overwritten.) In that case, try again with STRINGS set to NO.
; If you have a non-U-ROM Kaypro, you should at least be able to get the
; 1-character redefinitions to work. (But if even this doesn't work on your
; hardware, RESET and feel free to contact me.)
;
; NOTE: Only the arrow keys above the main keyboard and the numeric keypad
; keys are redefined. All other keys are unaffected, including the number keys
; on the main keypad.
;
; Run your favorite assembler/linker. ASM and MLOAD work fine. 
;
; Thanx to Eric Bohlman for tips related to memory addresses on this version
; of HK.
;
; This was a quickie effort to meet a special need, but performs its function
; fully. Experienced 8080 programmers (of which it will be readily apparent
; I'm not one) undoubtedly will be able to reduce code size and suggest
; further improvements. That would be welcomed. But if in the meantime you
; too find HK useful, enjoy. Please direct comments, or check for any updates
; on my BBS.
; 
;   	Jerry Olsen
;	Sysop, The Advocate/NOWAR RCP/M
;	312.939.4411
;	24 hrs., 300/1200/2400, 8/n/1
; 
; ----- Preliminaries
; 
;	ASEG			; Comment out if assembling with other than M80
;
NO	EQU	0		; Leave these alone
YES	EQU	NOT NO
;
; ----- User-settable equates
;
TOGGLE1 EQU	'B'		; Specify two characters as command-line
TOGGLE2	EQU	'W'		; toggles to invoke your configurations.
				; A toggle may be any single letter, number
				; or punctuation. But LOWER CASE letters are
				; *NOT* allowed. You might want to set one
				; to "V" for "vanilla" CP/M settings.
OFFSET	EQU	35H		; Offset to first byte of arrows configuration
				; from the beginning of the first page of
				; memory pointed to by location 02H.
				; Neither OFFSET nor OFFST2 should require
				; any change for non-U-ROM Kaypros. 
STRINGS EQU	YES		; *** See headnotes about this ***
OFFST2	EQU	61H		; Offset to where 4-char strings can be stored
				; if bytes in area following OFFSET are nulls.
				; (Only active if STRINGS is set YES--for later
				; vintage Kaypros.)
;
; *** You also need to set up the arrays toward the end of this file ***
;
; ----- Miscellaneous equates (leave alone)
;
WBOOT	EQU	0		; Warm boot location
BDOS	EQU	5		; BDOS entry point
PRINTF	EQU	9		; Print-a-string function
BUFF	EQU	80H		; Command line buffer
CR	EQU	0DH		; Carriage return
LF	EQU	0AH		; Linefeed
SPACE	EQU	20H		; Ordinary blank space
NULL	EQU	0		; May be used in arrays if desired
;
; ----- Begin
;
	ORG	100H		; Normal TPA entry point
;
	LXI	D,SIGNON	; Point to sign-on msg
	MVI	C,PRINTF	; Tell BDOS we want to print a string
	CALL	BDOS		; and do it
;
;	LXI	H,BUFF		; Get address of command-line buffer
	MOV	A,M		; Get buffer length
	CPI	NULL		; Is it a null?
	JZ	ERROR1		; Yep, so print error msg & quit
;
	MOV	B,A		; Nope, so save command-line length
	LXI	H,BUFF+1	; Point to first char of command line
GETIT:	DCR	B		; Decrement our length counter
	MVI	A,NULL		; Prepare for comparison
	CMP	B		; Is counter now a null?
	JZ	ERROR1		; Yep, so print error msg & quit
	MOV	A,M		; Nope, so fetch char
	INX	H		; & increment pointer
	CPI	SPACE		; Is it a space?
	JZ	GETIT		; Yep, try again
;
	CPI	TOGGLE1		; Is it first legal toggle?
	JZ	SAVEIT		; Yep, so skip loop
	CPI	TOGGLE2		; Is it second legal toggle?
	JZ	SAVEIT		; Yep
	JMP	ERROR1		; Nope,so print error msg & quit
;
SAVEIT:	STA	OPTION		; We need it later too
;
	LHLD	WBOOT+1		; See if we're really pointing to where should
	MOV	L,NULL		; Will look at first byte of memory page
	MOV	A,M		; Snatch the byte
	CPI	0C3H		; A JMP instruction?
	JZ	ERROR2		; Nope, something's wrong--abort (might be a
				; problem with another program trapping WBOOT)
;
	MVI	L,OFFSET	; Offset to first arrow char byte	
	XCHG			; Save pointer while freeing (HL)
	LDA	OPTION		; Get user choice back
	CPI	TOGGLE1		; Was it first choice?
	JNZ	ALT		; Nope, so skip to it
	LXI	H,KEYS1		; Yep, so point to first set-up
	JMP	DOIT		; and begin
ALT:	LXI	H,KEYS2		; Point to second set-up
;
DOIT:	MVI	B,18		; Counter = # of arrow + numeric keypad keys
DOIT2:	MOV	A,M		; Fetch first byte
	STAX	D		; and poke it
	DCR	B		; See if counter is done
	MVI	A,NULL
	CMP	B		; If done...
;
	IF	STRINGS
	JZ	DOIT3		; all direct key values are poked
				; so go do 4-char strings (if STRINGS YES)...
	ENDIF			; STRINGS
;
	IF	NOT STRINGS
	JZ	DONE		; ... or tell 'em what we've done & quit
	ENDIF			; NOT STRINGS
;
	INX	D		; If not done with direct key values
	INX	H		; increment both pointers
	JMP	DOIT2		; and keep truckin' 
;
	IF	STRINGS
DOIT3:	LHLD	WBOOT+1		; Set up pointer again--
	MVI	L,OFFST2	; this time to where CP/M stores strings
	XCHG			; Free up (HL)
	LDA	OPTION		; Get choice back
	CPI	TOGGLE1		; First choice?
	JNZ	ALT2		; Nope
	LXI	H,STR1		; Yep
	JMP	DOIT4
ALT2:	LXI	H,STR2
;
DOIT4:	MVI	B,18*4		; Counter = # keys * 4-char strings	
DOIT5:	MOV	A,M		; Fetch first byte
	STAX	D		; and poke it
	DCR	B		; See if counter is done
	MVI	A,NULL
	CMP	B		; 
	JZ	DONE		; Yep, so tell 'em what we've done & quit
	INX	D		; If not
	INX	H		; increment both pointers
	JMP	DOIT5		; and continue
	ENDIF			; STRINGS
;
DONE:	LXI	D,OKMSG		; Point to successful sign-off msg & ...
;
EXIT:	MVI	C,PRINTF	; Tell BDOS to print a string
	CALL	BDOS		; & do it
	RET			; then quit
;	
; ----- Subroutine to print error msg if invalid command-line toggle
;
ERROR1:	LXI	D,ERR1		; Point to error msg
	JMP	EXIT		; Go print it & quit
;
; ---- Error msg if can't find correct page of memory to use
;
ERROR2:	LXI	D,ERR2		; Point to error msg
	JMP	EXIT		; Go print it & quit
;
; ----- Storage Area
;
SIGNON:	DB	CR,LF,'HOTKEYS v. 1.01, (c) 1988, J.W. Olsen',CR,LF,'$'
ERR1:	DB	CR,LF,'Syntax: HK ',TOGGLE1,' or HK ',TOGGLE2,CR,LF,'$'
ERR2:	DB	7,CR,LF,'++ Valid memory locations not found ++',CR,LF,'$'
OKMSG:	DB	'"'	; Printing of exit msg begins here, continues thru...
OPTION: DS	1	; User choice (filled when TOGGLE1 or TOGGLE2 selected)
OKMSG2:	DB	'" configuration INSTALLED',CR,LF
	DB	'$'	 ; ...end of exit msg (used only if HK is successful)
;
; Enter your 1-character preferences for each keystroke below. (For nonprintable
; characters, use hex. For others, use either hex or alphanumeric. Examples of
; both below.)
;
; "What Is" reflects current values. (Replace with your description if 
; changes are made.) "Original" indicates vanilla CP/M. "Name" describes the 
; function of the original key. 
;
; "KEYS1" relate to your TOGGLE1 selection, "KEYS2" to TOGGLE2. If you want
; to substitute a 4-character substitute for any key, enter 00H or NULL for
; it & see "STR" (string) discussion, below--IF you set "STRINGS" to YES. As
; released, TOGGLE1 represents my configuration for running a BBS. Toggle 2 
; is my personal, albeit at first glance seemingly weird preferences for word
; processing with WordStar/VDE.
;
;			  What Is	Original	Name
;			  =========	========	========
KEYS1:	DB	NULL	; Uses STR1	05H		Up arrow
	DB	NULL	; Uses STR1	18H		Down arrow
	DB	NULL	; Uses STR1	13H		Left arrow
	DB	NULL	; Uses STR1	04H		Right arrow
	DB	'0'	; keypad 0	30H		0 (keypad)
	DB	'1'	; 1		31H		1 "
	DB	'2'	; 2		32H		2 "
	DB	'3'	; 3		33H		3 "
	DB	'4'	; 4		34H		4 "
	DB	'5'	; 5		35H		5 "
	DB	'6'	; 6		36H		6 "
	DB	'7'	; 7		37H		7 "
	DB	'8'	; 8		38H		8 "
	DB	'9'	; 9		39H		9 "
	DB	'-'	; Hyphen	2DH		Hyphen (keypad)
	DB	03H	; control-C	2CH		Comma	"
	DB	0DH	; Enter		0DH		Enter	"
	DB	'.'	; period	2EH		Period	"
;
;			  What Is	Original	Name
;			  =========	========	========
KEYS2:	DB	10H	; control-P	05H		Up arrow
	DB	0FH	; control-O	18H		Down arrow
	DB	0BH	; control-K	13H		Left arrow
	DB	02H	; control-B	04H		Right arrow
	DB	07H	; control-G	30H		0 (on KEYPAD)
	DB	19H	; control-Y	31H		1	
	DB	18H	; control-X	32H		2	
	DB	06H	; control-F	33H		3
	DB	13H	; control-S	34H		4
	DB	11H	; control-Q	35H		5
	DB	04H	; control-D	36H		6
	DB	15H	; control-U	37H		7
	DB	05H	; control-E	38H		8
	DB	01H	; control-A	39H		9
	DB	12H	; control-R	2DH		Hyphen	"
	DB	03H	; control-C	2CH		Comma	"
	DB	16H	; control-V	0DH		Enter 	"
	DB	14H	; control-T	2EH		Period	"
;
	IF	STRINGS
; For anything that's a NULL above, the corresponding key is replaced by the
; related string below--if you set STRINGS to YES.
;
;			  What Is	Original	Name
;			  =========	========	========
STR1:	DB	'BYE',CR ; [normally	[all NULLs]	Expands Up arrow
	DB	'CHAT'	; nulls, but			   " downn arrow
	DB	'HELP'	; set as			   " Left arrow
	DB	'`SD '	; blank spaces			   " Right arrow
	DB	'    '	; here to 			   " KEYPAD 0
	DB	'    '  ; facilitate 			    	    1
	DB	'    '  ; filling in			    	    2
	DB	'    '  ; with alpha				    3
	DB	'    '  ; characters]			  	    4
	DB	'    '  ;					    5
	DB	'    '  ;					    6
	DB	'    '  ;					    7
	DB	'    '  ;					    8
	DB	'    '  ;					    9
	DB	'    '  ;				   "	Hyphen
	DB	'    '  ;				   "	Comma
	DB	'    '  ;				   "	Enter 
	DB	'    '  ;				   "	Period
;
;			  What Is	Original	Name
;			  =========	========	========
STR2:	DB	'    '	; [all unused]	[all NULLs]	Expands Up arrow
	DB	'    '	;				   " downn arrow
	DB	'    '	;				   " Left arrow
	DB	'    '	;				   " Right arrow
	DB	'    '	;				   " KEYPAD 0
	DB	'    '  ;				    	    1
	DB	'    '  ;				    	    2
	DB	'    '  ;					    3
	DB	'    '  ;				  	    4
	DB	'    '  ;					    5
	DB	'    '  ;					    6
	DB	'    '  ;					    7
	DB	'    '  ;					    8
	DB	'    '  ;					    9
	DB	'    '  ;				   " 	Hyphen
	DB	'    '  ;				   " 	Comma
	DB	'    '  ;				   "	Enter 
	DB	'    '  ;				   "	Period
	ENDIF		; STRINGS
;
; ----- That's all, folks
;
	END
