home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource3
/
147_01
/
daytim.csm
< prev
next >
Wrap
Text File
|
1985-03-11
|
11KB
|
479 lines
;
;
;
; Contains:
;
; timdif a generic time difference routine
; originally written by Sigi Kluger, and
; modified to work as a .CSM for BDS-C.
;
; daytim returns in HL, a pointer a
; null-terminated string of the form:
;
; dd mmm yy hh:mm:ss
;
; uses CPM+ and MPM function #105
;
; Note: this module should work with the following operating systems:
;
; CPM 3.x (aka "CPM+")
; MP/M 2.x and higher
; TurboDOS 1.2x, 1.3x, and, presumably, higher
; Not (of course) CPM 1.x and 2.x, which have no real-time functions
;
; Note that it has only been tested with CP/M 3.1. --Ron Fowler
;
;
INCLUDE "a:bds.lib"
;
;TIMEDIF.ASM v1.10
;12/28/83
;By S. Kluger
;
;Converted to CSM file by FJW 12/31/83
;
;
; 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...
;
FUNCTION timdif
timdif: call arghak
push b
lhld arg1 ;point to start time (sttime)
call chform ;check proper format
jc exit ;return if error
lhld arg2 ;point to end time (entime)
call chform ;check that too
jc exit
;
; The stage is set - let's get down to business...
;
lhld arg1
lxi d,6
dad d ;point to seconds start (sttime+6)
call getbin ;get binary
mov d,a ;save it
push d
lhld arg2
lxi d,6
dad d ;seconds end (entime+6)
pop d
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: push d
lhld arg3
lxi d,7
dad d
pop d ;store as result (elaptm+7)
call stora
;
; Do the same stuff for minutes
;
push d
lhld arg1
lxi d,3
dad d ;minutes start (sttime+3)
pop d
call getbin ;get binary
mov d,a ;save binary
push d
lhld arg2
lxi d,3
dad d ;minutes end (entime+3)
pop d
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: push d
lhld arg3
lxi d,4
dad d ;store elapsed minutes (elaptm+4)
pop d
call stora
;
; Finally, here go the hours.
;
lhld arg1 ;hours start (sttime)
call getbin ;get 'em
mov d,a ;save start hours
lhld arg2 ;hours end (entime)
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: lhld arg3
inx h ;save as hours (elaptm+1)
call stora
xra a ;make sure error is reset
exit: pop b
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,0ffh ;-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
;
ENDFUNC
;
FUNCTION daytim
;
push b
lxi d,jdate ;pointer to date/time bufr
mvi c,105 ;C=return date/time function
call 0005h ;get date/time
sta secs ;cpm3 returns seconds in a
lxi d,datbuf ;get date buffer
lhld jdate ;fetch julian date
call dspdat ;display date in date buffer
call dsptim ;display time in time buffer
lxi h,datbuf ;get date buffer
xra a
pop b
ret
;
; Function 'dspdat' converts a Julian Date to ASCII.
;
; Call dspdat with address of ASCII string return buffer (9 bytes long)
; in DE, and Julian date to be converted in HL.
;
;
; Registers AF-BC-DE-HL-IX are destroyed.
;
dspdat: push d ;save return address
lxi d,yyear ;pass buffer to fmjul
call fmjul ;calculate y-m-d
pop h ;return address to hl
lda yday ;check for error
ora a
jz err
call decmem ;convert to decimal
mvi m,' ' ;move in a space
inx h
push h ;save pointer
lhld ymonth ;get month number
mvi h,0 ;make double length
dcx h ;make base 0
mov d,h ;multiply by 3
mov e,l
dad d
dad d
lxi d,months ;calculate month table address
dad d
pop d ;recover pointer
lxi b,3 ;length of move
db 0edh,0b0h ;LDIR ;move month into string
xchg ;pointer back to hl
mvi m,' ' ;move in a space
inx h
lda yyear ;get year
call decmem ;convert to decimal
jmp x ;done
err: mvi b,9 ;error, return 9 *'s
erl: mvi m,'*'
inx h
db 010h,0fbh ;DJNZ erl
x: mvi m,' ' ;insert delimeter
ret ;done
;
;
; Function 'dsptim' converts a bcd hours, minutes, and seconds to ASCII.
;
dsptim: lxi h,timbuf ;get time buffer
lxi d,hours ;get hours/minutes/seconds
ldax d ;get hours
inx d ;advance pointer
call bcdout ;convert hours to ascii
mvi m,':' ;inset colon
inx h
ldax d ;get minutes
inx d ;advance pointer
call bcdout ;convert minutes to ascii
mvi m,':' ;insert colon
inx h
ldax d ;get seconds
call bcdout ;convert seconds to ascii
mvi m,0 ;insert delimeter
ret ;done
;
decmem: mvi b,'0'-1 ;convert a-reg to decimal
dec: inr b
sui 10
jp dec
mov m,b
inx h
adi 10+'0'
mov m,a
inx h
ret
;
bcdout: push psw ;convert a-reg (bcd) to decimal
rrc ;hi nybble
rrc
rrc
rrc
call bcd1 ;process hi nybble
pop psw ;then lo
bcd1: ani 0fh ;4 bits only
adi '0' ;add ascii bias
mov m,a ;store it
inx h
ret
;
; routine to convert modified julian date passed in hl to
; yy/mm/dd form, into buffer passed in de. passed buffer
; looks like this:
;
; db year (bcd)
; db month "
; db date "
;
; returned julian date is the day number using a base date
; of jan 1 of "baseyr" (defined below)
;
;
baseyr equ 78 ;base year of date system (1978)
;
; we begin...
;
fmjul: push d ;save buffer pointer (for later)
mvi b,baseyr ;base year in b
;
; scan through years starting at baseyr
; subtracting days from our current date
;
julp: mov a,b ;fetch current year