   ;Don`t worry be happy!
   ;Autor: Daniel Gembris
   ;(c) MAXON Computer GmbH
   ;KICKSTART 1989

execbase = 4
AllocMem = -$C6
AllocAbs = -204
freemem = -210
OpenLib =  -408
CloseLib = -414
require = 2
CoolCapture = 46
ColdCapture = 42
DisplayAlert = -90
toffset0 = buserror-sound
toffset1 = addresserror-sound
toffset2 = illegalop-sound
toffset3 = divisionbyz-sound
toffset5 = aopex-sound
toffset6 = fopex-sound
toffset7 = uninitinter-sound
toffset8 = unpermittedinter-sound
laenge = dtend-dt
rate = 150
vol = 64
dauer = 90

   move.l  $8.s,d0                ;== testen, ob Programm bereits    ==
   and.l  #$00F00000,d0           ;== installiert                    ==
   bne  notyet                    ;noch nicht
   move.l  execbase.s,a6          ;Intuition-Library öffnen
   lea  i_name,a1
   moveq  #0,d0
   jsr  OpenLib(a6)
   move.l  d0,i_base
   move.l  d0,a6
   beq  Ende0
   moveq  #0,d0                  ;Alert ausgeben
   lea  string,a0
   moveq  #48,d1
   jsr  DisplayAlert(a6)
   move.l  execbase.s,a6            ;Library schließen
   move.l  i_base,a1
   jsr  CloseLib(a6)
Ende0: rts
notyet:
   move.l  execbase.s,a6            ;== Installationsroutine (IR) für neuen ==
   move.l  #Ende-Anfang,d0        ;==    "Alert" resetfest machen         ==
   moveq  #require,d1
   jsr  AllocMem(a6)              ;Speicher für IR anfordern
   tst.l  d0
   beq  fehler                    ;hat nicht geklappt
   move.l  d0,a1
   move.l  a1,CoolCapture(a6)     ;CoolCapture-Vektor auf IR umbiegen
   clr.l  ColdCapture(a6)         ;ColdCapture-Vektor wird nicht benötigt
   move.w  #Ende-Anfang,d0        ;IR kopieren
   lea  Anfang,a0
loop1: move.b  (a0)+,(a1)+
   dbra  d0,loop1
   jsr  Prüfsumme                 ;Prüfsumme neu berechnen
fehler: movem.l  d0-d7/a0-a6,-(sp) ;Register retten
   jmp weiter

Anfang: ;=====Installationsroutine======
   movem.l  d0-d7/a0-a6,-(sp)     ;Register retten
   move.l  execbase.s,a6            ;IR vor Löschung schützen
   move.l  #Ende-Anfang,d0
   lea  Anfang(pc),a1
   jsr  AllocAbs(a6)
   lea  Anfang(pc),a1             ;CoolCapture-Vektor neu setzen
   move.l  a1,CoolCapture(a6)
   clr.l  ColdCapture(a6)
weiter:
   move.l  #soundE-sound,d0       ;Speicher für neuen "Alert" besorgen
   move.l  execbase.s,a6
   moveq  #require,d1
   jsr  AllocMem(a6)
   lea  adresse(pc),a0            ;Adresse merken
   move.l  d0,(a0)
   beq  error                     ;kein Speicher verfügbar

   lea  adresse(pc),a2            ;Trap-Vektoren auf Debugger umbiegen
   move.l  (a2),a2
   lea  TrapData(pc),a1           ;ab TrapData werden die Adressen, auf
   ;die die Trap-Pointer zeigen, abgelegt
   lea  Traps(pc),a3              ;ab Traps stehen die Trap-Adressen
   lea  TrapOffsets(pc),a4        ;ab TrapOffsets stehen die Offsets - sie
   move.w  #7,d0                  ;werden zu sound addiert - für die
loop5: move.l  (a3)+,a5         ;neuen Trap-Routinen
   move.l (a5),(a1)+
   move.l  (a4)+,d1
   lea  0(a2,d1),a0
   move.l  a0,(a5)
   dbra  d0,loop5

   lea  adresse(pc),a1            ;Routine kopieren
   move.l  (a1),a1
   move.l  #soundE-sound-1,d1
   lea  sound(pc),a0
loop3: move.b  (a0)+,(a1)+
   dbra  d1,loop3
error: movem.l  (sp)+,d0-d7/a0-a6;Register mit den alten Werten be-
   rts                            ;schreiben
adresse: dc.l 0

sound: jmp  sound1(pc)

Prüfsumme: ;Prüfsumme neu berechnen
   move.l  execbase.s,a6
   clr.l  d1
   lea  34(a6),a0
   move.w  #$16,d0
loop2: add.w  (a0)+,d1
   dbra  d0,loop2
   not.w  d1
   move.w  d1,82(a6)
   rts

buserror: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #$0,d0
   jmp  sound(pc)
addresserror: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #4,d0
   jmp  sound(pc)
illegalop: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #8,d0
   jmp  sound(pc)
divisionbyz: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #12,d0
   jmp  sound(pc)
aopex: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #16,d0
   jmp  sound(pc)
fopex: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #20,d0
   jmp  sound(pc)
uninitinter: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #24,d0
   jmp  sound(pc)
unpermittedinter: movem.l  d0-d7/a0-a7,-(sp)
   moveq  #28,d0
   jmp  sound(pc)

radr: dc.l 0
tnumber: dc.l $FFFFFFFF
save0: dc.l 0

string:
   dc.b 0,66,16,'      Don`t worry, be happy! bereits installiert !!',0,255
   dc.b 0,66,26,'    OK                                            OK',0,0

i_base: dc.l 0
i_name: dc.b 'intuition.library',0,0
   even

Traps:
   dc.l  $000008,$00000C,$000010,$000014,$000028,$00002C,$00003C
   dc.l  $000060

TrapData:
   blk.l  8

TrapOffsets:
   dc.l  toffset0,toffset1,toffset2,toffset3,toffset5,toffset6
   dc.l  toffset7,toffset8

sound1: ;der neue "Alert" :
   lea  tnumber(pc),a0            ;Trap-Nummer merken
   move.l  d0,(a0)

   move.l execbase.s,a6             ;Speicher für Sound-Daten
   moveq #laenge,d0              ;anfordern
   moveq  #2,d1
   jsr  AllocMem(a6)
   lea saddress(pc),a0            ;Adresse retten
   move.l  d0,(a0)
   beq  endx                      ;keinen Speicher erhalten
   move.l  d0,a1                  ;Sound-Daten kopieren
   lea  dt(pc),a0
   moveq  #laenge-1,d0
cloop: move.b  (a0)+,(a1)+
   dbra  d0,cloop

   lea  $DFF0A0,a0                ;Sound-DMA initialisieren
   lea  saddress(pc),a1
   move.l  (a1),(a0)+
   move.w  #laenge/2,(a0)+
   move.w  #rate,(a0)+
   move.w  #vol,(a0)
   move.w  #$8201,$DFF096         ;Kanal 0 aktivieren

   jsr  cnt(pc)                   ;aktuellen Zählerstand des 50Hz-
   move.l  d0,d1                  ;Timers ermitteln
   add.l  #dauer,d1                  ;90/50 sec. Verzögerung
   and.l  #$FFFFFF,d1             ;möglichen Übertrag ignorieren
delay: jsr  cnt(pc)             ;warten, bis errechneter Stand
   cmp.l d0,d1                    ;erreicht
   bne  delay

   move.w  #$F,$DFF096            ;alle Audio-Kanäle abschalten
   lea  saddress(pc),a1
   move.l  (a1),a1
   moveq  #laenge,d0             ;Speicher an System zurückgeben
   jsr  freemem(a6)
endx:
   lea  TrapData(pc),a0           ;Rücksprungadresse ermitteln
   lea  tnumber(pc),a1
   move.l  (a1),d0
   lea  radr(pc),a2               ;in radr wird Rücksprungadresse gespeichert
   move.l  0(a0,d0),(a2)
   movem.l  (sp)+,d0-d7/a0-a7
   move.l  radr(pc),-(sp)         ;in Trap-Routine springen
   rts

saddress: dc.l 0
counter:
cn: dc.b 0
cmsb: dc.b 0
cmid: dc.b 0
clsb: dc.b 0

cnt:
   lea  clsb(pc),a0
   move.b  $BFE801,(a0)
   lea  cmid(pc),a0
   move.b  $BFE901,(a0)
   lea  cmsb(pc),a0
   move.b  $BFEA01,(a0)
   lea  counter(pc),a0
   move.l  (a0),d0
   rts

dt: ;Es folgen die Sounddaten, an dieser Stelle muß der gesampelte
   ;Sound eingesetzt werden.
   dc.b 0,0,1,124,0,0,0,0,254,252,252,250,248,248,246,246,246,244,244
   dc.b 240,242,244,244,246,250,252,252,254,0,2,4,8,14,14,18,22,22
dtend:
soundE:
Ende:



