*****************************************************************
*		     AMPRO Computers Inc.			*
*  			   Time.asm				*
*								*
* 		     Adapted from TIME.MAC 			*
*	                by Don Delwood, 			*
*	            with mods by Roger Warren			*	
*****************************************************************
;
; Version    date	  by	History
; -------  --------	------	--------
;   1.0	   4 mar 86	 fsw	Version 1.0 for use with bios 3.6
;
*---------------------------------------------------------------*

VER	EQU	10		; version 1.0

CR	EQU	13
LF	EQU	10

LDIR	EQU	0B0EDH		; z80 ldir

	ORG	100H
	JMP	BEGIN		; jump over logo
HELP:	CALL	PRINT
	DB	CR,LF,LF
	DB	'TIME '
	DB	'Version ',VER/10+'0','.',VER MOD 10+'0',CR,LF
	DB	'AMPRO Computers Inc.'
	DB	CR,LF,'To change the time, enter change '
	DB	'on the command line as follows:',cr,lf,lf
	DB	'du>TIME hh:mm:ss',cr,lf
	DB	0
	JMP	EXIT
BEGIN:	
	DW	73EDH,OLDSTK	; save old stack pointer
	LXI	SP,LOCSTK	; set new stack
;
	LXI	D,WBOOT		; build bios entry table
	LHLD	1		; get bios start
	LXI	B,51		; bytes to move
	DW	LDIR		; move it
;
	CALL	GETTBL		; get address of next jmp tbl
	CPI	36		; must be bios ver 3.6 or higher
	JC	BADVER		; give message and exit
	LXI	D,NXTTBL	; 'hl' has bios nxttbl address
	LXI	B,15		; 
	DW	LDIR		; move the table
	LXI	H,0		; make sure that clock is enabled
	CALL	TOD		; get clock base address
	MOV	A,L		; see if address of tick was returned
	ORA	H
	JZ	NOCLK		; exit clock not enabled

; 'hl' has addres of clock

	LXI	D,SEC		; move time
	LXI	B,6
	DW	LDIR		; save time

; Everthing needed has been moved into program area now.
; parse command tail to see if time was entered on command line.
;
	LXI	H,80H		; point to command tail
	MOV	A,M		; get character count
	ANA	A		; if zero nothing on cmd line
	STA	UPDATE		; save possible entry on cmd line
	JZ	SHTIME		; skip
	PUSH	H
	CALL	VALID		; see if numeric ascii
	POP	H
LOOP:	INX	H		; point to first entry
	MOV	A,M
	CPI	' '		; should be no leading spaces
	JZ	LOOP		; exit
	CALL	EVAL10
	CPI	24		; see if more the 24:00 hrs
	JNC	NVALMS
	STA	HOUR		; store hour
	INX	H
	CALL	EVAL10
	CPI	60		; see if more than 59 min
	JNC	NVALMS		; 
	STA	MIN		; store min
	INX	H
	CALL	EVAL10
	CPI	60		; see if more than 59 sec
	JNC	NVALMS
	STA	SEC

;
; convert the binary counts to ascii characters and dispaly
;
; make seconds

SHTIME:	LDA	SEC		; get seconds count
	CALL	BINASC		; convert to ascii
	DW	43EDH,SC	; ld(sc),bc - save seconds

; make minutes
	
	LDA	MIN		; get minutes count
	CALL	BINASC		; convert to ascii
	DW	43EDH,MN	; ld(mn),bc - save minutes

; make hours

	LDA	HOUR		; get hours
	CALL	BINASC		; convert to ascii
	DW	43EDH,HR	; ld(hr),bc - save hours

	CALL 	PRINT		; print message
CURTIM:	DB	'Current time is '
HR:	DB	'  :'
MN:	DB	'  :'
SC:	DB	'  '
	DB	0

;
; if time was not changed from the command line, do not place
; the time prameters back into the bios clock area.
;
	LDA	UPDATE
	ANA	A		; if zero time was only displayed
	JZ	EXIT
;
; move the new time prameters to bios clock area
;
	CALL	TOD		; get address of time counters
	XCHG			; bios time counter addresss to 'de'
	LXI	H,SEC		; 
	LXI	B,3		; time only, not date
	DW	LDIR		; move it to bios memory
	JMP	EXIT
;
; Test the command for valid time entry. Scan the command tail
; for along its legnth for the pattern hh:mm:ss. test for
; valid numeric characters. it has already been determined that
; somthing was entered on the command line
; 
VALID:	LXI	H,80H		; character count
	MOV	B,M		; get number of characters typed
	INX	H
	DCR	B
	JZ	NVALMS		; exit only spaces or one char on line
	MOV	A,M		; get first char
	CPI	' '
	JZ	VALID+4		; filter the spaces

VAL1:	MOV	A,M
	INX	H		; point to next char
	ANA	A		; 00h is terminator or zero count
	RZ
	CPI	'/'
	JZ	HELP		; show help
	CPI	'?'
	JZ	HELP		; show help
	CPI	':'
	JZ	VAL1		; delimeter ok
	CPI	'0'	
	JC	NVALMS		; less than ascii 0
	CPI	'9'+1
	JNC	NVALMS		; more than ascii 9
	JMP	VAL1
	
NVALMS:	CALL	PRINT
	DB	'Invalid time',cr,lf,0
	JMP	EXIT
;
; time of day TOD jmp was not in bios
;
NOCLK:
	CALL	PRINT
	DB	'Clock not installed',cr,lf,0
	JMP	EXIT
;
; wrong version bios
;
BADVER:	CALL	PRINT
	DB	'Requires Bios 3.6 or higher.',cr,lf,0
				; fall through to exit

;
; Normal program exit. Restores system stack and returns
;
EXIT:	
	DW	7BEDH,OLDSTK	; recover old stack pointer
	RET

;
; Print string of characters terminated with zero '0'.
;
PRINT:	POP	H
	MOV	A,M		; get byte
	ANA	A
	JZ	PRNEND
	PUSH	H		;
	MOV	C,A
	CALL	CONOUT		; call bios routine
	POP	H
	INX	H		; next byte
	JMP	PRINT+1

PRNEND:	XTHL			; hl has return
	RET

;***************************************************************
;		convert binary to ascii
; in:	a  - binary value
; out:	bc - ascii character (low high)	  (mod. after Rich Conn)
;***************************************************************
BINASC:	MVI	C,0		; init count
	MVI	B,10

BIN1:	SUB	B
	JC	BINEXT
	INR	C
	JMP	BIN1

binext:	ADD	B		; A = ones digit  C = tens digit
	ADI	'0'
	MOV	B,A
	MOV	A,C
	ADI	'0'
	MOV	C,A	
	RET
								
;***************************************************************
;	eval10 - convert ascii string to decimal value
; in:	hl - points to beginning of string
; out:	a  - e
;	de - value
;	hl - points to delimiter (error character)   
;					(mod. after Rich Conn)
;***************************************************************

EVAL10:	PUSH	B
	LXI	D,0		; init de to zero

E10L:	MOV	A,M		; next digit, check range '0'-'9'
	CPI	'0'
	JC	EVLOUT		; less than ascii 0
	CPI	'9'+1
	JNC	EVLOUT		; more than ascii 9
	SUI	'0'

MUL10:	PUSH	H		; multiply DE by 10
	MOV	H,D
	MOV	L,E
	DAD	H		; *2
	DAD	H		; *4
	DAD	D		; *5
	DAD	H		; *10
	MOV	E,A		; add in latest digit
	MVI	D,0
	DAD	D
	XCHG
	POP	H
	INX	H
	JMP	E10L

EVLOUT:	MOV	A,E
	POP	B
	RET
	
; local stack area
;
	DS	32		; 16 level stack
LOCSTK:	DW	EXIT		; exit point on top of stack
OLDSTK: DS	2		; save for old stack
UPDATE	DS	1		; flag for command entry
;
; bios entry table
;
WBOOT:	DS	3		; Warm start
CONST:	DS	3		; Console status
CONIN:	DS	3		; Console character in
CONOUT:	DS	3		; Console character out
LIST:	DS	3		; List character out
PUNCH:	DS	3		; Punch character out
READER:	DS	3		; Reader character in
HOME:	DS	3		; Seek to home position
SELDSK:	DS	3		; Select disk
SETTRK:	DS	3		; Set track number
SETSEC:	DS	3		; Set sector number
SETDMA:	DS	3		; Set DMA address
READ:	DS	3		; Read disk
WRITE:	DS	3		; Write disk
LISTST:	DS	3		; Return list status
SECTRAN:DS	3 		; Sector translate

GETTBL:	DS	3		; Point to more jumps, returns bioss
				; version in 'a'.
				; 

NXTTBL:	
SWAP:	DS	3		; jmp swap
HD$INF:	DS	3		; get hd table info
PHTBAC:	DS	3		; get/set phytab acces
PAGET:	DS	3		; get phytab entry address
TOD:	DS	3		; get base address of clock tick

SEC:	DS	1
MIN:	DS	1
HOUR:	DS	1
DAY:	DS	2
YEAR:	DS	1

	END
