Die Entwickler des ATARI ST haben offenbar ein kleines Detail ĂŒbersehen oder fĂŒr zu unwichtig gehalten, denn das Videosignal des Rechners wird auch dann nicht abgeschaltet, wenn der Rechner lĂ€ngere Zeit nicht benutzt wird.
Da dieser Umstand auf die Dauer unschöne Brennspuren auf der Fluoreszensschicht des Bildschirms hinterlĂ€Ăt und die Fummelei am Helligkeitsregler nicht die eleganteste Lösung ist, habe ich ein kleines Programm geschrieben, welches das Videosignal abschaltet wenn die Tastatur/Maus des Rechners 5 Minuten lang nicht benutzt wird. Das Bild erscheint wieder, wenn eine Taste gedrĂŒckt oder die Maus bewegt wird.
Das Programm wird im AUTO-Ordner untergebracht, damit es bei einem Systemstart installiert wird.
Die Funktion des Programms möchte ich anhand des dokumentierten Quellcodes erlÀutern:
Vorausschickend bleibt zu sagen, daĂ an der Speicheradresse SFF8200 das Register fĂŒr die Video-Anzeige liegt. In diesem Register steuert das Bit 0 die Synchronisation des Bildes. Wird dieses Bit auf âT gesetzt,werden die intern erzeugten Synchronisationssignale abgeschaltet und der Bildschirm erscheint dunkel. Zu beachten bleibt, daĂ bei gesetztem Bit der VBL-Interrupt, der verschiedene periodische Systemaufgaben ausfĂŒhrt, simuliert werden muĂ:
- Berechnung der ProgrammlĂ€nge; die ProgrammlĂ€nge wird nach der Initialisierung an das GEMDOS mit der Funktion $31 (keep process) ĂŒbergeben um das Programm im Speicher resident zu halten
- Supervisor-Modus einschalten, Programm initialisieren, User-Modus einschalten
- mit dem Aufruf der GEMDOS-Funktion $31 kehrt das Programm ins Desktop zurĂŒck
- im Initialisierungs-Teil wird ein ZĂ€hler fĂŒr System-Timer-Interrupts mit
â60000â geladen. Da der Timer mit einer Frequenz von 200 Hz Interrupts erzeugt und der ZĂ€hler in der eigenen Routine nach jedem Interrupt um 1 dekrementiert wird, ist nach 60000/200 = 300 Sekunden oder 5 Minuten! der ZĂ€hler auf â0â gezĂ€hlt; ein ZĂ€hler fĂŒr die Simulation des VBL-Interruptâs wird mit 3 geladen; dieser ZĂ€hler wird in der neuen Timer-Routine bei jedem Aufruf um 1 dekrementiert und bei Erreichen von â0â wird der VBL-Interrupt simuliert. Dies gibt eine Simulationsfrequenz von 200/3 = 66.66... Hz. Ein Flag fĂŒr Keyboard-Interrupts wird mit â0â vorbesetzt; danach werden die Interrupt-Vektoren fĂŒr den Timer und das Keyboard auf die neuen Routinen gesetzt und die alten Vektoren jeweils an das Ende der eigenen Routinen geschrieben; zusĂ€tzlich wird noch der Vektor auf den VBL-Handler in die neue Timer-Routine geschrieben.
- in der neuen Keyboard-Routine wird der ZĂ€hler fĂŒr Timer-Interrupts wieder mit â60000â geladen, das Interruptflag gesetzt und dann die alte Interrupt-Routine angesprungen
- in der neuen Timer-Routine wird zuerst geprĂŒft ob der Bildschirm schon abgeschaltet ist.
Wenn dies der Fall ist, wird das Keyboard-Interruptflag getestet und, falls es gesetzt ist, der Bildschirm eingeschaltet. Ist das Interruptflag nicht gesetzt,wird der ZĂ€hler fĂŒr die VBL-Simulation erniedrigt und bei Bedarf der VBL-Interrupt ausgefĂŒhrt.
War bei Anruf der Timer-Routine der Bildschirm noch eingeschaltet, wird der Timer-ZĂ€hler um â1â erniedrigt. Ist der ZĂ€hler noch nicht auf â0â gezĂ€hlt (die 5 Minuten sind noch nicht abgelaufen) wird die alte Timer-Routine angesprungen.
Andernfalls wird das Keyboardflag gelöscht, der nÀchste VBL-Interrupt abgewartet und dann der Bildschirm abgeschaltet. Die neue Timer-Routine wird in jedem Fall mit dem Aufruf der alten Routine beendet.
Anmerkung:
Der Inhalt des Datenregisters D0 muĂ gerettet werden, da in einer Interrupt-Routine die Registerinhalte nicht verĂ€ndert werden dĂŒrfen.
****************************************
* CRT-SAVER *
* H.-J. Moes *
* DorfstraĂe 19 *
* 7854 Inzlingen *
* *
****************************************
v_shift = $ff820a * adresse des videoshifters
.text
move.l a7,a5 * alten Stackpointer retten
move.1 #uss,a7 * Stackpointer auf userstack
move.1 4(a5),a5 * adresse der basepage
move.l #$100,d7 * laenge der basepage '
add.l 12(a5),d7 * laenge des textsegment
add.1 20(a5),d7 * laenge des datensegment
add.l 28(a5),d7 * laenge des bss-segment
clr.l -(sp) * userstack wird Supervisorstack
move.w #$20,-(sp) * in Supervisormodus schalten
trap 1
move.l d0,ssp * alten supervisorstack-pointer retten
addq.l #6,sp
bsr init * initialisierung
move.l ssp,-(sp) * supervisorstack-pointer zurueck
move.w #$20,-(sp) * supervisormodus abschalten
trap 1
addq.l #6,sp * .stack-korrektur
clr.w -(sp) * kein fehler
move.l d7,-(sp) * programmlaenge
move.w #$31,-(sp) * keep process
trap 1
init pea initstring * begruessungsstring ausgeben
move.w #$09,-(sp) * Print line
trap 1
addq.l #6,sp
move.w #65535,d0
halt subq.w #1,d0 * verzoegerungsschleife
bne halt
move.w #60000,count * zaehler fuer timerdurchlaeufe
move.b #3,vblcount * zaehler fuer simulierten VBL-interrupt
move.b #0,keyflag * flag fuer keyboard-interrupt
move.l $118,keyalt + 2 * alter keyboard-/midi-interrupt
move.l #keybrd,$118
move.l $114,timealt+2 * alter timer c - interrupt
move.l #timer,$114
move.l $70,vbl+2 * vbl-vektor eintragen
rts
keybrd move.w #60000,count * zaehler neu laden
bset #0,keyflag * flag setzen
keyalt jmp $100000 * alte keyboard-/midi-routine aufrufen
timer btst #0,v_shift * externe Synchronisation ?
beq ein * bildschirm ist eingeschaltet
aus btst #0,keyflag * tastaturinterrupt aufgetreten ?
bne _ein * ja
subq.b #1,vblcount * VBL-zaehler dekrementieren
bne timealt * noch keine 3 timerdurchlaeufe
move.b #3,vblcount * zaehler neu laden
andi.w #$f8ff,SR * Interruptmaske low
pea timealt * nach VBL-simulation in alte timerroutine
move.w SR,-(sp) * interrupt-stackzustand simulieren
vbl jmp $100000 * VBL-handler anspringen
_ein bclr #0,v_shift * auf interne Synchronisation schalten
timealt jmp $100000 * in alte timerroutine springen
*
ein subq.w #1,count * zeit abgelaufen
bne timealt * nein
bclr #0,keyflag * flag loeschen
move.w SR,-(sp) * Statusregister retten
andi.w #$f8ff,SR * interruptmaske low
move.1 d0,-(sp) * datenregister retten
move.l $466,d0 * zaehler fuer ausgefuehrte VBL-interrupts
warte cmp.1 $466,d0 * auf naechsten VBL-interrupt warten
beq warte
bset #0,v_shift * auf externe Synchronisation schalten
move.l (sp)+,d0 * register zurueckholen
move.w (sp) + ,SR * Statusregister zurueckholen
bra timealt * in alte timerroutine
*
. data
initstring .dc.b $1b,$45 * ESC E clear home
.de.b $1b,$59,32+3,32+3 * ESC Y
.dc.b âCRT-Saver ST-Computer HJ Moesâ
.dc.b $0d,0
vblcount .dc.b 0 * zaehler fuer VBL-simulation
keyflag .dc.b 0 * flag fuer keyboard-interrupt
. even
ssp .dc.l 0 * Speicher fuer alten Supervisorstack-pointer
count .dc.w 0 * zaehler fuer timer C - interrupts
.ds.1 50
uss .dc.l 0 * userstack
* assembliert mit folgendem Batch-File :
* as68 -1 -u %l.s
* link68 %1.68k = %l.o
* relmod %1.68k %l.prg
_________________________________________________
10 ' CRT.PRG Lader
11 Filename$="CRT.PRG"
12 OPEN "O",1,FilenameS
13 READ Wert
14 REPEAT
15 PRINT #1, CHR$ {Wert);
16 Summe=Summe+Wert
17 READ Wert
18 UNTIL Wert=-1
19 READ Pruefsumme
20 IF Pruefsumme<>Summe THEN
21 PRINT "Fehler In Datas"
22 ENDIF
23 CLOSE 1
100 DATA 96,26,0.0.1,56,0,0,0.254
101 DATA 0,0,0,0,0,0,0,0,0,0
102 DATA 0,0,0.0,0,0,0,0,42.79
103 DATA 46.124,0,0,2,50,42,109,0,4
104 DATA 46,60,0,0,1,0,222,173,0,12
105 DATA 222.173,0,20,222,173,0,28,66,167
106 DATA 63,60.0.32.78,65,35,192,0,0
107 DATA 1,100,92,143,97.24,47,57.0,0
108 DATA 1,100.63,60.0,32,78.65,92,143
109 DATA 66,103,47,7.63,60,0,49,78,65
110 DATA 72,121.0.0,1,56,63,60,0.9
111 DATA 78,65.92,143,48,60,255,255,83,64
112 DATA 102,252.51,252,234,96,0,0.1,104
113 DATA 19,252.0,3,0,0,1,98,19,252
114 DATA 0,0,0,0,1,99,35,249.0,0
115 DATA 1,24,0,0,0,188,35,252,0,0
116 DATA 0,170,0.0,1,24,35,249,0.0
117 DATA 1,20,0,0.1,0,35,252,0,0
118 DATA 0,192,0,0,1,20,35,249,0,0
119 DATA 0,112,0,0,0,242,78,117,51,252
120 DATA 234,96,0,0,1,104,8.249.0,0
121 DATA 0 0,1,99,78,249,0,16,0,0
122 DATA 8,57,0,0,0.255,130,10,103,58
123 DATA 8,57,0,0,0,0,1,99,102,34
124 DATA 83,57,0,0,1,98,102,34,19,252
125 DATA 0,3,0,0,1,98,2,124,248,255
126 DATA 72,121,0,0,0.254,64,231,78,249
127 DATA 0,16,0,0,8,185,0,0,0,255
128 DATA 130,10,78,249,0,16,0,0,83,121
129 DATA 0,0,1,104.102,242,8,185,0,0
130 DATA 0,0,1,99,64.231.2.124,248.255
131 DATA 47,0,32,57,0,0,4,102,176,185
132 DATA 0,0,4,102,103,248,8,249,'0,0
133 DATA 0,255,130,10,32,31,70,223,96,198
134 DATA 27,69,27,89,35,35,67,82,84,45
135 DATA 83,97,118,101.114,32,32,32,83,84
136 DATA 45,67.111,109,112,117,116,101,114,32
137 DATA 32,72,46,74,46,32,77,111,101,115
138 DATA 13,0,0,0,0,0,0,0,0,0
139 DATA 0,0,0,0,0,0,0,0,0,0
140 DATA 0,0,0,0,0.0.0,0,0,0
141 DATA 0,0,0,0,0,0,0,0,0,0
142 DATA 0,0,0,0,0,0,0,0,0,0
143 DATA 0,0,0,0,0,0,0,0,0,0
144 DATA 0,0,0,0,0,0,0,0,0.0
145 DATA 0,0,0,0,0,0,0,0,0,0
146 DATA 0.0,0,0,0,0,0.0,0,0
147 DATA 0.0,0,0,0,0,0,0,0.0
148 DATA 0,0,0,0,0,0,0,0,0,0
149 DATA 0,0,0.0,0,0,0.0.0,0
150 DATA 0,0,0.0,0,0,0,0,0,0
151 DATA 0,0,0,0,0,0,0,0,0,0
152 DATA 0,0,0,0,0,0,0.0,0.0
153 DATA 0,0,0,0,0,0,0,0,0,0
154 DATA 0,0,0,0,0,0,0,0,0,0
155 DATA 0,0,0,0,0,0,0,0,0,0
156 DATA 0,0,0.0,0,0,0,0,0,0
157 DATA 0,0,0,0,0,0,0.0,0,0
158 DATA 0,0,0,0,0,0,0,0,0,0
159 DATA 0,0,0,0,0,0,0,4,36,10
160 DATA 24,24,8,8,10.6,14,6,14,10
161 DATA 8,24,8,10,10,28,10,0,26
9998 DATA -1
9999 DATA 24015
(H.S.Moes)