
; Diverse Funktionen.  Compress-Tab 8.





_SysBase	EQU	4

CALL	MACRO
	IFEQ	NARG-2
	move.l	\2,a6
	ENDC
	IFLE	NARG-2
	jsr	_LVO\1(a6)
	MEXIT
	ENDC
	FAIL	CALL MACRO: PARAMETERFEHLER
	ENDM










; Zufallszahlen.

	IFD	Random

	XDEF	_FastRand,_RangeRand,_RangeRan



; FastRand (Zahl)
; Erzeugt schnell einen	Pseudo-Zufallszahl unter Benutzung der "Zahl".
; Rückgabe: Die	Zufallszahl.  Sollte für das nächste Mal gespeichert werden.

_FastRand
	move.l	4(SP),d0
SpecialRand
	add.l	d0,d0
	bhi.s	1$
	eor.l	#$1D872B41,d0
1$	rts



; RangeRand (Bereich)
; Erzeugt eine Zufallszahl im Bereich 1	bis "Bereich".	"Bereich" muß im
; Bereich 1 bis	65535 liegen.
; Rückgabe: Die	Zufallszahl.

_RangeRan
_RangeRand
	move.l	a0,-(SP)
	lea	1$(PC),a0
	move.l	(a0),d0
	bsr.s	SpecialRand		; erzeuge Zufallszahl
	move.l	d0,(a0)
	and.l	#$FFFF,d0
	tst	4+4+2(SP)
	beq.s	2$
	divu	4+4+2(SP),d0
2$	clr	d0
	swap	d0
	tst	d0
	bne.s	3$
	moveq	#1,d0			; gib statt Null immer 1 zurück
3$	move.l	(SP)+,a0
	rts

1$	dc.l	0	; Letzter Zufallswert



	ENDC










; Zu den folgenden Routinen ist	einiges	zu sagen:
; AddTOF benutzt eine erweiterte Version der Interrupt-Struktur	namens
; "Isrvstr", zu	finden in "graphics/graphint.i".  Das erste Zusatzlangwort
; zeigt	auf die	aufzurufende C-Routine,	das zweite auf das an diese Routine
; zu übergebende Datenfeld.
; _ttskasm ist die eigentliche Routine,	die die	Schnittstelle zur C-Routine
; bildet.  Sie ruft nur	die C-Routine mit dem Zeiger auf das Datenfeld auf.

	IFD	AddTOF

	INCLUDE	"exec/types.i"
	INCLUDE	"exec/interrupts.i"
	INCLUDE	"graphics/graphint.i"
	INCLUDE	"hardware/intbits.i"
	INCLUDE	"lvo/exec.i"
	INCLUDE	"lvo/graphics.i"

	XDEF	_AddTOF,_RemTOF,_ttskasm,_waitbeam

	XREF	_GfxBase	; für _waitbeam





; AddTOF (Interruptstruktur-Zeiger, C-Routinen-Zeiger, Datenfeldzeiger)
; Hängt	eine C-Routine in die Vertical-Blank-Interrupt-Serverkette.  Der
; C-Routine wird der Zeiger auf	das Datenfeld übergeben.
; Rückgabe: Keine.

_AddTOF_REG	REG	d0-d1/a0-a1/a6
REGISTER	SET	5

_AddTOF
	movem.l	_AddTOF_REG,-(SP)
	move.l	REGISTER*4+4(SP),a1	; Strukturzeiger (für AddIntServer)
	move.l	a1,Isrv_Iptr(a1)	; damit	A1 im Server gleich geladen ist
	lea	_ttskasm(PC),a0		; unsere Zwischenroutine...
	move.l	a0,Isrv_code(a1)	; ...ist aufzurufen
	move.l	REGISTER*4+8(SP),Isrv_ccode(a1)	; 1. Zusatzlangwort: C-Routine
	move.l	REGISTER*4+12(SP),Isrv_Carg(a1)	; 2. Zusatzlangwort: Datenfeld
	moveq	#INTB_VERTB,d0
	CALL	AddIntServer,_SysBase
	movem.l	(SP)+,_AddTOF_REG
	rts





; RemTOF (Interruptstruktur-Zeiger)
; Entfernt die C-Routine wieder	aus der	Serverkette.
; Rückgabe: Keine.

_RemTOF_REG	REG	d0-d1/a0-a1/a6
REGISTER	SET	5

_RemTOF
	movem.l	_RemTOF_REG,-(SP)
	move.l	REGISTER*4+4(SP),a1	; Interrupt-Struktur
	moveq	#INTB_VERTB,d0		; Interrupt-Nummer
	CALL	RemIntServer,_SysBase	; weg damit !
	movem.l	(SP)+,_RemTOF_REG
	rts





; Assembler-Hilfsroutine.  Bildet die Schnittstelle zur	C-Routine.

_ttskasm
	move.l	Isrv_ccode(a1),a0	; Zeiger auf C-Routine
	move.l	Isrv_Carg(a1),-(SP)	; Zeiger auf Datenfeld ist Parameter
	jsr	(a0)			; rufe C-Routine auf
	addq	#4,SP			; korrigiere Stack
	moveq	#0,d0			; d.h. andere Server auch aufrufen
	rts





; waitbeam (Positionszeile)
; Wartet, bis der Videostrahl über die Positionszeile gelaufen ist.
; Rückgabe: Die	aktuelle Videostrahl-Position.

_waitbeam_REG	REG	d1/a0-a1/a6
REGISTER	SET	4

_waitbeam
	movem.l	_waitbeam_REG,-(SP)
	move.l	_GfxBase,a6
1$	CALL	VBeamPos		; hole Position
	cmp.l	REGISTER*4+4(SP),d0	; schon	erreicht ?
	ble.s	1$			; nein,	weiter warten
	movem.l	(SP)+,_waitbeam_REG	; gib die aktuelle Position zurück
	rts



	ENDC




















; Ein- und Ausgabe.  Files sind	hier AmigaDOS-Filehandle.





; puts (Stringzeiger)
; Schreibt einen String	auf "stdout".  Das Stringende 0	wird durch ein Line-
; feed ersetzt.
; Rückgabe: Linefeed.  Im Fehlerfall -1.

	IFD	puts

	XDEF	_puts

	XREF	_fprintf
	XREF	_stdout

_puts
	move.l	4(SP),-(SP)		; Stringzeiger
	pea	1$(PC)			; Formatstring
	move.l	_stdout,-(SP)		; File
	jsr	_fprintf
	add	#4*3,SP
	rts

1$	dc.b	'%s',10,0		; Ausgabe mit Linefeed !

	ENDC





; fputs	(Stringzeiger, File)
; Schreibt einen String	in ein File.  Das Stringende 0 wird nicht geschrieben.
; Rückgabe: Das	letzte ausgegebene Zeichen.  Im	Fehlerfall -1.

	IFD	fputs

	XDEF	_fputs

	XREF	_fputc

_fputs_REG	REG	d1/a0-a2/a6
REGISTER	SET	5

_fputs
	movem.l	_fputs_REG,-(SP)
	move.l	REGISTER*4+4(SP),a2	; Stringzeiger
	bra.s	1$

2$	move.l	REGISTER*4+8(SP),-(SP)	; File
	move.l	d1,-(SP)		; Zeichen
	jsr	_fputc
	addq	#2*4,SP
	tst.l	d0			; Schreibfehler	?
	bmi.s	0$			; ja, Ende mit -1
1$	moveq	#0,d1
	move.b	(a2)+,d1
	bne.s	2$

	; Fertig.  D0 ist entweder -1 oder das letzte Zeichen.
0$	movem.l	(SP)+,_fputs_REG
	rts

	ENDC





; getchar ()
; Lies genau ein Zeichen von "stdin".
; Rückgabe: Das	gelesene Zeichen.  Im Fehlerfall oder bei Fileende -1.

	IFD	getchar

	XDEF	_getchar

	XREF	_fgetc
	XREF	_stdin

_getchar
	move.l	_stdin,-(SP)
	jsr	_fgetc
	addq	#4,SP
	rts

	ENDC





; putchar (Zeichen)
; Gib ein Zeichen auf "stdout" aus.
; Rückgabe: Das	ausgegebene Zeichen.  Im Fehlerfall -1.

	IFD	putchar

	XDEF	_putchar

	XREF	_fputc
	XREF	_stdout

_putchar
	move.l	_stdout,-(SP)
	move.l	4+4(SP),-(SP)
	jsr	_fputc
	addq	#2*4,SP
	rts

	ENDC





; fgetc	(File)
; Lies genau ein Zeichen aus einem File.
; Rückgabe: Das	gelesene Zeichen.  Im Fehlerfall oder bei Fileende -1.

	IFD	fgetc

	INCLUDE	"lvo/dos.i"

	XDEF	_fgetc

	XREF	_DOSBase

_fgetc_REG	REG	d1-d3/a6
REGISTER	SET	4

_fgetc
	movem.l	_fgetc_REG,-(SP)
	subq	#2,SP
	move.l	REGISTER*4+2+4(SP),d1	; File
	move.l	SP,d2			; Puffer
	moveq	#1,d3			; Länge
	CALL	Read,_DOSBase
	subq.l	#1,d0			; genau	ein Byte ?
	beq.s	1$
	moveq	#-1,d0			; nein,	Fehler
	bra.s	0$

1$	move.b	(SP),d0			; ja, hole das Byte (D0	war Null)

0$	addq	#2,SP
	movem.l	(SP)+,_fgetc_REG
	rts

	ENDC





; fputc	(Zeichen, File)
; Gib ein Zeichen auf ein File aus.
; Rückgabe: Das	ausgegebene Zeichen.  Im Fehlerfall -1.

	IFD	fputc

	INCLUDE	"lvo/dos.i"

	XDEF	_fputc

	XREF	_DOSBase

_fputc_REG	REG	d1-d3/a6
REGISTER	SET	4

_fputc
	movem.l	_fputc_REG,-(SP)
	move.l	REGISTER*4+8(SP),d1	; File
	lea	REGISTER*4+4+3(SP),a0
	move.l	a0,d2			; Puffer
	moveq	#1,d3			; Länge
	CALL	Write,_DOSBase
	tst.l	d0			; Fehler ?
	bmi.s	1$			; ja, gib -1 zurück
	move.l	REGISTER*4+4(SP),d0	; sonst	das Zeichen zurück
1$	movem.l	(SP)+,_fputc_REG
	rts

	ENDC





; fclose (File)
; Schließe das File.

	IFD	fclose

	INCLUDE	"lvo/dos.i"

	XDEF	_fclose

	XREF	_DOSBase

_fclose_REG	REG	d0-d3/a6
REGISTER	SET	5

_fclose
	movem.l	_fclose_REG,-(SP)
	move.l	REGISTER*4+4(SP),d1
	CALL	Close,_DOSBase
	movem.l	(SP)+,_fclose_REG
	rts

	ENDC










; Formatierte Ausgabe.





; sprintf (Stringzeiger, Formatstringzeiger {Argliste})
; Formatiert den Formatstring mit der Argumentliste und	schreibt den Ziel-
; string in (Stringzeiger).
; Rückgabe: Der	Zeiger auf den Zielstring.

	IFD	sprintf

	INCLUDE	"lvo/exec.i"

	XDEF	_sprintf

_sprintf_REG	REG	a0-a3/a6
REGISTER	SET	5

_sprintf
	movem.l	_sprintf_REG,-(SP)
	move.l	REGISTER*4+8(SP),a0	; Formatstring
	lea	REGISTER*4+12(SP),a1	; Daten
	lea	1$(PC),a2		; Prozedur
	move.l	REGISTER*4+4(SP),a3	; Zielstring
	CALL	RawDoFmt,_SysBase
	move.l	REGISTER*4+4(SP),d0	; gib Zeiger auf Zielstring zurück
	movem.l	(SP)+,_sprintf_REG
	rts

1$	move.b	d0,(a3)+
	rts

	ENDC





; fprintf (File, Formatstringzeiger {Argliste})
; Formatiert den Formatstring mit der Argumentliste und	schreibt den Ziel-
; string in ein	File.
; Rückgabe: 0.	Im Fehlerfall -1.

	IFD	fprintf

	XDEF	_fprintf

	XREF	__doprnt

_fprintf
	pea	12(SP)
	move.l	8+4(SP),-(SP)
	move.l	4+4+4(SP),-(SP)
	jsr	__doprnt
	add	#4*3,SP
	rts

	ENDC





; printf (Formatstringzeiger {Argliste})
; Formatiert den Formatstring mit der Argumentliste und	schreibt den Ziel-
; string nach "stdout".
; Rückgabe: 0.	Im Fehlerfall -1.

	IFD	printf

	XDEF	_printf

	XREF	__doprnt
	XREF	_stdout

_printf
	pea	8(SP)
	move.l	4+4(SP),-(SP)
	move.l	_stdout,-(SP)
	jsr	__doprnt
	add	#4*3,SP
	rts

	ENDC





; Hilfsroutine	 doprnt	(File, Formatstringzeiger, Argumentlistenzeiger)
; Formatiert den Formatstring mit der Argumentliste und	schreibe den Ziel-
; string in ein	File.
; Rückgabe: 0.	Im Fehlerfall -1.

	IFD	doprnt

	INCLUDE	"lvo/exec.i"
	INCLUDE	"lvo/dos.i"

	XDEF	__doprnt

	XREF	_DOSBase

__doprnt_REG	REG	d1-d3/a0-a4/a6
REGISTER	SET	9

__doprnt
	; Formatiere.
	movem.l	__doprnt_REG,-(SP)
	movem.l	REGISTER*4+8(SP),a0/a1	; Formatstring-	und Daten-Zeiger
	lea	1$(PC),a2		; Prozedur
	link	a4,#-256		; belege den Stringspeicher
	move.l	SP,a3			; Zielstring
	CALL	RawDoFmt,_SysBase

	; Vermesse den String.
	move.l	SP,a0			; fertiger String
2$	tst.b	(a0)+
	bne.s	2$
	subq	#1,a0
	sub.l	SP,a0			; ergibt Stringlänge ohne Null

	; Ausgabe.
	move.l	a0,d3
	beq.s	0$			; wenn String leer ist
	move.l	SP,d2			; Puffer
	move.l	REGISTER*4+8(a4),d1	; File
	CALL	Write,_DOSBase		; egal,	ob es klappt
	tst.l	d0			; Fehler ?
	bmi.s	0$			; ja, gib -1 zurück
	moveq	#0,d0			; nein,	gib Null zurück

	; Fertig.
0$	unlk	a4
	movem.l	(SP)+,__doprnt_REG
	rts

1$	move.b	d0,(a3)+
	rts

	ENDC










	END

