*
* 6581.asm - SID-Emulation
*
* Copyright (C) 1994-1995 by Christian Bauer
*

*
* Anmerkungen:
* ------------
*
* Funktionsprinzip:
*  - Es bestehen zwei Möglichkeiten zur SID-Emulation, die über das
*    Flag UseSIDCard ausgewählt werden. Zum einen die Verwendung der
*    SID-Karte, zum anderen die der "6581sid.library"
*
* SID-Karte:
*  - Die SID-Karte enthält einen echten C64-SID, der im Adreßraum
*    $a00001-$a00039 (Register an den ungeraden Adressen) eingeblendet
*    ist (z.B. auf einer Zorro-II-Karte)
*  - Wegen Timing-Problemen mit der Karte werden Lesezugriffe aus
*    SID-Registern nur simuliert
*  - Die Power-LED ist mit dem Reset-Eingang des SID verbunden,
*    d.h. ein kurzes Aus- und Einschalten der LED setzt den SID
*    zurück
*

		MACHINE	68020

		INCLUDE	"exec/types.i"
		INCLUDE	"exec/macros.i"
		INCLUDE	"exec/nodes.i"
		INCLUDE	"hardware/intbits.i"

		XREF	_SysBase
		XREF	_GfxBase
		XREF	_SID6581Base

		XREF	Random

		XDEF	Reset6581
		XDEF	ReadFrom6581
		XDEF	WriteTo6581
		XDEF	PauseSound
		XDEF	ResumeSound
		XDEF	ChangedSID
		XDEF	CloseSID
		XDEF	UseSIDCard	;Prefs

		SECTION	"CODE",CODE

*
* Definitionen
*

; 6581sid.library
SID_AllocSID	= -30
SID_FreeSID	= -36
SID_Interrupt	= -42
SID_Initialize	= -48
SID_ResetSID	= -54
SID_IRQOnOff	= -60
SID_ReadReg	= -72
SID_WriteReg	= -78

; SID Handle Struktur
sid_Enabled	= 4
sid_Filter	= 5
sid_60Hz	= 6
sid_RingQual	= 7
sid_SyncQual	= 8
sid_ADSRQual	= 13
sid_IRQRate	= 18


**
** SID-Einstellung wurde verändert.
** Emulation über Library ein-/ausschalten
**

ChangedSID	tst.w	UseSIDCard
		beq	OpenSID

; Emulation über Library ausschalten
CloseSID	move.l	SIDHandle,d0
		beq	1$

		move.l	a6,-(sp)
		move.l	_SID6581Base,a6		;SID abschalten
		move.l	d0,a1
		moveq	#-1,d0
		jsr	SID_IRQOnOff(a6)

		move.l	_SysBase,a6		;VBI entfernen
		lea	VBInterrupt,a1
		moveq	#INTB_VERTB,d0
		JSRLIB	RemIntServer

		move.l	_SID6581Base,a6
		move.l	SIDHandle,a1		;Und SIDHandle freigeben
		jsr	SID_FreeSID(a6)
		clr.l	SIDHandle
		move.l	(sp)+,a6
1$		rts

; Emulation über Library einschalten
OpenSID		tst.l	SIDHandle
		bne	1$

		move.l	_SID6581Base,d0		;6581sid.library offen?
		beq	1$

		move.l	a6,-(sp)		;Ja, SIDHandle holen
		move.l	d0,a6
		jsr	SID_AllocSID(a6)
		move.l	d0,SIDHandle
		beq	2$

		move.l	d0,a1			;Parameter setzen
		st.b	sid_Enabled(a1)
		clr.b	sid_Filter(a1)
		st.b	sid_60Hz(a1)
		move.b	#48,sid_RingQual(a1)
		move.b	#48,sid_SyncQual(a1)
		move.b	#48,sid_ADSRQual(a1)
		move.w	#60,sid_IRQRate(a1)
		jsr	SID_Initialize(a6)

		move.l	SIDHandle,a1		;SID anschalten
		moveq	#0,d0
		jsr	SID_IRQOnOff(a6)

		move.l	_SysBase,a6		;VBI einrichten
		lea	VBInterrupt,a1
		moveq	#INTB_VERTB,d0
		JSRLIB	AddIntServer

2$		move.l	(sp)+,a6
1$		rts


**
** Interrupt-Routine
** a1: SIDHandle
**

IntProc		move.l	_SID6581Base,a6
		jsr	SID_Interrupt(a6)
		moveq	#0,d0			;Nächsten Server aufrufen
		rts


**
** Sound stummschalten
**

PauseSound	move.l	SIDHandle,d0
		beq	1$
		move.l	a6,-(sp)
		move.l	_SID6581Base,a6
		move.l	d0,a1
		moveq	#-1,d0
		jsr	SID_IRQOnOff(a6)
		move.l	(sp)+,a6
1$		rts


**
** Sound wieder laut machen
**

ResumeSound	move.l	SIDHandle,d0
		beq	1$
		move.l	a6,-(sp)
		move.l	_SID6581Base,a6
		move.l	d0,a1
		moveq	#0,d0
		jsr	SID_IRQOnOff(a6)
		move.l	(sp)+,a6
1$		rts


**
** SID zurücksetzen
**

Reset6581	move.l	a6,-(sp)
		tst.w	UseSIDCard
		beq	1$
		move.l	_GfxBase,a6
		JSRLIB	WaitTOF
		bset	#1,$bfe001	;LED aus
		JSRLIB	WaitTOF
		bclr	#1,$bfe001	;LED an
		move.l	(sp)+,a6
		rts

1$		move.l	SIDHandle,d0
		beq	2$
		move.l	_SID6581Base,a6
		move.l	d0,a1
		jsr	SID_ResetSID(a6)
2$		move.l	(sp)+,a6
		rts


**
** Aus einem SID-Register lesen
** d0.w: Registernummer ($00-$1f)
** Rückgabe: d0.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
** Darf a1 nicht verändern!
**

ReadFrom6581	cmp.b	#$19,d0
		beq	ReadFF
		cmp.b	#$1a,d0
		beq	ReadFF
		cmp.b	#$1b,d0
		beq	ReadRnd
		moveq	#0,d0
		rts

ReadFF		move.b	#-1,d0		;A/D-Wandler
		rts

ReadRnd		jsr	Random
		moveq	#0,d1		;MSW löschen
		rts


**
** In ein SID-Register schreiben
** d0.w: Registernummer ($00-$1f)
** d1.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**

WriteTo6581	tst.w	UseSIDCard
		beq	1$
		lea	$a00001,a0	;SID-Karte
		move.b	d1,(a0,d0.w*2)
		rts

1$		tst.l	SIDHandle
		beq	2$
		move.l	a6,-(sp)
		move.l	_SID6581Base,a6
		move.l	SIDHandle,a1	;d0: Regnum, d1: Byte
		jsr	SID_WriteReg(a6)
		move.l	(sp)+,a6
		moveq	#0,d0
		moveq	#0,d1
2$		rts


**
** Konstanten
**

IntName		dc.b	"Frodo SID VBI",0

**
** Datenbereich
**

		SECTION	"DATA",DATA

VBInterrupt	dc.l	0,0
		dc.b	NT_INTERRUPT,0
		dc.l	IntName
SIDHandle	dc.l	0	;Handle für die 6581sid.library und Flag, daß sie verfügbar ist
		dc.l	IntProc

UseSIDCard	dc.w	0	;Flag: SID-Karte ansprechen

		END
