;	MODMON.MAC vers. 1.0
;
;	Written September 26, 1982
;	by
;	Ken Stephenson
;	5 Laurel Wood Dr.
;	Lawrenceville, N.J. 08648
;
;	This program provides customized character redefinition
;	for the Keytronics Word Processor keyboard operating
;	with the DRC Big Board computer.  The program allows
;	definition of up to 16 functions which are executed
;	directly in interupt status upon closure of the appropriate
;	keyboard key.  Presently, two functions have been implemented:
;	1) closure of cntl, shift, and key 69 will interupt the
;	program which is presently executing and print out the
;	processor register values which were in effect at the time
;	of interupt.  Control is then returned to the interupted
;	program which will continue executing.  2) closure of cntl,
;	shift, and key 70 will have the same effect as function 1
;	except that the function will reboot instead of returning
;	to the interupted program.  These two functions are useful
;	for debugging and graceful exits from infinite loops.
;
.z80
;	This program loads at 100h like a normal CPM program.
;	The keyboard interupt program section then relocates to
;	reside immediately above the PFM monitor.  The character
;	translation table is relocated immediately below the
;	monitor variable area ( ff00 - ffffh ).  The translation
;	table will permanently occupy this area, even as updates
;	are made to the interupt program.  In this way, user
;	programs operating in low memory can modify the table to
;	suit their requirements, and will not have to be changed
;	if updates are made to the interupt program.
;
;
prgdst	equ	0f7e8h		;interupt prog will relocate to here
datdst	equ	0feb2h		;translation table will relocate
				;to here
ptchlc	equ	0f49ah		;patch into monitor at this location
sploc	equ	0ff35h		;stack pointer is stored here
pnext	equ	0f3ech		;monitor ascii output routine
eot	equ	04h		;end of text marker
cr	equ	0dh
lf	equ	0ah
put4hs	equ	0f3cdh		;monitor hex output routine
boot	equ	0
;
;	program relocation
;
	ld	bc,pend-pstart	;number of bytes to relocate
	ld	hl,pstart	;start address of code to reloc
	ld	de,prgdst	;relocated code goes here
	ldir			;move code
;
;	translation table relocation
;
	ld	bc,dend-dstart	;number of bytes to relocate
	ld	hl,dstart	;start address of data to reloc
	ld	de,datdst	;relocated data goes here
	ldir			;move data
;
;	prepare to patch monitor
;
	ld	a,0c3h		;jump instruction into reg a
	ld	hl,prgdst	;jump address
	di			;no interupts while patching monitor
	ld	(ptchlc),a	;store jump instruction
	ld	(ptchlc+1),hl	;store jump address
	ei
	ret			;back to cpm
;
;
;	keyboard interupt routine begins in monitor and
;	jumps to here
;
pstart:
	.phase prgdst	;assemble code to run above PFM
;
	cp	20h	;is character a control char?
	jp	c,cntlch	;jump if yes
	cp	80h		;not cntl; is char asci?
	jp	nc,bit7		;jump if not asci
;
nrmret:	defb	2ah,59h,0ffh	;this is instruction ld hl,(pinvec)
				;which was overwritten in the
				;monitor patch
	jp	0f49dh		;return to monitor
;
;	arrive here if character is control char
cntlch:	ld	bc,ctldat	;bc points to character
				;translation table
ckchr:	ld	h,0		;character value is
	ld	l,a		;offset to translation value
	add	hl,bc
	ld	a,(hl)		;get translated character
ckspec:	cp	0f0h		;values above f0h will get
				;special treatment
	jp	nc,specl
	jr	nrmret		;if not special, return to monitor
;
;	arrive here if character has bit 7 set
bit7:	cp	201Q	;key 71, shift or cntl-shift is 201Q
	jr	nz,e1
	ld	a,(k71s)	;get translated value
	jr	ckspec		;check for special character
;
e1:	cp	221Q	;key 71, unshift or cntl
	jr	nz,e2		;jump if not 221Q
	ld	a,(k71u)	;get translated value
	jr	ckspec		;check for special character
;
e2:	cp	254Q	;all other bit 7 keys, but cntl-shift
	jr	nc,e3		;jump if >= 254Q
	sub	241Q	;generate table offset value
	ld	bc,ctlshf
	jp	ckchr		;go get translated char
;
e3:	cp	274Q	;all other bit7 keys, but cntl
	jr	nc,e4		;jump if >= 274Q
	sub	261Q	;generate table offset value
	ld	bc,ctl
	jp	ckchr		;go get translated char
;
e4:	cp	354Q	;all other bit 7 keys, but shifted
	jr	nc,e5		;jump if >= 354Q
	sub	341Q	;generate table offset value
	ld	bc,shift
	jp	ckchr		;go get translated char
;
e5:	sub	361Q	;to arrive here, must be unshifted
	ld	bc,unshft
	jp	ckchr		;go get translated char
;
;
;	arrive here for special characters. that is, characters
;	with values greater than 0f0h indicate that special
;	processing is to take place in the keyboard routine.
;
;	Presently, two special characters are implemented: 0feh
;	and 0ffh. For 0feh, the contents of the z80 registers
;	prior to interupt are displayed on the screen . Instead of
;	returning to the keyboard routine, return is directly
;	to the interupted program.  The function for 0ffh is
;	the same except that, instead of returning to the 
;	interupted program, a warm boot is performed.  These two
;	functions allow limited debugging and a graceful exit
;	from infinite loops.
;
char:	defs	1		;place to store character
regsto:	defs	12		;place to store register values
;
specl:	ld	(char),a	;remember character
	pop	hl		;hl now has value of af prior to intrp
	ld	(regsto),hl	;keep old af at regsto
	pop	hl		;hl now has value of bc prior to intrp
	ld	(regsto+2),hl	;keep old bc at regsto+2
	pop	hl		;hl now has value of de prior to intrp
	ld	(regsto+4),hl	;keep olf de at regsto+4
	pop	hl		;hl now has value of hl prior to intrp
	ld	(regsto+6),hl	;keep old hl at regsto+6
	ld	hl,(sploc)	;hl now has value of stk ptr prior
				;to interupt
	ld	(regsto+10),hl	;keep old stk ptr at regsto+10
	ld	sp,hl		;make old stk ptr new stk ptr
				;so that we can return to program
	pop	hl		;hl now has value of program counter
				;at point of interupt
	ld	(regsto+8),hl	;keep old pc at regsto+8
;	now comes tricky part
;	we want to use display routines but we cannot if we
;	are in interupt status.  Therefore, we will push our
;	present location onto the stack so that when we execute
;	a return-from-interupt, we will return to our present
;	location.
	ld	hl,rtnloc	;hl contains our desired rtn location
	push	hl		;put rtn location onto stack
	ei			;enable interupts
	reti			;return from interupt
rtnloc:	call	pnext		;we are back! print message
	defb	cr,lf
	defm	' intrp at '
	defb	eot
	ld	hl,(regsto+8)	;hl contains pc at point of interupt
	call	put4hs		;print pc on screen
	call 	pnext		;print message
	defb	cr,lf
	defm	' af '
	defb	eot
	ld	hl,(regsto)	;hl contains af at point of interupt
	call	put4hs
	call	pnext		;print message
	defb	cr,lf
	defm	' bc '
	defb	eot
	ld	hl,(regsto+2)	;hl contains bc at point of interupt
	call	put4hs
	call	pnext
	defb	cr,lf
	defm	' de '
	defb	eot
	ld	hl,(regsto+4)	;hl contains de at point of interupt
	call	put4hs
	call	pnext
	defb	cr,lf
	defm	' hl '
	defb	eot
	ld	hl,(regsto+6)	;hl contains hl at point of interupt
	call	put4hs
	call	pnext
	defb	cr,lf
	defm	' sp '
	defb	eot
	ld	hl,(regsto+10)	;hl contains stk ptr at pnt of intrp
	call	put4hs
	call	pnext
	defb	cr,lf,eot
	ld	a,(char)	;restore character to a
	cp	0ffh		;test for reboot char
	jp	z,boot		;boot if yes
	ld	hl,(regsto+8)	;otherwise, restore all reg for
				;return to interupted program
	push	hl		;push desired prog counter onto stack
	ld	hl,(regsto)	;cannot load af directly from
	push	hl		;memory, so do it in two steps
	pop	af
	ld	bc,(regsto+2)	;bc is easier
	ld	de,(regsto+4)	;load de
	ld	hl,(regsto+6)	;finally,restore hl
	ret			;return to interupted program
;
;
	.dephase
;
pend:				;end of program
;
dstart:				;start of data section
	.phase datdst		;locate immediately
				;below monitor variables
;
;	CHARACTER TRANSLATION TABLE
;
;	Customized to the Keytronics Word Processor Keyboard
;
;	The following redefinitions are made to incoming
;	control characters:
;
;	change cntl-j to cntl-z
;	  "    cntl-y to cntl-s
;	  "    cntl-z to cntl-x
;	  "    cntl-l to  \ (5ch). Keytronics does'nt have \ otherwise
;	  "    cntl-w to  | (7ch).     "         "      "  |     "
;	  "    cntl-k to  ~ (7eh).     "         "      "  ~     "
;
;
ctldat:	defb	0,1,2,3,4,5,6,7,8,9,1ah,7eh,5ch,13,14,15
	defb	16,17,18,19,20,21,22,7ch,24,13h,18h,27,28,29,30,31
;
;	use bit 7 keys as a numeric keypad when unshifted
;
k71u:	defm	'0'
k71s:	defm	'?'	;key 71 shifted is not presently used
;
unshft:	defm	'1234567890.'
shift:	defm	'???????????'
ctl:	defm	'???????????'
ctlshf:	defm	'?????????'
	defb	0feh,0ffh	;make these two keys special
;
;	end translation table
;
	.dephase
dend:
;
	end	100h		;link as cpm com file
