Als Hobbyprogrammierer habe ich schon einige grössere Programme auf die Beine gestellt; doch kam es immer vor, dass irgendwo in diesen Programmen noch Fehler versteckt waren, die sich erst nach mehrmaligem Ausprobieren plötzlich zeigten. meistens hatte ein Anwender gerade einige Zeit gearbeitet, als plötzlich ein Fehler auftrat, die Fehlerabfangroutine versagte und der Anwender sich zu seiner grössten Verwunderung auf dem Desktop wiederfand, während ihm einfiel, dass er noch nicht gespeichert hatte. Obwohl die Daten sich zu diesem Zeitpunkt noch im Arbeitsspeicher befanden, mussten die Anwender sich von neuem ans wer machen - bis heute.
Denn seit heute sind meine Programme mit einem neuen System ausgestattet, das ich Ihnen hier vorstelle. Es besteht aus einem Accessory (also einem Programm, das beim Booten geladen wird, und in jedem Programm, das eine Menüzeile hat, also auch dem Desktop, aufgerufen werden kann) und einer Routine, die in das Programm, dessen Daten geschützt werden sollen, eingebaut wird. Diese Routine übergibt dem Accessory Startadresse und Länge des Bereiches, der im Notfall gespeichert werden soll.
Tritt dieser Notfall ein, klickt der Benutzer das Accessory an (das sich ungefähr dort befindet, wo auch Kontrollfeld u.ä. zu finden sind), und die Daten werden in der Datei „\DA-TEN.ASC“ gespeichert.
Wenn Sie eigene Programme mit dem System versehen wollen, geben Sie das untenstehende Accessory ein und compilieren es als Accessory. Wichtig: es muß jetzt den Namen „RETTER.PRG“ tragen! Wenn Sie mit GFA-B ASIC 2.0 arbeiten, compilieren Sie es normal und behandeln es dann mit dem „Accessory-Maker“. (Tippen Sie das Listing ein, starten Sie das Programm und wählen Sie „RETTER.PRG“ in der Dateiauswahlbox) Geben Sie dann die Aufruf-Routine ein und bauen Sie sie nach dem angegebenen Beispiel in Ihr Programm ein. Die Daten, die gespeichert werden, müssen sich in einem geschlossenen Bereich befinden, dessen Anfangsadresse und Länge der Routine beim Aufruf übergeben werden. Leider verfügt GFA-BASIC 2.0 nicht über den einfachen Aufruf der GEM-Befehle wie die 3.5-Version. Sie müssen bei Verwendung der 2.0-Version deshalb die mit REM versehenen Befehle eingeben und jeweils den ersten Befehl vor einem solchen Block von REM-Befehlen weglassen.
Sollten Sie zu den „Banausen“ gehören, die sich nicht für die tieferen Geheimnisse der Programmierung interessieren, so können Sie an dieser Stelle getrost aufhören zu lesen.
Zum Accessory: es meldet sich nach dem Start sofort mit der GEM-Funktion MENU_REGISTER unter dem Titel „Datenrettung“ an und wartet dann in einer Endlosschleife auf einen Aufruf oder die Sendung der Anfangsadresse und Länge des zu speichernden Bereiches. Das Warten übernimmt der Befehl „EVNT_MESAG“, dem ein 16 Bytes großer Puffer (hier in Form von 4 Langwörtern) übergeben werden muß. Das erste Wort (=2 Bytes) enthält den Nachrichtentyp. Wird beispielsweise das Accessory angeklickt, steht hier der Wert 40; bekommt das Accessory Daten, so erhält es hier den Wert 42 (den ich ausgesucht habe). Das Accessory „weiß“ dann, daß es im 4. und 5. Wort des Puffers [=Puffer%(2)l die Startadresse und im 6. und 7. Wort [=Puffer%(3)] die Länge erhält. (Damit auch große Werte übergeben werden können, wurden für diese Parameter je 2 Wörter gewählt - wir haben ja Platz) Die Werte in den restlichen Wörtern sind für uns unerheblich.
Zur Routine: Sie muß mit der GEM-Funktion Appl_Find die Identifikationsnummer des Accessories finden, um ihm anschließend mittels Appl_write eine Nachricht zukommen zu lassen. Diese Nachricht enthält nun genau die Informationen (42, Startadresse, Länge), auf die das Accessory wartet.
Wenn Sie die Abfrage der Nachricht 42 sowie die Prozeduren im Accessory weglassen, können Sie es als normales Accessory für andere Zwecke gebrauchen. Die Prozedur, die nach dem Anklicken des Accessories ausgeführt werden soll, nennen Sie bitte Open ac.
Literatur:
[1] GFA-Clubnachrichten,Ausg. 1/2 und 3/4 1990
[2] Data Becker: Atari ST intern
' Accessory "RETTER" des Datenrettungssystems
' by Sebastian Mödersheim
' (c) 1991 MAXON Computer
'
RESERVE 33000 ! wir brauchen etwas Platz
ON BREAK CONT ! Abbruch nicht möglich
DIM puffer%(3) ! 4 Longwords = 16 Bytes
eintrag$=" Datenrettung" ! Accessory anmelden
ap_id%=APPL_INIT() ! Dazu brauchen wir unsere Identifikationsnummer
REM ap_id%=Dpeek(Lpeek(gb+4)+4)
dummy%= MENU_REGISTER(ap_id%,eintrag$)
REM DPOKE GINTIN,DPEEK(LPEEK(GB+4)+4)
REM LPOKE ADDRIN,VARPTR(eintrag$)
REM GEMSYS 35
'
DO
~EVNT_MESAG(V:puffer%(0)) ! Auf Aufruf und Daten warten
REM LPOKE ADDRIN,VARPTR(puffer%(0))
REM GEMSYS 23
' Wort 0: Nachrichtentyp (muß hier 40 oder 42 sein)
' 40: Accessory wurde angeklickt
' 42: Ein Programm will uns etwas übergeben
' Wort 1: Identifikationsnummer des sendenden Programmes
' Wort 2: <>0 bedeutet, die Nachricht hat Überlänge
IF (puffer%(0) DIV 65536)=40 THEN ! Accessory
@open_ac ! wurde angeklickt
ENDIF
IF (puffer%(0) DIV 65536)=42 THEN ! Daten werden
@get_datas ! übergeben
ENDIF
LOOP
'
PROCEDURE open_ac
IF begin%=0 ! Wenn Daten unkorrekt oder noch gar nicht
' übergeben wurden
ALERT 1,"Hier Datenretter.|Mir liegen keine|korrekten Daten vor",1," ... ",dummy%
ELSE
ALERT 1,"Hier Datenretter.|Ich kann Ihre|Daten jetzt speichern",1,"Na los|Halt",dummy%
IF dummy%=1
BSAVE "\Daten.asc",begin%,laenge%
ENDIF
ENDIF
RETURN
'
PROCEDURE get_datas
begin%=puffer%(2)
laenge%=puffer%(3)
' Wort 3+4 (=ein Langwort): Startadresse
' Wort 5+6 : Länge
IF begin%=0 OR laenge%=0 !Da kann was nicht stimmen ...
ALERT 1,"Hier Datenretter:|Habe fehlerhafte Daten|erhalten",1," Aha? ",dummy%
begin%=0
ELSE
ALERT 1,"Hier Datenretter:|Habe korrekte Daten|erhalten",1," Schön ", dummy%
ENDIF
RETURN
' Einbaumodul des Datenrettungssystems
' by Sebastian Mödersheim
' (c) 1991 MAXON Computer
' Hinweise:
' Die Daten, die im Bedarfsfall gerettet werden,
' müssen in einem Block liegen. Der Routine
' "CALL_SAVER, die am Anfang eines Programmes auf-
' gerufen wird, bekommt als Parameter Startadresse
' und Länge des Blockes übergeben.
'
' Beispiel für zu rettende Daten
Unsinn$="Gespeichert oder nicht gespeichert."
Unsinn$=Unsinn$+" Das ist doch wohl keine Frage."
GOSUB call_saver(VARPTR(Unsinn$),LEN(Unsinn$))
'
PROCEDURE call_saver(begin%,len%)
'
sende_id%=APPL_INIT() ! Unsere Identifikations-
REM GEMSYS 10 ! nummer
REM sende_id%=DPEEK(GINTOUT)
'
ziel$="RETTER " ! Zielidentifikations-
ziel_id%=APPL__FIND (ziel$) ! nummer
REM LPOKE ADDRIN,VARPTR(zielS)
REM GEMSYS 13
REM ziel_id%=DPEEK(GINTOUT)
'
IF ziel_id%=-1
ALERT 1,"Datenretter|nicht gefunden",1, " ... ",dummy%
GOTO tschuess
ENDIF
'
DIM puffer%(3) ! Nachricht
puffer%(0)=42*65536+sende_id%
puffer%(2)=begin%
puffer%(3)=len%
'
dummy%=APPL_WRITE (ziel_id%,16,varptr(puffer%(0)))
REM DPOKE GINTIN,ziel_id% ■ Nachricht senden
REM DPOKE GINTIN+2,16
REM LPOKE ADDRIN,VARPTR(puffer%(0))
REM GEMSYS 12
REM dummy%=DPEEK(GINTOUT)
'
IF dummy%=-1
ALERT 1,"Fehler bei der|Datenübermittlung",1," ... ",dummy%
GOTO tschuess
ENDIF
'
ON MENU GOSUB nix ! Dieses Spielchen ist nötig,
FOR dummy%=0 TO 10 ! da verschiedene Programme
ON MENU ! sonst verrückt spielen ...
NEXT dummy%
tschuess:
RETURN
PROCEDURE nix ! Gehört zum Sendemodul
RETURN
' Der Accessorymaker
' by Sebastian Mödersheim
' (c) 1991 MAXON Computer
'
Pfad$="\*.*"
Fileselect Pfad$,"",Datei$
If Datei$<>"" And Right$(Datei$,3)="PRG"
' Wurde ein Programm angewählt?
Open "U",#1,Datei$ ! Öffnen
Seek #1,28 ! und ab Stelle 28 die Daten
Restore Inf ! schreiben
Read Datum%
While Not Datum%=-1
Out #1,Datum%
Read Datum%
Wend
Seek #1,237 ! ... und an 237 noch was
Read Datum%
Out 1,Datum%
Close #1 ! ... und fertig
Name Datei$ As Left$(Datei$,Len(Datei$)-3)+"ACC"
Print "Umwandlung vorgenommen"
Endif
Inf:
Data 75,250,254,254,96,6,27,102,27,118,0,0,
Data 79,237,1,0,-1,54