* 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.
* -----------------------------------------------------------------------
*	NOLIST
	INCLUDE "exec/types.i"
	INCLUDE "exec/libraries.i"
	INCLUDE "exec/memory.i"
	INCLUDE "libraries/dos.i"
*	LIST

* External references

* DOS offsets
* -----------------------------------------------------------------------
Write		EQU	-48		; ((-5*6)+(-18)) (from RKM)
Output		EQU	-60		; ((-5*6)+(-30))

* Exec offsets
* -----------------------------------------------------------------------
ExeBase 	EQU	4
Forbid		EQU	-132		; ((-5*6)+(-102))
Permit		EQU	-138		; ((-5*6)+(-108))
AllocMem	EQU	-198		; ((-5*6)+(-168))
FreeMem 	EQU	-210		; ((-5*6)+(-180))
AvailMem	EQU	-216		; ((-5*6)+(-186))
OpenLibrary	EQU	-408		; ((-5*6)+(-378))
RawDoFmt	EQU	-522		; ((-5*6)+(-492))

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

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

	STRUCTURE	Variables,0
	LONG	v_CHIP		; storage for free chip parm
	LONG	v_LCHIP 	;    "     "   "    "   largest hunk
	LONG	v_FAST		;    "     "   "   fast parm
	LONG	v_LFAST 	;    "     "   "    "   largest hunk
	LONG	v_TOTAL 	;    "     "   "   total parm
	STRUCT	v_OUTPUT,96	; storage for output string
	LABEL	v_SIZEOF

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

	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	ExeBase,a6
	jsr	OpenLibrary(a6)
	MOVE.L	D0,-(a7)		; Save library pointer on stack
	BNE.S	gotdos

	; Should really issue an alert here...
	moveq	#RETURN_FAIL,D0 	; give up
	bra	FINISHED

gotdos:
*
*	; REGISTER USAGE:
*	;	A0,A1,A2= 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
*
*	Allocmem some variable space, so we can be resident
	move.l	#v_SIZEOF,d0		; size of the block
	move.l	#MEMF_PUBLIC,d1 	; memory type requirement
	movem.l d2-d7/a0-a6,-(sp)	; save to avoid trashing
	jsr	AllocMem(a6)		; get some
	movem.l (sp)+,d2-d7/a0-a6	; restore registers
	move.l	d0,a4			; store away for later
*	Obtain the output handle (needed for write)
	move.l	(a7),a6 		  ; get DOSBase
	jsr	Output(a6)
	MOVE.L	D0,D5			; Save for the write
	move.l	ExeBase,a6
	jsr	Forbid(a6)		; don't let 'em change while we ask
	move.l	#MEMF_CHIP,d1		; ok, check free chip
	jsr	AvailMem(a6)
	move.l	d0,v_CHIP(a4)		; store in parms table
	move.l	#MEMF_CHIP|MEMF_LARGEST,d1 ; to find largest hunk in chip ram
	jsr	AvailMem(a6)
	move.l	d0,v_LCHIP(a4)
	move.l	#MEMF_FAST,d1		; check free fast
	jsr	AvailMem(a6)
	move.l	d0,v_FAST(a4)		; store in parms table
	move.l	#MEMF_FAST|MEMF_LARGEST,d1 ; to find largest hunk in fast ram
	jsr	AvailMem(a6)
	move.l	d0,v_LFAST(a4)
	move.l	#MEMF_PUBLIC,d1 	; get all available memory
	jsr	AvailMem(a6)		; ask system how much there is
	move.l	d0,v_TOTAL(a4)		; store in parms table
	jsr	Permit(a6)		; done - they can load all they want
	lea	MEMORY,a0		; load format string
	movea.l a4,a1			;   pieces
	lea	store,a2		; routine that puts chars in output
	move.l	a4,d0			; where to put 'em
	add.l	#v_OUTPUT,d0		; adjust
	move.l	d0,a3			; and put it where RawDoFmt needs it
	move.l	a3,a5			; also, save it for PRINT
	jsr	RawDoFmt(a6)		; have system 'make' output string
	move.l	d5,d1			; Output file handle
	move.l	a5,d2			; pointer to buffer
	moveq	#v_SIZEOF,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	(a7),a6 		; get DOSBase for call
	jsr	Write(a6)		; and print it all out!
	move.l	a4,a1			; set up for _LVOFreeMem
	move.l	#v_SIZEOF,d0		; size to free
	move.l	ExeBase,a6
	jsr	FreeMem(a6)
	move.l	#RETURN_OK,D0
FINISHED:
	addq	#4,a7			; adjust stack for exit
	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: %ld, largest %ld',10
		DC.B	'Fast: %ld, largest %ld',10
		DC.B	'Free memory: %ld bytes.',10,0
	END

