	title	'PROF-180X time and user moule'
;
;	Zeit und User Module fuer PROF-180X
;
;	letzte Aenderung am 13.01.1986 (Joachim)
;
	public	?time,?user
;
	extrn	@date,@hour,@min,@sec
	extrn	dmatrans,adrtab
;
	maclib	hd64180
;
	maclib	psys
;
	maclib	pvec
;
	dseg
;
?time:

	push	h		;rette hl und de
	push	d		;
	mov	a,c		;lesen oder setzen
	ora	a		;setze flags
	jz	set$scb		;setze scb neu
				;setze zeit neu
				;berechne aus der absolutem zahl das datum
	lhld	@date		;lese datumszahl aus scb
	lxi	d,730		;setze auf 1 jan. 1980
	stc ! cmc		;loesche carry bit
	dsbc	d		;subtrahiere
	jc	time$ret	;zeit vor 1980, keine aenderung
	mvi	c,0		;zaehler fuer jahreszahl nach 1980
year$loop:			;
	lxi	d,366		;ziehe schaltjahr ab
	call	sub$end		;
	lxi	d,365		;ziehe drei normale jahre ab
	call	sub$end		;
	call	sub$end		;
	call	sub$end		;
	jr	year$loop	;beginne wieder von vorne
sub$end:			;
	stc ! cmc		;loesche  carry bit
	dsbc	d		;ziehe de von hl ab
	jrc	sub$end1	;wenn weniger als ein jahr, dann sub$end1
	inr	c		;jahr  zaehler um eins weiter
	ret			;return in year$loop
				;
sub$end1:			;ok jahreszahl ist berrechnet
	inx	sp		;setze stack richtig
	inx	sp		;fuer ausgang aus year$loop
	dad	d		;in hl jetzt die tage des verbleibenden jahres
	mov	a,c		;in c und a die jahre ab 1980
	call	set$feb		;setze februar bei schaltjahr auf 29 sonst 28
	mov	a,c		;wandle Jahresoffset in BCD-Zahl
	call	bindez		;
	adi	80h		;und addiere BCD 80 dazu
	daa			;um die richtige BCD-Jahreszahl zu erhalten
	sta	time$field+6	;	
				;
	lxi	d,monat$list	;berechne aus verbleibenden tagen den Monat
	mvi	b,0		;
monat$loop:			;
	ldax	d		;lade anzahl der tage des jeweiligen monats
	mov	c,a		;nach bc
	stc ! cmc		;loesche carry
	dsbc	b		;ziehe anzahl der tage ab
	jrc	monat$loop$end	;wenn carry, dann richtiger monat erreicht
	inx	d		;zeige auf naechsten monat
	jr	monat$loop	;
monat$loop$end:			;
	dad	b		;addiere monat wieder dazu
	mov	a,l		;
	call	bindez		;wandle in BCD-Zahl
	sta	time$field+3	;und speichere Tag ab
	xchg			;berrechne monatszahl aus d
	lxi	d,monat$list	;
	stc ! cmc		;loesche carry
	dsbc	d		;in l steht jetzt monat ab 0
	mov	a,l		;
	inr	a		;erhoehe um eins jan=1,.. dez=0ch
	call	bindez		;wandle in BCD-Zahl.
	sta	time$field+4	;speichere monat ab.
				;ok, datum ist berrechnet
				;und in time$field abgelegt.
	lda	@hour		;lege sunde ab
	sta	time$field+2	;
	lda	@min		;lege minute ab
	sta	time$field+1	;
	lda	@sec		;lege sekunde ab
	sta	time$field	;
				;ok time$field berechnet
	call	mwrite$time	;setze datum und uhrzeit in mk3835
				;
time$ret:			;lade de,hl zurueck
	pop	d		;
	pop	h		;
	ret			;und return



set$scb:
				;setze das datum und die uhrzeit im
				;system control block
				;
	call	mread$time	;lese zeit und datum aus mk3835
	lda	time$field+6	;lese BCD-Jahreszahl
	sui	80h		;wandle in binaeroffset
	daa			;zu 1980
	call	dezbin		;
	push	psw		;rette binaeroffset zu 1980 auf stack
	call	set$feb		;setze Februar entsprechend
				;berechne absolute tageszahl
	lda	time$field+3	;lese tag ein
	call	dezbin		;und wandle in binaerzahl
	mvi	h,0		;
	mov	l,a		;
				;in hl steht jetzt der tag
	lda	time$field+4	;lade monat
	call	dezbin		;wandle in binaerzahl
	lxi	d,monat$list	;zeiger auf die liste mit den monatstagen
	mvi	b,0		;
set$scb2:			;
	dcr	a		;ende der monats addition?
	jrz	set$scb3	;
	push	psw		;rette akku
	ldax	d		;
	mov	c,a		;
	pop	psw		;
	dad	b		;monat zu hl
	inx	d		;zeiger auf naechsten monat
	jr	set$scb2	;
set$scb3:			;die tage des laufenden jahres sind in hl
	pop	psw		;hole binearoffset zu 1980 vom stack
	lxi	d,365		;fuer jedes jahr 365 tage
	mov	b,a		;b dient als zaehler
	ora	a
	jrz	set$scb6	;wenn jahreszahl=0
set$scb4:
	mov	a,b		;wenn schaltjahr, ein tag mehr
	ani	3		;schaltjahr wenn untere 2 bits 01
	cpi	1		;
	jrnz	set$scb5	;sprung wenn kein schaltjahr
	inx	h		;ein tag mehr
set$scb5:			;
	dad	d		;365 tage dazu
	djnz	set$scb4	;addiere fuer alle jahre
set$scb6:			;in hl jetzt offset ab 1 jan 1980
	lxi	d,730		;berechene offset ab 1 jan 1978
	dad	d		;ok
	shld	@date		;ab, in scb
				;
				;uebertrage noch uhrzeit
	lda	time$field	;sekunden
	sta	@sec		;
	lda	time$field+1	;minuten
	sta	@min		;
	lda	time$field+2	;stunden
	sta	@hour		;
	jmp	time$ret	;alles ok



bindez:				;Binaer => BCD-Wandlung im Akku
	ora	a		;akku=0
	rz			;alles ok
	push	b		;rette bc
	mov	b,a		;b=zaehler
	xra	a		;akku=0
bindez1	inr	a		;akku=akku+1
	daa			;dez. korr.
	djnz	bindez1		;
	pop	b		;
	ret			;

dezbin:				;BCD => Binaer-Wandlung im Akku
	ora	a		;wenn akku=0
	rz			;dann alles ok
	push	b		;rette bc
	mvi	b,0		;
dezbin1	inr	b		;erhoehe b um eins Binaer
	dcr	a		;erniedrige akku um eins BCD
	daa			;BCD korrektur
	jrnz	dezbin1		;
	mov	a,b		;
	pop	b		;
	ret			;

set$feb:
				;pruefe ob in akku schaltjahr
				;dann setze tage im februar auf 29
				;sonst auf 28
	ani	3		;sind untere 2 bits null
	mvi	a,29		;
	jrz	set$feb1	;
	mvi	a,28		;kein schaltjahr, 28 tage
set$feb1:			;
	sta	monat$list+1	;speichere im februar ab
	ret			;

monat$list:
				; liste der tage im monat
				; erster eintrag fuer jan. dann feb usw.
	db	31,28,31,30
	db	31,30,31,31
	db	30,31,30,31


?user:				; BIOS-Funktion 30
				; Achtung bei Aufruf muss Bank 0
				; eingeschaltet sein (Aufruf ueber BDOS-50)
				;
	mov	a,c		; waehle unterfunktion aus
	cpi	0		;
	jrz	user0		;
	cpi	1		;
	jrz	user1		;
	cpi	2		;
	jrz	user2		;
	ret			; keine gueltige unterfunktion, dann return


user0:				; kopiere disk$type$list in tpa
				;
	sded	adrtab+3	; lege dest adresse ab
	mvi	a,4		;
	sta	adrtab+5	;
	lhld	typelist	; lege source ab
	shld	adrtab		;
	xra	a		;
	sta	adrtab+2	;
	lhld	ldtl		;
	shld	adrtab+6	;
	call	dmatrans	;
	ret			;

user1:				; lade dist$ype$list von tpa
				;
	sded	adrtab		; lege source adresse ab
	mvi	a,4		;
	sta	adrtab+2	;
	lhld	typelist	; lege dest adr. ab
	shld	adrtab+3	;
	xra	a		;
	sta	adrtab+5	;
	lhld	ldtl		;
	shld	adrtab+6	;
	call	dmatrans	;
	ret			;

user2:				; rufe unterprogramm in bank0 auf.
				; achtung, der anwender muss sicherstellen,
				; dass die call adresse ok ist, sonst
				; systemabsturz.
				; hl zeigt auf call adresse. vor
				; call wird zweitregistersatz aktiviert
				; und nach call wieder deaktiviert.
				;
	shld	hlcall+1	; lege call adresse ab
	exaf			; tausche registersatz
	exx			;
hlcall	call	0		; call subroutine, bank 0 ist ja eingeschaltet
	exx			; tausche registersatz zurueck
	exaf			;
	ret			; und zurueck

	end

