***********************************************************
* This is my TakeSystem and ResotreSystem routines that I now use
* in all my demos.  I am spreading them in hopes to get rid of the
* crapy coding pracitces that people have had since the C64 days.
* I'd like to thank Comrade J for his excelent "howtocode" files.
* A lot of the stuff here is based on his words of wisdom. :^).  Anyway,
* these routines, as of version 3.2, handle the following:
*		Getting the VBR.
*		Saving DMACON.
*		Saving Intena.
*		Saving and reseting WB view modes.
*		Owning/Disowning the blitter.
*		Pal/Ntsc/AGA modes.
*		Killing multitasking.
*		Killing interrupts.
*
* Feel free to cut and paste to fit your code (i.e. but the data and bss in
* your data and bss sections.), but please leave the CODE intact!
* If you have any questions/comments/suggestions, PLEASE contact me at
* either:
*		idr@rigel.cs.pdx.edu		(internet)
*	- or -
*		Epsilon
*		P.O.B.	1914
*		Beaverton, OR  97075-1914
*		U.S.A.
*
* Many of you may not like the fact that I use includes and system calls,
* I know I don't :), but it is the ONLY SAFE WAY TO TAKE THE SYSTEM!  To
* insure that your demo will work on any system, it's what you have to do.
*
***********************************************************
* Includes
***********************************************************

		incdir	"DevpacAm:include/"
		include	"exec/exec_lib.i"
		include	"exec/execbase.i"
		include	"graphics/gfxbase.i"
		include	"graphics/graphics_lib.i"
		include	"hardware/custom.i"

***********************************************************
* Other Macros
***********************************************************

CALL		MACRO
		jsr	_LVO\1(a6)
		ENDM

***********************************************************
* Other Equates
***********************************************************

 IFND	gb_ActiView
gb_ActiView	EQU	32
 ENDIF

 IFND	gb_CopInit
gb_CopInit	EQU	36
 ENDIF

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

		section TheCode,code

TakeSystem:	movea.l	4.w,a6		; exec base
		lea	$dff002,a5	; custom chip base + 2

		lea	GraphicsName,a1	; "graphics.library"
		moveq	#0,d0		; any version
		CALL	OpenLibrary	; open it.
		move.l	d0,gfx_base	; save pointer to gfx base
		beq.b	.exit		; if we got a NULL, then exit
		move.l	d0,a6		; for later callls...

		move.l  gb_ActiView(a6),OldView	; save old view

		move.w	#0,a1		; clears full long-word
		CALL	LoadView	; Open a NULL view (resets display
					;   on any Amiga)

		CALL	WaitTOF		; Wait twice so that an interlace
		CALL	WaitTOF		;   display can reset.

		CALL	OwnBlitter	; take over the blitter and...
		CALL	WaitBlit	;   wait for it to finish so we
					;   safely use it as we please.

		movea.l	4.w,a6		; exec base
		CALL	Forbid		; kill multitasking

		cmpi.b	#50,VblankFrequency(a6)	; is vblank rate pal?
		beq.b	.pal		; yup.
		st	ntsc		; set NTSC flag.

.pal:		move.w	$7c-2(a5),d0	; AGA register...
		cmpi.b	#$f8,d0		; are we AGA?
		bne.b	.not_aga	; nope.
		st	AGA		; set the AGA flag.
		move.w	#0,$dff1fc	; reset AGA sprites to normal mode

.not_aga:	bsr.b	GetVBR		; get the vector base pointer
		move.l	d0,VectorBase	; save it for later.

		move.w	dmaconr-2(a5),d0	; old DMACON bits
		ori.w	#$8000,d0	; or it set bit for restore
		move.w	d0,OldDMACon	; save it

		move.w	intenar-2(a5),d0	; old INTEna bits
		ori.w	#$c000,d0	; or it set bit for restore
		move.w	d0,OldINTEna	; save it

		move.l	#$7fff7fff,intena-2(a5)	; kill all ints
		move.w	#$7fff,dmacon-2(a5)	; kill all dma
.exit:		rts

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

RestoreSystem:	lea	$dff002,a5	; custom chip base + 2

	; You must do these in this order or you're asking for trouble!
		move.l	#$7fff7fff,intena-2(a5)	; kill all ints
		move.w	#$7fff,dmacon-2(a5)	; kill all dma
		move.w	OldDMACon,dmacon-2(a5)	; restore old dma bits
		move.w	OldINTEna,intena-2(a5)	; restore old int bits

		move.l	OldView,a1	; old Work Bench view
		move.l	gfx_base,a6	; gfx base
		CALL	LoadView	; Restore the view
		CALL	DisOwnBlitter	; give blitter back to the system.

		move.l	gb_CopInit(a6),$80-2(a5) ; restore system clist
		move.l	a6,a1
		movea.l	4.w,a6		; exec base
		CALL	CloseLibrary

	; there is no call to Permit() because it is implied by the return
	; to AmigaDOS! :^)
		rts

***********************************************************
* This function provides a method of obtaining a pointer to the base of the
* interrupt vector table on all Amigas.  After getting this pointer, use
* the vector address as an offset.  For example, to install a level three
* interrupt you would do the following:
*
*		bsr	_GetVBR
*		move.l	d0,a0
*		move.l	$6c(a0),OldIntSave
*		move.l	#MyIntCode,$6c(a0)
*
***********************************************************
* Inputs: none
* Output: d0 contains vbr.

GetVBR:		move.l	a5,-(sp)		; save it.
		moveq	#0,d0			; clear
		movea.l	4.w,a6			; exec base
		btst.b	#AFB_68010,AttnFlags+1(a6); are we at least a 68010?
		beq.b	.1			; nope.
		lea.l	vbr_exception(pc),a5	; addr of function to get VBR
		CALL	Supervisor		; supervisor state
.1:		move.l	(sp)+,a5		; restore it.
		rts				; return

vbr_exception:
	; movec vbr,Xn is a priv. instr.  You must be supervisor to execute!
;		movec   vbr,d0
	; many assemblers don't know the VBR, if yours doesn't, then use this
	; line instead.
		dc.w	$4e7a,$0801
		rte				; back to user state code

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

		section TheData,data

GraphicsName:	GRAFNAME		; name of gfx library
		EVEN

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

		section	OldPointers_and_such,bss

gfx_base	ds.l	1		; pointer to graphics base
OldView		ds.l    1		; old Work Bench view addr.
VectorBase:	ds.l	1		; pointer to the Vector Base

OldDMACon:	ds.w	1		; old dmacon bits
OldINTEna:	ds.w	1		; old intena bits

ntsc:		ds.b	1		; 0 = pal, 1 = ntsc
AGA:		ds.b	1		; 0 = ESC/standard, 1 = AGA
