CGROUP	 GROUP VECTOR,CODESEG
VECTOR	 SEGMENT AT 0H
	 DB    6CH DUP(?)	    ;FILLER
TIME_LO  DW    ?		    ;DOS TIME
TIME_HI  DW    ?		    ;DOS TIME
VEC_IP	 DW			    ;CLOCK UPDATE VECTOR IP
VEC_CS	 DW			    ;CLOCK UPDATE VECTOR CS
VECTOR	 ENDS

CODESEG  SEGMENT PARA
	 ASSUME CS:CODESEG,DS:CGROUP
	 ORG   100H
CLK	 PROC  FAR
	 JMP   SETUP		    ;ATTACH TO DOS
INTRPT	 LABEL DWORD
INT_IP	 DW    0		    ;OLD UPDATE VECTOR IP
INT_CS	 DW    0		    ;OLD UPDATE VECROR CS
TICKS	 DW    0		    ;TICK COUNTER
SCR_OFF  DB    0,0		    ;SCREEN OFFSET IN BUFFER
CRT_PORT DW    0		    ;SCREEN STATUS PORT
flag	 db    0
TIME	 DB    8 DUP(':',0BH)       ;TIME SAVE AREA
CLK_INT  LABEL NEAR
	 PUSH  AX		    ;SAVE REGISTERS
	 PUSH  CX
	 PUSH  DI
	 PUSH  SI
	 PUSH  DS
	 PUSH  ES
	 PUSHF			    ; AND FLAGS
	 CALL  CS:[INTRPT]	    ;DO OLD UPDATE INTERRUPT
	 MOV   CX,0040H 	    ;GET SEGMENT OF DOS TABLE
	 MOV   DS,CX		    ;PUT IN DS
	 MOV   CX,CS:TICKS	    ;GET TICK COUNT
	 INC   CX		    ;INCREMENT IT
	 CMP   CX,20	    ;01F4H	       ;HAS A MINUTE GONE BY?
	 JB    NO_MINUTE	    ;NO, MOVE ON
	 CALL  UPDATE		    ;YES, UPDATE CLOCK AND
	 MOV   CX,0		    ; RESET TICK COUNTER
NO_MINUTE:
	 MOV   CS:TICKS,CX	    ;SAVE UPDATED TICK COUNT
	 MOV   CX,0B000H	    ;GET VIDEO SEGMENT
	 MOV   ES,CX		    ;PUT IN ES
	 MOV   DX,CS:CRT_PORT	    ;GET CRT STATUS PORT ADDR
	 MOV   DI,WORD PTR CS:SCR_OFF  ;GET SCREEN BUFFER OFFSET
	 LEA   SI,CS:TIME	    ;GET DOS TIME
	 MOV   CX,16		    ;SET UP TO MOVE 10 BYTES
	 CLI			    ;DISABLE OTHER INTERRUPTS
WAIT1:	 IN    AL,DX		    ;READ CRT STATUS
	 TEST  AL,1		    ;CHECK FOR VERTICAL RETRACE
	 JNZ   WAIT1		    ;WAIT FOR RETRACE LOW
	 MOV   AH,CS:[SI]	    ;GET FIRST BYTE TO MOVE
WAIT2:	 IN    AL,DX		    ;GET CRT STATUS
	 TEST  AL,1		    ;CHECK FOR VERTICAL RETRACE
	 JZ    WAIT2		    ;WAIT FOR RETRACE HIGH
	 MOV   ES:[DI],AH	    ;MOVE BYTE TO SCREEN
	 INC   DI		    ;INCREMENT INDEX
	 INC   SI
	 LOOP  WAIT1		    ;MOVE NEXT BYTE
	 STI			    ;ENABLE INTERRUPTS
	 POP   ES		    ;RESTORE REGISTERS
	 POP   DS
	 POP   SI
	 POP   DI
	 POP   CX
	 POP   AX
	 IRET			    ;RETURN FROM INTERRUPT
CLK	 ENDP
UPDATE	 PROC  NEAR
	 PUSH  AX		    ;SAVE REGISTERS
	 PUSH  BX
	 PUSH  CX
	 PUSH  DX
	 PUSH  DS
	 MOV   AX,0040H 	    ;GET ADDRESS OF DOS TABLE
	 MOV   DS,AX		    ;PUT IN DS
	 MOV   AX,TIME_HI	    ;GET HIGH BYTE OF DOS TIME
	 mov   flag,0		    ;am flag
HOUR:	 CMP   AX,0CH		    ;CONVERT TO HOURS
	 JLE   H1
	 mov   flag,1		    ;set to pm
	 SUB   AX,0CH
	 JMP   HOUR
H1:	 AAM			    ;CONVERT TO ASCII
	 ADD   AX,3030H
	 LEA   BX,CS:TIME	    ;GET ADDRESS OF TIME AREA
	 MOV   CS:[BX],AH	    ;SAVE HOURS FIRST DIGIT
	 MOV   CS:[BX+2],AL	    ;SAVE HOURS SECOND DIGIT
	 MOV   AX,TIME_LO	    ;GET DOS TIME LOW BYTE
	 MOV   CX,8H		    ;CONVERT TO MINUTES
	 SHR   AX,CL
	 MOV   DX,3CH
	 MUL   DL
	 SHR   AX,CL
	 AAM			    ;CONVERT TO ASCII
	 ADD   AX,3030H
	 MOV   CS:[BX+6],AH	    ;SAVE MINUTES FIRST DIGIT
	 MOV   CS:[BX+8],AL	    ;SAVE MINUTES SECOND DIGIT
	 mov   byte ptr cs:[bx+12],'a'
	 cmp   flag,0		    ;is it am?
	 jz    goahead
	 mov   byte ptr cs:[bx+12],'p'
goahead:
	 mov   byte ptr cs:[bx+14],'m'
	 POP   DS		    ;RESTORE REGISTERS
	 POP   DX
	 POP   CX
	 POP   BX
	 POP   AX
	 RET
UPDATE	 ENDP
SETUP:	 MOV   AX,0		    ;GET ADDRESS OF VECTOR TABLE
	 MOV   DS,AX		    ;PUT IN DS
	 CLI			    ;DISABLE FURTHER INTERRUPTS
	 MOV   AX,[VEC_IP]	    ;GET ADDRESS OF OLD UPDATE IP
	 MOV   CS:[INT_IP],AX	    ;SAVE IT
	 MOV   AX,[VEC_CS]	    ;GET ADDRESS OF OLD UPDATE CS
	 MOV   CS:[INT_CS],AX	    ;SAVE IT
	 MOV   VEC_IP,OFFSET CLK_INT ;PUT ADDRESS OF CLK IN VECTOR IP
	 MOV   VEC_CS,CS	    ;PUT CS OF CLK IN VECTOR CS
	 STI			    ;ENABLE INTERRUPTS
	 MOV   AH,0FH		    ;READ VIDEO STATUS
	 INT   10H
	 SUB   AH,8		    ;SUBTRACT 8 CHAR TIME FROM NCOLS
	 SHL   AH,1		    ;MULTIPLY BY 2 FOR ATTRIBUTE
	 MOV   CS:SCR_OFF,AH	    ;SAVE SCREEN TIME LOCATION
	 MOV   WORD PTR CS:CRT_PORT,03BAH  ;SAVE MONO STATUS PORT ADDR
	 TEST  AL,4		    ;CHECK FOR COLOR MONITOR
	 JNZ   MONO		    ;IF MONO, MOVE ON
	 ADD   WORD PTR CS:SCR_OFF,8000H   ;ADD COLOR OFFSET TO TIME OFFSET
	 MOV   WORD PTR CS:CRT_PORT,03DAH  ;SAVE COLOR STATUS PORT ADDR
MONO:	 CALL  UPDATE		    ;DO FIRST UPDATE & PRINT TIME
	 MOV   DX,OFFSET SETUP	    ;GET END ADDRESS OF NEW INTERRUPT
	 INT   27H		    ;TERMINATE AND REMAIN RESIDENT
	 DB    117 DUP(0)	    ;FILLER
CODESEG  ENDS
	 END   CLK