;
;	@(#)	ColdBoot.a    v1.03(0)    5-Mar-91    pdd
;
;		This program will cold-boot the Amiga, trashing any memory-
;		resident stuff that may try to survive the boot, giving you
;		maximum memory on the reboot without having  to  power  off
;		the Amiga.
;
; -------------------------------------------------------------------------
;
;	Edit history:
;
;	  1-Mar-91 1.00(0)P	Began working on program.
;	  3-Mar-91 1.00(0)	First working version of program.
;	  3-Mar-91 1.01(0)	Made requester look more reasonable.
;	  5-Mar-91 1.02(0)	Added workbench interface.
;	  5-Mar-91 1.03(0)	Removed global storage; code is now pure.
;
; -------------------------------------------------------------------------
;

;
; ----- Define a section.  For our purposes, we only need one.
;

	SECTION CODE

;
; ----- Now include the necessary files.
;

	INCLUDE "exec/types.i"		;To define various data types.
	INCLUDE "libraries/dosextens.i"	;To get at our process info.
	INCLUDE "exec/alerts.i"		;So we can bring up GURUs.
	INCLUDE "exec/execbase.i"	;So we can trash it.
	INCLUDE "intuition/intuition.i"	;So we can bring up a requester.

;
; ----- Define the external symbols we will be using in this program.
;

	XREF	_AbsExecBase

	XREF	_LVOOpenLibrary
	XREF	_LVOCloseLibrary
	XREF	_LVOAlert
	XREF	_LVODisable
	XREF	_LVOSupervisor
	XREF	_LVOAutoRequest
	XREF	_LVOFindTask
	XREF	_LVOWaitPort
	XREF	_LVOGetMsg
	XREF	_LVOReplyMsg

;
; ----- We are going to use the exec library for various things, so prepare
;	a pointer to it.
;

	movea.l	(_AbsExecBase).w,a6	;Get pointer to exec library.

;
; ----- First make sure the workbench message pointer is null,  then  check
;	to  see if we were started by the workbench or not.  If so, get the
;	startup message and save it away.
;

	clr.l	d5			;Clear the message pointer.

	suba.l	a1,a1			;Find our task.
	jsr	_LVOFindTask(a6)	; ..
	movea.l	d0,a4			; ..
	tst.l	pr_CLI(a4)		;See if we were run from CLI.
	bne.s	RanFromCLI		;If so, there's no message.

	lea	pr_MsgPort(a4),a0	;Wait for the startup message.
	jsr	_LVOWaitPort(a6)	; ..
	lea	pr_MsgPort(a4),a0	;Get the startup message.
	jsr	_LVOGetMsg(a6)		; ..
	move.l	d0,d5			;Save it away.

;
; ----- Now we must open the intuition library, since we intend to  use  it
;	to bring up a requester.
;

RanFromCLI:

	lea	IntuiLibName,a1		;Point to library name.
	moveq	#33,d0			;Set the desired version.
	jsr	_LVOOpenLibrary(a6)	;Attempt to open the library.
	tst.l	d0			;See if the library opened ok.
	bne.s	IntuiOpenedOk		;If so, go on to other things.

;
; ----- If we are here, the intuition library  failed  to  open.   This  is
;	unlikely,  since  it  is  ROM-resident,  so we do the easiest thing
;	possible to alert the user (besides not saying anything): bring  up
;	a RECOVERABLE alert, then exit the program.
;

	ALERT AG_OpenLib+AO_Intuition	;Bring up the alert.
	rts				;Return to calling process.

; -------------------------------------------------------------------------

;
; ----- The intuition library  opened  ok.   Now,  since  cold-booting  the
;	machine is something of a drastic step, bring up a requester asking
;	if this is really the desired course of action.
;

IntuiOpenedOk:

	movea.l	d0,a6			;Use the intuition library.

	suba.l	a0,a0			;We don't have a window open.
	lea	IT_AreYouSure,a1	;Index text for the requester.
	lea	IT_Yes,a2		;Index text for positive button.
	lea	IT_No,a3		;Index text for negative button.
	moveq	#0,d0			;No special IDCMP flags.
	moveq	#0,d1			; ..
	move.l	#300,d2			;Set width of requester.
	move.l	#70,d3			;Set height of requester.
	jsr	_LVOAutoRequest(a6)	;Display and process the requester.

;
; ----- If the return value was TRUE (go ahead and reboot), go on  to  more
;	exciting stuff; otherwise, close intuition and exit.
;

	tst.l	d0			;See if user clicked "YES".
	bne.s	DoReset			;If so, go ahead and trash machine.

	movea.l	a6,a1			;Otherwise, index library to close.
	movea.l	(_AbsExecBase).w,a6	;Use the exec library.
	jsr	_LVOCloseLibrary(a6)	;Close the intuition library.

;
; ----- If we started from workbench, we  have  to  reply  to  the  startup
;	message before we exit.
;

	tst.l	d5			;See if there was a message.
	beq.s	NotWB			;If not, just return.

	movea.l	d5,a1			;Reply to workbench and exit
	jmp	_LVOReplyMsg(a6)	; ..


NotWB:

	moveq	#0,d0			;Set a good return value.
	rts				;Return to the calling process.

; -------------------------------------------------------------------------

;
; ----- Make sure the machine does a  completely  frigid  reboot.   If  the
;	checksum  of  ExecBase is wrong, the machine will assume all memory
;	is trashed, so we clear it.  Just to make extra sure, we also clear
;	the  pointers  to memory to preserve and modules to relink into the
;	system on a warm boot.  Note  that  we  DISABLE  interrupts  first,
;	since  once we get going here, other tasks on the machine will find
;	our actions most distressing.
;

DoReset:

	movea.l	(_AbsExecBase).w,a6	;Use the exec library again.
	jsr	_LVODisable(a6)		;Stop everything else.

	moveq	#0,d0			;Prepare to clear stuff.
	move.l	d0,ChkBase(a6)		;Trash the base complement.
	move.l	d0,ColdCapture(a6)	;Trash any coldboot vectors.
	move.l	d0,ChkSum(a6)		;Trash the ExecBase checksum.
	move.l	d0,KickMemPtr(a6)	;Trash recoverable memory locs.
	move.l	d0,KickTagPtr(a6)	;Trash ROMTAG list.
	move.l	d0,KickCheckSum(a6)	;Trash kickstart checksum.

;
; ----- Now we actually reboot the machine.  Since  we  are  a  lowly  user
;	process,  we  must request the system to execute our reboot code in
;	supervisor mode.  This code, and the actual reset code below, comes
;	from  page  219  of the Amiga Hardware Reference Manual for version
;	1.3.
;

	movea.l	(_AbsExecBase).w,a6	;Use the exec library.
	lea.l	MagicResetCode(pc),a5	;Point to the actual reset code.
	jsr	_LVOSupervisor(a6)	;Execute it.

;
; ----- Since the reset code should NOT return, if we got  here,  there  is
;	something  bizzare  going  on.  Since we intended to reboot anyway,
;	bring up a fatal alert (a.k.a. the GURU).  Note that the alert code
;	is  somewhat  of  an improvision, since there isn't really a "reset
;	failed" alert.
;

	ALERT AT_DeadEnd+AN_BootError	;Summon the GURU and die.

; -------------------------------------------------------------------------

;
; ----- This is the reset code itself, as documented on  page  219  of  the
;	Amiga  Hardware  Reference  Manual for version 1.3.  Note that this
;	code  MUST  be  executed  in  supervisor  mode,  since  the   RESET
;	instruction is not a user-mode instruction.
;
;	The reset code depends on two things: first, that when the  machine
;	is  reset,  the  ROM  image  is mapped to location $00000000 so the
;	680x0 processor will grab the reset vector  from  it;  and  second,
;	that  there  will  be  one instruction in the 680x0 internal cache,
;	since the RESET instruction makes all the memory go away!
;

	CNOP	0,4			;Code MUST be longword aligned.

MagicResetCode:

	lea.l	2,a0			;Index reset-vector-to-be.
	reset				;Reset the machine.
	jmp	(a0)			;Jump to the reset vector in ROM.

; -------------------------------------------------------------------------

;
; ----- Here are the IntuiText structures used for the requester.
;

IT_AreYouSure:

	dc.b	0,1			;Front and back pens.
	dc.b	RP_JAM1			;Drawing mode.
	dc.b	0			;Filler...
	dc.w	10,5			;Position of text.
	dc.l	0			;Use default font.
	dc.l	T_AreYouSure1		;Pointer to text.
	dc.l	IT_AreYouSure2		;Link to more text.

IT_AreYouSure2:

	dc.b	0,1			;Front and back pens.
	dc.b	RP_JAM1			;Drawing mode.
	dc.b	0			;Filler...
	dc.w	10,15			;Position of text.
	dc.l	0			;Use default font.
	dc.l	T_AreYouSure2		;Pointer to text.
	dc.l	IT_AreYouSure3		;Link to more text.

IT_AreYouSure3:

	dc.b	0,1			;Front and back pens.
	dc.b	RP_JAM1			;Drawing mode.
	dc.b	0			;Filler...
	dc.w	10,25			;Position of text.
	dc.l	0			;Use default font.
	dc.l	T_AreYouSure3		;Pointer to text.
	dc.l	0			;No more text.

IT_Yes:

	dc.b	0,1			;Front and back pens.
	dc.b	RP_JAM1			;Drawing mode.
	dc.b	0			;Filler...
	dc.w	18,3			;Position of text.
	dc.l	0			;Use default font.
	dc.l	T_Yes			;Pointer to text.
	dc.l	0			;No more text.

IT_No:

	dc.b	0,1			;Front and back pens.
	dc.b	RP_JAM1			;Drawing mode.
	dc.b	0			;Filler...
	dc.w	22,3			;Position of text.
	dc.l	0			;Use default font.
	dc.l	T_No			;Pointer to text.
	dc.l	0			;No more text.

;
; ----- All the actual text goes here, at the end of  the  program,  so  we
;	don't have to worry about alignment after we're done.
;

IntuiLibName:	dc.b	'intuition.library',0

T_AreYouSure1:	dc.b	'This program will COLD BOOT your',0
T_AreYouSure2:	dc.b	'machine.   Are you sure you want',0
T_AreYouSure3:	dc.b	'to do this?',0

T_Yes:		dc.b	'Yes   ',0
T_No:		dc.b	'No    ',0


	dc.b	'@(#) coldboot.a v1.03(0) 5-Mar-91 pdd',0


	end
