
; Diverse Funktionen





_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

