;=================
; Microb'Clock
; (c) TP 1996
;=================

; Juste en passant un petit cadeau pour les débutants en ASM
; ce petit prog qui affiche une petite montre à droite des
; écrans. J'ai fait ça car celle que j'utilisais me fait
; des enforcer hits. (Le mec devrait changer de C
; car son code est une HORREUR!)
; C'est du vite fait sur le pouce mais ça marche.
; Tiens, en passant, c'est du code relogeable et
; réentrant (pure).
; Pas de param en entrée
; Un bon break dans les dents pour quitter.

	include	exec/types.i
	include	dos/dos.i
	include	dos/datetime.i
	include	dos/dosextens.i
	include	intuition/intuition.i

	include	graphics_lib.i
	include	exec_lib.i
	include	dos_lib.i
	include	intuition_lib.i

 STRUCTURE var,0
	APTR	dosbase
	APTR	grafbase
	APTR	intbase
	APTR	_dumbase		* arrêt pour closelibs
	STRUCT	dos_date,dat_SIZEOF	* structure def en datetime.i
	STRUCT	strtime,16		* ma chaîne
	STRUCT	itext,it_SIZEOF		* structure pour intuitextlength
	APTR	OldMin			* ancienne heure
	APTR	OldScreen		* écran de l'affichage
	USHORT	TextLength		* longueur du txt
	USHORT	BackPen			* couleur fond
	USHORT	FrontPen		* couleur premier plan
	USHORT	OffsetX			* offset pour écrire
	LABEL	var_sizeof0

var_sizeof=(var_sizeof0+4)&$fffffffc		; multiple de 4

MX=26	* distance par rapport à la fin de l'écran
WAIT=25	* attente rafraichissement

version
	bra.s	.pipo
	dc.b	"$VER: Microb'Clock 0.9 (19.4.96)",$a,$d
	dc.b	"(c) Thomas PIMMEL 1996",$a,$d,0
	even
.pipo
	include	EasyStartup.asm		; pour lancement WBench
Start
	; pourquoi allouer de la mem pour les variables
	; alors que la pile est quasi-vide ?
	lea	-var_sizeof(sp),sp
	move.l	sp,a4
	; oui mais y'a des saletés
	bsr	ClearVar
	bsr	InitStr
	; pas de message d'erreur pour le kick 1.3, na!
	bsr	OpenLibs
	tst.l	d0
	beq.s	.rts
	bsr.s	Main
.rts
	bsr	CloseLibs
	moveq	#0,d0
	lea	var_sizeof(sp),sp
	rts

;======== The Main
Main
	;=== l'heure
	bsr	GetTime
	tst.l	d0
	beq.s	.wait			* pas disponible
	;== multitâââche
	move.l	4.w,a6
	jsr	_LVOForbid(a6)
	;== restore de l'ancien écran
	move.l	intbase(a4),a0
	move.l	ib_ActiveScreen(a0),a0
	cmp.l	OldScreen(a4),a0
	beq.s	.lemême
	move.l	a0,-(sp)
	bsr.s	RestorScreen
	move.l	(sp)+,a0
	tst.l	d0
	beq.s	.pass
	move.l	a0,OldScreen(a4)
	cmp.l	#0,a0
	beq.s	.pass
	bsr	GetPens
	move.l	OldScreen(a4),a0
	bsr	GetLength
.lemême
	move.l	OldScreen(a4),a0
	cmp.l	#0,a0
	beq.s	.pass
	;== Bar ?
	move.w	sc_Flags(a0),d0
	and.w	#SHOWTITLE,d0
	beq.s	.pass
	;== on est jamais trop prudent...
	tst.w	TextLength(a4)
	beq.s	.pass
	;== on fait joli
	lea	strtime(a4),a1
	move.b	(a1),d0
	cmp.b	#'0',d0
	bne.s	.no0
	move.b	#' ',(a1)
.no0
	;== go!
	bsr	WriteTime
.pass
	;=== Rétablir
	move.l	4.w,a6
	jsr	_LVOPermit(a6)
.wait
	;=== Attendre
	moveq	#WAIT,d1
	move.l	dosbase(a4),a6
	jsr	_LVODelay(a6)
	;=== Ctrl-C ?
	jsr	_LVOCheckSignal(a6)
	btst	#12,d0
	beq	Main
	move.l	OldScreen(a4),a0
	bsr.s	RestorScreen
	rts

;===================================
RestorScreen
	;= y avait-il un écran ?
	tst.l	OldScreen(a4)
	beq.s	.ok
	;= le draw était possible?
	move.w	BackPen(a4),d0
	add.w	FrontPen(a4),d0
	tst.w	d0
	beq.s	.ok
	;== vraiment possible ?
	tst.w	TextLength(a4)
	beq.s	.ok
	;= écran tj en service ?
	move.l	intbase(a4),a0
	move.l	ib_FirstScreen(a0),a0
	move.l	OldScreen(a4),a1
.loop
	cmp.l	#0,a0
	beq.s	.ok		* non, il est fermé
	cmp.l	a0,a1
	beq.s	.go
	move.l	sc_NextScreen(a0),a0
	bra.s	.loop

.go	;= efface mon gars!
	move.l	sc_BarLayer(a1),a5
	cmp.l	#0,a5
	beq.s	.ok
	move.l	grafbase(a4),a6
	;= param en a5, les autres registres servaient de cendrier
	;= quand les developpeurs de kommo fumaient les clops qui font rire.
	jsr	_LVOAttemptLockLayerRom(a6)
	tst.l	d0
	beq.s	.erreur
	;= I'm now the king of the road
	bsr.s	ClearMonChemin
	move.l	grafbase(a4),a6
	jsr	_LVOUnlockLayerRom(a6)
	moveq	#1,d0
.erreur
	rts

.ok
	; = c'est fini
	moveq	#1,d0
	rts


;===================================
ClearMonChemin	; effacer l'heure
	move.l	grafbase(a4),a6
	;== le bon pen
	move.w	BackPen(a4),d0
	move.l	lr_rp(a5),a1
	jsr	_LVOSetAPen(a6)
	;== rport
	move.l	lr_rp(a5),a1
	;== coords
	move.w	OffsetX(a4),d0
	moveq	#1,d1
	move.w	d0,d2
	move.w	d1,d3
	add.w	TextLength(a4),d2
	add.w	rp_TxHeight(a1),d3
	subq.w	#1,d2
	subq.w	#1,d3
	jsr	_LVORectFill(a6)
	;== a' y' est
	rts

;===================================
GetPens	* en a0 l'écran
	move.l	a0,-(sp)
	clr.w	BackPen(a4)
	clr.w	FrontPen(a4)
	move.l	intbase(a4),a6
	jsr	_LVOGetScreenDrawInfo(a6)
	move.l	(sp)+,a0
	tst.l	d0
	beq.s	.rts
	move.l	d0,a1
	move.l	dri_Pens(a1),a2
	;= au pif, mais où trouve-t-on ces valeurs?
	;= par chance j'ai un gros nez
	move.w	18(a2),FrontPen(a4)
	move.w	20(a2),BackPen(a4)
	jsr	_LVOFreeScreenDrawInfo(a6)	* a0 / a1
.rts
	rts

;===================================
GetLength * longueur de mon texte
	move.l	a0,-(sp)
	move.l	intbase(a4),a6
	lea	sc_RastPort(a0),a1
	lea	itext(a4),a0
	move.l	rp_Font(a1),a1
	move.l	a1,it_ITextFont(a0)
	lea	strtime(a4),a1
	clr.b	5(a1)				* effacer les secondes
	move.l	a1,it_IText(a0)
	jsr	_LVOIntuiTextLength(a6)
	move.w	d0,TextLength(a4)
	* calcul de l'offset
	move.l	(sp)+,a0
	moveq	#0,d1
	add.w	sc_Width(a0),d1
	sub.w	d0,d1
	sub.w	#MX,d1
	move.w	d1,OffsetX(a4)
	rts

;===================================
WriteTime	* en a0 l'écran
	move.l	grafbase(a4),a6
	move.l	sc_BarLayer(a0),a5
	cmp.l	#0,a5
	beq.s	.ok
	jsr	_LVOAttemptLockLayerRom(a6)
	tst.l	d0
	beq.s	.ok
	bsr	ClearMonChemin
	move.l	lr_rp(a5),a3
	; couleurs, ouhais je sais c'est du "Brutal"
	; dans un monde parfait on restore les valeurs
	move.l	a3,a1
	move.w	BackPen(a4),d0
	jsr	_LVOSetBPen(a6)
	move.l	a3,a1
	move.w	FrontPen(a4),d0
	jsr	_LVOSetAPen(a6)
	; à la bonne place
	move.l	a3,a1
	move.w	OffsetX(a4),d0
	move.w	rp_TxBaseline(a1),d1	*offset y
	addq.w	#1,d1
	jsr	_LVOMove(a6)
	; écrire
	move.l	a3,a1
	lea	strtime(a4),a0
	moveq	#5,d0
	jsr	_LVOText(a6)
	jsr	_LVOUnlockLayerRom(a6)
.ok
	rts

;====================================
GetTime
	move.l	dosbase(a4),a6
	lea	dos_date(a4),a3
	move.l	a3,d1
	jsr	_LVODateStamp(a6)
	tst.l	d0
	beq.s	.rts
	* à refaire ?
	move.l	ds_Minute(a3),d0
	cmp.l	OldMin(a4),d0
	beq.s	.rts			* ne change pas
	move.l	d0,OldMin(a4)
	move.l	a3,d1
	jsr	_LVODateToStr(a6)
.rts
	rts

;======== Effacer la zone de variable
ClearVar
	move.l	a4,a0
	move.w	#var_sizeof/4-1,d0
.clr
	clr.l	(a0)+
	dbf	d0,.clr
	rts

;======== initialisation de la struct date
InitStr
	lea	dos_date(a4),a0
	lea	strtime(a4),a1
	move.l	a1,dat_StrTime(a0)
	move.l	#-1,OldMin(a4)
	rts

;======== ouvrir les libs
OpenLibs
	move.l	4.w,a6
	lea	dosname(pc),a1
	moveq	#37,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,dosbase(a4)
	tst.l	d0
	beq.s	.rts

	lea	grafname(pc),a1
	moveq	#37,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,grafbase(a4)
	tst.l	d0
	beq.s	.rts

	lea	intname(pc),a1
	moveq	#37,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,intbase(a4)

.rts
	rts

;======= fermer les libs
CloseLibs
	lea	dosbase(a4),a3
	move.l	4.w,a6
.loop
	move.l	(a3)+,a1
	cmp.l	#0,a1
	beq.s	.rts
	jsr	_LVOCloseLibrary(a6)
	bra.s	.loop
.rts
	rts

;====== constantes =======
dosname		dc.b	'dos.library',0
intname		dc.b	'intuition.library',0
grafname	dc.b	'graphics.library',0
	even