*
* RetinaZ3.asm - ShapeShifter external video driver for Retina Z3
*
* $VER: RetinaZ3.asm 1.0 (22.07.95)
*
* (C) Copyright 1995 Christian Bauer
*

		MACHINE	68020

		INCLUDE	"exec/types.i"
		INCLUDE	"exec/macros.i"
		INCLUDE	"exec/memory.i"
		INCLUDE	"intuition/intuition.i"
		INCLUDE	"utility/tagitem.i"
		INCLUDE	"exec/alerts.i"
		INCLUDE	"retina/retina.i"
		INCLUDE	"retina/retinaemu.i"
		INCLUDE	"retina/retina_lib.i"
		INCLUDE	"retina/retinaemu_lib.i"
		INCLUDE	"shapeextvideo.i"

*
* Definition of our private context structure for storing local variables
*

 STRUCTURE	MyContext,0
	APTR	conIntuitionBase
	APTR	conGfxBase
	APTR	conDOSBase
	APTR	conRetinaBase
	APTR	conRetinaEmuBase

	APTR	conScreen	;The screen
	APTR	conViewPort	;The screen's ViewPort
	APTR	conBitMap	;The screen's RastPort
	APTR	conRetinaScr	;The screen's RetinaScreen

	STRUCT	conRGBBuf,256*3	;Buffer for LoadRGB32

	WORD	conVideoMode	;Video mode (VMODE_*)
 LABEL	MyContext_SIZEOF

*
* This is the driver header
*

		EVHEADER DriverTags

*
* The header tags that describe the driver and provide pointers to
* the driver's routines
*

DriverTags	dc.l	SHEV_Level,1		;Interface level 1
		dc.l	SHEV_Version,1
		dc.l	SHEV_Revision,1
		dc.l	SHEV_Name,DriverName
		dc.l	SHEV_ID,DriverID
		dc.l	SHEV_Author,DriverAuthor

		dc.l	SHEV_OpenScreen,MyOpenScreen
		dc.l	SHEV_CloseScreen,MyCloseScreen
		dc.l	SHEV_LoadRGB32,MyLoadRGB32
		dc.l	TAG_END,0

DriverName	dc.b	"Retina Z3 RetinaEmu Driver",0
		CNOP	0,4
DriverID	dc.b	"$VER: Retina Z3 1.1 (20.08.95)",13,10,0
		CNOP	0,4
DriverAuthor	dc.b	"Christian Bauer",0
		CNOP	0,4

*
* The OpenScreen routine
* a0: Taglist with input parameters
* a1: Taglist with output parameters
* a6: Base of utility.library
*

MyOpenScreen	movem.l	d2-d7/a2-a6,-(sp)
		move.l	a0,a4			;a4: Input taglist
		move.l	a1,a5			;a5: Output taglist
		move.l	a6,_UtilityBase
		move.l	(4).w,_ExecBase

; Allocate memory for context
		move.l	_ExecBase,a6
		move.l	#MyContext_SIZEOF,d0
		move.l	#MEMF_PUBLIC|MEMF_CLEAR,d1
		JSRLIB	AllocVec
		tst.l	d0
		beq	OpenFailed
		move.l	d0,a2			;a2: Context

; Open intuition.library
		move.l	_ExecBase,a6
		lea	IntuitionName,a1
		moveq	#37,d0
		JSRLIB	OpenLibrary
		move.l	d0,conIntuitionBase(a2)
		beq	OpenFailed

; Open graphics.library
		move.l	_ExecBase,a6
		lea	GfxName,a1
		moveq	#37,d0
		JSRLIB	OpenLibrary
		move.l	d0,conGfxBase(a2)
		beq	OpenFailed

; Open dos.library (for Delay())
		move.l	_ExecBase,a6
		lea	DOSName,a1
		moveq	#37,d0
		JSRLIB	OpenLibrary
		move.l	d0,conDOSBase(a2)
		beq	OpenFailed

; Open retina.library
		move.l	_ExecBase,a6
		lea	RetinaName,a1
		moveq	#0,d0
		JSRLIB	OpenLibrary
		move.l	d0,conRetinaBase(a2)
		beq	OpenFailed

; Open retinaemu.library
		move.l	_ExecBase,a6
		lea	RetinaEmuName,a1
		moveq	#0,d0
		JSRLIB	OpenLibrary
		move.l	d0,conRetinaEmuBase(a2)
		beq	OpenFailed

; Store context pointer in output taglist
		move.l	_UtilityBase,a6
		move.l	a5,a0
		move.l	#SHEV_Context,d0
		JSRLIB	FindTagItem
		move.l	d0,a0
		move.l	a2,ti_Data(a0)

; Get video mode and set the refresh type and screen depth accordingly
; This driver only supports VMODE_8BIT, VMODE_15BIT and VMODE_24BIT
		move.l	_UtilityBase,a6
		move.l	a4,a0
		move.l	#SHEV_VideoMode,d0
		moveq	#VMODE_1BIT,d1		;Dummy default
		JSRLIB	GetTagData
		move.w	d0,conVideoMode(a2)

		cmp.l	#VMODE_8BIT,d0
		bne	10$
		move.l	a5,a0
		move.l	#SHEV_RefreshType,d0
		JSRLIB	FindTagItem
		tst.l	d0
		beq	12$
		move.l	d0,a1
		move.l	#RTYPE_NONE,ti_Data(a1)
		move.l	#8,ScrDepth
		bra	12$
10$
		cmp.l	#VMODE_15BIT,d0
		bne	11$
		move.l	a5,a0
		move.l	#SHEV_RefreshType,d0
		JSRLIB	FindTagItem
		tst.l	d0
		beq	12$
		move.l	d0,a1
		move.l	#RTYPE_RGB16PC,ti_Data(a1)
		move.l	#2,ScrDepth		;Necessary for RE_OpenDeepScreen()
		move.l	#16,DeepScrDepth
		bra	12$
11$
		cmp.l	#VMODE_24BIT,d0
		bne	OpenFailed
		move.l	a5,a0
		move.l	#SHEV_RefreshType,d0
		JSRLIB	FindTagItem
		tst.l	d0
		beq	12$
		move.l	d0,a1
		move.l	#RTYPE_BGR24,ti_Data(a1)
		move.l	#2,ScrDepth		;Necessary for RE_OpenDeepScreen
		move.l	#24,DeepScrDepth
12$

; Extract screen parameters from input taglist
		move.l	_UtilityBase,a6
		move.l	a4,a0
		move.l	#SHEV_ScreenX,d0
		moveq	#0,d1
		JSRLIB	GetTagData
		move.l	d0,ScrWidth

		move.l	a4,a0
		move.l	#SHEV_ScreenY,d0
		moveq	#0,d1
		JSRLIB	GetTagData
		move.l	d0,ScrHeight

		move.l	a4,a0
		move.l	#SHEV_DisplayID,d0
		moveq	#0,d1
		JSRLIB	GetTagData
		move.l	d0,ScrDisplayID

		move.l	a4,a0
		move.l	#SHEV_OverscanType,d0
		moveq	#OSCAN_TEXT,d1
		JSRLIB	GetTagData
		move.l	d0,ScrOverscan

; Open the screen and store pointer in output taglist
		cmp.w	#VMODE_8BIT,conVideoMode(a2)
		bne	OpenDeepScreen

		move.l	conIntuitionBase(a2),a6	;8 Bit
		sub.l	a0,a0
		lea	ScreenTags,a1
		JSRLIB	OpenScreenTagList
		move.l	d0,a3			;a3: Screen
		move.l	d0,conScreen(a2)
		beq	OpenFailed
		bra	ScreenOpened

OpenDeepScreen	move.l	a2,-(sp)		;16/24 Bit
		move.l	conRetinaEmuBase(a2),a6
		sub.l	a0,a0
		lea	ScreenTags,a1
		lea	DeepScreenTags,a2
		jsr	_LVORE_OpenDeepScreen(a6)
		move.l	d0,a3
		move.l	(sp)+,a2
		move.l	d0,conScreen(a2)
		beq	OpenFailed

ScreenOpened	move.l	_UtilityBase,a6
		move.l	a5,a0
		move.l	#SHEV_Screen,d0
		JSRLIB	FindTagItem
		move.l	d0,a0
		move.l	a3,ti_Data(a0)

; Wait a bit (retinaemu seems to need this)
		move.l	conDOSBase(a2),a6
		moveq	#15,d1
		JSRLIB	Delay

; Extract our private data
		lea	sc_ViewPort(a3),a0
		move.l	a0,conViewPort(a2)
		lea	sc_RastPort(a3),a0
		move.l	rp_BitMap(a0),conBitMap(a2)

; Did it open on the Retina card?
		move.l	conRetinaEmuBase(a2),a6
		move.l	conBitMap(a2),a0
		jsr	_LVORE_GetRetinaScreen(a6)
		move.l	d0,conRetinaScr(a2)
		beq	OpenFailed

; Extract all the other data that the caller wants
		move.l	_UtilityBase,a6
		move.l	a5,a0
		move.l	#SHEV_ScreenBase,d0
		JSRLIB	FindTagItem
		tst.l	d0
		beq	1$
		move.l	d0,a1
		move.l	conRetinaScr(a2),a0
		move.l	_rs_BitMap(a0),a0
		move.l	conRetinaBase(a2),a6
		jsr	_LVORetina_SetSegmentPtr(a6)	;Preserves a1
		move.l	d0,ti_Data(a1)
1$
		move.l	_UtilityBase,a6
		move.l	a5,a0
		move.l	#SHEV_BytesPerRow,d0
		JSRLIB	FindTagItem
		tst.l	d0
		beq	2$
		move.l	d0,a1
		move.l	conRetinaScr(a2),a0
		moveq	#0,d0
		move.w	_rs_Modulo(a0),d0
		move.l	d0,ti_Data(a1)
2$

; Everything is OK
		movem.l	(sp)+,d2-d7/a2-a6
		moveq	#0,d0
		rts

; An error occurred
OpenFailed	movem.l	(sp)+,d2-d7/a2-a6
		moveq	#-1,d0
		rts

*
* The CloseScreen routine
* a0: Taglist with input parameters
* a1: Taglist with output parameters
* a2: Context pointer (never NULL)
* a6: Base of utility.library
*

MyCloseScreen	movem.l	d2-d7/a2-a6,-(sp)

; Close the screen
		move.l	conScreen(a2),d0
		beq	1$
		cmp.w	#VMODE_8BIT,conVideoMode(a2)
		bne	11$
		move.l	d0,a0			;8 Bit
		move.l	conIntuitionBase(a2),a6
		JSRLIB	CloseScreen
		bra	1$
11$		move.l	d0,a0			;16/24 Bit
		move.l	conRetinaEmuBase(a2),a6
		jsr	_LVORE_CloseDeepScreen(a6)
1$

; Close retinaemu.library
		move.l	conRetinaEmuBase(a2),d0
		beq	2$
		move.l	d0,a1
		move.l	_ExecBase,a6
		JSRLIB	CloseLibrary
2$

; Close retina.library
		move.l	conRetinaBase(a2),d0
		beq	3$
		move.l	d0,a1
		move.l	_ExecBase,a6
		JSRLIB	CloseLibrary
3$

; Close dos.library
		move.l	conDOSBase(a2),d0
		beq	4$
		move.l	d0,a1
		move.l	_ExecBase,a6
		JSRLIB	CloseLibrary
4$

; Close graphics.library
		move.l	conGfxBase(a2),d0
		beq	5$
		move.l	d0,a1
		move.l	_ExecBase,a6
		JSRLIB	CloseLibrary
5$

; Close intuition.library
		move.l	conIntuitionBase(a2),d0
		beq	6$
		move.l	d0,a1
		move.l	_ExecBase,a6
		JSRLIB	CloseLibrary
6$

; Free context
		move.l	_ExecBase,a6
		move.l	a2,a1
		JSRLIB	FreeVec

CloseDone	movem.l	(sp)+,d2-d7/a2-a6
		moveq	#0,d0
		rts

*
* The LoadRGB32 routine
* a0: Taglist with input parameters
* a1: Taglist with output parameters
* a2: Context pointer
* a6: Base of utility.library
*

; Get pointer to 32 bit color table
MyLoadRGB32	movem.l	d2-d7/a2-a6,-(sp)
		move.l	a0,a4		;a4: Input taglist
		move.l	#SHEV_ColorTable,d0
		moveq	#0,d1
		JSRLIB	GetTagData
		move.l	d0,a0		;a0: Color table

; Convert to 8 bit color table
		lea	conRGBBuf(a2),a1
		move.w	#256*3-1,d1
1$		move.l	(a0)+,d0
		rol.l	#8,d0
		move.b	d0,(a1)+
		dbra	d1,1$

; Activate palette
		move.l	conRetinaBase(a2),a6
		move.l	conRetinaScr(a2),a0
		moveq	#0,d0		;Start with color #0
		move.l	#256,d1		;Load 256 colors
		lea	conRGBBuf(a2),a1
		jsr	_LVORetina_LoadPalette(a6)

		movem.l	(sp)+,d2-d7/a2-a6
		moveq	#0,d0
		rts

*
* Constants
*

; Library names
IntuitionName	dc.b	"intuition.library",0
GfxName		dc.b	"graphics.library",0
DOSName		dc.b	"dos.library",0
RetinaName	dc.b	"retina.library",0
RetinaEmuName	dc.b	"retinaemu.library",0

; The name of our screen
ScreenName	dc.b	"ShapeShifter Screen",0
		CNOP	0,4

*
* Data section
*

		SECTION	"DATA",DATA

; Taglist for OpenScreen()
; Note that it's only safe to use this structure here because
;  the SHEV_OpenScreen routine is guaranteed not to be called
;  more than once at a time. The buffer for LoadRGB32, however,
;  is declared in the Context and not in the BSS segment because
;  that routine may be called multiple times for multiple
;  screens.
ScreenTags	dc.l	SA_Depth
ScrDepth	dc.l	0
		dc.l	SA_Width
ScrWidth	dc.l	0
		dc.l	SA_Height
ScrHeight	dc.l	0
		dc.l	SA_DisplayID
ScrDisplayID	dc.l	0
		dc.l	SA_Overscan
ScrOverscan	dc.l	0
		dc.l	SA_Quiet,-1
		dc.l	SA_Title,ScreenName
		dc.l	TAG_END,0

; Taglist for RE_OpenDeepScreen()
DeepScreenTags	dc.l	RESA_Depth
DeepScrDepth	dc.l	0
		dc.l	0,0

*
* BSS section
*

		SECTION	"BSS",BSS

; Library base pointers
_ExecBase	ds.l	1
_UtilityBase	ds.l	1

		END
