
; Listing11f.s - Verwendung von COPER- und VERTB-Interrupt per Level 3 ($6c).
; In diesem Fall definieren wir alle Interrupts richtig neu, 
; um eine Vorstellung davon zu geben, wie es gemacht wird.
; Der Unterschied zu Listing11e.s ist "formal", tatsächlich wird es 
; verwendet für Interrupts dem Standard des Amiga ROM. Wenn Sie wollen
; folgen Sie einfach dem Label, wie in diesem Beispiel.

	SECTION	INTERRUPT,CODE

;	include	"DaWorkBench.s"	; entferne das; vor dem Speichern mit "wo"

*****************************************************************************
	include	"/Sources/startup2.s"	; speichern Sie Interrupt, DMA und so weiter.
*****************************************************************************


; Mit DMASET entscheiden wir, welche DMA-Kanäle geöffnet und welche geschlossen werden sollen

			;5432109876543210
DMASET	equ	%1000001010000000	; Copper DMA aktivieren

WAITDISK	equ	30				; 50-150 zur Rettung (je nach Fall)

Start:
	move.l	BaseVBR(pc),a0	    ; in a0 ist der Wert des VBR

	move.l	#NoInt1,$64(a0)		; Interrupt "leer"
	move.l	#NoInt2,$68(a0)		; int leer
	move.l	#MyInt6c,$6c(a0)	; ich lege meinen Interrupt-Level 3 fest
	move.l	#NoInt4,$70(a0)		; int leer
	move.l	#NoInt5,$74(a0)		; " "
	move.l	#NoInt6,$78(a0)		; " "

	move.w	#DMASET,$96(a5)		; DMACON - aktivieren Copper								
	move.l	#Copperlist,$80(a5)	; Zeiger Copperlist
	move.w	d0,$88(a5)			; Start Copperlist
	move.w	#0,$1fc(a5)			; AGA "deaktivieren"
	move.w	#$c00,$106(a5)		; AGA "deaktivieren"
	move.w	#$11,$10c(a5)		; AGA "deaktivieren"

	movem.l	d0-d7/a0-a6,-(sp)
	bsr.w	mt_init				; initialisieren der Musik Routine
	movem.l	(sp)+,d0-d7/a0-a6

			; 5432109876543210
	move.w	#%1111111111111111,$9a(a5)  ; INTENA - aktivieren Sie alle
										; interrupts!

Mouse:
	btst	#6,$bfe001			; Maus gedrückt? (Der Prozessor 
	bne.s	Mouse				; unterbricht die Schleife zu jedem vertical blank
								; um die Musik zu spielen!
								; sowie jedes WAIT der Rasterzeile $a0).						
				
	bsr.w	mt_end				; Ende der Wiederholung!

	rts							; Exit


*****************************************************************************
*	INTERRUPT-Routine $64 (Level 1)
*****************************************************************************

;	.-==-.
;	| __ |
;	C °° )
;	| C. |
;	| __ |
;	|(__)|xCz
;	`----'

;02	SOFT	1 ($64)	Reserviert für durch Software ausgelöste Interrupts.
;01	DSKBLK	1 ($64)	Ende der Übertragung eines Datenblocks von der Diskette.
;00	TBE		1 ($64)	Puffer UART-Übertragungs der seriellen Schnittstelle leer

NoInt1:	; $64
	movem.l	d0-d7/a0-a6,-(sp)
	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; ist Bit Master Reset aktiviert?
	beq.s	NoInts1				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.
	btst.l	#0,d1				; TBE?
	beq.w	NoTbe
	; tbe Routine
NoTbe:
	btst.l	#1,d1				; DSKBLK?
	beq.w	NoDskblk
	; DSKBLK Routine
NoDskblk:
	btst.l	#2,d1				; INTREQR - SOFT?
	beq.w	NoSoft
	; SOFT Routine
NoSoft:
NoInts1:	; 210
	move.w	#%111,$dff09c		; INTREQ - soft,dskblk,serial port tbe
	movem.l	(sp)+,d0-d7/a0-a6
	rte

*****************************************************************************
*	INTERRUPT-Routine $68 (Level 2)
*****************************************************************************

;	             ... 
;	             :  ·:
;	             :   :
;	         ____¦,.,l____
;	        /·.·.·   .·.·.\
;	      _/ _____  _____  \_
;	     C/_  (°  C  °)     \).
;	      \ \_____________/ /-'
;	       \  \___l_____/  /xCz
;	   ____ \__`-------'__/ _____
;	  /    ¯¯ `---------' ¯¯    ¬\
;	 /                            ·
;	·

;03	PORTS	2 ($68)	Input/Output Ports und Timers, verbunden mit der INT2-Leitung

NoInt2:	; $68
	movem.l	d0-d7/a0-a6,-(sp)
	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; Bit Master Reset aktivieren?
	beq.s	NoInts2				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.

	btst.l	#3,d1				; INTREQR - PORTS?
	beq.w	NoPorts
	; Routine PORTS
NoPorts:
	move.l	d0,-(sp)			; speichern d0
	move.b	$bfed01,d0			; CIAA ICR - ist es ein Interrupt der Tastatur?
	and.b	#$8,d0
	beq.w	NoKey
	; Routine zum Lesen der Tastatur
NoKey:
	move.l	(sp)+,d0			; Wiederherstellung d0
NoInts2:	; 3210
	move.w	#%1000,$dff09c		; INTREQ - ports
	movem.l	(sp)+,d0-d7/a0-a6
	rte

*****************************************************************************
*	INTERRUPT-Routine $6c (Level 3) - VERTB und COPER benutzt.				*
*****************************************************************************

;	 _.--._     _ 
;	|   _ .|   (_)
;	|   \__|   ||
;	|______|   ||
;	.-`--'-.   ||
;	| | |  |\__l|
;	|_| |__|__|_))
;	 ||_| |    ||
;	 |(_) |
;	 |    |
;	 |____|__
;	 |______/g®m


;06	BLIT	3 ($6c)	Wenn der Blitter eine Blittata beendet hat, wird es auf 1 gesetzt
;05	VERTB	3 ($6c)	Wird jedes Mal generiert, wenn der Elektronenstrahl in Betrieb ist
					; und zur Zeile 00 geht, dh zu jedem vertical blank.
;04	COPER	3 ($6c)	; Sie können es mit dem Copper einstellen, um ihn zu einem 
					; bestimmten Zeitpunkt (Videozeile) zu erzeugen. Fordern Sie ihn  
					; einfach nach einer gewissen Wartezeit an.

MyInt6c:
	movem.l	d0-d7/a0-a6,-(sp)
	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; ist Bit Master Reset aktiviert?
	beq.s	NoInts3				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.
	btst.l	#6,d1				; INTREQR - BLIT?
	beq.w	NoBlit
	; Routine BLIT
NoBlit:
	btst.l	#5,d1				; INTREQR - ist Bit 5, VERTB zurückgesetzt?
	beq.s	NoIntVertb			; Wenn ja, ist es kein "echter" VERTB Interrupt!
	movem.l	d0-d7/a0-a6,-(sp)	; Register speichern auf dem stack
	bsr.w	mt_music			; Musik spielen
	movem.l	(sp)+,d0-d7/a0-a6	; Register vom stack nehmen
NoIntVertb:
	btst.l	#4,d1				; INTREQR - ist Bit 4, COPER ist zurückgesetzt?
	beq.s	NoIntCoper			; wenn ja, ist es kein COPER Interrupt!
	move.w	#$f00,$dff180		; int COPER, dann COLOR00 = rot
NoIntCoper:
NoInts3:	 ;6543210
	move.w	#%1110000,$dff09c	; INTREQ - Löschen Flag BLIT,VERTB,COPER
	movem.l	(sp)+,d0-d7/a0-a6
	rte							; Ende vom Interrupt BLIT,VERTB,COPER

*****************************************************************************
*	INTERRUPT-Routine $70 (Level 4)
*****************************************************************************

;	  .:::::.
;	 ¦:::·:::¦
;	 |·     ·|
;	C| ¬   - l)
;	 ¡_°(_)°_|
;	 |\_____/|
;	 l__`-'__!
;	   `---'xCz

;10	AUD3	4 ($70)	Lesen eines Datenblocks über den Kanal Audio 3 beendet
;09	AUD2	4 ($70)	Lesen eines Datenblocks über den Kanal Audio 2 beendet
;08	AUD1	4 ($70)	Lesen eines Datenblocks über den Kanal Audio 1 beendet
;07	AUD0	4 ($70)	Lesen eines Datenblocks über den Kanal Audio 0 beendet

NoInt4: ; $70
	movem.l	d0-d7/a0-a6,-(sp)
	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; ist Bit Master Reset aktiviert?
	beq.s	NoInts4				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.
	btst.l	#7,d1				; INTREQR - AUD0?
	beq.w	NoAud0
	; Routine aud0
NoAud0:
	btst.l	#8,d1				; INTREQR - AUD1?
	beq.w	NoAud1
	; Routine aud1
NoAud1:
	btst.l	#9,d1				; INTREQR - AUD2?
	beq.w	NoAud2
	; Routine aud2
NoAud2:
	btst.l	#10,d1				; INTREQR - AUD3?
	beq.w	NoAud3
	; Routine aud3
NoAud3:
NoInts4:	; 09876543210
	move.w	#%11110000000,$dff09c	; aud0,aud1,aud2,aud3
	movem.l	(sp)+,d0-d7/a0-a6
	rte

*****************************************************************************
*	INTERRUPT-Routine $74 (Level 5)
*****************************************************************************

;	  .:::::.
;	 ¦:::·:::¦
;	 |· - - ·|
;	C|  q p  l)
;	 |  (_)  |
;	 |\_____/|
;	 l__  ¬__!
;	   `---'xCz

;12	DSKSYN	5 ($74)	wird generiert, wenn das DSKSYNC-Register mit den Daten übereinstimmt
				; Lesen Sie von der Diskette im Laufwerk. Achten Sie auf Hardwarelader.
;11	RBF		5 ($74)	UART-Puffer zum Empfangen des FULL-Serial-Ports.


NoInt5: ; $74
	movem.l	d0-d7/a0-a6,-(sp)
	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; ist Bit Master Reset aktiviert?
	beq.s	NoInts5				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.
	btst.l	#12,d1				; INTREQR - DSKSYN?
	beq.w	NoDsksyn
	; Routine dsksyn
NoDsksyn:
	btst.l	#11,d1				; INTREQR - RBF?
	beq.w	NoRbf
	; Routine rbf
NoRbf:
NoInts5:	; 2109876543210
	move.w	#%1100000000000,$dff09c	; serial port rbf, dsksyn
	movem.l	(sp)+,d0-d7/a0-a6
	rte

*****************************************************************************
*	INTERRUPT-Routine $78 (Level 6)				    *
*****************************************************************************

;	  .:::::.
;	 ¦:::·:::¦
;	 |· - - ·|
;	C|  O p  l)
;	/ _ (_) _ \
;	\_\_____/_/
;	 l_\___/_!
;	  `-----'xCz

;14	INTEN	6 ($78)
;13	EXTER	6 ($78)	Interrupt extern, an die Leitung angeschlossen INT6 + TOD CIAB

NoInt6: ; $78
	movem.l	d0-d7/a0-a6,-(sp)
	tst.b	$bfdd00				; CIAB ICR - Reset interrupt timer
	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; ist Bit Master Reset aktiviert?
	beq.s	NoInts6				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.
	btst.l	#14,d1				; INTREQR - INTEN?
	beq.w	NoInten
	; Routine inten
NoInten:
	btst.l	#13,d1				; INTREQR - EXTER?
	beq.w	NoExter
	; Routine exter
NoExter:
NoInts6:	; 432109876543210
	move.w	#%110000000000000,$dff09c ; INTREQ - external int + ciab
	movem.l	(sp)+,d0-d7/a0-a6
	rte

*****************************************************************************
;	Wiederholungsroutine protracker/soundtracker/noisetracker
;
	include	"/Sources/music.s"
*****************************************************************************

	SECTION	GRAPHIC,DATA_C

Copperlist:
	dc.w	$100,$200			; BPLCON0 - no Bitplanes
	dc.w	$180,$00e			; COLOR00 blau
	dc.w	$a007,$fffe			; WAIT - warte auf Zeile $a0
	dc.w	$9c,$8010			; INTREQ - Fordere einen COPER-Interrupt an,
								; wodurch COLOR00 mit einem "move.w" geändert wird.
	dc.w	$ffff,$fffe			; Ende Copperlist

*****************************************************************************
;				MUSIK
*****************************************************************************

mt_data:
	dc.l	mt_data1

mt_data1:
	incbin	"/Sources/mod.yellowcandy"

	end

Wie Sie sehen, verwenden wir in dieser "Version" alle Tricks, die die
Betriebssystem-Interrupts verwenden:

	lea	$dff000,a0				; custom in a0
	move.w	$1c(a0),d1			; INTENAR in d1
	btst.l	#14,d1				; ist Bit Master Reset aktiviert?
	beq.s	NoInts1				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a0),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.
	btst.l	#0,d1				; TBE?
	...

In der Praxis wird eine weitere Überprüfung der Interrupt-Gültigkeit gemacht.
Es wird geprüft, ob das in INTREQR gesetzte Bit auch in INTENAR gesetzt ist, dh
ob es aktiviert ist. Eigentlich, wenn Sie einen Interrupt mit dem Register 
INTENA ($dff09a) deaktivieren, sollte es nicht weiter funktionieren. Es kann
jedoch sein, dass die Hardware nicht perfekt ist. Wenn Sie seltsame 
Inkompatibilitäten in ihren Interrupts finden, überprüfen Sie dies auch, wer 
weiß ob "deaktivierte" Interrupts nicht doch ausgeführt werden!
