; date.asm 6/24/85 compatible with DateStamper 2.0 ; runs under WordStar and other systems that modify 0001h ; print 'da Mon 19yr hr:mi:se' if real-time clock ; 'da Mon 19yr +nnnn' if relative clock ; ; Converted to Zilog mnemonics 12/6/87 Malcom Kemp ; RELCHAR EQU '+' bdos equ 0005 vers equ 26h aseg org 100h jp start db vers ; start: ld hl,0 add hl,sp ld (savstk),hl ld sp,stack call gtdate ;get bcd date/time pointer jp z,exit call ascdate ;format output string ex de,hl ld c,9 ;print the string call bdos exit: ld hl,(savstk) ;return to ccp ld sp,hl ; ckclk.asm 6/24/85 ;======================================== ; exit: hl = 0, Z set if no clock ; hl = DateStamper clock entry, Z reset if clock present ; clkadd is also set, so DSCLK can be called hereafter ; ; ; The logic for finding the clock is as follows: ; ; 1. Use BDOS version number call to check for DateStamper version >= 2.0 ; Call with E = 'D'. ; If DateStamper is installed, function returns H = 'D', L = 22h ; and DE = address of clock. ; ; 2. If version number test fails, check for DateStamper version 1. ; The DateStamper clock address is located from the ; bdos patch at LOGDR1+1 and is (LOGDR1+1) -49h. ; ; The checks must be done in this order to maintain compatibility ; with all DateStamper versions and non-standard bdos systems. ; GETVFN EQU 12 ;bdos get version function DSID EQU 'D' ;DateStamper ID for getversion call ; CKCLK: ld e,dsid ;special parameter for ld c,getvfn ; getversion call call bdos cp 22h ;must be 2.2 jp nz,noclk ld a,h cp dsid ;if H == DSID, ex de,hl ;..then clock addr was in de jp z,clka ;set it & return hl = clkadd, NZ ; ; else find bios vector & test for clock ; ; exit: NZ if test satisfied, hl = clock addr ; Z, hl=0 if not (end of memory reached) ; tst2: ld hl,(0001h) ;start at wb ptr retryj: call fndjmps jp z,retryx ;never found push hl ;save the found jmp vector call tstclk pop de ret nz ;found clock, hl = clockaddr ex de,hl ;no clock there, inc h ;..try next page up jp nz,retryj retryx: ld l,0 ;hl=0 ret ;z,hl=0 is not found ; ; test for 14 successive jumps, beginning with warmboot ; return: hl=base, Z set if found ; else NZ ; ; test omits coldboot, liststat and sectran ; which can be inline code in some bioses ; JCNT EQU 14 ; fndjmps:ld a,0c3h ; 8080 JMP instr testj: ld b,jcnt ld l,3 ;wboot ptr for page boundary vector lpj: cp (hl) jp z,okj inc h ;bump to next pg jp nz,testj ret ;z if never found okj: inc hl ;bump to next jmp inc hl inc hl dec b jp nz,lpj inc b ;Nz if found ret ; ; TSTLK - check for resident DateStamper clock ; 6/24/85 vers 2.0 ; ; enter: h = page of presumed bios base ; ; internal bdos addresses relative to base of bdos ; LOGDR1 EQU 0C42H ;'jmp 06a3' in standard cp/m 2.2 HILOGD EQU 0CH LOLOGD EQU 042H BITMAP EQU 06A3H ;addresses to be checked LOBITM EQU 0A3H HIBITM EQU 06H DELTAP EQU [HILOGD-HIBITM] GETVER EQU 0C7EH ;'mvi a,022h' in standard cp/m 2.2 IDSUM EQU 011H ;7-bit checksum of "<3bangs>TIME&DAT" CLKOFF EQU 42H+7H ;offset to DateStamper clock from (LOGDR1+1) BIOSWB EQU 0E03H ;bios warmboot address ; TSTCLK: ; ; test for version 1 bdos patch in standard 2.2 bdos ; ld b,h ;save b = bios base page ld l,3 ld de,[getver+1-bioswb] ;check for cp/m 2.2 vers byte add hl,de ld a,(hl) cp 22h jp nz,noclk ;not standard cp/m 2.2 bdos ; ; Version byte shows 2.2. Check for DateStamper patch at LOGDR1 ; ; unpatched 2.2 std bdos: JMP BITMAP ; patched std bdos: JMP dsaddress ; other: unknown ld de,[logdr1+1]-[getver+1] add hl,de ;point at addr word ld e,(hl) ;de = D/S addr, if resident ld a,e cp lobitm ;check low byte inc hl ld d,(hl) jp nz,check2 ld a,d ;check hi byte add deltap ;page difference in rel. addresses cp h jp nz,check2 ; noclk: ld hl,0 ;standard, unpatched 2.2 bdos ==> no clock jp clka ; ; ; Address differs from std. 2.2 bdos. ; Check whether it is internal to the bdos. ; check2: ld a,b ;base page of bios sub d ccf jp nc,stdclk ;external addr above bdos sub 0eh ;page length of bdos jp c,noclk ;addr is within bdos ; stdclk: ld hl,-clkoff ;calc. entry to DateStamper clock add hl,de ; clka: ld (xclkadd+1),hl ;set addr in ram for clock calls ld a,h or l ;Z if no clock ret ; ; ; read the DateStamper clock ; ; enter: hl -> 6-byte buffer for date/time ; exit: if no clock: hl = 0, NO CY (CLEAR) ; if clock: hl = entering hl, CY set ; current time at (hl)...(hl+5) DSCLK: EX DE,HL ;buffer ptr to de ld hl,(xclkadd+1) ;do we have a resident clock? ld a,h or l ret z ;return hl = 0, Z set ex de,hl ;buffer ptr to hl xclkadd:call 0000 ;call DateStamper clock scf ;cy is a clock ret ;======================================== ; ; get bcd date&time ; ; exit: hl = 0, Z set if no DateStamper clock ; hl = bcd buffer, Z reset if DateStamper clock ; gtdate: call ckclk ret z ;return hl = 0 (no clock) ld hl,bcdbuf push hl call dsclk pop hl ;return ptr to bcd buffer ld a,h or l ;nz ret ; bcdbuf: ds 6 ; ; format date & time for bdos string ; enter:hl = 6 byte bcd buffer ; exit: hl = formatted string, '$' terminated ; ascdate:ld de,abuf ld a,(hl) ;get bcd yr ld (yr),a inc hl inc hl ld a,(hl) ;get bcd day push hl call putbcd pop hl dec hl ld a,(hl) ;get bcd month call bcd2bin dec a ;1...12 ->0...11 ld b,a add a,a add a,b ;*3 = length of 'mon' ld e,a ld d,0 push hl ld hl,montbl ;index to 'mon' add hl,de ld b,3 ;move 'mon' to buffer ld de,amo call move ld de,ayr ;now year yr equ $+1 ld a,00 call putbcd ; pop hl inc hl inc hl ;ptr to bcd hour ld a,(hl) ;check hi bit of hour byte rla ld a,(hl) ld de,ahr ;set ptr jp nc,doreg call reltim ;BIT 7 ==> ordinal clock time jp gtxit doreg: call regtim gtxit: ld hl,abuf ret ;bcd (a) -> binary (a), uses bc bcd2bin: ld c,a and 0f0h rra rra rra rra ld b,a add a,a add a,a add a,b add a,a ;*10 ld b,a ld a,c and 00fh add a,b ret ; ; 'relative' time is stored as binary word +8000h, inverted byte order ; reltim: sub 80h ;deduct for hi bit push af inc hl ;get LOW order byte ld l,(hl) pop af ;and HI one ld h,a ld a,relchar ld (de),a ; store '+' inc de ex de,hl ld (decptr),hl ex de,hl call deczh ;put hl as +0000 ld hl,ahr+5 ; clear rest of field ld b,acrlf+1-[ahr+5] clrlp: ld (hl),' ' inc hl dec b jp nz,clrlp ret abuf: db '00 ' amo: db 'Jan 19' ayr: db '00 ' ahr: db '00:00:00' acrlf: db 0dh,0ah db '$' montbl: db 'JanFebMarAprMayJunJulAug' db 'SepOctNovDec' ; regtim: call putbcd ;hour ld a,':' ld (de),a inc de inc hl call putmbcd ;min ld a,':' ld (de),a inc de inc hl ;..sec putmbcd:ld a,(hl) ; ; put (A) at d,d+1 in bcd ; putbcd: push af and 0f0h rra rra rra rra call putbin pop af and 0fh putbin: add '0' ld (de),a inc de ret ; move: ld a,(hl) ld (de),a inc hl inc de dec b jp nz,move ret ; ; Print HL in decimal with leading zeros ; deczh: ld de,-1000 ;print 1000's digit call digit ld de,-100 ;etc. call digit ld de,-10 call digit ld a,'0' ;get 1's digit add a,l jp putdig ; digit: ld b,'0' ;start off with ascii 0 ; diglp: push hl ;save current remainder add hl,de ;subtract jp nc,digex ;quit on overflow pop af ;throw away remainder inc b ;bump digit jp diglp ;loop back ; digex: pop hl ;restore pointer ld a,b ; putdig: push hl ;put (A) at (ptr++) ld hl,(decptr) ld (hl),a inc hl ld (decptr),hl pop hl ret decptr: dw 0 ; ds 24 stack: savstk: dw 0 end TIMEBSX 180%XBIOSB11HB nDU4 180ZCALC BAKf?@H