; PPCAGA-Delta
; External Video Driver for
; Flaming Plus/4 emulator for the Amiga
;
; version 2.0

	MACHINE	68020

        INCDIR	Include:

	INCLUDE exec/types.i
	INCLUDE	exec/memory.i
	INCLUDE	exec/exec_lib.i
	INCLUDE	utility/tagitem.i
	INCLUDE	intuition/intuition.i
	INCLUDE	intuition/intuition_lib.i
	INCLUDE	intuition/screens.i
	INCLUDE	graphics/graphics_lib.i
	INCLUDE graphics/modeid.i
	INCLUDE	graphics/rastport.i
	INCLUDE	dos/dos.i
	INCLUDE	dos/dos_lib.i
	INCLUDE	libraries/asl.i
	INCLUDE	libraries/asl_lib.i
	INCLUDE	macros.i

;*** Handler structure

 STRUCTURE vxd_handler,0
  LONG intuibase
  LONG graphbase
  LONG dosbase
  LONG aslbase
  LONG myscr
  LONG mywin
  LONG planes
  WORD xsize
  WORD ysize
  LONG chunkysize
  LONG palette
  LONG palette32
  LONG emuscr1
  LONG emuscr2
  LONG delta
  LONG bytesperrow
  LONG scrmodereq
  LONG screendim
 LABEL	vxd_handler_SIZEOF

JSRLIB	MACRO
	jsr	_LVO\1(a6)
	ENDM

	XREF	drv_RefreshPPC		;The PPC based refresh routine

;*** Let's begin

	moveq.l	#0,d0
	rts

	dc.b "FLAMINGOXVD"
	dc.b "2"

	dc.l Name
	dc.l Author
	dc.w 2
	dc.w 0

	dc.l drv_Init
	dc.l drv_Done
	dc.l drv_Configure
	dc.l drv_OpenScreen
	dc.l drv_CloseScreen
	dc.l 0			;No 68k version of refresh
	dc.l drv_RefreshPPC

Name:	dc.b	"PPCAGA-Delta External Video Driver",0
Author:	dc.b	"Álmos Rajnai (original C2P by James McCoull & Peter McGavin)",0

	EVEN

;*** Functions

drv_Init:
	movem.l	a0-a1,-(sp)	;Saving infos
	move.l  4.w,a6		;Alloc memory for handler
	move.l	#MEMF_PUBLIC|MEMF_CLEAR,d1
	move.l	#vxd_handler_SIZEOF,d0
	JSRLIB	AllocVec
	movem.l	(sp)+,a0-a1	;Recover infos
        tst.l	d0
	beq.b	drv_Init_nomem	;No mem
	movea.l	d0,a2
        move.l	(a0),graphbase(a2)	;Saving graphics.library base
        move.l	4(a0),dosbase(a2)	;Saving dos.library base
        move.l	8(a0),intuibase(a2)	;Saving intuition.library base
        move.l	16(a0),aslbase(a2)	;Saving asl.library base
	tst.l	20(a0)			;No powerpc.lib -> error
	beq.b	drv_Init_nopowerlib

        movem.l	d0,-(sp)
	move.l	dosbase(a2),a6		;Reading config file
	move.l	#configfile,d1		;Config file is pretty simple:
	move.l	#MODE_OLDFILE,d2	;only a screenmode number
	JSRLIB	Open
	tst.l	d0
	beq.b	.2			;Failed open
	move.l	d0,d1
	move.l	(sp),a0
	lea	screendim(a0),a0
	move.l	a0,d2
	moveq.l	#4,d3
	movem.l	d0,-(sp)
	JSRLIB	Read			;Reading the 4 bytes
	cmp.l	#4,d0
	beq.b	.3
	move.l	(sp),a0			;Failed: set 0 instead garbage
	move.l	#0,screendim(a0)

.3	movem.l	(sp)+,d1
	JSRLIB	Close
.2	movem.l	(sp)+,d0		;Give back handler address
	rts

drv_Init_nomem:
	moveq.l	#0,d0
	move.l	#err_nomem,d1
	rts

drv_Init_nopowerlib:
	move.l	a2,a1
	JSRLIB	FreeVec			;Deallocate handler
	moveq.l	#0,d0
	move.l	#err_nopowerlib,d1
	rts

drv_Done:
	tst.l	a0
	beq.b	.1
	move.l	4.w,a6
	move.l	a0,a1
	JSRLIB	FreeVec			;Deallocate handler
.1
	rts

drv_Configure:				;Configure
					;A simple screenmode requester appears
	movem.l	a0,-(sp)
	move.l	screendim(a0),displayid
	move.l	#ASL_ScreenModeRequest,d0	
	move.l	aslbase(a0),a6
	lea	asltags,a0
	JSRLIB	AllocAslRequest
	move.l	(sp),a0
	move.l	d0,scrmodereq(a0)
	tst.l	d0
	bne.b	config2
	move.l	intuibase(a0),a6
	JSRLIB	DisplayBeep
	lea	4(sp),sp
	rts

config2:
	move.l	d0,a0
	suba.l	a1,a1
	JSRLIB	AslRequest
	tst.l	d0
	beq.b	.1

	move.l	(sp),a1
	move.l	scrmodereq(a1),a0
	move.l	sm_DisplayID(a0),screendim(a1)

	move.l	dosbase(a1),a6		;Writing config file
	move.l	#configfile,d1		;Config file is pretty simple:
	move.l	#MODE_NEWFILE,d2	;only a screenmode number
	JSRLIB	Open
	tst.l	d0
	beq.b	.1			;Failed open
	move.l	d0,d1
	move.l	(sp),a0
	lea	screendim(a0),a0
	move.l	a0,d2
	moveq.l	#4,d3
	movem.l	d0,-(sp)
	JSRLIB	Write			;Writing the 4 bytes

	movem.l	(sp)+,d1		;We don't care too much on
	JSRLIB	Close			;success...

.1	movem.l	(sp)+,a0
	move.l	aslbase(a0),a6
	move.l	scrmodereq(a0),a0
	JSRLIB	FreeAslRequest
	rts

drv_OpenScreen:
	movea.l a0,a5
	move.w	(a1)+,xsize(a5)
	move.w	(a1)+,ysize(a5)
	move.l	(a1)+,palette(a5)
	move.l	screendim(a5),screenmode	;screenmode from init

	moveq.l	#0,d0
	move.l	d0,d1
	move.w	xsize(a5),d0
	move.w	ysize(a5),d1
	mulu.w	d1,d0
	move.l	d0,chunkysize(a5)
	move.l	#MEMF_PUBLIC|MEMF_CLEAR,d1
	move.l	4.w,a6
	JSRLIB	AllocVec
	move.l	d0,emuscr1(a5)		;allocating emulator screen1
	tst.l	d0
	beq.w	.1
	move.l	chunkysize(a5),d0
	move.l	#MEMF_PUBLIC|MEMF_CLEAR,d1
	move.l	4.w,a6
	JSRLIB	AllocVec
	move.l	d0,emuscr2(a5)		;allocating emulator screen2
	tst.l	d0
	beq.w	.1

	move.l	chunkysize(a5),d0
	move.l	#MEMF_PUBLIC|MEMF_CLEAR,d1
	move.l	4.w,a6
	JSRLIB	AllocVec
	move.l	d0,delta(a5)		;allocating delta buffer
	tst.l	d0
	beq.w	.1

	move.l	#MEMF_PUBLIC,d1
	move.l	#128*3*4+4+16,d0
	JSRLIB	AllocVec
	move.l	d0,palette32(a5)	;Convert palette to 32 bit per gun
	beq.w	.1
	movea.l	d0,a0
        move.l	palette(a5),a1
	move.w	#128,(a0)+
	move.w	#$0,(a0)+
	move.l	#128*3-1,d2
.2	moveq.l	#0,d0
	move.b	(a1)+,d0
	swap	d0
	asl.l	#8,d0
	move.l	d0,(a0)+
	dbf	d2,.2
	move.l	#0,(a0)+
	move.l	#0,(a0)+
	move.l	#0,(a0)+
	move.l	#0,(a0)+
	move.w	xsize(a5),width+2
	move.w	ysize(a5),height+2
	move.l	palette32(a5),pal

        suba.l	a0,a0			;No newscreen stuct
        lea	scrtags,a1
	movea.l	intuibase(a5),a6
	JSRLIB	OpenScreenTagList
	move.l	d0,myscr(a5)
	beq.w	.1
	move.l	d0,wscr
	move.l	d0,a0
	lea	sc_RastPort(a0),a0
	movea.l	rp_BitMap(a0),a0
	move.l	#BMA_FLAGS,d1
	movea.l	graphbase(a5),a6
	JSRLIB	GetBitMapAttr
	and.l	#BMF_STANDARD|BMF_INTERLEAVED,d0
	cmp.l	#BMF_STANDARD|BMF_INTERLEAVED,d0
	beq.b	.3
	movea.l	intuibase(a5),a6
	move.l	myscr(a5),a0
	JSRLIB	CloseScreen
	moveq.l	#0,d0
	move.l	d0,myscr(a5)
	bra.b	.1

.3	move.w	xsize(a5),wwidth+2
	move.w	ysize(a5),wheight+2
	suba.l	a0,a0
	lea	wintags,a1
	movea.l	intuibase(a5),a6
	JSRLIB	OpenWindowTagList
	move.l	d0,mywin(a5)
	beq.b	.1
	movea.l	d0,a1
	move.l  wd_RPort(a1),a0
	move.l	rp_BitMap(a0),a0
	move.l	bm_Planes(a0),planes(a5)
	moveq.l	#0,d0
	move.w	bm_BytesPerRow(a0),d0
	lsr.w	#3,d0
	move.l	d0,bytesperrow(a5)
	move.l  wd_UserPort(a1),d0	;IDCMP port
	move.l	emuscr1(a5),d2		;chunky buffer

.1	move.l	#err_noscr,d1
	moveq.l	#0,d3			;no chunky modulo
	rts

drv_CloseScreen:
	move.l	a0,a5
	move.l	mywin(a5),a0
	cmpa.l	#0,a0
	beq.b	.1

	move.l	intuibase(a5),a6
	move.l	mywin(a5),a0
	JSRLIB	CloseWindow

.1	move.l	myscr(a5),a0
	cmpa.l	#0,a0
	beq.b	.2
	JSRLIB	CloseScreen

.2	movea.l	palette32(a5),a1
        cmpa.l	#0,a1
	beq.b	.3
	move.l	4.w,a6
	JSRLIB	FreeVec			;Deallocate translated palette

.3	movea.l	emuscr1(a5),a1
        cmpa.l	#0,a1
	beq.b	.6
	move.l	4.w,a6
	JSRLIB	FreeVec			;Deallocate chunky buffer

.6	movea.l	emuscr2(a5),a1
        cmpa.l	#0,a1
	beq.b	.5
	move.l	4.w,a6
	JSRLIB	FreeVec			;Deallocate chunky buffer

.5	movea.l	delta(a5),a1
        cmpa.l	#0,a1
	beq.b	.4
	move.l	4.w,a6
	JSRLIB	FreeVec			;Deallocate delta buffer

.4	moveq.l	#0,d0
	move.l	d0,emuscr1(a5)		;They were already freed
	move.l	d0,emuscr2(a5)
	move.l	d0,delta(a5)
	move.l	d0,palette32(a5)
	move.l	d0,myscr(a5)
	move.l	d0,mywin(a5)

	rts

;*** Constants

scrtags:
	dc.l    SA_Width
width:	dc.l	0
	dc.l	SA_Height
height:	dc.l	0
	dc.l	SA_Depth,8
	dc.l	SA_Colors32
pal:	dc.l	0
	dc.l	SA_Title,scrtitle
	dc.l	SA_ShowTitle,FALSE
	dc.l	SA_DisplayID
screenmode:
	dc.l	0
	dc.l	SA_Interleaved,TRUE
	dc.l	SA_Type,CUSTOMSCREEN
	dc.l	SA_AutoScroll,TRUE
	dc.l	SA_Overscan,OSCAN_STANDARD
	dc.l	SA_Quiet,TRUE
	dc.l	TAG_DONE

wintags:
	dc.l    WA_Left,0
	dc.l	WA_Top,0
	dc.l	WA_Width
wwidth:	dc.l	0
	dc.l	WA_Height
wheight:	dc.l    0
	dc.l	WA_IDCMP,IDCMP_RAWKEY
	dc.l    WA_Title,0
	dc.l	WA_Backdrop,TRUE
	dc.l	WA_RMBTrap,TRUE
	dc.l	WA_Borderless,TRUE
	dc.l	WA_NoCareRefresh,TRUE
	dc.l	WA_CustomScreen
wscr:	dc.l    0
	dc.l	WA_SimpleRefresh,TRUE
	dc.l	WA_Activate,TRUE
	dc.l	TAG_DONE

asltags:
	dc.l	ASLSM_TitleText,configwintxt
	dc.l	ASLSM_InitialDisplayID
displayid:
	dc.l	0
	dc.l	TAG_DONE

powerpclibname:	dc.b	"powerpc.library",0

scrtitle:	dc.b	'Flamingo Plus/4 emulator screen',0

configwintxt:	dc.b	'Choose desired screenmode',0

configfile:	dc.b	'ppcaga-delta.cfg',0

;*** Errors

err_nomem:
	dc.b	'Ran out of memory',0
err_noscr:
	dc.b	'Cannot open screen',0
err_nopowerlib:
	dc.b	'This driver requires powerpc.library',0

