;	.          _               .   .  .
;	|   _  _  / \|  _  _ |    /|  /| /|
;	|  |_)/ \(   | / \| `|/    |   |  |
;	|__|_,\_/ \_/|_\_/|_,|\    |o  |  |
;
;	1993-04-27
;	1993-06-28
;	1995-02-09
;	1996-03-26
;
;
;	Here it is, the complete OS 2.0 clock that fits in one (1) FFS
;	disk block; less than 512 bytes, that is.
;
;	If you get this any smaller, or just want to write something
;	to me, please mail me to the following addresses:
;
;	Henrik Herranen
;	Atomikatu 6 A 9
;	SF-33720 Tampere
;	Finland
;
;	e-mail: leopold@cs.tut.fi
;
;	New for v1.01: The clock now fits on 1 OFS disk block (488 bytes)!
;	New for v1.10: With help from jhsa@cs.tut.fi and albert@cs.tut.fi 36
;		bytes saved (JUST LOOK AT THE OPENING OF LIBRARIES!) :-) .
;	New for v1.11: With help from Timo Kaikumaa (timok@cs.tut.fi) another
;		12 bytes went away. 440 to go.


;	The following lines would normally be included from external files

;	include 'ainclude:macros.i'
;	include 'ainclude:include.i'

_LVOOpenLibrary		EQU	-552
_LVOChangeWindowBox	EQU	-486
_LVOCloseLibrary	EQU	-414
_LVOOldOpenLibrary	EQU	-408
_LVOReplyMsg		EQU	-378
_LVOGetMsg		EQU	-372
_LVOWindowToFront	EQU	-312
_LVOSetTaskPri		EQU	-300
_LVOFindTask		EQU	-294
_LVOSizeWindow		EQU	-288
_LVOSetWindowTitles	EQU	-276
_LVOOpenWindow		EQU	-204
_LVODelay		EQU	-198
_LVODateStamp		EQU	-192
_LVOMoveWindow		EQU	-168
_LVOCloseWindow		EQU	-72
_LVOTextLength		EQU	-54

WBENCHSCREEN	EQU	1

wd_WScreen	EQU	$2E
wd_UserPort	EQU	$56
wd_LeftEdge	EQU	$4
wd_TopEdge	EQU	$6
sc_Width	EQU	$C
sc_BarHeight	EQU	$1E
sc_RastPort	EQU	$54
lib_Revision	EQU	$16

IDCMP_CLOSEWINDOW	equ	$200
WFLG_CLOSEGADGET	equ	$8
WFLG_DEPTHGADGET	equ	$4
WFLG_DRAGBAR		equ	$2

;
;	Here begins my code
;
WIDEST		equr	d4
CURRWIDTH	equr	d2
WIN		equr	a3

INTUITIONBASE	equr	d5
EXECBASE	equr	d6
GRAPHICSBASE	equr	a4

ASC0		equr	d3
LAST_MINUTE	equr	d7

				; The registers A2 and A5 are left for free use
	section text,CODE

main:
;	OpenLib	dos

	moveq.l	#60-60,WIDEST
;	moveq.l	#-1,LAST_MINUTE		; Not necessarily needed

	move.l	$4.w,EXECBASE		; My version of A68k doesn't like the
					; .w extension. Take it away if it
					; disturbs your compiler.

	move.l	EXECBASE,a6

	sub.l	a1,a1			; MyTask = FindTask(0);
	jsr	_LVOFindTask(a6)
	move.l	d0,-(sp)		; Store MyTask to stack

	move.l	d0,a1			; InheritedPri = SetTaskPri(MyTask, 4);
	moveq.l	#4,d0
	jsr	_LVOSetTaskPri(a6)
	move.w	d0,-(sp)		; Store InheritedPri to stack

	lea	IntuitionName(pc),a1	; IntuitionBase = OldOpenLibrary("intuition.library");
	lea	_LVOOldOpenLibrary(a6),a5
	jsr	(a5)
	move.l	d0,INTUITIONBASE

	lea	IntuitionName+7(pc),a1	; DosBase = OldOpenLibrary("dos.library");
	addq.w	#'os'-'on',(a1)
	subq.b	#'i'-'d',-(a1)
	jsr	(a5)
	move.l	d0,-(sp)

	lea	IntuitionName+9(pc),a1
	lea	Gfx+8(pc),WIN
	move.l	-(WIN),-(a1)		; GraphicsBase = OldOpenLibrary("graphics.library");
	move.l	-(WIN),-(a1)
	jsr	(a5)
	move.l	d0,GRAPHICSBASE

	move.l	INTUITIONBASE,a6	; Win = OpenWindow(&NewWin);
	lea	NewWin(pc),a0
	jsr	_LVOOpenWindow(a6)
	move.l	d0,WIN			; if (!Win) exit(0);
	tst.l	d0
	beq	FailedOpeningWindow

MainLoop:
	move.l	(sp),a6			; DateStamp(&MyDate); (DosBase is on top of the stack)
	lea	MyDate(pc),a2
	move.l	a2,d1
	jsr	_LVODateStamp(a6)

;	lea	MyDate_Minute(pc),a2	; if (MyDate_Minute != LastMinute)
	addq.l	#MyDate_Minute-MyDate,a2
	cmp.l	(a2),LAST_MINUTE
	beq.s	MinuteNotChanged

	move.l	INTUITIONBASE,a6	; 	WindowToFront(Win);
	move.l	WIN,a0
	jsr	_LVOWindowToFront(a6)

MinuteNotChanged:
	moveq.l	#'0',ASC0		; Here ASC0 gets its nominal value '0'

	move.l	(a2)+,LAST_MINUTE	; LastMinute = MyDate_Minute;
	move.l	wd_WScreen(WIN),a5	; a5 = Win -> WScreen

	lea	TimeStr(pc),a1		; TimeStr[0] = MyDate_Minute / 600 + '0';
	move.l	LAST_MINUTE,d0
	divu.w	#600,d0
	bne.s	1$
	subq.l	#1,a1
1$:	bsr.s	setnum

	moveq.l	#60,d1			; TimeStr[1] = MyDate_Minute / 60 + '0';
	bsr.s	divud1d0_setnum

	moveq.l	#10,d1			; TimeStr[3] = MyDate_Minute / 10 + '0';
	bsr.s	adda1_divud1d0_setnum

	bsr.s	setnum			; TimeStr[4] = MyDate_Minute + '0';

	move.l	(a2)+,d0		; TimeStr[6] = MyDate_Tick / 50 / 10 + '0';
	divu.w	#50,d0
	move.l	d0,-(sp)		; Store whole 32-bit division result for later use
	ext.l	d0

	bsr.s	adda1_divud1d0_setnum
	bsr.s	setnum			; TimeStr[7] = MyDate_Tick / 50 + '0';
	bra.s	aftersetnum

; The structures have moved here for easier access. Parts of the NewWindow
; structure has been changed to contain code.
	
MyDate:
MyDate_Days:
Gfx:	dc.b	"grap"
MyDate_Minute:
	dc.b	"hics"
MyDate_Tick:
Pad:	dc.b	0

IntuitionName:
	dc.b	"intu"
TimeStr:
	dc.b	"ition.library"
NewWin:
	dc.w    0,0,60,20		; Left, Top, Width, Height
	dc.b    1,2			; DetailPen, BlockPen
	dc.l    IDCMP_CLOSEWINDOW	; IDCMP flags
	dc.l	WFLG_CLOSEGADGET+WFLG_DEPTHGADGET+WFLG_DRAGBAR	; Flags
	dc.l	0			; *FirstGadget
	dc.l	0			; *CheckMark
	dc.l    0			; *WindowTitle

; Changing the length of this code will kill the compiler. The correct length
; is 16 bytes (move.b is 4 bytes, other commands 2 bytes/cmd)

adda1_divud1d0_setnum:			; *Screen, *BitMap, Min/Max-Width/Height
	move.b	#':',(a1)+
divud1d0_setnum:
	divu.w	d1,d0
setnum:
	or.b	ASC0,d0			; This is "or" and not "add" because "or" might be faster :-)
	move.b	d0,(a1)+
	swap	d0			; These were the most common commands after calling setnum!
	ext.l	d0			;   The code is not always needed, but doesn't do any harm either,
					;   and again another 8 bytes was saved!
	rts
; End of code inserted to NewWindow structure

WantedLoc:
	dc.w    WBENCHSCREEN		; Type of mother screen

; End of NewWindow structure

aftersetnum:
	clr.b	(a1)			; NULL terminate string
	move.l	INTUITIONBASE,a6	; SetWindowTitles(Win, &TimeStr[0 (or 1)], (UBYTE *) ~0L);
	move.l	WIN,a0

					; Now a2 points to the next longword after MyDate_Tick
					; Thus, by adding 1 you can get the address of TimeStr!
	addq.l	#TimeStr-MyDate_Tick-4,a2
	exg	a1,a2
	move.l	a1,ASC0			; ASC0 looses its value '0' here!!!
	sub.l	a1,a2			; a2 = length of string
;	Display "LEN=",long,a2
;	Display "PTR=",long,a1
	move.l	a2,-(sp)		; put length to stack
	move.w	#-1,a2			; no ScreenTitle string
	jsr	_LVOSetWindowTitles(a6)

	lea	sc_RastPort(a5),a1	; CurrWidth = TextLength(Win->WScreen.RastPort, TimeStr[0/1], 8/7);

	move.l	ASC0,a0			; ASC0 isn't '0' anymore
	move.l	(sp)+,d0

	move.l	GRAPHICSBASE,a6
	jsr	_LVOTextLength(a6)
	move.w	d0,CURRWIDTH

	cmp.w	WIDEST,CURRWIDTH	; if (CurrWidth > Widest) {
	ble.s	EndUpdate

	move.l	INTUITIONBASE,a6	; MoveWindow(Win, ##, 0);
	move.l	WIN,a0
	moveq.l	#-60-24,d0
	add.w	sc_Width(a5),d0		; a5 still contains the Win->WScreen ptr
	sub.w	CURRWIDTH,d0
	move.w	d0,ASC0			; ASC0 isn't '0'
	lea	WantedLoc(pc),a2
	sub.w	(a2),d0
	move.w	ASC0,(a2)		; ASC0 isn't '0'
	moveq.l	#0,d1
	jsr	_LVOMoveWindow(a6)

	move.l	WIN,a0			; SizeWindow(Win, ##, ##);
	move.w	CURRWIDTH,d0
	sub.w	WIDEST,d0
	moveq.l	#1,d1
	add.b	sc_BarHeight(a5),d1	; a5 still contains the Win->WScreen ptr
	lea	NewWin+6(pc),a5		; Address of CurrWinHeight to a5
	sub.w	(a5),d1
	add.w	d1,(a5)
	jsr	_LVOSizeWindow(a6)

	move.w	CURRWIDTH,WIDEST

EndUpdate:				; } /* end if(CurrWidth > Widest) */
	moveq.l	#50,d1
	sub.w	(sp),d1			; Get former tick / 50 division % from upper word of last stack item
	addq.l	#4,sp			; Clear last stack item (whole word!)
	move.l	(sp),a6			; Now DosBase is on top of the stack
	jsr	_LVODelay(a6)

	move.l	EXECBASE,a6		; if (!GetMsg(Win -> UserPort)) goto MainLoop
	move.l	wd_UserPort(WIN),a0
	jsr	_LVOGetMsg(a6)
	tst.l	d0
	beq	MainLoop

	move.l	d0,a1			; ReplyMsg(WinIDCMP);
	jsr	_LVOReplyMsg(a6)

	move.l	INTUITIONBASE,a6	; CloseWindow(Win);
	move.l	WIN,a0
	jsr	_LVOCloseWindow(a6)

FailedOpeningWindow:
	move.l	EXECBASE,a6

	lea	_LVOCloseLibrary(a6),a5	; CloseLib(GraphicsBase);
	move.l	GRAPHICSBASE,a1
	jsr	(a5)

	move.l	(sp)+,a1		; CloseLib(DosBase); (+ restore DosBase from stack)
	jsr	(a5)

	move.l	INTUITIONBASE,a1	; CloseLib(IntuitionBase);
	jsr	(a5)

	move.w	(sp)+,d0		; Restore InheritedPri from stack
	move.l	(sp)+,a1		; Restore MyTask from stack
	jsr	_LVOSetTaskPri(a6)	; SetTaskPri(MyTask, InheritedPri);


	moveq.l #0,d0
	rts

	END
