C 64
Hardware

Nichts ist ewig

Zugegeben, der Commodore 64 hat einige Nachteile. Aber warum sollte man sich damit abfinden? Alles kann mit dem ROM-Change-Programm verändert werden.

Bild 1. Die Steckplätze U3 bis U5

Jedem Computer, auch dem Commodore 64 wird ab Werk eine bestimmte Ausstattung an Software mit auf den Weg gegeben. Damit ist nicht die Demo-Diskette gemeint, sondern die fest im Computer eingebaute, auf PROMs gespeicherte Firmware. Sie sorgt dafür, daß der Commodore überhaupt auf Eingaben reagiert oder einen Basic-Befehl ausführt.

Der gesamte C 64 (und jeder andere Computer) ist eigentlich nichts anderes als eine Anzahl miteinander verdrahteter Baugruppen, die allein zu nichts fähig sind. Leben eingehaucht wird dem ganzen erst durch ein sehr wichtiges Programm, das sogenannte Betriebssystem. Dieses Programm initialisiert und verwaltet die gesamte Hardware. Beim Commodore 64 ist es genau 8 KByte lang und liegt im Bereich von $E000 bis $FFFF. Der zweite wichtige Festwertspeicher ist der Basic-Interpreter. Er ist ein Übersetzungsprogramm, das eine Anweisung in ein maschinengerechtes Signal umwandelt. Auch der Interpreter benötigt 8 KByte und liegt im Bereich von $A000 bis $C000. Jetzt fehlt nur noch der Charakter-Set von 4 KByte, der ebenfalls in einem eigenen ROM untergebracht ist.

Diese drei Programme sind für das äußere Erscheinungsbild und die Funktionalität des Commodore 64 verantwortlich. Hier eröffnet sich ein extrem interessanter Bereich der Programmierung. Dazu bieten sich zwei Wege an: Der erste Weg beruht auf der glücklichen Tatsache, daß es beim Commodore möglich ist, den RAM-Bereich unter einem ROM zu nutzen. In der Praxis sieht das folgendermaßen aus: Die Speicherinhalte des ROMs werden zum Bearbeiten in den darunter liegenden RAM-Bereich kopiert. Ob nun das RAM oder das ROM aktiv ist, entscheidet das 6510 Datenrichtungsregister (Speicherstelle 1). Vom Basic aus ist dieses Register allerdings nur dann zu verändern, wenn sowohl der Basic-Interpreter, als auch das Betriebssystem in das RAM kopiert wurden. Das geschieht entweder mit einer POKE-Schleife oder mit dem ROM-Change Programm. (Betriebssystem kopieren: FOR A = 57344 TO 65535: POKE A,PEEK (A): NEXT)

(Basic kopieren: FOR A = 40960 TO 49152: POKE A, PEEK (A) : NEXT). Der Normalwert dieses Registers ist 55 (probieren Sie es aus). Soll das RAM (für Basic) selektiert aktiv sein, muß hier der Wert 54 eingeschrieben werden. Für Basic und Betriebssystem zusammen beträgt der Wert 53. Alle Veränderungen des Basic und Betriebssystems sind dann aktiv. Bekannte Programme wie Quickcopy und viele Basic-Erweiterungen funktionieren nach diesem Prinzip.

Der zweite und wesentlich reizvollere Weg die Firmware zu beeinflussen ist, das Betriebssytem dauerhaft zu verändern. Dazu ist aber ein Eingriff im Computer notwendig, denn die oben beschriebenen Bausteine müssen gegen andere ausgetauscht werden. Wer also noch Garantie auf seinen Commodore hat, sollte besonders vorsichtig sein. Im ersten Teil dieses Artikels wollen wir, zum Einüben sozusagen, die Funktionstasten des Commodore 64 mit bestimmten, oft gebrauchten Werten belegen. Im zweiten Teil wird das Hypra-Load aus der Ausgabe 10/84 im Betriebssytem verankert. Der Nachteil dieser Änderungen soll nicht verschwiegen werden. Da alle neuen Funktionen natürlich Speicherplatz benötigen, müssen andere Teile des Betriebssystems entfallen. Wir haben uns entschlossen, die Kassettenroutinen ab $F800 herauszunehmen und zu überschreiben. Das Laden von Kassette wird dadurch unmöglich, es sei denn, das alte Betriebssystem wird parallelgeschaltet.

Bild 2. Der 2764 (links) und der 2364 (rechts)

Bevor wir nun auf das Hilfsprogramm für diese Veränderungen, das ROM-Change-Programm, eingehen, sollen die Hardware-Voraussetzungen für die Änderung des Betriebssystems erklärt werden. Nach dem Öffnen des Computers finden wir auf der linken hinteren Seite drei kleine Bausteine, hinter denen auf der Platine die Bezeichnungen U3 bis U5 stehen. U3 ist der Basic-Interpreter, U4 das Betriebssytem, U5 das Charakter-ROM (Bild 1). Heute interessieren wir uns aber nur für den U4-Steckplatz. Wer Glück hat, findet dort einen Stecksockel. Wer Pech hat, muß seinen Händler oder einen Lötkolbenfachmann bitten, ihm hier einen Stecksockel einzulöten. Anstelle des dort befindlichen ROMs kann aber, und das ist die wesentlichste Veränderung, auch ein EPROM stecken. Am besten eignen sich hierzu die 2564-Typen, denn sie sind pinkompatibel zu den Commodore-ICs. Leider sind sie sehr schwer zu beschaffen. Im Normalfall wird aber wahrscheinlich ein 2764-EPROM Verwendung finden. Der Nachteil dieses EPROMs besteht in einer anderen Belegung der Anschlußpins. Hier hilft allerdings ein einfacher Adaptersockel. Dazu braucht man einen 24- und einen 28-Pin-Stecksockel. Diese beiden Sockel werden miteinander verdrahtet (Bild 2 und 3). Bild 2 zeigt die beiden Sockel mit den Beinen nach unten stehend. Der kleine Sockel steckt später im U4-Steckplatz, der größere Sockel trägt das geänderte Betriebssystem und steckt auf dem kleineren Sockel. Vor dem Einbau ist es aber ratsam, alle Kontakte auf richtigen Anschluß und Leitfähigkeit zu überprüfen. Schon ein einziger falscher Anschluß führt zum »Absturz« des gesamten Systems. Bild 4 zeigt, wie der neue Sockel mit der EPROM-Kerbe zur Gehäuse-Rückseite auf der Platine steht.

Nun aber zur Praxis, dem ROM-Change-Programm. Es ermöglicht das gefahrlose Ändern und Ausprobieren aller Umprogrammierungen. Dazu wird nach dem Start der selektierte ROM-Bereich (Betriebssytem oder Basic) ab Adresse $6000 ins RAM kopiert. Das geschieht mit einem kurzen Maschinenprogramm, das im Kassettenpuffer steht. Das Programm ist für den Betrieb mit einem Diskettenlaufwerk gedacht, läuft aber auch im Kassettenbetrieb, wenn ein eigener Monitor zum Laden und Abspeichern Verwendung findet. Nach dem Kopieren erscheint das Hauptmenü, von dem aus alle wichtigen Funktionen erreichbar sind. Die erste dient dem Einlesen von fest im Programm eingebauten DATA-Zeilen. In unserem Beispiel sind ab Zeilennummer 8000 die DATAs für die Funktionstasten einprogrammiert. Hier können natürlich auch eigene Werte stehen. Die erste Zahl gibt dabei die reelle Adresse an, ab der die DATAs geschrieben werden sollen (zum Beispiel 57612 = $E10C). Der Computer errechnet dann die entsprechende Stelle im RAM. Die zweite Zahl gibt an, wieviel Bytes übertragen werden sollen. Die dritte Zahl ist die Prüfsumme. Danach folgen die Programm-DATAs. Bei einem Prüfsummenfehler zeigt der Computer die falsche Prüfsumme an. Eigene Daten werden einfach an die vorhandenen DATAs angehängt. Die ersten drei Bytes müssen natürlich auch die obige Bedeutung haben. Als letzte Zeile muß stehen: DATA 0, da es sonst zu einem OUT OF DATA ERROR kommt. Der zweite Menüpunkt liest Maschinenprogramme direkt an die vorgesehene Stelle. Damit kann man beispielsweise ein Programmfile, das von einem Assembler erzeugt wurde, direkt einlesen. Wichtig ist, daß die Startadresse des Programms im ROM-Adreßbereich beziehungsweise im Bereich $6000 liegt. Der mit Punkt 3 wählbare Minimonitor hilft beim schnellen Ändern einzelner Bytes im hexadezimalen Zahlensystem. Die Startadresse entspricht dabei der Adresse im ROM. Der Minimonitor wird durch Eingabe einer Zahl größer $FF oder des Buchstabens X verlassen. Will man keine Speicherstelle ändern, genügt RETURN für die Übernahme des alten Wertes. Für größere Änderungen reicht dieser Minimonitor natürlich nicht mehr aus. Dazu wird mit Punkt 4 ein eigener Monitor aktiviert. Dieser muß allerdings vor dem Start des ROM-Change-Programms bereits geladen sein. Der Monitor darf im Bereich von $8000 bis $9FFF oder von $C000 bis $CFFF stehen. Zum Starten genügt das Eingeben der Startadresse des Monitors hexadezimal!). Mit den Menüpunkten 5 und 6 wird der Speicherbereich von $6000 bis $7FFF geladen beziehungsweise abgespeichert. Das Laden eines kompletten Betriebssystems dauert allerdings mehrere Minuten. Einer der wichtigsten Menüpunkte ist aber der siebte. Er startet das gerade veränderte oder geladene neue Betriebssystem (es wird natürlich zuerst in seinen richtigen Speicherbereich verschoben). Vor dem Ausprobieren dieser Funktion muß in jedem Fall der Punkt 5 angewählt werden, wenn die Änderungen nicht verlorengehen sollen. Es kann vorkommen, daß das Betriebsystem beim Starten »abstürzt«. Dann genügt ein RESET und die erneute Aktivierung des geänderten ROMs durch POKE 1,53.

2764 2364
1,28,27,26 24
2 21
3 1
4 2
5 3
6 4
7 5
8 6
9 7
10 8
11 9
12 10
13 11
14 12,20
15 13
16 14
17 15
18 16
19 17
20,14 nicht angeschl.
21 19
22 20
23 18
24 22
25 23
1,28,27,26 24
Bild 3. So wird der 2764 mit den Pins des 2364-Sockels verbunden

Sind alle Tests im RAM positiv verlaufen, können wir uns an die Speicherung des neuen Betriebssytems auf EPROMs heranwagen. Das neue Betriebssystem wird von Diskette in den RAM-Bereich ab $6000 absolut, das heißt mit LOAD"Ihr Betriebssytem",8,1 geladen. Ab dieser Adresse beginnt auch die Programmierung des EPROMs. Sie endet bei $8000 (8 KByte). Das neue EPROM wird anschließend in den beschriebenen Stecksockel eingesetzt und in Steckplatz U4 befestigt. Fertig ist das Betriebssytem.

Was noch zu klären bleibt, ist die im ROM-Change-Programm bereits eingebaute Funktionstastenbelegung. Die Abfrage der Tastatur geschieht im Betriebssytem über den Interrupt. Wird eine Taste gedrückt, hält der Prozessor das laufende Programm an und springt in die Interrupt-Unterroutine bei $EA31. Dort wird festgestellt, welche Taste gedrückt wurde. Der ASCII-Code der Taste wird im Tastaturpuffer gespeichert. Das Funktionstastenprogramm greift an dieser Stelle ein, indem es den Wert der gedrückten Tasten mit den ASCII-Codes für die Funktionstasten (133-140) vergleicht. Stimmt der Wert nicht überein, so wird das Programm normal weitergeführt. Ansonsten vergleicht das Programm den Tastenwert mit einer Tabelle, in der die Belegungen für die Funktionstasten stehen. Hat das Programm die zur Funktionstaste gehörige Belegung gefunden, wird diese in den Tastaturpuffer geschrieben. Damit auch Programme, die auf einer Abfrage der Funktionstaste aufbauen, funktionieren, wurde eine Autoabschalt-Unterroutine mitprogrammiert. Kommt es dennoch einmal zu Schwierigkeiten, werden die Funktionstasten mit POKE 2,1 abgeschaltet und mit POKE 2,0 wieder aktiviert.

Abschließend sei nochmals darauf hingewiesen, daß alle Arbeiten an der Hardware des C 64 mit einem nicht geringen Zerstörungsrisiko verbunden sind. Wer also im Umgang mit Lötkolben und EPROMs nicht geübt ist, sollte sich an einen Fachmann wenden.

(Arnd Wängler/Ernst Schöberl/aa)
Bild 4. Das EPROM 2754 zweifach »gesockelt«

Beim Abtippen des Programms sind die Werte in Klammern am Ende einer Zeile nicht miteinzugeben. Sie sind erst für eine spätere Ausgabe von Bedeutung. Unterstrichene Buchstaben sind mit der Shift-Taste, überstrichene mit der Commodore-Taste einzugeben. Bei Ausdrücken in eckigen Klammern ist die jeweilige Taste zu drücken.

100 rem speicherplatz fuer rom vor basic schuetzen
110 poke 55,0:poke 56,96:clr
120 poke 53272,23:poke 53280,2
130 gosub 1130
140 if peek(53247)<>33 then 160
150 if peek(53246)=0 then gosub 3600:goto 500
155 gosub 3700:goto 500
160 print"{down}{down}":print" Druecken sie":print
170 print:print tab(7);"1  um Kernal ($E000-$FFFF)"
180 print:print tab(7);"2  um Basic ($A000-$BFFF)"
190 print:print:print tab(11);"in RAM ab $6000 zu kopieren."
200 get a$:if a$=""then 200
210 if a$="1"then poke 32767,255:gosub 3600:goto 240
220 if a$<>"2"then 200
230 gosub 3700
240 gosub 1600
300 poke k+8,int(an/256)
310 poke k+29,int(en/256)
340 sys k :rem schieberoutine
500 poke 53280,5:gosub 1130:print:poke 53247,0
505 print:print:print"      Erweiterung des ROMs durch":print
506 print tab(8);"1: Data Zeilen einlesen"
510 print tab(8);"2: Programm von Disk"
520 print tab(8);"3: Hexmonitor"
530 print tab(8);"4: Eigenen Monitor"
540 print tab(8);"5: Abspeichern des neuen ROMs"
545 print tab(8);"6: Laden von geaendertem ROM"
546 print tab(8);"7: Starten des neuen ROMs"
547 print tab(8);"8: Programm beenden"
550 print:print:print tab(10);"Bitte waehlen sie!"
560 get a$:if a$=""then 560
570 i=val(a$):if i<1 or i>8 then 560
580 on i goto 1000,2000,3000,4000,5000,6000,2500,3500
999 rem data zeilen einlesen
1000 print"{clr}":print:print tab(10);"Lesen der Data-Zeilen":print:print
1010 gosub 1600
1020 read a:if a=0 then 500
1030 read b:rem anzahl der bytes
1032 read p1:rem pruefsumme
1033 p2=0
1035 d=a:gosub 1300:print"$";a$;"-";:d=a+b-1:gosub 1300:print"$";a$;
1040 for i=a-of to a-of-1+b
1050 read d:poke i,d
1051 p2=p2+d:if p2>65535 then p2=p2-65536
1053 next i
1055 if p2<>p1 then 1070
1057 print"   ok"
1060 goto 1020
1070 print"pruefsumme falsch: ";p2
1080 get a$:if a$=""then 1080
1090 goto 1020
1100 stop
1130 print"{clr}":print tab(8);"Programm zum Aendern des":print
1140 print tab(12)"Betriebssystems":print:print
1150 print" geschrieben von Ernst Schoeberl (1984)"
1160 return
1199 rem hex in dez umwandlung
1200 d=0:for j1=0 to len(a$)-1
1210 b=asc(right$(a$,1)):a$=left$(a$,len(a$)-1)
1220 b=b-48:if b>9 then b=b-7
1230 if b<0 or b>16 then 1280
1240 d=d+b+16^j1
1250 next j1
1260 return
1280 d=-1:return
1299 rem dez in hex
1300 j2=int(log(d)/log(16)):a$=""
1310 for j1=j2 to 0 step-1
1320 k1=int(d/16^j1):d=d-k1*16^j1
1330 if k1>9 then k1=k1+7
1340 k1=k1+48:a$=a$+chr$(k1)
1350 next j1
1360 return
1600 restore:k=828:for i=k to k+32:read a:poke i,a:next i
1610 data 120,160,0,132,251,132,253,169,224,133,252,169,96,133,254,177,251,145
1620 data 253,200,208,249,230,252,230,254,165,252,201,0,208,239,96
1630 return
1999 rem programm von disk in rom einfuegen
2000 gosub 1130:print
2010 print tab(2);"Einfuegen eines Programms von Disk"
2020 print:print:print:input"Filename:";a$
2030 open 1,8,0,a$
2033 gosub 6100:i=asc(a$):gosub 6100:i=i+256*asc(a$):if st>0 then 6200
2035 print:print"found ";a$
2036 if i<an then 2110
2040 get#1,a$:a$=a$+chr$(0)
2050 if st>0 then 2100
2060 poke i-of,asc(a$):i=i+1:goto 2040
2100 close 1:goto 500
2109 rem programm nicht in rombereich
2110 print"ROM von $";:d=an:gosub 1300:print a$;"-";:d=an+8191:gosub 1300:print a$
2120 print"Startadresse des Programms bei $";:d=i:gosub 1300:print a$
2130 input"Neue Startadresse (muss im ROM-Bereich liegen:";a$
2140 gosub 1200:if d=-1 or d<an then 2100
2150 i=d:goto 2040
2499 rem rom starten
2500 gosub 1600
2510 poke k+8,160:poke k+29,0
2515 poke k+12,160
2520 sys k
2525 k=828
2530 poke k+8,96
2540 poke k+9,128
2550 poke k+12,int(an/256)
2560 sys k
2565 print"{clr}":print">Neues Rom aktiviert":print
2570 poke 1,53:input"Reset (j/n)";a$:if a$="j"then sys 64738
2580 goto 500
2999 rem monitor fuer einzelne speicherstellen
3000 print"{clr}":print"*** Monitor {SHIFT-*}{SHIFT-*}{SHIFT-*}":print:print
3010 input"Startadresse:";a$:gosub 1200
3020 i=d-of:if i=-1 then 3010
3030 d=i+of:gosub 1300:print a$;" ";:d=peek(i):gosub 1300:print a$;"    ";
3040 input":";a$
3050 if a$=chr$(13)then 3070
3060 gosub 1200:if d=-1 or d>255 then 3090
3065 poke i,d
3070 i=i+1:goto 3030
3090 print"Ende (j/n)"
3095 get a$:if a$="n"then 3010
3096 if a$<>"j"then 3095
3100 goto 500
3500 poke 53247,0:end
3599 rem werte fuer kernal ram
3600 an=14*4096:en=0:of=8*4096:poke 53246,0:return
3699 rem werte fuer basic rom
3700 an=10*4096:en=12*4096:of=4*4096:poke 53246,1:return
3999 rem eigener monitor
4000 print"{clr}":print:print"       Eigener Monitor"
4010 print:print:input"startadresse (hex):";a$
4020 if len(a$)>4 then 4000
4030 gosub 1200:if d=-1 then 4000
4040 sys d
4050 goto 500
4999 rem abspeichern des roms
5000 gosub 1130:print
5010 print tab(7);"Abspeichern des neuen ROMs"
5020 print:print:print:input"Filename:";a$
5030 open 1,8,1,a$
5035 print:print"saving ";a$
5040 print#1,chr$(0);chr$(96);
5050 for i=6*4096 to 32767
5060 print#1,chr$(peek(i));:next i
5070 print#1,chr$(an-int(an/256)*256);
5080 print#1,chr$(an/256)
5090 close 1:goto 500
5999 rem geaendertes rom laden
6000 gosub 1330:print
6010 print tab(10);"Laden eines neuen ROMs"
6020 print:print:print:input"Filename:";a$
6030 open 1,8,0,a$
6040 gosub 6100:gosub 6100
6042 if st>0 then 6200
6043 print:print"loading ";a$
6050 for i=6*4096 to 32767
6060 get#1,a$:a$=a$+chr$(0)
6070 poke i,asc(a$):next i
6080 gosub 6100:an=asc(a$):gosub 6100:an=an+256*asc(a$)
6090 of=an-6*4096:en=an+8192:close 1
6095 if en>65535 then en=0
6096 if an<14*4096 then poke 53246,1:goto 500
6097 poke 53246,0:goto 500
6100 get#1,a$:a$=a$+chr$(0):return
6200 close 1:print
6210 open 1,8,15
6220 if st=64 then 6250
6230 get#1,a$:print a$;:goto 6220
6250 close 1
6260 get a$:if a$=""then 6260
6270 goto 500
7990 rem ab hier datas
8000 data 64226,126,14014
8001 data 232,134,198,201,133,144,4,201,141,144,3,76,66,235,157,119,2,72,152
8002 data 72,160,0,196,2,208,13,185,41,251,221,119,2,240,11,200,192,176,208
8003 data 243,104,168,104,76,66,235,200,185,41,251,201,133,144,4,201,141,144
8004 data 238,236,137,2,176,233,157,119,2,232,134,198,76,15,251,133,76,207
8005 data 34,36,34,44,56,13,137,76,79,65,68,134,76,73,83,84,13,138,83,65,86
8006 data 69,135,82,85,78,13,139,83,89,83,136,63,70,82,69,40,48,41,13,140,83
8007 data 89,83,54,52,55,51,56,13,133,136
8010 data 60223,3,552
8011 data 76,226,250
10000 data 0
Listing »ROM-Change«
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →