home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
GLEN
/
CLOCKS11.ZIP
/
SCRNCLK.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-11-01
|
10KB
|
238 lines
TITLE SCREEN CLOCK FOR MS-DOS
PAGE 60,132
; SCRNCLK -- SCREEN CLOCK FOR MS-DOS (Z-150 OR IBM PC)
;
; THIS PROGRAM PROVIDES A SCREEN CLOCK FOR MS-DOS THAT FUNCTIONS
; LIKE THE HDOS AND CP/M SCREEN CLOCK PRESENTED IN REMARK #22,
; NOV., 1981.
;
; THE CLOCK IS TIMED INTERNALLY DUE TO THE INABILITY TO ACCESS THE
; SYSTEM TIME FROM THE BIOS. IT CAN BE SET TO THE SYSTEM TIME WITH
; THE COMPANION PROGRAM "CLOCK". THE COLOR OF THE DISPLAYED CLOCK
; IS DETERMINED BY THE LABEL "COLOR", BELOW. IF YOU ARE IN A B/W
; MODE, THE COLOR IS AUTOMATICALLY SET TO WHITE.
;
; BY PAT SWAYNE, Heath Users Group 22-MAY-84
; DEFINITIONS
BLUE EQU 001B ;color control bits
GREEN EQU 010B
CYAN EQU 011B
RED EQU 100B
MAGENTA EQU 101B
YELLOW EQU 110B ;(IBM calls it brown)
WHITE EQU 111B
COLOR EQU WHITE ;clock color
ROW EQU 0 ;put clock on top row
CALFAC EQU 89 ;calibration factor
SCRINT EQU 10H ;screen control interrupt
SCP EQU 2 ;set cursor position
GCP EQU 3 ;get curosr position
WCHAR EQU 9 ;write character
GVS EQU 15 ;get video state
TIMEINT EQU 1CH*4 ;IBM-PC timer interrupt vector
CLK SEGMENT
ASSUME CS:CLK,DS:CLK,ES:CLK,SS:CLK
ORG 100H
START: JMP SETUP ;set up clock interrupt, etc.
; clock data area
CLKFLG DB 1 ;clock on/off flag
SEC DB 0 ;second (binary)
MIN DB 0 ;minute
HOU DB 0 ;hour
TICCNT DB 18 ;tick counter
SECCNT DB 0 ;second counter (for calibration)
OLDIP DW 0 ;old instruction pointer
SYSSTK DW 0 ;system stack
SYSSTKS DW 0 ;system stack segment
CPOS DW 0 ;cursor position
CMODE DB 0 ;current video state
MODES DB 0,1,2,3,1,0,2,2 ;decoded modes
TIMSTR DB ' ' ;space before time
HOUR DW 0 ;hour (ascii)
DB ':'
MINUTE DW 0 ;minute
DB ':'
SECOND DW 0 ;second
DB 0FFH
DB 256 DUP(?) ;stack space
MYSTAK EQU $
; process clock interrupts here
DB 'CK' ;identifier
MYTIME: POP CS:OLDIP ;save instruction pointer
PUSH AX
DEC CS:TICCNT ;decrement tick counter
JNZ TIMEXIT ;not timed out
MOV CS:TICCNT,18 ;else, reset tick counter
MOV AL,CS:SECCNT ;get second counter
INC AL ;add one
CMP AL,CALFAC ;reached calibration factor?
MOV CS:SECCNT,AL ;update counter
JNZ NOTCAL ;cal factor not reached
MOV CS:SECCNT,0 ;else, zero counter
JMP SHORT TIMEXIT ;and exit
NOTCAL: MOV AL,CS:SEC ;get seconds
INC AL ;add one
CMP AL,60 ;60 seconds?
MOV CS:SEC,AL ;reset seconds
JNZ CHKFLG ;not a minute, check flag
MOV CS:SEC,0 ;else, zero seconds
MOV AL,CS:MIN ;get minutes
INC AL ;add one
CMP AL,60 ;60 minutes?
MOV CS:MIN,AL ;reset minutes
JNZ CHKFLG ;not an hour
MOV CS:MIN,0 ;else, zero minutes
MOV AL,CS:HOU ;get hour
INC AL ;add one
CMP AL,24 ;24 hours?
MOV CS:HOU,AL ;reset hours
JNZ CHKFLG ;not a day
MOV CS:HOU,0 ;else, zero hour
CHKFLG: CMP CS:CLKFLG,0 ;clock enabled?
JNZ UPDATE ;if so, update screen clock
TIMEXIT:POP AX
PUSH CS:OLDIP ;restore old instruction pointer
TIMEX DB 0EAH ;far jump instruction
DB 0,0,0,0 ;system timer address goes here
; a second has passed, print time on the screen
UPDATE: MOV CS:CLKFLG,0 ;disable other clock interrupts
MOV CS:SYSSTK,SP ;else, save system stack
MOV CS:SYSSTKS,SS ;save system stack segment
CLI ;kill interrupts (on at entry)
MOV AX,CS
MOV SS,AX ;put stack segment here
MOV SP,OFFSET MYSTAK ;set local stack
STI ;set interrupts
PUSH BX ;save registers
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH BP
MOV AX,CS
MOV DS,AX ;put ds here
PTIME: MOV AL,HOU ;get hours
CALL CONASC ;convert to ascii
MOV HOUR,AX ;result to buffer
MOV AL,MIN ;get minutes
CALL CONASC ;convert to ascii
MOV MINUTE,AX ;result to buffer
MOV AL,SEC ;get seconds
CALL CONASC ;convert to ascii
MOV SECOND,AX ;result to buffer
MOV AH,GVS
INT SCRINT ;get video state
PUSH BX ;save page
MOV BX,OFFSET MODES ;point to video modes
XLAT ;get mode code
MOV CMODE,AL ;save decoded mode
POP BX ;get page
MOV AH,GCP
INT SCRINT ;get cursor position
MOV CPOS,DX ;save it
MOV DH,ROW ;get row for clock
MOV DL,31 ;assume column 31
CMP BYTE PTR CMODE,2 ;80 column mode?
JB PTIME0 ;no
MOV DL,71 ;else, set column 71
PTIME0: MOV AH,SCP
INT SCRINT ;set cursor position to time area
MOV CX,9 ;set a counter
MOV BL,WHITE ;assume white color
CMP BYTE PTR CMODE,0 ;40 column B/W?
JZ PTIME1 ;yes
CMP BYTE PTR CMODE,2 ;80 column B/W?
JZ PTIME1
MOV BL,COLOR ;else, use color
PTIME1: MOV SI,OFFSET TIMSTR ;point to time string
PTMLP: LODSB ;get a digit
PUSH CX ;save counter
PUSH SI ;save pointer
CALL PDIGIT ;print digit
POP SI
POP CX
LOOP PTMLP ;loop until done
PDONE: MOV AH,SCP
MOV DX,CPOS
INT SCRINT ;restore cursor to user's position
POP BP
POP ES
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
CLI ;clear interrupts
MOV SS,CS:SYSSTKS ;restore system stack
MOV SP,CS:SYSSTK
STI ;set interrupts
MOV CS:CLKFLG,1 ;re-enable clock
JMP TIMEXIT ;and exit
; convert number in al to ascii digits in al,ah
CONASC: MOV AH,0 ;clear ah
MOV BH,10 ;get radix
DIV BH ;divide by it
ADD AX,'00' ;add ascii
RET
; print a digit on the screen
PDIGIT: MOV AH,WCHAR
MOV CX,1
INT SCRINT ;write character
MOV AH,GCP
INT SCRINT ;get cursor position
INC DL ;move it over
MOV AH,SCP
INT SCRINT ;set new cursor position
RET
LEND: ;end of resident code
; set up clock vector and initialize time
; then exit with program resident
SETUP: MOV AH,2CH
INT 21H ;get time
MOV SEC,DH ;save second
WFSEC: MOV AH,2CH
INT 21H ;get time again
CMP SEC,DH ;same second?
JZ WFSEC ;wait for a new second
MOV SEC,DH ;set seconds
MOV WORD PTR MIN,CX ;set minutes, hours
PUSH DS ;save ds
XOR AX,AX
MOV DS,AX ;DS at 0
MOV SI,OFFSET TIMEINT ;point to timer interrupt
LES DI,DWORD PTR [SI] ;get vector in ES:DI
CMP WORD PTR ES:-2[DI],'KC' ;clock already in?
JZ ITSIN ;yes
CLI ;else, turn off interrupts
MOV WORD PTR [SI],OFFSET MYTIME ;put in my vector
MOV 2[SI],CS ;and this segment
POP DS ;restore DS
MOV WORD PTR TIMEX+1,DI ;put old vector at our exit
MOV WORD PTR TIMEX+3,ES
STI
MOV DX,OFFSET LEND ;point to end of res. code
INT 27H ;exit, leave program here
ITSIN: INT 20H ;exit, nothing done
CLK ENDS
END START