* FreeMem.a:	An assembler free memory lister.  I came up with this
*		as a quicker way to get free ram than 'avail.'
*
* Author:
*		James E. Cooper Jr.
*		113 Collier Pl.  Apt 1B
*		Cary, NC  27513
*
* Notes:
*		First working version. 3/1/87  jec
*		Modified to handle FAST RAM. 4/6/87  jec
*		Added RawDoFmt call, instead of bindec and ldiv,
*			giving FASTER operation, and SMALLER code.
*			Many, MANY thanks to Joe Bostic of THE
*			AMIGAN for documenting this call!!!
*			(See AMIGAN, Vol II, #3)  8/22/87  jec
*		Added dynamic variable allocation, so you can make
*			it resident, if anyone ever figures out how!
*			8/23/87  jec
*		Added largest hunk report.  8/23/87  jec
*
* Included equate files.
* -----------------------------------------------------------------------
	ifd	CAPE
	EXEOBJ
	objfile 'ram:FreeMem'
	optimon -1
	endc

	NOLIST
	INCLUDE "exec/types.i"
	INCLUDE "exec/libraries.i"
	INCLUDE "exec/memory.i"
	INCLUDE "libraries/dos.i"
	INCLUDE "offsets/exec.i"
	INCLUDE "offsets/dos.i"
	LIST

* Local Equates
* ------------------------------------------------------------------------
TRUE	EQU	-1
FALSE	EQU	0

* A structure definition
* -------------------------------------------------------------------------

v_CHIP		EQU	-128		; storage for free chip parm
v_LCHIP 	EQU	-124		;    "     "   "    "   largest hunk
v_FAST		EQU	-120		;    "     "   "   fast parm
v_LFAST 	EQU	-116		;    "     "   "    "   largest hunk
v_TOTAL 	EQU	-112		;    "     "   "   total parm
v_OUTPUT	EQU	-108		; storage for output string

* The code segment
* -------------------------------------------------------------------------

	link	a4,#-128

	moveq	#0,d0

	;------ get Exec's library base pointer:
	LEA.L	DOSName(PC),A1          ; name of dos library
	move.l	#LIBRARY_VERSION,d0

	move.l	a0,a5			; save A0 for later use
	move.l	_AbsExecBase,a6
	Call	OpenLibrary
	MOVE.L	D0,a6			; Save library pointer on stack
	BNE.S	gotdos

	; Should really issue an alert here...
	moveq	#RETURN_FAIL,D0 	; give up
	unlk	a4
	rts

gotdos:
*
*	; REGISTER USAGE:
*	;	A0-2	= scratch
*	;	A3	= pointer to output string area, for store routine
*	;	A4	= pointer to variable storage
*	;	A6	= dos library base pointer
*	;	D1-3	= AmigaDOS scratch argument registers
*	;	D5	= output handle
*
	move.l	a4,d0			; store away for later
	moveq	#127,d4 		; initialize counter
zero:
	move.b	#0,-(a4)                ; zero the data space
	dbra	d4,zero
	move.l	d0,a4			; and get the pointer again
*	Obtain the output handle (needed for write)
	Call	Output
	move.l	a6,d6			; save DOSBase for later calls
	MOVE.L	D0,D5			; Save for the write
	move.l	_AbsExecBase,a6
	Call	Forbid			; don't let 'em change while we ask
	move.l	#MEMF_CHIP,d1		; ok, check free chip
	Call	AvailMem
	move.l	d0,v_CHIP(a4)           ; store in parms table
	move.l	#MEMF_CHIP+MEMF_LARGEST,d1 ; to find largest hunk in chip ram
	Call	AvailMem
	move.l	d0,v_LCHIP(a4)
	move.l	#MEMF_FAST,d1		; check free fast
	Call	AvailMem
	move.l	d0,v_FAST(a4)           ; store in parms table
	move.l	#MEMF_FAST+MEMF_LARGEST,d1 ; to find largest hunk in fast ram
	Call	AvailMem
	move.l	d0,v_LFAST(a4)
	move.l	#MEMF_PUBLIC,d1 	; get all available memory
	Call	AvailMem		; ask system how much there is
	move.l	d0,v_TOTAL(a4)          ; store in parms table
	Call	Permit			; done - they can load all they want
	lea	MEMORY(pc),a0           ; load format string
	lea	v_CHIP(a4),a1           ; where the pieces are
	lea	store(pc),a2            ; routine that puts chars in output
	lea	v_OUTPUT(a4),a3         ; where to put 'em
	move.l	a3,a5			; also, save it for PRINT
	Call	RawDoFmt		; have system 'make' output string
	move.l	d5,d1			; Output file handle
	move.l	a5,d2			; pointer to buffer
	moveq	#127,d0 		; convenient count
	moveq	#0,d3			; init char count
lenloop:
	cmpi.b	#0,(a5)+                ; NULL yet?
	beq.s	printit 		; yes, goforit!
	addq.l	#1,d3			; increment char count
	dbra	d0,lenloop		; and check again
printit:
	move.l	d6,a6			; get DOSBase for call
	Call	Write			; and print it all out!
	move.l	#RETURN_OK,D0
FINISHED:
	unlk	a4			; remove stack frame
	rts

* Subroutines
* ------------------------------------------------------------------------
********************************************************************************
* STORE:	routine used by _LVORawDoFmt to store output string
********************************************************************************

store:
	move.b	d0,(a3)+
	rts

********************************************************************************
* Data declarations
********************************************************************************

	CNOP	0,4
DOSName 	DOSNAME
MEMORY		DC.B	'Chip: %7ld, largest %7ld',10
		DC.B	'Fast: %7ld, largest %7ld',10
		DC.B	'Free memory: %ld bytes.',10,0
	END
