
; Listing8a.s - Das universelle Startup, um DMA-Kanäle zu studieren

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

			;5432109876543210
DMASET	equ	%1000001110000000	; Copper- und Bitplane-DMA aktiviert
;			 -----a-bcdefghij

;	a: Blitter Nasty   (Im Moment ist es uns egal, lassen wir es auf Null)
;	b: Bitplane DMA	   (Wenn es nicht gesetzt ist, verschwinden auch die Sprites)
;	c: Copper DMA	   (Auch die Copperliste wird nicht auf Null zurückgesetzt)
;	d: Blitter DMA	   (Im Moment sind wir nicht interessiert)
;	e: Sprite DMA	   (Nur die 8 Sprites verschwinden)
;	f: Disk DMA		   (Im Moment sind wir nicht interessiert)
;	g-j: Audio 3-0 DMA (Wir setzen den Amiga auf Null zurück)

******************************************************************************
;    680X0 & AGA StartUP BY FABIO CIUCCI - Komplexitätsgrad 1
******************************************************************************

Maincode:
	movem.l	d0-d7/a0-a6,-(sp)	; speichern der Register auf dem stack
	move.l	4.w,a6				; ExecBase in a6
	lea	GfxName(pc),a1			; Name der zu öffnenden Bibliothek
	jsr	-$198(a6)				; OldOpenLibrary - öffne die Bibliothek
	move.l	d0,GfxBase			; speichern der GfxBase in einem Label
	beq.w	Exit2				; wenn ja, beenden wir das Programm, ohne den
								; Code auszuführen
	lea	IntuiName(pc),a1		; Intuition.lib
	jsr	-$198(a6)				; Openlib
	move.l	d0,IntuiBase
	beq.w	Exit1				; Wenn Null, geh raus! Fehler!

	move.l	IntuiBase(pc),a0
	cmp.w	#39,$14(a0)			; Version 39 oder größer? (kick3.0+)
	blt.s	VecchiaIntui		; alte Intui
	bsr.w	ResettaSpritesV39

VecchiaIntui:
	move.l	GfxBase(pc),a6
	move.l	$22(a6),WBView		; speichern des aktuellen System WBView

	suba.l	a1,a1				; View null, um den Videomodus zurückzusetzen
	jsr	-$de(a6)				; LoadView Null - Videomodus zurücksetzen
	suba.l	a1,a1				; View null
	jsr	-$de(a6)				; LoadView (zweimal zur Sicherheit...)
	jsr	-$10e(a6)				; WaitOf (Diese beiden Aufrufe von WaitOf)
	jsr	-$10e(a6)				; WaitOf (werden verwendet, um das Interlace
	jsr	-$10e(a6)				; zurückzusetzen) Noch zwei, vah!
	jsr	-$10e(a6)

	movea.l	4.w,a6
	suba.l	a1,a1				; NULL task - finde den Task
	jsr	-$126(a6)				; findtask (d0=task, FindTask(name) in a1)
	movea.l	d0,a1				; Task in a1
	moveq	#127,d0				; Priorität in d0 (-128, +127) - MAXIMUM!
	jsr	-$12c(a6)				; _LVOSetTaskPri (d0=Priorität, a1=task)

	move.l	GfxBase(pc),a6
	jsr	-$1c8(a6)				; OwnBlitter, gibt uns den exklusiven Zugang auf den Blitter
								; verhindert, dass er vom Betriebssystem verwendet wird.
	jsr	-$e4(a6)				; WaitBlit - warten auf das Ende eines Blitts
	jsr	-$e4(a6)				; WaitBlit

	move.l	4.w,a6				; ExecBase in a6
	jsr	-$84(a6)				; FORBID -  Multitasking deaktivieren
	jsr	-$78(a6)				; DISABLE - deaktiviert auch die Interrupts
								; des Betriebssystems

	bsr.w	HeavyInit			; Jetzt können Sie den Teil ausführen, der 
								; auf den Hardware-Registern arbeitet

	move.l	4.w,a6				; ExecBase in a6
	jsr	-$7e(a6)				; ENABLE - ermöglicht System Interrupts
	jsr	-$8a(a6)				; PERMIT - ermöglicht Multitasking

	suba.l	a1,a1				; NULL task - finde den Task
	jsr	-$126(a6)				; findtask (d0=task, FindTask(name) in a1)
	movea.l	d0,a1				; Task in a1
	moveq	#0,d0				; Priorität in d0 (-128, +127) - NORMAL
	jsr	-$12c(a6)				; _LVOSetTaskPri (d0=Priorität', a1=task)

	move.w	#$8040,$dff096		; blitt ermöglichen
	btst.b	#6,$dff002			; WaitBlit...
Wblittez:
	btst.b	#6,$dff002
	bne.s	Wblittez

	move.l	GfxBase(pc),a6		; GfxBase in a6
	jsr	-$e4(a6)				; WaitBlit - warten auf das Ende eines Blitts
	jsr	-$e4(a6)				; WaitBlit
	jsr	-$1ce(a6)				; DisOwnBlitter, das Betriebssystem 
								; kann den Blitter jetzt wieder verwenden
	move.l	IntuiBase(pc),a0
	cmp.w	#39,$14(a0)			; V39+?
	blt.s	Vecchissima
	bsr.w	RimettiSprites

Vecchissima:
	move.l	GfxBase(pc),a6		; GfxBase in a6
	move.l	$26(a6),$dff080		; COP1LC - Zeiger auf das alte System "Copper1"
	move.l	$32(a6),$dff084		; COP2LC - Zeiger auf das alte System "Copper2"
	jsr	-$10e(a6)				; WaitOf (setzt Interlace zurück)
	jsr	-$10e(a6)				; WaitOf
	move.l	WBView(pc),a1		; alten WBView in a1
	jsr	-$de(a6)				; loadview - den alten View zurücksetzen
	jsr	-$10e(a6)				; WaitOf (setzt Interlace zurück)
	jsr	-$10e(a6)				; WaitOf
	move.w	#$11,$dff10C		; Dies stellt es nicht von selbst wieder her ..!
	move.l	$26(a6),$dff080		; COP1LC - Zeiger auf das alte System "Copper1"
	move.l	$32(a6),$dff084		; COP2LC - Zeiger auf das alte System "Copper2"
	moveq	#100,d7

RipuntLoop:
	move.l	$26(a6),$dff080		; COP1LC - Zeiger auf das alte System "Copper1"
	move.w	d0,$dff088
	dbra	d7,RipuntLoop		; zur Sicherheit...

	movea.l	IntuiBase(pc),a6
	jsr	-$186(a6)				; _LVORethinkDisplay - zeichnet alles neu
								; Displays, einschließlich ViewPorts und alle
								; Interlace- oder Multisync-Modi.
	move.l	a6,a1				; IntuiBase in a1 um die Bibliothek zu schließen
	move.l	4.w,a6				; ExecBase in a6
	jsr	-$19e(a6)				; CloseLibrary - intuition.library GESCHLOSSEN
Exit1:
	move.l	GfxBase(pc),a1		; GfxBase in a1 um die Bibliothek zu schließen
	jsr	-$19e(a6)				; CloseLibrary - graphics.library GESCHLOSSEN
Exit2:
	movem.l	(sp)+,d0-d7/a0-a6	; die alten Registerwerte wiederherstellen
	rts							; zu ASMONE oder Dos / WorkBench zurückkehren

*******************************************************************************
;	Sprite-Auflösung "legal" zurücksetzen
*******************************************************************************

ResettaSpritesV39:
	lea	Workbench(pc),a0		; Bildschirmname von Workbench in a0
	move.l	IntuiBase(pc),a6
	jsr	-$1fe(a6)				; _LVOLockPubScreen - Wir "blockieren" den Bildschirm
								; (dessen Name in a0 steht).
	move.l	d0,SchermoWBLocckato
	beq.s	ErroreSchermo
	move.l	d0,a0				; Struktur Screen in a0
	move.l	$30(a0),a0			; sc_ViewPort + vp_ColorMap: in a0 haben wir jetzt
								; die ColorMap-Struktur des Bildschirms, die dient
								; (in a0) zur Durchführung einer "video_control"
								; von graphics.library.
	lea	GETVidCtrlTags(pc),a1	; In a1 die TagList für die Routine
								; "Video_control" - die Anforderung, dass
								; Lassen Sie uns diese Routine zu tun ist
								; VTAG_SPRITERESN_GET oder zu wissen
								; die aktuelle Sprite-Auflösung.
	move.l	GfxBase(pc),a6
	jsr	-$2c4(a6)				; Video_Control (in a0 die cm und in a1 die tags)
								; Berichte in der Tagliste, in der langen
								; "resolution", die aktuelle Auflösung des
								; Sprite in diesem Bildschirm.

; Lassen Sie uns nun durch die VideoControl-Routine, die Auflösung einstellen.
; SPRITERESN_140ns -> dh lowres!

	move.l	SchermoWBLocckato(pc),a0
	move.l	$30(a0),a0			; Struktur sc_ViewPort+vp_ColorMap in a0
	lea	SETVidCtrlTags(pc),a1	; TagList, das setzt die Sprites zurück.
	move.l	GfxBase(pc),a6
	jsr	-$2c4(a6)				; video_control... die Sprites zurücksetzen!

; Jetzt setzen wir auch den möglichen "Vordergrund" -Bildschirm zurück, zum
; Beispiel den Assembler-Bildschirm:

	move.l	IntuiBase(pc),a6
	move.l	$3c(a6),a0			; Ib_FirstScreen (Großaufnahme!")
	move.l	$30(a0),a0			; Struktur sc_ViewPort+vp_ColorMap in a0
	lea	GETVidCtrlTags2(pc),a1	; In a1 die TagList GET
	move.l	GfxBase(pc),a6
	jsr	-$2c4(a6)				; Video_Control (in a0 die cm und in a1 die tags)

	movea.l	IntuiBase(pc),a6
	move.l	$3c(a6),a0			; Ib_FirstScreen -"angeln" den Bildschirm ein
								; Vordergrund (zB ASMONE)
	movea.l	$30(a0),a0			; Struktur sc_ViewPort+vp_ColorMap in a0
	lea	SETVidCtrlTags(pc),a1	; TagList Das setzt die Sprites zurück.
	movea.l	GfxBase(pc),a6
	jsr	-$2c4(a6)				; video_control... Sprites zurücksetzen!

	movea.l	SchermoWBLocckato(pc),a0
	movea.l	IntuiBase(pc),a6
	jsr	-$17a(a6)				; _LVOMakeScreen - müssen den Bildschirm wiederholen
	move.l	$3c(a6),a0			; Ib_FirstScreen - "angeln" den Bildschirm ein
								; Vordergrund (zB ASMONE)
	jsr	-$17a(a6)				; _LVOMakeScreen - müssen den Bildschirm wiederholen
								; um sicher zu gehen, dass das zurückgesetzt wurde, ist es notwendig
								; Rufen Sie MakeScreen auf, gefolgt von...
	jsr	-$186(a6)				; _LVORethinkDisplay - was das ganze neu gestaltet
								; Displays, einschließlich ViewPorts und alle
ErroreSchermo:					; Interlace- oder Multisync-Modus.
	rts

; Jetzt müssen wir die Sprites auf die Startauflösung zurücksetzen.

RimettiSprites:
	move.l	SchermoWBLocckato(pc),d0	; Adresse Struktur Screen
	beq.s	NonAvevaFunzionato			; wenn = 0, dann sünde...
	move.l	d0,a0
	move.l	OldRisoluzione(pc),OldRisoluzione2 ; Alte Auflösung zurücksetzen
	lea	SETOldVidCtrlTags(pc),a1
	move.l	$30(a0),a0			; Struktur ColorMap des Bildschirms
	move.l	GfxBase(pc),a6
	jsr	-$2c4(a6)				; _LVOVideoControl - Auflösung auflösen

; Bildschirmzeit im Vordergrund (falls vorhanden)...

	move.l	IntuiBase(pc),a6
	move.l	$3c(a6),a0			; Ib_FirstScreen - "angeln" den Bildschirm ein
								; Vordergrund (zB ASMONE)
	move.l	OldRisoluzioneP(pc),OldRisoluzione2 ; Alte Auflösung zurücksetzen.
	lea	SETOldVidCtrlTags(pc),a1
	move.l	$30(a0),a0			; Struktur ColorMap des Bildschirms
	move.l	GfxBase(pc),a6
	jsr	-$2c4(a6)				; _LVOVideoControl - Auflösung auflösen

	movea.l	SchermoWBLocckato(pc),a0
	movea.l	IntuiBase(pc),a6
	jsr	-$17a(a6)				; RethinkDisplay - wir "überdenken" die Anzeige
	move.l	$3c(a6),a0			; Ib_FirstScreen - Bildschirm im Vordergrund
	jsr	-$17a(a6)				; RethinkDisplay - wir "überdenken" die Anzeige
	move.l	SchermoWBLocckato(pc),a1
	SUB.L	a0,a0				; null
	movea.l	IntuiBase(pc),a6
	jsr	-$204(a6)				; _LVOUnlockPubScreen - und "entsperren"
NonAvevaFunzionato:				; screen Workbench.
	rts

SchermoWBLocckato:
	dc.l	0

; Dies ist die Struktur zur Verwendung von Video_Control. Das erste long ist zum
; ÄNDERN (SET) der Auflösung der Sprites oder Sie möchten die alte Auflösung 
; kennen (GET).

GETVidCtrlTags:
	dc.l	$80000032	; GET
OldRisoluzione:
	dc.l	0			; Auflösung sprite: 0=ECS, 1=lowres, 2=hires, 3=shres
	dc.l	0,0,0		; 3 Nullen für TAG_DONE (Beenden der TagList)

GETVidCtrlTags2:
	dc.l	$80000032	; GET
OldRisoluzioneP:
	dc.l	0			; Auflösung sprite: 0=ECS, 1=lowres, 2=hires, 3=shres
	dc.l	0,0,0		; 3 Nullen für TAG_DONE (Beenden der TagList)

SETVidCtrlTags:
	dc.l	$80000031	; SET
	dc.l	1			; Auflösung sprite: 0=ECS, 1=lowres, 2=hires, 3=shres
	dc.l	0,0,0		; 3 Nullen für TAG_DONE (Beenden der TagList)

SETOldVidCtrlTags:
	dc.l	$80000031	; SET
OldRisoluzione2:
	dc.l	0			; Auflösung sprite: 0=ECS, 1=lowres, 2=hires, 3=shres
	dc.l	0,0,0		; 3 Nullen für TAG_DONE (Beenden der TagList)

; WorkBench-Bildschirmname

Workbench:
	dc.b	'Workbench',0

******************************************************************************
;	Ab hier können Sie direkt auf der Hardware arbeiten
******************************************************************************

HeavyInit:
	lea	$dff000,a5				; Basis der CUSTOM-Register für Offsets
	move.w	$2(a5),OLDDMA		; alten Status von DMACONR speichern
	move.w	$1c(a5),OLDINTENA	; alten Status von INTENA speichern
	move.w	$10(a5),OLDADKCON	; alten Status von ADKCON speichern
	move.w	$1e(a5),OLDINTREQ	; alten Status von INTREQ speichern
	move.l	#$80008000,d0		; die High-Bit-Maske vorbereiten
								; zum Setzen der Bits die in den
								; Worten gespeichert wurden 
	or.l	d0,OLDDMA			; Bit 15 aller gespeicherten Werte setzen
	or.l	d0,OLDADKCON		; der Hardware-Register,  unverzichtbar für
								; das zurücksetzen dieser Werte in die Register.

	move.l	#$7fff7fff,$9a(a5)	; deaktiviert INTERRUPTS & INTREQS
	move.l	#0,$144(a5)			; SPR0DAT - Nullzeiger!
	move.w	#$7fff,$96(a5)		; deaktiviert alle DMA

	bsr.s	Start				; das Programm ausführen

	lea	$dff000,a5				; Basis von CUSTOM-Registern für Offsets
	move.w	#$7fff,$96(a5)		; deaktiviert alle DMA
	move.l	#$7fff7fff,$9a(a5)	; deaktiviertT INTERRUPTS & INTREQS
	move.w	#$7fff,$9e(a5)		; deaktiviert die Bits von ADKCON
	move.w	OLDADKCON(pc),$9e(a5)	; ADKCON 
	move.w	OLDDMA(pc),$96(a5)		; den alten DMA-Status zurücksetzen
	move.w	OLDINTENA(pc),$9a(a5)	; INTENA STATUS
	move.w	OLDINTREQ(pc),$9c(a5)	; INTREQ
	rts

;	Beim Start gespeicherte Daten

WBView:							; WorkBench View-Adresse
	dc.l	0
GfxName:
	dc.b	'graphics.library',0,0
IntuiName:
	dc.b	'intuition.library',0

GfxBase:						; Zeiger auf die Basis der Graphics Library
	dc.l	0
IntuiBase:						; Zeiger auf die Basis der Intuition Library
	dc.l	0
OLDDMA:							; alter Status DMACON
	dc.w	0
OLDINTENA:						; alter Status INTENA
	dc.w	0
OLDADKCON:						; alter Status ADKCON
	dc.w	0
OLDINTREQ:						; alter Status INTREQ
	dc.w	0

Start:
	move.l	#Bitplane,d0		; Adresse der Bitplane
	lea	Bplpointers,a1			; Bitplanepointer in der Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

	move.w	#DMASET,$96(a5)		; DMACON - aktivieren Bitplane und 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"

Mouse:
	btst	#6,$bfe001			; linke Maustaste gedrückt?
	bne.s	Mouse
	rts							; exit


	SECTION	CopProva,DATA_C

Copperlist:
	dc.w	$8e,$2c81			; DIWSTRT
	dc.w	$90,$2cc1			; DIWSTOP
	dc.w	$92,$0038			; DDFSTRT
	dc.w	$94,$00d0			; DDFSTOP
	dc.w	$102,0				; BPLCON1
	dc.w	$104,0				; BPLCON2
	dc.w	$108,0				; BPL1MOD
	dc.w	$10a,0				; BPL2MOD
				; 5432109876543210
	dc.w	$100,%0001001000000000	; 1 Bitplane LOWRES 320x256

Bplpointers:
	dc.w	$e0,0,$e2,0			; erste Bitplane

	dc.w	$0180,$000			; COLOR00 - Hintergrund
	dc.w	$0182,$19a			; COLOR01 - Schrift

;	Gradient Copperlist

	dc.w	$5007,$fffe			; WAIT Zeile $50
	dc.w	$180,$001			; COLOR00
	dc.w	$5207,$fffe			; WAIT Zeile $52
	dc.w	$180,$002			; COLOR00
	dc.w	$5407,$fffe			; WAIT Zeile $54
	dc.w	$180,$003			; COLOR00
	dc.w	$5607,$fffe			; WAIT Zeile $56
	dc.w	$180,$004			; COLOR00
	dc.w	$5807,$fffe			; WAIT Zeile $58
	dc.w	$180,$005			; COLOR00
	dc.w	$5a07,$fffe			; WAIT Zeile $5a
	dc.w	$180,$006			; COLOR00
	dc.w	$5c07,$fffe			; WAIT Zeile $5c
	dc.w	$180,$007			; COLOR00
	dc.w	$5e07,$fffe			; WAIT Zeile $5e
	dc.w	$180,$008			; COLOR00
	dc.w	$6007,$fffe			; WAIT Zeile $60
	dc.w	$180,$009			; COLOR00
	dc.w	$6207,$fffe			; WAIT Zeile $62
	dc.w	$180,$00a			; COLOR00

	dc.w	$ffff,$fffe			; Ende Copperlist

;	Mit dem Befehl dcb erstellen wir eine zufällige Zeichnung in der Bitebene

Bitplane:
	dcb.l	10240/4,$ff00ff00

	end

Es gibt zwei Details, die in der Lektion nicht enthalten sind: Das erste ist, 
dass es eine Routine gibt, die den Videomodus der Sprits zurücksetzt, falls
KickStart Version 3.0 oder höher ist.
Das zweite Detail ist, dass eine Anweisung hinzugefügt wurde, um AGA zu
deaktivieren:

	move.w	#$11,$10c(a5)		; AGA "deaktivieren"

In Wirklichkeit ist diese Anweisung meist überflüssig, weil es so gut wie nie
vorhanden ist, aber auch hier sollte die Sicherheit nicht vernachlässigt
werden.

Schalten Sie die Bitmap- und Copper-DMA-Kanäle nacheinander aus. Sie werden
feststellen, dass das Balkenmuster verschwindet, wenn der Bitplane-Kanal 
ausgeschaltet wird. Wenn Sie Copper deaktivieren, wird auch der Schatten
ausgeblendet. Versuchen Sie auch, Bit 9, den allgemeinen Schalter,
auszuschalten, und Sie werden sehen dass, auch wenn die anderen Bits aktiviert
sind, alles ausgeschaltet wird.
Der Versuch, Bit 15 zurückzusetzen, ist sinnlos!