C 64
Tips und Tricks

Der EPROM-Automat

Was steckt hinter der Datenspeicherung auf EPROMs? Wir zeigen Ihnen, wie man seine eigenen Module aus Basic-Programmen herstellt.

Zur Programmierung von EPROMs sind drei Dinge notwendig: Ein Computer, ein EPROM-Programmiergerät, und das Wissen, in welcher Form Programme auf EPROMs gespeichert sein müssen. Dieser Artikel zeigt Ihnen, wie man eigene Programme so modifiziert, daß sie auf ein EPROM gespeichert und anschließend von dort auch ausgeführt werden können. In den folgenden Zeilen soll schrittweise erarbeitet werden, was dabei zu beachten ist. Sie sollen in die Lage versetzt werden, das Programm Auto-Eprom (Listing 1) zu verstehen und gegebenenfalls an Ihre eigenen Bedürfnisse anzupassen.

Was ist eigentlich ein EPROM? Nun, zunächst ist ein EPROM nichts anderes als ein Datenspeicher, der sich beschreiben, lesen und auch wieder löschen läßt. Wenn man einmal von dem etwas komplizierten Schreib- und Löschvorgang absieht, unterscheidet sich ein EPROM nur in einem für den C 64-Programmierer wichtigen Punkt von anderen Speichern wie beispielsweise den Disketten oder der Datenkassette. Es handelt sich hierbei um die Tatsache, daß ein auf EPROM gespeichertes Programm in der Regel die Anfangsadresse $8000 (dezimal 32768) hat. Wie kann man aber den Computer überlisten und ein Basic-Programm, das ja normalerweise ab $0801 (dezimal 2049) liegt, sofort nach dem Einschalten des Computers ohne weitere Befehle startet? Dafür gibt es prinzipiell zwei Lösungen. Die erste Möglichkeit besteht darin, den Basic-Start mit den Befehlen »POKE 44,128:Poke 32768,0:NEW« nach $8000 zu verschieben und ein Basic-Programm in diesem Speicherbereich laufenzulassen.

Diese Methode hat jedoch den entscheidenden Nachteil, daß dann für Programm und Variablen nur noch magere 8 KByte zur Verfügung stehen. Die zweite wesentlich elegantere Möglichkeit besteht darin, das auf EPROM gebrannte Basic-Programm nach dem Einschalten des Computers in den normalen Speicherbereich für Basic-Programme ab $0801 (dezimal 2049) zu verschieben. Es wird dann vom C 64 genauso behandelt, als ob es von einem externen Datenspeicher, wie dem Diskettenlaufwerk, geladen worden wäre. Ein automatisches Starten des Programms soll dabei natürlich nicht vergessen werden. Es versteht sich beinahe von selbst, daß diese Anforderungen nur in Maschinensprache zu realisieren sihd. Wir wollen nun gemeinsam ein entsprechendes Programm erarbeiten. Dazu ist zunächst die Betriebssystem-Routine zu betrachten, die beim Einschalten des C 64 beziehungsweise nach einem Reset durchlaufen wird (Listing 2). Für uns besonders interessant ist das Unterprogramm, das in der Speicherzelle $FCE7 beginnt. Dieses Unterprogramm prüft, ob ab Adresse $8005 die Zeichenfolge »CBM80« steht. Sollte dies der Fall sein, wird in der nächsten Zeile die Adresse angesprungen, die in $8000 und $8001 gespeichert ist. Das bedeutet für das Verschiebeprogramm, dafür zu sorgen, daß ab $8000 die Startadresse des Programms steht und ab $8005 die Zeichenfolge »CBM80« zu finden ist. Damit haben wir schon einmal das erste Problem gelöst, da nun beim Einschalten das Verschiebeprogramm angesprungen wird. Das nächste Problem ist die Durchführung der Reset-Routine. Das ist deshalb erforderlich, da sich der Computer nach dem Einschalten in einem völlig undefinierten Zustand befindet. Würde in diesem Zustand die Kontrolle an den Basic-Interpreter übergeben (was wir nach dem Verschieben des Basic-Programms ja vorhaben), wäre ein Systemabsturz die unweigerliche Folge. Das Verschiebeprogramm führt deshalb als nächstes dieselbe Initialisierungs-Routine durch, die das Betriebssystem des C 64 sonst automatisch ausführt. Anschließend gilt es dann, das Basic-Programm wieder an den Basic-Start nach $0801 zu verschieben. Dazu stellt der Basic-Interpreter bereits eine bestens geeignete Routine zur Verfügung. Diese Routine erwartet die Anfangsadresse des zu verschiebenden Bereichs in den Speicherzellen $5F/$60 (dezimal 95/96) in der Form Low-/High-Byte, die Endadresse in den Speicherzellen $5A/$5B (dezimal 90/91) und die Endadresse des Bereichs in den verschoben werden soll in $58/$59 (dezimal 88/89).

Schließlich gibt es noch zwei Speicherstellen in der Zeropage, die unsere Beachtung verdienen. Es sind die Zellen $2D/$2E (dezimal 45/46). Hier schaut der Interpreter später nach, wo das Basic-Programm aufhört, um nicht mit Variablenzuweisungen das Basic-Programm zu überschreiben. Beim Laden von der Diskette oder Kassette werden diese Speicherstellen automatisch auf die richtigen Werte gesetzt, in unserem Fall fällt diese Aufgabe dem Verschiebeprogramm zu. Nachdem wir die Blockverschieberoutine durchgeführt haben, könnte man bereits durch Sprung auf den Basic-Warmstart die Programm-Kontrolle an den Basic-Interpreter übergeben. Das Basic-Programm ist bereits list- und lauffähig. Es muß aber noch manuell mit RUN gestartet werden. Um auch dies dem Computer zu überlassen, brauchen wir vor dem Sprung auf den Basic-Warmstart lediglich noch den ASCII-Code für RUN und RETURN in den Tastaturpuffer schreiben und dem Interpreter mitteilen, daß im Tastaturpuffer ein zu verarbeitender Befehl steht. Der Tastaturpuffer beginnt bei $0277 (dezimal 631) und die Anzahl der Zeichen, die im Tastaturpuffer stehen, werden dem Computer über die Speicherstelle $00C6 (dezimal 198) mitgeteilt. Wenn der C 64 nun in den Direktmodus schaltet, verhält er sich genauso, als wenn Sie über die Tastatur »RUN« eingeben und die RETURN-Taste betätigt hätten. Damit ist das Verschiebeprogramm auch schon fertig. Bevor wir uns nun mit dem Problem beschäftigen, wie ein selbstgeschriebenes Basic-Programm zum Brennen auf EPROM in den Speicherbereich ab $805C (hinter das Verschiebeprogramm) kopiert wird, schauen Sie sich bitte zunächst das dokumentierte Listing des Verschiebeprogramms an (Listing 3). Bei den Werten in den Adressen $8045/$8049/$804D und $8053 handelt es sich um Platzhalter. Diese Werte werden später entsprechend der Länge des Basic-Programms verändert. Jetzt braucht man das eigentliche Programm nur noch an das Ende des Verschiebeprogrammes ab $805C zu kopieren, die Platzhalter im Verschiebeprogramm durch die richtigen Werte ersetzen und den EPROMmer anwerfen.

Bei eingestecktem EPROM wird dann das Basic-Programm direkt nach dem Einschalten des Computers oder nach einem Reset automatisch gestartet. Nun wäre es aber sehr mühsam, jedes Programm, das gebrannt werden soll, mit einem Monitor nach $805C zu verschieben. Genau diese Arbeit nimmt Ihnen das Programm »EPROM-Automat« (Listing 1) ab.

In diesem Programm finden Sie auch das eben entwickelte Maschinenprogramm in den DATA-Zeilen 2970 bis 3010 wieder. Die Bedienungsanleitung zu »EPROM-Automat« finden Sie in Bild 1. Betrachten wir uns die Zeilen 2650 bis 5010, die der eigentliche Hauptteil dieses Programms sind, etwas genauer. In diesen Zeilen wird das oben entwickelte Maschinenprogramm in den Speicherbereich ab $8000 geschrieben und dahinter das zu bearbeitende Basic-Programm kopiert. Nachdem man den Namen des zu bearbeitenden Programms eingegeben hat, wird in Zeile 2730 ein Lesekanal geöffnet. Danach werden die ersten beiden Byte dieser Programmdatei von der Diskette gelesen. Sie geben in der Form Low-/High-Byte die Startadresse des gespeicherten Programms an. Sollte die Startadresse nicht $0801 sein, springt das Programm sofort ins Menü zurück. Natürlich ist es theoretisch möglich, auch reine Maschinenprogramme, die an einer beliebigen Adresse beginnen und mit SYS (Startadresse) gestartet werden, mit dem EPROM-Automat zu bearbeiten. Dazu sind folgende Änderungen notwendig: Das Verschiebeprogramm muß so modifiziert werden, daß es nicht mehr mit RUN gestartet wird, sondern die Startadresse direkt mit JMP (Startadresse) angesprungen wird. Die Endadresse darf nicht mehr mit dem festen Offset 30811 (Zeile 2920) berechnet werden, sondern muß in Abhängigkeit von der Anfangsadresse des Programms ermittelt werden. Wenden wir uns der Zeile 2810 zu. In dieser Zeile wird das Maschinenprogramm in den richtigen Speicherbereich verschoben. Im Anschluß daran wird Byte für Byte das Basic-Programm dahintergeschrieben. Dabei wird immer wieder in Abhängigkeit vom Zähler »I« geprüft, ob das Programmende nicht über $A000 (dezimal 40960) hinausgeht. In diesem Fall käme man nämlich nicht mehr mit einem 8-KByte-EPROM aus. Wollen Sie jedoch auch 16-KByte-EPROMs brennen, müssen Sie außer dem Vergleichswert in Zeile 2850 auch noch das Verschiebeprogramm dahingehend modifizieren, daß es beim Kopieren des Basic-Programms den ROM-Bereich ab $A000 abschaltet, um den darunterliegenden RAM-Bereich lesen zu können. Weiterhin wäre es dann erforderlich, die PEEK-Funktion des C 64 dahingehend zu erweitern, daß sie in der Lage ist, auch den vom ROM überlagerten RAM-Bereich ab $A000 zu lesen.

Wollen Sie dagegen 4-KByte-EPROMs benutzen, müssen Sie lediglich den Wert in Zeile 2 850 von 40960 in 36864 ($9000) ändern oder selbst darauf achten, daß das Programm, das Sie bearbeiten wollen, nicht länger als 4 KByte ist. Wenn das Programmende erreicht ist, wird der Programmkanal in Zeile 2 890 wieder geschlossen und die Werte für die Speicherstellen $8046/$804A und $804E/$8054 werden berechnet. Sie erinnern sich, dort stehen bisher nur Platzhalter, die noch durch die richtigen Werte für den zu verschiebenden Ursprungs- und Zielbereich ersetzt werden müssen. Die Berechnung der Endadresse des Ursprungsbereiches ist relativ einfach. Dazu muß man lediglich den Zähler »I«, der ja mit dem Programmende im Speicher übereinstimmt, in Low- und High-Byte zerlegen. Aber auch die Berechnung der Endadresse des Zielbereichs ist nicht viel schwieriger. Dazu braucht man von »I« lediglich die Differenz zwischen der jetzigen Anfangsadresse ($805C) und der normalen Anfangsadresse ($0801) subtrahieren. Nun steht Ihr Basic-Programm brennfertig ab $8000 im Speicher. Nachdem Sie es auf EPROM gebrannt haben, bleibt noch ein kleines Problem. Beim Einschieben einer Modulplatine in den Expansion-Port des C 64 stehen für den Basic-Programmierer nur noch 30719 Byte zur Verfügung. Sollte Ihr Programm mit großen Variablenfeldern arbeiten, werden Sie die restlichen 8 KByte vielleicht auch noch benötigen. Sofern die Garantiezeit bei Ihrem Computer abgelaufen ist, öffnen Sie ihn einfach und bringen einen einfachen Ein-/Aus-Schalter an, der, wie in Bild 2 dargestellt, verdrahtet wird. Mit diesem Schalter können Sie dann bei Bedarf die Leitung EXROM, die bei eingesteckter Modulplatine normalerweise auf Masse liegt, freigeben und haben dann wieder den vollen Speicherbereich zur Verfügung. Noch ein Tip für diejenigen, die keinen EPROMmer besitzen. Auch sie können den EPROM-Automat sehr effektvoll einsetzen, da die präparierten Programme nach einem Reset automatisch wieder starten. In Ihrem Basic-Programm muß lediglich die Zeile: POKE 55,0:POKE 56,128:CLR enthalten sein.

Bild 2. Mit einem kleinen Trick lassen sich auch Module abschalten, das Bild wurde mit HI-EDDI erstellt.
(Dirk Gazic/aw)

Bedienungsanleitung für das Programm EPROM-Automat:

  1. Folgende Anforderungen muß das zu bearbeitende Programm erfüllen:
    1. Es muß mindestens eine Basic-Zeile enthalten.
    2. Es darf nicht länger als 8 KByte (32 Blöcke auf der Diskette) sein.
  2. Menü

    Nach dem Programmstart meldet sich der EPROM-Automat mit einem Menü. Sie können nun mit Hilfe der Cursorsteuertasten die einzelnen Optionen anwählen. Die jeweils angewählte Option wird dabei hervorgehoben. Durch Druck auf die RETURN-Taste wählen Sie dann den entsprechenden Programmteil aus. Sie haben im Hauptmenü zusätzlich die Möglichkeit, die eingestellten Bildschirmfarben zu verändern (F1 = Rahmen, F2 = Hintergrund, F3 = Schrift).

  3. Programme bearbeiten

    Geben Sie bitte den Namen des Programms ein, das Sie bearbeiten wollen. Fehlermeldungen werden gegebenenfalls in der unteren Statuszeile ausgegeben.

  4. Speicherinhalt sichern

    Dient zum Abspeichern von bearbeiteten Programmen auf Diskette. Sobald Sie diese Option angewählt haben, wird überprüft, ob Sie bereits ein Programm bearbeitet und dieses noch nicht gespeichert haben. Andernfalls werden Sie aufgefordert, einen Programmnamen anzugeben. Wenn Sie möchten, können Sie auch den vorgegebenen Namen übernehmen. Anschließend werden Sie gebeten, die Startadresse, ab der das Programm später geladen wird, einzugeben. Sollte die Steuersoftware für Ihren Eprommer bei $8000 liegen, so können Sie zum Beispiel »6« statt »8« eingeben.

  5. Directory zeigen

    Dieser Menüpunkt zeigt das Inhaltsverzeichnis der eingelegten Diskette. Dieser Vorgang kann jederzeit mit F1 abgebrochen werden. Die Funktionstaste F3 hält die Auflistung so lange an, bis eine beliebige Taste gedrückt wird.

  6. Programm beenden

    Diese Option beendet nach positiver Beantwortung der Sicherheitsabfrage, die Arbeit mit EPROM-Automat. Das zuletzt bearbeitete Programm bleibt dabei im weiterhin geschützten Speicherbereich ab $8000 erhalten und kann sofort auf ein EPROM gebrannt werden.

Bild 1. Bedienungsanleitung zum Programm »EPROM-Automat«
1 rem (c) 1985 by dirk gazic
2 rem             amsterdamer str. 41
3 rem             5000 koeln 90
4 rem             tel.:02203/32921
5 :
6 :
7 :
8 :
9 :
1000 rem initializierung ---------------
1010 :
1020 poke55,0:poke56,128:clr:dimze%(4),te$(4)
1030 hf=0:vf=0:sf=5:rem farbvorgabe
1040 printchr$(14)chr$(8)chr$(147)
1050 re$(0)="{rvof}":re$(1)="{rvon}"
1060 fori=1to4:readze%(i):readte$(i):next
1070 ei$="Ihre Eingabe Bitte >>>":rem haeufigste statuszeile
1080 data 8,"Programm bearbeiten"
1090 data10,"Speicherinhalt sichern"
1100 data 12,"Directory zeigen"
1110 data 14,"Programm beenden"
1120 goto2560:rem hauptprogramm
1130 :
1140 :
1150 :
1160 rem input-routine -----------------
1170 :
1180 poke204,0:poke205,2:wait207,1,1:poke204,1
1190 l=len(ww$):printww$;" {left}";:ifl>0thenforzz=1tol:print"{left}";:next:l=0
1200 poke204,0
1210 poke198,0:wait198,1:getw$
1220 poke205,2:wait207,1,1:poke204,1
1230 ifw$=chr$(29)andl<mxthen1300
1240 ifw$=chr$(157)andl>0thenl=l-1:printw$;:goto1200
1250 ifw$=chr$(13)then1320
1260 ifw$=chr$(20)andl>0then1350
1270 ifasc(w$)<32orasc(w$)=34then1200
1280 ifw$="*"orw$=";"orw$=","then1200
1290 ifasc(w$)>127andasc(w$)<160then1200
1300 l=l+1:printw$;:ifl<mxthen1200
1310 l=mx-1:print"{left}";:goto1200
1320 ifl>0thenforzz=1tol:print"{left}";:next
1330 ww$="":open3,3:forzz=1tomx:get#3,w$:ww$=ww$+w$:next:close3
1340 return
1350 ifl=0then1200
1360 gosub1320
1370 forzz=1tomx:print"{left}";:next
1380 ifl=1thenww$=mid$(ww$,2):goto1190
1390 ww$=left$(ww$,l-1)+mid$(ww$,l+1):printww$;" ";
1400 forzz=1tomx-l+1:print"{left}";:next
1410 l=l-1:goto1200
1420 :
1430 :
1440 :
1450 rem leerstellen entfernen ---------
1460 :
1470 l1=len(ww$):ifl1=0thenreturn
1480 l2=asc(right$(ww$,1)):ifl2<>32andl2<>160thenreturn
1490 ww$=left$(ww$,l1-1):goto1470
1500 :
1510 :
1520 :
1530 rem untere statuszeile ------------
1540 :
1550 i=int((39-len(an$))/2)
1560 an$=left$("                                    ",i)+an$
1570 poke214,23:sys58640:print:print"{rvon}                                       {rvof}";
1580 poke214,23:sys58640:print:print"{rvon}";an$"{rvof}";
1590 poke2023,160:poke56295,peek(646)
1600 return
1610 :
1620 :
1630 :
1640 rem obere statuszeile -------------
1650 :
1660 print"{home}{rvon}                                        {rvof}"
1670 i=int((39-len(an$))/2)
1680 an$=left$("                                    ",i)+an$
1690 print"{home}{rvon}";an$;"{rvof}"
1700 return
1710 :
1720 :
1730 :
1740 rem fehlerton ---------------------
1750 :
1760 si=54272
1770 for i=0 to 23:poke i+si,0:next
1780 pokesi+1,7:pokesi+5,60:pokesi+24,15:pokesi+2,50:pokesi+3,15:pokesi+4,65
1790 return
1800 :
1810 :
1820 :
1830 rem disk-fehler -------------------
1840 :
1850 input#1,ff$,fe$,tt$,ss$
1860 iffe$="ok"thenreturn
1870 an$=ff$+","+fe$+","+tt$+","+ss$
1880 gosub1530
1890 ifff$="74"thenprint#1,"uj":fori=1to3000:next
1900 gosub1740:poke198,0:wait198,1
1910 return
1920 :
1930 :
1940 :
1950 rem directory ---------------------
1960 :
1970 open1,8,15,"i":gosub1830:close1:iffe$<>"ok"thenreturn
1980 print"{clr}";:re=0
1990 open1,8,0,"$0"
2000 get#1,a$,b$
2010 get#1,a$,b$
2020 get#1,a$,b$
2030 getq$:ifq$="{f1}"thenclose1:return
2040 ifq$="{f3}"thenwait198,1:poke198,0
2050 print"{rvof}";
2060 c=0
2070 if a$<>"" then c=asc(a$)
2080 if b$<>"" then c=c+asc(b$)*256
2090 printmid$(str$(c),2);:poke211,4
2100 ifre=0thenprint"{rvon}";
2110 get#1,b$:if st<>0 then 2220
2120 if b$<>chr$(34) then 2110
2130 printchr$(34);
2140 get#1,b$:printb$;:ifb$<>chr$(34)then2140
2150 print"  ";
2160 get#1,b$:if b$=chr$(32) then 2160
2170 poke211,24:c$=""
2180 c$=c$+b$:get#1,b$:ifb$<>""then 2180
2190 ifleft$(c$,1)="*"thenpoke211,23
2200 printc$
2210 if st=0 then re=1:goto 2010
2220 print"blocks free"
2230 close1
2240 an$="'TASTE' fuer Rueckkehr ins Menue":gosub1530
2250 poke198,0:wait198,1
2260 return
2270 :
2280 :
2290 :
2300 rem menuesteuerung ----------------
2310 :
2320 print"{clr}":poke646,sf
2330 an$=nm$:gosub1640
2340 an$="Waehlen mit CURSOR und RETURN":gosub1530
2350 gosub2510:re=1:gosub2500
2360 poke53280,hf:poke53281,vf
2370 poke198,0:wait198,1:getq$
2380 ifq$=chr$(13)thenreturn
2390 ifq$="{up}"andze>1thenre=0:gosub2500:ze=ze-1:re=1:gosub2500:goto2360
2400 ifq$="{up}"thenre=0:gosub2500:ze=4:re=1:gosub2500:goto2360
2410 ifq$="{down}"andze<4thenre=0:gosub2500:ze=ze+1:re=1:gosub2500:goto2360
2420 ifq$="{down}"thenre=0:gosub2500:ze=1:re=1:gosub2500:goto2360
2430 ifq$="{f1}"andhf<255thenhf=hf+1:goto2360
2440 ifq$="{f1}"thenhf=0
2450 ifq$="{f3}"andvf<255thenvf=vf+1:goto2360
2460 ifq$="{f3}"thenvf=0
2470 ifq$="{f5}"andsf<15thensf=sf+1:goto2300
2480 ifq$="{f5}"thensf=0:goto2300
2490 goto2360
2500 poke211,8:poke214,ze%(ze):sys58640:printre$(re)te$(ze):return
2510 fori=1to4:poke211,8:poke214,ze%(i):sys58640:printte$(i):next
2520 return
2530 :
2540 :
2550 :
2560 rem hauptprogramm -----------------
2570 :
2580 nm$=" Auto.Eprom V1.2      (c) by Dirk Gazic"
2590 ze=1:gosub2300
2600 onzegosub2650,3050,1950,3270
2610 goto2560
2620 :
2630 :
2640 :
2650 rem programm bearbeiten -----------
2660 :
2670 an$="Modus: Programm bearbeiten":gosub1640
2680 an$=ei$:gosub1530:ww$=""
2690 print"{home}{down}{down}{down}{down}{down}{down}{down}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{CBM-A}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{CBM-S}"
2700 print"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{SHIFT--}Filename:                 {SHIFT--}"
2710 print"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{CBM-Z}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{CBM-X}"
2720 print"{up}{up}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}";:mx=16:gosub1160:gosub1450:na$=ww$
2730 open1,8,15:open2,8,0,na$
2740 gosub1830:iffe$<>"ok"thenclose1:close2:return
2750 get#2,lb$:get#2,hb$
2760 ifasc(lb$+chr$(0))=1andasc(hb$+chr$(0))=8then2790
2770 an$="Programmstart ist nicht $0801":close1:close2:gosub1740:gosub1530
2780 poke198,0:wait198,1:return
2790 restore
2800 an$="Bitte warten":gosub1530
2810 fori=1to4:reada:reada$:next
2820 fori=32768to32859:reada:pokei,a:next
2830 get#2,a$:a$=a$+chr$(0)
2840 pokei,asc(a$)
2850 i=i+1:ifi<40960orst=64then2880
2860 an$="Programm ist zu lang":close1:close2:gosub1740:gosub1530
2870 poke198,0:wait198,1:return
2880 ifst<>64then2830
2890 close1:close2
2900 hb=int(i/256):lb=i-hb*256
2910 poke32838,lb:poke32842,hb
2920 i1=i-30811:i2=i
2930 hb=int(i1/256):lb=i1-hb*256
2940 poke32846,lb:poke32852,hb
2950 return
2960 :
2970 data9,128,9,128,195,194,205,56,48,120,142,22,208,32,163,253,32,80,253,32
2980 data21,253,32,91,255,88,32,83,228,32,191,227,32,61,128,162,251,154,169
2990 data82,141,119,2,169,213,141,120,2,169,13,141,121,2,169,3,141,198,0,76
3000 data134,227,169,92,133,95,169,128,133,96,169,110,133,90,169,128,133,91
3010 data169,20,133,88,133,45,169,8,133,89,133,46,76,191,163
3020 :
3030 :
3040 :
3050 rem speicherinhalt sichern --------
3060 :
3070 ifi2=0thengosub1740:return
3080 an$="Modus: Speicherinhalt sichern":gosub1640
3090 an$=ei$:gosub1530
3100 print"{home}{down}{down}{down}{down}{down}{down}{down}{down}{down}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{CBM-A}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{CBM-S}"
3110 print"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{SHIFT--}Filename:                 {SHIFT--}"
3120 print"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{CBM-Z}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{SHIFT-*}{CBM-X}":ww$="modul."+na$
3130 ww$=left$(ww$,16):print"{up}{up}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}";:mx=16:gosub1160:gosub1450
3140 open1,8,15:open2,8,1,ww$
3150 gosub1830:iffe$<>"ok"thenclose1:close2:return
3160 print"{home}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{SHIFT--}Startadresse:   * 4096    "
3170 ww$=mid$(str$(8),2):print"{up}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}";:mx=1:gosub1160
3180 ad=val(ww$):ifad<1orad>8thengosub1740:goto3160
3190 ad=ad*4096:hb=int(ad/256):lb=ad-hb*256
3200 print#2,chr$(lb)chr$(hb);
3210 an$="Bitte warten":gosub1530
3220 fori=32768toi2:print#2,chr$(peek(i));:next
3230 gosub1830:close1:close2:i2=0:return
3240 :
3250 :
3260 :
3270 rem programm beenden --------------
3280 an$="Modus: Programm beenden":gosub1640
3290 an$="Wollen Sie wirklich beenden [j/n]":gosub1530:poke198,0:wait198,1:getq$
3300 ifq$="n"thenreturn
3310 ifq$<>"j"then3290
3320 print"{clr}":ifi1=0then3340
3330 print"Bearbeitetes Programm steht ab $8000    Epromfertig im Speicher"
3340 new
Listing 1. EPROM-Automat — ein komfortables Programm zur Modulherstellung. Bitte beachten Sie die Eingabehinweise auf Seite 54.
FCE2 LDX &FF
FCE4 SEI
FCE5 TXS
FCE6 CLD
FCE7 JSR FD02   prüft auf ROM in $8000
FCEA BNE FCEF   Sprung wenn kein Autostart-Modul
FCEC JMP (8000) Sprung auf Modul-Start
FCEF STX D016   Ab hier folgt der eigentliche Reset
FCF2 JSR FDA3
FCF5 JSR FD50
FCF8 JSR FD15
FCFB JSR FF5B
FCFE CLI
FCFF JMP (A000) Sprung zum BASIC Kaltstart
Listing 2. Diese Betriebssystem-Routine prüft, ob ein Modul eingesteckt ist.
8000 .byte 09 Startadresse des Verschiebeprogramms (Lowbyte)
8001 .byte 80 Startadresse des Verschiebeprogramms (Highbyte)
8002 .byte 09 Neuer NMI-Vektor (Lowbyte)
8003 .byte 80 Neuer NMI-Vektor (Highbyte)
8004 .byte C3 ''C''
8005 .byte C2 ''B''
8006 .byte CD ''M''
8007 .byte 38 ''8''
8008 .byte 30 ''0''
8009 SEI
800A STX D016
800D JSR FDA3 Interrupt vorbereiten
8010 JSR FD50 Arbeitsspeicher initialisieren
8013 JSR FD15 Hardware und I/O Vektoren setzen
8016 JSR FF5B Video-Reset
8019 CLI
801A JSR E453 Basic-Vektoren laden
801D JSR E3BF RAM für Basic initialisieren
8020 JSR 803D Basic-Programm verschieben
8023 LDX #FB
8025 TXS
8026 LDA #52 Code für »r«
8028 STA 0277
802B LDA #D5 Code für »U«
802D STA 0278
8030 LDA #0D Code für RETURN
8032 STA 0279
8035 LDA #03 3 Zeichen im Tastaturpuffer
8037 STA 00C6
803A JMP E386 Sprung zum Basic-Warmstart
803D LDA #5C Anfangsadresse des zu verschiebenden Bereiches (Lowbyte)
803F STA 005F
8041 LDA #80 Anfangsadresse des zu verschiebenden Bereiches (Highbyte)
8043 STA 0060
8045 LDA #6E Endadresse des zu verschiebenden Bereiches (Lowbyte)
8047 STA 005A
8049 LDA #80 Endadresse des zu verschiebenden Bereiches (Highbyte)
804B STA 005B
804D LDA #14 Endadresse des Zielbereiches (Lowbyte)
804F STA 0058
8051 STA 002D Basic-Ende setzen (Lowbyte)
8053 LDA #08 Endadresse des Zielbereiches (Highbyte)
8055 STA 0059
8057 STA 002E Basic-Ende setzen (Highbyte)
8059 JMP A3BF Sprung zur Blockverschiebroutine
Listing 3. Dieses Programm muß vor jedem Basic-Programm im EPROM stehen
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →