Q-Disk

Bei allen Vorteilen des Desktops - einen Nachteil hat es bestimmt: ein Diskettenwechsel wird nicht gemerkt! Man muß stattdessen immer durch einen Druck auf die ESC-Taste manuell nachhelfen. Das ist mir (wie sicherlich schon vielen anderen) allmählich auf die Nerven gegangen, so daß ich kurzerhand ein kleines Programm geschrieben habe, das dem Floppy auf die Sprünge hilft.

Zuerst muß man sich dazu die Hardware des ST betrachten. Da gibt es zunächst einen sogenannten Floppy-Disk-Controller (FDC), einen selbständigen kleinen Prozessor, der nichts anderes macht, als Daten von einer angeschlossenen Floppy in den Arbeitsspeicher des ST zu übertragen (READ) oder umgekehrt (WRITE). Dieser Chip ist über 14 Leitungen mit der Floppy verbunden. Wie man aus Quelle (1) entnehmen kann, sind die Floppies aber imstande weit mehr zu leisten, als beim ATARI ST verlangt wird: Die sind nämlich mit sage und schreibe 34 (!!!) Anschlüssen ausgerüstet, nach Adam Riese liegen also 20 brach. Daß da auch mancher nützliche dem Rotstift zum Opfer fiel, liegt auf der Hand, so z.B. der Ready-Pin: er sollte durch ein LOW signalisieren, daß gerade eine Disk eingelegt wurde ...

Vom Schieber zum Bit

„Wo die Hardware fehlt, kommt auch die beste Software nicht weiter“, dachten sich wohl die „cleveren“ Programmierer des Desktops und bauten eine Diskwechsel-Erkennungsroutine vorsichtshalber gar nicht erst ein. Daß es aber (meistens) doch geht, zeigt das vorliegende Programm. Bit 6 des Statusregisters des FDC enthält nämlich die interessante Information, ob die Disk im vorher selektierten Laufwerk schreibgeschützt ist oder nicht. Dazu muß man folgende drei Möglichkeiten betrachten:

  1. Die Disk ist schreibgeschützt (WP). Dann ist Bit 6 gesetzt.
  2. Die Disk ist nicht WP. Hier ist es logischerweise gelöscht.
  3. Es ist gar keine Disk eingelegt. Hier ist das Bit ebenfalls gesetzt!

Wenn man nun eine Nicht-WP-Disk einlegt, ändert sich das ominöse Bit: es wird gelöscht. Heißt: immer, wenn das Bit gelöscht wurde, ist gerade eine Diskette eingeschoben worden. Überwacht man dieses Bit in regelmäßigen Abständen (z.B. im Vertical Blank Interrupt), kann man jederzeit feststellen, ob ein Disk-Wechsel stattgefunden hat. Schön und gut: das klappt natürlich nur, wenn die eingeschobene Disk nicht schreibgeschützt ist. Aber ich denke, kaum einer wird nur mit schreibgeschützten Disketten arbeiten.

Das Programm

Braucht man also nur noch eine entsprechende VBL-Routine zu installieren, und schon ist man fertig, wie? Pustekuchen! Jetzt fängt die Arbeit ja erst an!

  1. Dem Desktop muß gesagt werden, daß es das Inhaltsverzeichnis aktualisieren soll. Das ist ja noch ganz einfach, dazu braucht man ja nur einen ESC-Code in den Tastaturpuffer zu schreiben. Wie das gemacht wird, kann man z.B. in der ST-COMPUTER 4/91 nachlesen, deshalb will ich mich an diesem Punkt nicht lange aufhalten. Nur noch soviel: wer noch das Rauchpilz-TOS besitzt (das wird sicherlich kaum noch einen betreffen), muß zwei Programmzeilen ändern, sonst läuft das Programm bei ihm nicht. Zu diesen Ur-Zeiten bestand nämlich ein Eintrag im Tastaturpuffer nur aus einem Word (High-Byte: Scan-, Low-Byte: ASCII-Code). Diese wohl kaum bekannte Tatsache dürfte auch der Grund sein, warum etliche Programme nicht auf diesem System laufen...

  2. Daraus ergibt sich aber gleich das Problem eines Programmstarts. Sobald man sich nicht mehr im Desktop befindet, wird ein ESC nicht mehr so verstanden, wie wir es wollen. Es würde vermutlich eher stören. Sobald also ein Programm gestartet wird, darf nichts mehr von unserer Seite in den Tastaturpuffer hinein. So weit, so gut. Wie überwacht man aber, wann ein Programm gestartet, und wann es beendet wird?

Dazu muß man sich schon ins GEMDOS hängen, das (Assembler-Programmierern wohlbekannt) über einen TRAP #1 aufgerufen wird. Vorher wurden die benötigten Parameter und zuletzt die Funktionsnummer auf dem Stapel abgelegt. Wir müssen jetzt folgendes tun:

Wichtig ist aber auch der Exec-Modus; nicht immer wird gleich ein Programm gestartet, wenn GEMDOS #75 aufgerufen wird! Außerdem gibt es Programme, die nie beendet werden. Zum einen gibt es da die ACCESSORIES, erkennbar an ihrem Namens-Anhängsel „ACC“. Bei ihnen darf der Zähler natürlich nicht erhöht werden, denn sie laufen ja quasi parallel zum Desktop. Und zum anderen handelt es sich um das Desktop selbst, das auch durch ein Pexec() gestartet wird! Es gibt jedoch nur eine Möglichkeit, daß unser Programm vor dem Desktop gestartet wurde, und zwar aus dem AUTO-Ordner heraus. Zu diesem Zeitpunkt ist aber auch noch nicht die Maus initialisiert, sprich der erste Slot in der VBL-Queue ist noch frei, denn der wird später immer durch die Mausbewegungsroutine belegt. Somit braucht man nur zu prüfen, ob der Slot frei ist, und schon weiß man Bescheid. In einem solchen Fall ist unser Zähler bei Programmstart auf -1 zu setzen, damit er dann beim Start des Desktops auf Null erhöht wird. Ab MC 68010 ist der Aufbau des Stacks bei einem TRAP anders. Daher muß man unter Berücksichtigung des Prozessortyps auf dem Stack die Parameter suchen. Einzelheiten hierzu entnehme man der ST-Computer 12/91 (Artikel: Trap-Trapper).

  1. Man darf im Desktop immer nur das Standardlaufwerk aktualisieren. Gibt es also zwei physikalische Laufwerke, und sind auch beide Directories zu sehen, darf man natürlich nur dann gleich mit einem Zeichen ans Desktop reagieren, wenn sich im Standardlaufwerk was getan hat! (Natürlich sollte man sich den „Vorfall“ trotzdem merken und später darauf zurückkommen.) Gleichzeitig muß man an dieser Stelle auch auf etwaige Hard- oder RAM-Disks achten. Man muß also ständig informiert sein, was das Standardlaufwerk ist. Dazu hängt man sich erneut ins GEMDOS und fängt den Opcode #14 ab. Diese Funktion setzt das Default-Drive.

Wichtiger Hinweis zum Abtippen: Nach Ende der meisten Programme wird das Inhaltsverzeichnis automatisch aktualisiert. Q-DISK macht das bei Bedarf auch noch, was manchen evtl, nerven könnte. Deshalb habe ich die entsprechende Zeile (321) rechts mit „***!!! ***“ gekennzeichnet: hier wird das oben geschilderte Phänomen unterbunden. Wer aber auf Nummer Sicher gehen will, sollte diese Zeile einfach nicht mit abtippen.

  1. Probleme ergeben sich bei nur einer „real existierenden“ Floppy. Das kann man aber über eine Systemvariable erfahren. Hier reicht es, wenn man die einmal am Anfang abfragt, denn ihr Wert wird (vom TOS her) niemals mehr verändert.

Installation

Es versteht sich nach all diesen Erläuterungen wohl fast von selbst, daß ein solches Programm nur in Assembler zu realisieren ist. Ich denke aber, daß es dafür nicht zu lang geworden und trotzdem recht komfortabel ist. Einmal abgetippt und übersetzt, kopiert man es sich am besten gleich in den AUTO-Ordner und macht einen Reset. Das Programm bleibt dann resident im Speicher und verbraucht hier ca. 4,5 KB. Sollte man es versehentlich nochmal starten, wird es nach einer kurzen Meldung sofort wieder beendet, ohne weiteren Speicher zu belegen. Selbstverständlich kann es aber auch sonst jederzeit gestartet werden. Bei Verbiegung des TRAP #1 -Vektors unterstützt es die XBRA-Methode.

Verträglichkeit

Meiner Ansicht nach müßte Q-DISK fast zu jedem anderen Programm laufen, ohne dieses zu stören oder zu verlangsamen. Bei den meisten Programmen reicht es aus, nur die Register d3-d7 und a3-a6 zu retten, denn laut (1) muß man damit rechnen, daß die anderen Register verändert werden. Es hat sich aber gezeigt, daß sich mancher Programmierer darüber hinweggesetzt hat, deshalb werden auch noch d1-d2 und a0-a2 gerettet. (d0 wird grundsätzlich geändert.) Das also gleich schon mal als Vorwarnung, bei mir traten aber bei keinem der getesteten Programme mehr Fehler oder gar Bomben auf. Auch die meisten vektorverbiegenden Hintergrundprogramme liefen fehlerfrei.

Erweiterungen

Natürlich ist das Programm erweiterbar. Man könnte es z.B. als Accessory starten und von ihm aus das Desktop manipulieren (Disk-Icons nach Disk-Namen beschriften, nur die angemeldeten Disks auch anzeigen usw.). Den fleißigen Programmierern ist da Tür und Tor geöffnet.

Literatur:

[1] H.-D. Jankowski, J. F. Reschke, D. Rabich: ATARI ST Profibuch, Sybex-Verlag, 2. Auflage 1989.

[2] ST-Computer, Nr. 4/91 und 12/91

;*********************************************
;                Q-DISK V 1.3                *
;*********************************************
; Programm sorgt dafür, daß Diskettenwechsel *
; im Desktop erkannt werden, sofern die Disk *
; nicht schreibgeschützt ist.                *
;*********************************************
; by Martin Glodde  (c) 1992 MAXON Computer  *
;*********************************************
; Offsets für Texte
info           equ 0        ;Titelinformation
err            equ 4        ;Text bei Installierungsfehler 
taste          equ 8        ;'Bitte Taste drücken'
installed      equ 12       ;'Schon installiert'
; Offsets für Variablen
nflops         equ 0        ;Anz. der Floppies
defdrv         equ 2        ;Standardlaufwerk
keyparam       equ 4        ;Tastaturpuffer-Parameterblock 
WP             equ 8        ;Schreibschutz-Flags
nprgs          equ 10       ;Anz. gestarteter Programme
akt            equ 12       ;Flags zur Akt. der Directories 
save_area      equ 14       ;Zeiger auf Bereich zur Registerrettung bei TRAP #1 
autostart      equ 18       ;Flag: Ist aus Autoordner gestartet worden ? 
stk_offs       equ 20       ;wo liegen Params bei TRAP#1? (abh. vom Prozessor)
;
prg:
    movea.l 4(sp),a5        ;Zeiger auf Basepage
    move.l  $c(a5),d0       ;Länge des Textsegments 
    add.l   $14(a5),d0      ;+ Länge des DATA-Segments
    add.l   $1c(a5),d0      ;+ Länge des BSS-Segments
    addi.1  #$1100,d0       ;+ Länge der Basepage + 1K für Stack & Savearea 
    move.l  d0,d1
    add.l   a5,d1
    andi.l  #-2,d1          ;Adresse des Stacks berechnen, runden ... 
    movea.l d1,sp           ;...und setzen
    lea.l   varfeld(pc),a5  ; Zeiger auf Variablenfeld 
    move.l  sp,eave.area(a5) ; Stackbereich dient später als Save Area
;
    clr.w   -(sp)           ;kein Fehler
    move.l  d0,-(sp)        ;Bedarf (für Ptermres)
    move.w  #$31,-(sp)      ;Ptermres()
;
    .DC.w   $a00a           ;Maus ausschalten
    lea.l   texte(pc),a6    ;Texttabelle
    move.l  info(a6),-(sp)  ;1. Text ausgeben 
    move.w  #9,-(sp)        ;Cconwsl)
    trap    #1              ;GEMDOS
    addq.l  #6,sp
;
    clr.l   -(sp)           ;Supervisor ein
    move.w  #32,-(sp)       ;Super()
    trap    #1              ;GEMDOS
    addq.l  #6,sp
    move.l  d0,-(sp)        ;alten Wert merken
    bsr     get_mc_type     ;Prozessortyp holen
; (ab MC 68010 gibt's bei Exceptions mind. einen Parameter mehr)
    move.w  $4a6,d0         ;merken, wieviele Floppies existieren
    subq.w  #1,d0
    move.w  d0,nflops(a5)
    move.w  #25,-(sp)       ;Dgetdrv()
    trap    #1              ;GEMDOS
    addq.l  #2,sp
    move.w  d0,defdrv(a5)   ;Default-Drive merken
    bsr     get_wp          ;Feststellen, ob Disk in A: oder B: schreibgeschützt ist
;
    move.w  #1,-(sp)        ;Tastaturpuffer-Parameterblock 
    move.w  #14,-(sp)       ;Iorec()
    trap    #14 ,-XBIOS
    addq.l  #4, sp
    move.l  d0,keyparam(a5) ;Zeiger auf Parameterblock merken
;
    lea.l   newtrap(pc),a3  ;neuer TRAP #1-Vektor
    move.l  $84,-4(a3)      ;alten Vektor in XBRA-Struktur eintragen 
    move.l  a3,$84          ;neuen Vektor setzen
;
    movea.l $456,a1         ;VBL-Queue
    move.w  $454,d6         ;_nvbls
    subq.w  #2,d6           ;-1 wg. dbra; -1 wg. reserviertem 1. Eintrag 
    tst.l   0(a1)           ;Ist 1.Slot noch frei ?
    seq     autostart(a5)   ;dann wurde aus AUTO-Ordner aufgerufen !
    moveq.l #0,d1
vbl_lp:
    tst.l   4(a1,d1.w)      ;nach freiem Eintrag suchen
    beq.s   gefunden
    movea.l 4(a1,d1.w),a0
    cmpi.w  #$4d47,-2(a0)   ;eigene Kennung (d.h. schon installiert ?) 
    beq.s   schon_inst      ;ja, Abbruch
    addq.w  #4,d1           ;nächster Slot
    dbra    d6,vbl_lp
;
;Fehler bei Installierung:
    movea.l err(a6),a4      ;Fehlertext
    bra.s   w2
schon_inst:
    movea.l installed(a6),a4 ;sonst anderen Text nehmen
w2:
    move.l  -4(a3),$84      ;alten TRAP #1-Vektor wieder herstellen 
    move.w  #32,-(sp)       ;Super()
    trap    #1              ;GEMDOS (zurück in Usermodus)
    lea.l   $e(sp),sp       ;Stack aufraumen: 6 für GEMDOS #32, 8 für 
; nicht benötigte Parameter für Ptermres() 
    move.w  #-1,-(sp)       ;Prg.-Ende vorbereiten: Rückgabewert = Fehler! 
    move.w  #76,-(sp)       ;Pterm()
;
    move.l  a4,-(sp)
    move.w  #9,-(sp)        ;Fehlermeldung ausgeben
    trap    #1
    addq.l  #6,sp
    bra.s   ok
;
gefunden:
    move.l  #vblrout,4(a1,d1.w) ;sonst VBL-Routine installieren 
    move.w  #32,-(sp)
    trap    #1              ;wie oben zurück in den Usermodus 
    addq.l  #6,sp           ;aber Ptermres() lassen
;
ok:
    tst.w   autostart(a5)
    bne.a   auto ;bei Aufruf aus Autoordner nicht auf Taste warten 
    move.l  taste(a6),-(sp) ;'Bitte Taste drücken' ausgeben 
    move.w  #9,-(sp)        ;Cconws()
    trap    #1              ;GEMDOS
    addq.l  #6,sp
    move.w  #7,-(sp)        ;Crawcin()
    trap    #1              ;GEMDOS
    addq.l  #2,sp
    bra.s   ende
auto:
    subq.w  #1,nprgs(a5)    ;weil bei AUTO-Start noch das Desktop initiali-
        ;siert (= mit Pexec() gestartet) wird ...
ende:
    trap    #1              ;Programmende (bei Fehler durch Pterm(),
;sonst durch Ptermres() )
;
get_mc_type:
; Prosessortyp ermitteln (wichtig für Stack-Aufbau beim TRAP #1)
    move.l  $5a0,d0         ;Zeiger auf Cookies
    beq.s   _68000          ;keiner da => altes TOS => MC 68000
    movea.l d0,a0
search_lp:
    move.l  (a0)+,d1
    beq.s   68000           ;keine Kennung => altes TOS (s.o.) 
    cmpi.l  #'CPU',d1       ;nach CPU-Cookie suchen
    beq.s   found
    addq.l  #4,a0           ;nächsten Eintrag
    bra.s   search_lp
found:
    tst.l   (a0)            ;Welcher Prozessor?
    beq.s   _68000          ;0=MC 68000, 10=MC 68010, ... 
    move.w  #2,stk_offs(a5) ;ggf. Stack-Offset erhöhen
_68000:
    rts
;
get_wp:
    tst.w   $43e            ;Zugriff erlaubt ?
    bne.s   get_wp          ;nein, warten
    moveq.l #4,d0           ;Floppy A:
    lea.l   WP(a5),a4       ;WP-Statustabelle
    lea.l   $ffff8800,a3    ;(a3) -> Soundchip; 2(a3) -> PSG-Data (W) 
    move.w  nflops(a5),d3
flop_lp;
    move.w  #$80,$ffff8606  ;FDC-Statusregister 
    move.w  sr,-(sp)
    ori.w   #$700,sr        ;Interrupts sperren
    move.b  #$e,(a3)        ;PSG Port A selektieren 
    move.b  (a3),d1         ;alten Wert merken
    move.b  d1,d4
    andi.b  #$f8,d1         ;die unteren 3 Bits
    or.b    d0,d1           ;d0=4 -> A: ; d0=2 -> B: (Seite egal) 
    move.b  d1,2(a3)        ;in Port A schreiben
    move.w  $ffff8604,d2    ;FDC-Status nach d2
    move.b  (a3),d1
    andi.b  #$f8,d1
    btst    #7,d2           ;Floppy MOTOR ON ?
    bne.s   motor
    ori.b   #6,d1           ;beide Floppies deselektieren
    bra.s   set
motor:
    or.b    d4,d1           ;Bei MOTOR ON alten Status setzen
set:
    move.b  d1,2(a3)
    move.w  (sp)+,sr
    btst    #6,d2           ;Ist Floppy A: W.P. ?
    sne     (a4)+           ;Flag setzen
    subq.w  #2,d0           ;ggf. noch Floppy B:
    dbra    d3,flop_lp
    rts
;
    .DC.w   $4d47 
vblrout:
;um Registerrettung braucht man sich bei VBL-Routinen nicht zu 
;kümmern, das macht schon das TOS !
    tst.w   $43e            ;Floppy-Zugriff erlaubt ? 
    bne     exit            ;nein
    lea.l   varfeld(pc),a5  ;Zeiger auf Variablenfeld 
    move.w  WP(a5),d5       ;alten WP-Status der Floppies merken
    bsr.s   get_wp          ;neuen Status ermitteln
    cmp.w   WP(a5),d5       ;hat sich was verändert ? 
    beq.s   weiter          ;nein!
    move.w  nflops(a5),d0   ;Anz. der angeschl. Floppies
    bne.s   testlp
    lsr.w   #8,d5           ;wenn nur Floppy A:, dann alten Wert verschieben
testlp:
    cmp.b   WP(a5,d0.w),d5  ;ist Floppy nicht mehr W.P. ? (alt=$FF,neu=$0)
    bpl.s   no_change       ;dann wäre das N-Flag gesetzt! 
    st      akt(a5,d0.w)    ;Flag zur Aktualisierung
no_change:
    lsr.w   #8,d5           ;nächste Floppy
    dbra    d0,testlp
;
weiter:
    tst.w   nprgs(a5)       ;im Moment Desktop?
    bne.s   exit            ;nein: keine Aktualisierung 
    move.w  defdrv(a5),d0   ;Default-Drive holen
    cmpi.w  #2,d0           ;Ist's auch keine Hard-/RAM-Disk ? 
    bcc.s   exit            ;doch -> raus
    tst.b   akt(a5,d0.w)    ;Muß Inhaltsverzeichnis aktualisiert werden ? 
    beq.s   exit            ;nein
    movea.l keyparam(a5),a0 ;Zeiger auf Tastaturpuffer-Parameterblock 
    move.w  8(a0),d1        ;nächste Leseposition 
    addq.w  #4,d1           ;Beim Rauchpilz-TOS durch "addq #2,d1" ersetzen 
    cmp.w   4(a0),d1        ;Länge überschritten ? 
    bcs.s   erhoeh          ;nein
    moveq.l #0,d1           ;sonst auf Pufferstart setzen
erhoeh:
    cmp.w   6(a0),d1        ;Schreibpos. = Lesepos. (=Puffer voll) ? 
    beq.s   exit            ;ja
    movea.l 0(a0),a2        ;Zeiger auf Puffer
    move.l  #$1001b,0(a2,d1.w) ;>ESC< (Scan- & ASCII-Code) in Puffer sehr. 
;Beim Rauchpilz-TOS durch "move #$11b,0(a2,d1.w)" ersetzen!
    move.w  d1,8(a0)        ;Zeiger korrigieren
    sf      akt(a5,d0.w)    ;Aktualisierungsflag löschen
exit:
    rts
;
    .DC.l   $58425241 
    .DC.l   $512d442e 
old_trp:
    .DC.l   0 
newtrap:
    movem.l d1/d2/a0-a2,regs ;Regs retten,
; weil sich manche Programme darauf verlassen, daß sie unverändert bleiben
    lea.l   varfeld(pc),a1  ;Zeiger auf Variablenfeld 
    move.w  stk_offs(a1),d0 ;Stack-Offset
    lea.l   6(sp, d0.w),a0  ;Parameterzeiger = Supervisor-Stack 
    btst    #5,(sp)         ;Auf welchem Stack liegen die Param's?
    bne.s   super_stack
    move.l  usp,a0          ;wenn Supervisor-Bit gelöscht ist, sind sie auf Userstack 
super_stack:
    cmpi.w  #14,(a0)        ;Dsetdrv() ?
    beq.s   dsetdrv
    cmpi.w  #75,(a0)        ;Pexec() ?
    beq.s   pexec
normal:
    movem.l regs,d1/d2/a0-a2 ;Reg. wieder herstellen (s.o.)
    move.l  old_trp,-(sp)
    rts                     ;normalen Trap aufrufen
;
dsetdrv:
    move.w  2(a0),defdrv(a1) ;neues Defaultdrive merken 
    tst.w   nflops(a1)      ;bei 2 phys. Laufwerken O.K.
    bne.s   normal
    cmpi.w  #1,2(a0)        ;bei 1 Floppy und neuem Pef.Drv. B: ...
    bne.s   normal
    clr.w   defdrv(a1)      ;... dieses wie phys. Floppy A: behandeln
    bra.s   normal
;
pexec:
    tst.w   2(a0)           ;Exec-Modus = 'laden und starten' ? 
    beq.s   prgstart        ;ja!
    cmpi.w  #4,2 (a0)       ;Exec-Modus = 'starten' ? 
    beq.s   prgstart        ;ja!
    cmpi.w  #6,2(a0)        ;Neuer Exec-Startmodus bei TOS 1.4 ? 
    bne.s   normal          ;nein!
prgstart:
    movea.l 4(a0),a2        ;Zeiger auf Programmnamen holen
search0:
    cmpi.b  #46,(a2)        ;Punkt?
    beq.s   pktgef
    tst.b   (a2)+           ;String zu Ende
    bne.s   search0
    bra.s   aufruf
pktgef:
    addq.l  #1,a2
    move.b  (a2)+,d0        ;1. Zeichen
    andi.b  #$df,d0         ;Großbuchstabe
    cmpi.b  #65,d0          ;'A' ?
    bne.s   aufruf          ;nein!
    move.b  (a2)+,d0        ;2. Zeichen (Wordzugriff nicht immer möglich!) 
    andi.b  #$df,d0         ;Großbuchstabe
    cmpi.b  #$43,d0         ;'C' ?
    bne.s   aufruf          ;nein
    move.b  (a2)+,d0        ;3. Zeichen
    andi.b  #$df,d0         ;Großbuchstabe
    cmpi.b  #$43,d0         ;'C' ?
    beq.s   normal          ;bei 'ACC (=Accessory) normaler Prg.-Start
aufruf:
    addq.w  #1,nprgs(a1)    ;Anzahl der gestarteten Programme +1 
    movea.l save_area(a1),a2 ;save_area
    move.w  (sp)+,-(a2)     ;SR, ...
    move.l  (sp)+,-(a2)     ;...Rücksprungadresse
    tst.w   stk_offs(a1)    ;noch ein Parameter ?
    beq.s   mc_alt1         ;nein, alter Prozessor
    move.w  (sp)+,d0        ;sonst jenen merken
    move.w  d0,-(a2)        ;und retten
mc_alt1:
    movem.l d3-d7/a3-a7,-(a2) ;und Register retten
    move.l  a2,save_area(a1) ;neue Save_area
    movea.l a0,sp           ;Stack zeigt auf Parameterliste 
    tst.w   stk_offs(a1)    ;ggf. noch weiteren Parameter ablegen
    beq.s   mc_alt2
    move.w  d0,-(sp) ;auf Stack
mc_alt2:
    pea     ret             ;neue Rücksprungadr.
    move.w  sr,-(sp)        ;und akt. SR
    move.l  old_trp(pc),-(sp)
    rts                     ;alte TRAP-Routine aufrufen
ret:
    lea.l   varfeld(pc),a1
    clr.w   akt(a1)         ;bei Prg-Ende nicht 'ESC' simulieren *** !!! *** 
    movea.l save_area(a1),a2 ; save area
    movem.l (a2)+,d3-d7/a3-a7
    tst.w   stk_offs(a1)    ;ggf. auch hier zus. Parameter
    beq.s   mc_alt3
    move.w  (a2)+,-(sp)     ;wieder zurück
mc_alt3:
    move.l  (a2)+,-(sp)     ;Register, Rücksprungadr. und Statusreg. 
    move.w  (a2)+,-(sp)
    move.l  a2,save_area(a1) ;alte save.area
    subq.w  #1,nprgs(a1)    ;Anzahl der aufgerufenen Programme -1 
    rte                     ;fertig
;
    .DATA
texte:
    .DC.l   t1,t2,t3,t4
t1:
    .DC.b   27, "E", 10,10,10,10,13,9
    .DC.b   " Q - DISK V 1.3 (Dezember '91)  ",10,13,9
    .DC.b   " -------------------------------",10,10,13,9
    .DC.b   " von Martin Glodde.",10,10,10,13
    .DC.b   "Das Programm erkennt Diskettenwechsel, wenn ...",10,13 
    .DC.b   "- ... die neue Disk nicht schreibgeschützt ist.",10,13 
    .DC.b   "- ... man sich im Desktop befindet.”,10,10,10,13,0
t2:
    .DC.b   "ERROR: Kein Platz mehr in der VBL-Queue.",10,13 
    .DC.b   "Q-DISK ist nicht installiert.",10,10,10,13,0
t3: .DC.b   "Bitte Taste drücken!",0,0
t4: .DC.b   "Programm ist schon installiert!",10,10,10,13,0
;
    .BSS
varfeld:
    .DS.b   22 
regs: .DS.l 5

Martin Glodde
Links

Copyright-Bestimmungen: siehe Über diese Seite