	machine	68020

******************************************************************************
* main 1.1.2
******************************************************************************
* INFO	moves the VBR to FAST memory;
*	if VBR has already been moved with VBR2FAST itself, the old
*	VBR is restored
* NOTE	run from CLI only
******************************************************************************

KWD0	=	"vBr2"
KWD1	=	"fAsT"

	when init[]		;init

	 when #-1<>GetVBR[]	;get VBR
	  move.l d0,CurVBR	;store it

	  when ChkPatch[d0]	;check if already VBR2FASTed
	   RestVBR[CurVBR]	;if so, restore previous VBR
	   prt[#TxtTtl]
	   prt[#TxtSxs1]
	  owhen MkVecTab[CurVBR]	;else build vectors new table
	   ChgVBR[d0]	;update VBR with new one
	   prt[#TxtTtl]
	   prt[#TxtSxs0]
	  othw		;if not enough memory
	   prt[#TxtTtl]
	   prt[#TxtNoMem]	;show error message
	  ewhen

	 othw		;if 68000
	  prt[#TxtTtl]
	  prt[#Txt68000]	;show error message
	 ewhen

	ewhen
	rts



******************************************************************************
* ChkPatch 0.0.0
******************************************************************************
* INFO	checks if the VBR has already been VBR2FASTed
* SYN	V2Fed = ChkPatch[CurVBR]
*	d0.l             a0.l
* IN	CurVBR	current value of VBR
* OUT	V2Fed	0=not patched; ~0=patched
******************************************************************************

	function ChkPatch[a0],a0:d0
	moveq.l	#0,d0
	when.s #KWD0=-(a0) & #KWD1=-(a0)
	 moveq.l	#1,d0
	ewhen
	efunc



******************************************************************************
* RestVBR 0.0.0
******************************************************************************
* INFO	restores the VBR previously patched by VBR2FAST
* SYN	RestVBR[CurVBR]
*	        a0.l
* IN	CurVBR	current value of VBR
* NOTE	when calling this procedure be sure CurVBR has really been
*	set by VBR2FAST, otherwise... GURU!!!
******************************************************************************

	procedure RestVBR[a0],d0-d1/a0-a1/a6
	clr.l	-(a0)	;clear safety
	clr.l	-(a0)	;keyword
	ChgVBR[-(a0)]	;restore previous VBR
	movea.l	-(a0),a1	;get buffer actual address
	move.l	#256*4+20,d0
	movea.l	4.w,a6
	jsr	(-210,a6)	;FreeMem()
	eproc



******************************************************************************
* MkVecTab 1.1.0
******************************************************************************
* INFO	allocates and builds the new table of vectors
* SYN	NewVBR = MkVecTab[CurVBR]
*	d0.l               d0.l
* IN	CurVBR	current VBR
* OUT	NewVBR	address of new table (0=ERROR)
* NOTE	- the NewVBR is always longword aligned
*	- the vector table has an header of this kind:
*	   NewVBR-16: actual buffer address (may not be longword aligned)
*	   NewVBR-12: old VBR (=CurVBR)
*	   NewVBR -8: KWD1 part1 of safety keyword
*	   NewVBR -4: KWD0 part0 of safety keyword
******************************************************************************

	function MkVecTab[d0],d1-d7/a0-a6:d0.l

	movea.l	d0,a2	;keep CurVBR

	move.l	#256*4+20,d0	;room for 256 vectors+header+alignment
	moveq.l	#4,d1	;FAST memory only
	movea.l	4.w,a6
	jsr	(-198,a6)	;AllocMem()
	move.l	d0,d1	;keep table address
	when ne		;if table address<>0

	 addq.l	#3,d0	;longword
	 andi.l	#$fffffffc,d0	;alignment
	 movea.l	d0,a0	;aligned address
	 move.l	d1,(a0)+	;store table actual address
	 move.l	a2,(a0)+	;store CurVBR
	 move.l	#KWD1,(a0)+	;write safety
	 move.l	#KWD0,(a0)+	;keyword

	 move.l	a0,d0	;new VBR

	 expire d1=#255	;copy all
	  move.l	(a2)+,(a0)+	;exception vectors
	 nexp

	ewhen
	efunc



*****************************************************************************
* init 0.0.0
*****************************************************************************
* INFO	just some general inits...
* SYN	ErrCode = init[]
*	d0.l
* OUT	ErrCode	0=ERROR; ~0=OK
* MOD	DOSBase	dos.library base pointer
*	StdOut	output handle assigned by AmigaOS
*****************************************************************************

	function init[],d1-d2/a0-a1/a6:d0.l
	moveq.l	#0,d2	;ERROR

	lea.l	(DOSNm,pc),a1
	moveq.l	#36,d0	;at least KS 2.0
	movea.l	4.w,a6
	jsr	(-552,a6)	;OpenLibrary()
	move.l	d0,DOSBase
	when.s ne
	 movea.l	d0,a6
 	 jsr	(-60,a6)	;OutPut()
	 move.l	d0,StdOut
	 moveq.l	#1,d2	;OK
	ewhen
	efunc,d2



*****************************************************************************
* GetVBR 0.0.4
*****************************************************************************
* INFO	gets the current value of the VBR
* SYN	VBR = GetVBR[]
*	d0.l
* OUT	VBR	current VBR
* NOTE	VBR = -1 if the CPU is a 68000
*****************************************************************************

	function GetVBR[],a5-a6:d0.l
	movea.l	4.w,a6
	btst.b	#0,($129,a6)
	when.s ne		;if not 68000
	 lea.l	(.get,pc),a5
	 jsr	(-30,a6)	;Supervisor()
	othw		;else if 68000
	 moveq.l	#-1,d0	;ERROR
	ewhen
	pop.s		;don't execute movec again
.get	movec.l	vbr,d0	;get the VBR
	rte
	efunc



*****************************************************************************
* ChgVBR 0.0.1
*****************************************************************************
* INFO	changes the value of the VBR
* SYN	GetVBR[NewVBR]
*	       d0.l
* IN	NewVBR	value to write to the VBR
* NOTE	no check on 68k type
*****************************************************************************

	procedure ChgVBR[d0],a5-a6
	movea.l	4.w,a6
	lea.l	(.chg,pc),a5
	jsr	(-30,a6)	;Supervisor()
	pop.s		;don't execute movec again
.chg	movec.l	d0,vbr	;write NewVBR
	rte
	eproc



*******************************************************************************
* prt 0.0.1
*******************************************************************************
* INFO	prints a text to the standard output
* SYN	prt[TxtPtr]
*	      d2.l
* IN	TxtPtr	pointer to NULL-terminated text string
* REQ	DOSBase	dos.library pointer
*	StdOut	standard output handle
*******************************************************************************

	procedure prt[d2],d0-d3/a0-a1/a6
	movea.l	d2,a0
.FndEnd	tst.b	(a0)+
	bne.s	.FndEnd	;find end of string
	move.l	a0,d3
	sub.l	d2,d3	;string length
	movea.l	DOSBase,a6
	move.l	StdOut,d1
	jsr	(-48,a6)	;Write()
	eproc



******************************************************************************
* data

	cnop	0,4
DOSBase	dc.l	0
StdOut	dc.l	0
CurVBR	dc.l	0

DOSNm	dc.b	"dos.library",0
	dc.b	"$VER: VBR2FAST 1.2 (20.5.2002)"
TxtTtl	dc.b	10,"›1mVBR2FAST 1.2›0m (20.5.2002) - © 1999 Simone Bevilacqua",10,0
Txt68000	dc.b	"ERROR: the MC68000 has not the VBR!",10,10,0
TxtNoMem	dc.b	"ERROR: not enough memory",10,10,0
TxtSxs0	dc.b	"VBR successfully moved!",10,10,0
TxtSxs1	dc.b	"VBR successfully restored!",10,10,0
