;Funktion zum erstellen eines Messageports:

;>= A0 = Zeiger auf Namen des Ports (nur für globale Ports nötig)
;>= D0 = Priorität des Ports (nur für globale Ports nötig)

;=> D0 = Zeiger auf Port. Wenn kein Port erstellt, D0 = Null


;Die Option 'IDNT' ist nur wichtig, wenn man vor hat sich die Funktion
;'CreatePort' in eine eigene Library einzubauen, um sie dann durch
;hinzulinken immer parat zu haben.

 IDNT "CreatePort.o"

 include "exec/types.i"
 include "exec/ports.i"
 include "exec/memory.i"
 include "exec/execbase.i"


CALLSYS	MACRO
	jsr _LVO\1(a6)
	ENDM
XLIB	MACRO
	XREF _LVO\1
	ENDM

;Die Funktion wird anderen Programmen durch die XDEF Option
;zu Verfügung gestellt.

 XDEF _CreatePort

 XREF _AbsExecBase
 XLIB AllocMem
 XLIB FreeMem
 XLIB AllocSignal
 XLIB AddPort

_CreatePort:
	movem.l	d2/a2-a3/a6,-(a7)  ;Register retten
	move.w	d0,d2	;Priorität nach D0
	move.l	a0,a2	;Zeiger auf Name
	move.l	_AbsExecBase,a6    ;ExecBase nach A6

;Die Angaben über die Art des zu belegenden Speichers 
;'MEME_PUBLUC' und 'MEMF_CLEAR' sind innerhalb des Include-Files
;'exec/memory.i' geschehen.

	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1 ;Speicherbeschreibung

;Die Größe der Port Struktur ist über die Struktur 'MP', die
;innerhalb des Include-File 'exec/ports.i' definiert ist
;festgelegt. Die größe ist in 'MP_SIZE' gespeichert.

	move.l	#MP_SIZE,d0	;Größe der Port-Struktur

;CALLSYS ist ein Macro, welches zu Beginn des Programms erstellt wurde

	CALLSYS	AllocMem	;belege Spicher
	tst.l	d0	;wurde Speicher belegt?
	beq.s	1$	;nein, dann Fehler
	move.l	d0,a3	;Zeiger auf Speicher für Port
	move.l	#-1,d0	;Wert für belibiges Signal
	CALLSYS	AllocSignal	;Signal für Port belegen
	tst.b	d0	;konnte Signal belegt werden ?
	bpl.s	2$	;Ja, alles Ok
	move.l	a3,a1	;sonst, Zeiger auf Speicher holen
	move.l	#MP_SIZE,d0	;größe des Speichers nach d0
	CALLSYS	FreeMem	;Speicher freigeben
	clr.l	d0	;D0 löschen (Fehlermeldung)
	bra.s	1$	;Sprung zum Ende

;Durch die zu Beginn angegebenen Includes, wird auch das File
;'exec/nodes.i' automatisch eingelesen. Hier sind die Einträge
;'LN_NAME', 'LN_PRI', 'LN_TYPE' und 'NT_MSGPORT' definiert.

2$:	move.l	a2,LN_NAME(a3) ;Zeiger auf Namen eintragen
	move.b	d2,LN_PRI(a3)  ;Priorität eintragen
	move.b	#NT_MSGPORT,LN_TYPE(a3)  ;Type eintagen

;Wenn eine Nachricht an den Port gelangt, soll ein Signal am Task
;gesetzt werde. Hierfür muß das MsgPort-Flag entsprechend gesetzt
;werden. PA_

	move.b	#PA_SIGNAL,MP_FLAGS(a3)
	move.b	d0,MP_SIGBIT(a3)

;Um den Zeiger auf den eigenen Task zu erhalten, gibt es zum einen die
;Möglichkeit, ihn mit der 'FindTask'-Funktion zu holen oder schneller
;ihn einfach aus der ExecBase-Struktur auszulesen. Um das letztere
;praktitieren zu können müssen wir uns aus dem Include-File
;'exec/execbase.i' den Offset diese Eintrags holen. Der Offset ist
;in 'ThisTask' gespeichert.

	move.l	ThisTask(a6),MP_SIGTASK(a3)  ;Zeiger auf Task holen

;Damit unser Port Nachrichten in Form einer Liste "aufbewaren" kann,
;muß in ihm eine soche List-Struktur initialisiert werden. Dies
;geschieht über ein Macro, welches in dem Include-File 'exec/lists.i'
;eingetragen ist. Dieses File wird automatisch beim öffnen des Files
;'exec/ports.i' eingelesen. Das Macro heißt NEWLIST und initialisiert
;eine List-Struktur. Als Parameter muß der Zeiger auf die
;List-Struktur in einem Adressregister übergeben werden.

	lea	MP_MSGLIST(a3),a1	;Zeiger auf List-Struktur
	NEWLIST	A1	;Macroaufruf
	move.l	a2,d0	;Zeiger auf Namen des Posts
	beq.s	3$	;verzweige, wenn kein Name angegeben
	move.l	a3,a1	;Zeiger auf Port-Struktur
	CALLSYS	AddPort	;Port in globale Liste eintragen
3$:	move.l	a3,d0	;Zeiger auf Port nach D0
1$:	movem.l	(a7)+,d2/a2-a3/a6  ;Register zurückholen
	rts		;Rücksprung

	END
