Der Erste Schritt bei der Multiplattform-Programmierung besteht im Erkennen des Computersystems. Denn bei aller Ähnlichkeit zwischen den Commodore 8-Bit-Rechnern, gibt es doch genügend Unterschiede, die es zu beachten gilt. Zur Unterscheidung sind spezifische und unverwechselbare Kriterien heranzuziehen. Ein Beispiel für eine automatische Rechnererkennung ist die Routine die sauhund im Forum64 gepostet hat.
Wenn man auf Details, wie den RAM-Ausbau beim VC20 oder die Unterscheidung zwischen C16 und Plus4 verzichten kann, geht es aber auch einfacher. Statt diverse Adressen zu prüfen, genügt es, sich auf eine zu beschränken, die bei allen Rechnern unterschiedlich ausfällt aber bei allen ROM-Varianten identisch ist. Eine vertiefende Analyse läßt sich dann in den erforderlichen Fällen noch nachträglich durchführen.
Am Ende des ROMs finden sich gleich zwei geeignete Kandidaten für einen Rechnercheck. Nach meinen bisherigen Recherchen sind IRQ- (Puls) und RESET-Vektor bei jedem Commodore-Rechner unterschiedlich jedoch für verschiedene ROM-Versionen eines Rechners immer identisch. Zur Identifizierung genügt es, das Low-Byte des Vektors zu prüfen. Ich persönlich bevorzuge dabei den IRQ-Vektor, für irgendetwas muss man sich ja mal entscheiden.
Computer |
IRQ |
LB (hex) |
LB (dez) |
RESET |
LB (hex) |
LB (dez) |
PET 2001 |
$E66B |
$6B |
107 |
$FD38 |
$38 |
056 |
CBM 3001 |
$E61B |
$1B |
027 |
$FCD1 |
$D1 |
209 |
CBM 4001/8001 |
$E442 |
$42 |
066 |
$FD16 |
$16 |
022 |
P 500 / CBM 500 |
$FBE5 |
$E5 |
229 |
$F99E |
$9E |
158 |
CBM 600 / 700 |
$FBD6 |
$D6 |
214 |
$F997 |
$97 |
151 |
VC 20 |
$FF71 |
$72 |
114 |
$FD22 |
$22 |
034 |
C 64 / C64 SX |
$FF48 |
$48 |
072 |
$FCE2 |
$E2 |
226 |
C 16 / C 116 / Plus 4 |
$FCB3 |
$B3 |
179 |
$FF6F |
$F6 |
246 |
C 128 / C 128 D |
$FF17 |
$17 |
023 |
$FF3D |
$3d |
061 |
Tabelle der Systemvektoren IRQ und RESET für alle Commodore-8-Bit-Rechner
Der IRQ-Vektor liegt bei $FFFE/FFFF, der RESET-Vektor bei $FFFC/FFFD im ROM; wie bei der CPU 6502 üblich im Format LSB/MSB (Low-Byte/High-Byte bzw. LB/HB). Mittels PEEK lässt sich der gewünschte Wert auslesen. PEEK(65534) liefert das Low-Byte des IRQ-Vektors, PEEK(65532) den des RESET-Vektors. Beim Commodore Plus 4 (und C16 / C116) muss zuvor allerdings noch das ROM eingeblendet werden, was einen kleinen schmutzigen Trick erfordert. Man kann ihn in Zeile 130 des nachfolgenden Listings finden:
100 rem *** cbm checker a (wte) ***
110 :
120 cbm=peek(65534): pet=0: c$=“commodore “
130 if peek(1177)=63 then poke1177,62: cbm=peek(65534): poke1177,63
140 rem 2001,3001,4001,p500,cbm600/700,vc20,c64,c16/p4,c128
150 restore:data 107, 27, 66, 229, 214, 114, 72, 179, 23
160 ix=0: for i=1 to 9: read a:if a=cbm then ix=i: i=9
170 next: on ix gosub 240, 260, 280, 340, 360, 380, 400, 420, 440
180 if ix then 460
190 print
200 print „not supported system!“
210 print „dieser computer wird nicht unterstuetzt!“
220 end
230 :
240 a$=“2″: goto300
250 :
260 a$=“3″: goto300
270 :
280 a$=chr$(52-(peek(224)=0)*4)
290 :
300 if a$<„4“ then poke59458,peek(59458) or 32:rem killer poke (fast poke)
310 a$=mid$(„pet cbm „,5+(a$=“2″)*4,4)+a$
320 pet=59468: c$=c$+a$+“001 series“: return
330 :
340 c$=c$+“p500/cbm510″: return
350 :
360 c$=c$+“600/700 series“: return
370 :
380 c$=c$+“vic20/vc20″: return
390 :
400 c$=c$+“64″: return
410 :
420 c$=c$+“c16/c116/plus4″: return
430 :
440 c$=c$+“128″: graphic 0: slow: return
450 :
460 print chr$(147)chr$(142): if pet then poke pet,12
470 print „this program is running on a“
480 print c$: print
490 print „dieses programm laeuft auf einem“
500 print c$: print: end |
Variante A der Systemerkennung. Rechnerspezifische Details werden über ON / GOSUB definiert
100 rem *** cbm checker b (wte) ***
110 :
120 cbm=peek(65534): c$=“commodore “
130 if peek(1177)=63 then poke1177,62: cbm=peek(65534): poke1177,63
140 restore
150 rem 2001,3001,4001,p500,cbm600/700,vc20,c64,c16/p4,c128
160 data 107, pet 2001 series, 1, 1, 0
170 data 27, cbm 3001 series, 1, 1, 0
180 data 66, cbm 4001 series, 1, 0, 0
190 data 229, p500/cbm510, 0, 0, 0
200 data 214, 600/700 series, 0, 0, 0
210 data 114, vic20/vc20, 0, 0, 0
220 data 72, 64, 0, 0, 0
230 data 179, c16/c116/plus4, 0, 0, 0
240 data 23, 128, 0, 0, 1
250 :
260 ix=0: for i=1 to 9
270 read a, a$, pet, kp, c128
280 if a=cbm then ix=i: i=9
290 next
300 if ix then 370
310 :
320 print
330 print „not supported system!“
340 print „dieser computer wird nicht unterstuetzt!“
350 end
360 :
370 if kp then poke59458,peek(59458) or 32:rem killer poke (fast poke)
380 if kp<>pet then if peek(224)=0 then a$=“cbm 8″+mid$(a$,6)
390 c$=c$+a$: if c128 then graphic 0: slow
400 :
410 print chr$(147)chr$(142): if pet then poke 59468,12
420 print „this program is running on a“
430 print c$: print
440 print „dieses programm laeuft auf einem“
450 print c$: print: end |
Variante B der Systemerkennung. Rechnerspezifische Details werden über DATA-Statements definiert
Wer den Quellcode genau studiert, wird feststellen, dass für die Rechner der CBM 8000er Reihe, die den gleichen IRQ-Vektor haben wie die 4000er, eine zusätzliche Detailprüfung implementiert wurde. Über die Speicherstelle $E0 (224) in der Zeropage kann man leicht erkennen, welchen Rechner (8001 Series: 0 / 4001 Series: 128) man vor sich hat.
Beide Varianten der Rechnererkennung haben ihre Vor- und Nachteile und stehen hier nur beispielhaft für zwei Möglichkeiten das Problem anzugehen [die Programme können als Text- und PRG-Dateien (gezippt) für Testzwecke heruntergeladen werden]. Da sich meine Multiplattform-Programme in der Regel auf die Rechner mit 40-Zeichen-Darstellung beschränken, lasse ich in der Praxis die Erkennung von CBM 600/700 und VC 20 „unter den Tisch fallen“ und erkläre sie zu „nicht unterstützten Systemen“. Und natürlich muss der Identifizierung auch eine ausgefeilte Differenzierung folgen (hier angedeutet durch den „Killer-POKE“ und die BASIC 7-Befehle GRAPHIC und SLOW). Doch dazu berichte ich später mehr.