********************************************************
*
* Installationsroutine und Interruptroutine
* fuer MIDInet
*
* (C) 1987 by A. Buttchereit
*         and G. Nowinski
*             Moosholzweg 10
*             3392 Clausthal-Zellerfeld 3
*
********************************************************




gemdos:       EQU           $01
bios:         EQU           $0d
xbios:        EQU           $0e

start:  
              move.l        4(sp),a0
              add.l         #$86,a0
              clr.l         d0
              move.b        #6,d1       ;Zaehler
l1:           asl.l         #4,d0
              and.b         #$0f,-(a0)
              or.b          (a0),d0             ;Wiederherstellen
              subq.b        #1,d1
              bne           l1


              move.l        d0,nummer_adr   ;Adresse berechnet

              addq.l        #2,d0
              move.l        d0,send_adr     ;Adresse des Sendreq

              addq.l        #2,d0
              move.l        d0,recei_adr    ;Adresse des receivereq

              addq.l        #2,d0
              move.l        d0,busy_adr     ;Adresse des busy-Flags

              addq.l        #2,d0
              move.l        d0,auto_ack    ;Adresse des auto_ack-Flags

              addq.l        #2,d0
              move.l        d0,ok_adr       ;Adresse des OK-Flags

              addq.l        #2,d0
              move.l        d0,ack_adr      ;Adresse des Ack-Feldes

              add.l         #30,d0
              move.l        d0,online_adr   ;Adresse des Online-Feldes

              add.l         #30,d0
              move.l        d0,in_adr       ;Adresse des Eingabepuffers

              add.l         #128,d0
              move.l        d0,out_adr      ;Adresse des Ausgabepuffers

              move          #2,-(sp)
              move          #14,-(sp)
              trap          #xbios  
              addq.l        #4,sp

              move.l        d0,a0
              move.l        (a0),mpuf_adr   ;Adresse des MIDI-puffers
 
              addq.l        #6,d0
              move.l        d0,hd_adr       ;Adresse des Headindexes

              addq.l        #2,d0
              move.l        d0,tl_adr       ;Adresse des Tailindexes

              move.l        #continue,d0
              move.l        d0,adresse      ;VBI 'richtig' starten

              move.l        4(sp),a6        ;L„nge des Prgs berechnen
              move.l        #$100,d6
              add.l         12(a6),d6
              add.l         20(a6),d6
              add.l         28(a6),d6

              jsr           super_ein

              move.w        $454,d0         ;freien VBI-Vektor suchen
              lsl           #2,d0
              move.l        $456,a0
              clr.l         d1
vbltest:      
              tst.l         0(a0,d1.l)
              beq           vblfound
              addq.l        #4,d1
              cmp           d0,d1
              bne           vbltest
        
*---------------------------------------------*
*    Installation hat nicht geklappt          *
*---------------------------------------------*
              jsr           super_aus
              move.l        (sp)+,d0
              move          #0,-(sp)
              trap          #gemdos
*---------------------------------------------*
*         Freie Adresse gefunden              *
*---------------------------------------------*
vblfound:
              lea           0(a0,d1.l),a2  ;dieses Prg eintragen    
              move.l        #meinprog,(a2)
              jsr           super_aus
*---------------------------------------------*
* Programm resident im Speicher hinterlassen  *

*---------------------------------------------*
              clr.l         -(sp)
              move.l        d6,-(sp)
              move          #$31,-(sp)
              trap          #gemdos
*---------------------------------------------*
*    Supervisor-Modus einschalten             *
*---------------------------------------------*
super_ein:   
              clr.l         -(sp)
              move          #32,-(sp)
              trap          #gemdos
              addq.l        #6,sp
              move.l        d0,oldstack
              rts
*---------------------------------------------*
*     Supervisor-Modus ausschalten            *
*---------------------------------------------*
super_aus:
              move.l        oldstack,-(sp)
              move          #32,-(sp)
              trap          #gemdos
              addq.l        #6,sp
              rts
*************************************************************************

oldstack:     DS.l          1

nummer_adr:   DS.l          1
send_adr:     DS.l          1
recei_adr:    DS.l          1
busy_adr:     DS.l          1
auto_ack:    DS.l          1
ok_adr:       DS.l          1
ack_adr:      DS.l          1
online_adr:   DS.l          1
in_adr:       DS.l          1
out_adr:      DS.l          1

mpuf_adr:     DS.l          1
hd_adr:       DS.l          1
tl_adr:       DS.l          1

adresse:      DS.l          1
kennung:      DS.w          1
laenge:       DS.w          1
zaehler:      DS.w          1
adressat:     DS.w          1
absender:     DS.w          1
checksum:     DS.w          1
*************************************************************************
***********************     Mein Programm     ***************************
*************************************************************************

meinprog:
              movem.l       a0-a2/d0-d2,-(sp)

              move.l        adresse,a0
              jmp           (a0)
                                            
continue:                          
              bsr           MIDI_in
              bne           cont1
              move.l        #continue,adresse
              bra           B_exit

cont1: 

                                            
              cmp           #0,d1         
              bne           kein_freiz      ;*    zur Blockbehandlung    *
              
freizeichen:  
              move.l        busy_adr,a0     ;*   Aktion auf Bus merken!  *
              move          #1,(a0)           
              move.l        send_adr,a0      
              cmp           #0,(a0)          ;**************************** 
              beq           kein_sendreq     ;*Wenn send_req, dann senden*
              bra           senden           ;****************************
              
kein_sendreq: 
              bsr           sende_frei       
              bra           N_exit           ;*  Sonst Frei weitergeben! * 
                                             
kein_freiz:
              move          d1,kennung
              and           #$f,d1
              move          d1,adressat
              move          kennung,d1
              lsr           #4,d1
              and           #$f,d1
              move          d1,absender

wie_lang:
              bsr           MIDI_in
              bne           cont2
              move.l        #wie_lang,adresse
              bra           B_exit

cont2:
              move          d1,laenge
              move.l        busy_adr,a0     ;*   Aktion auf Bus merken!  *
              move          #1,(a0)   

              move.l        nummer_adr,a0
              move          adressat,d0      ;****************************
              cmp           (a0),d0          ;*Sind die Daten fuer mich? *
              bne           not_for_me       ;****************************

for_me:
              move          laenge,d1
              cmp           #0,d1            ;*   L„nge=0 ?   *                                 
              bne           kein_ack   
              
acknol:              
              move          absender,d0       
              subq          #1,d0           
              lsl           #1,d0           ;*****************************
              move.l        ack_adr,a0      ;*      Acknol. merken!      *
              move          #1,0(a0,d0.w)   ;*****************************

              move.l        busy_adr,a0
              move          #0,(a0)         ;* Busy noch zurueckhalten *
wait_ok:
              bsr           MIDI_in
              bne           setze_ok_flag
              move.l        #wait_ok,adresse
              bra           B_exit

setze_ok_flag:
              move.l        ok_adr,a0
              move          d1,(a0)

              move.l        busy_adr,a0
              move          #1,(a0)         ;* aber jetzt busy *

              bra           N_exit          ;Block fertig
              
kein_ack:     
              move.l        recei_adr,a0
              cmp           #0,(a0)
              beq           uebernehmen

kein_platz:              
              bra           WOM   

not_for_me:
              move          absender,d0     ;*****************************
              move.l        nummer_adr,a0   ;*    Bin ich der Absender?  *
              cmp           (a0),d0         ;*****************************
              bne           MIDI_durch

from_me:
              bra           WOM1

************************************************************************
******************      KEIN ... PLATZ ... WOM      ********************
WOM:
              clr           zaehler

              move          laenge,d0
              addq          #1,d0            ;* Laenge+1 fuer Checksum *
              move          d0,laenge

Block_WOM:
              bsr           MIDI_in
              bne           cont3
              move.l        #Block_WOM,adresse            
              bra           B_exit 
cont3: 
              move          zaehler,d0
              addq          #1,d0
              move          d0,zaehler
              cmp           laenge,d0 
              bne           Block_WOM
              
              bsr           sende_frei       ;*   Freiz. ohne Acknol.   *
              bra           N_exit


************************************************************************
******************      NOT ... ONLINE ... WOM      ********************
WOM1:
              move          adressat,d0     
              subq          #1,d0           ;***************************
              lsl           #1,d0           ;*                         *
              move.l        online_adr,a0   ;*   Muell vergessen &     *
              move          #0,0(a0,d0.w)   ;*   Adressat streichen!   *
                                            
              clr           zaehler

              move          laenge,d0
              addq          #1,d0            ;* Laenge+1 fuer Checksum *
              move          d0,laenge

Block_WOM1:
              bsr           MIDI_in
              bne           cont4
              move.l        #Block_WOM1,adresse            
              bra           B_exit 
cont4: 
              move          zaehler,d0
              addq          #1,d0
              move          d0,zaehler
              cmp           laenge,d0 
              bne           Block_WOM1

              bsr           sende_frei
              bra           N_exit            
 
***********************************************************************
*********     Ein Zeichen von der MIDIschnittstelle lesen    **********
MIDI_in:
              move.l        hd_adr,a1        ;****************************                                                    
              move          (a1)+,d0  ;head   *     Ist ein Zeichen      *     
              cmp           (a1),d0   ;tail   *        im Puffer ?       *
              bne           Zeichen          ;****************************
              rts
Zeichen: 
              addq          #1,d0            
              and           #$7f,d0         
              move.l        mpuf_adr,a0     
              move.b        0(a0,d0.w),d1    ;Zeichen nach D1!
              and           #$ff,d1    
              move          d0,-(a1)         ;head setzen
              move          #1,d0
              cmp           #0,d0
              rts



**************************************************************************

sende_frei:
              move          #0,d1
              jsr           MIDI_out
              rts

*************************************************************************


MIDI_out:     lea           $FFFC04,A1      ;Adresse des MIDI-Chips
midiloop:     move.b        0(a1),d2
              btst          #1,d2
              beq           midiloop
              move.b        d1,2(a1)
              rts
*************************************************************************

*************************************************************************
*********     Senderoutine schreibt einen Block ins Netz     ************
         
senden:       
              move          #0,checksum

              move.l        out_adr,a0
              move.b        (a0),d1     ;Adresse
              jsr           MIDI_out
              move.b        1(a0),d1    ;L„nge
              and           #$ff,d1
              move          d1,laenge
              jsr           MIDI_out
              clr           d0

loop:
              cmp           laenge,d0
              beq            raus
              move.b        2(a0,d0.w),d1  ;Daten
              move          checksum,d2
              eor           d1,d2
              move          d2,checksum
              jsr           MIDI_out
              addq          #1,d0
              bra           loop

raus:
              move          checksum,d1
              jsr           MIDI_out

              move.l        send_adr,a0
              clr           (a0)              
              bra           N_exit              ;Block geschrieben
              
*************************************************************************                     


*************************************************************************
*********  Routine uebernimmt einen Block in den Eingabepuffer  *********

uebernehmen:
              move          #0,checksum

              move.l        nummer_adr,a0
              move          absender,d0
              cmp           (a0),d0          ;Nachr. von mir an mich ?
              bne           normal

              move.l        busy_adr,a0
              move          #0,(a0)          ;Dann noch kein busy !
normal:
              move.l        in_adr,a0
              move          kennung,d1
              move.b        d1,(a0)          ;erstes Byte
              move          laenge,d1
              move.b        d1,1(a0)         ;L„nge
              clr           zaehler
block_ein:
              bsr           MIDI_in
              bne           cont5
              move.l        #block_ein,adresse            
              bra           B_exit 
cont5: 
              move          checksum,d2
              eor           d1,d2
              move          d2,checksum

              move.l        in_adr,a0
              move          zaehler,d0
              move.b        d1,2(a0,d0.w)
              addq          #1,d0
              move          d0,zaehler
              cmp           laenge,d0 
              bne           block_ein

warte_test:
              bsr           MIDI_in
              bne           testen
              move.l        #warte_test,adresse
              bra           B_exit

testen:
              move          checksum,d2
              cmp           d2,d1
              beq           no_io_error
io_error:

              move          adressat,d1
              lsl           #4,d1
              add           absender,d1      ;* sende Acknol. an Absender *
              jsr           MIDI_out
              move          #0,d1
              jsr           MIDI_out
              move          #0,d1
              jsr           MIDI_out
              bsr           sende_frei
              bra           N_exit

no_io_error:
              move.l        auto_ack,a0
              move          (a0),d0
              cmp           #0,d0            ;* kein Auto-Acknol. ? *
              beq           no_auto_ack

              move          adressat,d1
              lsl           #4,d1
              add           absender,d1      ;* sende Acknol. an Absender *
              jsr           MIDI_out
              move          #0,d1
              jsr           MIDI_out 

              move          #1,d1
              jsr           MIDI_out

              bsr           sende_frei

no_auto_ack:         
              move.l        recei_adr,a0
              move          #1,(a0)
               
              bra           N_exit

*************************************************************************


*************************************************************************
***********    Weiterschicken eines Blockes ueber das Netz   ************

MIDI_durch:
              move          kennung,d1
              jsr           MIDI_out
              move          laenge,d1
              jsr           MIDI_out

              addq          #1,d1
              move          d1,laenge         ;* Laenge+1 fuer checksum *

              clr           zaehler

block_durch:
              move          zaehler,d0
              cmp           laenge,d0
              beq           N_exit
         
              bsr           MIDI_in
              bne           cont6           
              move.l        #block_durch,adresse            
              bra           B_exit 
cont6: 
              jsr           MIDI_out
              move          zaehler,d0
              addq          #1,d0
              move          d0,zaehler
              bra           block_durch


*************************************************************************
     
                           
N_exit:       move.l        #continue,adresse

B_exit: 
              movem.l       (sp)+,a0-a2/d0-d2
              rts

*************************************************************************
