
; Listing11o3.s		Laden einer Datendatei mit der dos.library
; Anmerkung: Die Länge der Datei muss nicht bekannt sein!
; Drücken Sie die linke Taste zum Laden, die rechte zum Verlassen

	SECTION DOSLOAD,CODE

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

*****************************************************************************
	include	"/Sources/startup2.s"	; speichern interrupt, dma etc.
*****************************************************************************

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

			;5432109876543210
DMASET	equ	%1000001110000000	; Copper, Bitplane DMA aktivieren

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

Start:
	move.l	#Picture,d0
	lea	Bplpointers2,a1
	moveq	#5-1,d1				; Anzahl der Bitplanes
PointBp:
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0
	add.l	#34*40,d0			; Länge der Bitplane
	addq.w	#8,a1
	dbra	d1,PointBp			; mach das d1 mal (d1=Anzahl der Bitplanes)

; wie zeigen auf einen leeren Puffer, der immer leer bleibt..

	move.l	#Logo+40*40,d0		; Adresse logo (etwas abgesenkt)
	lea	Bplpointers,a0
	moveq	#6-1,d7				; 6 Bitplanes HAM.
BpLoop:
	move.w	d0,6(a0)
	swap	d0
	move.w	d0,2(a0)
	swap	d0
	addq.w	#8,a0
	add.l	#176*40,d0			; Länge Bitplane
	dbra	d7,BpLoop
	
; Wir zeigen auf unseren Level 3 Int

	move.l	BaseVBR(pc),a0	     ; in a0 ist der Wert des VBR
	move.l	OldInt6c(pc),CrappyInt	; für DOS LOAD - wir springen zum oldint
	move.l	#MyInt6c,$6c(a0)	; meine Routine Int. Level 3 anlegen

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

	move.w	#$c020,$9a(a5)		; INTENA - aktivieren interrupt "VERTB"
								; per Level 3 ($6c)

Mouse:
	btst	#6,$bfe001			; Maus gedrückt? (Der Prozessor 
	bne.s	Mouse				; unterbricht die Schleife zu jedem vertical blank
								; um die Musik zu spielen!) 

	lea	FileName1(pc),a0 		; Name der hochzuladenden Datei
	lea	BufFile1(pc),a1			; Label in welchem die Adresse der Datei
								; die in den Speicher geladen wurde gespeichert wird
	lea	Size1(pc),a2			; Label in welchem die Größe gespeichert ist
	moveq	#2,d0				; Art von Speicher Ziel.: CHIP RAM!	
	bsr.w	DosLoad2			; Laden Sie eine Datei mit dos.lib hoch
								; während wir unsere eigene Copperliste ansehen
								; und unser Interrupt läuft.
								; Zuerst definieren "TypeOfMem", mit "2" für CHIP
								; oder "1" für PUBLIC, und die anderen Parameter.
	tst.b	d1					; Haben wir Speicher zur freien Verfügung gestellt?
	beq.s	NoFreeMem			; d1=0, dann nicht zugeordnet
	st.b	FreeMem1			; wenn ja, dann FreeMem1
NoFreeMem
	tst.l	d0					; Auf Fehler prüfen...
	bne.s	ErrorLoad			; Datei nicht geladen? Dann lass es uns nicht benutzen!
								; d0=0, dann ist alles in Ordnung

; wir zeigen nun auf die geladene Figur:

	lea	Bplpointers,a0
	move.l	BufFile1(pc),d0		; Adresse der hochgeladenen Datei
	add.l	#40*40,d0			; Logo etwas abgesenkt (zentrieren ...)
	moveq	#6-1,d7				; 6 Bitplanes HAM.
PointLoop2:
	move.w	d0,6(a0)
	swap	d0
	move.w	d0,2(a0)
	swap	d0
	addq.w	#8,a0
	add.l	#176*40,d0			; Länge Bitplane
	dbra	d7,PointLoop2

ErrorLoad:
Mouse2:
	btst	#2,$dff016			; Maus gedrückt? (Der Prozessor macht den
	bne.s	Mouse2				; Loop)

	bsr.w	mt_end				; Ende der Wiederholung!

; Denken Sie immer daran, den gesamten Speicher freizugeben!
; Aber auch, das FreeMem nicht aufzurufen, wenn wir nicht wirklich Speicher zugewiesen 
; haben, das ist eine Super-Guru-Meditation - Softwarefehler - verschiedene Probleme.

	tst.b	FreeMem1			; Gab es einen Fehler vor dem AllocMem?
	beq.s	NotAllocated1		; wenn ja, mach das nicht FreeMem!

	move.l	Size1(pc),d0		; Größe des Blocks in bytes
	move.l	BufFile1(pc),a1		; Adresse des zugewiesenen Speicherblocks
	move.l	4.w,a6
	jsr	-$d2(a6)				; FreeMem
NotAllocated1:
	rts							; Exit


; Variablen, in denen wir die Dateigröße und Adresse gespeichert haben
; verwenden und am Ende freigeben

BufFile1:
	dc.l	0
Size1:
	dc.l	0
FreeMem1:
	dc.l	0

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

MyInt6c:
	btst.b	#5,$dff01f			; INTREQR - Bit 5, ist VERTB zurückgesetzt?
	beq.s	NoIntVertb			; Wenn ja, ist es kein "echter" VERTB Interrupt!
	movem.l	d0-d7/a0-a6,-(sp)	; Register auf dem stack speichern
	bsr.w	mt_music			; Musik spielen
	bsr.w	ColorCycle			; Wechseln der Farben des Bildes
	movem.l	(sp)+,d0-d7/a0-a6	; Register vom stack wiederherstellen
NoIntVertb:
	move.w	#$20,$dff09c		; INTREQ - Löschen Flag BLIT,VERTB,COPER
								; da der 680x0 es nicht von selbst löscht!!!
	rte							; Ende vom Interrupt VERTB

*****************************************************************************
*	Routine, die die Farben der gesamten Palette "wechselt".		     *
*	Diese Routine wechselt die ersten 15 Farben getrennt vom			 *
*   zweiten Farbblock. Es funktioniert wie das "RANGE" des Dpaint.       *
*****************************************************************************

;  Der "Counter" -Zähler wird verwendet, um 3 Frames vorher warten zu lassen
;  Laufroutine fortsetzen In der Praxis "verlangsamen" die Ausführung. 

Counter:
	dc.w	0

ColorCycle:
	addq.b	#1,Counter
	cmp.b	#3,Counter				; Handle nur einmal alle 3 Frames
	bne.s	NotYet			; sind wir noch nicht auf dem dritten Platz? Exit!
	clr.b	Counter				; wir sind am dritten, setzen Sie den Zähler zurück

; Rückwärtsrotation der ersten 15 Farben

	lea	Cols+2,a0				; Erste Farbadresse der ersten Gruppe
	move.w	(a0),d0				; Speichern der ersten Farbe in d0
	moveq	#15-1,d7			; 15 Farben zum "Drehen" in der ersten Gruppe
Cloop1:
	move.w	4(a0),(a0)			; Kopieren Sie die Farbe vorwärts in die erste
	addq.w	#4,a0				; springe zur nächsten Spalte "zurück"
	dbra	d7,Cloop1			; wiederhole d7 mal
	move.w	d0,(a0)				; Ordne die erste als letzte gespeicherte Farbe an

; Vorwärtsrotation der zweiten 15 Farben

	lea	Cole-2,a0				; Erste Farbadresse der zweiten Gruppe
	move.w	(a0),d0				; Speichern der ersten Farbe in d0
	moveq	#15-1,d7			; Weitere 15 Farben, die separat "gedreht" werden können
Cloop2:	
	move.w	-4(a0),(a0)			; Kopieren Sie die Farbe zurück zum nächsten
	subq.w	#4,a0				; zur vorherigen Spalte springen "vorrücken"
	dbra	d7,Cloop2			; wiederhole d7 mal
	move.w	d0,(a0)				; Ordne die erste als letzte gespeicherte Farbe an
NotYet:
	rts

*****************************************************************************
; Routine, die eine Datei lädt, während wir ins Metall schlagen.
;
; Eingehende Parameter:
;
; a0	= Adresse des Strings mit dem Namen der zu ladenden Datei
; a1	= Label Adresse (.L), unter der die Adresse der Datei gespeichert werden soll
; a2	= Label Adresse (.L), um die Länge der Datei zu speichern
;
; Ausgehende Parameter:
;
; d0.l	= wenn = 0, kein Problem, wenn = -1 gab es einen Fehler
; d1.b	= wenn = 0 wir haben AllocMem nicht ausgeführt,
;	      wenn = 1, müssen wir FreeMem ausführen!
*****************************************************************************

DosLoad2:
	movem.l	d2-d7/a3-a6,-(sp)
	move.l	a0,FileName 		; Name der hochzuladenden Datei
	move.l	a1,DestLoad			; Label in welchem die Adresse gespeichert wird
	move.l	a2,SaveSize			; Label in welchem die Dateigröße gespeichert wird
	move.l	d0,TypeOfMem		; Typ Speicher Ziel: CHIP RAM!	
	bsr.w	PrepareLoad			; Stellen Sie das Multitasking wieder her und 
								; stellen Sie das Interrupt-Load ein
	moveq	#5,d1				; Anzahl der zu wartenden Frames
	bsr.w	WaitBlanks			; warte 5 frames

	bsr.s	LoadFile2			; Laden Sie die Datei mit der dos.library von
								; jeder "unbekannten" Länge.
	move.l	d0,ErrorFlag		; Speichern Sie den Erfolgs- oder Fehlerstatus

; Bemerkung: Jetzt müssen wir auf den Laufwerksmotor warten
; Eine schlechte Festplatte oder CD-ROM wird heruntergefahren, bevor alles sperrt 
; oder es wird ein spektakulärer Systemabsturz verursacht.

	move.w	#150,d1				; Anzahl der zu wartenden Frames
	bsr.w	WaitBlanks			; warte 150 frames

	bsr.w	AfterLoad			; Deaktivieren Sie Multitasking und setzen Sie Interrupts zurück
	move.l	ErrorFlag(pc),d0	; Setzen Sie das Fehler- / Erfolgskennzeichen
	moveq	#0,d1
	move.b	FreeMemFlag(pc),d1	; setze den freemem marker dazu
	clr.b	FreeMemFlag			; setzen Sie es für das nächste zurück (nicht zugewiesen)
	movem.l	(sp)+,d2-d7/a3-a6
	rts

ErrorFlag:
	dc.l	0

*****************************************************************************
; Eine Routine, die eine Datei beliebiger "unbekannter" Länge in den
; CHIP- oder PUBLIC-Speicherpuffer, der mit AllocMem zugewiesen wurde, lädt.
; Definieren Sie zuerst "TypeOfMem" mit "2" für CHIP RAM oder "1" für PUBLIC.
; Beim Beenden ist d0 = 0, wenn dies erfolgreich war, 
; oder -1, wenn Probleme aufgetreten sind
*****************************************************************************

;        ''~``
;       ( o o )
;+-.oooO--(_)--Oooo.---------------------------------------------------------+
;|									     |
;|   Oooo          Tut mir leid, wenn die Routine etwas zu durcheinander ist    |
;|   (   )   Oooo.                         				     |
;+----\ (----(   )-----------------------------------------------------------+
;      \_)    ) /
;            (_/

LoadFile2:
	move.l	FileName(pc),d1		; Adresse mit String "file name + path"
	move.l	#$3ed,d2			; AccessMode: MODE_OLDFILE - Datei, die existiert
								; ja und so können wir lesen.
	move.l	DosBase(pc),a6
	jsr	-$1e(a6)				; LVOOpen - "Öffnen" Sie die Datei
	move.l	d0,FileHandle		; Speichern Sie das Handle
	beq.w	ErrorOpen			; wenn d0 = 0 dann liegt ein Fehler vor!

; Lassen Sie uns nun die Datei sperren, um dann die Prüfung durchführen zu können

	move.l	FileName(pc),d1		; Name der Datei
	moveq	#-2,d2				; AccessMode = ACCESS_READ
	jsr	-$54(a6)				; Sperren Sie die Datei
	move.l	d0,FileLock			; Wir speichern den Zeiger auf die Dateisperre
	beq.w	ErrorLock			; d0 = 0? dann Fehler!

; Wir reservieren Speicher für Examines FileInfoBlock ()

	move.l	#$104,d0			; Größe des Blocks in bytes
	move.l	#1,d1				; Typ Speicher: public
	move.l	4.w,a6
	jsr	-$c6(a6)				; Allocmem
	move.l	d0,FibAdr			; Startadresse des zugeordneten Speicherblocks
	beq.s	ErrorAlFib			; d0=0? dann Fehler!

; Untersuchen wir nun die Datei, um ihre Länge zu ermitteln

	move.l	FileLock(pc),d1		; lock ptr in d1 zu untersuchen
	move.l	FibAdr(pc),d2		; File Info Block zu untersuchen
	move.l	DosBase(pc),a6
	jsr	-$66(a6)				; überprüfen Sie, welcher den Fib-Puffer füllt ($104 byte)
								; Infos der Datei (Name, dir/file, size, date)
	tst.l	d0					; Probleme mit der Prüfung?
	beq.s	ErrorExamine
	move.l	FibAdr(pc),a0
	move.l	$7c(a0),d3			; offset Größe (Länge)
	move.l	d3,SizeFile

; Jetzt können wir auch den für FileInfoBlock verwendeten Speicher freigeben

	bsr.w	LiberaFib

; Wir reservieren Speicher für die Datei

	move.l	SizeFile(pc),d0		; Größe des Blocks in bytes
	move.l	TypeOfMem(pc),d1	; Typ Speicher
	move.l	4.w,a6
	jsr	-$c6(a6)				; Allocmem
	move.l	d0,FileAdr			; Startadresse des zugeordneten Speicherblocks 
	beq.s	ErrorAllFile		; d0=0? dann Fehler!

; Wir machen eine Kopie der Datei-Adresse für uns und den Freemem

	move.l	DestLoad(pc),a0
	move.l	d0,(a0)
	move.l	SaveSize(pc),a0	; und auch die Länge speichern
	move.l	SizeFile(pc),(a0)

	st.b	FreeMemFlag			; Denken wir daran, das Freemem zu machen

; Wir laden die Datei in den zugewiesenen Speicherblock:

	move.l	FileHandle(pc),d1; FileHandle in d1 für das Lesen
	move.l	FileAdr(pc),d2		; Adresse Ziel in d2
	move.l	SizeFile(pc),d3		; Länge des file (genau!)
	move.l	DosBase(pc),a6
	jsr	-$2a(a6)				; LVORead - Lesen Sie die Datei und kopieren Sie sie in den Puffer
	cmp.l	#-1,d0				; Fehler gefunden? (hier ist es mit -1 angegeben)
	beq.s	ErrorRead

; Wir entsperren die Datei

	bsr.s	UnlockFile

; Und schließe es

	bsr.s	CloseFile

; Beachten Sie, dass die anderen Programme dies nicht tun, wenn Sie die Datei nicht SCHLIESSEN
; Sie können auf diese Datei zugreifen (Sie können sie nicht löschen oder verschieben).

	moveq	#0,d0				; Gesamterfolg melden!
	rts


; Hier ist die Zusammenstellung möglicher Fehler:


ErrorExamine:
	bsr.s	LiberaFib
ErrorAllFile:
ErrorAlFib:
	bsr.s	UnlockFile
ErrorLock:
	bsr.s	CloseFile
ErrorOpen:
	moveq	#-1,d0				; den Fehler melden
	rts

ErrorRead:
	bsr.s	UnlockFile
	bsr.s	CloseFile
	st.b	FreeMemFlag			; Denken wir daran, das Freemem zu machen
	moveq	#-1,d0				; Melden Sie den Fehler
	rts

; Routineaufrufe aus vielen Teilen:

CloseFile:
	move.l	DosBase(pc),a6
	move.l	FileHandle(pc),d1; FileHandle in d1
	jsr	-$24(a6)				; LVOClose - schließe die Datei
	rts

UnlockFile:
	move.l	DosBase(pc),a6
	move.l	FileLock(pc),d1		; lock ptr in d1 zum Entsperren
	jsr	-$5a(a6)				; Entsperren des file
	rts

LiberaFib:
	move.l	4.w,a6
	move.l	#$104,d0			; Blockgröße in bytes
	move.l	FibAdr(pc),a1		; Adresse des Blocks des zugewiesenen Speichers
	jsr	-$d2(a6)				; FreeMem
	rts

SaveSize:
	dc.l	0
DestLoad:
	dc.l	0
FileHandle:
	dc.l	0
TypeOfMem:
	dc.l	0
FileName:
	dc.l	0
FileLock:
	dc.l	0
FibAdr:
	dc.l	0
SizeFile:
	dc.l	0
FileAdr
	dc.l	0
FreeMemFlag:
	dc.l	0

; Textstring, der mit einer 0 endet, auf die d1 vorher zeigen muss
; Öffnen Sie die Datei dos.lib. Es ist besser, den ganzen Pfad anzugeben.

FileName1:
	dc.b	"/Sources/amiet.raw",0	; Pfad+Name file
	even

*****************************************************************************
; Interruptroutine, die beim Laden ausgeführt werden soll. Die Routine dafür
; wird in diesem Interrupt abgelegt und auch während des 
; Ladens von Diskette, Festplatte oder CD-ROM ausgeführt.
; BITTE BEACHTEN SIE, DASS WIR DEN INTERRUPT COPER UND NICHT DEN VBLANK VERWENDEN
; DIES WEIL WÄHREND DES LADENS VON DER DISKETTE, INSBESONDERE UNTER KICK 1.3,
; DER INTERRUPT VERTB NICHT STABIL IST, so dass die Musik stockt.
; Wenn wir stattdessen "$9c,$8010" in unsere Copperliste setzen, sind wir sicher
; dass diese Routine nur einmal pro Frame ausgeführt wird.
*****************************************************************************

MyInt6cLoad:
	btst.b	#4,$dff01f			; INTREQR - Bit 4, COPER, gelöscht?
	beq.s	NoInt				; Wenn ja, ist es kein "echter" int COPER!
	move.w	#%10000,$dff09c		; Wenn nicht, ist es die richtige Zeit, lasst uns 
	movem.l	d0-d7/a0-a6,-(sp)	; die Anforderung entfernen!
	bsr.w	mt_music			; Musik spielen
	movem.l	(sp)+,d0-d7/a0-a6
NoInt:
	dc.w	$4ef9				; Hexadezimalwert von JMP
CrappyInt:
	dc.l	0	; Adresse, an die gesprungen werden soll, um AUTOMATISIERT zu werden...
				; VORSICHT: der selbstmodifizierende Code sollte
				; nicht verwendet werden. Jedenfalls, mit
				; ClearMyCache vorher und nachher funktioniert es!

*****************************************************************************
; Routine, die das Betriebssystem mit Ausnahme der Copperliste wiederherstellt
; Außerdem setzen Sie unseren $6c-Interrupt, der dann zum System-Interrupt springt.
; Beachten Sie, dass der Interrupt während des Ladevorgangs vom int "COPER" verwaltet wird.
*****************************************************************************

PrepareLoad:
	lea	$dff000,a5				; Basis der CUSTOM-Register für Offset
	move.w	$2(a5),OldDmaL		; Speichern Sie den alten Status von DMACON
	move.w	$1C(a5),OldIntenaL	; Speichern Sie den alten Status von INTENA
	move.w	$1e(a5),OldIntreqL	; Speichern Sie den alten Status von INTREQ
	move.l	#$80008000,d0		; Bereiten Sie die Maske der High-Bits vor
	or.l	d0,OldDmaL			; Bit 15 der gespeicherten Werte setzen
	or.w	d0,OldIntreqL		; der Register, um sie zurückzusetzen.

	bsr.w	ClearMyCache

	move.l	#$7fff7fff,$9a(a5)	; DEAKTIVIEREN SIE INTERRUPTS & INTREQS

	move.l	BaseVBR(pc),a0	     ; in a0 ist der Wert des VBR
	move.l	OldInt64(pc),$64(a0) ; Sys int lev1 speichern (softint,dskblk)
	move.l	OldInt68(pc),$68(a0) ; Sys int lev2 speichern (I/O,ciaa,int2)
	move.l	#MyInt6cLoad,$6c(a0) ; Int was dann zu dem von sys springt. 
	move.l	OldInt70(pc),$70(a0) ; Sys int lev4 speichern (audio)
	move.l	OldInt74(pc),$74(a0) ; Sys int lev5 speichern (rbf,dsksync)
	move.l	OldInt78(pc),$78(a0) ; Sys int l

	move.w	#%1000001001010000,$96(a5) ; Aktivieren Sie aus Sicherheitsgründen "blit" und "disk"
	move.w	OLDINTENA(pc),$9a(a5)	; INTENA STATUS
	move.w	OLDINTREQ(pc),$9c(a5)	; INTREQ
	move.w	#$c010,$9a(a5)		; Wir müssen sicher sein, dass COPER
								; (interrupt über copperlist) ON ist!

	move.l	4.w,a6
	jsr	-$7e(a6)				; Enable
	jsr	-$8a(a6)				; Permit

	move.l	GfxBase(pc),a6
	jsr	-$e4(a6)				; Warten Sie, bis alle blittata verschwunden sind
	jsr	-$e4(a6)				; WaitBlit
	jsr	-$1ce(a6)				; DisOwnBlitter, das Betriebssystem 
								; kann den Blitter jetzt wieder benutzen
								; (In Kick 1.3 wird es zum Laden von der Diskette verwendet.)
	move.l	4.w,a6
	suba.l	a1,a1				; NULL task - finde diese Aufgabe
	jsr	-$126(a6)				; findtask (Task(name) in a1, -> d0=task)
	move.l	d0,a1				; Task in a1
	moveq	#0,d0				; Priorität in d0 (-128, +127) - NORMAL
								; (damit die Laufwerke atmen können)
	jsr	-$12c(a6)				; _LVOSetTaskPri (d0=Priorität, a1=task)
	rts

OldDmaL:
	dc.w	0
OldIntenaL:						; Old status INTENA
	dc.w	0
OldIntreqL:						; Old status INTREQ
	DC.W	0

*****************************************************************************
; Routine, die das Betriebssystem schließt und unseren Interrupt zurücksetzt
*****************************************************************************

AfterLoad:
	move.l	4.w,a6
	suba.l	a1,a1				; NULL task - finde diese Aufgabe
	jsr	-$126(a6)				; findtask (Task(name) in a1, -> d0=task)
	move.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)

	jsr	-$84(a6)				; Forbid
	jsr	-$78(a6)				; Disable

	move.l	GfxBase(pc),a6
	jsr	-$1c8(a6)				; OwnBlitter, das gibt uns exklusiv den Blitter
								; Verhinderung seiner Verwendung durch das Betriebssystem.
	jsr	-$e4(a6)				; WaitBlit - Er wartet auf das Ende jeder blittata
	jsr	-$e4(a6)				; WaitBlit

	bsr.w	ClearMyCache

	lea	$dff000,a5				; Offset für Custom Register
WarteF:
	move.l	4(a5),d0			; VPOSR und VHPOSR - $dff004/$dff006
	and.l	#$1ff00,d0			; wählen Sie nur die Bits der vertikalen Pos.
	cmp.l	#$12d00,d0			; warte auf Zeile $12d um das zu verhindern
	beq.s	WarteF				; Das Ausschalten des DMA führt zu Flimmern

	move.l	#$7fff7fff,$9a(a5)	; DEAKTIVIEREN SIE INTERRUPTS & INTREQS

			; 5432109876543210
	move.w	#%0000010101110000,d0	; DEAKTIVIEREN DMA

	btst	#8-8,OldDmaL		; test bitplane
	beq.s	NoPlanesA
	bclr.l	#8,d0				; nicht ausschalten planes
NoPlanesA:
	btst	#5,OldDmaL+2		; test sprite
	beq.s	NoSpritez
	bclr.l	#5,d0				; nicht ausschalten sprite
NoSpritez:
	move.w	d0,$96(a5)			; DEAKTIVIEREN DMA

	move.l	BaseVBR(pc),a0			; in a0 ist der Wert des VBR
	move.l	#MyInt6c,$6c(a0)		; meine Routine int. Level 3.
	move.w	OldDmaL(pc),$96(a5)		; Gibt den alten DMA-Status zurück
	move.w	OldIntenaL(pc),$9a(a5)	; INTENA STATUS
	move.w	OldIntreqL(pc),$9c(a5)	; INTREQ
	rts

*****************************************************************************
; Diese Routine wartet D1-Frames. Alle 50 Bilder vergehen 1 Sekunde.
;
; d1 = Anzahl der zu wartenden Frames
;
*****************************************************************************

WaitBlanks:
	lea	$dff000,a5				; OFFSET für CUSTOM REGISTER
WBlan1xb:
	move.w	#$80,d0
WBlan1bxb:
	cmp.b	6(a5),d0			; vhposr
	bne.s	WBlan1bxb
WBlan2xb:
	cmp.b	6(a5),d0			; vhposr
	beq.s	WBlan2xb
	dbra	D1,WBlan1xb
	rts

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

*****************************************************************************

	SECTION	GRAPHIC,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

Bplpointers:
	dc.w	$e0,0,$e2,0			; erste	 bitplane
	dc.w	$e4,0,$e6,0			; zweite    "
	dc.w	$e8,0,$ea,0			; dritte    "
	dc.w	$ec,0,$ee,0			; vierte    "
	dc.w	$f0,0,$f2,0			; fünfte    "
	dc.w	$f4,0,$f6,0			; sechste   "

	dc.w	$180,0	;		 Color0 schwarz


				 ;5432109876543210
	dc.w	$100,%0110101000000000	; bplcon0 - 320*256 HAM!

	dc.w	$180,$0000,$182,$134,$184,$531,$186,$443
	dc.w	$188,$0455,$18a,$664,$18c,$466,$18e,$973
	dc.w	$190,$0677,$192,$886,$194,$898,$196,$a96
	dc.w	$198,$0ca6,$19a,$9a9,$19c,$bb9,$19e,$dc9
	dc.w	$1a0,$0666

	dc.w	$9707,$fffe			; warte auf Zeile $97

	dc.w	$100,$200			; BPLCON0 - keine bitplanes
	dc.w	$180,$00e			; color0 BLAU

	dc.w	$b907,$fffe			; warte auf Zeile $b9
Bplpointers2:
	dc.w	$e0,0,$e2,0			; erste	 bitplane
	dc.w	$e4,0,$e6,0			; zweite    "
	dc.w	$e8,0,$ea,0			; dritte    "
	dc.w	$ec,0,$ee,0			; vierte    "
	dc.w	$f0,0,$f2,0			; fünfte    "

	dc.w	$100,%0101001000000000	; BPLCON0 - 5 bitplanes LOWRES

; Die Palette, die in 2 Gruppen von 16 Farben "gedreht" wird.

Cols:
	dc.w	$180,$040,$182,$050,$184,$060,$186,$080	; Grünton
	dc.w	$188,$090,$18a,$0b0,$18c,$0c0,$18e,$0e0
	dc.w	$190,$0f0,$192,$0d0,$194,$0c0,$196,$0a0
	dc.w	$198,$090,$19a,$070,$19c,$060,$19e,$040

	dc.w	$1a0,$029,$1a2,$02a,$1a4,$13b,$1a6,$24b	; Blauton
	dc.w	$1a8,$35c,$1aa,$36d,$1ac,$57e,$1ae,$68f
	dc.w	$1b0,$79f,$1b2,$68f,$1b4,$58e,$1b6,$37e
	dc.w	$1b8,$26d,$1ba,$15d,$1bc,$04c,$1be,$04c
Cole:

	dc.w	$da07,$fffe			; warte auf Zeile $da
	dc.w	$100,$200			; BPLCON0 - deaktiviere bitplanes
	dc.w	$180,$00e			; color0 BLAU

	dc.w	$ff07,$fffe			; warte auf Zeile $ff
	dc.w	$9c,$8010			; INTREQ - Ich fordere eine COPER-Unterbrechung an,
								; um  Musik zu spielen (auch während wir
								; mit der dos.library laden).

	dc.w	$ffff,$fffe			; Ende copperlist


*****************************************************************************
; 		DESIGN 320*34 mit 5 bitplanes (32 Farben)
*****************************************************************************

Picture:
	incbin	"/Sources/pic320x34x5.raw"

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

mt_data:
	dc.l	mt_data1

mt_data1:
	incbin	"/Sources/Mod.Prova"


******************************************************************************
; Puffer, der leer bleibt, dient hier nur als "schwarz" vor dem Laden.
; Wir hätten auch einfach die Bitebenen deaktivieren und aktivieren können
; nur mit der Figur geladen, um diesen Nullplatz zu sparen!
******************************************************************************

	SECTION	LEEREPLANE,BSS_C

Buffer:
Logo:
	ds.b	6*40*176	; 6 bitplanes * 176 Zeilen * 40 bytes (HAM)


	end

Dieses Listing sperrt die Datei, prüft sie auf ihre Länge und ordnet ihr 
mit AllocMem Speicher zu, lädt es und gibt schließlich den Speicherblock 
mit FreeMem frei. Bitte beachten Sie die unterschiedlichen Möglichkeiten von
Fehlern, FreeMem nicht auszuführen, wenn nichts zugewiesen wurde und
die Datei nicht zu verwenden, wenn sie nicht richtig geladen wurde. Es ist IMMER 
erforderlich alles zu überprüfen und die Routinen auf Fehler vorzubereiten.
Die Routine wurde parametrischer gestaltet. Tatsächlich können Sie jederzeit
bei Aufruf der Routine einen beliebigen Dateinamen und den benötigten Speichertyp 
angeben. Nur für den Fall wenn sie mehr Dateien hochladen möchten, verwechseln 
sie am Ende nicht die verschiedenen FreeMems !
Hier ist ein Beispiel, wo wir 2 Dateien hochladen:

; erste Datei:

	lea	FileName1(pc),a0 		; Name der hochzuladenden Datei
	lea	Buffile1(pc),a1			; Label in welchem die Adresse der Datei 
								; im Speicher geladen wird
	lea	Grandezz1(pc),a2		; Label in welchem die Größe der Datei gespeichert wird
	moveq	#2,d0				; Speichertyp Ziel: CHIP RAM!

	bsr.w	DosLoad2			; Laden Sie eine Datei mit dos.lib hoch
								; während wir unsere eigene copperliste ansehen
								; und unser Interrupt läuft 
								; Definieren Sie zuerst "TypeOfMem" mit "2" für CHIP
								; oder "1" für PUBLIC und die anderen Parameter.
	TST.B	d1					; Haben wir Speicher zur freien Verfügung gestellt?
	beq.s	NonFreeMemare		; d1=0, dann nicht zugeordnet
	st.b	FreeMema1			; wenn ja, setzen sie FreeMema1
NonFreeMemare
	TST.L	d0					; Auf Fehler prüfen...
	bne.s	ErroreLoad			; Datei nicht geladen? Dann lass es uns nicht benutzen!
								; d0 = 0, dann ist alles in Ordnung
	....

; zweite Datei:

	lea	FileName2(pc),a0 		; Name der hochzuladenden Datei
	lea	Buffile2(pc),a1			; Label in welchem die Adresse der Datei 
								; im Speicher geladen wird
	lea	Grandezz2(pc),a2		; Label in welchem die Größe der Datei gespeichert wird
	moveq	#2,d0				; Speichertyp Ziel: CHIP RAM!

	bsr.w	DosLoad2			; Laden Sie eine Datei legal mit dos.lib hoch
								; während wir unsere eigene copperliste ansehen
								; und unser Interrupt läuft 
								; Definieren Sie zuerst "TypeOfMem" mit "2" für CHIP
								; oder "1" für PUBLIC und die anderen Parameter.
	TST.B	d1					; Haben wir Speicher zur freien Verfügung gestellt?
	beq.s	NonFreeMemare2		; d1=0, dann nicht zugeordnet
	st.b	FreeMema2			; wenn ja, setzen sie FreeMema2
NonFreeMemare2
	TST.L	d0					; Auf Fehler prüfen...
	bne.s	ErroreLoad2			; Datei nicht geladen? Dann lass es uns nicht benutzen!
	...							; d0 = 0, dann ist alles in Ordnung


Und am Ende müssen wir 2 FreeMems machen:

	tst.b	FreeMema1			; Gab es einen Fehler vor dem AllocMem?
	beq.s	NonEraAllocata1		; wenn ja, mach kein FreeMem!

	move.l	Grandezz1(pc),d0	; Größe des Blocks in bytes
	move.l	Buffile1(pc),a1		; Adresse des Blocks des zugewiesenen Speichers
	move.l	4.w,a6
	jsr	-$d2(a6)				; FreeMem
NonEraAllocata1:

	tst.b	FreeMema2			; Gab es einen Fehler vor dem AllocMem?
	beq.s	NonEraAllocata2		; wenn ja, mach kein FreeMem!

	move.l	Grandezz2(pc),d0	; Größe des Blocks in bytes
	move.l	Buffile2(pc),a1		; Adresse des Blocks des zugewiesenen Speichers
	move.l	4.w,a6
	jsr	-$d2(a6)				; FreeMem
NonEraAllocata2:

	rts							; exit


Natürlich können Sie die Routine nach Belieben ändern oder parametrisieren
um Dateien mit einer bestimmten Länge hochzuladen ...
mach es wie du willst, aber mach keine Fehler!

