GRRERBENNN va: WR Inieriage Age IT If

Systemlhaneluch i j III

= NN

COMMoOLELE HA ua ea

2 EEE a FE EIS! B£, SERIE SESERIETTETN Ral 2 Babel Fin ® SEX. ..w KRISE IISTER 2 TRIER Aa . PEN RR Michael Krau . er x ei N <= IT q nn A » D

DAS INTERFACE AGE SYSTEMHANDBUCH ZUM COMMODORE 64 UND VC-20

Ralph Babel

unter Mitarbeit von

Michael Krause und Andreas Dripke

Gesamtherstellung

Unternehmensberatung Andreas Dripke

Vertrieb

INTERFACE AGE Verlagsgesellschaft

VORWORT

Die Nutzbarkeit eines Computers aus der Sicht des Program- mierers hängt in entscheidender Weise von der verfügbaren Dokumentation ab. Für effiziente Programmierung ist die genaue Kenntnis der internen Strukturen unerläßlich.

In dem vorliegenden Werk wird das Betriebssystem des Commo- dore 64 unter Einbeziehung des VC-20 ausführlich und umfas- send dargelegt. Viele der in diesem Buch enthaltenen Infor- mationen dürften zum Zeitpunkt des Erscheinens nur wenigen Menschen auf der Erde bekannt sein. Sie finden hierin alle Daten, die für die Programmierung des Computers relevant sind.

Alle in diesem Buch genannten fakten wurden sorgfältig recherchiert und äußerst sorgsam aufbereitet.

Die Informationen sind sowohl für den BASIC- als auch für den Assembler-Programmierer geeignet. Dabei wird es für Sie oftmals unerläßlich sein, Abschnitte mehrmals zu lesen, um sie voll zu verstehen. Die Fülle an Daten - komprimiert in einem Handbuch - macht dies erforderlich. Hätten wir einen weiter ausschweifenden Stil gewählt und damit diesem Buch mindestens dreimal so viele Seiten gegeben, so wäre es prak- tisch unmöglich, Daten gezielt zu suchen und insbesondere zu finden. Das Systemhandbuch ist sowohl zum Durchlesen als auch als Nachschlagewerk geeignet.

Bitte haben Sie Verständnis dafür, daß wir keine Fragen zur Programmierung beantworten können. Würden wir dies einmal anfangen, kämen wir sicherlich nicht mehr dazu, weitere Bücher für Sie zu schreiben. Wir freuen uns aber über Kritik und Anregungen von Ihnen und werden diese in einer weiteren Auflage des Werkes berücksichtigen. Und wenn Ihnen unser Buch gefällt, freuen wir uns natürlich über Ihre Empfehlung an Kollegen, Bekannte und Freunde. i

Nun wollen wir Sie der faszinierenden Fülle an Daten über- lassen, die Ihnen dieses Buch zu bieten hat. Möge es Ihnen ein hilfreches Handbuch bei der Programmierung Ihres Compu- ters sein.

Ralph Babel Michael Krause Andreas Dripke

Babel, Ralph; Krause, Michael; Dripke, Andreas DAS INTERFACE AGE SYSTEMHANDBUCH ZUM COMMODORE 64 UND VC-20

1. (1983) 2. (1983)

ISBN 3-88986-001-X

Dieses Buch ist mit internationalem Copyright belegt. Alle Rechte vorbehalten. Kein Teil des Werkes darf in irgendeiner Form ohne schriftliche Genehmigung von Andreas Dripke reproduziert, übersetzt, verarbeitet, verbreitet oder veröffentlicht werden.

Weder Autoren noch Verlag oder Händler übernehmen eine Gewähr dafür, daß das Werk frei von Fehlern ist. Für Schäden, die durch solche Fehler entstehen, insbesondere für Folgeschäden, wird keine Haftung übernommen.

Die Veröffentlichung von Namen, Schaltungen, Programmen, Verfahren, Funktionsgruppen etc. in diesem Buch berechtigt nicht zu der Annahme, daß diese frei von Schutzrechten Dritter seien.

Made in West Germany

Copyright (C) 1983 by Unternehmensberatung Andreas Dripke Gesamtherstellung: Unternehmensberatung Andreas Dripke

Distribution(BRD): INTERFACE AGE VERLAG GMBH, Vohburgerstr.] D-8000 München 21, Tel. (089) 5 80 67 02.

Director Sales/Marketing: Issi Franckh

International Distribution: COMPUTER BOOKBASE (DATA DYNAMICS TECHNOLOGY, USA) Div. of INTERFACE AGE Inc. 16704 Marquardt Avenue Cerritos, CA 90701, U.S.A.

Druck: Offsetdruck Georg Kapehl, Wiesbaden

INHALTSVERZEICHNIS

VOrWOTEN.G GN a aa ns een een InhalEsverzeichnzs zus. een 1. BASIE=-Interpreter „ur: Interne Codierung der BASIC-Programme ..... ee Tabelle der BASIC-Befehle ......sceerereoeeeeenenn Binärarithmetik oo. ... o oe oe oe oo 08 v...—. 1. .:.—.0—© 0 eeov01e eo oo 0 08 0 0 Darstellung von Fließkommazahlen ........erecer0.. Darstellung und Ablage von Variablen ............ Nicht-indizierte Variablentypen .......c.:.. Arrays oo. ....2—.>.0—0© ee vv. .:e ee. oe oo oe © oe... .“.a„...„.”a.n”.”eC"eeese oe. USR-Funktion . .. 0. 01 0 0 0 oo oo 0 _—. er ar era er steuercöde-Auflistung „cs sn 00er 000006 Rn Steuercodes in Listings ........ een

2. Assembler .eo oe 0 0 0 0 90 90 98 90 0 0 0 98 08 8 8 HH HH Vf 8 oe oe... ...”e”.—.e7—e067. .». .ee.... Einführung in Assembler ............ enrese BERPTE

4.

Assembler/Disassembler .....ec:eeeeoneeeereennnn nn Assembler-Befehlsliste: „issue... 222 53 Symbolische Befehlsliste ......cceceooeeneeeneenee Adressierungsarten „2.00 2. 0 aan

Graphik und Farbe (VIC-II-Chip) ....c:.20.. EEE Bildschirmspeicher ....... ES RE ER EIER > karbspeicher. sis... er ERTL Zeichengenerator ...... na een Definition eigener Zeichen ......cc.ece.00e0.e Modus für erweitere Hintergrundfarben ...... Mehrfarbige Zeichen (Multicolor-Modus) ..... Hochauflösende Graphik (Hi Res) ....eecccrecnconee Standard Bit-Map-Modus .....sceeeneeeeeeenee Multicolor-Bit-Map-Modus .....cseecr0. Seas Sprites - MOB '"Movable Object Block" ....... ee Aufbau-eines SprTrites u... 4.,4220u2.0 0. a Multicolor-Sprites ........:.. ERIRITREERN a Prioritäten zu... 4404 ee ee EEE Kollısionen ser ar u Interrupt- und Graphik-Kontrolle .....vseccccceoe Screen Blanking ee ee ne ee ee Scerolling in Punktzeilen (Smooth ee ee Registerübersicht ......... eier lee ie Farben_des VIC-II-Chips ...o.vereeoneeeennnennn ne Pinbelegung des VIC-II-Chips ..... EST RT FR SPTILE=-ENtwuürfsblatl. us ss na Sprite-Generator-Programm ........ ELTERN Funke 1onstästen. „es: sr EEE

>.

10.

Tonerzeugung (SID 6581 Chip) ........ es re

Tongenerator (Frequenzberechnung) ......c.r.... a ADSR-Funktion sa... et a as EN en Wellenformen .......sc.0..0. el er ET ETE Tonerzeugung ........ EUER EIETIEEETN et Filter 4,.228%% EURER ETUI Tongeneratort 3 za. rer

Hullküurve .,2. 5300004 ee FREE

Oszillatorn „asus nenne ee er A/DeWändler 2. erh ER TRREN > Registerübersicht ....... ee ee Pinbelegung ss. a

Ein/Ausgabe (I/D) .....c..0.2.. BESTEN ELRHENR es

seriellen. Bus. 2:42. u 2 En an RS=232 Datentransfer +»... 0.20 a, 1 2 a EIA.:6526 Chip ass Portprogrammierung ........+.. see ers serieller.-Port>»22:uuuu anne ee Timer ons "Tine DEF Day" Clock. u. ren il Interrupt-Handling .....vc2creeeoreeenneeenne Registerübersicht ....... nee ee Anwendung im Commodore 64 .....cereeererene.e Pinbelegung .„.ccscoeesesecne..e ....00..+ EEE Control-Ports ..... DE er DENE Joystick zueuncnaaaeer ee Paddle 4.445 ee es Lightpen +»... 028. 0 een Datenspeicherung Cassette/Diskette .........c.... Cassette ..v.coococoeseenesen nee sennnene ea. Header ...o-oser00essseeenne IRRE Datentypen ...:csc..0 0000000... EEE Zusammenfügen von Programmen .......+. s

Diskette ausser ae era ene Dverlay ........ ee reeiee

Echtzeituhr (EIA TIock) san it Adaption von CBM-Programmen .....s.e.:. eek

Speicheraufteilung .......... TESTER ITETTN

Speicherübersicht ........osc0s00s..00% EEFLIERTE Memory Map .. oo oo0eooneee seen een ernennen ne CPU 6510 / Speicherverwaltung ......o.rercc0.. BR Prozessorport .„....ecceeeeeeocseeeonneene ae Banking ...<oeeeeueneeenn nennen nn een. Pinbelegung der CPU 6510 .....voerreeeeneenee

ROM-LIStIiNG cr rer ROM-Listing Commodore 64 .....ceereerereneneenene

Adressumrechnung für VC-20 ...c.erereeeeerenneenee Systemroutinen .....ccececeeenene ee ae

Stichwortverzeichnis ....... a a a ee ee RER

30C

INTERNE CODIERUNG DER BASIC-PROGRAMME

BASIC-Befehle werden, zur Einsparung von Speicherplatz und zur Beschleunigung der Programmausfuehrung, in einen be- stimmten Code umgewandelt. Ausserdem wird jeder Programmzei- le noch die Information ueber die Ablageposition der naech- sten Programmzeile mitgegeben, die das Suchen von Programn- zeilen (zum Beispiel bei Sprungbefehlen) vereinfacht und die Suchgeschwindigkeit erhoeht. Dies geschieht beim 'Abschik- ken' einer Programmzeile durch die RETURN-Taste. Auch Befeh- le, die im Direktmodus gegeben werden, werden in die soae- nannten 'Tokens' umgewandelt, bleiben jedoch im BASIC-Einaa- bepuffer ab Adresse 512 stehen. Daraus resultiert auch, wa- rum Befehle, die auch den Eingabepuffer benoetigen (INPUT, INPUT# und GET(#)), im Direktmodus im Normalfall nicht aus- gefuehrt werden koennen.

Die Startadresse eines BASIC-Programms steht als Pointer in den Adressen 43 und 44 und kann durch ...

PRINT PEEK(43) + 256 * PEEK(44)

... abgefragt werden. Im Normalfall duerfte das Ergebnis gleich 2049 sein, da dies die vom Betriebssystem vorgesehene Startadresse fuer BASIC-Programme ist, die jedoch fuer eige- ne Anwendungen geaendert werden kann.

Die ersten beiden Bytes jeder Programmzeile (bei der ersten Zeile eines Programms sind das die Speicherstellen 2149 und 2050) enthalten die Startadresse der naechsten Zeile im Adressformat, wobei (wie das in fast allen Faellen der Ab- speicherung von 16-Bit-Werten ist) zuerst die Adresse low und dann die Adresse high abgespeichert wird.

Die naechsten beiden Bytes stellen die Zeilennummer der Pro- grammzeile dar, die im Normalfall im Bereich von 0 bis 63999 liegt. Durch 'POKE' ist es jedoch auch moeglich, hoehere Zeilennummern (bis 65535) zu erzeugen, was dann aber bei Sprungbefehlen und zum Beispiel bei 'INPUT' zu sicherlich unerwuenschten Effekten fuehren kann.

Danach folgt der eigentliche Programmtext, wobei alle Befeh- le, Funktionen und Operatoren in Tokens codiert sind. Davon unbetroffen bleiben alle Texte, die innerhalb von Anfueh- rungszeichen stehen, Bemerkungen nach 'REM' sowie Daten nach einem 'DATA'-Befehl. Der Programmtext ist mit dem Nullcode abgeschlossen.

Dieser Aufbau wiederholt sich bis zur letzten Zeile, der dann zwei Nullcodes folgen, die das Programmende markieren. Der Zeiger auf den Anfang der Variablentabelle zeigt auf das erste Zeichen nach den beiden (es sind, zusammen mit dem Nullcode zur Markierung des Endes der Programmzeile, drei aufeinanderfolgende Nullcodes) Nullcodes. Dieser ° Zeiger steht in den Adressen 45 und 46 und ist aeqauivalent dem Pointer auf den Anfang des BASIC-Programms abzufragen.

Die Laenge eines Programms kann, unabhaengiq von eventuell schon definierten Variablen, durch folgende Befehlsfolge ab- gefragt werden

PRINT PEEK(45) + 256 * PEEK(46) - PEEK(43) - 256 * PEEK(44)

vas zum Beispiel bei sich selbst modifizierenden Pro- grammen oder waehrend der Entwicklung von Programmen zur Ueberwachung der Programmlaenge verwendet werden kann.

Ein Beispiel fuer die intere Codierung

Folgendes Programm wird, nach der Eingabe von 'NEW', um ein eventuell noch vorhandenes Programm zu loeschen, in den Com- modore 64 eingegeben.

100 rem test 500 print "Tokens 999 end

Diese drei Zeilen werden nun durch folgende Werte darge- stellt (der jeweils erste Wert einer Zeile gibt die Start- adresse der jeweiligen Zeile nur zum besseren Verstaendnis an und hat mit der Abspeicherung nichts zu tun).

2049 12 8100 0143 32 84 69 83 84 0 REM t e Ss t

2060 28 8 244 1153 32 34 212 94 75 69 78 83 0 PRINT T Oo k e n s

2076 34 8 231 3 128 0 END

2082 0 0

Betrachten wir nun die ersten beiden Bytes der ersten Pro- grammzeile, so stellen wir fest, dass diese auf die naechste Programmzeile zeigen (12 + 256 * ß = 2060). Diese beiden Bytes haben nun die Werte 28 und B und ergeben genau die Startadresse der dritten Programmzeile (28 + 256 * 8 = 2076). Das gleiche ist auch bei der letzen Programmzeile der Fall, davon abgesehen, dass nun keine Programmzeile mehr folgt, sondern auf die beiden Nullcodes zur Kennzeichnuna des Endes eines Programms gezeigt wird. Diese Pointer, die jeweils auf den Pointer der naechsten Zeile zeigen, werden auch Linkpointer genannt, da sie die Verbindung zwischen den einzelnen Zeilen herstellen.

Das jeweils dritte und vierte Byte von Programmzeilen aibt die Zeilennummer an. Da die Zeilennummern im Bereich von 0 bis 63999 liegen koennen, werden sie, ebenso wie die Link- pointer, in zwei Bytes aufgespalten. So wird die Zeilennum- mer '999' durch die beiden Bytes 231 und 3 (231 + 256 * 3 = 999) dargestellt.

Der Programmtext selbst ist in Einzelbytes aufgebaut. Jedem Befehl ist ein Wert zugewiesen, in diesem Beispiel sind das 'REM' mit dem Code 143, 'PRINT' mit dem Code 153 sowie 'END' mit dem Code 128.

Waehrend die Leercodes direkt nach der Zeilennummer nicht abgespeichert werden, so ist. dies doch bei allen Leercodes der Fall, die ansonsten eingegeben werden.

Eine vollstaendige Aufstellung der Tokens ist der Tabelle der Interpretercodes oder dem Betriebssystemlisting zu ent- nehmen.

Takelle der BERASIC-Befehle.

Die Befehle sind alphasketisch aesordrnet, da Reihe der Interpretercoades aus dem RüOM-Listi

abs and 3SC. atn chr$ close cir cmd cont cos data def dim end exp fn for fre get C goszuk Aatc if input input# int

182 175 198 193 133 180

156

157 154 130 131 154 134 128 189 1655 129 184 181 2093 141 137 1:33 133 132 181

left$ lern let list load 1ca4 mid new next not

ar aper cr peel: pake pas errint rrint# read rem restore return riaht$ rnd run zan,e

ler ler 1E

new nE nC an or or rE

258 1353 136 155 147 133 ea2 162 130 188 145 153 175 134 151 135 173 132 135 143 140 142 zual 197 138 143

Interpretercaodes

Folsende Cades finden zusserdem Verwendung:

a

32 kis 95 identisch

255

und Akkuer zungen

die Ruflistung n4 ersichtlich

Nullcode am Zeilenende und Proar ammerde

mit dem

Coade fuer PI

Die Codes li kis 31. Grundversion des Betriekssuvstems nicht verwendet. werden jedach

teilweise von der Standard-ERSIC-Erweiteruna EXsEBRASIC

kenutzt.

9& kiss 127

ıarıd

ad bis

Lonmadere—-ASCII

zan eG sin =1 sp. =P za =Uü step =tE stop =T str$ =tR sus er +tak: A tarı tar then tH +0 +0 UeEr 115 al A „eritw JE wait wAÄ + +

# #

e” 224 werden

LEVEL

in ist,

fe jeub feed jeub feeb fjmehb fe jun fe fen fe Sen feeb fen fee jemib

LEN ohne! in Home) NO

SAUNA N VONLUN-N

fh fm eb be jenb jub jeeb fees

der

Il

BINAERARITHMETIK

Binaeres Rechnen und Umgang mit binaeren Zahlen wird beim Arbeiten mit dem Computer immer wieder benoetigt. Ganz gleich, ob es sich dabei um die hochaufloesende Graphik, die Definition von Zeichen oder das Aendern einzelner Bits in bestimmten Registern handelt. \

Eine Zahl im fuer uns gebraeuchlichen Dezimalsystem kann aus mehreren Ziffern bestehen. Dabei wird die hintere Ziffer als Einerstelle bezeichnet. Die vorletzte Ziffer ist die Zehner- stelle, die drittletzte Stelle bestimmt die Anzahl an Hun- dertern und so weiter. Von der Zahl eins fuer die letzte Stelle ausgehend wird der Stellenwert einer Ziffer fuer iede Stelle weiter links mit zehn multipliziert. Klar, denn unser Zahlensystem kennt schliesslich auch zehn Ziffern. Die Zahl 1983 heisst also nicht anderes als... |

1983 = 1 * 1000 + 9 * 100 +8 *10 +3 *]

Da das Binaersystem jedoch nur zwei Zustaende kennt (Strom fliesst, Strom fliesst nicht), stehen hier also auch nur zwei verschiedene Ziffern zur Verfuegung. Die Stellenverte einzelner Ziffern koennen also nicht das zehnfache der rechts davon stehenden Ziffer betragen, sondern nur das Nop- pelte. Somit ergeben sich zum Beispie) fuer das Binaersystem folgende Stellenwerte: fuer die letzte Stelle, wie in jedem Zahlensystem, den Stellenwert eins, dann der Wert zwei, da- rauf vier, als Stellenwert fuer die viertletzte Stelle den Wert acht und entsprechend jeweils das Doppelte fuer weitere Stellen.

Da als Ziffern nur die Zahlen O und 1 zur Verfuegung stehen, hat eine Stelle demnach entweder den Wert null (falls die Ziffer null an dieser Stelle steht) oder den Stellenvert der entsprechenden Stelle (falls die Ziffer eins an dieser Stel- le steht). Dieses eigentlich recht einfache Prinzip ist Grundlage jeglicher Operationen des Computers. Auch das Rechnen erfolgt im Binaersystem, die eingegebenen Dezimal- zahlen werden fuer interne Berechnungen naemlich erst in das Binaersystem umgewandelt.

Die einzelnen Ziffern einer Binaerzahl, "Bits" genannt, wer- den von ihrer Position von rechts her mit Null beginnend durchnummeriert. Bit 4 zum Beispiel ist demnach die fuenfte Stelle einer Binaerzahl (von rechts!). Die Stellenwerte ]as- sen sich durch diese Vereinbarung sehr leicht errechnen. Es muss nur die Bitposition zur Basis zwei potenziert werden. Fuer Bit 4 ergibt dies einen Stellenvert von 2 4 (lies: zwei hoch vier), entsprechend dem Dezimalvert 16. Ein Bit (oder eine bestimmte Bitposition) zu SETZEN . heisst nun nichts anderes, als dieser Binaerstelle den Ziffernwert ']1' zuzuweisen. Das LOESCHEN eines Bits entspricht demnach der Zuweisung des Ziffernvwerts '0' an eine Bitposition.

Da der Commodore 64 einen Prozessor mit einem "8-Bit-Daten- bus" besitzt, werden jegliche Speicheroperationen immer mit acht Bits gleichzeitig ausgefuehrt. Werden Daten aus dem Speicher gelesen, so werden immer acht Bits gelesen, so auch bei den Befehlen "POKE" und "PEEK", die immer Daten mit ei- ner Breite von acht Bits schreiben beziehunasveise lesen. Bei der sogenannten "vorzeichenlosen Binaerarithmetik" mit acht Bits haben die einzelnen Stellen folgende Stellenverte:

10

Der Minimalvert (alle Bits geloescht), den eine vorzeichen- lose Binaerzahl annehmen kann, ist demnach der Wert 0, der Maximalwert (alle Bits gesetzt) einer achtstelligen Binaer- zahl ist 255. Eine solche Binaerzahl mit einer Breite von acht Bits nennt man auch "Byte". Ein Byte ist also gleichzu- setzen mit acht Bits.

Zusaetzlich zu den Bytes existieren nun noch die "Adressen". Eine Adresse ist eine vorzeichenlose Binaerzahl, die aus sechzehn Bits (entsprechend zwei Bytes) besteht. Durch eine Adresse kann die Position bestimmter Stellen im Arbeitsspei- cher festgelegt werden. Zwei aufeinanderfolgende Bytes im Arbeitsspeicher, die auf eine andere Stelle verweisen, nennt man "Pointer".

Hierzu gleich zwei Programme, die die Umwandlung einer na- tuerlichen Dezimalzahl ins Binaersystem und umgekehrt vor- nehmen:

Binaer nach Dezimal:

100 INPUT B$ : D =D : FOR I = 1 TO LEN (B$)

110 S$ = MID$ (B$, I, 1)

120 IF S$ C "o" OR S$ > "1" THEN I = LEN (B$) : NEXT : END 130 D =D * 2 ASC (S$) - 48 : NEXT : PRINT D : END

Dezimal nach Binaer:

200 INPUT D : B$ = ""

210 R = INT (D / 2) : B$ = CHR$ (D- R* 2 + 48) + B$ 220D=R : IF R GOTO 210

230 PRINT B$ : END

Bei der Umwandlung ins Binaersystem werden die Binaerzahlen so umgewandelt, dass fuehrende Nullen unbeachtet bleiben. Ist eine Darstellung des Binaeraequivalents von Dezimalzah- len im Bereich von OD bis 255 in Form von acht Binaerstellen erwuenscht (Auffuellen auf eine Laenge von acht Ziffern), so ist folgende Programmzeile hinzuzufuegen:

225 IF LEN (B$) C 8 THEN B$ = RIGHT$ ("0000000" + B$, 8)

Allerdings kann ein Byte nicht nur die Funktion der Darstel- lung einer Zahl haben (arithmetische Funktion). Es ist moeg- lich, dass jedem Bit in einem Byte eine bestimmte Funktion zukommt (logische Funktion). So koennen anhand eines Bytes insgesamt acht Bedingungen mit je zwei Moeglichkeiten abge- prueft werden. Man nennt in diesem Fall ein solches Bit, mit der Bedeutung als Hinveis fuer eine Ja/Nein-Entscheidung, eine "Flag", was soviel heisst wie "Flagge".

Solche "Flags" treten besonders in bestimmten "Registern" auf. Ein Register ist ein Byte innerhalb des Arbeitsbereichs des Computers, das eine bestimmte funktion erfuellt. Dies sind zum Beispiel die Register des VIC-II-Chips, anhand de- rer bestimmte Funktionen des Video-Chips festgelegt werden, oder viele Adressen im Bereich von O bis 1023.

11

Zur Manipulation von Binaerzahlen stehen beim Commodore- BASIC zwei Befehle zur Verknuepfung zweier Binaerzahlen zur Verfuegung: "AND" und "OR". Die beiden Operatoren bevirken, dass die beiden Argumente als Binaerzahlen Bit fuer Bit (insgesamt verarbeiten die Befehle 16 Bits, jedoch mit vVor- zeichen, was aber beim Arbeiten mit 8-Bit-Zahlen unbeachtet bleiben kann) verglichen werden und gleichzeitig das Ergeb- nis aufgebaut wird. Werden zwei Zahlen mittels "OR" ver- knuepft, so sind in der Ergebnis-Binaerzahl saemtliche Bit- positionen geloscht, bei denen beide Bitpositionen der bei- den Argumente geloescht waren, alle anderen Bits sind ge- setzt. Bei "AND" sind entsprechend alle Bits gesetzt, bei denen beide Bitpositionen der Argumente gesetzt waren, ande- re Bitpositionen sind geloescht. Dadurch laesst sich nun be- wirken, dass innerhalb eines Registers durch "PEEK" und "POKE" einzelne Bits gesetzt und geloescht werden koennen.

Soll zum Beispiel ein bestimmtes Bit (mit dem Stellenvert N) an der Adresse A ‚gesetzt werden, so kann dies durch ...

POKE A, PEEK (A) ORN

... erfolgen. Dies erklaert sich daraus, dass jegliche Bits, die durch "OR" mit dem Ziffernwvert '0' verknuepft werden, unbeeinflusst bleiben. Wird jedoch eine Verknuepfung durch- gefuehrt, bei der mindestens eins der beiden Bits gesetzt ist, so ist auch im Ergebnis dieses Bit gesetzt.

Aehnlich verlaeuft ‘dies beim Loeschen von Bits, was aber nur mittels "AND" moeglich ist. Wird naemlich ein Bit durch "AND" mit dem Wert '0O' verknuepft, so ist das Ergebnisbit auch geloescht. Allerdings muss nun erreicht werden, dass die uebrigen Bits unbeeinflusst bleiben. Dies ist dann der Fall, wenn sie bei der "AND"-Verknuepfung mit dem Wert ']' verknuepft werden. Es muss also nun mit einem Byte gearbei- tet werden, bei dem das Bit, das geloescht werden soll, den Bitwert '0' hat, alle uebrigen Bits den Wert ']1'. Entspre- chend dem Beispiel fuer das Setzen von Bits erreicht man das Loeschen durch

POKE A, PEEK (A) AND (255 - N)

Die Klammern fuer die Subtraktion dienen nur der Uebersicht und koennen entfallen, da der Operator '-' einer hoehere Prioritaet als 'AND' hat und daher auf jeden Fall vorher ausgefuehrt wird.

Sollen mehrere Bits gleichzeitig entweder gesetzt oder ge- loescht werden, so kann dies durch Addition der Stellenverte erfolgen.

Zur Bezeichnung von Binaerziffern und zusammengesetzten Bi- naerziffern existieren noch weitere gebraeuchliche Begriffe: So zum Beispiel MSB und LSB (Most/Least Significant Byte): Ein MSB ist das Byte innerhalb einer Kette von Bytes, dem der hoechste Stellenwert zukommt. Bei einer Adresse waere dies das Byte mit den Stellenwerten von 256 bis 32768. Das LSB ist entsprechend das niederwertigste Byte. Bei Adressen sind nur zwei Bytes verwendet, jedoch findet sich dieser Be- griff auch bei der Verwendung von Binaerziffern mit mehr als 16 Stellen (Bits). Die Begriffe MSB und LSB werden jedoch auch im Zusammenhang mit Bits verwendet. Hierbei ist dann mit MSB (Most Significant Bit) das hoechstwertige Bit (in- nerhalb eines oder mehrerer Bytes) gemeint.

Auch gebraeuchlich sind (oft auch im Zusammenhang mit Zahlen im Hexadezimalsystem oder gepackten BCD-Ziffern) die Be- zeichnung MSN und LSN, die fuer die Bezeichnung von "Nybbles" verwendet werden. Ein Nybble ist ein halbes Byte, also vier Bits. Ein Byte besteht daher aus zwei Nybbles, das eine besteht aus den Bits der Positionen O bis 3 (LSN), das andere entsprechend aus den Bits 4 bis 7 (MSN). |

Noch eine kurze Anmerkung zum Hexadezimalsystem: Dieses Zah- lensystem baut auf der Basis 16 (entsprechend 16 verschiede- nen Ziffern) auf. Diese Ziffern sind die Zahlen von '0' bis '9' sowie die Buchstaben von 'A' bis 'F', wobei die Buchsta- ben fuer die Dezimalwerte von 10 bis 15 stehen. Dieses Zah- lensystem fand und findet hauptsaechlich auf Einplatinensys- temen Anwendung, wo die Moeglichkeit einer Programmierung im Dezimalsystem ein zu aufwendiges Monitorprogramm benoetigen wuerde (Hexadezimalzahlen lassen sich leichter ins fuer den Computer verstaendliche Binaersystem umsetzen). Doch mit dem Aufkommen von groesseren Computern wurde in vielen Faellen dieses fuer den Menschen doch sehr ungebraeuchliche Zahlen- system mituebernommen, anstatt dem Programmierer durch Ver- wendung des Dezimalsystems entgegenzukommen. Mittlerweile haben sich viele Programmierer fuer die Assemblerprogrammie- rung im Dezimalsystem entschlossen, da dieses ein wesentlich komfortableres Arbeiten erlaubt. Das Hexadezimalsystem fin- det seine Berechtigung nur auf Minimalsystemen und nicht auf Computern, die im Normalfall (BASIC, PASCAL etc.) sowieso zum Arbeiten im Dezimalsystem konzipiert sind.

Zurueck zum Binaersystem: Es kann auch vorkommen, dass Dezi- malzahlen mit Nachkommastellen ins Binaersystem umgewandelt werden muessen. Hierbei wieder ein Vergleich mit dem Dezi- malsystem: Die Stelle vor dem Komma (die Einerstelle) hat ein Zehntel des Wertes der Stelle links davon (Zehnerstel- le), demnach hat die erste Stelle nach dem Komma den Wert '0.1', die naechste den Wert '0.01' und so weiter. Im Bi- naersystem hat demnach die erste Nachkommastelle den Wert '0.5' (hier wird naemlich durch zwei dividiert, nicht durch zehn), die zweite Nachkommastelle den Wert '0.25', die naechste '0.125'. Soll eine Dezimalzahl mit Nachkommastellen ins Binaersystem umgewandelt werden, so hat zuerst die Unm- wandlung des Vorkommateils zu erfolgen. Der Nachkommateil wird nun verdoppelt (die Binaerzahl wird also um eine Ziffer nach LINKS verschoben). Die Ziffer, die sich nun als Vorkom- mastelle ergibt (entweder '0' oder '1l'), ist die erste Nach- kommastelle. Mit dem Nachkommateil dieser verdoppelten Zahl wird nun genauso verfahren: Verdopplung und Verwendung der Vorkommastelle als naechste Nachkommastelle. Daraus resul- tiert natuerlich, dass nicht alle Dezimalzahlen sich abbre- chend ins Binaersystem umwandeln lassen. So ist zum Bei- spiel die Dezimalzahl '0.1' eine periodische Binaerzahl:

0.1 (dezimal) = 0.0001100110011001100110011... (binaer)

Ausser der Darstellung von gebrochenen Zahlen wird beim Un- gang mit Binaerzahlen nun noch die Darstellung von negativen Zahlen benoetigt: Eine Moeglichkeit der Darstellung von Bi- naerzahlen ist, das Vorzeichen in Form einer Flag zusammen mit der Zahl abzuspeichern. Diese Methode wird bei der win- ternen Darstellung von Fliesskommazahlen beim Commodore- BASIC (siehe dort) verwendet. Es wird nur der Betrag der Zahl abgespeichert, aber zusammen mit einem Bit, das angibt, ob die Zahl positiv oder negativ ist.

13

Bei der gebraeuchlicheren Methode erfolgt die Darstellung in Form des sogenannten "Zweierkomplements". Erst einmal zum Begriff der Komplements: das "Einserkomplement" einer Bi- naerzahl ergibt sich aus der invertierten Darstellung der Ausgangszahl. Jede Ziffer wird durch die entgegengesetzte Ziffer dargestellt, die '0' wird durch die '1' ersetzt und umgekehrt. So ist das Komplement von 'O01101110' gleich '10010001'. Das Zweierkomplement entspricht nun dem um den Wert eins erhoehten Einserkomplement. Hierzu ein Beispiel:

12 (dezimal) = 00001100 (binaer) Einserkomplement von 00001100 (binaer) = 11110011 (binaer) 11110011 (binaer) + 1 (binaer) = 11110100 (binaer)

Wird nun die positive Zahl zu ihrem Zweierkomplement ad- diert, so ist das Ergebnis gleich null.

Aus dieser Darstellung einer Binaerzahl mit Vorzeichen Te- sultiert jedoch jetzt, dass Bit 7 (falls nur mit acht Bits gearbeitet wird) nun nicht mehr den Stellenwert 128, sondern vielmehr -128 hat. Addiert man nun die Ziffernverte der Zahl '-12' aus dem obigen Beispiel (-128 + 64 + 32 + 16 + 4), so erhaelt man auch den korrekten Wert. Auch beim Commodore- BASIC wird bei den Operatoren "AND", "OR" und "NOT" (dieser Befehl errechnet das Einserkomplement) mit vorzeichenbehaf- teten Binaerzahlen gerechnet, jedoch mit Binaerzahlen einer Breite von sechzehn Bit. Daraus ergibt sich, dass Bit 15 nicht den Wert 32768, sondern -32768 hat (Bit 7 behaelt den normalen Wert von 128). Wird zum Beispiel eingegeben

PRINT NOT O

... so erhaelt man den auf den ersten Blick unsinnigen Wert '-1' als Ergebnis. Da jedoch das Einserkomplement von '0' (oder in Binaer '0000 0000 0000 0000') gleich '1111 1111 1111 1111' ist, erhaelt man nun durch Addition aller Stel- lenverte den Wert '-1'. Auch die Statusvariable 'ST' wird als 8-Bit-Zahl mit Vorzeichen angesehen. Dies kann man je- doch umgehen durch

PRINT 255 AND ST

... da hierdurch der Wert von ST (8 Bits) zuerst in 16 Bits umgewandelt wird (die Ziffer von Bit 7 wird in die Positio- nen 8 bis 15 uebertragen), dann werden die Bits 8 bis 15 ab- geschnitten. Da jedoch bei logischen Operatoren nicht Bit 7, sondern Bit 15 gesetzt sein muss, um negative Zahlen darzu- stellen, wird nun der Wert von 'ST' so ausgegeben, als sei er eine vorzeichrenlose Zahl. Der Wertebereich von 8-Bit-Zah- len mit Vorzeichen ist -128 bis 127, bei 16-Bit-Zahlen von -32768 bis 32767 (beim Commodore-BASIC kann die Zahl -32768 als Ergebnis einer logischen Operation auftreten, als Argu- ment wird sie jedoch durch die Fehlermeldung "?ILLEGAL QUANTITY ERROR" zurueckgeviesen).

Eine weitere Darstellungsveise fuer Zahlen ist das gepackte BCD (binary coded decimal) Format (wird im Dezimalmodus der 65er CPUs direkt verarbeitet, andere CPUs besitzen Befehle zur Anpassung): Hier entspricht jedes Nybble eines Bytes ei- ner Dezimalstelle. Jedoch nimmt dieses Nybble jetzt nicht mehr die Werte von O bis 15, sondern nur noch die Werte von D bis 9 an. Ein Byte, das eine Zahl im gepackten BCD-Format enthaelt, kann daher jetzt nur noch Zahlen im Bereich von O0 bis 99 enthalten. Zum Beispiel wird die Dezimalzahl '49' im BCD-Format als '0100 1001' gespeichert. Das MSN hat den Wert 4, das LSN den Wert 9.

14

DARSTELLUNG VON FLIESSKOMMAZAHLEN IM CBM-BASIC

Das BASIC des Commodore 64 bietet die Fliesskommazahlen als Variablentyp an. Die Darstellung derselben unterscheidet sich jedoch so stark von der Darstellung von Integervaria- blen (die problemlos ins Dezimalsystem rueckuebersetzbar sind), so dass hier gesondert darauf eingegangen werden soll. Fliesskommawerte werden innerhalb der Variablentabelle in fuenf Bytes abgespeichert (siehe Darstellung von Varia- blen). Auf die Bedeutung dieser fuenf Bytes soll im folgen- den eingegangen werden.

Als Beispiel dient hier die Abspeicherung der Zahl '-9876.25'. Der erste Umwandlungsschritt ist die Darstellung dieser Zahl im Binaersystem. Das Vorzeichen bleibt hierbei unberuecksichtigt, da negative Zahlen nicht in Form des um eins erhoehten Einserkomplements dargestellt werden, sondern das Vorzeichen getrennt angegeben wird. Die Zahl '9876.25' sieht im Binaersystem nun wie folgt aus:

9876.25 (dezimal) = 10011010010100.01 (binaer)

Nun lassen sich Binaerzahlen, wie Zahlen eines jeden anderen Zahlensystems auch, in Exponentialdarstellung bringen. So vie die Dezimalzahl ...

25000 zu 2.5E+04

... wird, so laesst sich auch die obige Binaerzahl in Expo- nentialdarstellung (zur Basis zwei) bringen. Wird nun das Komma (unter Erhoehung des Exponenten) so verschoben, dass keine Zahl mehr vor diesem steht (und direkt nach dem Komma eine eins), so entspricht dies schon im ungefaehren der Dar- stellung im CBM-BASIC. Die Zahl im obigen Beispiel wuerde nun wie folgt aussehen:

10011010010100.01 = 0.1001101001010001 E 1110

... saemtliche Zahlen im Binaersystem. Der Exponent ent- spricht der Dezimalzahl 14, da das Komma schliesslich um 14 Stellen nach links verschoben wurde. Bei einer Verschiebung nach rechts waere der Exponent negativ. Zu diesem Exponen- ten wird nun der Wert 128 addiert, man erhaelt das erste Byte des Variablenverts bei Real-Variablen, aus dem man wie- derum den Exponenten errechnen kann. Um nun die restlichen vier Bytes zu erhalten, muss folgendermassen vorgegangen werden: Man unterteilt die Mantisse der Binaerzahl in vier Gruppen zu je acht Ziffern (falls nicht genug Ziffern vor- handen sind, wird der Rest mit Nullen aufgefuellt) und er- setzt die erste Ziffer (das war der Ziffernwert eins, der eine Stelle rechts des Kommas stand) im ersten Block mit acht Ziffern durch die Vorzeichenflag (positiv = 0, negativ = l). Das Komma kann ab hier entfallen, es ist nur die Zif- fernfolge von Bedeutung. Hier wieder unser Beispiel

Mantissenziffernfolge: 1001101001010001 In Bloecke unterteilt: 10011010 01010001 00000Nn0N NnoNnOonnan Ersetzung der ersten Ziffer durch die Vorzeichenflag:

1 0011010 01010001 00CnHAANN AOnananN In diesem Fall aendert sich die erste Ziffer nicht, da wir

ja von einer negativen Zahl ausgegangen sind. Waere die Zahl positiv,-so waere die erste Ziffer eine Null.

15

Die nun folgenden Umwandlungsschritte macht der Rechner nun nicht mehr mit, da er selbst ja normalerweise auch im Bi- naersystem arbeitet und so die Zahlenbloecke nicht mehr zur veiteren Verarbeitung ins Dezimalsystem konvertieren muss.

Wie gesagt werden diese vier Bloecke zu acht Ziffern (Bits) nun ins Dezimalsystem umgewandelt. Man erhaelt so die weite- ren vier Bytes des Variablenwerts. Im Endeffekt wird unsere Zahl (falls sie einer Variablen zugeviesen wird) abgespei- chert als

142 154 81 0 0

Das erste Byte ist der (Binaer-) Exponent (zur Basis 2, um 128 erhoeht), der Rest stellt die Mantisse und das Vorzei- chen dar.

Die Zahlendarstellung in den Rechenregistern (FAC und ARG, auch Fliesskommaakkumulatoren #1l und #2 genannt) des Be- triebssystems ist ein wenig anders. Hier wird das fuer das Vorzeichen zustaendige Bit wieder durch eine eins ersetzt und das Vorzeichen selbst in einer getrennten Zeropage- Adresse abgespeichert. Zusaetzlich besitzt FAC (Floating- point ACcumulator) im Unterschied zu ARG (floatingpoint ARGument) noch eine Rundungsstelle, die einem fuenften Man- tissenbyte gleichkommt.

16

DARSTELLUNG UND ABLAGE VON VARIABLEN

Die Variablen werden im Commodore-BASIC in drei Bloecken va- riabel verwaltet. Es handelt sich dabei um die einfachen (nichtindizierten) Variablen, die indizierten Variablen, Felder oder Arrays genannt, sowie die Inhalte der Stringva- riablen, die in einem weiteren Datenblock verwaltet werden.

Der erste Block liegt direkt hinter dem BASIC-Programm, wo- durch auch klar wird, warum Variablen durch Programmaende- rungen geloescht werden - es werden beim Einbau von Pro- grammzeilen die Variablen einfach ueberschrieben. Der Point- er (45/46) zeigt auf den Beginn des Variablenbereichs, das Ende wird durch den Anfangspointer auf den Block mit den in- dizierten Variablen bestimmt, die direkt hinter den nichtin- dizierten stehen. Diese Startadresse der Feldvariablentabel- le wird durch den Pointer (47/48) festgelegt. Die Endadresse (plus eins, wie alle Endpointer) steht in (49/50).

Die Tabelle der nichtindizierten Variablen ist in Eintraege zu je sieben Bytes aufgeteilt, die den Variablennamen und den Inhalt (beziehungsweise den Pointer auf den Inhalt) ent- halten. Bei den Eintraegen handelt es sich um die Real-Vari- ablen, die Integer-Variablen, die Strings sovie die mittels 'DEF' definierten "Variablen". Der Aufbau eines Eintrags in folgender Tabelle in einer Uebersicht:

Typ [Byte O|Byte 1|Byte 2 [Byte 3 |Byte 4 | Byte 5 |Byte 6

real| reset Variablenwert von MSB bis LSB

Startadresse ILH| Startadresse LH| Variablenp. LH

Der Variablenname steht in den ersten beiden Bytes, und da Zeichen des Variablennamens nur Buchstaben oder Zahlen sein duerfen, wird Bit 7 zusaetzlich zur Markierung des V\Varia- blentyps verwendet. Die Angabe 'set' beziehungsweise 'reset' bezieht sich also auf Bit 7 des Variablennamens. Die wveite- ren fuenf Bytes geben, sofern benutzt, den Variablenvert an. Die Aufteilung dieser fuenf Bytes bei den Reals und Integers bedarf keiner weiteren Erklaerung.

Die Angabe 'Startadresse LH' bei Eintraegen von Stringvaria- blen bezieht sich auf die Startadresse (erst low, dann hiah) des Stringinhalts, der entweder im Programm (bei Direktzu- weisungen) oder am Ende des Arbeitsspeichers liegen kann (Stringoperationen oder Eingaben). Ist die Stringlaenge gleich null, so ist die Startadresse natuerlich egal.

FN-Variablen enthalten einerseits den Pointer auf den Aus- druck, der auszuwerten ist, sowie den Pointer auf die FN-Va- riable, die im Ausdruck verwendet wird. Beim Aufruf einer selbstdefinierten Funktion wird der Inhalt der FN-Variablen gerettet, das Argument des FN-Ausdrucks in die Variable uebertragen, der Ausdruck ausgevertet (bei Fehlern im Aus- druck wird die Zeilennummer, in der das FN steht, ausgege- ben, nicht die des FN-Ausdrucks) und zur weiteren Verwendung in FAC uebertragen. Danach wird der Inhalt der FN-Variablen wiederhergestellt und das Programm an der Stelle hinter dem FN-Aufruf fortgesetzt.

Das Suchen und Anlegen von Variablen kann durch die Routine '"VARSUC' (ab 45195) durchgefuehrt werden.

17

Der Block am Ende des Arbeitsspeichers enthaelt die String- inhalte, sofern sie nicht direkt im Programm zugewiesen wur- den. Diese Stringinhalte reichen bis zum Ende des Arbeits- speichers (Endadresse im Pointer (55/56)) und werden nach unten hin angebaut. Saemtliche Zwischenergebnisse bei Stringoperationen werden abgespeichert und dann zu weiteren Berechnungen herangezogen. Ist ein Ausdruck ausgewertet, so verden die "Reste", die Zwischenergebnisse und frueheren Stringinhalte, nicht beseitigt, sondern unveraendert im Block gelassen, dessen Anfang, festgelegt durch den Pointer (51/52), sich immer weiter in Richtung der Variablentabelle bewegt. Wird nun beim Einbau einer neuen Variablen, eines Variablenfeldes oder eines weiteren Strings mehr Platz be- noetigt, als momentan verfuegbar ist, so werden diese un- gueltigen Strings durch eine Routine namens "GARBAGE COLLECT" (woertlich uebersetzt: Abfallsammlung) beseitigt. Ist nun immer noch nicht genug Platz vorhanden, so wird ein "OUT OF MEMORY" ausgegeben, ansonsten wird die Ausfuehrung normal fortgesetzt. GARBAGE COLLECT kann durch die Funktion 'FRE(O)' erzwungen werden.

Man sollte uebrigens, wenn ein Programm grosse Felder ver- vendet, aus Zeitgruenden normale Variablen VOR der Dimensio- nierung von Feldern anlegen, da sonst, um eine Variable ein- zufuegen, der gesamte Block mit Feldvariablen durch eine sehr zeitaufwendige Routine um sieben Bytes nach oben ver- schoben werden muss.

Nun zum Aufbau von Feldern: Eintraege einzelner Elemente von Feldvariablen sind, im Gegensatz zu nichtindizierten Varia- blen, unterschiedlich lang. 50o benoetigt eine Realvariable zwar, wie sonst auch, fuenf Bytes, um den Wert darzustellen, Integer- und Stringvariablen jedoch werden nun nicht mehr mit Nullen aufgefuellt, sondern nur noch so lang abgespei- chert, wie Werte verwendet werden; zwei Bytes bei Integerva- riablen und drei Bytes bei Strings.

Zu Beginn eines Feldes steht der sogenannte Arrayheader, ein Kopfeintrag, der die Informationen ueber das Feld enthaelt. Dies sind Angaben ueber die Anzahl Dimensionen, die Spalten- laenge(n), die Feldlaenge und natuerlich der Name des Fel- des. Auch hier sind die Namensmarkierungen identisch denen bei nichtindizierten Variablen, auch wenn es natuerlich kei- ne Felder vom Typ 'FN' gibt. Ist das zweite Byte eines Va- riablennamens nicht benutzt, so wird auch hier der Code 0 beziehungsweise 128 (abhaengig vom Variablentyp) als zweites Zeichen gespeichert.

Hier ein schematischer Aufbau des Arrayheaders:

Byte O0 |Byte 1 |Byte 2 | Byte 3 |Byte 4 |Byte 5 |Byte 6 erstes | zweites| Feldlaenge in Anzahl | Spaltenlaenge Zeichen! Zeichen] LH Darstellung | Dimens.| HL Darstellung!

Byte 5 und 6 werden, je nach Anzahl an Dimensionen, wieder- holt. Dabei muss beachtet werden, dass die letzte Spaltenan- gabe beim DIM-Befeh]l als erster Eintrag abgespeichert wird. Ausserdem wird die Spaltenlaenge und nicht die Zahl beim DIM-Befehl im Arrayheader eingetragen, da schliesslich noch ein Element mit dem Index Null existiert (der Wert im Kopf- eintrag ist also um eins hoeher als der Parameter im DIM-Be- fehl).

18

Hierzu ein Beispiel: ein Stringfeld soll durch folgenden DIM-Befehl angelegt werden:

DIM X5$ (2,5,567)

Das Feld wird nun folgendermassen im Arbeitsspeicher abge- legt:

Feldadresse Inhalt Bedeutung

plus ... 0 88 Code fuer "X" (Bit 7 geloescht) 1 181 Code fuer "5" (Bit 7 gesetzt) 2 219 Feldlaenge in Low/High Darstellung 3 119 (ist hier gleich 30683) 4 3 Anzahl an Dimensionen des Feldes 5 2 Wert 568 fuer Spaltenlaenge 6 56 (High/Low Darstellung!) 7 0 Wert 6 fuer Spaltenlaenge 8 6 9 0 Wert 3 fuer Spaltenlaenge 10 3 ll - Stringlaenge fuer Element (0,0,0) 12 - zugehoerige Startadresse in 13 - Low/High Darstellung ... San 10222 weitere Stringelemente 30680 - Stringlaenge fuer Element (2,5,567) 30681 - zugehoerige Startadresse in 30682 - Low/High Darstellung

Die Zaehlweise der Elemente innerhalb des Feldes geht fol- gendermassen vor sich: Die erste Spalte ist die "niedervwer- tigste Spalte", die letzte die "hoechstvertigste". Der auf den ersten Eintrag im obigen Beispiel folgende Eintrag waere der des Elements (1,0,0), darauf (2,0,0) und dann (0,1,0) und so weiter.

Nun ist es auch einfach, eine Methode zur Berechnung der Laenge eines Feldes zu entwickeln. Man multipliziert die um eins erhoehten (Null-Eintrag!) Parameter des DIM-Befehls miteinander, multipliziert dies mit der Laenge eines Ein- trags (Real = 5, String = 3, Integer = 2) und addiert dazu den Wert fuenf und die doppelte Anzahl Dimensionen. Das obi- ge Feld belegt nach dieser Formel

(2+1) * (5+1) * (567 +1) * 3+5+3%*2

; gleich 30683 Bytes. Dies ermoeglicht es in Programmen, den Anwender auf eine freundlichere Art als "OUT OF MEMORY" darauf aufmerksam zu machen, dass der Arbeitsspeicher nicht ausreicht. Man muss vor Ausfuehrung des DIMs nur die Feld- laenge mit dem noch freien Platz vergleichen.

19

DIE VERWENDUNG DER USR-FUNKTION

Das Commodore-BASIC verfuegt ueber eine Funktion mit dem Na- men "USR". Waehrend man im Normalfall durch Verwendung die- ser Funktion nur einen "?ILLEGAL QUANTITY ERROR" erzielen kann, so koennen durch Maschinenprogramme der "USR"-Funktion viele Bedeutungen (fast) aller Art zugeviesen werden. Eine dieser speziellen Aufgaben ist zum Beispiel die "PEEK"-Funk- tion, die immer den Inhalt des RAMs liest (siehe Speicher- verwaltung). Auch das Arbeiten mit der internen Uhr (siehe CIA, Time of Day) erfaehrt eine erhebliche Vereinfachung, wenn man ein geeignetes Programm zur Bedienung der Uhr an- wendet. Um ein problemloses Implementieren eigener Funktio- nen so einfach wie moeglich zu machen, hier eine Beschrei- bung:

Die Funktion "USR" ist eine Funktion wie jede andere auch, sei es nun eine mathematische Funktion wie "SIN" oder "EXP", eine spezielle Funktion im Zusammenhang mit Strings (zum Beispiel "VAL" oder "CHR$") oder nur etwas systemspezifi- sches wie "PEEK" oder "FRE". Allen diesen Funktionen, deren Interpretercodes im Bereich von 180 bis 199 liegen, ist ge- meinsam, dass sie EIN Argument benoetigen, auch wenn es (vie im Falle von "POS" und "FRE") nicht beachtet wird, dessen Typ (numerisch oder String) festgelegt ist. Alle diese Funk- tionen liefern ausserdem EIN vom Typ her festgelegtes Ergeb- nis.

In der gleichen Weise funktioniert die "USR"-Funktion auch. Man gibt ein Argument mit und erhaelt ein Ergebnis. Der je- weilige Typ (sowohl Argument, als auch Ergebnis) wird durch das zugehoerige Maschinenprogramm festgelegt und kann nicht nur, wie dies besonders in Literatur zum PET und zu den CBMs immer wieder behauptet wird, im Integerbereich von -32767 bis 32767 liegen.

Die vom Betriebssystem festgelegte Startadresse der USR- Funktion ist 784 (siehe Vektortabelle der BASIC-Funktionen). Dort befindet sich aber der sogenannte USR-Vektor, also, ein "JMP", dessen Argument vom Benutzer festzulegen ist. Im Nor- malfall zeigt das Argument dieses "JMP"-Befehls (Code 76, dezimal) auf die Fehlermeldung "?ILLEGAL QUANTITY ERROR", vodurch dieser Fehler auch bei Nichtsetzen des USR-Vektors und Benutzung des Befehls auftritt. Soll also das Maschinen- programm zur Definition der USR-Funktion beispielsweise an der Adresse 828 (Cassettenpuffer) beginnen, so muss dies dem Computer durch

POKE 785, 60 : POKE 786, 3

... mitgeteilt werden. Die Reihenfolge der Abspeicherung ist natuerlich low/high. Nun zur Struktur von Funktionen im all- gemeinen:

Das Betriebssystem wertet beim Erkennen einer Funktion (die Funktionen LEFT$, RIGHT$ und MID$ bilden eine Ausnahme, da sie mehrere Argumente benoetigen) das im Klammern stehende Argument, unabhaengig vom Typ des Arguments, aus. Sollte. es sich bei dem Argument um einen numerischen Ausdruck handeln, so wird diese Zahl im Fliesskommaaccu #1 (Floatingpoint ACcumulator, FAC) abgelegt. Dabei handelt es sich um das Hauptrechenregister des Microsoft-BASICs. Dieses Argument kann dann durch Betriebssystemroutinen entsprechend weiter- verarbeitet werden. Eine Unterscheidung zwischen Realzahlen und Integerzahlen wird hier nicht gemacht.

20

Handelt es sich jedoch um ein Argument des Typs String, so wird der Descriptor (bestehend aus drei Bytes, die die Laen- ge und Startadresse festlegen) dieses Strings in die De- scriptortabelle gebracht. Durch die Routine "FRESTR" (Ein- sprungadresse 46755) wird zuerst geprueft, ob es sich bei dem Argument auch um einen String handelt. Daraufhin wird der durch den String belegte Speicherbereich wieder freige- geben und der Pointer (34/35) auf die Startadresse des Strings gesetzt. Der Accu enthaelt nach Rueckkehr die Stringlaenge.

Mit diesen Angaben kann nun die Auswertung beginnen: Als Beispiel soll hier eine mathematische Funktion dienen: die im Commodore-BASIC nicht implementierte Umkehrfunktion zur SINUS-Funktion. Die Umrechnungsformel lautet

ARC SIN (X) = ATN (X / SQR (1-X*xX))

Sollen von Maschinensprache aus Funktionen ausgevertet ver- den, so muss das Argument sich in FAC befinden. Nach Aufruf durch "JSR" befindet sich ebenfalls in FAC das Ergebnis. Fuer Operationen wie "-" oder "*" muss anders vorgegangen verden. Hier muss der erste Wert in das Rechenregister ARG (floatingpoint ARGument) uebertragen verden, der zweite Wert zur Ausfuehrung der Operation befindet sich (vie das Ergeb- nis der Operation auch) in FAC. Es muss also die Funktion zerlegt werden, aehnlich wie sie auf einem UPN-Taschenrech- ner eingegeben wuerde.

Nun die theoretische Vorgehensweise zur Berechnung dieser Funktion (das Argument "X" befindet sich in FAC):

"X" muss quadriert werden, also wird FAC in ARG kopiert und dann FAC mit ARG multipliziert, Ergebnis bereits in FAC.

Dieses Ergebnis muss nun von der Zahl "]" subtrahiert wer- den. Dazu wird die Konstante "1" in ARG wuebertragen, davon wird FAC, der das Ergebnis der vorherigen Operation ent- haelt, subtrahiert.

Daraus wird die Wurzel gezogen, was einfach durch Aufruf der "SQR"-Routine erfolgen kann. Nun muss das in FAC abgelegte Zwischenergebnis durch "X", also das urspruengliche Argu- ment, geteilt werden. Da dieses Argument aber mittlerweile nicht mehr verfuegbar ist, muss es also zu Beginn des Ma- schinenprogramms in einen Bereich webertragen werden, der durch keine bis hierhin verwendete Berechnung ueberschrieben wird. Dieses gerettete Argument wird sodann in ARG uebertra- gen und die Divisionsroutine aufgerufen.

Zum Abschluss erfolgt ein Sprung zur "ATN"-Routine, die dann noch den Arcustangens in FAC bringt. Da das Endergebnis ei- ner Funktion sich in FAC befinden muss, ist keine weitere Behandlung des Ergebnis der "ATN"-Routine mehr noetig.

21

Hier nun das Maschinenprogramm zur Ausfuehrung der Berech- nung:

828 LDX #0 (XR/YR) := 256

830 LDY #

832 JSR 48084 > FAC nach 256 bis 260 retten

835 JISR 48140 > FAC nach ARG uebertragen

838 LDA 97 Exponentbyte in Accu fuer Nullpruefung 840 JSR 47659 > FAC := ARG * FAC

843 LDA #188 (Accu/YR) := 47548

845 LDY #185 Startadresse der Konstanten "1"

848 JSR 47184 ) FAC := Konstante / FAC

851 JSR 49009 > FAC := SQR (FAC)

854 LDA #0 (Accu/YR) := 256

856 LDY #1 Startadresse des geretteten Arguments 858 JSR 47887 > FAC := Konstante / FAC

861 JMP 58126 > FAC := ATN (FAC)

Das zugehoerige BASIC-Programm zum Einlesen der Maschinen- routine:

100 FOR I = 828 TO 862 : READ A : POKE I, A : NEXT

110 POKE 785, 60 : POKE 786, 3

120 DATA 162, , 160, 1, 32, 212, 187, 32, 12, 188, 165, 97 130 DATA 32, 43, 186, 169, 188, 160, 185, 32, 80, 184, 32 140 DATA 113, 191, 169, , 160, 1, 32, 15, 187, 76, 14, 227

Vielleicht ist es Ihnen aufgefallen, dass nicht der Typ des Arguments geprueft wurde. Dieser kann durch den Inhalt der Adresse 13 (siehe Memory Map) oder durch Aufruf der entspre- chenden Routine zur Pruefung des Ausdrucktyps festgestellt verden. Dies ist jedoch nicht noetig, da die Adresse )3 durch Berechnungen nicht geaendert wird. Daher ist nach Be- endigung der Berechnung diese Flag im Falle eines Stringar- guments noch immer auf "String" gesetzt. Da jedoch bei die- ser Funktion ein numerisches Ergebnis erwartet wird, erfolgt die Ausgabe von "?TYPE MISMATCH ERROR", falls ein Stringar- gument mitgegeben wurde.

Hat eine Funktion ein Ergebnis des Typs String, so muss an- ders vorgegangen werden, da eine direkte Rueckkehr zur auf- rufenden Auswertungsroutine mittels "RTS" nur bei numeri- schem Resultat erfolgen darf. Zuerst muss fuer den Ergebnis- string der Funktion Platz im Arbeitsspeicher geschaffen vwer- den. Zu diesem Zeitpunkt muss die Laenge des Ergebnisstrings bekannt sein, da bei Aufruf der Routine 46205 der Accu die Laenge enthalten muss. Entsprechend dieser Angabe wird dann Platz im Arbeitsspeicher geschaffen. Registerpaar (98/99) zeigt dann auf die Startadresse dieses Bereichs. Ist alles abgespeichert worden, so muss nun die Ruecksprungadresse in die Auswertungsschleife mittels "PLA", "PLA" vom Stack ge- holt werden. Durch "JMP 46282" wird dann der Descriptor :des im oberen Stringbereich abgelegten Strings in die Descrip- tortabelle gebracht. Ein verstaendliches Beispiel fuer die- ses Prinzip ist die Funktion "CHR$" ab der Adresse 46828.

22

STEUERCODES FUER DEN COMMODORE 64

000: - 128: -

001: - 129: ORANGE: Cursorfarbe orange 002: - 130: -

C03: RUNSTOP 131: Shift RUNSTOP

004: - 132: -

005: WHITE: Cursorfarbe weiss 133; Fl Codes fuer die

006: - 134: F3 Funktionstasten

007: - 135: F5

008: Shift + Commodore blockieren 136: F7

009: Shift + Commodore freigeben 137: F2

010: - 138: F4

Oll: - 139: F6

0l2: - 140: FB

013: RETURN 141: Shift RETURN

014: Gross- und Kleinschrift 142: Grossschrift und Graphik

015: - 143: -

016: - 144: BLACK: Cursorfarbe schwarz 017: CURSOR DOWN: Cursor nach unten 145: CURSOR UP: Cursor nach oben 018: REVERS DON: Negativdruck 146: REVERS OFF: Positivdruck

019: HOME: Cursor nach oben links 147: CLEAR SCREEN: Bildschirm loeschen 020: DELETE: Zeichen loeschen 148: INSERT: Zeichen einfuegen

021: - 149: BROWN: Cursorfarbe braun

022: - 150: LT. RED: Cursorfarbe rosa

023: - 151: GRAY 1: Cursorfarbe dunkelgrau 024: - 152: GRAY 2: Cursorfarbe mittelgrau 025: - 153: LT. GREEN: ”’Cursorfarbe hellgruen 026: - 154: LT. BLUE: Cursorfarbe hellblau 027: - 155: GRAY 3: Cursorfarbe hellgrau 028: RED: Cursorfarbe rot 156: PURPLE: Cursorfarbe purpur 029: CURSOR RIGHT: Cursor nach rechts 157: CURSOR LEFT: Cursor nach links 030: GREEN: Cursorfarbe gruen 158: YELLOW: Cursorfarbe gelb

031: BLUE: Cursorfarbe blau 159: CYAN: Cursorfarbe cyan Nichtaufgefuehrte Codes haben in der Standardversion des Betriebssystems

keinerlei Wirkung.

Saemtliche angegeben Steuercodes sind ueber die CHR$-Funktion sowie, von 142 abgesehen, auch ueber die Tastatur erreichbar.

Die Codes 013, 131, lM41 und im Normalfall auch 020 und 148 werden immer ausgefuehrt und bewirken keine Ausgabe von Steuersymbolen. Sie sollten bei verwendung in Programmen daher ueber der CHR$-Funktion programmiert werden.

Die Codes 003, 131 sowie 133 bis 140 (Funktionstasten) haben bei der Ausgabe keinerlei Funktion und finden daher im Normalfall wohl nur zur Abfrage der Tasten Verwendäng. Lediglich der Code 13] hat ueber die Programmierung des Tastaturpuffers die Funktion, die er auch im Normalfall hat, das Einladen und Starten von Cassettenprogrammen.

Die Codes von 000 bis 031 sind unter anderem auch durch Druecken der Control-Taste zusammen mit einer der Tasten von "WW", "A" bis "zZ", ":", *"Pound', „,;", "&" und "=" erreichbar, es gelten jedoch auch hier die oben gemachten Ein- schraenkungen.

23

STELERCODES IN LISTINGS

Waehrend zich heim FET 2001 die Anzahl der Steuercades mach im Rahmen hielt, sc sikt es keim Commadore 854 schan insge- samt 42 Codes, die irgendeine Bedeutung haken. Besonders keim Eintippen von Listings ist es notwendig. das Steuerzei- chen mit der Taste (die diesen [ode erzeugt) in Verkindung zu krinrgen. Deshalk eine Aufstelluna aller »erwendeten Steu- erccdes: Es wird jeweils das pasitive zum besseren Erken- nen» und das neastive Zeichen “dss in den Listings vorkommt)» ansgegeker. Ruch werden keide Darstellunasmodi Graphik und Kleinschrift> beruecksichtist:

-— RUNSTOP

-— Control E- Contrcl H

Control I. Control N

- Control D, CURSOR DOuN

- Control R., Control 93

—-— Control S. HOME

-— DELETE. CHF$i\ 20)

- Control £. Cantrol 23

—-— Cantraoal :, CURSOR RIGHT - Cantrcal - Control &

- Control =, Control 7

- Commodore 1

-— Shift-RUNSTOP

- Fi

- F3

- FS

- F7

- F2

- Fa

-

- FS3

CHR$U142)

- Control 1

CURSOR UP

- Control 8

CLEAR SCREEN

INSERT. CHR$ 1485

- Commodore —- Commodore - Commodore —-— Lommadeore - Commodare - Commodore - Commodore - Control 5 - CURSOR LEFT - Control 3

-— Control 4

Central 2

Es U nd 29 ed u Bu Li [al |

+Nn I2I3I-Fon

IIStrt>u AWO ZITIMN I >

«

)

r

[

“._ ANIO TDTZTFTR“MHM TOTNTMNID

WE Ge ee a [ee En Di Isa Ei Ina ma ia iz ER En = I a an I bi |

u

KE<

N-

BR, FDBSEUBSSEU AMELIE EN EEE u IE I BR EI bi ED a ei ee Du Be I I DNS Bw m

A3—- "HR _LIUNX-

De PR

24

EINFUEHRUNG IN DIE ASSEMBLER-PROGRAMMIERUNG

Das "Herz" eines jeden Mikrocomputers ist der Mikroprozes- sor. Im VIC 20 ist ein Mikroprozessor des Typs "6502" einge- baut, im Commodore 64 ein "6510". Beide sind bezueglich der Programmierung in Assembler voellig identisch.

Jeder Mikroprozessor kann eine bestimmte Anzahl von genau definierten Assembler-Anweisungen verstehen und ausfuehren, etwa so, wie ein BASIC-Interpreter bestimmte BASIC-Befehle verarbeiten kann. Derjenige, der diese Assembler-Anweisungen beherrscht, kann also direkt den Mikroprozessor program- mieren.

Programme, die in Assembler geschrieben sind, laufen wesent- lich schneller ab als in BASIC und koennen die Moeglich- keiten des Computers viel besser ausnutzen. Fuer jeden fort- geschrittenen Programmierer ist daher die Beherrschung der Assembler-Sprache unerlaeßlich.

Um erfolgreich in Assembler programmieren zu koennen, ist es wichtig, den Aufbau des Computers zu kennen.

Jeder Computer besteht aus einer Vielzahl von kleinen Schaltern, die entweder offen sind (es fließt kein Strom) oder geschlossen (es fließt Strom). Natuerlich handelt es sich dabei nicht um mechanische Schalter, sondern vielmehr um Schaltelemente, die in IC-Bausteinen ("Chips") unterge- bracht sind. Einen solchen einzelnen Schalter nennt man "Bit" und statt "offen" und "geschlossen" redet der Fachmann von zwei "Zustaenden", die er "0" und "1" nennt. Ein solches System heißt "binaer", "zweier Zustaende faehig".

Der 6502/6510 Mikroprozessor ist derart aufgebaut, daß er jeweils 8 Bits gleichzeitig verarbeitet. Eine solche Einheit von B Bits nennen wir "Byte". Ein Beispiel fuer ein Byte ist "00110101".

l Byte = (z.B.) 0011071071 Bit Nummer 65 43 210

Wie Sie sehen, werden die einzelnen Bits eines Bytes von rechts nach links von O0 bis 7 durchnumeriert.

Nun ist der gesamte Computerspeicher aufgebaut aus einzelnen "Speicherzellen", wobei jede Zelle genau ein Byte groß ist. Sie koennen sich das ungefaehr so vorstellen:

Speicherzelle 0: 10101010 = 8 Bit = 1 Byte Speicherzelle 1: 01101101 Speicherzelle 2: 00011001 Speicherzelle 655335: 01000011

Die Bytes unterscheiden sich dadurch voneinander, daß sie zum Teil unterschiedliche Bitkombinationen (z.B. "01000011") enthalten. Man redet auch davon, daß ein Bit "gesetzt" (= ]) oder "geloescht (= 0) ist. Die in der Skizze genannten Bit- kombinationen sind willkuerlich gewaehlt.

Da 8 Bits nur 256 verschiedene Kombinationen darstellen koennen, kann der Mikroprozessar 6502/6510 grundsaetzlich nur Zahlen von 0 bis 255 bearbeiten (s. auch Kapitel "Binaerarithmetik").

25

Kombination 0: 0000000 Kombination 1: 0000001" Kombination 2: 00000710 Kombination 3: 0000011 Kombination 4: 0000100 Kombination 255: 1l1ı1l1 111

Sie sehen, daß jeder Bitkombination, also jedem Byte, ein bestimmter dezimaler Wert von O bis 255 zugeordnet ist. Wenn Sie z.B. "POKE3,255" eingeben, so bedeutet das nichts anderes, als daß in die Speicherzelle 3 die Bitkombination "11111111" eingeschrieben wird.

Der Speicher besteht aus einzelnen Speicherzellen von der Groeße eines Bytes, die prinzipiell voellig gleich sind. Wir unterscheiden jedoch unterschiedliche Funktionsbereiche wie Programm- und Variablenspeicher, Betriebssystem- und BASIC- Interpreter-Bereich, Ein-/Ausgabespeicher, Betriebssystem- zwischenspeicher u.a. Das vorliegende Buch erlaeutert die Arbeitsweise jedes einzelnen Funktionsbereiches im Detail. Dabei gibt es sog. "RAM-Speicher" und "ROM-Speicher". "RAM" bedeutet, daß Daten eingeschrieben und auch wieder gelesen werden koennen (z.B. Programm- und Variablenspeicher), "ROM" hingegen meint, daß der betreffende Speicherbereich aus- schließlich gelesen, nicht aber durch anderen Daten ueber- schrieben (veraendert) werden kann (z.B. BASIC-Interpreter).

Machen Sie sich klar, daß der gesamte Computerspeicher aus einzelnen Speicherzellen besteht, die wiederum Zahlen bein- halten. Diese Zahlen haben allerdings ganz verschiedene Bedeutungen, es kann sich um ein BASIC-Programm handeln, oder um ein Assembler-Programm, oder auch um Daten.

Sehen wir uns nun - ausgeruestet mit einem Minimum an theoretischen Wissen - das erste Assembler-Programm an. Um das Programm in den Computer eingeben zu koennen, benoetigen wir noch ein sog. "Assembler-System", das unsere Assembler- Anweisungen in reinen Zahlencode umsetzt. Sie finden ein solches - allerdings sehr einfaches Assembler-System - im Anschluß an dieses Kapitel. Es ist sicher sinnvoll, wenn Sie sich zunaechst dort mit der Bedienung vertraut machen. Sie koennen dann gleich die erklaerten Beispiele nachvollziehen.

Commodore 64 VC-20 (bis 8K) VC-20 (groeßer BK) 828 LDA #65 828 LDA #65 828 LDA #65 830 STA 1024 830 STA 7680 830 STA 4096 833 LDA #3 833 LDA #3 833 LDA #3 835 STA 55296 835 STA 38400 835 STA 37888 838 RTS 838 RTS 838 RTS

Um das Programm auszuprobieren, geben Sie von BASIC aus SYS 828 (RETURN) ein. Es sollte sodann ein Zeichen in der linken oberen Bildschirmecke zu sehen sein. Jeder Assembler-Schritt besteht aus:

828 LDA #65

Adresse Assemblerbefehlswort Argument ("auch Mnemonic")

26

Die "Adresse" gibt an, ab welcher Speicherzelle die Assembler-Anweisung beginnt. Es existieren insgesamt 65536 verschiedene Speicherzellen, die die Adressen von 0 bis 65535 tragen. Jede Assembler-Anweisung belegt je nach Befehl l bis 3 Bytes. Der Adresse folgt das eigentliche Assembler- Befehlswort, im Beispiel "LDA". Sie finden in diesem Buch ein Verzeichnis aller gqueltigen Befehlsworte. Dem Befehls- wort kann - je nach Befehl - noch ein Argument folgen, in unserem Beispiel "Doppelkreuz 65". Es gibt auch Assembler- Anweisungen ohne Argument. Schließlich existieren ja auch in BASIC Befehle mit und ohne Argument (z.B. POKE mit zwei Argumenten, STOP ohne Argument).

Das Befehlswort "LDA" steht fuer "load accumulator", "Lade Akkumulator", oder in diesem Fall "Lade Akkumulator mit dem Wert 65". "STA" bedeutet "store accumulator", "speichere

Akkumulator an der angegebenen Adresse ab".

Um das verstehen zu koennen, muessen Sie wissen, daß es in Assembler im Unterschied zu BASIC keine Variablen gibt. Als Ersatz dafuer existieren in Asembler drei "Register", naemlich "Akkumulator", "X-Register" und "Y-Register". Ein solches Register kann Werte von 0 bis 255 beinhalten. Jetzt koennen Sie das Programm verstehen (beispielhaft fuer den Commodore 64):

828 LDA #65 ;sAkkumulator mit dem Wert 65 laden

830 STA 1024 ;sdiese 65 in Speicherzelle 1024 speichern 833 LDA #3 sAkkumulator mit dem Wert 3 laden und

835 STA 55296 sdie 3 in Speicherzelle 55296 speichern 838 RTS ;sbeendet jedes Assembler-Programm

Beachten Sie die Bedeutung des Doppelkreuz-Zeichens: Der Akkumulator wird direkt mit dem Wert 65 geladen (und nicht mit dem Wert, der in der Speicherzelle 65 steht, was auch moeglich waere). Hingegen wird diese 65 dann in Speicher- zelle 1024 abgespeichert. Die Anweisung RTS ("return from subroutine", "Rueckkehr aus einer Unterroutine") muß unbe- dingt am Ende jedes Assemblerprogramms stehen. Andernfalls geraet der Computer im allgemeinen in einen voellig wunkon- trollierten Zustand ("Absturz"), da er versucht, weitere An- weisungen auszufuehren, obwohl kein gueltiger Assemblercode mehr vorhanden ist.

Warum unser Programm ein Zeichen auf dem Bildschirm ausgibt? Nun, Speicherzelle 1024 (Commodore 64) entspricht der linken oberen Bildschirmposition (Zeichencode), Speicherzelle 55296 bestimmt die Farbe eben dieser Position. Experimentieren Sie selbstaendig in dieser Richtung, indem Sie statt 65 andere Werte zwischen O0 und 255 nehmen, statt der 3 andere Werte von O bis 7 (VIC 20) bzw. von O bis 15 (Commodore 64).

Assembler BASIC 828 LDA #65 828 A = 65 830 STA 1024 830 POKE 1024, A 833 LDA #3 833A= 3 835 STA 55296 835 POKE 55296, A 838 RTS 838 END Natuerlich existieren in Assembler noch eine Vielzahl

anderer Befehlsworte. Ein Teil davon ist den bereits gelernten so aehnlich, daß Sie sie sofort verstehen werden.

27

Fuer das X- und Y-Register lauten die Befehlsworte zum Laden und Abspeichern wie folgt:

Assembler Funktion BASIC-Entsprechung LDX #wert laedt X-Register X = wert STX adresse speichert X-Register POKE adresse, X LDY #wert laedt Y-Register Y= wert STY adresse speichert Y-Register POKE adresse, Y

X- und Y-Register sind - genau wie der Akkumulator - interne

Register des Mikroprozessors von der Groeße eines Bytes. Sie koennen also Zahlen von O bis 255 enthalten.

Um einen Text auf dem Bildschirm auszugeben, wird dieser einfach Zeichen fuer Zeichen mit LD? (LDA, LDX oder LDY) in ein Register geladen und mit ST? an die entsprechende Bildschirmposition gebracht. Außerdem muß die korrespon- dierende Speicherzelle des Farbspeichers mit einem Farbwert versehen werden (s. auch Kapitel "Bildschirmspeicher" und "Farbspeicher").

Weitere wichtige Assembler-Befehle in Bezug auf die Prozes- sorregister sind Anweisungen zum Erhoehen und Erniedrigen der Register:

Assembler Funktion BASIC-Entsprechung INX erhoeht X-Reg. um eins X=X+]1 DEX erniedrigt X-Reg. um eins X=X-] INY erhoeht Y-Reg. um eins Y=Y+]l DEY srniedrigt Y-Reg. um eins Y=Y-]l

Diese Anweisungen benoetigen kein Argument. Ein entsprechen- der Befehl zum Inkrementieren oder Dekrementieren des Akku- mulators existiert nicht. Hingegen gibt es die Moeglichkeit, einzelne Speicherzellen direkt um eins zu erhoehen oder zu erniedrigen.

Assembler BASIC-Entsprechung INC adresse POKE adresse, PEEK(adresse) + 1 . DEC adresse POKE adresse, PEEK(adresse) - 1]

Ein Beispielprogramm soll Ihnen die Moeglichkeiten der In- krement/Dekrement-Anweisungen verdeutlichen (Commodore 64):

Assembler Funktion BASIC-Entsprechung 830 LDX #0 ;Schleifenzaehler 830X=0

832 LDA #42 ;sZeichencode "*" 832 A = 42

834 STA 1024,X ;Bildschirmspeicher 834 POKE 1024+X,A

837 LDA #3 ;Farbzahl 837 A=3

839 STA 55296,X ;Farbspeicher 839 POKE 55296+X,A 842 INX ;X-Reg. von O0 bis 8422 X=X +1

843 CPX #50 ;50 zaehlen und

845 BNE 832 ;Sprung zu 832 845 IFX 5O0THENB32 847 RTS ;Programmende 847 END

Anpassung fuer VIC 20: bis 8K: 7680 statt 1024, 38400 statt 55296; ueber 8K: 4096 statt 1024, 37888 statt 55296. Geben Sie das Programm ein und starten Sie es mit SYS 830. Es sollten 50 farbige Sternchen zu sehen sein.

28

Experimentieren Sie selbstaendig: Ersetzen Sie einmal die 42 durch andere Werte von OD bis 255, die 3 durch andere Werte von O0 bis 7 (VIC 20) bzw. von O bis 15 (Commodore 64), die 50 durch andere Werte von OD bis 255.

Zur Erklaerung: Mit Hilfe des X-Registers wird eine Schleife programmiert, die von DO bis 50 zaehlt. INX bewirkt jeweils die Erhoehung um eins. "CPX" steht dabei fuer "compare x- register", "vergleiche X-Register", in diesem fall mit 50. Darauf folgt die BNE-Anweisung. "BNE" bedeutet "branch on not equal", "verzweige bei Ungleichheit". Mit anderen Wor-: ten: Solange das X-Register noch nicht gleich 50 ist, wird zu Adresse 832 zurueckgesprungen. CPX und BNE hintereinander entsprechen in BASIC einer IF-THEN-Anweisung (bedingte Sprunganweisung mit logischem Vergleich).

Insgesamt existieren in Assembler drei Vergleichsbefehle:

Assembler Funktion

CMP #wert vergleicht Akkumulator mit dem Wert CPX #wert vergleicht X-Register mit dem Wert CPY #wert vergleicht Y-Register mit dem Wert

Entsprechungen in BASIC gibt es nicht. Auf jede Vergleichs- anweisung folgt ein sog. "Branch-Befehl", in unserem Bei- spiel ist das "BNE". Das ist ungefaehr so, wie in BASIC auf IF in jedem Fall THEN folgen muß.

Damit existieren in Assembler die folgenden Moeglichkeiten bedingter Sprunganweisungen:

Sprung bei Gleichheit: CMP #wert BEQ adresse

Sprung bei Ungleichheit: CMP #wert BNE adresse

Sprung bei 'kleiner als': CMP #wert BCC adresse

Sprung bei 'groesser/gleich': CMP #$wert BCS adresse

Wir moechten allerdings an dieser Stelle ausdruecklich darauf hinweisen, dass die Erklaerungen im Rahmen dieser "Einfuehrung in die Assembler-Programmierung" stark verein- facht und keineswegs vollstaendig sind. Ein umfassender systematischer Assembler-Kurs wuerde den Rahmen dieses Buches sprengen. Allen wirklich Interessierten empfehlen wir unseren "6502-Assembler-Kurs fuer Beginner", ISBN 3-88986- 000-1. Schließlich ist ein Systemhandbuch weder ein BASIC- noch ein Assembler-Lehrbuch.

Soll ein Sprung unabhaengig von irgendwelchen Bedingungen erfolgen, so wird dies in Assembler mit dem Befehlen JMP (normaler Sprung) oder JSR (Unterprogrammsprung) erreicht. "JMP" steht fuer "jump", "Sprung", "JSR" bedeutet "jump to subroutine", "Sprung zu Unterprogramm".

Assembler Funktion BASIC-Entsprechung JMP adresse Sprung GOTO zeilennummer JSR adresse Unterprogrammsprung GOSUB zeilennummer

29

Die Rueckkehr aus einem Unterprogramm erfolgt mittels RTS, "return from subroutine".

Assembler Funktion BASIC-Entsprechung RTS Ruecksprung aus RETURN Unterprogramm

Es wird Ihnen auffallen, daß dies derselbe Befehl ist, mit dem jedes Assembler-Programm enden muß. Der Grund dafuer ist recht einfach: Von BASIC aus wird jedes Assembler-Programm als Unterprogramm aufgerufen (SYS, USR), folglich muß es auch wie ein Unterprogramm abgeschlossen werden.

Wie Sie bereits wissen, gibt es drei Arbeitsregister in der CPU 6502/6510: Akkumulator sowie X- und Y-Register. Der Transfer von Daten zwischen diesen Registern erfolgt mit den folgenden Anweisungen:

Assembler Funktion: BASIC-Entsprechung transferiert...

TAX Akku nach X-Register x = A

TAY Akku nach Y-Register vV=A

TXA X-Register nach Akku A=X

TYA Y-Register nach Akku A=Y

Beispiel: Im Rahmen eines groesseren Programmes sollen Akku- mulator sowie X- und Y-Register mit dem Wert der Speicher- zelle 900 geladen werden (Adressen/Zeilennummern wurden weg- gelassen):

Assembler BASIC LDA 900 A = PEEK(900) TAX X=A TAY Y=A

Beachten Sie, daß diesmal LDA ohne Doppelkreuz verwendet wird, da hier nicht der Wert 900 gemeint ist, sondern die Speicherzelle mit der Adresse 900.

Zwei weitere wichtige Befehle zum Addieren und Subtrahieren in Assembler sollten Sie noch kennenlernen. Die Befehlswor- te lauten "ADC", "add with carry", "Addiere mit Uebertrag" und "SBC", "subtract with carry", "Subtrahiere mit Ueber- trag". Wichtig in diesem Zusammenhang ist das sog. "Carry- Bit" oder "Carry-Flag" zur Bestimmung des Uebertrages (Zum Begriff "Flag" s. auch Kapitel "Binaerarithmetik"). Der Vor- gang ist im Grunde recht einfach: Der Mikroprozessor 6502/ 6510 kann - wie Sie wissen - nur Zahlen von O bis 255 verar- beiten. Daher muß vor jeder Addition das Carry-Bit ge- loescht (= 0) werden. Dann werden die beiden Zahlen addiert und ist das Ergebnis groesser als 255, so wird das Carry-Bit gesetzt (= 1), andernfalls bleibt es geloescht.

828 LDA #24 ;laedt Akku mit dem Wert 24

830 CLC sloescht Carry-Bit (CLC, "clear carry") 831 ADC #68 saddiert den Wert 68 zu dem Wert 24

833 STA 850 ;speichert Ergebnis (92) nach Adresse 850 836 RTS ;Programmende

Das Ergebnis der Addition kann von BASIC aus mit ?PEEK(850) abgefragt werden; gestartet wird das Programm mit SYS 828.

30

Die Subtraktion wird in Assembler aehnlich programmiert, nur darf dabei das Carry-Bit vorher nicht geloescht, sondern muss im Gegenteil gesetzt werden:

828 LDA #128 ;laedt Akku mit dem Wert 128

830 SEC ;ssetzt Carry-Bit (SEC, "set carry")

831 SBC #6 ;ssubtrahiert den Wert 6 von 128

833 STA 850 ;speichert Ergebnis(122) nach Adresse 850 836 RTS ;Programmende

Ist das Ergebnis der Subtraktion im "normalen" Bereich von OD bis 255, so bleibt das Carry-Bit unveraendert gesetzt, andernfalls wird es geloescht.

Mit BCC und BCS laeßt sich der Zustand des Carry-Bits fest- stellen. "BCC" bedeutet "branch on carry clear", "Sprung bei geloeschtem Carry-Bit", "BCS" hingegen "branch on carry set", "Sprung bei gesetztem Carry-Bit". Sie kennen die An- weisungen BCEC und BCS bereits aus dem Zusammenhang "Bedingte Sprunganweisungen".

828 LDA #128 ;laedt Akku mit dem Wert 128

830 CLC ;ssetzt Carry-Bit (SEC, "set carry")

831 ADC #200 saddiert den Wert 200 zu dem Wert 128 833 BCS 838 ;Sprung nach 838, wenn Carry-Bit gesetzt 835 STA 850 ;speichert Ergebnis nach Adresse 850

838 RTS ;Programmende

In diesem Beispiel wird das Ergebnis nur dann in Speicher- zelle 850 abgespeichert, wenn es im zulaessigen Bereich von 0 bis 255 liegt. Andernfalls wird durch die Addition mit ADC das Carry-Bit gesetzt (Ueberlauf) und die danach folgende BCS-Anweisung verzweigt den Programmablauf zu Adresse 838, die STA-Anweisung bei 835 wird also uwebersprungen. Der Wert in Speicherzelle 850 bleibt in diesem Fall unveraendert. Mit den Beispielwerten 128 und 200 wird dies natuerlich immer der Fall sein - schliesslich ist 328 ja groesser als 255. Probieren Sie einmal andere Werte aus.

Außer dem Carry-Bit oder Carry-Flag - auch "C-Flag" - gibt es noch sechs andere sog. "Statusbits" oder "Statusflags". Alle sieben Statusbits sind im Prozessor zusammengefasst im "Prozessor-Statusregister". Das achte Bit dieses Registers wird nicht genutzt. Im einzelnen heissen die Status-Bits:

negativ result (negatives Ergebnis) overflow (Vorzeichen-Ueberlauf)

break command (Break-Befehl)

decimal mode (Dezimalbetrieb) interrupt disable (Interrupt sperren) zero result (Null-Ergebnis)

Carry

DNTODOD<Z

Es wuerde den Rahmen dieses Einfuehrungskurses sprengen, wollten wir alle Flags erklaeren. Die zwei am haeufigsten anzutreffenden sind N- und Z-Flag.

Das Z-Flag wird immer dann vom Prozessor selbst gesetzt, wenn das Ergebnis des direkt vorausgegangenen Befehls Null ist. Andernfalls wird das Z-Flag geloescht. Ausschnitt aus einem groesseren Programm:

;laedt Akku mit dem Inhalt von Speicher-

900 LDA 1024 ‚zelle (Adresse) 1024 903 BEQ 920 ;Sprung zu 920, wenn Akkuinhalt gleich 0

31

BEQ fragt das Z-Flag ab und bewirkt einen Sprung zu der angegebenen Adresse (920), wenn es gesetzt ist. Das wiederum haengt davon ab, ob das Ergebnis der LDA-Operation Null ist oder nicht. BNE ist das Gegenstueck zu BEQ; bei BNE erfolgt der Sprung dann, wenn das Z-Flag geloescht ist. Sie haben BEQ und BNE bereits im Zusammenhang mit Vergleichsanwei- sungen kennengelernt.

Hier die Befehle zur Abfrage des Prozessor-Statusregisters:

BCC - Sprung bei geloschtem Carry-Flag BCS - Sprung bei gesetztem Carry-Flag BEQ - Sprung bei gesetztem Z-Flag

BNE - Sprung bei geloeschtem Z-Flag BMI - Sprung bei gesetztem N-Flag

BPL - Sprung bei geloeschtem N-Flag BVC - Sprung bei geloeschtem V-Flag BVS - Sprung bei gesetztem V-Flag

Zum Abschluß wollen wir uns jetzt noch ansehen, wie eigent- lich Assembler-Programme im Speicher abgelegt werden. Das ist naemlich fuer das Grundverstaendnis der Programmierung in Assembler recht wichtig.

Der Mikroprozessor ist prinzipiell nur in der Lage, Zahlen zu verarbeiten. Er muß sowohl Daten als auch Steueranwei- sungen als Zahlen erhalten. Deswegen wird jedes Assembler- Programm als eine Folge von Zahlen abgespeichert. Wenn Sie Assembler-Text wie "LDA, "STX" etc. eingeben, so sorgt das betreffende Assembler-System dafuer, dass dieser Text bei Druecken der RETURN-Taste sofort in eine entsprechende Zahlenfolge zerlegt und abgespeichert wird. Daher ist zur Assembler-Programmierung immer auch ein Assembler-System notwendig - egal, ob Sie nun das in diesem Buch abgedruckte einfache System oder ein so komplexes Assembler-System wie

'T.EX.AS.' - "Terminal Extended Assembler" - benutzen. Assemblertext Zahlencode 828 LDA #65 169 65 830 STA 1024 141 0 4 833 LDA #3 169 3 835 STA 55296 141 0 216 838 RTS 96

Das Programm steht wie folgt im Speicher:

Adresse Inhalt (dezimal) Bedeutung 828 169 LDA # 829 65 Argument zu LDA # 830 141 STA 831 0 l. Teilargument zu STA 832 4 2. Teilargument zu STA 833 169 LDA # 834 3 Argument zu LDA # 835 141 STA 836 0 l. Teilargument zu STA 837 216 2. Teilargument zu STA 838 96 RTS

Die Zerlegung einer Zahl in zwei Teilzahlen - genannt LSB

(1. Teilzahl) und MSB (2. Teilzahl) - erfolgt so:

Gesamtzahl = LSB + 256 x MSB

32

Beispiel: 1048 geteilt durch 256 ergibt 4,09375. 4 mal 256 ist gleich 1024. 1048 minus 1024 ergibt 24. Also ist das MSB

gleich 4 und das LSB gleich 24. Denn: 1024 24 + 256 x 4

Die Zerlegung einer Zahl in zwei Teilzahlen ist notwendig, da eine Speicherzelle nur Zahlen von 0 bis 255 aufnehmen kann. Groessere Zahlen werden in zwei aufeinanderfolgenden Speicherzellen eben in zwei Teilzahlen als LSB und MSB dar- gestellt. "LSB" bedeutet "least significant byte", "nieder- wertiges Byte", "MSB" steht fuer "most significant byte", "hoeherwertiges Byte" (s. auch Kapitel "Binaerarithmetik").

Die Zuordnung der Assembler-Befehlsworte zu Zahlen ist stan- dardmaessig festgelegt (STA ist gleich 141 usw.). Neben dem Befehlswort spielt dabei auch die "Adressierungsart" eine Rolle. Sie haben bereits folgende Adressierungsarten kennen- gelernt:

unmittelbar LDA #wert absolut LDA adresse STA adresse LDX adresse STX adresse LDY adresse STY adresse JMP adresse USW. implizit INX DEX INY DEY RTS USW. indiziert STA adresse,X STA adresse,Y USW.

Insgesamt gibt es in Assembler 13 verschiedene Adressie- rungsarten. Die Zuordnung aller Assembler-Befehlsworte in den moeglichen Adressierungsarten zu den entsprechenden Zah- lencodes finden Sie in diesem Buch in der Tabelle "Adressie- rungsarten".

Damit sind wir am Ende dieses "Assembler-Schnellkurses" an- gelangt. Sie sind - falls Sie nicht noch andere Literatur zu Rate gezogen haben - jetzt weder in der Lage ein komplexeres

Assembler-Programm zu lesen noch gar eines zu schreiben. Aber Sie verstehen genug von Assembler, um erstens zu wissen, worum es dabei geht und zweitens sich entscheiden zu koennen, ob Sie sich naeher damit befassen moechten. In diesem Fall moechten wir Ihnen als ausfuehrliches und leicht verstaendliches Lehrbuch nochmals den "6502-Assemblerkurs fuer Beginner", ISBN 3-88986-000-1, empfehlen. Das Buch nimmt speziell Bezug auch auf die Computer Commodore 64 und vVIC 20. Zur fortgeschrittenen Programmierung in Assembler offerieren wir Ihnen unser "'T.EX.AS.' - Assembler Entwick- lungs- und Lehrsystem". Wir wuerden uns jedenfalls freuen, Sie in dem einen oder anderen Werk wieder begruessen zu koennen. INTERFACE AGE VERLAG GMBH, Vohburgerstr. 1, D-8000 Muenchen 21, Tel. (089) 5 80 67 02.

33

ASSEMBLER UND DISASSEMBLER FUER COMMODORE 64 UND VIC-20

Um das Erstellen eigener Maschinenprogramme zu vereinfachen, ist im folgenden ein einfacher, zum groessten Teil in BASIC geschriebener Assembler, abgedruckt. Mit diesem ist es moeg- lich, Maschinenprogramme, Bytes und Adressen einzugeben, wo- bei der Assembler alle notwendigen Umwandlungen selbst vor- nimmt. Auch koennen beliebige Speicherbereiche disassem- bliert werden. Hierzu die genaue Anleitung zur Handhabung dieses Assemblers:

Beim Eintippen des Assemblers muss ganz besonders auf die korrekte Eingabe der DATA-Zeilen geachtet werden. Daher wird empfohlen, den gesamten Text nach der Eingabe noch einmal zu kontrollieren. Auch sollte man den Assembler vor dem ersten Start durch "RUN" erst einmal auf Cassette oder Disc abspei- chern, um sich ein zweites. Eintippen im Falle eines "Abstur- zes" zu ersparen.

Ist der Assembler durch "RUN" gestartet worden, so muss sich nach einigen Sekunden der Computer mit einem blinkenden Cur- sor melden. Nun ist der Assembler eingabebereit und erwartet Ihre Anweisungen.

Jede Eingabezeile MUSS mit einer Adresse im Bereich von 0 bis 65535 beginnen. Bei folgender Eingabe eines Maschinenbe- fehls ist dies die Adresse, ab der der Befehl (gegebenen- falls mit Argument) abgelegt werden soll. So zum Beispiel bei Eingabe des folgenden Beispielprogramms fuer den 64er:

828 LDX #0

830 LDA 646

833 STA 55296,X 836 TXA

837 STA 1024,X 840 INX

841 BNE 830

843 RTS

Wie Sie sicher bemerken, wird automatisch die naechste Adresse nach dem eingegebenen Befehl vorgegeben, aehnlich einem Autonumber fuer BASIC. Auch muss bei Verzweigungsbe- fehlen nicht der Offset angegeben werden, sondern die Abso- lutadresse.

Entsprechend erfolgt die Eingabe von Bytes und Adressen. Auf die Adresse folgt das Byte beziehungsweise die Adresse, die an der angegebenen Adresse abgelegt werden soll. So ent- spricht ...

650 128 .

dem Befehl "POKE 650, 128". Fuer die Eingabe von Adres- sen existiert kein gleichvertiger Befehl im Commodore-BASIC, lediglich EXBASIC besitzt den Befehl "DOKE". So koennte von EXBASIC aus statt ...

785 828

... auch geschrieben werden "DOKE 785, 828" oder in diesem Fall "DEF USR = 828". Soll ein Wert im Bereich von O bis 255 als Pointer abgelegt werden, so muss vor den Wert der Klam- meraffe "®" gesetzt werden, um dem Computer zu zeigen, dass es sich um einen 16-Bit-Wert handelt.

34

Fuer die Ausgabe von Speicherinhalten stehen. drei Befehle zur Auswahl: "D" fuer Daten in Form von Bytes, "A" fuer Adressen und "L" fuer Assemblertext. Die Syntax fuer alle diese Befehle ist gleich:

Startadresse Befehl (Endadresse)

Um den Speicherbereich von 41866 bis 41900 zu disassemblie- ren, muss eingegeben werden ...

41866 L 41900

Leerzeichen koennen, ausser bei der Eingabe von Bytes und Adressen (zur Trennung der Zahlen) entfallen.

Das Verlassen des Assembler erfolgt durch das Kommando "X", wobei auch hier eine Zahl vor dem Buchstaben stehen muss (die allerdings keine Bedeutung hat).

Hinweise fuer VIC-20

Fuer den VIC-20 wird mindestens eine Erweiterung um 3 KB be- noetigt, um mit dem Assembler arbeiten zu koennen. Da jedoch beim VIC-20 kein freier Bereich fuer das Maschinenprogramm zur Verfuegung steht, muss der Anfang des BASIC-Bereichs verlegt werden. Dies muss VOR der Eingabe des Listings sowie VOR dem Einladen geschehen.

VICs mit INSGESAMT 8 KB, also mit 3-KB-Erweiterung: Verlagerung des BASIC-Anfangs:

POKE 44, 5 : POKE 1280, O

Programmaenderungen (Position im Listing unterstrichen):

110 FORI=1025101240:... 120 SYS1117:... 470 DATA...11,4... 490 DATA...11,4...

Aufhebung der Verlagerung:

POKE 44, 4 : NEW

VICs mit MEHR ALS 8 KB, also mit B oder 16-KB-Erweiterung: Verlagerung des BASIC-Anfangs:

POKE 44, 19 : POKE 4608, O

Programmaenderungen (Position im Listing unterstrichen):

110 FORI=4609T04824:... 120 SYS4701:... 470 DATA...11,18... 490 DATA...11,18...

Aufhebung der Verlagerung:

POKE 44, 18 : NEW

Die Aufhebung der Verlagerung ist notwendig, wenn andere Programme geladen werden sollen oder BASIC programmiert ver-

den soll.

Ausserdem muss bei allen VICs vor den Befehl "SPpC(20)" in Zeile 370 der Leerstring ("") gesetzt werden.

35

RSS5EIMBLER FUER COmrMmMODORE &4

198 ı11a 120 13a 140 150 169 ıra 1808 120 zu 21a 220 230 2408 238 260 era 23a 29a 384 3ıa 320 338 340 358 360 ara 3838 330 a0 418 420 438 440 +50 460 470 4230 430 Sag s1a s2a 538 4 ssa Sssa Sva 384 Ss98 sad si 820 830 40 850 sea

AF="":B$="":1=. :J=. ıfl=. ıP=. 10=. :B=. ıh=. :DEFFNDGT5=PEERSITY+2SSHPEEKCI+1> FORI=-S3932T053247 :RERODIA :POKEI .R=NEXT: DIMB$«25S> :FORI=. TO131 :READB$CI> :HEX SYSS3124 1A$=A$+"" :IFA$=""GOTO12A

R=FND« 2537 :P=FNOD<2515 :1I=. :IFLEN{A$IF2ZGOTOSBE

B=RASCER$> : IFB=91 THENPOKER..P :P=A:G0OTO1ra

IFB=33THENPOKER „PEEKK 2515 sPOKER+1 „FPEERN 2525 :P=A:GOTO190

IFB-S8SGOTO1SQ

GOSUBFSTA:RB=1 :Q=PEEK AD :GOSUBFSA SPRINT :ONFGOTO1Y79:GOTO230

IFB-ESGOTOZaa

GOSUBISTA :B=2 :Q=FNDE AD :GOSUBFIR SPRINT :ONFGOTO19G:GOTOZIE

IFB-F&ETHENON- “BIISSPGOTCO1 28 :END :GOTO1206

GOSUB37O : I=SPEEK«KA> SIFI-4#INTX 174 >=. VSTHENI=Z

A$=B$ IK. 75+. 755 :PRINTLEFTSECA$,3)" "r:B=2:1IFLENER$S=ITHENB=1:6G0TO2S0 FORI=4TOLEN“A$> :BS=MIDSEA$.I.19 :IFBS="L" THENO=PEERCR+1> SGOSUB3EA :GOTOZTFA IF IANDS1>=18 THENPOKE 144 .„PEEKÜR+13 :0=ST+R+2 :G0OSUB3EB :GOTOZ7R

IFB$=" 3" THENG=FNOXRA+1D :B=3 :GOSUB3EU :GOTOZTA

FRINTB$;

NET

PRINT :GOSUB4AG :ONFGOTCZ210

GOSUBFSG :PRINT"TV' :sFORI=. TOS:POKES3S1+1.29 :NEKT :POKE19S,5:G0T0120 ON-<B$CT>=AFIGOTO3S1QA: 1[I=1+1 :0ON- 1IL192>GOTO309 :GOTO120

I=INT< 1733+1:B=3 : IFLEN{A$>=3STHENB=1 :GCTCOI48 IFMID$S<A$.4.19="L"ORMIDSCA$,S,.19="C" THENB=2

IFETANDS3S1>=18 THENB=2 :P=P-A-2 sQON- KPÖ - 12SORP>127>GOTO128 :POKE2S1 ,PRND2SS POKER,.I:sIFBP1THENPOKER+1 -FPEEKX 2515 Ss IFB=3THENPOKER+2 „PEEK (2525

P=A:GOTOZ1E

PRINTMID$SCSTE$CO) ,2> : :RETURN

POKEZ11,. sOPEN3,3:PRINT#3,SPCK 205 :CLOSES:POKEZIM..

PRINTRIGHT$«" "+5TR$ER) .2>" "RSRETURN

PRINTMID$ISTRFCO) .25 >

A=R+B :A=A+58II35 HC AFEIIFT) SF=1-ABSESGNLPEEKCSSTSIORASF) 5 SRETURN DATA24,165.7,53,252,.133,.7, 25.6 a 169,,133,251.133,232,.133.7,202.232,183. DATRZ.201,.32,240,.248.232.201. 24a,.240,202 ‚2a. 48.144.227 ,201.5%8.175.,.224 DATA1S9. ‚2 .,265.233,48, 144.208 .2 GG 1a,176,. 203,72,.165,252, 133,5, 165,251, 10.2 DATAS,10,38,8,101.251,.133,251.165,8.101.252. 1#3.292.6.251.38, 2S52,.104,.101 DATA251,133.2531.- 144 ,2,230, 252.,232,263.205,169,.133,211.133,208,.32.207.255 DATRZa1,32,244. 249.162, 201.13,24Q,13,157,.2,134,7.3 32,207 .255.166,7.222 DATRA293.233,138.244,221. 169, .157,.2.168,17@, 32.50,207.169.251.133,.253,169 DATR2S2,133,254.176,201 ,.202,232,189,,2,240,46,201 .32,290,245,201 .689.1r6.4 DATAZa1.43,176,6,.153,,1,200,.208,232,32,579,207.1765,23,3.169,91,.4a.244,2 DATA169.93.153,,1.200,199, .2.244,6.153,.1,.232.288, 244, 152,160.2,195,.45,18 DATA,208,145,45,169,1,.2008.145.45.96

DATABRK , "ORRLL 43" „ORAL, ARSLE.,FHP.ORASE ‚AS, .ORRI,.RS nd: BPII."ORREL> „'r DATA, "ORAL .#" „"ASLE.8",CLC, "ORAI.Y"., ."ORAI, K"U,"'ASLI,.R",„T5SRT."RANDET.%> DATA,BITE,ANDE ROLL .PLP,RAND#E,ROL.BITI.ANDI.RCGLI,BMII."ANDELD.Y".-„."ANDE. DATA"ROLL,X" „SEC, "ANDI .Y",. . „"RANDI.=" ."ROLI,82" .RTI,"EOR£EL,AD",.. „EORL.LSRI DRATAPHA ,EOR#TL ,LSR, IMPJI.EORI,LSRI,.BYCI."EORLCD,V".,„ „"EORL,@","LSRC.®" .CLI DATR"EOR],Y",,„"EORI.%" ,"LSRI,.#" .RTS."ADCCEL,#>",, „ADCLE,RÜÖRL,PLR,.ROCHE „ROP DATATMPX > ,.RDCI,.RORI.BYSI. "ROCK .Y".. „"ROCL,#" ."RORL.%",SEI."RDCI.YT"., DATA"ADCI,#" ,"RORI,8",,"STRCL,MD3" „„‚STYL,STAL.STKL,DEY, „TKA,STYI.STAI.STK] DATRBCCI,"STACCD,Y",,"STYL,#" "STALL. #"."STAL.Y".TYA,."STRI,Y".TAS,."STAI.E DATA,LOW#L,"LOR<C,SD" „LOX#C,LDY[.LDA[L ,LOs[,TAY,LOR#EC,TRAS,LDYJI.LDARI,LD0%8] DATRBCSI,"LORCEI,Y" "LOVE." ."LOAL.=&","LDSC,Y" ,CLY,"LORI,Y",T2S."LDYI,& DATA"LDAI,%","LDXJ.Y",CPY#L,"CMPSL.X5", „CPYC,CHPE,DEC[E.INY.CHPAC,DES,CPY) DATACHPI,DECI..BNEI,"CMPCCH,Y" ,„„"CMPL.X","DEC[.R2" ,CLO,"CMPJI.Y".-„"CMPI.® DATA"DECI.X" CPX#L."SBCEL,X>", ,CPXL,SBCLE, INCL, IN% .SBCHL,HOP.CP=3I,5BCJ. INC DATABEQI,"SBC<CI.,.Y",.,„"SBCE.@" ,"INCC.#",SED,."SBC1.Y".,,"SBCJI.#"."INCI.®

36

ADC: AND: ASL: BCC: BCS: BEQ: BIT: BMI: BNE: BPL: BRK: BVC: BVS: CLC: CLD: CLI: CLV: CMP: CPX: CPY: DEC: DEX: DEY: EOR: INC: INX: INY: JMP: JSR: LDA: LDX: LDY: LSR: NOP: ORA: PHA: PHP: PLA: PLP: ROL: ROR: RTI: RTS: SBC: SEC: SED: SEI: STA: STX: STY: TAX: TAY: TSX: TXA: TXS: TYA:

BEFEHLSLISTE

Speicher mit Carry zu Accumulator addieren Speicher durch "AND" mit Accumulator verknuepfen Speicher/Accumulator um ein Bit linksverschieben Verzweigung bei geloeschtem Carry

Verzweigung bei gesetztem Carry

Verzweigung bei gesetzter Zero-Flag

Bit-Test zwischen Speicher und Accumulator Verzweigung bei gesetzter Negative-Flag Verzweigung bei geloeschter Zero-fFlag Verzweigung bei geloeschter Negative-fFlag Ausloesung eines Software-Interrupts

Verzweigung bei geloeschter Overflovw-fFlag Verzweigung bei gesetzter Overflow-Flag

Carry loeschen

Dezimalmodus ausschalten

Interrupt freigeben

Overflow-Flag loeschen

Speicher mit Accumulator vergleichen

Speicher mit X-Register vergleichen

Speicher mit Y-Register vergleichen

Verminderung des Speicherinhalts um eins Verminderung des X-Registers um eins Verminderung des Y-Registers um eins

Speicher durch "EXOR" mit Accumulator verknuepfen Erhoehung des Speicherinhalts um eins

Erhoehung des X-Registers um eins

Erhoehung des Y-Registers um eins

Sprung zu Adresse

Unterprogrammsprung zu Adresse

Accumulator mit Wert laden

X-Register mit Wert laden

Y-Register mit Wert laden

Speicher/Accumulator um ein Bit rechtsverschieben keine Operation

Speicher durch "OR" mit Accumulator verknuepfen Accumulator auf Stack legen

Prozessorstatus auf Stack legen

Accumulator vom Stack holen

Prozessorstatus vom Stack holen

Linksrotation um ein Bit (Speicher, Accumulator) Rechtsrotation um ein Bit (Speicher, Accumulator) Ruecksprung aus Interruptsequenz

Ruecksprung aus Unterprogramm

Speicher mit Carry von Accumulator subtrahieren Carry setzen

Dezimalmodus einschalten

Interrupt sperren

Accumulator in Speicher ablegen

X-Register in Speicher ablegen

Y-Register in Speicher ablegen

Accumulator in X-Register uebertragen Accumulator in Y-Register uebertragen Stackpointer in X-Register uebertragen X-Register in Accumulator uebertragen

X-Register in Stackpointer uebertragen Y-Register in Accumulator uebertragen

ausgefuehrte Operation, symbolische Darstellung

A+M+C>A,Cc AAM-NA C=- 76543210 -—0D branch on C branch branch AAM, branch on N branch on Z branch on N P V V

= SQ nonzuann

oo»

PC + 2), branch on branch on

ı u

<< x ZI. < x Zz<x >o0o000 =

ey 1) > PCL (PC 2) > PCH PC +2),

an in ©) ig)

eration

A X Y 76543210 —C p MA

76543210 C 76543210 —C

[ep] =. { 7 —>

P>yWı>Px<x< 52 2Z2-,D0N

a Ze re

<xxwW>,><<DJ-br-r.F-r->UO DNNINTTIPI D> > I OO > =Z= 2

(PC + 1) PCL (PC + 2) _. PCH

38

BEFEHLSLISTE

Statusregister NVBDIZC

* * 2 A . * %* * 3 oe ®e U} * ®. * ®. ® ®. ® * * M7M6. U} ® } ® ® 1 ® 1 ® ®. [ _} ®. . . ® 0 ® ® ® 0 U} U} 0} } [7 ® 0} 0 oe _} } 0 ®. ®. ® ® 3 * [} ®. U} ® * * %* ® ® “. U} * * %* y 5 . * %* * ®. ®. } * 3} * e } . ® * 0} * ®. ®. ® * . * ®. ® } * 0} * ® ®. . * * L} . 0} 7 * _} * ® ® ® * * ® EZ 2 * U} * . “. . * * ®. ® } * ® 0 ® 1 o 0} * * * ®. ®. [7 . * ® * ®. . ® } * vom Stack * ® . . . * * * ® ® ® * * vom Stack * %* Pr * %* ®. ®. . ®. } l ®. . 1 . ®. ® . ® ®. 1 * = . * * ®. ® ®e * * 2 n %+ * ® * ®. %* A *

Zeichen- erklaerungen

Accumulator X-Register Y-Register Memory, Argument P Prozessor- status- register 5S Stack- pointer

PC Program-

counter,

Programnm-

zaehler

PC low

PC high

0O Bitwert DO

l Bitvert 1

Transfer nach

= Transfer nach

} Ablegen auf Stack

f Holen vom

Stack

Addition

Subtraktion

logisches

UND

logisches

ODER

logisches

EXKLUSIV-

ODER,

Antivalenz

* beeinflusst

keine

Aenderung

gleich

Negativflag

Overflov,

Vorzeichen-

ueberlauf

B Flag fuer Software- IRQ (BRK)

D Flag fuer Dezimal- modus

I Interrupt- disablebit

Z Zeroflag, Nullflag

C Carry, Uebertrag

B Borrow,_

l-c,c€

2<x<>

4 < >ı+

<< zZ ı

acc umu lat or

10

74

106

imm edi ate

105 4l

201 224 192

73

233

36

102

229

133 134 132

ADRESSIERUNGSARTEN

zer zer abs abs opa opa olu

ge, x

117

53 22

213

‚214

85 246

181

180 86

21

>4

118

245

149

148

ge, y

182

150

te

109 45 14

44

205 236 204 206

77 238

76 32 173 174 172 78

13

46

110

237

141 142 140

olu te,

221 222 93

254

189

188 94

29

62 126

253

157

39

abs imp rel olu lie ati

te, y

121 57

217

89

185 190

25

249

153

d

232 200

248 120

170 168 186 138 154 152

ve

144

176 240

48 208 16

80 112

(in dir ect „x)

97 33

65

161

225

129

(in

(in

dir dir ect ect

),y

113 49

209

81

177

17

241

145

)

108

DER VIDEO INTERFACE CHIP

Saemtliche Graphikmoeglichkeiten des Commodore 64, sei es nun die hochaufloesende Graphik, seien es die Sprites oder die "gewoehnliche" Darstellung von 40 Spalten mal 25 Zeilen, lassen sich auf den 6567 Video Interface Chip (auch VIC-II- Chip genannt) zurueckfuehren. Dieser sehr intelligente Bau- stein ermoeglicht, es beim Commodore 64 graphische Effekte in Programme einzubauen, die auf anderen Computern eines sehr grossen Programmieraufwandes beduerfen oder schlichtweg unmoeglich sind. Im folgenden soll nun auf die einzelnen Ei- genschaften des VIC-II-Chips eingegangen werden, so dass es Ihnen moeglich sein wird, seine Moeglichkeiten vollstaendig auszuschoepfen, was jedoch gar nicht so einfach ist.

Zunaechst einen allgemeinen Hinveis auf die Struktur des VIC-II-Chips, die bei saemtlichen Anwendungen beruecksich- tigt werden muss. Die 6567 kann, von dem vom Computer adres- sierbaren Bereich von 64 KB, jeweils nur 16 KB nutzen. Im Normalfall ist dies der Bereich von Adresse O bis 16383, der beim Einschalten des Computers als fuer den VIC-II-Chips sichtbar deklariert wird. Dieser Bereich von "nur" 16 KB re- sultiert aus der Anzahl an Adressleitungen, von denen der VIC-II-Chip nur 14 (anstelle der 16 Adressleitungen des Pro- zessors) hat. Soll nun ein anderer Bereich spezifiziert ver- den (dies kann immer nur in L16-KB-Bloecken geschehen), so muss dies in den Bits O und 1 des Ports A (Adresse 56576) der NMI-CIA (CIA #2) festgelegt werden.

Es stehen folgende Moeglichkeiten fuer den Adressbereich des VIC-II-Chips zur Verfuegung (das Datenrichtungsregister muss natuerlich auf Ausgang geschaltet sein):

Adressbereich Bitmuster dezimal 0 - 16383 11 3 Normalvwert 16384 - 32767 10 2 32768 - 49151 01 1 49152 - 65535 00 0

Um nun auf einen anderen Bereich umzuschalten, muessen Bit 0 und Bit 1 des Port A auf den unter "dezimal" stehenden Wert gesetzt werden. Dies koennte folgendermassen vor sich gehen:

POKE 56576, PEEK (56576) AND 252 OR dezimal

Dieses 16-KB-Konzept ist Teil aller Speicherzugriffe des VIC-II-Chips und sollte daher unbedingt beachtet werden. Ist zum Beispiel der Bereich von 32768 bis 49151 gewaehlt, so liegt der Bildschirmspeicher (sofern nicht geaendert) ab der Adresse 32768 (Video-Bank-Startadresse) plus 1024 (normale Startadresse des Bildschirmspeichers) = 33792. Aber auch die Daten der Sprites und der hochaufloesenden Graphik unterlie- gen diesem Konzept.

Ein weiterer Hinweis bezueglich des Video-Chips: Er umfasst 47 Register, durch die dessen Funktionen gesteuert werden. Diese Register liegen im Bereich von 53248 bis 53294 und koennen mittels POKE und PEEK bearbeitet werden. Eine Ueber- sicht bezueglich des Video-Chips ist dem Anhang zu entneh- men.

Der Bildschirmspeicher

Der Bereich, in dem die Daten fuer die normale Darstellung von 40 mal 25 Zeichen liegen, wird Bildschirmspeicher ge-

41

nannt. Dies ist ein Bereich von 10008 Bytes mit einer Breite von 8 Bits. Jede Speicherzelle kann daher Werte aus dem Be- reich von O bis 255 annehmen. Diese Werte geben im "Standard Character Mode" das Zeichen an, das an der entsprechenden Stelle des Bildschirms erscheinen soll. In anderen Darstel- lungsmodi kann dieser Bereich auch die Farbcodes fuer ein Feld von 8 mal 8 Dots enthalten. Darauf wird dann aber ge- sondert eingegangen. Der Bildschirmspeicher kann in |]-KB- Bloecken verschoben werden. Bei einem fuer den VIC-II-Chip adressierbaren Bereich von 16 KB ergeben sich daher 16 Moeg- lichkeiten fuer die Lage des Bildschirmspeichers. Bits 4 bis 7 von Register 24 (Adresse 53272) geben diese- Startadresse an. Folgende Tabelle zeigt die moeglichen Bereiche fuer den Bildschirmspeicher:

Adressbereich Bitmuster dezimal D - 999 0000 0 1024 - 2023 0001 l Normalvwert 2048 - 3047 0010 2 3072 - 4071 0011 3 4096 - 5095 0100 4 5120 - 6119 0101 5 6144 - 7143 0110 6 7168 - 8167 OH1 7 8192 - 9191 1000 B 9216 - 10215 1001 9 10240 - 11239 1010 10 11264 - 12263 1011 11 12288 - 13287 1100 12 13312 - 14311 1101 13 14336 - 15335 1110 14 15360 - 16359 1111 15

Auch hier duerfen nur die entsprechenden Bits geaendert ver- den, da ein Register oft mehrere Bedeutungen hat. Der Befehl zum Aendern des Adressbereichs des Bildschirms lautet ...

POKE 53272, PEEK (53272) AND 15 OR 16 * dezimal

Bei der Festlegung der Startadresse fuer die Videomatrix ist zu beachten, dass hierzu, vie bei allen Adressfestlegungen fuer den VIC-II-Chip, die Startadresse der momentanen Video- Bank zu addieren ist, um die wirkliche Startadresse des Bildschirmbereichs zu erhalten, ab der dann die Daten abge- legt werden koennen.

Dieser Bereich des Bildschirmspeichers wird nun aber noch nicht durch die Zeichenausgaberoutine des Betriebssystems unterstuetzt, da das 05 (Operating System) nicht ueber- prueft, ob die Startadresse des Bildschirms vom Wert 1024 abweicht. Hierzu ist es noetig, die Speicherstelle 648 zu aendern. Diese gibt die Startpage des Bildschirmspeichers an.

Dazu ein Beispiel: Wurde als Video-Bank der Bereich von 32768 bis 49151 spezifiziert und soll die Videomatrix ab Adresse 35840 liegen (dies entspricht der Adresse 3072 in- nerhalb des 16-KB-Bereichs), so muessen folgende Befehle eingegeben werden, damit ausserdem die Zeichenausgaberoutine des Betriebssystems die Zeichen in diesem Bereich ausgibt:

POKE 56576, PEEK (56576) AND 252 OR ]

POKE 53272, PEEK (53272) AND 15 OR 16 * 3 POKE 648, 35840 / 256

42

Hierdurch ist es zum Beispiel auch moeglich, den Bildschirm- anfang auf die Adresse 32768 zu legen, da sich auf diese Weise das Umschreiben von Programmen fuer die CBMs mit 40 Zeichen je Zeile wesentlich vereinfacht. Lediglich der Be- reich fuer die Farben der einzelnen Zeichen muss hierbei noch miteinbezogen werden.

Da der Bildschirmbereich nur 1000 Bytes umfasst, bleiben am Ende noch 24 Bytes des 1-KB-Blocks fuer die Videomatrix ueb- rig. Hiervon sind die ersten 16 Bytes unbenutzt, die letzten acht Bytes stehen im Zusammenhang mit den Sprites und werden bei der Erklaerung der Sprites ausfuehrlich erlaeutert.

Der Farbspeicher

Um jedes einzelne Zeichen des Bildschirmspeichers in einer der 16 verschiedenen farben darzustellen, wird der Farbspei- cher benoetigt. Dieser RAM-Bereich umfasst 1024 Adressen zu je 4 Bits (Bit O0 bis Bit 3), wobei jede Zelle einen Wert von 0 bis 15 enthaelt, der fuer die jeweilige Farbe steht. Der Farbspeicher hat jedoch auch noch andere Aufgaben, auf die dann aber im entsprechenden Zusammenhang naeher eingegangen werden wird.

Der Farbspeicher kann nicht in einen anderen Bereich verlegt verden und liegt daher konstant an den Adressen 55296 bis 56319, wobei jedoch auch hier, wie bei der Videomatrix, nur die ersten 1000 Nybbles (damit ist ein Block von vier Bits gemeint) benutzt sind. Die restlichen 24 Nybbles sind unbe- nutzt.

Der Zeichengenerator (Definition eigener Zeichen)

Im Zeichengenerator sind die Informationen gespeichert, wie die Zeichen, die im normalen Darstellungsmodus auf dem Bild- schirm erscheinen, aussehen. Da ein Zeichen eine Gebiet von 8 mal 8 Punkten umfasst, werden zur Definition eines Zei- chens 64 Bits (entsprechend 8 Bytes) benoetigt. Bei einem Zeichenvorrat von 256 Zeichen ergibt dies 256 * 8 Bytes gleich 2 KB, die ein kompletter Zeichensatz einnimmt.

Die Lage des Zeichensatzes ist in 2-KB-Bloecken frei waehl- bar, daraus resultieren 8 Moeglichkeiten fuer den Bereich des Zeichengenerators. Die Bits 1] bis 3 des Registers 24 (Adresse 53272) muessen zur Festsetzung der Startadresse ge- aendert werden. Der Zeichengenerator-ROM des Betriebssystems liegt in den Adressen von 53248 bis 57343. Es werden 4 KB benoetigt, da der Commodore 64 schliesslich zwei vollstaen- dige Zeichensaetze vorsieht und bei Umschaltung von einem zum anderen Zeichensatz nur die Startadresse geaendert wird. Dieser 4-KB-Bereich ist im Normalfall jedoch fuer 1/O und das Farb-RAM vorgesehen, und der Benutzer kann nicht direkt auf die Daten des Zeichengenerators zugreifen.

Das Einblenden des Zeichengenerators und das Ausblenden der 1/0-Bausteine kann durch Loeschen von Bit 2 im Prozessorport der CPU 6510 erfolgen. Allerdings muss zuvor der Interrupt abgeschaltet werden (Bit 0 des Adresseninhalts von 56334 loeschen), da das Betriebssystem auf diesen Bereich zugreift und, sofern die I/O-Register nicht erreichbar sind, den Conm- puter abstuerzen laesst. Nach Zugriff auf den Zeichengenera- tor sollte dieser durch Setzen von Bit 2 des Prozessorports wieder ausgeblendet werden und das Interrupthandling durch Setzen von Bit O des Kontrollregisters A wieder aufgenommen werden. Um zum Beispiel den Zeichengenerator aus dem Bereich von 53248 bis 55295 in den Bereich von 14336 bis 16383 zu

43

uebertragen kann folgendermassen vorgegangen werden:

POKE 56334, PEEK(56334) AND 254

POKE 1, PEEK(1) AND 251

FOR 1=53248 TO 55295 : POKE 1-38912, PEEK(I) : NEXT POKE 1, PEEK(1) OR 4

POKE 56334, PEEK(56334) OR 1

Da der VIC-II-Chip jedoch immer nur auf einen 16-KB-Bereich zugreifen kann, muss das Zeichengenerator-ROM fuer den Video-Chip auf eine weitere Weise verfuegbar sein. Schliess- lich liegen die Adressen von 53248 bis 57343 nicht im Be- reich der Standard Video-Bank von O bis 16383. Daher ist der Zeichengenerator zusaetzlich in den Bereichen von 4096 bis 8191 sowie 36864 bis 40959 sichtbar, dies jedoch nur (!) fuer den VIC-II-Chip. RAM, das in diesem Bereich liegt, ist daher ohne jegliche Einschraenkungen benutzbar. Auch wenn der Zeichengenerator in den vom Prozessor lesbaren Bereich eingeblendet wird, so bleiben die obengenannten Bereiche da- von unberuehrt. Soll jedoch der VIC-II-Chip auf einen RAM- Bereich zugreifen, der auch von Character-ROM "unterlegt" ist, so wird dieser sich fuer den RODM-Bereich entscheiden. Eigene Zeichensaetze, Bildschirmdaten, HIRES-Graphiken etc. sollten daher in anderen Bereichen abgelegt werden.

Hier eine Uebersicht ueber die moeglichen Bereiche des Zei- chengenerators. Zu den Bereichsadressen ist auch hier die Bankstartadresse zu addieren:

Adressbereich Bitmuster dezimal 0 - 2047 000 0 2048 - 4095 001 l

4096 - 6143 010 2 Normalvwert

6144 - 8191 011 3 8192 - 10239 100 4 10240 - 12287 101 5 12288 - 14335 110 6 14336 - 16383 ıll 7

In Video-Bank DO und 2 sind die Bereiche 4096 bis 8191 von der Kopie des Zeichengenerators belegt. Zum Aendern der Startadresse des Zeichengenerators dient der folgende Be- fehl:

POKE 53272, PEEK (53272) AND 241 OR 2 * dezimal

Um nun ein eigenes Zeichen zu definieren muss folgenderma- ssen vorgegangen werden: Der Bildschirmcode des zu definie- renden Zeichens wird mit 8 multipliziert (jedes Zeichen be- noetigt zur Darstellung 8 Bytes) und zur Startadresse des Zeichengenerators addiert. Diese Adresse gibt nun die Start- adresse fuer die Daten dieses speziellen Zeichens an.

Angenommen, folgendes Summenzeichen solle definiert werden:

Zeichen Binaer Dezimal u oIIIIIlo 126 “a. ** olloollo 102

er oolloooo 48 *%* ooollooo 24 *%* oolloooo 48 “ar *%* olloolIo 102 KraRRH olIIIIIo 126 00000000 0

Hierzu gleich ein Hinweis: Es sollten immer mindestens zwei gesetzte Punkte nebeneinander liegen, da es ansonsten zu farblichen Veraenderungen in der Darstellung kommen kann.

Ein gesetztes Bit entspricht nun einem Punkt in der Farbe, die im zugehoerigen Nybble des Farb-RAMs spezifiziert wurde. Geloeschte Bits werden als Dots in der momentanen Hinter- grundfarbe dargestellt.

Um nun dieses Zeichen in den Zeichensatz, den wir zuvor in den Bereich von 14336 bis 16383 uebertragen haben, einzubin- den, muessen die unter der Spalte 'Dezimal' stehenden Zahlen in die Zeichengeneratortabelle uebertragen werden. Vergessen Sie nicht, den Bereich ab 14336 vor Zugriff durch BASIC mit- tels den Befehlen

POKE 55, O0 : POKE 56, 56 : CLR

... zu schuetzen, da sonst der Zeichengenerator ueberschrie- ben werden kann (die Befehlsfolge sollte in der ersten Zeile des Programms stehen). Soll das Sigma-Zeichen nun dem Bild- schirmcode 28 (im Normalfall das Pfund-Zeichen) zugeordnet werden, so muessen die Daten fuer das neue Zeichen ab der Position 14336 (Startadresse des Zeichengenerators) plus 8 * 28 (Zeichencode) abgelegt werden. Dies kann zum Beispiel er- folgen durch ...

FOR 1=14560 TO 14567 : READ A : POKE I, A : NEXT DATA 126, 102, 48, 24, 48, 102, 126, O

Auch der Code Null ist in diesem Fall wichtig, da schliess- lich alle 8 Zeilen des Zeichens neu belegt werden muessen. Nun muss der Zeichensatz mit dem neuen Zeichen noch akti- viert werden. Dies erfolgt durch den Befehl zur Festsetzung der Startadresse eines Zeichengenerators, in diesem Spezial- fall fuer die Startadresse 14336 durch

POKE 53272, PEEK (53272) AND 241 OR 2 * 7

Sollten Sie die auf dieser und der vorherigen Seite aufge- fuehrten Befehlskombinationen in der korrekten Reihenfolge (oberen Bereich vor BASIC schuetzen, Zeichensatz kopieren, neues Zeichen in Zeichensatz uebertragen, neuen Zeichengene- rator aktivieren) eingegeben haben, so sollte jetzt jedes- mal, wenn Sie die Pfund-Taste druecken, das Summenzeichen erscheinen.

Hierzu noch Anmerkungen: Wird nun mittels der Commodore-Ta- ste oder ueber CHR$ in einen anderen Zeichensatz umgeschal- tet, so wird der Bildschirm keinerlei Zeichen mehr enthalten (meist wohl irgendwelche Punkte und Linien), da durch obige Befehlsfolgen nur ein Zeichensatz definiert wurde. Es ist jedoch moeglich, einen zweiten Zeichensatz zu definieren, der dann auch (wie der zweite interne Zeichensatz) direkt angesprochen werden kann. Hierbei muessen jedoch beide Zei- chensaetze innerhalb eines 4-KB-Blocks liegen.

Ein weiterer Punkt: Auch wenn nun das Zeichen definiert wur- de, so ist das Pfund-Zeichen noch immer als negatives Zei- chen vorhanden. Dies ist erkennbar, wenn man zum Beispiel den Cursor auf ein Sigma-Zeichen bewegt. Negative Zeichen muessen daher, sofern erwuenscht, getrennt definiert werden. Soll das bereits als positives Zeichen vorhandene Sigma auch als negatives Zeichen mit dem Code 156 (128 plus 28) erreichbar sein, so kann die Definition durch

45

FOR I = 14336 + 156 * 8 TO 14336 + 156 * 8 + 7 READ A : POKE I, 255 - A : NEXT

... erfolgen (vergessen Sie den RESTORE-Befehl nicht, falls Sie die gleichen Daten ein weiteres Mal verwenden). Bei ne- gativen Zeichen werden gesetzte Bits durch geloeschte Bits ersetzt und umgekehrt.

Durch die Zeichendefinition ist es moeglich, den gesamten Zeichensatz umzudefinieren. Allerdings bevirkt ein veraen- dertes Aussehen an den Zeichen nichts. Sie haben noch immer die gleichen Funktionen, die sie auch vorher hatten, auch venn sie in BASIC-Listings vielleicht ein wenig seltsam aus- sehen moegen.

Hier noch einmal kurz die Vorgehensweise, die 8 Bytes an Da- ten fuer den Zeichensatz aus einem fertigen 8 mal B Punkte- muster zu erzeugen: Jede der acht Zeilen wird getrennt bear- beitet und in der Reihenfolge von oben nach unten in der DATA-Zeile abgelegt. Die acht Punkte innerhalb einer Zeile verden als Binaerzahl aufgefasst. Ein gesetzter Punkt ent- spricht daher der Ziffer 1, ein geloeschter Punkt dem Zif- fernvert O0. Jede Stelle innerhalb des Bytes (8 Bits) hat nun einen bestimmten Wert. Dies sind die Potenzen von 2. Das linke Bit hat den Wert 128 (entsprechend 2 hoch 7), das rechte Bit den Wert 1 (entsprechend 2 hoch 0). Jeder Wert einer Bitposition wird nun mit dem Zifferwert dieses Bits multipliziert (das Ergebnis ist also entweder gleich null oder gleich dem Bitwert) und alle Ergebnisse addiert. Dies ist dann einer der acht Werte.

Modus fuer erweiterte Hintergrundfarben

Oft ist es wuenschenswert, mehr als nur eine Hintergrundfar- be fuer ein Zeichen zür Verfuegung zu haben. Fuer solche An- wendungen ist der Modus fuer erweiterte Hintergrundfarben (Extended Background Color Mode) gedacht, der es ermoeg- licht, jedem Zeichen eine der vier globalen Hintergrundfar- ben zuzuordnen. Ausserdem ist es weiterhin moeglich, eine der sechzehn Vordergrundfarben fuer das Zeichen auszuwaeh- len. Das Aktivieren dieses Moedus' erfolgt durch Setzen von Bit 6 in Register 17 (Adresse 53265) des VIC-II-Chips, wo- durch Bit 6 und Bit 7 des in der Videomatrix stehenden Zei- chencodes nun als Information ueber die Hintergrundfarbe des Zeichens verarbeitet werden. Aus der Kombination von zwei Bits ergeben sich nun folgende vier Moeglichkeiten:

Bit 7 Bit 6 Dezimalbereich Hintergrundfarbregister 0 0 0 - 63 Background Color #0 (53281) 0 1 64 - 127 Background Color #1 (53282) l 0 128 - 191 Background Color #2 (53283) 1 l 192 - 255 Background Color #3 (53284)

Aus der Verwendung der Bits 6 und 7 als Hintergrundfarb- pointer (schliesslich geben die beiden Bits nicht die Farbe selbst, sondern das Background Color Register, aus dem die Farbe stammt, an) resultiert, dass nur noch die Zeichencodes von O0 bis 63 verwendet werden koennen. Alle Zeichen mit ei- nem Bildschirmcode ab 64 werden wieder in den Bereich von DO bis 63 umgewandelt und mit der zugehoerigen Hintergrundfarbe dargestellt.

In BASIC-Programmen lassen sich die Bildschirmcodes recht

gut erreichen. Die Zeichen von 0 bis 63 (entsprechend den CHR$-Codes von 32 bis 95) werden wie gewohnt, dass heisst in

46

/

der "normalen" Hintergrundfarbe, dargestellt. Die gleichen Zeichen mit den Codes von 64 bis 127 (also mit der Hinter- grundfarbe #1, die in Adresse 53282 festgelegt wird) koennen zum groessten Teil (alle Buchstaben, die restlichen Zeichen muessen leider gesucht werden, da nicht bei jeder Taste die Kombination mit der Shift-Taste eine Erhoehung des Zeichen- codes um 64 bewirkt) durch zusaetzliches Druecken der Shift- Taste erreicht werden. Negative Zeichen wiederum werden in den Hintergrundfarben #2 und #3 dargestellt.

Da die Farben selbst nicht dem Zeichencode direkt mitgegeben werden (sondern nur die Information, wo die Farbe zu finden ist), ist es zum Beispiel moeglich, saemtlichen Zeichen ei- ner Hintergrundfarbe gleichzeitig eine neue Hintergrundfarbe zuzuordnen, ohne dass etwas am Zeichencode geaendert werden muss (es muss einfach nur das Register fuer die entsprechen- de Hintergrundfarbe geaendert werden). Die Vordergrundfarbe, also die Farbe, in der das Zeichen selbst dargestellt wird, kann (vie im normalen Darstellungsmodus auch) ueber die Farbtasten geandert werden und wird weiterhin im Color Memo- ry (Farb-RAM) im Adressbereich von 55296 bis 56295 abgelegt.

Mehrfarbige Zeichen (Multicolor Modus)

Oft ist es erwuenscht, ein Zeichen innerhalb eines B mal B8 Feldes in mehreren Farben darzustellen. Hierzu eignet sich moeglicherweise der 'Modus fuer erweiterte Hintergrundfar- ben', der mit dem hier beschriebenen Modus NICHT kombinier- bar ist. Eine weitere Moeglichkeit fuer eine groessere fFarb- auswahl ist der Multicolor Modus. Dieser wird durch Setzen von Bit 4 im Register 22 (Adresse 53270) eingeschaltet. De- durch werden die Daten aus dem Zeichengenerator ein wenig anders interpretiert, als dies der fall ist, wenn dieses Bit geloescht ist.

Voraussetzung fuer die Darstellung eines Zeichens im Multi- color Modus ist, dass Bit 3 im Color-Nybble-RAM gesetzt ist (also eine Farbe ueber die Commodore Taste ausgewaehlt wur- de). Ist dies nicht der Fall, so wird das Zeichen in der ge- wohnten Weise dargestellt (allerdings stehen fuer diese 'ge- wohnte Darstellungsveise' - durch die Benutzung von Bit 3 als Flag - nur noch die ersten acht Farben zur Verfuegung). Eine Mischung beider Modi ist daher problemlos moeglich. Bei gesetzem Bit 3 im Farb-RAM werden jeweils zwei Bits aus dem Zeichengenerator fuer die Auswahl der Farbe verwendet. Da aber auch jeweils zwei Punkte angesprochen werden, halbiert sich die effektive Aufloesung auf eine Groesse von 4 (hori- zontal) mal 8 (vertikal) doppelten Dots. Die Groesse des Zeichens bleibt daher bei 8 mal 8 Punkten. Die einzelnen Bitpaare koennen folgende Zustaende annehmen und haben daher folgende Bedeutungen:

Bitpaar Farbquelle Funktion 00 Background #0 (5328]) Hintergrund 01 Background #1 (53282) Hintergrund 10 Background #2 (53283) Vordergrund 11 Color RAM, Bits 0-2 Vordergrund

Auch fuer die zum Bitpaar '1l]l' gehoerigen Dots stehen nur noch die ersten acht Farben zur Verfuegung, da nur noch Bit 0 bis Bit 2 des Farb-RAM zur Verwendung freistehen. Die Spalte 'Funktion' haengt mit der Benutzung von Sprites zu- sammen und hat ansonsten keinerlei Bedeutung.

47

Hierzu ein Beispiel: spiel sind identisch mit denen fuer die Definition des

ma-Zeichens, gesetzt und die DATA-Zeile geaendert werden.

Es soll folgendes Zeichen (bestehend aus drei plus der fuer den Hintergrund zustaendigen Farbe)

verden: Zeichen

++ * ++ *%* ++** ++** *Rrr+ u v* ++

++

Die Voraussetzungen

Farbgruppen

allerdings muss zusaetzlich das Multicolor

Binaer

olIIIIIo

oloooolo ooollooo ooollooo oolooloo oolooloo Iooooool IoIIlIllolI

Bei- 5Sig- Bit

fuer dieses

Farben (+*#) definiert

Dezimal

Die Datenzeile muss nun natuerlich lauten

DATA 126, 66, 24, 24, 36, 36, 129, 190

Das Einschalten des Multicolor Modus erfolgt durch ...

POKE 53270, PEEK (53270) OR 16

Bei vorheriger Auswahl einer Farbe durch die Commodore-Taste (!) und Druecken der Pfund-Taste wird nun ein Zeichen ausge- geben, das aus zwei Diagonalen und zwei am oberen und unte- ren Ende des Zeichens befindlichen Balken (in der spezifi- zierten Farbe) besteht. Die Farben der Diagonalen haengen von den Registern 53282 und 53283 ab, von denen das erstere die Farbe der Diagonalen von links oben nach rechts unten angibt und das zweite die der anderen Diagonalen. Aller- dings, und das sollte unbedingt erwaehnt werden, ist die Farbe nicht unbedingt so sauber, wie dies bei grossen Flae- chen (Rahmen oder Hintergrund) der Fall ist. Sie haengt in erster Linie vom verwendeten Fernseher beziehungsveise Moni-

tor ab. Durch POKE-Befehle lassen sich nun die Farben der Diagonalen veraendern. Hier stehen jedoch, im Gegensatz zum Bitpaar '1l1', alle 16 Farben frei zur Verfuegung.

Wird das definierte Zeichen allerdings mit einem Cursorfarb- code von O bis 7 (oder bei geloeschtem Multicolor Bit) aus- gegeben, so wird das Aussehen des Zeichens sich aendern, da hier, wie dies auch beim Sigma der Fall war, dann nur noch nach gesetzten und geloeschten Bits mit einer Aufloesung von

8 mal 8 Punkten unterschieden wird. Andererseits ergeben sich recht interressante Effekte, wenn bei eingeschaltetem Multicolor Modus mit normalen Zeichen gearbeitet wird, die

im Mehrfarbenmodus dargestellt sind.

Auch hier ist es, wie dies in aehnlicher Form im Modus fuer erweiterte Hintergrundfarben moeglich war, durch Aendern ei- nes Registers moeglich, saemtliche zugehoerige Bitpaare (mit Ausnahme des Bitpaars 11) auf einmal zu aendern. Diesem Prinzip entspricht uebrigens auch die Aenderung der Hinter- grundfarbe im normalen Darstellungsmodus. Hier werden saent- liche Bits mit dem Wert O (die man als 'nicht sichtbar' be- zeichnen wuerde, da sie der Hintergrund des Zeichens sind) in einer globalen Farbe dargestellt, im Gegensatz zu den ge- setzten Bits, die die zugehoerigen Dots in der im Color Nybble RAM spezifizierten Farbe erscheinen lassen. So sind im Multicolor Modus drei globale Farben vorhanden.

48

Die bis hier beschriebenen Darstellungsmodi, die sich alle unter dem Begriff "Zeichendarstellung" zusammenfassen las- sen, sind alle Moeglichkeiten der Darstellung bei Zugriff auf den Zeichengenerator.

Die hochaufloesende Graphik (HIRES, High Resolution)

Zusaetzlich zu den vorher beschriebenen Darstellungsmodi, die in irgendeiner form auf einen Zeichengenerator zugrei- fen, existiert ein weiterer Darstellungsmodus, in dem jeder der 64000 Bildpunkte getrennt angesprochen werden kann. Die- ser Modus wird daher 'hochaufloesend' genannt. Er eignet sich speziell fuer die Darstellung von mathematischen Funk- tionen, die mit grosser Genauigkeit aufgeloest werden koen- nen, oder als Hintergrund fuer Spiele, da Sprites auch mit HIRES-Graphiken kombinierbar sind.

Eine Programmierung dieses Bit Map Modus (jedes Bit aus dem fuer die hochaufloesende Graphik spezifizierten Bereich ist fuer einen Bildschirmpunkt zustaendig) ist sehr aufwendig. BASIC ist hierzu speziell aus Geschwindigkeitsgruenden nur sehr bedingt geeignet. Man wird bei groesseren Programmen auf die Verwendung von Maschinenprogrammen zum Setzen und Loeschen von Punkten, Linien und Flaechen wohl nicht ver- zichten koennen, falls nicht gar das gesamte Programm in Ma- schinensprache geschrieben werden muss.

Fuer die hochaufloesende Graphik wird ein Bereich von 8000 Bytes an Speicher benoetigt, der im Normalfall von BASIC- Speicher abgezweigt werden muss. Diese B KB werden direkt auf dem Bildschirm dargestellt. Es ist daher moeglich, den Zustand (genaugenommen die Farbe) eines jeden Punktes direkt zu aendern. Wie auch bei der Darstellung von Zeichen aus dem Zeichengenerator, so existieren auch im Bit Map Modus unter- schiedliche Formen. Dies ist der Standard Bit Map Mode und der Multicolor Bit Map Mode. Die horizontale Aufloesung wird, wie dies bei mehrfarbigen Zeichen auch der Fall war, im Multicolor Bit Map Modus auf die Haelfte (160 doppelte Dots) reduziert, da auch hier immer zwei Dots gleichzeitig angesprochen werden. In beiden Modi bekommt ausserdem die Videomatrix eine neue Bedeutung. Durch sie werden nun zwei der moeglichen Farben innerhalb eines Feldes von 8 mal 8 Dots festgelegt.

Das Einschalten des Bit Map Modus' erfolgt durch Setzen von Bit 5 in Register 17 (Adresse 53265), die Startadresse des 8-KB-Bereichs (wodurch sich durch die 16-KB-Architektur des VIC-II-Chips zwei Moeglichkeiten ergeben) wird durch Bit 3 in Register 24 (Adresse 53272) festgelegt (natuerlich muss auch hier wieder die Startadresse der Video-Bank addiert verden):

Adressbereich Bitwert 0 - 7999 0 8192 - 16191 l

Dieses Bit wird auch zur Festsetzung der Startadresse des Zeichengenerators benutzt, der jedoch im HIRES-Modus nicht verwendbar ist. Die Startadresse des Zeichengenerators muss daher wieder neu gesetzt werden, falls in einen Modus ge- schaltet werden soll, der den Zeichengenerator benoetigt.

Der Bereich von O bis 7999 kann in Video-Bank 0 natuerlich

nicht benutzt werden, da ansonsten wichtige Systemadressen ueberschrieben werden muessten.

49

Standard Bit Map Modus

In diesem Modus bleibt das Color Nybble RAM unbeachtet, nur die Videomatrix und der B-KB-Bereich fuer die 64000 Punkte werden verwendet. Das erste Byte aus dem 8-KB-Bereich ist fuer die ersten acht Punkte zustaendig. Dabei erfolgt die Unterteilung innerhalb des Bytes von Bit 7, erster Dot (oben links) bis Bit O, achter Dot. Das zweite Byte bestimmt die ersten acht Dots innerhalb der zweiten Dotzeile. Dies geht so weiter bis zum achten Byte, das die ersten acht Dots der achten Dotzeile bestimmt. Ab dem neunten Byte wird nun wie- der in die erste Zeile zurueckgegangen. Hier bestimmen die Bitzustaende nun das neunte bis sechzehnte Dot von links. Auch dieses Prinzip wird (wie man sich bei einer horizonta- len Aufloesung von 320 Dots leicht ausrechnen kann) bis zum 320sten Byte fortgesetzt. Die nun folgenden 320 Bytes be- stimmen.die Dotzustaende der Zeilen 9 bis 16. Dieses geht so veiter, bis alle der 320 mal 200 Punkte bearbeitet sind. Al- lein an dieser zwar sehr logischen aber doch fuer BASIC sehr umstaendlich zu handhabenden Aufteilung erkennt man, dass wohl viel Zeit allein fuer die Berechnung der Bitposition benoetigt wird. Hier eine Darstellung fuer den Aufbau des Bildschirms aus den zugehoerigen Bytes:

Spalte 0 - 7 8 - 15 ....304 - 311 312 - 319 Reihe 0: Byte 0, Byte 8, ..., Byte 304, Byte 312 Reihe l: Byte l, Byte 9, ...,;, Byte 305, Byte 313

.oeo.o oe. .v.., .ee0 .o...,. ...;,. .oe oe ...,9 .eoo .oeeo Reihe 6: Byte 6, Byte 14, ..., Byte 310, Byte 318 7: Byte 7, Byte 15, ..., Byte 311, Byte 319

8: Byte 320, Byte 328, ..., Byte 624, Byte 632

Reihe 9: Byte 321, Byte 329, ..., Byte 625, Byte 633 “. ve ...y ...,. oe... ..oyg .oeo oe».

Reihe 14: Byte 326, Byte 334 ..., Byte 630, Byte 638 Reihe 15: Byte 327, Byte 335, ..., Byte 631, Byte 639

Reihe 192: Byte 7680, Byte 7688, ..., Byte 7984, Byte 7992 Reihe 193: Byte 7681, Byte 7689, ..., Byte 7985, Byte 7993

.... .oeo ua ee ZUR } ...;,- .oeoe

ie re We RT eg en Reihe 198: Byte 7686, Byte 7694, ..., Byte 7990, Byte 7998 Reihe 199: Byte 7687, Byte 7695, ..., Byte 7991, Byte 7999 Ist nun ein Bit gesetzt, so wird die Farbe des zugehoerigen Punktes vom hoeherwertigen Nybble (MSN, most significant nybble) innerhalb der Videomatrix bestimmt, bei geloeschten

Bits ist dies das niedervwertige Nybble (LSN, least significant nybble) der Videomatrix:

Bitvert Farbe spezifiziert durch 0 LSN (Bits 0 - 3) des zugehoerigen Videomatrixbytes l MSN (Bits 4 - 7) des zugehoerigen Videomatrixbytes

Es stehen also zwei unterschiedliche Farben, die NICHT aus dem Color-Nybble-RAM stammen, innerhalb eines 8 mal B Feldes zur Verfuegung. Bei der Darstellung von Funktionen werden sich diese beiden Farben wohl ueber den gesamten Bildschirm erstrecken, wobei dann eine Farbe als Hintergrundfarbe ver- wendet werden wird und eine andere Farbe fuer den Funktions-

50

graphen selbst. Bei vier zur Verfuegung stehenden Bits fuer jede Farbe koennen daher alle sechzehn Farben verwendet ver- den.

Hier noch eine. Umrechnungmethode in Form eines BASIC-Unter- programms, das durch GÜSUB aufgerufen werden kann. Die Va- riablen X und Y geben die Koordinate des zu setzenden Punkts an:

B = 8192 + (X AND 504) + 40 * (Y AND 248) + (Y AND 7) POKE B, PEEK (B) OR 2 # (7 - (X AND 7)) = RETURN

Dieses Programm geht von einem Bit Map Bereich von 8192 bis 16191 aus. Wie erkennbar, ist dieses Programm sehr leicht in Maschinensprache zu uebersetzen, da saemtliche Operationen direkt durchfuehrbar sind (teilweise jedoch 16 Bit). Die Multiplikation mit 40 muss in mehreren Schritten durchge- fuehrt werden: Als erstes wird der Operand mit 4 multipli- ziert, dann wird der ÜOperand selbst noch einmal addiert (dies entspricht einer Multiplikation mit 5). Das Ergebnis wird dann noch dreimal linksverschoben. Eine Potenzierung zur Basis zwei kann durch Verschiebung eines gesetzten Bits innerhalb eines Bytes erfolgen.

Zum Loeschen eines Punktes muss in der obigen Routine ledig- lich der POKE-Befehl etwas geaendert werden:

POKE B, PEEK (B) AND 255 - 2 (7 - (X AND 7))

Um nun zum Beispiel eine Sinuskurve auf den Bildschirm zu bringen, kann folgendes Programm verwendet werden:

POKE 53280, 14 : POKE 55, O : POKE 56, 32 : CLR

FOR I = 8192 TO 16191 : POKE I, DO : NEXT

FOR I = 1024 TO 2023 =: POKE I, 1 : NEXT

POKE 53272, PEEK (53272) OR 8

POKE 53265, PEEK (53265) OR 32

FOR X = 0 TO 319 : Y = 100 - 100 * SIN (X * pi / 160) GOSUB punktsetzroutine : NEXT

Dabei ist mit 'pi' natuerlich die Shift-Funktion der Taste zwischen 'RESTORE' und '*' gemeint. Als Punktsetzroutine kann zum Beispiel die obige verwendet werden. Um die durch das Wort 'READY.' erzeugten Farbfelder zu vermeiden, kann man am Ende des Programms eine Endlosschleife anfuegen.

Der Abbruch sollte durch RUNSTOP und RESTORE erfolgen, da dann wieder in den Normalmodus zurueckgekehrt wird. Der Pointer auf das Ende des Arbeitsspeichers kann dann auch wieder rueckgesetzt werden. In diesem speziellen Programm waere es nicht einmal noetig gewesen, den Pointer (55/56) zu aendern, da keinerlei Strings verwendet werden. Die Ablage von Variablen ist jedoch bereits anderweitig erklaert.

Multicolor Bit Map Modus

Waehrend im Standard Bit Map Modus nur zwei verschiedene Farben für jeden Punkt zur Verfuegung stehen, so sind dies im Multicolor Modus vier verschiedene Farben. Mehrere Farben koennen benoetigt werden, wenn zum Beispiel zwei verschie- denfarbige Linien sich kreuzen oder einfach, um bessere Farbgraphiken zu erstellen. Wie dies beim Multicolor Modus fuer Zeichen jedoch auch der Fall war, so muss auch hier die Haelfte der horizontalen Aufloesung geopfert werden. Es ste- hen hier also noch 160 (horizontal) mal 200 (vertikal) dop- pelte Dots zur Verfuegung, da auch hier jeweils zwei Bits an

51

Daten im Bit Map Speicherbereich fuer zwei Dots Gueltigkeit haben.

Initialisiert wird der Multicolor Bit Map Modus durch Setzen des Multicolor Bits (Bit 4) in Register 22 (Adresse 53270) sowie natuerlich durch Setzen des Bits fuer den Bit Map Mo- dus, Bit 5 in Register 17 (Adresse 53265).

Die Anordnung der Bytes auf dem Bildschirm bei eingeschalte- tem Multicolor Modus ist identisch mit der des Standard Bit Map Modus. Lediglich die Bedeutungen der Bits innerhalb ei- nes Bytes sind unterschiedlich. Bei zwei Bits an Daten fuer jeweils zwei Dots stehen folgende vier Moeglichkeiten zur Auswahl:

Bitpaar Farbquelle Funktion 00 Background #0 (53281) Hintergrund 01 MSN (Videomatrix) Hintergrund 10 LSN (Videomatrix) Vordergrund 11 Color Nybble RAM Vordergrund

Die Spalte 'Funktion' steht auch hier im Zusammenhang mit den Sprites.

Wie ersichtlich, existiert eine globale Farbe fuer den ge- samten Bildschirm. Ausserdem stehen innerhalb eines jeden B8 mal 8 Feldes weitere drei Farben zur Verfuegung. Innerhalb eines 8 mal 8 Feldes koennen daher maximal vier Farben Ver- wendung finden. Waehrend das Farb-RAM im Standard Bit Map Mode unbenutzt war, dient es hier als Farbquelle bei der Darstellung des Bitpaars '1l1l'.

Die SPRITES (Movable Object Blocks, MOBs)

Die Sprites sind, um es einmal ganz bescheiden auszudruek- ken, das absolute Nonplusultra des VIC-II-Chips. Durch sie ist es zum Beispiel moeglich, Spielprogramme so zu vereinfa- chen, dass selbst in BASIC noch schnelle Graphikspiele pro- blemlos auch fuer den Einsteiger zu programmieren sind. In Maschinensprache ergibt sich dann sogar die Steigerung die- ses Superlativ, da man viele Moeglichkeiten (gerade im Zu- sammenhang mit der hochaufloesenden Graphik) von- BASIC aus gar nicht voll ausnutzen kann.

Bei den Sprites handelt es sich um eine Art uweberdimensio- niertes Zeichen in einer Groesse von 24 (horizontal) mal 2] (vertikal) Bildschirmpunkten. Diese 504 Punkte eines Sprites koennen beliebig gesetzt und geloescht werden, so wie das bei der hochaufloesenden Graphik auch der Fall war. Sprites koennen ausserdem mit jedem Bildschirmmodus uneingeschraenkt kombiniert werden, ganz gleich, ob es sich dabei um die hochaufloesende Graphik, einen Multicolor Modus oder die Darstellung von einzelnen (durch den Zeichengenerator defi- nierten) Zeichen handelt.

Die Programmierung der Sprites erfolgt unabhaengig von der des restlichen Bildschirms. So muss bei der Erstellung fuer die Graphik eines Spiels in keinster Weise auf die Bewegun- gen der MOBs Ruecksicht genommen werden. Allerdings ist es moeglich, Kollisionen eines Sprites mit dem webrigen Bild- schirm oder mit anderen der wingesamt acht verchiedenen Sprites zu erkennen. Es muessen daher noch nicht einmal Ab- fragen auf die Positionen der Sprites in ein Programm einge- baut werden, da diese Ueberpruefungen bereits durch den MOS 6567 durchgefuehrt werden.

52

Jedes Sprite laesst sich in X- und Y-Richtung bewegen. Man gibt dem VIC-II-Chip dazu nur die gewuenschte Position an, worauf das Sprite an diese Position gesetzt wird. Auch sind Ueberlagerungen von Sprites, Bildschirmvorder- und Hinter- grund moeglich, so dass der Eindruck einer dreidimensionalen Darstellung erreicht werden kann.

Der Aufbau der Sprites

Jedes Sprite besteht aus 504 Punkten, die einzeln beein- flusst werden koennen. Ein Sprite stellt also ein kleines Gebiet hochaufloesender Graphik dar. Um diese 504 Punkte zu definieren, benoetigt man 63 Bytes, da jedes Byte aus 8 Bit (und jedes Bit ist fuer einen Dot zustaendig) besteht. Diese 63 Bytes werden in einem Block im Arbeitsspeicher abgelegt. Die Zuordnung der Bytes innerhalb des Gebiets von 24 mal 21 Punkten ist folgendermassen: Das erste Byte bestimmt die er- sten acht Punkte der ersten Zeile, das zweite Byte die Punk- te 9 bis 16, das dritte die Punkte 17 bis 24 der ersten Zei- le. Die naechsten drei Bytes sind fuer die zweite Zeile zu- staendig. Dies geht so bis zum 21. Block von drei Bytes wvei- ter. Innerhalb eines Bytes ist (wie dies auch bei der Defi- nition von eigenen Zeichen oder bei der hochaufloesenden Graphik der Fall war) Bit 7 dem ersten Bildschirmpunkt in- nerhalb der Reihe von acht Punkten zugeordnet, Bit 0 ent- sprechend dem letzen Dot. Zum Aufbau hier noch eine anschau- liche Darstellung:

Spalte

0- 7 8 - 15 16 - 23

Zeile 0: Byte 0, Byte 1], Byte 2 Zeile 1: Byte 3, Byte 4, Byte 5 Zeile 2: Byte 6, Byte 7, Byte 8 Zeile, 3: Byte 9, Byte 10, Byte 11

Zeile 17: Byte 51, Byte 52, Byte 53 Zeile 18: Byte 54, Byte 55, Byte 56 Zeile 19: Byte 57, Byte 58, Byte 59 Zeile 20: Byte 60, Byte 61, Byte 62

Da jedes Bit. eines Bytes der Sprite-Daten einem Dot des Sprites zugeordnet ist, ergeben sich fuer die Bedeutung der Bits folgende Moeglichkeiten:

Bitvert Bedeutung

0 transparent, keine Aenderung des Bildschirmbildes 1 Darstellung des Punktes in der Farbe des MOBs

Im Gegensatz zu den Bedeutungen der Bits bei den anderen Bildschirmmodi ergibt sich aus dem Bitwert OD hier keine Dar- stellung des Punktes in der Hintergrundfarbe. Vielmehr wird dieser Spritepunkt ueberhaupt nicht beachtet, so dass die Daten, die normalerweise an dieser Stelle auf dem Bildschirm stehen, weiterhin sichtbar bleiben.

Die Farbe des MOBs, also die Farbe der Punkte, deren Daten- bits gesetzt sind, wird in den Registern 39 bis 46 des VIC- II-Chips festgelegt. Diese Register liegen an den Adressen 53287 bis 53294, deren untere vier Bits (LSN) den Farbcode enthalten. In diesen Registern koennen die oberen 4 Bits un- beachtet bleiben (es muss also der fFarbwert nicht mittels 'AND' und 'OR' festgesetzt werden), da diese keinerlei Funk-

53

tion haben. Somit kann ein Sprite in jeder der sechzehn Far- ben dargestellt werden.

Sprites belegen einen "geraden" Block von 64 Bytes, wovon nur die ersten 63 Bytes benutzt sind. Es stehen also winner- halb eines 16-KB-Bereichs insgesamt 256 Moeglichkeiten der Ablage von Sprite-Daten zur Verfuegung. Soll zum Beispiel ein Sprite ab der Adresse 832 abgelegt werden, so ist dies der 64-Byte-Block mit der Nummer 13 (von Nummer 0 ausge- hend). Die Ablage dieser Nummern fuer die acht MOBs erfolgt, wie schon bei der Erklaerung der Videomatrix angedeutet, am Ende der 24 restlichen Bytes des 1024-Byte-Bereichs des Bildschirmspeichers. Dies ist im Normalfall der Bereich von 2040 bis 2047, wobei 2040 die Startadresse von Sprite Nummer 0 angibt. Sollten also die Daten fuer Sprite Nummer 5 ab der Adresse 832 abgelegt werden, so muesste dies dem VIC-II-Chip durch ...

POKE 2045, 13

... mitgeteilt werden. Die Angabe der Position der Sprite- Daten ist allerdings nicht genug. ‚Jedes Sprite verfuegt au- sserdem noch ueber einen Schalter, der angibt, ob: dieses Sprite momentan auch auf dem Bildschirm dargestellt werden soll. Diese acht Schalter befinden sich im Register 2]1 (Adresse 53269) des Video-Chips. Jedes Bit (von Bit 0 bis Bit 7) ist dem entsprechenden Sprite (Spritenummer identisch mit Bitnummer) zugeordnet. Ist ein solches Bit gesetzt, so wird das Sprite entsprechend den Daten dargestellt. Ist es geloescht, so existiert dieses Sprite nicht. Es wird in kei- ner Form auf die Daten zugegriffen oder aehnliches.

Ausserdem laesst sich jedes Sprite sowohl in X-Richtung als auch in Y-Richtung in seiner Ausdehnung verdoppeln. Somit kann ein MOB maximal eine Ausdehnung von 48 mal 42 Punkten haben. Eine Verbesserung der Aufloesung wird damit aber nicht erreicht. Jeder Bildschirmpunkt wird lediglich in zwei Zeilen und/oder Spalten dargestellt, so dass der MOB in dop- pelter/vierfacher Groesse erscheint.

Diese Erweiterung in X- oder Y-Richtung wird durch die Regi- ster 29 (Adresse 53277, X-Erweiterung) und Register 23 (Adresse 53271, Y-Erweiterung) festgelegt. Auch hier sind die Bits von Bit O bis Bit 7 den Sprites von O bis 7 zuge- ordnet. Ist ein Bit in einem dieser Register gesetzt, so wird das entsprechende Sprite in die ausgewaehlte Richtung verbreitert.

Zusaetzlich existiert noch das Prioritaetsregister, auf das aber erst spaeter im Zusammenhang mit Kollisionen eingangen werden soll. Es befindet sich an der Adresse 53275 und wird im folgenden erst einmal unbeachtet belassen.

Nun zur Festlegung der Position des Sprites auf dem Bild- schirm: Jedes Sprite kann an jeder Stelle des Bildschirms stehen. In horizontaler Richtung ergeben sich, resultierend aus der Bildschirmbreite von 320 Punkten und der Sprite- breite von 24 Punkten, insgesamt 297 verschiedene Positio- nen, in denen das Sprite vollstaendig dargestellt ist. Dies sind die X-Werte im Bereich von 24 bis 320. Dabei beziehen sich diese Werte auf die linke obere (eventuell, je nach Sprite-Daten, auch nicht vorhandene) Ecke des Spriteblocks. Ist ein X-Wert von 24 gewaehlt, so befindet sich die linke Kante des Spriteblocks am Rand des linken Bildschirmrahmens. Die 180 vollstaendig sichtbaren Y-Werte liegen von 50 bis 229. Werden Werte ausserhalb dieses Bereiches gewaehlt, so

54

ist das Sprite nur teilweise sichtbar. So ist es zum Bei- spiel moeglich, ein Sprite langsam auf dem Bildschirm er- scheinen zu lassen.

Die Festlegung der Sprite-Koordinaten geht folgendermassen vor sich:.

Register 1 (Adresse 53249) enthaelt die Y-Koordinate des er- sten Sprites (Nummer O0). Wie bereits erwaehnt, bevirken man- che Werte nur eine teilweise (oder gar keine) Darstellung des Sprites au dem Bildschirm.

Register O0 (Adresse 53248) sowie Bit 0 von Register 16 (Adresse 53264) bilden zusammen das Register fuer die X-Ko- ordinate des Sprites Nummer O mit einer Breite von 9 Bits. Dies ist notwendig, da der Bildschirm eine Breite von mehr als 256 Dots hat. Bei X-Werten im Bereich von OD bis 255 ist demnach Bit O0 von Register 16 geloescht. Ist es gesetzt, liegt der X-Wert im Bereich von 256 bis 511. Auch hier fueh- ren manche Werte wieder zu einer unvollstaendigen Darstel- lung des MOBs.

Zum langsamen Erscheinen von Sprites: Hat ein Sprite die normale Groesse von 24 mal 21 Punkten, so ist es moeglich, diesen Sprite von jeder Seite aus in einzelnen Rasterzeilen auf den Bildschirm zu bevegen. Ist der Sprite jedoch in X-Richtung verdoppelt worden, so ist er zu breit, um "unter" dem linken Rand versteckt zu werden. In X-Richtung erveiter- te Sprites sollten daher nicht am linken Rand in Erscheinung gebracht werden, falls auf ein stueckweises Erscheinen Wert gelegt wird. Bei der Verbreiterung in Y-Richtung entstehen keinerlei Probleme. Auch bei verbreiterten MOBs geben die Koordinatenregister die Position der linken oberen Ecke an (eine Verbreiterung erfolgt nach rechts oder unten, nicht um den urspruenglichen Sprite herum), die linke obere Ecke ver- aendert ihre Position nicht.

Die Koordinaten des Sprites Nummer ]l werden in den Registern 2 (Y-Koordinate) sowie Register 3, das zusammen mit Bit ]1 von Register 16 wieder den 9-Bit-breiten Wert fuer die X-Ko- ordinate ergibt, festgelegt. Die Koordinatenregister der veiteren Sprites liegen (auch jeweils paarweise plus einem zusaetzlichen Bit aus Register 16) in den Registern 4 bis 15 (jeweils die acht niedervwertigen Bits fuer die X-Koordinate im ersten Register, dann die Y-Koordinate).

Hierzu jetzt endlich ein Beispiel: Folgender Pac-Man ("Pac- Man" ist ein Warenzeichen der Firma ATARI) soll als ein Sprite definiert werden:

DI ATINLBIEDDOAITNIN LINIEN

Te retten febjab jerb ja jan jan fan jmuh

55

Um aus diesem Muster nun ein Programm zu machen, das diese Figur auf den Bildschirm bringt, muessen zuerst saemtliche 63 Bloecke zu je acht Punkten in Dezimalwerte umgewandelt verden. Dazu muss in der gleichen Weise vorgegangen werden, vie bei der Definition eigener Zeichen auch. Die daraus er- haltenen 63 Zahlen muessen dann in DATA-Zeilen eingebaut werden. Die Anordnung erfolgt wie zuvor angegeben: von Zeile 0 bis Zeile 20 und innerhalb der Zeilen die Bytes von links nach rechts. Man erhaelt fuer den "Pac-Man" folgende Werte fuer die DATAs:

100 DATA 0, 127, 0 210 DATA 255, 254, 0 110 DATA 3, 255, 192 220 DATA 255, 254, 0 120 DATA 15, 255, 240 230 DATA 255, 255, 0 130 DATA 31, 255, 248 240 DATA 127, 255, 128 140 DATA 63, 243, 252 250 DATA 127, 255, 192 150 DATA 127, 243, 254 260 DATA 63, 255, 224 160 DATA 127, 255, 254 270 DATA 31, 255, 240 170 DATA 255, 255, 252 280 DATA 15, 255, 224 180 DATA 255, 255, 240 290 DATA 3, 255, 192 190 DATA 255, 255, 192 300 DATA 0, 127, 0

Die folgende Zeile dient dazu, diese Werte im Bereich von 832 bis 894 abzulegen ...

310 FOR I = 832 TO 894 : READ A : POKE I, A : NEXT

Sollen nun Sprite Nummer DO diese Daten (im Speicherblock 13) zugeordnet werden, so erreicht man dies durch

320 POKE 2040, 13

Ausserdem muss dieser Sprite nun noch eine Farbe (gelb) be- kommen und die Freigabe fuer die Ausgabe auf dem Bildschirm muss erfolgen:

330 POKE 53287, 7 : POKE 53269, 1

Durch diese Zeile wird nun noch die Figur ueber den Bild- schirm bevegt:

340 FOR I = 0 TO 255 : POKE 53248, I : POKE 53249, I : NEXT

Bevor Sie das Programm durch 'RUN' starten, sollten Sie noch einmal "RUNSTOP" und "RESTORE" druecken, damit eventuell noch vorhandene Restparameter aus anderen Programmen aus dem Video-Chip entfernt werden (Initialisierung des VIC-II- Chips). Die Figur wird nun diagonal ueber den Bildschirm be- vegt.

Diese Figur kann nun natuerlich auch noch in X-Richtung und Y-Richtung vergroessert werden. Bauen Sie doch noch einmal zusaetzlich eine der folgenden Zeilen ein:

335 POKE 53271, 1 : POKE 53277, 0 335 POKE 53271, O0 : POKE 53277, 1 335 POKE 53271, 1 : POKE 53277, 1

Soll Ihr "Pac-Man" nun auch noch Fressbewegungen machen, so muessen Sie saemtliche verschiedenen Figuren erst einmal in verschiedenen 64-Byte-Bloecken ablegen. Um nun die verschie- denen Figuren auch erscheinen zu lassen, wird einfach der Zeiger auf den Datenblock (bei diesem Beispiel in Adresse 2040) der naechsten Figur gesetzt. So wird eine bewegte Spielfigur gezeigt, ohne dass die Daten ausgetauscht werden

56

muessen. Ein Datenblock kann jederzeit verschiedenen Sprites gleichzeitig zugeordnet sein. Besteht ein Spiel also aus mehreren gleichen Figuren, so muessen die Daten dazu nur einmal vorhanden sein.

Multicolor Sprites

Auch Sprites lassen sich im Multicolor Modus darstellen. Dies ermoeglicht es dem Programmierer, einem Sprite drei Farben (plus transparent) zuzuordnen. Jedoch werden auch hier jeweils zwei Bits der Daten verwendet, um die Farbe zu spezifizieren, so dass sich die horizontale Aufloesung auf 12 doppelte Punkte halbiert. Da aber (wie in allen Multico- lor Modi) immer zwei Punkte auf einmal angesprochen werden, veraendert sich die Spritegroesse nicht. Sprites lassen sich unabhaengig voneinander in den Multicolor Modus schalten. Die geschieht durch das Setzen des entsprechenden Bits in Register 28 (Adresse 53276). Bit O ist hier Sprite Nummer O0 zugeordnet, Bit 7 ist fuer Sprite Nummer 7 zustaendig. Auch Multicolor Sprites lassen sich vergroessern; dies erfolgt in gleicher Weise, wie bei normalen Sprites auch.

Hier die Bedeutungen der Bitpaare:

Bitpaar Farbquelle

00 transparent

01 MOB Multicolor #0 (Register 37) 10 MOB Farbe (Register 39 bis 46)

11 MOB Multicolor #1 (Register 38)

Wie erkennbar, existiert fuer Multicolor MOBs also eine ei- gene Farbe fuer jeden MOB sowie zwei globale Farben, die fuer alle MOBs verwendet werden. Diese beiden globalen Far- ben befinden sich in den Adressen 53285 und 53286. Auch hier koennen die Farbwerte (von O bis 15 fuer alle sechzehn Far- ben) ohne Beruecksichtigung der hoeherwertigen Bits (wie das bei allen Farbregistern der Fall ist) direkt in das Register eingeschrieben werden, da die hoeherwertigen Bits keinerlei Bedeutung haben.

Prioritaeten

Sprites haben untereinander und zu dem uebrigen Bildschirm bestimmte Prioritaeten. Ueberlappen sich zum Beispiel nicht- transparente Daten zweier Sprites, so werden die Daten des Sprites mit der niedrigeren Nummer dargestellt. So verdeckt bespielsweise Sprite Nummer O immer die Dots der wuebrigen Sprites.

Anders ist dies im Zusammenhang mit dem uebrigen Bildschirm. Hier ist es fuer den Benutzer frei waehlbar, ob die Sprites vor oder hinter den Vordergrunddaten dargestellt werden (Hintergrunddaten rangieren immer an unterster Stelle der Prioritaet und werden daher immer von nichttransparenten Da- ten verdeckt). Register 27 (Adresse 53275) enthaelt nun fuer jeden MOB ein Prioritaetsbit. Ist dieses Bit gesetzt, so werden MOB-Daten durch Vordergrunddaten verdeckt. Bei ge- loeschtem Bit haben die MOB-Daten eine hoehere Prioritaet und werden daher "ueber" den Vordergrunddaten dargestellt.

Im Zusammenhang mit den Prioritaeten erklaert sich nun auch die Spalte 'Funktion' bei den Uebersichten ueber die Bedeu- tungen der Bitpaare in den Multicolor Modi. Waehrend bei den Standard Modi geloeschte Datenbits Hintergrund und gesetzte Datenbits Vordergrund repraesentieren, so kann in den Multi-

57

color Modi mit zwei Hintergrundfarben gearbeitet werden, von denen dann auch keine (weder '00', noch '01') andere Daten verdeckt.

Dieses System hat allerdings einen kleinen Nachteil: Da bei Ueberlagerung zweier MOBs zuerst die Prioritaet der MOBs un- tereinander ausgevertet wird und dann erst die Prioritaet zum Bildschirm, mag es in einigen Faellen zu einer "fal- schen" Darstellung auf dem Bildschirm kommen, indem durch ein MOB verdeckte Vordergrunddaten durch ein zweites Sprite (mit niederer Nummer und daher hoeherer Prioritaet zum ande- ren Sprite, aber niederer Prioritaet zum Bildschirmvorder- grund) wieder "sichtbar" gemacht werden. Dies duerfte aber in den meisten Faellen vernachlaessigt werden.

Kollisionen

In Spielen ist es wichtig festzustellen, ob sich Sprites be- ruehren oder ob ein Sprite soeben Vordergrunddaten ueber- lappt. Alle diese Faelle werden naemlich durch den VIC-II- Chip bereits geprueft. Es muessen die fertigen Daten nur noch ausgevertet werden.

Kollisionen zwischen Sprites

Treffen nichttransparente Daten zweier (oder mehr) Sprites zusammen, so wird in Register 30 (Adresse 53278) das ent- sprechende Bit eines jeden Sprites gesetzt, das in dieses Zusammentreffen verwickelt ist. Gleichzeitig wird Bit 2 des Interrupt Latch Registers gesetzt, so dass (falls der Inter- rupt freigegeben ist) der Prozessor in die Interruptroutine verzweigen kann, wo dann die Kollision behandelt werden kann.

Kollision zwischen Vordergrunddaten und Sprites

Auch hier wird beim Zusammentreffen eines Sprites mit Vor- dergrunddaten (im Multicolor Modus gilt das Bitpaar '01', wie im Zusammenhang mit den Prioritaeten, als Hintergrund) fuer dieses Sprite in Register 31 (Adresse 53279) das zum Sprite gehoerige Bit gesetzt. Hierbei wird dann Bit |] des Interrupt Latch Registers gesetzt. Eine Behandlung von Kol- lisionen zwischen Sprites und Vordergrunddaten kann daher auch hier durch eine Interruptroutine erfolgen.

Kollisionen (allgemein)

Ein Bit in einem der Kollisionsregister bleibt solange ge- setzt, bis das Register ausgelesen wird. Das zugehoerige Bit im Interrupt Latch wird dann gesetzt, wenn mindestens ein Bit in .einem der Kollisionsregister gesetzt wird. Bei fol- genden Kollisionen wird dieses Latchbit NICHT gesetzt, falls nicht vorher das Kollisionsregister gelesen wurde, auch wenn das Latchbit mittlerweile geloescht wurde.

Die Interrupt-Register

Die Interrupt-Register ermoeglichen ausser der Erkennung von Kollisionen noch die Abfrage des Lightpen-Eingangs und des Rasteregisters (siehe jeweils dort).

Die Steuerung der Interrupts wird durch zwei Register des VIC-II-Chips vorgenommen: Das erste ist das Interrupt Enable Register (Register 26, Adresse 53274). In ihm wird festge- legt, ob durch einen der vier faelle, die einen Interrupt ausloesen koennen, auch die Interrupt-Leitung des Prozessors

58

auf Low gezogen werden soll. Die in diesem Register vervwen- deten unteren vier Bits stehen fuer die vier Interruptquel- len. Jede Interruptquelle kann also unabhaengig von anderen Interrupts als Ausloeser eines IRQs freigegeben werden, um so dem Prozessor mitzuteilen, dass ein zu behandelndes ETr- eignis aufgetreten ist.

Freigegeben wird ein Interrupt, indem das zugehoerige Bit des Interrupt Enable Registers auf den Wert 1 gesetzt wird. Das Sperren einer Interruptquelle erreicht man entsprechend durch das Loeschen des zugehoerigen Bits. Beim Auslesen wird der entsprechende Wert zurueckgegeben (die unbenutzten Bits 4 bis 7 haben den Bitvert |)

Hier die Zuordnungen der Bits sowohl des Interrupt Latch Re- gisters als auch des Interrupt Enable Registers:

Bitposition Zustaendig fuer Interruptquelle ...

Rasterregister

Kollision zwischen Sprite und Vordergrunddaten Kollision zwischen Sprites

Negative Flanke auf Lightpen-Input

VUND-t+O

Unabhaengig davon, ob eine Interruptquelle als Ausloeser freigegeben ist, wird im Interrupt Latch Register (Register 25, Adresse 53273) das zur Quelle gehoerige Bit gesetzt, wenn ein entsprechendes Ereignis auftritt (Kollision etc.). Ist ausserdem dieser Interrupt auch durch ein gesetztes Bit im Interrupt Enable Register freigegeben, so wird zusaetz- lich Bit 7 im Interrupt Latch Register gesetzt (ansonsten ist Bit 7 geloescht). Dies signalisiert dem Programm, dass die Interruptleitung zum Prozessor auf Low-Pegel gelegt wur- de.

Dieses Bit 7 von Register 25 laesst sich verwenden, um in- nerhalb der Interruptroutine zu erkennen, ob der VIC-II-Chip Ausloeser fuer den Interrupt war, da schliesslich auch die IRQ-CIA einen IRQ ausloesen kann. So kann gleich zu Beginn der Routine festgestellt werden, ob eine Verzweigung in eine Behandlungsroutine fuer den VIC-II-Chip erfolgen muss.

Ein gesetztes Latchbit im Interrupt Latch Register kann durch Schreiben einer Eins in die gleiche Bitposition wieder geloescht werden.

Das Raster Register

Dieses Register (Register 18, Adresse 53266 sowie Bit 7 von Register 17, Adresse 53265) gibt die Zeile des momentan auf den Bildschirm gebrachten Bildschirminhalts an. Dies kann dazu verwendet werden, um bei Aenderungen des Bildschirm- inhalts ein Flackern zu vermeiden. Man darf in diesem Fall dann nur solche RAM-Bereiche aendern, die waehrend des Aen- derungsvorganges nicht durch den VIC-II-Chip ausgelesen ver- den.

Wird in dieses Register 18 (inklusive Bit 7 von Register 17) schreibend zugegriffen, so wird dieser Wert in ein internes Latch uebertragen. Erreicht das Raster Register diesen zwvi- schengespeicherten Wert, so wird Bit O des Interrupt Latch Registers gesetzt. Ist Bit O0 des Interrupt Enable Registers gesetzt, so wird ausserdem ein IRQ ausgeloest. Das Raster Register wird beim Commodore 64 dazu benutzt, um die Fern- sehnorm/Taktfrequenz des Geraetes festzustellen.

59

Der Lightpen-Input

Bei Auftreten einer negativen Flanke auf dem Lightpen-Input wird die momentane Bildschirmposition in ein Latch uebertra- gen. Das Register 19 (Adresse 53267) enthaelt dann die acht hoechstwertigen der neun fuer die X-Position zustaendigen Bits. Daher betraegt die horizontale Aufloesung nur zwei Dots. Die Y-Position zum Zeitpunkt der negativen Flanke wird in Register 20 (Adresse 53268) wuebertragen (innerhalb des sichtbaren Bereichs des Bildschirms reichen fuer die verti- kale Aufloesung jedoch acht Bits aus). Je Einzelbild kann aber nur einmal eine Uebertragung der Position in das Light- pen Latch erfolgen.

Bei einer negativen Flanke am Lightpen-Input wird ausserdem Bit 3 im Interrupt Flag Register gesetzt, so dass bei ge-. setztem Bit 3 im Interrupt Enable Register ein IRQ ausge- loest wird. Allerdings sollte in Programmen beachtet werden, dass - durch Verwendung der Ports der IRQ-CIA sowohl fuer die Tastatur als auch fuer die Kontrollports - auch durch die Tastatur eine negative Flanke auf den Lightpen-Input ge- geben werden kann.

SCREEN BLANKING

Wird Bit 4 in Register 17 (Adresse 53265) geloescht, so wird der gesamte Bildschirm mit der Rahmenfarbe (Exterior Color, Register 32) gefuellt. Der Prozessor greift nur noch waeh- rend Phase 1 auf den Systembus zu, der Prozessor wird nicht mehr angehalten, ihm steht also der gesamte Bus zur Verfue-

gung.

Allerdings wird bei aktiven Sprites trotzdem auf deren Daten zugegriffen, falls Register 21 (MOB Enable) nicht auf den Wert null gesetzt wurde.

Da waehrend der Recorderoperationen die CPU keinesfalls an- gehalten werden darf (es handelt sich um sehr zeitabhaengige Routinen), wird beim Commodore 64 waehrenddessen der Bild- schirm auf die genannte Weise "abgeschaltet", um ein ein- wandfreies Arbeiten des Computers zu gewaehrleisten. Sollten waehrend dieses Zeitraums jedoch MOBs aktiviert sein, so duerfte es vermutlich zu Lesefehlern kommen (falls ueber- haupt Daten erkannt wurden).

Scrolling in einzelnen Punktzeilen

Unter "Scrolling" versteht man das Verschieben des Bild- schirminhalts in eine bestimmte Richtung. Waehrend der Conm- modore 64 den Bildschirminhalt im Normalfall nur nach oben verschieben kann (wenn der Cursor ueber den unteren Bild- schirmrand hinaus bewegt wird oder ueber den unteren Bild- schirmrand hinaus gedruckt wird), so kann auch die Notven- digkeit bestehen, den Bildschirminhalt in die anderen Rich- tungen zu verschieben. Diese Eigenschaft hat zum Beispiel ein sogenannter "SCROLLER", der zum Beispiel in EXBASIC LEVEL II fuer den Commodore 64 enthalten ist. Beim Progranm- mieren von BASIC ermoeglicht er es, BASIC-Programme ueber den Bildschirm zu rollen, als waeren sie in einem Band vor- handen. Das englische Wort "scroll" heisst schliesslich auch "Schriftrolle". Wird mit dem Cursor ueber den Bildschirmrand hinausgefahren, so wird die naechste oder vorherige (je nachdem, ob der untere oder obere Bildschirmrand "ueber- schritten" wurde) BASIC-Zeile automatisch gelistet, was die Korrektur von Programmen erheblich vereinfacht. Diese Art des Scrollens ist allerdings auch nur waehrend der Programm-

60

entwicklung verwendbar. Bei der Ausfuehrung eines Programms muessen andere Moeglichkeiten vorhanden sein.

Beim Scrolling, das der VIC-II-Chip des Commodore 64 unter- stuetzt, handelt es sich jedoch um ein Scrolling, das den Bildschirminhalt in einzelnen Punktzeilen, aus dem die LCon- putergraphiken aufgebaut sind, verschiebt, wohingegen das normale BASIC-Scrolling immer um ganze Zeichen - bestehend aus acht Punktzeilen - verschiebt (anders ist dies in BASIC ja auch nicht sinnvoll).

Diese Moeglichkeit des Video-Chips kann dazu benutzt werden, Daten und Informationen an den Benutzer langsam auf dem Bildschirm erscheinen zu lassen. Waehrend der vVIC-II-Chip dazu jedoch schon einen erheblichen Beitrag leistet, indem er das Scrollen innerhalb eines Bereichs von acht Rasterzei- len erledigt, so muss das eigentliche Scrollen um acht Ra- sterzeilen (also um ein ganzes Zeichen) durch ein getrenntes Maschinenprogramm selbst erfolgen.

Hier erst einmal das Prinzip des sogenannten "Smooth Scrolling" in der Theorie:

Da die Daten, die auf den Bildschirm gescrollt werden sol- len, langsam erscheinen und zeitweilig nur teilweise sicht- bar sind (genauso wie die Zeichen, die langsam verschvin- den), wird eine Pufferzone benoetigt, die die neuen Daten aufnimmt und dann nach und nach auf den Bildschirm gebracht wird. Diese Pufferzone in Form einer unsichtbaren Zeile oder Spalte erhaelt man, indem man den Bildschirm einfach ver- kleinert. Dieses ist bereits durch den VIC-II-Chip vorgese- hen. Soll in horizontaler Richtung verschoben werden, so kann der Bildschirm einfach auf eine Breite von 38 Zeichen verkleinert werden. Ebenso ist es moeglich (bei vertikaler Verschiebung des Bildschirminhalts), eine Verkleinerung auf 24 Zeilen zu erreichen. Es existieren nun "geschuetzte" Zei- len, die nicht gesehen werden koennen (aber fuer den Compu- ter immer noch vorhanden sind), da die Umrahmung nun eine groessere Flaeche als zuvor einnimmt.

Die noch sichtbare Flaeche kann nun (je nachdem was verklei- nert wurde) um jeweils acht Punktzeilen (wird durch drei Bits in einem Register des Video-Chips festgelegt) verscho- ben werden. Bei einem Extremvert (null oder sieben, je nach Richtung) ist gerade eine Zeile (oder gar keine) des neuen Zeichens zu erkennen, beim anderen Extremvert (sieben oder null, je nach Richtung) das gesamte Zeichen (oder sieben Zeilen davon).

Nach der Verkleinerung des Bildschirms wird zuerst das Regi- ster fuer die einzelnen Zeilen auf den Maximal- oder Mini- malwert gebracht (richtungsabhaengig, siehe Uebersicht). Dann werden die neuen Daten "unter" dem Rand (also dorthin, vo nur eine oder gar keine Punktzeile des Zeichens zu erken- nen ist) plaziert. Darauf erfolgt die Verminderung/Erhoehung des Registers, das fuer die Einzelzeilenverschiebung zu- staendig ist. Ist der Minimal- beziehungsweise Maximalwert erreicht, so wird das Maschinenprogramm aufgerufen. Es ver- schiebt nun den Bildschirminhalt wirklich (also nicht nur scheinbar gemaess der Darstellung) und setzt sofort darauf das Einzelzeilenregister wieder auf den Anfangsvwert zurueck, so dass wieder neue Daten plaziert werden koennen.

Die Verkleinerung auf eine Breite von 38 Zeichen je Zeile

(nur scheinbar!!!) erfolgt durch Loeschen von Bit 3 in Regi- ster 22 (Adresse 53270) des VIC-II-Chips. Bit 3 von Register

61

17 (Adresse 53265) dient entsprechend zur vertikalen Schrumpfung des Bildschirms auf 24 Zeilen.

Die Einzelzeilenregister zu je drei Bits (fuer acht ver- schiedene Werte) befinden sich jeweils in den Bits 0 bis 2 von Register 22 (Adresse 56270) fuer die Verschiebung in X-Richtung sowie Register 17 (Adresse 53265) fuer eine Y-Verschiebung.

Hier eine Uebersicht, welche Register in welcher Weise be-

einflusst werden muessen, um eine Verschiebung in eine be- stimmte Richtung zu erreichen:

m u m m m En m ab ED TE CE m ED TE CE EB ER ER ab a Ep Em CE EC ET > CE TE > ES u CD GE m En «ED CE EB <ED Em ED ED CD ED «ES En m CED Cm mp am = 2 m ab CD CD CD CD ED CD m eb ED a am ED CE ED ED > m a ED En CED ED de CE ED ED CE ED Cup ED ED ED CED CED «ED GEB mb air dED mr CED «ED MED CAD CE GES (E> um am dm m— m mm ED CE ED ED CD CD TE Em ED CE CD CD ED TR ED CE m TE TE En CD U Cu ED En CE TE En EEE u ED Ep ED CE EEE EB ED EU GE GE CE ED a Cum

I Scrollregister I Y I Y I X I X I lanfanguert IT I oO ı 7 rı0o1 I Veraenertug I 1 I A I 1. 1 I Pufferrend I unten I oben I rechts I links I

Befindet sich der Wert null (als Anfangsvert) in einem Scrollregister, so ragt unter dem Pufferrand (fuer neue Da- ten) genau eine Punktzeile hervor. Wurde der Wert sieben in eins der Scrollregister (ebenfalls als Anfangsvert) ge- schrieben, so ist das ganze Zeichen (unter dem Pufferrand) unsichtbar. Entsprechendes gilt fuer die Endwerte und Pufferraender, in denen die Daten verschwinden.

Hierzu ein Beispiel: Es soll ein auf dem Bildschirm stehen- der Text von unten nach oben Totiert werden, ohne dass neue Daten zugefuehrt werden.

Es wird eine Maschinenroutine benoetigt, die den Bildschirm- inhalt um eine Zeichenzeile nach oben verschiebt und die obere Zeile dann wieder nach unten kopiert (dies entspricht einem Rotieren des Bildschirminhalts).

Allerdings wird man bemerken, dass es damit allein nicht ge- tan ist; wird naemlich das Einzelzeilenregister geaendert (oder die Maschinenroutine aufgerufen), so wird man bemer- ken, dass es zu einem Flackern auf dem Bildschirm kommt. Dies liegt daran, dass es waehrend der Erstellung des Bildes auf dem Bildschirm zu einer Aenderung der Darstellungsvweise beziehungsweise der Daten kommt. Ein Teil des Bildes wird nach den alten Daten erstellt, ein anderer Teil nach neuen Daten. Dies gilt es zu verhindern. Waehrend das aber bei der Einzelzeilenverschiebung noch recht einfach ist, so bereitet es bei der Zeichenverschiebung schon Schwierigkeiten, da auch Maschinenprogramme, wenn sie auch noch so schnell sind, im Verhaeltnis zu der Zeit bei der Bilderstellung nicht schnell genug sind.

Allerdings wurde dieses Flackern durch Abfrage des Raster- zeilenregisters umgangen. Die Aenderung der Bildschirmdaten erfolgt so, dass es nicht zu einer Ueberlappung (und damit zu einem Flackern) kommen kann. Dies war aber nur durch An- wendung einer nicht sehr eleganten Methode moeglich. Aber

62

schliesslich kam es hierbei auf Geschwindigkeit an. Hier das fertige Programm:

100 FOR I = 828 TO 927 : READ A : POKE I, A : NEXT

110 DATA 120, 169, 251, 205, 18, 208, 208, 251, 206, 17, 208 120 DATA 88, 96, 120, 173, 17, 208, 16, 251, 72, 173, 17

130 DATA 208, 48, 251, 169, 107, 205, 18, 208, 208, 251, 160 140 DATA 40, 185, 255, 3, 153, 255, , 136, 208, 247, 185, 40 150 DATA 4, 153, , 4, 200, 208, 247, 185, 40, 5, 153, „5 160 DATA 200, 208, 247, 185, 40, 6, 153, , 6, 200, 208, 247 170 DATA 160, 64, 185, 232, 6, 153, 192, 6, 200, 208, 247 180 DATA 160, 39, 185, , 1, 153, 192, 7, 136, 16, 247, 104 190 DATA 9, 7, 141, 17, 208, 88, 96

200 POKE 53265, PEEK (56265) AND 240 OR 7 : C = PEEK (646)

210 FOR I = 55296 TO 56295 : POKE I, C : NEXT : N = 63 300 FOR I = 0 TO 6 : FOR J = O0 TON : NEXT : SYS 828 : NEXT 310 FOR J = 0 TO.N : NEXT : SYS 841 : GOTO 300

In Zeile 100 wird das Maschinenprogramm in den Bereich des Cassettenpuffers eingelesen, da dieser normalerweise unbe- nutzt ist (das Programm enthaelt jedoch keinerlei Absolut- adressen und kann daher auch an jeder anderen Stelle im Ar- beitsspeicher stehen). Die Daten fuer das Maschinenprogramm stehen in den Zeilen 110 bis 190. Zwei aufeinanderfolgende Kommas entsprechen uebrigens dem Wert null. Zeile 200 ver- kleinert den Bildschirm auf 24 Zeilen und stellt die momen- tane Cursorfarbe fest. Mit dieser Farbe wird nun das gesamte Farb-RAM gefuellt. Mancher ahnt, was es damit auf sich hat: Die Maschinenroutine verschiebt lediglich den Inhalt der Vi- deomatrix im Bereich von 1024 bis 2023. Das Farb-RAM und auch die Tabelle der Doppelzeilenkennzeichnungen (!) bleibt unbeachtet, da dadurch die Routine zu langsam wuerde. Daher sollte (wenn auf dem Bildschirm Programmzeilen verschoben wurden) nach Abbruch auf jeden Fall der Bildschirm geloescht verden, da es, -venn solche Programmzeilen editiert werden, zu Techt. merkwuerdigen Effekten kommen kann.

Die Variable N ist der Wert fuer die Geschwindigkeit (Ver- zoegerungsschleife). Dann wird der Bildschirm in sieben Schritten jeweils um eine Punktzeile verschoben, wozu die Routine ab der Adresse 828 dient. Sie wartet mit dem Vermin- dern des Einzelzeilenregisters ab, bis es zu keinem flackern kommen kann. Die Routine ab Adresse 841 verschiebt den Bild- schirminhalt um eine Zeile nach oben und setzt das Einzel- zeilenregister wieder auf den Anfangsvert zurueck. Auch hier wird durch eine entsprechende Abfrage ein Flackern verhin- dert.

Soll dieses Programm so abgeaendert werden, dass jeweils neue Daten nachgefuellt werden, so muss nach Aufruf der Ver- schieberoutine (SYS 841) die letzte Zeile mit den neuen Da- ten gefuellt werden (achten Sie darauf, dass der Cursor nicht ueber die letzte Zeile hinausfaehrt). Sind die neuen Daten "unter" dem Bildschirmrand plaziert, so kann wieder mit Zeile 300 fortgefahren werden.

Die folgenden Programme entsprechen dem obigen Programm, nur wird jeweils in eine andere Richtung verschoben. Auch jedes dieser Programme besteht aus zwei Teilen: ab Adresse 82B zum Aendern des Einzelzeilenregisters sowie ab Adresse 84] zum Verschieben um ein ganzes Zeichen. Lediglich beim Verschie- ben des Bildschirminhalts nach UNTEN kam es zu zeitlichen Problemen. Da hier der Bildschirminhalt von unten nach oben geaendert werden muss (im Gegensatz zu den uebrigen Program- men, die den Bildschirm von oben nach unten aendern), ist es hier nicht mehr moeglich, die Bildaenderung so zu steuern,

63

dass diese nicht vom Zeilenstrahl "ueberholt" wird. So exi- stieren zwei Einsprungstellen: die erste an der Stelle 850. Hierbei kommt es zu einem Flackern, das jedoch durch geeig- nete Abfragen auf ungefaehr die vier unteren Bildschirmzei- len begrenzt werden kann. Die zweite Einsprungstelle befin- det sich an der Adresse B4l. Hier wird nun der Bildschirm "abgeschaltet" (siehe SCREEN BLANKING). Es sollte jedoch bei Verwendung dieser Einsprungstelle die Farbe fuer den Rahmen identisch mit der des Hintergrunds sein, da dann das Ab- schalten am wenigsten stoert.

Scerolling nach LINKS:

100 FOR I = 828 TO 927 : READ A : POKE I, A : NEXT

110 DATA 120, 169, 251, 205, 18, 208, 208, 251, 206, 22, 208 120 DATA 88, 96, 120, 173, 17, 208, 16, 251, 173, 17, 208 130 DATA 48, 251, 169, 60, 205, 18, 208, 208, 251, 162, 39 140 DATA 134, 251, 232, 134, 253, 162, 3, 134, 252, 134, 254 150 DATA 24, 162, 25, 160, 217, 177, 251, 72, 177, 253, 145 160 DATA 251, 200, 208, 249, 136, 104, 145, 253, 165, 251 170 DATA 105, 40, 133, 251, 165, 252, 105, , 133, 252, 165 180 DATA 253, 105, 40, 133, 253, 165, 254, 105, , 133, 254 190 DATA 202, 208, 213, 173, 22, 208, 9, 7, 141, 22, 208, 88 200 DATA 96

300 POKE 53270, PEEK (53270) AND 240 OR 7 : CE = PEEK (646)

310 FOR I = 55296 TO 56295 : POKE I, C : NEXT : N = 63 320 FOR I = 0 T0 6 :: FOR J = 0 TO N : NEXT : SYS 828 : NEXT 330 FOR J = 0 TO N : NEXT : SYS 841 : GOTO 320

Scrolling nach RECHTS:

100 FOR I = 828 TO 927 : READ A : POKE I, A : NEXT

110 DATA 120, 169, 251, 205, 18, 208, 208, 251, 238, 22, 208 120 DATA 88, 96, 120, 173, 17, 208, 16, 251, 173, 17, 208 130 DATA 48, 251, 169, 73, 205, 18, 208, 208, 251, 162, 255 140 DATA 134, 251, 232, 134, 253, 162, 3, 134, 252, 232, 134 150 DATA 254, 24, 162, 25, 160, 39, 177, 253, 72, 177, 251 160 DATA 145, 253, 136, 208, 249, 104, 145, 253, 165, 251 170 DATA 105, 40, 133, 251, 165, 252, 105, , 133, 252, 165 180 DATA 253, 105, 40, 133, 253, 165, 254, 105, , 133, 254 190 DATA 202, 208, 214, 173, 22, 208, 41, 248, 1l4l, 22, 208 200 DATA 88, 96

300 POKE 53270, PEEK (53270) AND 240 : C = PEEK (646)

310 FOR I = 55296 10 56295 : POKE I, C : NEXT : N = 63 320 FOR IT =0T06 : FOR J =0 TO N : NEXT : SYS 828 : NEXT 330 FOR J = 0 TO N : NEXT : SYS 841 : GOTO 320

Scrolling nach UNTEN:

100 FOR I = 828 TO 924 : READ A : POKE I, A : NEXT

110 DATA 120, 169, 251, 205, 18, 208, 208, 251, 238, 17, 208 120 DATA 88, 96, 120, 173, 17, 208, 41, 239, 141, 17, 208 130 DATA 120, 160, 39, 185, 192, 7, 153, ,„ 1, 136, 16, 247 140 DATA 185, 192, 6, 153, 232, 6, 136, 208, 247, 136, 185 150 DATA 193, 5, 153, 233, 5, 136, 208, 247, 136, 185, 194 160 DATA 4, 153, 234, 4, 136, 208, 247, 160, 195, 185, 255 170 DATA 3, 153, 39, 4, 136, 208, 247, 160, 39, 185, , 1 180 DATA 153, , 4, 136, 16, 247, 173, 17, 208, 4l, 248, 9 190 DATA 16, 14l, 17, 208, 88, 96

300 POKE 53265, PEEK (53265) AND 240 : C = PEEK (646)

310 FOR I = 55296 TO 56295 : POKE I, C : NEXT : N = 63

320 FOR I =0T06 : FOR J = 0 TON : NEXT : SYS 828 : NEXT 330 FOR J = 0 TON : NEXT : SYS 841 : GOTO 320

64

Register

Register

Register bis Register

Register

Register

Register

Register

Register

Register

17:

18:

19:

20:

21:

Registeruebersicht fuer den VIC-II-Chip:

Die Adresse eines Registers errechnet sich aus der Summe der Registernummer und der Start- adresse 53248.

enthaelt die acht niedervwertigen der insgesamt neun Bits der X-Koordinate von Sprite #0. Das hoechstwertige Bit befindet sich in Bit 0 von Register 16.

enthaelt die Y-Koordinate von Sprite #0. Hierzu exisitiert kein weiteres Bit, da nur acht Bits zur Darstellung der Y-Koordinate benoetigt ver- den.

diese Register haben paarweise die gleiche Be- deutung wie die Register 0 und 1, jedoch je- weils fuer Sprite #1 bis Sprite #7.

hier befinden sich die acht hoechstvertigen Bits der X-Koordinaten der Sprites. Dabei ist jedem Sprite das jeweilige Bit mit der Nummer des Sprites zugeordnet.

Bits 0 bis 2 enthalten den Wert der vertikalen Verschiebung des Bildschirms in Rasterzeilen (siehe Scrolling).

Ist Bit 3 geloescht, so werden nur noch 24 Zei- len des Bildschirms dargestellt, ansonsten alle 25 Zeilen.

Ein Loeschen von Bit 4 bewirkt das Ausfuellen des gesamten Bildschirms mit der Farbe des Rah- mens (Bildschirm "ausschalten").

Bit 5 schaltet (wenn gesetzt) in den Bit Map Modus um.

Bit 6 schaltet (wenn gesetzt) in den Extended Color Mode (Modus fuer erweiterte Hintergrund- farben).

Bit 7 ist das hoechstwertige Bit der neun Bits des Rasterregisters.

Rasterregister (zusammen mit Bit 7 aus Register 17). Wird das Register gelesen, so wird die mo- mentane Rasterzeile (die auf dem Bildschirm dargestellt wird) ausgelesen. Beim Schreiben wird der geschriebene Wert in einen internen Zwischenspeicher uebertragen, der dann zum Ausloesen eines IRQs verwendet wird.

X-Koordinate der Position des Zeilenstrahls beim Ausloesen einer negativen Flanke auf dem Lightpen-Input (die acht hoechstwertigen der neun Bits).

vie Register 19, aber Y-Koordinate Sprite Enable. Jedem Sprite ist ein Bit (der Nummer entsprechend) zugeordnet. Ist das Bit

gesetzt, so ist dieses Sprite aktiviert ("ein- geschaltet").

65

Register 22:

Register

Register

Register

Register

Register

Register

Register

Register

Register

Register

Register

23:

24:

25;

26

21%

28:

29:

30:

31:

32:

33;

Bits O bis 2 enthalten den Wert der horizonta- len Verschiebung des Bildschirms in Rasterzei- len (siehe Scrolling).

Ist Bit 3 geloescht, so werden nur noch 38 Spalten des Bildschirms dargestellt, ansonsten alle 40 Spalten.

. Bit 4 schaltet (wenn gesetzt) in den Multicolor

Modus um.

Bit 5 ist das Reset-Bit und muss bei der lIlni- tialisierung geloescht werden, da . ansonsten keinerlei Operationen von Seiten des VIC-II-Chips durchgefuehrt werden.

Sprite Y-Expand. Wird ein Bit gesetzt, so wird das zugehoerige Sprite in doppelter Breite dar- gestellt.

Bits 1 bis 3 legen die Startadresse des Zei- chengenerators fest.

Im Bit Map Modus gibt Bit 3 jedoch die Start- adresse der Bit Map an.

Durch Bit 4 bis 7 wird die Startadresse der Vi- deomatrix (Bildschirmspeicher) festgelegt.

Interrupt Flag Register:

Bit O0: Rasterregister

Bit 1: MOB-DATA Kollision:

Bit 2: MOB-MOB Kollision

Bit 3: Lightpen

Ist ein Bit gesetzt, so ist die zugehoerige Be- dingung erfuellt. Wird eine Eins in eine Bitpo- sition geschrieben, so wird das Bit geloescht. Bit 7 ist gesetzt,. falls mindestens eins der Bits von O bis: 3 zusammen mit seinem Enable Bit gesetzt ist.

Interrupt Enable Register:

Belegung wie oben (Bit 7 unbenutzt). Zugehoeri- ges Bit gibt an, ob die Interruptquelle einen IRQ ausloesen kann.

MOB-DATA Prioritaetsregister: Ist das zum

'Sprite gehoerige Bit gesetzt, so besitzt das

Sprite eine niedrigere Prioritaet als der Vor- deryrund.

MOB-Multicolor: Bei gesetztem Bit wird das zu- gehoerige Sprite im Multicolor-Modus darge- stellt.

Sprite X-Expand. Wird ein Bit gesetzt, so wird das zugehoerige Sprite in doppelter Hoehe dar- gestellt.

MOB-MOB Collision: zum MOB gehoeriges Bit wird gesetzt, falls Beruehrung mit anderem MOB er- folgte.

MOB-DATA Collision: zum MOB gehoeriges Bit wird gesetzt, falls Beruehrung mit Vordergrunddaten erfolgte.

Exterior Color (Rahmenfarbe)

Background Color #0 (Standard HNintergrundfarbe)

66

Register 34: Background Color #1 bis Background Color #3, bis veitere Hintergrundfarben fuer andere Darstel- Register 36: lungsmodi.

Register 37: enthalten die Farben zur Darstellung von Multi- Register 38: color Sprites.

Register 39: Jedes Register enthaelt eine Farbe zur Darstel- bis je eines Sprites (von Nummer 0, Register 39 bis Register 46: Nummer 7, Register 46).

Bei Farbregistern (Register 32 bis 46) ist jeweils nur das untere Nybble (Bit O bis Bit 3) benutzt.

Nichtaufgefuehrte Bits sind unbenutzt. Unbenutzte Bits ent- halten den Wert eins.

Die Farben des VIC-II-Chips

Der Video-Chip verfuegt ueber die Moeglichkeit der Darstel- lung von sechzehn Farben. Diese Farben werden in Form von Farbcodes sowohl in den Farbregistern als auch im Color- Nybble-RAM verwendet. Hier eine Uebersicht ueber alle farben und wie sie ueber die Tastatur erreicht werden koennen (PRINT):

Farbcode Farbe Tastatur 0 schwarz Control - 1 1 weiss Control - 2 2 rot Control - 3 3 cyan (tuerkis) Control - 4 4 violett Control - 5 5 gruen Control - 6 6 blau Control - 7 7 gelb Control - 8 8 orange Commodore - ] 9 braun Commodore - 2 10 rosa Commodore - 3 11 hellgrau Commodore - 4 12 mittelgrau Commodore - 5 13 hellgruen Commodore - 6 14 hellblau Commodore - 7 15 dunkelgrau Commodore - B

Ist der Multicolor Modus eingeschaltet (bei Zeichendarstel- lung), so stehen nur die ersten acht Farben fuer Zeichen zur Verfuegung.

67

Die

Pin Pin Pin Pin Pin Pin Pin Pin Pin

Pin

Pin Pin Pin Pin Pin Pin Pin Pin Pin Pin Pin Pin

Pinbelegung des VIC-II-Chips (MOS 6567)

- 7:

Datenbus des Prozessors (Bit 6 bis Bit 0)

IRQ/ Ausgang zum Prozessor

Lightpen/ Eingang

CS/ Chip Select, Zugriff auf Register des Chips R/W Schreib/Leseleitung des Prozessors, O=Write BA (Bus Available) Freigabe des Prozessorbus' VDD, Stromversorgung (+12 Volt)

COLOR, Ausgang fuer Farbsignal

SYNC, Ausgang fuer Synchronisationssignale AEC/, Kontrolle des Systembus' durch VIC

PHO, Ausgang des Prozessortakts

RAS/, Steuersignal fuer dynamische RAMs

CAS/, Steuersignal fuer dynamische RAMs

GND, Masseleitung

PHCL, Eingang der Colorfrequenz

PHIN, Eingang der Dotfrequenz

All, Adressbus des Prozessors

AO bis A5, AB bis Al3, gemultiplexter Adressbus A6 bis 10, Adressbus des Prozessors

Datenbus fuer Zugriff auf Color Nybble RAM Datenbus des Prozessors (Bit 7)

VCC, Stromversorgung (+5 Volt)

Fr DÖHNFTGURAT ICH ER nn i u 3 b-, ILL 33 DRT BD I DES 37 PTIOB9 357 0B1G 35 DE11 a4 ala 330777993 32 Ins os sser LH Zu Re &9 m 28 7 IA ALZ 27 Fnsni 1 25 7 JRZrALG 25 AL’R3 24 Ra-R: FÄAS TDT]18 ER =: chE 13 22 FHIH GHO Dee 24 FTIFHCL

SPFEFEITE-EHTLIURFSBILRTT

SANTOS FION- NG

En En DE DD a nt

GLIIIIITITETTIETTTIT TH OL II TI III T IT TITTTTCTT Pa | U BE DE GR DR ER DE DR HE DE DR RR DR HR HR TE Te TI TTTrT

SATIN TAUATIION-U CS

need

IE IR EEE DucG BE DU DR OU DER DR DE DR DR DER N HR DR DE ED SGANATIO-VO SAU TION-ONG

Rn ee ee a er Tot]

HE Da DE u EEE DER DU HER EN EN ER EN EN SU TIOL-ONETIN TIIOR- NS

III I IT TUN | SANATIGNM-ONETOIAITITION- NS

RD DT De aD n/a

SEATTLE FRI TAUNITIANOT- HT

need

69

BEDIENUNG DES SPRITE-GEHERRTORS

Da=z Proaramm "SPRITE GENERRTOR" wandelt nach dem Start durch "RUN" ein in DATA-Zeilen kefindliches Muster der Groesse var 21 Zeilen mal 24 Spalten in die entsprechenden Dezim=lwerte fuer die Definition eires Sprites um. Die Dezimalwerte wer- den automatisch in Proaranmzeilen mit DATA=E umgewandelt, de- ren erste Zeilennummer durch die Yariakle "L" und der Ak- stand zwischen dern Zeilen durch "5" beides in Zeile 1)» festselest werden. Es muss natuerlich darzauf wesachtet wer- den, dass die neuen Zeilernummern nicht das (rsprungsero- Sr anım vebkerschreiken. wern nach weitere Sprites kreiert wer— den sallen.

Die Yariakle "FF" dekenf=lls in Zeile 1) least fest. ck das Muster als Standard- (F=1) oder Multicclor-Sprite «F=2> auf- gefasst merden scll. Im Standercdmadus entspricht ein Leer- zeichen dem Bitwert a und ein Asterisk '"%" einem wesetztenr Bit. Im Gesensatz dazu werden im Multicolarmodus immer zwei aufeinander falgende Zeichen behandelt. Sc entsprechen zwei Blanks dem Bitpazr "aa". "a4" entspricht "al", "++" wird in "1a" und "#4" in "11" umgewandelt.

sSPEFEITE GEHERRTOR

a REM ##4# SPRITE GENERATOR FÜR THE COMMODORE 84 ###

1 L=199:5=10:F=1:PRINT" UM" :N=. :GOSUBRE :FORI=. TO2a:RERDA$ :FORI=. TOZ:R=. 2 FORK=1TOSSTEPF :B=2%#B#F :C$=MNID$LA$ . T$S+K „FD s IFCH="K" ORCH=" #4" THENB=B+H1 3 B=B-2%0C$=" ++") - IL C$="44") NEXT :P$="" Ss IFRTHENF$=MIDESESTRECRD „25

4 IFPOS«. >+LEN<P$>>P7STHENPRINTCHRE 205 :GOSUBE

S PRINTP3$" ." 3 :NEXT NEST :PRINTCHRS CZ" 3 :POKE19S.N:END

& PRINTMID$S{STR$<LI . 27" DR" 7 :L=L+SsPOKES3S1+N. 13 :N=HN+1 RETURN

1a DATR" FEEEREEN "

11 DATA" FEFTETETETREN z

12 DATA" FETTE TFT vi

13 DATA" VERERRRERTTENTENTENE

14 DATH" Ki ek" 15 DATA" Be OR" 16 DATA" Br" 17 DATA ERREREEEEEEEEREEREEE "' 18. DATA 5 13 DATA KARRIERE 2a DATA 2

21 DATA BERRRRIEIEE . 22 DATA ERREREEEE 23 DATA" n 24 DATA" ll = 23 DATA" elek " 26 DATR" Sek . 27 DATR" EEE EC & 28 DATR" EEE 2 29 DATR" KERNE & 38 DATA" RER > ERDY.

70

ABFRAGE UND BELEGUNG DER FUNKTIONSTASTEN

Sowohl Commodore 64 als auch \IC-20 verfuegen ueber vier Funktionstasten, die zum Beispiel dıe Erstelluna von Pro- grammen wesentlich vereinfachen koennen. Auch ermoealichen sie eine bequeme und uebersichtliche Benutzerfuehrung durch Anvender- und Spielprogramme. Im folgenden die Erklaerung der praktischen Ausfuehrung dieser Moeglichkeiten:

Abfrage der Funktionstasten

Die Funktionstasten sind Tasten, deren ASCIIs im Bereich von 133 bis 140 liegen. Dies sind Codes im Bereich der nicht- druckenden Steuercodes (siehe Tabelle), was Grund dafuer ist, dass das Druecken dieser Tasten keinerlei Wirkung zeigt. Lediglich innerhalb von Anfuehrungszeichen (im soge- nannten Quote-Modus) und nach dem Einfuegen von Leerzeichen durch "INSERT" (im Insert-Modus) werden Zeichen ausgegeben, abhaengig vom Darstellungsmodus entweder Balken oder \Vier- telkreise (im Grafikmodus) oder Buchstaben von "E" bis "L" (im Kleinschriftmodus), beide Male jedoch in Negativdarstel- lung. Dieses Verhalten ist aehnlich dem der Tasten zur Cur- sor- und Farbsteuerung.

Um nun eine gedrueckte Funktionstaste in BASIC-Programmen zu erkennen, muss entsprechend der Abfrage von anderen Tasten. vorgegangen werden. Zum Beispiel so, wie im folgenden Pro- grammausschnitt:

350 PRINT CHR$ (147) "Fl - SEGMENT A"

360 PRINT : PRINT "F3 - SEGMENT B"

370 PRINT : PRINT "BITTE 'Fl' ODER 'F3' DRUECKEN!" 380 GET G$ : IF 6G$ = CHR$ (133) GOTO 500

390 IF G$ C) CHR$ (134) GOTO 380

400 REM SEGMENT B

500 REM SEGMENT A

Hier die Codes der Funktionstasten:

Fl: 133 F3: 134 F5: 135 F7: 136 F2: 137 Fa: 138 F6: 139 F8: 140

Die Codes von 133 bis 136 verden beim Druecken der Funk- tionstaste alleine erzeugt, die ASCIIs von 137 bis 140 erge- ben sich beim gemeinsamen Druecken entweder mit einer SHIFT- Taste oder der COMMODORE-Taste.

Belegung von Funktionstasten

Unterschiedlich dazu ist die Vorgehensweise zum Belegen der Funktionstasten. Hierbei werden den Tasten bestimmte Texte oder Befehlsworte zugeordnet, die haeufig benoetigt werden. Bei Ausuebung dieser Funktion werden die Tasten auch als "Softkeys" bezeichnet.

Das Belegen ist NUR durch Verwendung eines geeigneten Ma- schinenprogramms moeglich und NICHT ueber BASIC. Hierzu wird der Sprungvektor (655/656) geaendert, so dass auf ein eige- nes Maschinenprogramm verzweigt wird. Dieser Vektor wird in der Routine SCNKEY verwendet, die die Abfrage der Tastatur erledigt und normalerweise durch die Interruptroutine aufge- rufen wird. SCNKEY belegt den Bereich von 60039 bis #HN60N (siehe ROM-Listing).

71

Bei Erreichen des Sprungvektor (655/656) sind bereits die Adressen 203 und 653 auf den aktuellen Wert gesetzt worden. Erstere enthaelt den Tastaturmatrixcode von OD bis 64, (653) gibt an, welche Kombinationstasten gedrueckt sind (SHIFT, COMMODORE und CONTROL).

Ist durch das zusaetzliche Maschinenprogramm nun festge- stellt worden, dass eine Funktionstaste gedrueckt wurde, so muss nun noch der Zustand der SHIFT-Flag geprueft werden. Daraus errechnet sich dann, velcher Text im Tastaturpuffer abgelegt werden soll.

Dies wird durch das im Anschluss abgedruckte BASIC-Programm erledigt. Es legt das Maschinenprogramm zur Abfrage der Funktionstasten im Bereich ab Adresse 828 ab, kann jedoch auch in einen beliebigen anderen Bereich gelegt werden. Hierzu muss nur die Variable "S" geaendert werden. Der Be- ginn der Texttabelle wird durch "D" festgelegt. Sie ist in acht Eintraege zu je zehn Bytes aufgeteilt, entsprechend "Fl" bis "F8". Die Belegungen koennen durch Aendern der letzten DATA-Zeile eigenen Anwendungen angepasst werden. Der Rueckwaertspfeil gibt an, ob die RETURN-Taste gedrueckt wer- den soll. Die Laenge des Textes darf zehn Buchstaben nicht ueberschreiten.

Nach Ausfuehrung des Programms durch "RUN" wird die ervei- terte Tastaturabfrage automatisch aktiviert. Jedoch wird Vektor (655/656) beim Druecken von "RUNSTOP" und "RESTORE" wieder auf den Normalwert gesetzt, so dass eine Neuaktivie- rung notwendig ist. Dies erfolgt durch einen "SYS" mit der Zahl als Argument, die beim Start des Programms ausgegeben wurde.

iaa REM ## FUHCTICH KEYS FÜR THE COMMODORE 84 & THE VIC2a ## 11a 5 = 828 ; D= 312 : FOR IT =5 TOS + S3 : RERD R v

12a POKE I. R =: NE#T : POKE 5 + 74. S - 2565 # INT (S / 256) 13a FPOKE S + 76. S .* 256 : PÜKE S + 4 D .’ 256 i4&@ POKE 5 + 45. DO - 256 # INT iD 2

15a FOR I = a TO 7 : RERD A$ : FOR IT 18a B = ASC KMID$ {A#, I. 125 : IFB iva FKED + I # 14 + T- 1.B : NEXT isa IF I <> 11 THEN POKE OD + I #19 + T-1,0

128 NEXT =: FRINT 5 + 73 : SYS S + 73

2aa DATA 184. 203, 1968. 197, 208, il, 44, 259, 255. 16, 3 ia DATA 76, 220. 235, 76. 72, 235. 177, 245. 201. 137, 176 eza DATA 239, 233. 132. 144. 235. 168, 173, 141, 2. 74. 152 23a DATA 42. 133, 197. 18. 18. 1al, 197, 1a, 168, 162, 185 e4a DATA „. 240, 9, 157. 119. 2, 200. 232. 224, 18, 208

esa DATA 242, 134. 198, 162, 255, 44, 25a, 255. 16. 3, 76 esa DATA 186, 235, 76, 38, 235. 182. 160, 142, 143, 2 era DATA 14a, 144, 2, 96

sag DATR RUNe.GOTG,LISTr.?FRECBIe,POKE.PEEK« „THEN, INPUT

> 1 TO LEN &R$> 95 THEN RB = 13

72

SOUNDERZEUGUNG MIT DEM COMMODORE 64

Der Commodore 64 besitzt einen hochwertigen Soundbaustein, den MOS 6581, auch SID (Sound Interface Device) genannt. Mit diesem lassen sich Geraeusche fast aller Art erzeugen, Mu- sikstuecke spielen und Soundeffekte zum Beispiel in Spiele einbauen. Hier eine grobe Funktionsuebersicht:

Der SID verfuegt ueber drei getrennte Soundgeneratoren (die miteinander synchronisiert oder ringmoduliert werden koen- nen) mit einem Frequenzbereich von O0 Hz bis ca. 4 kHz. Die Huellkurve (ADSR) eines jeden Tongenerators kann getrennt gewaehlt werden, ebenso die Wellenform, von der vier ver- schiedene (Dreieck, Saegezahn, Rechteck und Rausch) zur Aus- wahl stehen. Es steht ausserdem ein filter zur Verfuegung, mit dem die drei Tongeneratoren sowie eine externe Signal- quelle verfremdet werden koennen. Der dritte Tongenerator kann ausserdem durch zwei weitere Register kontrolliert ver- den: Eines gibt die Huellkurve und damit die Amplitude an, das zweite Register kann zur Modulation der anderen beiden Soundgeneratoren oder zum Beispiel zur Erzeugung von Zu- fallszahlen dienen.

Jeder der drei Tongeneratoren kann durch folgende Parameter gesteuert werden:

Frequenz: Die Frequenz wird durch einen Wert einer Breite von 16 Bits festgelegt und wird daher durch zwei Register (je Stimme) bestimmt. Dadurch existieren 65536 verschiedene Tonhoehen. Die Frequenz errechnet sich dabei wie folgt:

F=-NnN*+c/ 2 t 24

Dabei ist N die 16-Bit-Zahl, C die Systemtaktfrequenz und F die effektive Frequenz (die letzteren beiden Angaben in Hertz). Um zum Beispiel einen Ton einer bestimmte Frequenz erklingen zu lassen, kann prinzipiell folgendermassen vorge- gangen werden:

14318180 / 14 : IF PEEK (678) THEN C = 17734472 / 18

30C = 310Q=2 24 /C 320?N=F *Q : HI = INT (N / 256) : LO = N - 256 * HI

Wie ersichtlich, sollten hier, wie bei anderen Gelegenheiten auch, die verschiedenen Taktfrequenzen der verschiedenen Ge- raete beachtet werden, da die Taktfrequenz nicht exakt ein MHz betraegt. Die Variablen "LO" und "HI" enthalten nach Ausfuehrung nun das LSB und MSB fuer die beiden Register zur Festlegung der Frequenz. Die Frequenz laesst sich in Schrittweiten von ungefaehr 0.06 Hz festlegen.

ADSR-Funktion: Durch diese aus vier Parametern bestehende Funktion wird der Lautstaerkeverlauf gesteuert. Der erste Parameter (A, ATTACK) gibt die Zeitspanne an, in der der Ton die hoechste Lautstaerke erreicht haben soll. Ist diese Zeitspanne vorueber, so wird der DECAY-Zyklus eingeleitet. Durch diesen zweiten Parameter wird die Zeitspanne festge- legt, in der der Ton auf die durch den Parameter SUSTAIN festgelegte Lautstaerke zurueckfaellt. Diese Lautstaerke wird nun solange gehalten, bis durch Loeschen einer bestimm- ten Flag RELEASE beginnt. Der RELEASE-Parameter gibt, aehn- lich wie bei DECAY auch, die Zeitspanne an, innerhalb der der Ton auf die Lautstaerke 0 zurueckgegangen sein soll.

Durch diese Funktion laesst sich der Klang der verschieden- sten Instrumente imitieren.

73

Graphisch laesst sich diese ADSR-Funktion wie folgt darstel- len:

ATTACK

Als Zeitspannen von ATTACK, DECAY und RELEASE stehen folgen- de Moeglichkeiten zur Auswahl:

Wert ATTACK-Spanne DECAY/RELEASE-Spanne

0 0.002 sec 0.006 sec l 0.008 sec 0.024 sec 2 0.016 sec 0.048 sec 3 0.024 sec 0.072 sec 4 0.038 sec 0.114 sec 5 0.056 sec 0.168 sec 6 0.068 sec 0.204 sec 7 0.08 sec 0.24 sec 8 0.1 sec 0.3 sec 9 0.25 sec 0.75 sec 10 0.500 sec 1.9 sec 11 0.800 sec 2.4 sec 12 1 sec 3 sec 13 3 sec 9 sec 14 5 sec 15 sec 15 8 sec 24 sec

Auch wenn fuer DECAY und RELEASE die gleiche Einteilung vor- handen ist, so lassen sich diese beiden Parameter natuerlich unterschiedlich waehlen. Jedoch beziehen sich auch diese An- gaben wieder auf eine Taktfrequenz von einem MHz. Sollte ei- ne genaue Angabe der wirklichen Zeitspanne erforderlich sein, so sind die obigen Werte mit dem faktor ...

l MHz / Systemtaktfrequenz zu multiplizieren.

Als eine weitere Moeglichkeit der Beeinflussung der einzel- nen Stimmen steht die Wellenform zur Verfuegung. An Wellen- formen stehen vier verschiedene zur Auswahl: die Dreieck- Wellenform, die Saegezahn-Wellenform, die Pulse-Wellenform sovie die ”"Wellenform" Rausch, die beispielsweise fuer Ex- plosionen, Wind und Schlagzeug genutzt werden kann.

Dreieck Saegezahn Pulse

ZINN ZN TR)

"Rausch" liefert ein Signal in Form eines Rauschens, dessen Frequenzen innerhalb eines bestimmten Bereichs liegen.

74

Die Wellenform "Pulse", auch Rechteckschwingung genannt, kann ausserdem noch durch die Pulsebreite variiert werden. Dieser Wert mit einer Breite von 12 Bits im Bereich von OD bis 4095 (die Randverte allerdings bewirken, dass kein Ton ausgegeben wird) gibt an, wie lange das Signal den Nullpegel annehmen soll. Ist also ein Wert von 2048 gewaehlt, so er- haelt man eine exakt regelmaessige Rechteckschwingung. Durch Aendern der. Pulsebreite (waehrend der Ton erklingt) koennen klangliche Veraenderungen (ein sogenanntes "Phasing") er- zeugt werden. Ist eine andere Wellenform als Rechteck ausge- waehlt, so hat die Angabe einer Pulsebreite keinerlei Aus- wirkungen auf die Tonerzeugung.

Jede Stimme besitzt sieben Steuerregister (von den insgesamt 29 Registern des SID) zur Kontrolle. Die ersten beiden Regi- ster eines der drei Bloecke (fuer jeden Oszillator) bestim- men die Frequenz der Stimme. Dabei handelt es sich um den unter "Frequenz" beschriebenen 16-Bit-Wert, der in der Rei- henfolge LSB/MSB in den beiden Registern abgelegt wird.

Die folgenden beiden Register sind fuer die Angabe der Pulsebreite verwendet. Da diese jedoch nur 12 Bits benoe- tigt, ist das MSN des zweiten Registers unbenutzt. Das erste enthaelt die Bits O bis 7, das LSN des zweiten Registers Bit 8 bis Bit 11.

Bei den Registern 4, 11 und 18 (je nach Tongenerator) han- delt es sich um die Steuerregister fuer den Ablauf der Huellkurve (darauf wird im folgenden noch eingegangen). Die Bits 4 bis 7 waehlen die Wellenform aus. Ist ein bestimmtes Bit gesetzt, so wird die entsprechende Wellenform fuer den Tongenerator verwendet. Auch ist es moeglich, mehrere Bits gleichzeitig zu setzen. Allerdings resultiert die dabei ent- stehende Wellenform aus einer "UND"-Verknuepfung der ausge- vwaehlten Wellenformen. Hier eine Aufstellung, welches Bit welche Wellenform auswaehlt (sofern gesetzt):

Bit 4: Triangle (Dreieck) Bit 5: Sawtooth (Saegezahn) Bit 6: Pulse (Rechteck)

Bit 7: Noise (Rauschen)

Durch das naechste Register (5, 12, 19) werden die Parameter ATTACK und DECAY festgelegt. Die Daten fuer ATTACK befinden sich im MSN, DECAY belegt das LSN. Der Wert kann also durch ...

POKE 54272 + T*7+5, A* 16 + D

PR abgespeichert werden, wobei 54272 die Basisadresse des SID ist, T der Tongenerator (von O bis 2) und A und D (je- veils von O bis 15) die Daten fuer ATTACK und DECAY enthal- ten.

Das letzte tongeneratorspezifische Register dient zur fest- legung des SUSTAIN-Levels und der Zeitspanne fuer RELEASE. Die Laustaerke fuer SUSTAIN befindet sich im MSN, die RELEASE-Zeitspanne muss im LSN festgelegt werden.

Alle diese Register koennen nur BESCHRIEBEN und NICHT ausge- lesen werden. Sollen also auf bereits festgelegten Parame- tern aufbauend andere Effekte erreicht werden, so muessen die Daten zusaetzlich im RAM abgelegt werden. Die Register befinden sich an den Adressen 54272 bis 54292.

75

Um nun einen Ton zu erzeugen, muss folgendermassen vorgegan- gen werden: Zuerst sollten die ADSR-Daten und die Frequenz (sowie, falls erforderlich, die Pulsebreite) abgespeichert werden. Ist dies erfolgt, so kann nun, gleichzeitig mit der Definition der Wellenform, der ADSR-Zyklus begonnen werden. Dies erfolgt durch Abspeichern eines Wertes in Register- adresse 54276, 54283 oder 54290 (tongeneratorabhaengig), in dem Bit O0 gesetzt ist. Bit 4 bis Bit 7 geben die Wellenform an. Ist der SUSTAIN-Level erreicht worden, so wird dieser so lange gehalten, wie das Bit O (GATE- oder KEY-Bit genamnt) gesetzt ist. Wird .es geloescht (die Bitkombonation fuer die Wellenform muss erhalten bleiben!), so wird RELEASE ausge- fuehrt. Ist der Nullevel erreicht worden, kann dem Register der Wert 0 zugewiesen werden. Wird das GATE-Bit geloescht, bevor DECAY abgeschlossen ist, so wird sofort RELEASE einge- leitet. Auch wird ATTACK begonnen, falls GATE gesetzt wird, unabhaengig davon, ob sich dieser Tongenerator vielleicht noch in der RELEASE-Phase befindet. Das GATE-Bit kann so zum Beispiel in Abhaengigkeit davon, ob eine bestimmte Taste ge- drueckt ist, gesetzt und geloescht werden, die Tastatur wuerde also zu einer Art Klaviatur umfunktioniert.

Um jedoch ein hoerbares Ergebnis zu erzielen, muss die Hauptlautstaerke festgesetzt werden. Diese kann in 16 Stufen von O0 (kein Ton) bis 15 (hoechste Lautstaerke) durch das LSN von Register 24 variiert werden.

Zurueck zum Kontrollregister, mit dem der ADSR-Zyklus ini- tialisiert und die Wellenform festgelegt wird: Bit 1 dient, falls gesetzt, zur Synchronisation der Grundfrequenzen ver- schiedener Oszillatoren. Dazu muss der Oszillator, nach dem synchronisiert wird, auf eine von null verschiedene Frequenz gesetzt werden, andere Register dieses Oszillators haben keinen Einfluss auf die synchronisierte Stimme.

Ein Setzen von Bit 2 bevirkt, falls die Dreieck-Wellenform des entsprechenden Generators gewaehlt ist, dass der 0szil- latorausgang dieser Stimme durch ein durch Ringmodulation (Summe und Differenz der beiden Grundstimmen) kombiniertes Signal dieses und eines zweiten Generators ersetzt wird. Auch hier muss der zweite Generator eine von null verschie- dene Frequenz haben um einen Unterschied zur normalen Ausga- be zu erzielen.

Bit 3 sperrt den entsprechenden Oszillator und fuehrt gleichzeitig einen RESET des entsprechenden Oszillators durch. Dies kann notwendig sein, wenn bei der Auswahl der Wellenformen NOISE mit einer weiteren Wellenform kombiniert wurde, da dann der Rauschgenerator blockieren kann.

FILTER

Register 21 und 22 bilden ein Register, das die fFilterfre- quenz bestimmt. Bit O0 bis 2 von Register 21 (Adresse 54293), Bit O bis 2 des 11 Bits breiten Werts, sowie alle Bits von Register 22 (Adresse 54294), Bit 3 bis 10 des Werts, bestim- men die Filterfrequenz. Diese errechnet sich durch ...

F= (30 + N * 5.81) Hz

Dabei ist N der 11-Bit-Wert und F die fFilterfrequenz in Hertz. Im Gegensatz zu anderen Werten ist dieser Wert unab- haengig von der Taktfrequenz. Als Filterarten stehen nun folgende Moeglichkeiten zur Auswahl: LOWPASS (alle Frequenz- komponenten des Signals UEBER der Filterfrequenz werden mit 12 dB je Oktave abgeschwaecht), HIGHPASS (entsprechend Lov-

76

pass, jedoch werden alle Frequenzkomponenten des Signals UNTER der Filterfrequenz mit 12 dB/Oktave abgeschwaecht) so- wie BANDPASS (alle Frequenzkomponenten UNGLEICH der Filter- frequenz werden um 6 dB/Oktave vermindert).

Die verschiedenen Ausgabesignale der Filter koennen durch gleichzeitiges Setzen der entsprechenden Bits additiv ver- knuepft werden. So kann durch Kombination von Lowpass und Highpass eine Bandsperre programmiert werden. Der Filter wird im allgemeinen dazu verwendet, um bestimmte Frequenzen eines Signals zu eliminieren.

Ausserdem kann die Filterresonanz durch einen Wert von O0 (keine Wirkung) bis 15 (hoechste Resonanz) im MSN von Regi- ster 23 festgelegt werden. Dies bewirkt eine besondere Beto- nung der Frequenzkomponenten der filterfrequenz woraus ein schrillerer Ton resultiert.

Vier verschiedene Stimmen koennen ueber den Filter laufen: jeder der Oszillatoren ] bis 3 sowie ein externes Signal. Dieses externe Signal wird durch den Eingang "AUDIO IN" (Pin 5) ueber die Audio/Video-Buchse zum SID geleitet. Soll eine dieser Stimmen durch den Filter modifiziert werden, so muss eines der Bits des LSN von Register 23 (Bits 0 bis 2 fuer Stimme 1 bis 3, Bit 3 fuer das externe Signal) gesetzt wver- den. Es ist moeglich, mehrere Stimmen gleichzeitig durch den Filter zu leiten.

TONGENERATOR 3

Stimme 3 (Register 14 bis 20, Adressen 54286 bis 54292) nimmt eine gesonderte Stellung innerhalb der drei Oszillato- ren ein. Hier kann der Verlauf der Huellkurve und der Zu- stand des Oszillators festgestellt werden.

Huellkurve: Die Huellkurve (Register 28) gibt die momentane Amplitude der ADSR-Funktion an. Ist die durch das LSN von Register 24 festgelegte Lautstaerke nach Initialisierung des ADSR-Zyklus' (Setzen des GATE-Bits) erreicht worden (nach der ATTACK-Phase), so enthaelt dieses Register den Wert 255, nach RELEASE den Wert OD. So kann zum Beispiel, falls SUSTAIN eine festgelegte Zeitspanne gehalten verden soll, nach Ab- lauf dieser Zeitspanne automatisch RELEASE eingeleitet wver- den. Dazu muss lediglich gewartet werden, bis nach dem Er- reichen des Werts 255 das Huellkurvenregister den von SUSTAIN abhaengigen Inhalt hat. Dann wird die gewuenschte Zeitspanne gewartet, und nach Beendigung der Warteschleife das GATE-Bit geloescht. Auch kann so erkannt werden, wann RELEASE beendet ist, um das Kontrollregister (Register 4, 1l, 18 sowie Adressen 54276, 54283, 54290) einer Stimme auf den Wert null zu setzen, um (sehr schwaches) Nachklingen zu vermeiden. Auch koennen durch dieses Register sehr winteres- sante Effekte erzielt werden, wenn in Abhaengigkeit vom Zu- stand der Huellkurve die Frequenz oder Pulsebreite geaendert wird. Auch durch Aendern der fFilterfrequenz sind viele wir- kungsvolle Effekte moeglich.

Oszillator: Dieses Register (#27, Adresse 54299) gibt den Zustand der acht hoechstvertigen Bits von Oszillator > an. Der Registerinhalt aendert sich je nach gewaehlter Wellen- form. Bei der Wellenform "Dreieck" nimmt der Inhalt des Registers gleichmaessig von OD bis 255 zu. Ist der Wert 255 erreicht worden, so wird dieser Wert nun wieder bis auf null vermindert, woraufhin wieder von vorne begonnen wird. "Sae- gezahn" laesst den Inhalt dieses Registers auch von 0 bis 255 ansteigen, faellt nach Erreichen dieses Werts jedoch so-

77

fort wieder auf null zurueck. Ein staendiger Wechsel von O0 auf 255 (und zurueck) wird bei "Pulse" ausgefuehrt. Die Laenge dieser beiden Phasen ist vom Pulsebreitenregister ab- haengig. Bei "Noise" koennen "zufaellige" Werte im Bereich von O0 bis 255 ausgelesen werden. Die Hauptanwendung dieses Register besteht, wie beim vorherigen Register auch, Echt- zeit-Effekte auszufuehren (was natuerlich im Normalfall nur von Maschinensprache aus moeglich ist), wobei die Parameter anderer Oszillatoren durch Werte, die durch Oszillator 3 er- zeugt wurden, geaendert werden.

Viele Effekte, die auf von Oszillator 3 errechneten Daten aufbauen, benoetigen diese Stimme jedoch ueberhaupt nicht. Daher ist es moeglich, Stimme 3 abzuschalten, ohne jedoch die internen Vorgaenge zu beeinflussen. Das Signal von Ton- generator 3 erscheint so also nicht am Audio-Ausgang des SID-Chips. Jedoch bleiben Synchronisation und Ringmodulation davon unbetroffen, da diese kombinierten Signale davon unab- haengig sind, ob Oszillator 3 ein- oder ausgeschaltet ist. Das Ausschalten von Stimme 3 erfolgt durch Setzen des MSB in Register 24 (Adresse 54296).

Die AD-Wandler

Der SID verfuegt ausserdem ueber zwei AD-Wandler (POTX und POTY, Adressen 54297 und 54298), die es ermoeglichen, Poten- tiometerzustaende zu erkennen. Die in den Registern befind- lichen Werte - sie werden alle 512 Taktzyklen auf den neue- sten Wert gebracht - koennen im Bereich von 0 (niedrigster Widerstand) bis 255 (hoechster Widerstand) liegen.

Beim Commodore 64 finden diese beiden Eingaenge des SID im Normalfall fuer die Paddles Verwendung, jedoch auch eine Verwendung als Temperaturfuehler oder Helligkeitsmesser wae- re nicht abwegig.

Registeruebersicht (die Basisadresse des SID ist 54272): Register 0: LSB der Frequenz des Oszillators von Stimme 1 Register 1: MSB der Frequenz des Oszillators von Stimme 1

Register 2: niederwertigsten acht Bits des Pulsebreitenre- gisters (Stimme 1) fuer die Erzeugung von Rechtecksignalen

Register 3: das LSN dieses Registers bildet die Bits 8 bis ll des Pulsebreitenregisters (Stimme 1), das MSN ist unbenutzt

Register 4: Kontrollregister fuer Stimme |] Bit DO: GATE, Stimme 1

wird dieses Bit gesetzt, so wird der durch die ADSR-Parameter gewaehlte Ab- lauf der Huellkurve begonnen. Innerhalb der durch ATTACK festgelegten Zeitspanne steigt die Lautstaerke bis auf den Maxi- malwert (durch LSN in Register 24 fest- gelegt), um dann die RELEASE-Phase zu beginnen, in der die Lautstaerke auf den durch SUSTAIN festgelegten Pegel zu- rueckfaellt. Dieser wird so lange gehal- ten, bis das GATE-Bit wieder rueckge- setzt wird. Im gleichen Augenblick be- ginnt SID RELEASE und laesst dadurch den Ton bis auf Nullpegel zurueckfallen.

78

Register

Register

Register

Register

Register

Register

Register

5:

6:

Bit 1: SYNC Eine Synchronisation von Stimme |] mit Stimme 3 erfolgt durch Setzen dieses Bits.

Bit 2: RING MOD Eine Ringmodulation von Stimme |] mit Stimme 3 erfolgt durch Setzen dieses Bits.

Bit 3: TEST

Wird dieses Bit gesetzt, so wird Stimme l gesperrt und gleichzeitig ein Reset des Oszillators durchgefuehrt, wodurch eine eventuelle (durch Kombination von "Rausch" mit einer weiteren Wellenform) Blockade des Rauschgenerators aufgehoben vird.

Bit 4: Auswahl der Dreieckswellenform (TRIANGLE), falls Bit gesetzt

Bit 5: Auswahl der Saegezahnwellenform (SAWTOOTH), falls Bit gesetzt

Bit 6: Auswahl der Wellenform PULSE, falls Bit gesetzt

Bit 7: Auswahl der "Wellenform" NDOISE, falls Bit gesetzt

ATTACK/DECAY

Bits 4 bis 7 (ATTACK) geben die Dauer (von 2 msec bis 8 sec) an, die SID benoetigt, bis die Maximallautstaerke vom Nullpegel aus erreicht werden soll.

Bits O0 bis 3 (DECAY) definieren die Zeitspanne (von 6 msec bis 24 sec), in der die Lautstaerke vom Maximalwert (nach ATTACK) auf SUSTAIN zu- rueekgeht.

SUSTAIN/RELEASE

Bits 4 bis 7 (SUSTAIN): Lautstaerkepegel, auf den bei DECAY zurueckgegangen wird. Dieser Level wird gehalten, bis GATE rueckgesetzt wird.

Bits 0O bis 3 (RELEASE): Zeitspanne, in der der Lautstaerkepegel von SUSTAIN wieder auf null zurueckgeht. Der Bereich erstreckt sich, wie bei DECAY auch, von 6 msec bis 24 sec.

Diese sieben Register haben die gleiche Funk- tion, wie die ersten sieben Register auch, je- doch fuer Stimme 2. Ringmodulation und Synchro- nisation erfolgen mit Stimme ].

Diese sieben Register haben die gleiche Funk- tion, wie die ersten sieben Register auch, je- doch fuer Stimme 3. Ringmodulation und Synchro- nisation erfolgen mit Stimme 2.

FILTER LO ; Die niedervwertigster drei Bits bilden Bit O bis Bit 2 der Filterfrequenz (fuer alle Tongenera- toren identisch). Vebrige Bits sind ungenutzt.

79

Register 22: FILTER HI Dieses Byte bildet zusammen mit Bits 0 bis 2 von Register 21 die Filterfrequenz. Diese gibt die Eck- beziehungsweise Zentralfrequenz des Filters an.

Register 23: das MSN gibt die Resonanz im Bereich von 0 bis 15 an. Dadurch werden die Frequenzkomponenten im Bereich der fFilterfrequenz besonders hervor- gehoben. Bit O0: leitet Stimme ] ueber den Filter (falls Bit gesetzt) Bit l: leitet Stimme 2 ueber den Filter (falls Bit gesetzt) Bit 2: leitet Stimme 3 ueber den Filter (falls Bit gesetzt) Bit 3: leitet externes Signal ueber den Filter

* (falls Bit gesetzt)

Register 24: LSN: globale Maximallautstaerke von 0 (ausge- schaltet) bis 15 (hoechste Lautstaerke) Bit 4: LOWPASS des Filters einschalten Bit 5: BANDPASS des Filters einschalten Bit 6: HIGHPASS des Filters einschalten (Kombination ist, wie beschrieben, moeglich)

Bit 7: schaltet Stimme 3 aus, falls Bit ge- setzt. Dadurch kann Stimme 3 zur reinen Daten- gewinnung durch Register 27 und 28 verwendet verden.

Auf all diese Register (#0 bis #24) kann NUR SCHREIBEND zu- gegriffen werden. Ein Auslesen ist nicht moeglich, da immer der Wert null ausgelesen wird.

Die folgenden vier Register dahingegen koennen nur - ausgele- sen werden, ein schreibender Zugriff hat keinerlei Ausvir- kungen:

Register 25: POTX, digitaler Wert des ersten A/D-Wandlers Register 26: POTY, digitaler Wert des zweiten A/D-Wandlers

Register 27: der Registerinhalt gibt den momentanen Zustand des Oszillators 3 an und dient meist zur Erzeu- gung von speziellen Effekten.

Register 28: hiermit kann der Verlauf der Huellkurve von Stimme 3 verfolgt werden. Je nach Zustand kann hier ein Wert im Bereich von 0 (niedrigste Lautstaerke) bis 255 (hoechste Lautstaerke) ausgelesen werden.

Um einen Ton der gleichschwebend temperierten Skala (zum Beispiel beim Klavier) zu erzeugen, hier noch ein kurzes Beispielprogramm:

100 B = 54272 : K = 77 * 2 $ 21.25 / 715909

110 IF PEEK (678) THEN K = 495 * 2 ? 20.25 / 2216809

120 POKE B + 5, O : POKE B + 6, 240 : POKE B + 24, 15

130 FOR I = 0 T0 94 : n = Int (2t (1 / 12) *K + .5)

140 H = INT (N / 256) : POKE-B, N - 256 * H : POKE B + 1, H 150 POKE B + 4, 17 : FOR J = 0 TO 99 : NEXT : POKEB +4, 0 160 NEXT : POKEB+4,0

Die Pinbelegung des SID (MOS 6581)

Pin

l

2:

13:

CAPAA, CAP1B: Anschluss fuer Kondensator, der durch den Filter benoetigt wird. Die Kapazitaet des angeschlossenen Kondensators betraegt beim Commodore 64 2200 pF

CAPZA, CAP2B: Kondensatoranschluss fuer Filter; siehe Pin 1 und 2

RES/, setzt SID in Grundzustand, alle internen Register werden auf null gesetzt

PH2, Systemtaktfrequenz fuer Buskontrolle

R/W, Schreib/Leseleitung des Prozessors

CS/, Chip-Select, steuert Zugriff auf Register des SID 6581

AO bis A4, Steuerleitungen zur Auswahl der Register des SID, die drei letzten Register sind unbenutzt und haben keine Bedeutung

GND, Masseleitung

DO bis D7, Datenbus zum Transfer von Daten vom und zum Prozessor

Analogeingaenge (POTY, POTX) fuer Paddles

VCC, Versorgungsspannung (+5 Volt)

EXT IN, Eingang fuer externes Audio-Signal, das durch den Filter des SID geleitet werden soll AUDIO OUT, Ausgang aller im SID erzeugten Signale sowie EXT IN

VDD, Versorgungsspannung (+12 Volt)

PIN CONFIGURATIOH CAFIR 1 u 28 „DE: CAPIE 2 ar AUGICG CUT CAPZA 2 ze EXT IHN CAPZE J 2s CC RE= Ss 4 FOT= PHE 12 ea POT Ru ae ee ee CT cs g us BSel oe ra 3 2 DS Ri a 1 1 1 l 1

1021 Ba DER Ba 1 EN a Bu u BZ 2 &

£ aM»

DD nz

[=

|

|

|

81

DER SERIELLE BUS DES COMMODORE 64

Der Commodore 64 verfuegt ueber einen seriellen Bus, an den mehrere Peripheriegeraete angeschlossen werden koennen. Die- ser uebertraegt, im Gegensatz zum IEEE-488-Bus der Geraete der CBM-Serie, die Daten seriell (aehnlich der RS-232- Schnittstelle) zwischen Computer und Peripheriegeraet. Die Bedienung des Ports von Maschinensprache aus erfolgt aber ueber Routinen, die von der Funktion her identisch mit denen der CBMs sind. Diese Routinen lassen sind in zwei Gruppen einteilen: Die erste Gruppe bedient die Peripheriegeraete ueber ein Filehandling. Es wird jedem Kanal eine fFilenummer zugeordnet (es koennen mehrere Files gleichzeitig geoeffnet - aber nicht aktiv - sein), ein Zugriff erfolgt dann unter Angabe einer Filenummer. Dieses Prinzip entspricht ziemlich genau den BASIC-Befehlen fuer das Arbeiten mit Files: OPEN, CLOSE, PRINT#, INPUT# und GET#. So ist es zum Beispiel durch Aendern der Geraetenummer auch moeglich, eine Ausgabe auf den Bildschirm anstelle einer Ausgabe auf den Drucker zu er- reichen.

Die zweite Gruppe von Routinen erfordert ein wesentlich sorgfaeltigeres Arbeiten, da man direkt ueber den seriellen Bus arbeitet. Daher koennen ueber diese Routinen (normaler- veise) auch nur Geraetenummern im Bereich von 4 bis 15 ver- wendet werden. Ein Programm, das ueber diese Routinen zum Beispiel auf die Diskettenstation zugreift, kann nicht (vie beim Arbeiten ueber logische Files) durch Aendern der Gerae- tenummer fuer Recorder umgeschrieben werden. Auch kann zu einem Zeitpunkt nur ein Kanal geoeffnet sein, durch den auf den seriellen Bus zugegriffen wird.

Hier nun die genaue Vorgehensweise, um einen Kanal fuer den seriellen Bus zu bedienen. Es werden die Kommandos mit den Bezeichnungen versehen, wie sie auch in der Sprungtabelle fuer die Systemroutinen (siehe dort) verwendet worden sind. Um ein Kommando auszufuehren, muss der entsprechende Eintrag in der Sprungtabelle durch "JSR" oder "JMP" aufgerufen wver- den.

Der erste Befehl dient zur Festlegung, ob das Geraet am se- riellen Bus Daten SENDEN oder EMPFANGEN soll. Entsprechend ist das erste Kommando entweder "TALK" oder "LISTEN", der Accu muss beim Aufruf einer dieser Routinen die Geraetenum- mer enthalten. Die naechste Routine dient zur Ausgabe der Sekundaeradresse, die im Normalfall der Festlegung des AT- beitsmodus' des Geraets dient. Je nachdem, ob die erste Rou- tine "TALK" oder "LISTEN" war, wird als zweite Routine "TKSA" oder "SECOND" verwendet. Der Accu enthaelt hier die Sekundaeradresse, die die Bits O0 bis 3 belegt. Die Bits 4 bis 7 dienen weiterhin der Festlegung, ob ein Kanal (inner- halb des Peripheriegeraets) geoeffnet, geschlossen oder auf einen geoeffneten Kanal zugegriffen werden soll. Beim Schliessen eines Kanals sind die Bits 5 bis 7 gesetzt, beim Zugriff auf einen geoeffneten Kanal sind die Bits 5 und 6 gesetzt, beim Eroeffnen eines Kanals sind alle Bits des MSN gesetzt. Die Ausgabe der Sekundaeradresse beendet automa- tisch den Kontrollmodus.

Die Ausgabe eines Filenamens kann nach der Neuanmeldung ei- nes Kanals erfolgen, ist jedoch nicht unbedingt erforder- lich. Jedes Byte des Filenamens wird dann ueber "CIOUT" (Zeichencode im Accu) zeichenveise ausgegeben. Ist die Aus- gabe beendet, so muss die Routine "UNLSN" aufgerufen werden, da die Uebertragung des Filenamens schliesslich abgeschlos- sen ist. Auf diesen Kanal kann nun unter Angabe der gleichen

82

Sekundaeradresse wieder zugegriffen werden, was besonders beim Arbeiten mit Diskette wichtig ist. Auch die Ausgabe ei- nes CLOSE-Kommandos auf ein Peripheriegeraets hat - wie das BOPEN-Kommando auch - ueber "LISTEN", "SECOND" und "UNLSN" zu erfolgen.

Wurde das Geraet durch gesetztes Bit 5 und Bit 6 in der Se- kundaeradresse angesprochen, so koennen nun durch "ACPTR" und "CIOUT" Daten empfangen und gesendet werden. Die Ueber- gabe der Parameter erfolgt jeweils ueber den Accu. Sind alle Daten uebertragen worden (beim Empfang durch die EOI-Kenn- zeichnung zu erkennen, jedoch nicht unbedingt bei Geraeten, die nicht von Commodore stammen), wird auch hier der Ab- schluss des Zugriffs durch "UNLSN" oder "UNTLK" (je nachdem) dem Peripheriegeraet mitgeteilt.

Als Beispiel soll hier das Einlesen des Disketteninhaltsver- zeichnisses dienen, das beim Commodore 64 normalerweise ueber 'LOAD "$", 8' und 'LIST' ausgegeben werden muss. Beim folgenden Beispielprogramm wird nun aber nicht mehr das Pro- gramm, dass sich im Arbeitsspeicher befindet, weberschrie- ben, da das Inhaltsverzeichnis bei Aufruf der Routine direkt ausgegeben wird. Zum besseren Verstaendnis sollte der Aufbau von BASIC-Programmen (Ablage im Arbeitsspeicher) bekannt sein.

LDA #0

STA STATUS ;Statusvariable 'ST' loeschen

LDA #8 sGeraetenummer fuer Diskettenstation

JSR LISTEN ; LISTEN auf Bus ausgeben

LDA #%11110000 ;sSekundaeradresse fuer OPEN Kanal OD

JSR SECOND sKanal in Diskettenstation eintragen

LDA #"$ ;sZeichen fuer Filenamen

JSR CIOUT ;Filenamen auf Bus ausgeben

JSR UNLSN sUNLISTEN auf Bus ausgeben

LDA #8 sGeraetenummer fuer Diskettenstation

JSR TALK ;TALK auf Bus ausgeben

LDA #%01100000 ;Zugriff auf Kanal O der Floppy

JSR TKSA ;Sekunaderadresse nach TALK ausgeben

LDX #5 ;‚Zaehlwert fuer Schleife

.BY 44 ;Code fuer BIT-Befehl START LDX #3 ;Zaehlwert fuer Schleife LOOP JSR GETBYT ;sZeichen holen, Status pruefen

DEX

BNE LOOP ;Schleife ausfuehren

TAX ;Filelaenge (LSB) in XR uebertragen

JSR 43735 ;sCRLF auf Bildschirm ausgeben

JSR GETBYT ;MSB der Anzahl an Bloecken holen

JSR 48589 ;Ausgabe der Anzahl an Bloecken LOOP2Z JSR GETBYT ;Zeichen holen, Status pruefen

TAX ;Statusflags setzen

BEQ START ;Nullcode? Zeilenende erkannt

JSR CHROUT ;Ausgabe Zeichen auf den Bildschirm

BNE LOOP2 ;Unbedingter Sprung GETBYT JSR ACPTR ;Zeichen von seriellem Bus holen

LDY STATUS ;Statusvariable 'ST' pruefen

BNE STOP ;Statusbit im Status gesetzt?

RTS ;Nein: Rueckkehr zum Hauptprogramm STOP PLA ;Ruecksprungadresse vom Stack holen

PLA

JSR UNTLK ;Zugriff auf Kanal beenden

LDA #8 sGeraetenummer fuer Diskettenstation

JSR LISTEN ;LISTEN auf Bus ausgeben

LDA #%11100000 ;Sekundaeradresse fuer CLOSE Kanal O0

JSR SECOND ;Kanaleintrag loeschen

JMP UNLSN ;sUNLISTEN auf Bus ausgeben

84

Soll dieses Programm ab der Adresse 828 abgelegt werden, so kann dies durch folgendes Programm geschehen (da das Pro- gramm dann im Bereich des Cassettenpuffers liegt, wird es natuerlich durch Recorderoperationen ueberschrieben):

100 FOR I = 828 TO 917 : READ A : POKE I, A : NEXT

110 DATA 169, , 133, 144, 169, 8, 32, 177, 255, 169, 240, 32 120 DATA 147, 255, 169, 36, 32, 168, 255, 32, 174, 255, 169 130 DATA 8, 32, 180, 255, 169, 96, 32, 150, 255, 162, 5, 44 140 DATA 162, 3, 32, 124, 3, 202, 208, 250, 170, 32, 215

150 DATA 170, 32, 124, 3, 32, 205, 189, 32, 124, 3, 170, 240 160 DATA 232, 32, 210, 255, 208, 245, 32, 165, 255, 164, 144 170 DATA 208, 1, 96, 104, 104, 32, 171, 255, 169, 8, 32, 177 180 DATA 255, 169, 224, 32, 147, 255, 76, 174, 255

Durch Anhaengen der Programmzeile ...

190 POKE 874, 202 : POKE 879, 221

kann das Programm auf dem WVIC-20 betrieben werden (siehe Adressumrechnung fuer VIC-20), da bei diesem das Arbeiten

mit dem seriellen Bus in der gleichen Weise erfolgt, wie bei Commodore 64 auch.

85

DATENTRANSFER UEBER DIE RS-232-SCHNITTSTELLE

Im Betriebssystem des Commodore 64 ist die Geraetenummer zwei der Bedienung der RS-232-Schnittstelle vorbehalten. Dies ist die Bezeichnung fuer einen Standard der seriellen Datenuebertragung und ist aehnlich der europaeischen V.24- Norm. Bei der seriellen Uebertragung wird nicht, wie dies zum Beispiel beim IEEE-488-Bus der Fall ist, ein Byte auf einmal, sondern Bit fuer Bit jede Informationseinheit ge- trennt uebergeben. Daraus resultiert natuerlich eine langsa- mere Vebertragungsrate als bei paralleler Uebertragung, da- fuer werden aber wesentlich weniger Datenleitungen benoe- tigt. Ein Anwendungsfall fuer eine serielle Uebertragung vaere zum Beispiel der Datenaustausch ueber Telefon.

Zu den bereits im Commodore 64 enthaltenen Routinen fuer die Bedienung der RS-232-Schnittstelle wird nur noch ein Steck- modul benoetigt, das auf den Userport gesteckt wird und die Schnittstelle selbst darstellt, die dann vom Betriebssystem bedient wird. Nun ist es Ihnen mit dem Commodore 64 zum Bei- spiel auch moeglich, Peripheriegeraete mit RS-232-Schnitt- stelle zu verwenden.

Wird beim Commodore 64 ein File mit der Geraetenummer zwei eroeffnet, so werden automatisch zwei Pufferbereiche (first in, first out) einer Laenge von je einer Page festgelegt, die fuer den Empfang und fuer das Senden von Daten verwendet werden. Dieser durch den OPEN-Befehl reservierte Bereich von 512 Bytes wird am Ende des BASIC-Arbeitsspeichers angelegt. Nach Anlegen des RS-232-Pufferbereichs wird zusaetzlich ein "CLR" durchgefuehrt, so dass das Oeffnen eines RS-232-Kanals zu Beginn eines Programms durchgefuehrt werden sollte. Es kann immer nur ein RS-232-Kanal auf einmal geoeffnet sein, da durch ein zweites OPEN mit der Geraetenummer zwei die Pointer in die Puffer zurueckgesetzt werden und so bereits empfangene Daten oder noch nicht gesendete Daten verloren gehen. Auch das Schliessen eines RS-232-Kanals, das auch gleichzeitig die 512 Bytes wieder freigibt, beinhaltet ein "CLR" 5

Achtung! Ist zum Zeitpunkt des Deffnens des RS-232-Kanals das Programm (ohne Variablen) so lang, dass keine 512 Bytes mehr frei sind, so wird wohl, ohne dass ein Fehler gemeldet werden wird, eine Zerstoerung des Programms die Folge sein.

Saemtliche BASIC-Befehle zur Filebehandlung koennen auch bei Benutzung der RS-232-Schnittstelle Verwendung finden. Das gleichzeitige Empfangen und Senden von Daten ist, sofern spezifiziert, moeglich. Ansonsten geschieht dies nacheinan- der.

Die Parameter zur Uebertragung werden durch den Filenamen (erstes Byte (Kontrollregister) und zweites Byte (Kommando- register)) festgelegt. Das dritte und vierte Byte werden nur dann benoetigt, falls eine durch den Benutzer festlegbare Vebertragungsrate spezifiziert werden soll. Wird kein File- name angegeben, so werden die Daten des letzten DPEN-Befehls verwendet.

Das Kontrollregister bestimmt die Uebertragungsrate (Baud- Rate), die Laenge eines Datenworts (fuenf bis acht Bits) und die Anzahl an Stoppbits, die nach der Vebertragung der Da- tenbits (vor der Uebertragung des Startbits fuer die negati- ve Flanke) gesendet werden.

Durch das Kommandoregister werden der Handshake-Modus und die Art der UVebertragung des Paritybits festgelegt. Ausser- dem wird angegeben, ob Vollduplex oder Halbduplex erwuenscht ist.

Die einzelnen Bits des Kontrollregisters sind folgenderma- ssen organisiert: Bit O bis Bis 3 geben die Baud-Rate an, Bit 5 und 6 bestimmen die Wortlaenge und Bit 7 ist fuer die Anzahl an Stoppbits zustaendig. Bit 4 ist unbenutzt. Im fol- genden eine Uebersicht:

Bit 3 21 0 dez Baud-Rate

0000 0 User Rate siehe Beschreibung 0007] l 50 Baud

0071 0 2 75 Baud

oo 171 3 110 Baud

0100 4 134.5 Baud

0 107]1 5 150 Baud

01210 6 300 Baud

7171 7 600 Baud

10 0 0 8 1200 Baud

100 \]1 9 1800 Baud

10710 10 2400 Baud

10.1 ]1 11 3600 Baud nicht implementiert 11000 12 4800 Baud nicht implementiert i: 2: 20:1 13 7200 Baud nicht implementiert 112100 14 9600 Baud nicht implementiert r. 4. 10 >41 15 19200 Baud nicht implementiert

Bit 6 5 dez Wortlaenge

0 0 0 8 Bits

0 1 32 7 Bits

1 0 64 6 Bits

1 1 96 5 Bits

Bit 7 dez Stoppbits

0 0 1 Stoppbit l 128 2 Stoppbits

Durch das Kommandoregister wird durch Bit 0 der Handshake- Modus festgelegt, Bit 4 legt die Art des Duplex fest und Bit 5 bis 7 sind fuer die Parity-Uebertragung notwendig. Die restlichen Bits (1, 2, 3) sind unbenutzt. Auch hier eine Uebersicht:

Bit OD dez Handshake

0 0 3-Line-Handshake l 1 X-Line-Handshake

Bit 4 dez Duplex

0 0 Vollduplex l 16 Halbduplex Bit 765 dez Parity-Uebertragung

0 0 weder Pruefung, noch Uebertragung 1 32 ungerade Parity

1 96 gerade Parity 1 l

.u.O0O -O-0 \

160 keine Pruefung, Vebertragung Bitvwert 1 224 keine Pruefung, Vebertragung Bitwert 0

87

Hierzu ein praktisches Beispiel:

Es soll ein RS-232-Kanal mit folgenden Parametern eroeffnet werden:

VUebertragungrate: 110 Baud

Wortlaenge: 8 Bits

Anzahl Stoppbits: 2 Stoppbits Handshake: 3-Line-Interface Duplex: Halbduplex Parity: Ungerade Parity

Das Eroeffnen koennte nun folgendermassen vorgenommen ver- den:

OPEN 1, 2, O0, CHR$(128+0+3) + CHR$(32+16+0)

Die weiteren zwei Zeichen werden nicht benoetigt, da keine eigene Uebertragungsgeschvwindigkeit spezifiziert wurde.

Werden Wortlaengen unter acht Bits verwendet, so enthalten unbenutzte Bits den Wert null.

Die Uebernahme von Zeichen sollte durch den GET#-Befehl er- folgen, da bei einem Fehler waehrend einer Uebernahme durch INPUT# (CTS- oder DSR-Missing) sich das System aufhaengt und nur durch RESTORE zurueckgeholt werden kann. Bei Empfang des Null-Zeichens CHR$(0) wird der Leerstring uebernomnmen.

Bei der Vebergabe eines Wagenruecklaufs an einen Drucker wird nicht gevartet, bis der Drucker wieder bereit ist, Da- ten zu empfangen (falls der Drucker keine interne Pufferung besitzt). Daher sollte, falls der Drucker diese Moeglichkeit besitzt, X-Line-Interface verwendet werden, da hier die zu uebergebenden Zeichen solange in einem Puffer zwischenge- speichert werden, bis der Drucker durch die CTS-Leitung vie- der angibt, empfangsbereit zu sein.

Beim Schliessen eines RS-232-Kanals wird jeglicher Daten- transfer abgebrochen und saemtliche Ausgaenge werden auf high gesetzt.

Wird der RS-232-Status gelesen, so wird dieser automatisch geloescht, so dass bei mehreren Abfragen der Wert der Sta- tusvariablen einer anderen Variablen uwebergeben werden muss. Der RS-232-Status wird nur dann gelesen, falls die letzte Datentransferoperation die RS-232-Schnittstelle betraf. Die Bits des Statusregisters haben bei der Verwendung des RS-232-Kanals folgende Bedeutungen:

Bit dez Bedeutung

1 Parityfehler 2 Framingfehler 4 Empfangspuffer ueberlaufen 8 Empfangspuffer leer (Zeichen ungueltig) 16 CTS (Clear To Send) Signal fehlt 32 unbenutzt 64 DSR (Data Set Ready) Signal fehlt 128 Abbruch erkannt

SOAVFUuUNMO

Ist Bit 2 gesetzt, so sollten mehr als 256 Zeichen im Emp- fangspuffer zwischengespeichert werden. Der Pufferzeiger wurde zurueckgesetzt. Die Zeichen sind verlorengegangen. Wird versucht ein Zeichen zu lesen, waehrend der Empfangs- puffer leer ist, so wird Bit 3 gesetzt.

88

Dıe Spezifizierung von eigenen Uebertragungsraten ist moeg- lich. Hierbei sollte jedoch beachtet werden, dass auf diese Weise nicht die vom Betriebssystem auferlegte obere Grenze von 2400 Baud ueberwunden werden kann, da durch die Taktfre- quenz hoehere Geschwindigkeiten nicht mehr verarbeitet ver- den koennen.

Zum besseren Verstaendnis bei der Errechnung eigener Baud- Raten sollte das Betriebssystemlisting im Bereich von 62499 bis 62540 herangezogen werden. Ausserdem wird die Kenntnis des Sprungvektors in Adresse 65409 (siehe Beschreibung der Systemroutinen) empfohlen.

Ein Programmanfang, der einen RS-232-Kanal mit den im Bei- spiel spezifizierten Parametern eroeffnet, aber stattdessen eine Vebertragungsrate von 200 Baud (Variable B) definiert, koennte folgendermassen aussehen:

100 F=14318180/14:IF PEEK(678) THEN F=17734472/18 110 B=200:T=INT(F/B/2-99.5):H=INT(T/256):1L=T-256*H 120 OPEN 1,2,0,CHR$(128+0+0)+CHR$( 32+16+0)+CHR$CL)+CHR$(H)

Allerdings sollte beachtet werden, dass dies keinerlei Stan- dards entspricht. Das obige Programmsegment kann jedoch dann vervendet werden, wenn Sender und Empfaenger auf die Baud- Raten eingerichtet sind.

Zum Abschluss noch eine Tabelle der beim RS-232-Handling verwendeten, RS-232-spezifischen Adressen in der Zeropage, Page 2 und im I/O-Bereich der NMI-CIA:

167 : Zwischenspeicher fuer empfangenes Bit

168 : Bitzaehler fuer den Empfang von Bytes

169 : Flag fuer Empfang des Startbits

170 : serielles Shift-Register fuer Empfang von Daten 171 : Register zur Errechnung der Parity beim Empfang 180 : Bitzaehler fuer die Ausgabe von Bytes

181 : naechstes zu sendendes Bit (Bit 2)

182 : serielles Shift-Register fuer Ausgabe von Daten 189 : Register zur Bestimmung der Parity bei der Ausgabe

247/248: Zeiger auf Beginn des Empfangspuffers; gueltig, falls Highbyte ungleich null

249/250: Zeiger auf Beginn des Sendepuffers; gqueltig, falls Highbyte ungleich null

659 : Kontrollregister (siehe Beschreibung) 660 : Kommandoregister (siehe Beschreibung) 661/662: Wert fuer Baud-Rate aus Tabelle 663 : RS-232-Statusbyte 664 : Wortlaenge (Berechnung bei OPEN) 665/666: Wert fuer Timer beim Senden 667 : Zeiger auf Ende des Empfangspuffers (letztes Zeichen + ]) 668 : Zeiger auf Zeichen im RS-232-Empfangspuffer (naechstes Zeichen bei GET) 669 : Zeiger auf zu uebertragendes Byte 670 : Zeiger auf naechste freie Stelle im Sendepuffer 673 : Flagregister fuer aktive NMIs (Datenuebertragung)

Bit 0 ist beim Senden von Daten gesetzt; Bit 1 und Bit 4 werden beim Empfang benoetigt, Bit 1 fuer Timeout-TimerB und Bit 4 fuer die Erkennung des Startbits beim Uebergang vom high des Stoppbits zum low des Startbits.

89

Verwendete Adressen der NMI-CIA:

56576 : Port A, siehe unten 56577 : Port B, siehe unten 56580/56581: TimerA, Baud-Rate fuer Ausgabe von Daten 56582/56583: TimerB, Baud-Rate fuer Empfang von Daten

56589 : ICR, Festsetzung der aktiven NMIs, Feststellung der NMI-Quelle

56590 : CRA, Festlegung des TimerA Arbeitsmodus'

56591 : CRB, Festlegung des TimerB Arbeitsmodus'

Belegung des User-Ports in Verbindung mit den CIA-Ports:

Pin 6526 Beschreibung Richtung

A - GND : Protective Ground -

B FLAG Sin : Received Data (fuer Startbit) IN C PBO Sin : Received Data, RS-232 IN IN D PBl RTS : Request To Send OUT E PB2 DTR : Data Terminal Ready DUT F PB3 RI : Ring Indicator IN H PB4 DCD : Data Carrier Detect IN J PB5 unbenutzt IN K PB6 CT5S : Clear To Send IN L PB7 DSR : Data Set Ready IN M PA2 Sout: Transmitted Data, RS-232 OUT DUT N - GND : Signal Ground _

DER 1/0 BAUSTEIN MOS 6526 (CIA) DES COMMODORE 64

Zwei 1/0-Bausteine des Typs 6526 besitzt der Commodore 64. Durch sie wird der Kontakt vom Computer zur Aussenwelt ge- schaffen. Die Tastaturabfrage, die Erkennung von Signalen auf Cassette, die Kommunikation ueber den seriellen Bus oder die RS-232-Schnittstelle, all dies und noch einiges mehr ist erst durch diese beiden Bausteine moeglich, deren Funktionen hier dargelegt werden sollen.

Zuerst eine allgemeine Beschreibung, die fuer beide CIAs (Complex Interface Adapter) gilt. Auf die Unterschiede zvi- schen den beiden Bausteinen, die nur in deren Verwendung beim Commodore 64 liegen, wird im Anschluss eingegangen.

Eine kurze Uebersicht: Dieser Baustein verfuegt ueber 16 einzeln programmierbare Portleitungen sovie ueber zugehoeri- ge Kontrolleitungen, die fuer Handshaking verwendet werden koennen, zwei kombinierbare 16-Bit-Timer und ein B-Bit- Shiftregister fuer serielle Datenuebertragungen. Ausserdem existiert eine interne 24-Stunden-Uhr mit programmierbarer Alarmzeit.

Die Steuerung all dieser Moeglichkeiten erfolgt ueber sech- zehn Register, die verschiedene Funktionen erfuellen. Vier dieser Register dienen der Programmierung der

PORTS DER CIA

Die CIA besitzt zwei Ports zu je einer Breite von acht Bits. Jede Portleitung der beiden Ports (Port A und Port B ge- nannt) kann unabhaengig als Eingang oder Ausgang geschaltet werden. Dies geschieht ueber die Datenrichtungsregister der CIA. Entsprechend den beiden Ports existieren zwei Daten- richtungsregister mit den Bezeichnungen "DDRA" und "DDRB" (Data Direction Register). Jedes Bit eines Datenrichtungsre- gisters gehoert entsprechend zu einem Bit eines der beiden Register, in denen dann der Zustand der Portleitung geaen- dert oder geprueft werden kann. Diese beiden Register hei- ssen "PRA" und "PRB" (Peripheral Data Register).

Um eine Portleitung als EINGANG zu kennzeichnen, muss das zugehoerige Bit im Datenrichtungsregister GELDOESCHT werden. Entsprechend ist das Bit im Datenrichtungsregister zu SET- ZEN, wenn die Portleitung als AUSGANG verwendet werden soll.

Die Datenrichtungsregister befinden sich an den Adressen 2 (DDRA) und 3 (DDRB) relativ zur Basisadresse des Bausteins. Die Ports nehmen die Adressen O (PRA) und 1 (PRB) ein. Die Nummern der Portleitungen (PAO bis PA7, PBO bis PB7) ent- sprechen den Nummern der Bits der zugehoerigen Steuerregi- ster. PB6 und PB7 werden auch