	NOLIST
*
*  gfxmem.c  - graphically display available memory.  Quick program
*     that's a freebie.  Give it to anyone you please, just don't sell it.
*
*       Version 0.0 - initial version, released on INFO-AMIGA.
*       Version 0.1 - added numeric indication of available and used memory
*                     in bar graphs.
*       Version 0.2 - added condition compilation for timer.device code.  If
*                     I can figure out how to make it create timer signals,
*                     then I can define USE_TIMER for much more prompt
*                     response to window sizing attempts.  Oh well.
*       Version 0.3 - removed conditional compilation for timer.device
*                     code.  We now use the timer, and all seems well.
*       Version 0.4 - calculate character data placement according to
*                     display preferences.  Check for updated preferences
*                     while running.
*	 Version 0.5 - don't display fast memory if none exists.  Handle
*		       Lattice C 3.03 in V1.1 update kit that insists on
*		       creating a window for stdin, stdout and stderr with-
*		       out asking.  Foo!
*			source size = 19,728 bytes
*			running size= 32,088 bytes

*	Version A.6 - converted to assembly by Darrel Schnieder.
*			source size =  1,576
*			running size=  9,984
*		Changes:
*			 1. Window now SMART_REFRESH. This simplifies what
*			  messages need to be responded to. The only time
*			  the window needs to be refreshed is if the window
*			  is resized.
*			 2. Used RMBTRAP so that the window wouldn't get
*			  menu messages.
*			 3. Got rid of the SetWindowTitles message that was
*			  written when the window became active.
*			 4. HorizSpace = AvailWidth>>5 in place of
*			   HorizSpace = AvailWidth/20
*			  This has the effect of the margin being smaller.
*			 5. The loop that sets ChipMax & FreeMax is only
*			  called once. This means that if the user adds
*			  memory to the system while running gfxmem that
*			  memory will not show up.
*			   Also in the same loop comparisons are made to
*			  MEMF_FAST+1 and MEMF_CHIP+1 rather than
*			  MEMF_FAST   and MEMF_CHIP as the original program
*				      did.
*			  This works on my system and I don't understand the
*			  need for the difference.
*			 6. The redraw subroutine uses FORBID/PERMIT so that
*			  once it starts tasks of a higher priority will not
*			  preempt it.
*			 8. The numerical sizes of the memory are displayed
*			  to the far left and right rather than the middle.
*			  I did this so that it would be easier to use the
*			  middle to display some more info.
*			  I also made the text colors opposite.
*			 9. When the numerical amount is printed it only
*			  prints the actual number with no preceeding
*			  blank spaces.
*			  This means it is more likely that the number can
*			  be printed since it takes up less space.
*			10. Used SetDrMd to set the mode to JAM1 and thus
*			  need never worry about setting the background
*			  pen. This got rid of 6 calls to SetBPen.
*			11. Consolidated the natural parrallelism between
*			  ChipMem and FastMem code in redraw. This roughly
*			  cut the size of redraw in half.
*			12. Will now run with a stack as small as 1600 bytes.
*			13. Displays graphically most recent change.
*			  This is done by a bar in the middle.

 			
*  TODO:
*       Add menu selection package to display Kbytes or percent of memory
*       used and free. If you do this get rid of the RMBTRAP.
*
*       Add requestor to display statistics like min and max for free and
*       avail, time running, etc..
*
*
*                 Copyright (C) 1985,
*                 Louis A. Mamakos
*                 Software & Stuff

	INCLUDE "exec/types.i"
	INCLUDE "exec/nodes.i"
	INCLUDE "exec/lists.i"
	INCLUDE "exec/interrupts.i"
	INCLUDE "exec/libraries.i"
	INCLUDE "exec/execbase.i"
	INCLUDE "exec/ables.i"
	INCLUDE "exec/ports.i"
	INCLUDE "exec/devices.i"
	INCLUDE "exec/memory.i"
	INCLUDE "exec/io.i"
	INCLUDE "devices/timer.i"
	INCLUDE "hardware/blit.i"
	INCLUDE "graphics/copper.i"
	INCLUDE "graphics/gfx.i"
	INCLUDE "graphics/regions.i"
	INCLUDE "graphics/rastport.i"
	INCLUDE "graphics/gfxbase.i"
	INCLUDE "graphics/gels.i"
	INCLUDE "graphics/text.i"
	INCLUDE "graphics/view.i"
	INCLUDE "devices/inputevent.i"
	INCLUDE "graphics/clip.i"
	INCLUDE "graphics/layers.i"
	INCLUDE "intuition/intuition.i"

	XREF	_LVOAvailMem
	XREF	_LVOFreeMem
	XREF	_LVOOpenLibrary
	XREF	_LVOOpenWindow
	XREF	_LVOAllocSignal
	XREF	_LVOAllocMem
	XREF	_LVOFreeSignal
	XREF	_LVOFindTask
	XREF	_LVOAddPort
	XREF	_LVOOpenDevice
	XREF	_LVOCloseDevice
	XREF	_LVOCloseLibrary
	XREF	_LVORemPort
	XREF	_LVOFreeSignal
	XREF	_LVOCloseWindow
	XREF	_LVOReplyMsg
	XREF	_LVOGetMsg
	XREF	_LVOSendIO
	XREF	_LVOGetPrefs
	XREF	_LVOSetAPen
	XREF	_LVOSetDrMd
	XREF	_LVOText
	XREF	_LVOMove
	XREF	_LVODraw
	XREF	_LVORectFill
	XREF	_LVOWait
	XREF	_LVOBeginRefresh
	XREF	_LVOEndRefresh

	TASK_ABLES
	
;	LLEN 132
;	NOPAGE
;	LIST

* D2 = Refresh: if 0 then redraw changes only; if 1 then total redraw 
* D3 = IntuitionLib
* D4 = waitFlags
* D5 = TimerPort
* D6 = if 0 then Do Draw; if 1 then Don't Draw
* D7 = GraphicsLib

* A2 = window's rastPort
* A3 = window
* A4 = window's userPort
* A5 = timeRequest

*********************** CODE ****************************************

************** Find out how much memory is installed ****************

	MOVEA.L 4,A6			; load exec library address

	MOVEQ	#0,D4	
	MOVEQ	#0,D5	
	MOVE.L	MemList+LH_HEAD(A6),D0	; D0 = Memory Region Header
	FORBID
BeginScanMemoryLoop:
	MOVE.L	D0,A0			; A0 = Memory Region Header
	MOVE.L  (A0),D0			; look ahead
	BEQ.S	EndScanMemoryLoop	; EXIT LOOP
	MOVE.W	MH_ATTRIBUTES(A0),D2
	MOVE.L	MH_UPPER(A0),D1
	SUB.L	MH_LOWER(A0),D1
	CMP.W	#MEMF_FAST+1,D2
	BNE.S	isItChip
	; it is Fast Memory
	ADD.L	D1,D5
	BRA.S	BeginScanMemoryLoop
isItChip:
	CMP.W	#MEMF_CHIP+1,D2
	BNE.S	BeginScanMemoryLoop
	; it is Chip Memory
	ADD.L	D1,D4
	BRA.S	BeginScanMemoryLoop
EndScanMemoryLoop:	
	PERMIT
	lea	ChipMax(PC),A0
	move.l	D4,(A0)+	; save ChipMax
	move.l	D5,(A0)		; save FastMax

***** open libraries *****
	lea	IntuitionName(PC),A1
	moveq	#0,D0
	jsr	_LVOOpenLibrary(A6)
	move.l	D0,D3
	BEQ.L	FailOpeningIntuitionLib

	lea	GraphicsName(PC),A1
	moveq	#0,D0
	jsr	_LVOOpenLibrary(A6)
	move.l	D0,D7
	BEQ.L	FailOpeningGraphicLib

***** open window *****
	lea	MyNewWindow(PC),A0
	exg	D3,A6
	jsr	_LVOOpenWindow(A6)
	exg	D3,A6
	tst.l	D0
	BEQ.L	FailOpeningWindow
	movea.l	D0,A3
	; get Window->UserPort->mp_SigBit into D0
	MOVEA.L wd_UserPort(A3),A0	; A0 = @lockWindow->UserPort
	MOVEQ   #0,D0
	MOVE.B  MP_SIGBIT(A0),D0	; D0 = the @lockWindow's mp_SigBit
	MOVEQ   #1,D1
	LSL.L   D0,D1
	MOVE.L  D1,D4		; D4 = waitFlags

***** create timer port *****
	; get a signal bit
	MOVEQ   #-1,D0
	JSR     _LVOAllocSignal(A6)
	MOVE.L  D0,D2		; D2 = sigBit
	BMI.L   FailCreateTimer1

	; alloc port structure
	MOVEQ   #MP_SIZE,D0	; size of structure
	MOVE.L  #$10001,D1	; memory type = CLEAR and PUBLIC
	JSR     _LVOAllocMem(A6)
	MOVE.L  D0,D5		; D5 = timer Port
	BNE.S   SkipFailCode

	; AllocMem failed
	MOVE.L  D2,D0
	JSR     _LVOFreeSignal(A6)
	BRA.S   FailCreateTimer2
SkipFailCode:
	; fill port fields
	MOVEA.L D5,A2
	ADDQ.L  #8,A2		; A2 now points to the LN_TYPE field
	MOVE.W  #$400,(A2)+	; LN_TYPE = NT_MSGPORT, LN_PRI = 0
	LEA	TimerPortName(PC),A0
	MOVE.L  A0,(A2)+	; LN_NAME = address of timer port name
	MOVE.W  D2,(A2)+	; MP_FLAGS = (#PA_SIGNAL=0), MP_SIGBIT = sigBit
	MOVEQ   #0,D0
	MOVEA.L D0,A1
	JSR     _LVOFindTask(A6)	; 0 arg means find this task
	MOVE.L  D0,(A2)		; MP_SIGTASK = pointer to found task

	; add the port
	MOVEA.L D5,A1
	JSR     _LVOAddPort(A6)

***** use the timer port sigBit(D2) to set the waitFlags(D4) *****
	MOVEQ   #1,D0
	LSL.L   D2,D0
	OR.L    D0,D4		; update the waitFlags(D4)

	BRA.S	EndTerminationSection

**************** TERMINATION SECTION ********************

CloseWindow:
	; abort any standing timer request
	MOVEA.L A5,A1
	; ABORTIO System Macro
		MOVE.L  A6,-(A7)
		MOVEA.L $14(A1),A6
		JSR     -$24(A6)	
		MOVEA.L (A7)+,A6
	; close timer device
	MOVEA.L A5,A1
	JSR     _LVOCloseDevice(A6)
	; deallocate timeRequest structure
	MOVEQ   #-1,D6
	MOVE.B  D6,8(A5)
	MOVE.L  D6,$14(A5)
	MOVE.L  D6,$18(A5)
	MOVEA.L A5,A1
	MOVEQ   #$28,D0
	JSR     _LVOFreeMem(A6)

FailOpeningDevice:
FailTimeRequestAlloc:
	; close timer port
	MOVEA.L D5,A1
	JSR     _LVORemPort(A6)
	MOVEA.L D5,A2
	; D6 = -1
	MOVE.B  D6,$A(A2)
	MOVE.L  D6,(A2)
	MOVEQ	#0,D0
	MOVE.B  MP_SIGBIT(A2),D0	; get the sigBit
	JSR     _LVOFreeSignal(A6)
	MOVEA.L D5,A1
	MOVEQ   #$22,D0
	JSR     _LVOFreeMem(A6)

FailCreateTimer2:
FailCreateTimer1:
	MOVEA.L A3,A0
	EXG     D3,A6
	JSR     _LVOCloseWindow(A6)
	EXG	D3,A6

FailOpeningWindow:
	MOVEA.L	D7,A1			; Graphics Library
	JSR	_LVOCloseLibrary(A6)

FailOpeningGraphicLib:
	MOVEA.L	D3,A1			; Intuition Library
	JSR	_LVOCloseLibrary(A6)

FailOpeningIntuitionLib:
	MOVEQ   #0,D0		; this is the return value
	RTS

**************** END TERMINATION SECTION ****************

EndTerminationSection:

***** allocate timeReq structure *****
	MOVEQ   #IOTV_SIZE,D0
	MOVE.L  #(MEMF_CLEAR!MEMF_PUBLIC),D1
	JSR     _LVOAllocMem(A6)
	TST.L   D0
	BEQ.S   FailTimeRequestAlloc
	MOVEA.L D0,A5		; A5 = timeRequest
	MOVE.W  #((NT_MESSAGE<<8)+0),LN_TYPE(A5)
	MOVE.L  D5,MN_REPLYPORT(A5)
	; AllocMem set to zero the IO_FLAGS, IO_ERROR fields

***** open vblank timer device *****
	LEA     TimerName(PC),A0	; A0 = timer name
	MOVEA.L A5,A1			; A1 = timeRequest
	MOVEQ   #UNIT_VBLANK,D0	
	MOVEQ   #0,D1
	JSR     _LVOOpenDevice(A6)
	TST.L   D0
	BNE.S   FailOpeningDevice
	MOVE.W  #TR_ADDREQUEST,IO_COMMAND(A5)

***** initialize enviroment *****

	movea.l wd_UserPort(A3),A4
	movea.l wd_RPort(A3),A2

	moveq	#1,D2			; 1 ->  refresh = true
	moveq	#0,D6			; 0 ->  do draw
	BSR.S	newPrefs
	BSR.L	redraw
	BSR.S	startTimer

mainLoop:
	move.l	D4,D0
	JSR	_LVOWait(A6)
BeginWhileMsg:
	movea.l	A4,A0
	JSR	_LVOGetMsg(A6)
	tst.l	D0
	BEQ.S	ExitWhileMsg
	movea.l	D0,A1
	move.l	im_Class(A1),D2		; save the class of the message
	JSR	_LVOReplyMsg(A6)
	move.l	D2,D0			; D0 = message's class

	move.w	#(NEWSIZE!SIZEVERIFY!NEWPREFS!CLOSEWINDOW),D1
	and.w	D0,D1			; will be zero if D0 not in the D1 set
	BEQ.S	BeginWhileMsg		; ignore the message
	cmpi.w	#NEWSIZE,D0
	BNE.S	isItSIZEVERIFY
	; message is NEWSIZE
	moveq	#0,D6			; 0 ->  do draw	
	moveq	#1,D2			; 1 ->  refresh = TRUE
	pea	BeginWhileMsg(PC)	; push the return address
	BRA.S	redraw			; jump to the subroutine
isItSIZEVERIFY:
	cmpi.w	#SIZEVERIFY,D0
	BNE.S	isItNEWPREFS
	; message is SIZEVERIFY
	moveq	#1,D6			; 1 ->  don"t draw
	BRA.S	BeginWhileMsg
isItNEWPREFS:
	cmpi.w	#NEWPREFS,D0
	BNE.L	CloseWindow		; only option left is CloseWindow
	; message is NEWPREFS
	BSR.S	newPrefs
	moveq	#1,D2
	pea	BeginWhileMsg(PC)	; push the return address
	BRA.S	redraw

ExitWhileMsg:
	movea.l	D5,A0
	JSR	_LVOGetMsg(A6)
	tst.l	D0
	BEQ.S	mainLoop
	moveq	#0,D2		; 0 ->  refresh = false
	BSR.S	redraw
	pea	mainLoop(PC)	; push the return address

	; let it fall through to startTimer

************************ SUBROUTINES *********************************
	
startTimer:
    QUANTUM: EQU 2
	lea	IO_SIZE+TV_SECS(A5),A0
	clr.l	(A0)
	addq.l	#QUANTUM,(A0)+		; QUANTUM = number of seconds to wait
	clr.l	(A0)			; TV_MICRO = 0 => zero ticks
	movea.l	A5,A1
	JSR	_LVOSendIO(A6)
	RTS

***********************************
	
*
*  This function is called during startup and when new preferences are
*  selected.  Get the font size from the Preferences structure.
*/
newPrefs:
	lea	fontType(PC),A0
	moveq	#1,D0
	exg	D3,A6
	jsr	_LVOGetPrefs(A6)
	exg	D3,A6
	move.b	fontType(PC),D0
	moveq	#TOPAZ_EIGHTY,D1
	cmp.b	D1,D0
	BNE.S	isItSIXTY
	rts			; D0 = 8 = char_size

isItSIXTY:
	moveq	#TOPAZ_SIXTY,D1
	cmp.b	D1,D0
	BNE.S	setnmfaultSize
	moveq	#11,D0		; D0 = 11 = char_size
	rts

setnmfaultSize:
	moveq	#12,D0		; D0 = 12 = char_size
	rts

***************************************
	GUTTER: EQU 3
	BLUE:	EQU 0
	WHITE:	EQU 1
	BLACK:	EQU 2
	ORANGE: EQU 3

redraw:
	tst.b	D6
	BEQ.S	continueRedraw
	RTS

continueRedraw:
	movem.l	D3-D6/A4-A5,-(SP)
**		x_max	 = D2
**		y_max	 = D3
**		ChipMax  = D4
**		FastMax  = D5
**		ChipFree = D6
**		FastFree = D7
**		A4,A5 used as memory variable pointers

	FORBID

*   ChipFree = AvailMem (MEMF_CHIP);
	MOVEQ	#MEMF_CHIP,D1		; also D1<<16 = MEMF_LARGEST
	JSR	_LVOAvailMem(A6)
	MOVE.L	D0,D6			; store ChipFree

*   FastFree = AvailMem (MEMF_FAST);
	MOVEQ	#MEMF_FAST,D1
	JSR	_LVOAvailMem(A6)
	exg	D7,A6
	move.l	D7,-(SP)
	MOVE.L	D0,D7			; store FastFree

	lea	oldChipFree(PC),A4
	lea	ChipDiff(PC),A5
	move.l	D6,D0
	sub.l	(A4),D0			; D0 = newChipFree - oldChipFree
	move.l	D6,(A4)+		; store newChipFree as oldChipFree
	cmp.l	D0,D6
	BNE.S	wasNotFirstTime
	; if this code is executed then this is the first time
	; need to clear the Diff variables so that no change will be drawn.
	; The fact that oldChipFree was 0 implies that oldFastFree was 0
	; This assummes that the only time 0 bytes of Chip mem will be
	; availiable is the first time through

	moveq	#0,D1
	moveq	#0,D0
	addq.l	#8,A5	; ChipDiff & FastDiff already zero
	move.l	D7,(A4)+		; store newFastFree as oldFastFree
	BRA.S	skipSinceFirstTime

wasNotFirstTime:
	move.l	D0,(A5)+		; store D0 into ChipDiff
	move.l	D7,D1
	sub.l	(A4),D1			; D1 = newFastFree - oldFastFree
	move.l	D7,(A4)+		; store newFastFree as oldFastFree
	move.l	D1,(A5)+		; store D1 into FastDiff

skipSinceFirstTime:
	; A4 now points to txt
	move.l	(A5)+,D4		; D4 = ChipMax
	move.l	(A5)+,D5		; D5 = FastMax
	; A5 = &HorizSpace

	tst.w	D2
	BNE.S	totalRedraw

	; partial Redraw
	add.l	D0,D1
	BEQ.L	exitRedraw
	BRA	needsRedrawing

totalRedraw:
	movea.l	A2,A1
	moveq	#BLACK,D0
	JSR	_LVOSetAPen(A6)
	; SetOPen
	move.b	#BLACK,rp_AOLPen(A2)
	ori.w	#8,rp_Flags(A2)
	movea.l	A2,A1
	moveq	#0,D0
	moveq	#0,D1
	moveq	#0,D2
	moveq	#0,D3
	move.w	wd_Width(A3),D2
	move.b	wd_BorderRight(A3),D0
	sub.w	D0,D2
	move.w	wd_Height(A3),D3
	move.b	wd_BorderBottom(A3),D0
	sub.w	D0,D3
	move.b	wd_BorderLeft(A3),D0
	move.b	wd_BorderTop(A3),D1
	JSR	_LVORectFill(A6)
	; now recalculate the spacing parameters for this sized window
	moveq	#0,D0
	move.b	wd_BorderLeft(A3),D0
	sub.w	D0,D2			; D2 = availWidth
	move.b	wd_BorderTop(A3),D0
	sub.w	D0,D3			; D3 = availHeight

	; clear the Chip & Fast Diff since the window is being resized
	; this keeps the drawChange routine from executing.

	lea	ChipDiff(PC),A4
	clr.l	(A4)+
	clr.l	(A4)+
	addq.l	#8,A4

	; A4 now points to HorizSpace

	; set HorizSpace
	move.w	D2,D0
	lsr.l	#5,D0
	move.w	D0,(A4)+
	add.w	D0,D0
	sub.w	D0,D2

	; set Thickness
	tst.l	D5
	BEQ.S	noFastMemory
	sub.w	#(GUTTER*3),D3
	lsr.w	#1,D3
	BRA.S	doneSettingThickness

noFastMemory:
	subq.w	#(GUTTER*2),D3
doneSettingThickness:
	move.w	D3,(A4)+		; store in Thickness

	; set Scale
	cmp.l	D4,D5			; is FreeMax > ChipMax
	BHI.S	FreeMaxLarger
	; ChipMaxLarger
	move.l	D4,D0
	BRA.S	setScale

FreeMaxLarger:
	move.l	D5,D0
setScale:
	DIVU	D2,D0
	move.w	D0,(A4)+		; store in Scale
	addq.l	#8,A4

	; A4 now points to txt

needsRedrawing:
	
**** draw amount of allocated chip memory *****
	movea.l	A2,A1
	moveq	#RP_JAM1,D0
	JSR	_LVOSetDrMd(A6)
	movea.l	A2,A1
	moveq	#ORANGE,D0
	JSR	_LVOSetAPen(A6)
	; SetOPen
	move.b	#WHITE,rp_AOLPen(A2)
	moveq	#0,D0
	moveq	#0,D1
	move.w	(A5)+,D0			; x_min = HorizSpace
	move.b	wd_BorderTop(A3),D1
	addq.w	#GUTTER,D1			; y_min
	lea	tempYmin(PC),A0
	move.w	D1,(A0)
	move.l	D0,D2
	sub.l	D6,D4				; D4 = ChipMax - ChipFree
	move.l	D4,D3
	divu	Scale(PC),D3
	add.w	D3,D2				; x_max
	move.l	D1,D3
	add.w	(A5),D3				; y_max = D3 + Thickness
	movea.l	A2,A1
	JSR	_LVORectFill(A6)
	movea.l	D4,A0
	moveq	#0,D4
	move.b	fontType(PC),D4		; D4 is now used for the fontType
	BSR.L	printAllocatedMem	

printAmountOfFreeChipM:
	move.l	ChipDiff(PC),-(SP)
	pea	ChipDividingLine(PC)
	BSR.L	printAmountOfFreeMem

printaC:
	lea	Cstring(PC),A0
	BSR.S	printMemTypeChar(PC)

printAllocatedFastM:
	tst.l	D5
	BEQ.S	exitRedraw
	
***** draw amount of allocated fast memory *****
	movea.l	A2,A1
	moveq	#ORANGE,D0
	JSR	_LVOSetAPen(A6)
	moveq	#0,D0
	move.w	(A5)+,D0			; x_min = HorizSpace
	move.l	D3,D1
	addq.w	#GUTTER,D1			; y_min = y_max + GUTTER
	lea	tempYmin(PC),A0
	move.w	D1,(A0)
	move.l	D0,D2
	sub.l	D7,D5				; D5 = FastMax - FastFree
	move.l	D5,D3
	divu	Scale(PC),D3
	add.w	D3,D2				; x_max = x_min + (D5/Scale)
	move.l	D1,D3
	add.w	(A5),D3				; y_max = y_min + Thickness
	movea.l	A2,A1
	JSR	_LVORectFill(A6)
	move.l	D5,A0
	BSR.L	printAllocatedMem	

*****************************

printAmountOfFreeFastM:
	move.l	D7,D6
	move.l	FastDiff(PC),-(SP)
	pea	FastDividingLine(PC)
	BSR.S	printAmountOfFreeMem

printaF:
	lea	Fstring(PC),A0
	BSR.S	printMemTypeChar(PC)

exitRedraw:
	move.l	(SP)+,D7
	movem.l	(SP)+,D3-D6/A4-A5
	exg	D7,A6
	PERMIT
	RTS

*********************************************************************

* expects pointer to character to print in A0

printMemTypeChar:
	move.l	D4,D0			; get fontType
	addq.w	#5,D0
	cmp.w	-(A5),D0
	BLS.S	contPrintMemType1	; since HorizSpace > fontType+5
	RTS

contPrintMemType1:
	subq.w	#4,D0
	cmp.w	Thickness(PC),D0
	BLS.S	contPrintMemType2	; since Thickness > fontType
	RTS

contPrintMemType2:
	move.l	A0,D6		; save A0 in D6
	movea.l	A2,A1
	moveq	#0,D0
	move.w	(A5),D0		; get the HorizSpace
	sub.w	D4,D0
	subq.w	#1,D0		; D0 = (HorizSpace - fontType - 1)
	move.w	Thickness(PC),D1
	lsr.w	#1,D1
	add.w	tempYmin(PC),D1
	addq.w	#4,D1		; D1 = (y_min + Thickness/2 + 4)
	JSR	_LVOMove(A6)
	movea.l	A2,A1
	move.l	D6,A0
	moveq	#1,D0
	JSR	_LVOText(A6)
	RTS

******************************************************************
* expects the amount of free memory in D6

printAmountOfFreeMem:
	movea.l	A2,A1
	moveq	#BLUE,D0
	JSR	_LVOSetAPen(A6)
	move.l	D2,D0		; x_min = x_max
	move.l	D6,D1
	divu	Scale(PC),D1
	add.w	D1,D2		; x_max += (Chip/Fast)Free/Scale
	moveq	#0,D1
				; y_max unchanged
	lea	tempXmin(PC),A0
	move.w	D0,(A0)+
	move.w	(A0),D1		; y_min =  TOP + GUTTER (i.e. tempYmin)
	JSR	_LVORectFill(A6)
	move.l	(SP)+,D0	; pop return address temporarily
	move.l	(SP)+,A0	; get address of (Chip/Fast)DividingLine
	move.l	(SP),D1		; get (Chip/Fast)Diff value
	move.l	D0,(SP)		; put the return address back on the stack
	move.w	D2,-(SP)
	BSR.L	drawChange
	move.w	(SP)+,D2
	movea.l	A2,A1
	moveq	#WHITE,D0
	JSR	_LVOSetAPen(A6)

	; can it be printed?
	move.l	D4,D1		; get the fontType
	addq.w	#1,D1
	cmp.w	(A5),D1
	BLS.S	contPrintAmountFree1	; since Thickness <= fontType+1
	RTS

contPrintAmountFree1:
	moveq	#10,D0
	lsr.l	D0,D6
	move.l	D6,D0
	BSR.S	IntToString
	move.l	D4,D1
	mulu	D0,D1			; D1 = fontType * #ofCharacters
	move.l	D0,D6			; save the #ofCharacters
	swap	D6
	addq.w	#2,D1	
	move.w	D1,D6			; save (fontType * #ofCharacters) + 2
	move.w	D2,D0
	sub.w	tempXmin(PC),D0
	cmp.w	D1,D0
	BHI.S	contPrintAmountFree2	; since x_max-x_min <= (#ofChar * fontType) + 2
	RTS

contPrintAmountFree2:
	
	move.l	A0,-(SP)		; save string pointer
	movea.l	A2,A1
	move.l	D2,D0
	sub.w	D6,D0		; D0 = x_max - ((#ofChars * fontType) + 2)
	move.w	(A5),D1
	lsr.w	#1,D1
	add.w	tempYmin(PC),D1
	addq.w	#3,D1		; D1 = (y_min + Thickness/2 + 3)
	JSR	_LVOMove(A6)
	movea.l	A2,A1
	movea.l (SP)+,A0	; get the string pointer
	swap	D6
	move.w	D6,D0
	JSR	_LVOText(A6)
	RTS

********************************
* expects D0 = integer to put in string pointed to by A4
* the 5th character of A4 is the last and only the first 4 
* can be numeric. IntToString assummes that the Int in D0 will have
* no more then 4 numeric characters representing it. 
* It will convert 0 to '0'
* RETURNS:
*		A0 = points to first character
*		D0 = count of characters including terminating 'K'

IntToString:
	move.l	A4,A0
	move.l	#$30303030,(A0)+
	moveq	#3,D1
IntRepeatTop:
	divu	#10,D0
	swap	D0
	add.b	D0,-(A0)
	clr.w	D0
	swap	D0
	DBEQ	D1,IntRepeatTop
	; D1 >= 0
	moveq	#5,D0
	sub.w	D1,D0
	RTS

******************************************
* expects amount of allocated memory in A0

printAllocatedMem:
	; can it be printed?
	moveq	#0,D1
	move.b	D4,D1
	addq.w	#1,D1
	cmp.w	(A5),D1			; compare D1 and Thickness
	BLS.S	contPrintAllocated1	; since Thickness > fontType+1
	RTS

contPrintAllocated1:

	moveq	#10,D1
	move.l	A0,D0
	lsr.l	D1,D0
	BSR.S	IntToString
	move.l	D4,D1
	mulu	D0,D1			; D1 = fontType * #ofCharacters
	move.l	D0,A1			; save the #ofCharacters
	addq.w	#4,D1	
	move.w	D2,D0
	sub.w	HorizSpace(PC),D0
	cmp.w	D1,D0
	BHI.S	contPrintAllocated2	; since x_max-x_min > #ofChars * fontType
	RTS

contPrintAllocated2:
	move.l	A0,-(SP)	; save string pointer address
	move.w	A1,-(SP)	; save #ofCharacters

	movea.l	A2,A1
	moveq	#BLACK,D0
	JSR	_LVOSetAPen(A6)		
	movea.l	A2,A1
	moveq	#0,D0
	move.w	HorizSpace(PC),D0
	addq.w	#2,D0			; D0 = x_min + 2
	moveq	#0,D1
	move.w	(A5),D1		; get the Thickness
	lsr.w	#1,D1
	add.w	tempYmin(PC),D1
	addq.w	#3,D1		; D1 = (y_min + Thickness/2 + 3)
	JSR	_LVOMove(A6)
	movea.l	A2,A1
	move.w	(SP)+,D0
	move.l	(SP)+,A0
	JSR	_LVOText(A6)
	RTS

*********************************************************************
* expects A0 to contain address of (Chip/Fast)DividingLine
* expects D1 to contain (Chip/Fast)Diff value 
* on entry and exit D3 = y_max

drawChange:
	move.w	(A0),D2		; get old dividing line
	swap	D2
	move.w	tempXmin(PC),D2	; get new dividing line
	move.w	D2,(A0)		; store new dividing line as the old div. line
	addq.w	#1,D2

	; SetAPen
	moveq	#ORANGE,D0

	tst.l	D1
	BNE.S	contDrawChange1
	RTS

contDrawChange1:
	BPL.S	contDrawChange2
	subq.w	#2,D2
	; SetAPen
	moveq	#BLUE,D0

contDrawChange2:
	move.l	A2,A1
	JSR	_LVOSetAPen(A6)
	swap	D3
	move.w	tempYmin(PC),D3
	; D2 = x_max | x_min = DividingLine | tempXmin
	; D3 = y_max | y_min = y_max | tempYmin

	move.l	A2,A1
	moveq	#0,D0
	move.w	D2,D0	; D0 = tempXmin
	moveq	#0,D1
	move.w	D3,D1	; D1 = tempYmin
	JSR	_LVOMove(A6)

	swap	D2
	; D2 = x_max | x_min = tempXmin | DividingLine
	BSR.S	drawLineSegment

	swap	D3

	; D3 = y_max | y_min = tempYmin | y_max
	BSR.S	drawLineSegment

	swap	D2
	; D2 = x_max | x_min = DividingLine | tempXmin
	BSR.S	drawLineSegment

	swap	D3

	; D3 = y_max | y_min = y_max | tempYmin
	BSR.S	drawLineSegment
	
	clr.w	D3
	swap	D3	; D3 = y_max

	RTS

drawLineSegment:
	move.l	A2,A1
	moveq	#0,D0
	move.w	D2,D0
	moveq	#0,D1
	move.w	D3,D1
	JSR	_LVODraw(A6)
	RTS

***************************************************

IntuitionName:	CNOP 0,2
	DC.B	'intuition.library',0
GraphicsName:	CNOP 0,2
	DC.B	'graphics.library',0

TimerPortName:	CNOP 0,2
	DC.B	'Timer',0
TimerName:	CNOP 0,2
	TIMERNAME

windowFlags: 	EQU CLOSEWINDOW!SIZEVERIFY!NEWSIZE!NEWPREFS!REFRESHWINDOW
windowGadgets:	EQU NOCAREREFRESH!RMBTRAP!WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE!WINDOWSIZING!SMART_REFRESH

windowTitle:	CNOP 0,2
	DC.B	'GfxMem A.6',0
MyNewWindow:	CNOP 0,2
	DC.W	10
	DC.W	10
	DC.W	170
	DC.W	40
	DC.B	-1
	DC.B	-1
	DC.L	windowFlags
	DC.L	windowGadgets
	DC.L	0
	DC.L	0
	DC.L	windowTitle
	DC.L	0
	DC.L	0
	DC.W	150
	DC.W	30
	DC.W	640
	DC.W	100
	DC.W	WBENCHSCREEN

ChipDiff:	CNOP 0,2
	DC.L	0
FastDiff:	CNOP 0,2
	DC.L	0
ChipMax:	CNOP 0,2
	DS.L	1
FastMax:	CNOP 0,2
	DS.L	1
HorizSpace:	CNOP 0,2
	DS.W	1
Thickness:	CNOP 0,2
	DS.W	1
Scale:		CNOP 0,2
	DS.W	1
oldChipFree:	CNOP 0,2
	DC.L	0
oldFastFree:	CNOP 0,2
	DC.L	0
txt:		CNOP 0,2
	DC.L	0
	DC.B	'K'
fontType:	CNOP 0,2
	DS.B	1
Cstring:	
	DC.B	'C'
Fstring:	
	DC.B	'F'
tempXmin:	CNOP 0,2
	DS.W	1
tempYmin:	CNOP 0,2
	DS.W	1
ChipDividingLine:	CNOP 0,2
	DC.W	0
FastDividingLine:	CNOP 0,2
	DC.W	0

	END
