;***********************************************************************
;                                CLOCK.ASM
;***********************************************************************
;Description:
;            An extremely simple TSR that loads the time to the upper right
;            corner of the screen from (70,0) to (79,0).
;            It uses int 1Ah to read real time, and int 10H to go to the
;            locations needed and writes it.
;Comments:
;            For advanced programmers this program seems clumsy, they may
;            wonder :
;                -  Why in earth would you use int 10 functions and need to
;            put the cursor up to the location, then write the character, then
;            go back, and continue this way while you could've written direct-
;            ly to the screen at location 0B800H CGA buffer?
;
;               -  Why use int 1AH and need to do all these corrections to the
;            hour, minute, and seconds while you could've applied int 21H's
;            DOS functions to get the time?
;
;               -  Why in earth need to write this program at all, while you
;            can know the time by writing time at the DOS prompt?
;
;            The answers of all these questions is :
;                It's possible to write directly to the buffer, and it's also
;                possible to use DOS's get time function. But I did it the
;                hard way to demonstrate the use of these interrupts. The truth
;                is that this program could've been and faster easier to build.
;                But,,,,,

;            Why I wrote this program is another matter, it's because I
;            needed to since I used to enter telnet from an NFS system in a
;            LAN, and needed to run some unix command to get the time, so I
;            said why not write the program to stay even in telnet shells?
;            And I did. If you think that it's of no use, you may delete it!
;
;               Thanx for getting my program, please report any bugs to:
;
;                               Walid Al-Saqqaf
;                               e78199@erkin.ceng.metu.edu.tr
;**********************************************************************


        .MODEL  SMALL
        .CODE
        ORG     100H
FIRST:  jmp     Install
        old_int_label       label   word
        old_int             dd      ?
        H                   db      ?; hours
        M                   db      ?; minutes
        S                   db      ?; seconds
        LD                  db      ?; lower digit
        HD                  db      ?; higher digit
new_int PROC
        push    ax      ;save registers and flags
        push    bx
        push    cx
        push    dx
        pushf

        mov     ah,03           ;save the original x,y coord.
        mov     bh,0
        int     10h             ; dh:row,dl:col
        push    cx
        push    dx
        mov     ah,1            ;and hide cursor for a while
        mov     cx,2000h
        int     10h

;Begin WRITE TIME
        mov    ah,2             ;Get time from CMOS directly, (not from DOS)
        int    1Ah              ;Use the interrrupt 1Ah to get real time
        cmp    ch,25            ;from RTC (CMOS)
        jle     h1
        sub    ch,12
        jmp    h2
h1:     cmp    ch,9             ;Adjust the hour's value from RTC to resolve
        jle     h2              ;the actual time
        sub    ch,6
h2:     mov    H,ch

        cmp    cl,73
        jle     m1
        sub    cl,30         ;Adjust the minutes' value from RTC to resolve
        jmp    m5            ;the correct minutes' value
m1:     cmp    cl,57
        jle     m2
        sub    cl,24
        jmp    m5
m2:     cmp    cl,41
        jle     m3
        sub    cl,18
        jmp    m5
m3:     cmp    cl,25
        jle     m4
        sub    cl,12
        jmp    m5
m4:     cmp    cl,9
        jle     m5
        sub    cl,6
m5:     mov    M,cl

        cmp    dh,73
        jle     s1          ;Adjust the seconds' value from RTC to resolve
        sub    dh,30        ;the correct seconds' value
        jmp    s5
s1:     cmp    dh,57
        jle     s2
        sub    dh,24
        jmp    s5
s2:     cmp    dh,41
        jle     s3
        sub    dh,18
        jmp    s5
s3:     cmp    dh,25
        jle     s4
        sub    dh,12
        jmp    s5
s4:     cmp    dh,9
        jle     s5
        sub    dh,6
s5:     mov    S,dh

        mov     ah,0           ;Since we can only type one digit at a time,
        mov     al,H           ;with the int 10H, We should partition the
        mov     bl,10          ;BCD value of H, M, and S to 2 digits (LD,HD)
        div     bl
        mov     HD,al
        mov     LD,ah          ;get HD & LD of hours (low and high digits)

        mov     ah,2           ;go to position (2,70)
        mov     dh,0
        mov     dl,70
        int     10h
        mov     ah,9
        mov     al,'º'        ;and write a 'º'
        mov     bl,27
        mov     cx,1
        int     10h

        mov     ah,2           ;go to hour position (2,71)
        mov     dl,71
        int     10h
        mov     ah,9
        add     HD,48
        mov     al,HD        ;and First write HD of the Hours
        mov     bl,27
        int     10h

        mov     ah,2           ;go to hour position (2,72)
        mov     dl,72
        int     10h
        mov     ah,9
        add     LD,48
        mov     al,LD        ;and write the LD of Hours
        mov     bl,27
        int     10h

        mov     ah,2           ;go to hour's : position (2,73)
        mov     dl,73
        int     10h
        mov     ah,9
        mov     al,':'        ;and write a ':'
        mov     bl,27
        int     10h

        mov     ah,0
        mov     al,M
        mov     bl,10
        div     bl              ;get HD & B of Minutes
        mov     HD,al
        mov     LD,ah

        mov     ah,2           ;go to hour position (2,74)
        mov     dl,74
        int     10h
        mov     ah,9
        add     HD,48
        mov     al,HD        ;and First write HD of the Minutes
        mov     bl,27
        int     10h

        mov     ah,2           ;go to Minute position (2,75)
        mov     dl,75
        int     10h
        mov     ah,9
        add     LD,48
        mov     al,LD        ;and write the LD of Minutes
        mov     bl,27
        int     10h

        mov     ah,2           ;go to  position (2,76)
        mov     dl,76
        int     10h
        mov     ah,9
        mov     al,58        ;and write a blinking ':'
        mov     bl,155       
        int     10h

        mov     ah,0
        mov     al,S
        mov     bl,10
        div     bl              ;get HD & LD of Seconds
        mov     HD,al
        mov     LD,ah

        mov     ah,2           ;go to second's position (2,77)
        mov     dl,77
        int     10h
        mov     ah,9
        add     HD,48
        mov     al,HD        ;and First write HD of the Seconds
        mov     bl,27
        mov     cx,1
        int     10h

        mov     ah,2           ;go to hour position (2,78)
        mov     dl,78
        int     10h
        mov     ah,9
        add     LD,48
        mov     al,LD        ;and write the LD of Seconds
        mov     bl,27
        int     10h

        mov     ah,2           ;go to position (2,79)
        mov     dl,79
        int     10h
        mov     ah,9
        mov     al,'º'        ;and write a 'º'
        mov     bl,27
        int     10h
;End write time

exit:   mov     ah,1            ;enable cursor
        mov     ch,6
        mov     cl,7
        int     10h

        pop     dx
        mov     ah,02           ;go back to where you were
        int     10h
        pop     cx
        mov     ah,1            ;with the same cursor type
        int     10h

        popf
        pop     dx      ;restore registers
        pop     cx
        pop     bx
        pop     ax
        pushf
        call    old_int      ;and call old_int (original int 8)
        iret
new_int    ENDP

Install       PROC
        mov     ax,3508h
        int     21h
        mov     old_int_label, bx
        mov     old_int_label[2], es    ;save the old int 8
        mov     ah, 25h
        lea     dx, new_int
        int     21h                     ;associate new_int with int 8
        mov     dx, offset Install
        int     27h
Install       ENDP
        END     FIRST

