;TIMEDIF.ASM v1.10
;12/28/83
;By S. Kluger
;
; the fact that a major bug has not been discovered yet by
; anyone proves the popularity of the program...
;
; This is a module for use with RMAC and can be adapted to
; M80 with minimum effort.
;
; Purpose:
; Evaluate two ASCII character strings in HH:MM:SS format and
; return their difference.
;
; Entry point:  TIMDIF
; Externals:    STTIME
;               ENTIME
;               ELAPTM
;
; Input parameters:
; STTIME holds a time string of HH:MM:SS format. STTIME must point
; to the tens hours digit. The time string must be in 24 hour format.
; The time stored there should be the beginning time of an event.
;
; ENTIME holds a string with the same format. The time stored there
; should be the end of an event.
;
; On return, ELAPTM will be filled with the elapsed time in
; hours and minutes and the accumulator will be cleared with the
; ZERO flag SET. If either entry parameter contained an illegal
; quantity, the CARRY flag will be SET and ELAPTM will be undefined.
; NOTE: TIMDIF will not place delimiters into ELAPTM!
;
; Only the first 8 characters of the strings are processed and checked
; for proper range. Be sure to zero the seconds field if not needed!
;
; NOTE:
; If ENTIME is smaller than STTIME, then 24 hours are added to ENTIME.
;
; This routine is intended for application where the event time will
; never be greater than 23:59:59 (RCPM and BBS use mainly).
;
       PUBLIC  TIMDIF          ;entry point
       EXTRN   STTIME          ;start time field
       EXTRN   ENTIME          ;end time field
       EXTRN   ELAPTM          ;elapsed time field
;
       cseg
;
; Entry point. All registers meet their doom...
;
timdif: lxi     h,sttime        ;point to start time
       call    chform          ;check proper format
       rc                      ;return if error
       lxi     h,entime        ;point to end time
       call    chform          ;check that too
       rc
;
; The stage is set - let's get down to business...
;
       lxi     h,sttime+6      ;point to seconds start
       call    getbin          ;get binary
       mov     d,a             ;save it
       lxi     h,entime+6      ;seconds end
       call    getbin          ;get binary
       mvi     e,0             ;reset our private borrow flag
       sub     d               ;subtract
       jnc     skbs            ;skip if no borrow
       dcr     e               ;set our borrow flag
       adi     60              ;make mod 60
skbs:   lxi     h,elaptm+7      ;store as result
       call    stora
;
; Do the same stuff for minutes
;
       lxi     h,sttime+3      ;minutes start
       call    getbin          ;get binary
       mov     d,a             ;save binary
       lxi     h,entime+3      ;minutes end
       call    getbin          ;get binary
       inr     e               ;if not borrow...
       jnz     skbm1           ;then skip...
       inr     d               ;...else add borrowed value
skbm1:  mvi     e,0             ;make sure borrow flag reset
       sub     d               ;subtract
       jnc     skbm2           ;skip if no borrow
       dcr     e               ;set borrow
       adi     60              ;make mod 60
skbm2:  lxi     h,elaptm+4      ;store elapsed minutes
       call    stora
;
; Finally, here go the hours.
;
       lxi     h,sttime        ;hours start
       call    getbin          ;get 'em
       mov     d,a             ;save start hours
       lxi     h,entime        ;hours end
       call    getbin          ;get binary
       inr     e               ;if not borrow...
       jnz     skbh1           ;...then skip...
       inr     d               ;...else add borrowed hour
skbh1:  sub     d               ;subtract
       jnc     skbh2           ;jump if no borrow
       adi     24              ;else add 24 hours
skbh2:  lxi     h,elaptm+1      ;save as hours
       call    stora
       xra     a               ;make sure error is reset
       ret                     ;end of execution, back to caller.
;
; Get the ASCII value at HL as a binary into A
;
getbin: mov     a,m             ;get tens
       ani     0fh             ;strip ASCII offset
       mov     b,a             ;save tens
       xra     a               ;set accumulator
       mvi     c,10            ;set up cheap multiplier
mul:    add     c
       dcr     b
       jnz     mul
       mov     b,a             ;save tens
       inx     h               ;point to units
       mov     a,m             ;get units
       ani     0fh             ;same treatment
       add     b               ;add the tens
       ret
;
; Check format of HH:MM:SS string. Checks all digits for presence
; and validity.
;
chform: mov     a,m             ;get 10s H
       cpi     '0'
       rc
       cpi     '3'
       cmc
       rc
       inx     h
       mov     a,m             ;get 1s H
       call    ck10            ;check decimal
       rc
       inx     h               ;get colon
       mov     a,m
       cpi     ':'
       stc
       rnz
       inx     h               ;point to 10s M
       mov     a,m
       call    ck6             ;check hex
       rc
       inx     h
       mov     a,m             ;1s M
       call    ck10
       rc
       inx     h
       mov     a,m             ;get delimiter
       cpi     ':'
       stc
       rnz
       inx     h
       mov     a,m             ;get 10s S
       call    ck6
       rc
       inx     h
       mov     a,m
ck10:   cpi     '0'
       rc
       cpi     '9'+1
       cmc
       ret
;
ck6:    cpi     '0'
       rc
       cpi     '7'
       cmc
       ret
;
; Store accumulator as ASCII digits at HL and HL+1
;
stora:  mvi     b,-1
tlp:    inr     b
       sui     10              ;subtract 10
       jnc     tlp             ;until borrow
       adi     10              ;make mod 10
       ori     '0'             ;make ASCII
       mov     m,a
       dcx     h
       mvi     a,'0'
       add     b
       mov     m,a
       ret
;
       end