   ; Programm : Sound Effect Machine
   ; Modul    : Hauptprogramm
   ; by       : Dan Dark Software / Jörg Schließer
   ; Version  : V1.0 / Juni 1990
   ; Assembler: Kick-Ass V1.20

   ; Hauptprogramm zum Programm S.E.M.


   ; Übergabeparameter beim Aufruf: keine


   ; Rückgabeparameter: keine


   ; Betriebsystem-Routinen

AllocSignal   = -330
FreeSignal   = -336
Wait   = -318
Signal   = -324

   ; Chip-Register:

dmacon     = $DFF096      ; DMA Kontrollregister (write)
dmaconr   = $DFF002      ; DMA Kontrollregister (read)
tasten   = $BFEC01      ; Tastencodes

   ; Konstanten:

execbase   = $4           ; Exec Basisadresse

   even
programmstart:
   bsr    startmodul         ;Startparameter ermitteln
   tst.l  d0                 ;kein Parameter ?
   beq    ende               ;Da kann man nichts machen !
   move.l #$10003,d0         ;Speicher: Chip-Mem
   bsr    loadtab            ;Im Parameterfile angegebene Sounds laden
   move.l a0,tabelle         ;Zeiger auf Tabelle der Soundadressen
   move.l d0,samples         ;Anzahl der geladenen Samples
   beq    ende               ;keine Samples ? => nix los !

   move.l execbase.s,a6
   move.l #0,a1
   jsr    FindTask(a6)       ;Adresse der Task-Struktur ermitteln
   move.l d0,thistask        ;und sichern
   moveq  #31,d0             ;Signal-Bit Nr. 31
   jsr    AllocSignal(a6)    ;anforden

   clr.l  168(a6)            ;Speicherstellen für Parameter-
   clr.l  180(a6)            ;übergabe in den Interrupt-Vektor
   clr.l  192(a6)            ;Strukturen der Audio-Interrupts
   clr.l  204(a6)            ;löschen

   lea    irqprog,a0         ;Zeiger auf Interruptroutinen
   bsr    installvtb         ;und in VertB einhängen

   moveq  #0,d0
   bset   #31,d0             ;Auf Signal Nr. 31 warten
   jsr    Wait(a6)

   ;hier wird unser Task in den Waiting-State versetzt und
   ;macht ein Nickerchen...

   move.l execbase.s,a6      ;Task wurde gewäckt !
   moveq  #31,d0
   jsr    FreeSignal(a6)     ;Signalbit wieder freigeben
   bsr    removevtb          ;und Interruptroutinen aushängen
   move.w #15,dmacon         ;Sounds ausschalten
   move.l tabelle,a0         ;Zeiger auf Tabelle der Sounds
   move.l samples,d0         ;Zahl der Samples
   bsr    cleartab           ;und Speicher wieder freigeben
ende:
   rts                       ;That's It !

irqprog:
   movem.l d0-d7/a0-a6,-(sp) ;Register sichern
   move.l execbase.s,a3
   add.l  #204,a3            ;Zeiger auf Übergabestelle Stimme 4
   moveq  #3,d7              ;Kennung für Stimme 4
irqloop:
   bsr    doirqsound         ;gucken, ob was zu spielen ist
   sub.l  #12,a3             ;Zeiger auf nächst tiefere Stimme
   dbra   d7,irqloop         ;Loop zum Abspielen der Stimmen
   cmp.b  #$74,$BFEC01       ;Escape-Taste gerade gedrückt ?
   bne    noescape           ;nein ... mal weiter gucken
   move.w #15,dmacon         ;ja ... alle Stimmen ausschalten
noescape:
   cmp.b  #$39,$BFEC01       ;CTRL-Taste gedrückt ?
   bne    endirq             ;nein... Fertig mit Interrupting
   cmp.b  #$74,alttast       ;das letzte mal Escape gedrückt ?
   bne    endirq             ;nein... also doch Fertig
   moveq  #0,d0              ;ja... dann Signal
   bset   #31,d0             ;zum Wecken des Tasks setzen
   move.l execbase.s,a6
   move.l thistask,a1
   jsr    Signal(a6)
endirq:
   move.b $BFEC01,alttast    ;aktuellen Tastencode sichern
   movem.l (sp)+,d0-d7/a0-a6
   rts                       ;Interrupt beenden

doirqsound:
   move.l 0(a3),d5           ;Soundparameter lesen
   beq    nothingtodo        ; = 0 ? ... Stimme stumm, nix zu tun
   cmp.l  #-2,d5             ; = -2 ? (Stimme stoppen ?)
   bne    nostumm            ;nein ... also weiter gucken
   moveq  #0,d4
   bset   d7,d4              ;Bit für aktuelle Stimme setzen
   move.w d4,dmacon          ;und Stimme ausschalten
   bra    voiceisoff         ;und weiter unten
nostumm:
   cmp.l  #-1,d5             ; = -1 ? (neuer Soundaufruf ?)
   bne    dosomething        ;ja ... Sound ist gefragt
   move.w dmaconr,d4         ;sonst DMA-Status leden
   btst   d7,d4              ;prüfen, ob Stimme noch spielt
   bne    nothingtodo        ;Stimme Spielt noch... das war's
voiceisoff:
   clr.l  0(a3)              ;Rückgabewert für freie Stimme setzen
   rts                       ;und fertig
dosomething:
   moveq  #0,d2
   move.b d5,d2              ;Nummer des Sounds nach d2
   subq.b #1,d2              ; -1 für Berechnung des Zeigers
   asl.w  #3,d2              ;mal 8 gibt Zeiger in Tabelle
   move.l tabelle,a1         ;Zeiger auf Tabelle der Sounds
   move.l 0(a1,d2),a0        ;Adresse des gewünschten Sounds in a0
   lsr.l  #8,d5              ;8 mal rechts Schieben in d5
   moveq  #0,d1              ;ergibt Zahl der Wiederholungen
   move.b d5,d1              ;in d1
   bne    okiplaygo          ;Wiederholungen <> 0 ... is OK
   moveq  #1,d1              ;sonst wenigstens 1 Wiederholung
okiplaygo:
   move.l d7,d0              ;Nummer der Stimme nach d0
   bsr    playsound          ;und versuchen, Sound zu starten
   tst.l  d0                 ;Rückgabewert prüfen
   bne    nothingtodo        ; <> 0 ... hat noch nicht geklappt
   move.l #-1,0(a3)          ; = 0 ... Rückgabewert für Sound aktiv
nothingtodo:
   rts                       ;das war's in dieser Stimme

   ;Zwischenspeicher für Variablen, Konstanten usw.

tabelle:   dc.l   0
samples:   dc.l   0
thistask:   dc.l   0
alttast:   dc.b   0
   even


