← ST-Computer 04 / 1988

Disk schreibgeschützt? Ihr ST warnt Sie, wenn nicht

Programmierpraxis

Haben Sie nicht auch schon öfter mal eine Diskette aus Versehen gelöscht? Dieses kleine Programm kann Ihnen hier unter die Arme greifen. Denn es wird Sie jedesmal mit einem Ton warnen, wenn eine nicht schreibgeschützte Diskette in das Laufwerk gelegt wird.

Die Bedienung des Programmes ist äußerst einfach. Es kann mit nahezu jedem Assembler bearbeitet werden. Es könnten eventuell Probleme bei den Kommentaren und am Ende des Listings bei den DS.x-Befehlen auftreten. Durch das Weglassen der Kommentare und Ersetzen der DS.x-durch BLK.x-Mnemonics dürften keine Fehler mehr Vorkommen.

Nach erfolgreichem Assemblieren sann man das erhaltene Programm aus dem Desktop starten oder man Kopiert es in den AUTO-Ordner der Startdiskette. Dort installiert es sich dann selbst.

Nun wird man jedesmal durch einen Ton gewarnt, wenn eine Diskette mit fehlendem Schreibschutz eingelegt wird.

Es muß nur noch beachtet werden, daß das Programm durch einen RESET verloren geht, d.h. es muß erneut installiert werden.

Wie funktioniert das alles ?

Als erstes muß das Einlegen einer Diskette ohne Schreibschutz festgestellt werden. Dank dem TOS hat man es sehr leicht, denn in der Speicherzelle h&9B2 wird dieses Ereignis durch den Wert Null angezeigt. Ansonsten enthält sie den Wert $FF.

Da es leider keine andere Möglichkeit gibt, als die Abfrage in den VBL-Interrupt einzubinden, muß man den Wechsel von $FF auf $00 feststellen. Würde man dies nicht so lösen, hätte man einen Dauerton, solange die Diskette eingelegt ist.

Der Wechsel wird durch das Zwischenspeichern des Wertes aus der Adresse $9B2 erkannt. Der jeweils aktuelle Inhalt dieser Speicherzelle wird mit dem alten gespeicherten Wert verglichen. Tritt hier ein Unterschied auf, fand ein Wechsel statt. Es muß nur noch geprüft werden, ob es sich um die Änderung von $FF auf $00 handelt.

Hat man auf diese Weise erkannt, daß eine Diskette ohne Schreibschutz eingelegt wurde, geht es an den Soundchip. Die Programmierung dieses Chips sieht so aus, daß man ein Register anwählt und dann einen Wert hineinschreibt.

Es wurden folgende Adressen des Soundchips verwendet:

$FF8800 In dieser Speicherzelle kann ein Register angewählt und ebenso ausgelesen werden. SFF8802 Hier kann man einen Wert in das gewählte Register schreiben.

Will man nun dem Soundchip einen Ton entlocken, muß man als erstes einen Kanal einschalten. Um einen klaren Ton zu erhalten, wird das Rauschen abgestellt. Das zugehörige Register ist hier das siebte. Dort werden die entsprechenden Bits gesetzt oder gelöscht.

Der nächste Schritt ist das setzen der Frequenz für den Ton. Hierzu ist das erste Register zuständig.

Da das Programm im VBL abläuft, kann man sich aus Zeitgründen nicht um die Dauer des Tones kümmern. Doch hier bietet sich die Möglichkeit an, eine Hüllkurve des Soundchips zu benutzen, d.h. der Chip kümmert sich selber um die Dauer. Das hat allerdings den Nachteil, daß keine schönen Klänge verwirklicht werden können. Um die Hüllkurve festzulegen, muß man das 12. und 13. Register verwenden.

Wer sich noch für die Installation der Routine im VBL-Interrupt interessiert kann dies in der Januar ’88-Ausgabe auf Seite 84 nachlesen.

* Computer meldet sich mit einem, Ton wenn * eine nicht schreibgeschuetzte Diskette in's * Laufwerk gelegt wird . * * (C) Markus Siebler * * Programmlaenge veststellen move.l $4(a7),a0 move.l $c(a0),d0 add.l $14(a0),d0 add.l $1c(a0),d0 add.l #$100,d0 move.l d0,len * Superviser anschalten clr.l -(sp) move.w #$20,-(sp) trap #1 add.l #6,sp move.l d0,save_ssp * Routine in VBL-Liste eintragen move.l $456,a1 clr.l d1 loop: tst.l $0 (a1,d1) beq free addq #4,d1 jmp loop free: tst.l d1 bne m3 addq #4,d1 bra loop m3: lea.l $0(a1,d1),a2 move.l #vbl,a1 move.l a1,(a2) * Programm verlassen jmp ende * VBL-Routine vbl: move.l d0,-(sp) * DO Zwischenspeichern move.b $9b2,d0 * $9b2 enthaelt WP-Status cmp.b ws,d0 * hat sich was geaendert ? beq quit * Nein -> quit cmp.b #$ff,d0 * Ja -> wurde Disk eingelegt ? beq quit * Nein -> quit move.b #7,$ff8800 * Ja -> Soundchip Reg.7 anwaehlen move.b $ff8800,d0 * in DO speichern and.b #$fe,d0 * Kanal 1 Ton ein or.b #$8,d0 * Kanal 1 Rauschen aus move.b d0,$ff8802 * DO wieder in Reg.7 schreiben move.b #1,$ff8800 * Frequenz des Tones einstellen move.b #3,$ff8802 move.b #8,$ff8800 * Lautstaerke einstellen move.b #$10,$ff8802 * Huellkurve waehlen move.b #12,$ff8800 * Frequenz der Huellkurve move.b #7,$ff8802 move.b #13,$ff8800 * Huellkurve waehlen move.b #4,$ff8802 quit: move.b $9b2,ws * WP-Status in < ws > speichern move.l (sp)+,d0 * DO wieder in alten Zustand rts * weiter geht's im VBL * Supervisor aus ende: move.l save_ssp,-(sp) move.w #$20,-(sp) trap #1 add.l #6,sp * Programm verlassen und resident halten move.w #0,-(sp) move.l len,-(sp) move.w #$31,-(sp) trap #1 len: ds.1 1 * Programmlaenge save_ssp: ds.1 1 * USER-Stack-Pointer ws: ds.b 1 * WP-Status cnt: dc.b -1 * Tondauer 10 ' W_PROTEC.PRG Lader (Zeilennummern nicht notwendig) 11 Filename$= "W_PR0TEC.PRG" 12 OPEN ”O", 1,Filename$ 13 REPEAT 14 C=C+1 15 READ Wert 16 IF Wert=-1 THEN 17 END 18 ENDIF 19 IF (C MOD 11)=0 THEN 20 IF Wert<>(Summe AND 255) THEN 21 PRINT"Fehler in Datazeile "C/11 22 END 23 ENDIF 24 Summe=0 26 ELSE 27 PRINT #1, CHR$(Wert); 28 Summe=Summe+(Wert+C MOD 11)^2 29 ENDIF 30 UNTIL Wert=-1 31 CLOSE(1) 100 DATA 96,26,0,0,1,22,0,0,0,0,68 101 DATA 0,0,0,0,0,0,0,0,0,0,129 102 DATA 0,0,0,0,0,0,0,0,32,111,142 103 DATA 0,4,32,40,0,12,208,168,0,20,65 104 DATA 208,168,0,28,6,128,0,0,1,0,100 105 DATA 35,192,0,0,1,12,66,167,63,60,107 106 DATA 0,32,78,65,223,252,0,0,0,6,149 107 DATA 35,192,0,0,1,16,34,121,0,0,124 108 DATA 4,86,66,129,74,177,16,0,103,0,242 109 DATA 0,10,88,65,78,249,0,0,0,56,51 110 DATA 74,129,102,0,0,8,88,65,96,0,135 111 DATA 255,230,69,241,16,0,34,124,0,0,44 112 DATA 0,102,36,137,78,249,0,0,0,234,23 113 DATA 47,0,16,57,0,0,9,178,176,57,145 114 DATA 0,0,1,20,103,0,0,102,176,60,83 115 DATA 0,255,103,0,0,94,19,252,0,7,69 116 DATA 0,255,136,0,16,57,0,255,136,0,172 117 DATA 2,0,0,254,0,0,0,8,19,192,252 118 DATA 0,255,136,2,19,252,0,1,0,255,7 119 DATA 136,0,19,252,0,3,0,255,136,2,182 120 DATA 19,252,0,8,0,255,136,0,19,252,180 121 DATA 0,16,0,255,136,2,19,252,0,12,41 122 DATA 0,255,136,0,19,252,0,7,0,255,131 123 DATA 136,2,19,252,0,13,0,255,136,0,174 124 DATA 19,252,0,4,0,255,136,2,19,249,109 125 DATA 0,0,9,178,0,0,1,20,32,31,168 126 DATA 78,117,47,57,0,0,1,16,63,60,32 127 DATA 0,32,78,65,223,252,0,0,0,6,149 128 DATA 63,60,0,0,47,57,0,0,1,12,231 129 DATA 63,60,0,49,78,65,0,0,0,49,251 130 DATA 0,0,0,49,0,255,0,0,0,24,127 131 DATA 20,24,22,8,14,114,10,22,0,0,97 9999 Data -1

Das Assembler-Listing als BASIC-Datas

Markus Siebler