Grafikkurs: "Picasso und all die an-
dern..." (Teil 3)
----------------------------------------
Willkommen zum dritten Teil des Grafik-
kurses. Nachdem wir ja nun die Sprites
abgehandelt hätten, können wir uns die-
sen Monat nun endlich an die oft begehr-
te Programmierung der HIRES-Grafik ma-
chen. Auch dies ist ein relativ komple-
xes Thema, obwohl wir diesmal nicht all-
zu vielen in Registern "herumpoken" müs-
sen, als bei den Sprites. Das kompli-
zierte hierbei ist mal wieder der Aufbau
einer HIRES-Grafik, doch das sollte nun
auch kein Problem mehr für Sie sein.
Außerdem werden Sie auch noch ein
anständiges Stück vom Binärsystem benö-
tigen, beziehungsweise Sie sollten mitt-
lerweile vielleicht etwas geübter in der
Benutzung der logischen Operatoren von
BASIC sein, das hatten wir ja aber auch
schon, und somit kann ja nichts mehr
schief gehen...
Klären wir doch zunächst einmal, was
"HIRES" überhaupt bedeutet. HIRES ist
schlichtweg die Abkürzung für "HIgh RE-
Solution" und das heißt nichts anderes
als "hohe Auflösung". Sie haben also bei
einer HIRES-Grafik eine hohe Auflösung
zur Verfügung - genauer gesagt erstreckt
sich diese auf eine Ausdehnung von
320x200 Punkten, oder Pixels, wie man
sie auch oft nennt. Dieses Feld von
Punkten wird vom Bildschirmrand einge-
rahmt. Das heißt also, daß wir mit Hilfe
des HIRES-Modus des C64 jeden einzelnen
Punkt auf dem Bildschirm seperat ans-
teuern können.
Doch wie geht das nun vor sich? Zunächst
einmal sollte ich vielleicht erwähnen,
daß eine solche Grafik, wie die Sprites
auch, natürlich Speicherplatz benötigt.
Und das in verhältnismäßig gewaltigem
Maße! Wie Sie sich bestimmt denken
repräsentiert ein Grafikpunkt hier
natürlich auch ein Bit im Speicher des
64ers, das hatten wir ja bei den Sprites
ja auch scon, nun können Sie sich das ja
mal ausrechnen. Wir haben da
320*200=64000 Pixel, das ganze dividie-
ren wir durch 8, weil ja ein Byte 8 Bit
hat, und so kommen wir auf 8000 Bytes
pro Grafik! Das macht schon ein Achtel
des Gesamtspeichers des 64ers aus - Sie
sehen, die hohe Auflösung hat ihren
Preis.
Doch da gibt es noch ein riesengroßes
Problem für uns. Für die paar kleinen
Sprites aus den letzten beiden Kurstei-
len haben wir ja noch Speicherplatz ge-
funden, aber 8000 Bytes sind nicht mehr
so einfach dazischenzumogeln. Der ganze
Speicher des 64ers ist ja schon komplett
für andere spezifische Aufgaben reser-
viert. Woher also nehmen, wenn nicht
stehlen? Genau das werden wir jetzt aber
tun müssen! Wir werden uns etwas Spei-
cher von unserem 64er "klauen" müssen,
sonst is nix drin mit HIRES. Und das
geht folgendermaßen:
Das Betriebssystem hat ganz am Anfang
des Speichers eine ganze Menge Speicher-
stellen für sich reserviert, in dem es
sich einige Zwischenergebnisse und Hin-
tergrundinformationen "merkt". Dort be-
finden sich auch zwei kleine Speicher-
zellen, die ihm die Startadresse des
Basicspeichers angeben. In der Fachspra-
che nennt man so etwas "Pointer", oder
auch "Zeiger" (ähnlich wie die Sprite-
zeiger bei Sprites). Nomalerweise liegt-
der Basicspeicher, wie ich auch schon im
fünften Teil des Basickurses erwähnte,
ab Adresse 2048. Der Trick, den wir nun
anwenden werden, ist schlichtweg der,
daß wir dem Betriebssystem vorgaukeln,
der Basicspeicher beginne weiter hinten,
und schon können wir uns einen passenden
Speicherbereich für unsere Grafik reser-
vieren. Aber Vorsicht! Wie bei den Spri-
tes auch können wir uns da nicht jeden
X-beliebigen Speicherberech rausgreifen.
Hiresgrafiken dürfen nämlich grundsätz-
lich nur bei Speicherstellen beginnen,
die durch 8192 teilbar sind (bei Sprites
war der Teiler ja 64...). Demnach gibt
es also insgesamt 8 Bereiche, die in
Frage kämen, nämlich:
Nr. Von Bis
----------------
0 0 7999
1 8192 16191
2 16192 24191
3 24192 32191
4 32192 40191
5 40192 48191
6 48192 56191
7 56192 64191
Wir werden uns Bereich 1 wählen, aus 2
ganz bestimmten Gründen, die ich Ihnen
jetzt noch näher erklären möchte. Be-
reich 0 können wir ja vergessen, hier
sind ja wieder vorreserviete Funktionen
angelegt, die man tunlichst in Ruhe las-
sen sollte. Soviel hierzu. Jetzt zu den
Bereichen 2 bis 7. Diese sind ja eigent-
lich auch alle in reservierten Berei-
chen, aber es wäre auch hier denkbar
(über viele Tricks) sie "bebaubar" zu
machen. Das ist sogar sehr gut möglich
und wird auch von sehr vielen Programmen
eifrig praktiziert. Doch damit das ein-
facher geht, ist es meist sinnvoller das
Ganze in Assembler zu versuchen (zu die-
sem Zweck können Sie ja einmal in den
Assemblerkurs reinschauen, der seit Ja-
nuar parallel zu meinem hier läuft -
eine echte Gelegenheit für Basicprofis
noch tiefer in die Materie einzustei-
gen), und dann gibt es da auch noch ein
internes Problem, das mit dem VIC zu tun
hat, was jedoch zuviel wäre jetzt hier
erwähnt zu werden.
Bereich 1 ist einfach am Besten, da
pflegeleicht und für uns leicht erreich-
bar.
Also dann wollen wir einmal den Basic-
speicheranfang etwas höher setzen. Die
beiden Speicherstellen die ich eben
erwähnte belegen die Adressen 43 und 44.
Der 64er hat ja insgesamt 65535 Spei-
cherstellen, was der 16-Bit-Zahl
"1111111111111111" (16 mal "Bit ge-
setzt") entspricht. Um eine Adresse in-
nerhalb des Speichers für den Computer
darstellen zu können, brauchen wir also
immer 16 Bit, gleich 2 Byte. So auch bei
der Adresse des Basicanfangs (daher auch
2 Speicherstellen!). Die beiden Bytes,
die wir benötigen, teilen sich auf in
ein sogenanntes "niederwertiges-" oder
"LOW-Byte" und in ein "höherwertiges"
oder auch "HIGH-Byte". In Adresse 43 ist
nun das LOW- und in Adresse 44 das
HIGH-Byte des Basicanfangs gespeichert.
Lesen wir doch einfach einmal diese bei-
den Bytes aus, also:
PRINT PEEK(43),PEEK(44)
Auf dem Bildschirm sollten jetzt die
beiden Zahlen:
1 8
stehen. 1 wäre also dann der Wert des
LOW-Bytes und 8 der des HIGH-Bytes. Set-
zen wir uns also unsere 16-Bit-Zahl aus
diesen beiden Bytes zusammen. Das höher-
wertige Byte kommt beim Schreiben der
Binärzahl nach "oben" also nach links,
das niederwertige nach "untern" bezie-
hungsweise nach rechts:
--> 00001000 00000001
=8(HIGH) =1(LOW)
--> in dezimaler Schreibweise:
2↑11+2↑1=2049
Huch, das ist ja 2049 und nicht 2048, wo
ja eigentlich der Basicspeicher norma-
lerweise beginnen sollte! Doch keine
Angst, es stimmt schon so, denn das Be-
triebssystem möchte mämlich hier die
"wahre" Anfangsadresse des Basicspei-
chers plus 1 stehen haben. Das 0. Byte
dieses Bereichs wird noch zu einem ande-
ren Zweck benutzt, wie wir gleich noch
sehen werden. Möchten wir also bei-
spielsweise den Anfang des Basicspei-
chers nach Adresse 20000 verschieben, so
müßten wir hier die Adresse 20001 ange-
ben! Ok?
Zugegeben, das Prozedere, eine Adresse
zuerst einmal als Binärzahl zu schrei-
ben, um sie dann in zwei Bytewerte umzu-
rechnen ist relativ umständlich, deshalb
möchte ich Ihnen hier noch einen einfa-
cherern Weg zeigen, wie ein solcher 2-
Byte-Wert umgerechnet werden kann:
Das erste Bit des höherwertigen Bytes
hat ja in der 16-Bit-Schreibweise den
Dezimalwert 2↑8=256, da es ja das 8. Bit
der 16-Bit-Zahl ist (das Zweite 2↑9=512
etc.). Demnach wäre also die niedrigste
Zahl, die (ausschließlich) mit dem
HIGH-Byte dargestellt werden kann (das
LOW-Byte hat also den Wert 0) die Zahl
256. Demnach genügt es schlichtweg, die
absolute 8-Bit-Zahl des HIGH-Bytes mit
dem Wert 256 zu multiplizieren. Der Wert
des LOW-Bytes bleibt erhalten und wird
einfach zu dem 256fachen Wert des HIGH-
Bytes hinzuaddiert, also:
--> HI*256+LO=absolute Adresse
--> Oder in unserem Beispiel:
8*256+1=2048+1=2049
Genauso geht es auch umgekehrt. Um das
HIGH-Byte eines absoluten Wertes zu er-
mitteln dividieren wir diesen durch 256
und nehmen den ganzzahligen Anteil des
Ergebnisses als HIGH-Byte (also OHNE
Nachkommastellen, falls die Division
nicht aufgehen sollte). Das LOW-Byte
wird nun ermittelt, indem wir das HIGH-
Byte mit 256 multiplizieren und das Er-
gebnis von dem absoluten (Anfangs-)Wert
subtrahieren. Das hört sich vielleicht
komplizierter an als es ist, der Ein-
fachheit halber hier die Umrechnung als
kleines BASIC-Programm:
10 INPUT"Absoluter Wert (max. 65535)";WE
20 HI=INT(WE/256)
30 LO=WE-256*HI
40 PRINT "LOW-Byte : "LO
50 PRINT "HIGH-Byte: "HI
Starten Sie doch einmal dieses Programm
(auf der Vorderseite der MD unter dem
Namen "LO-HI-UMRECHNUNG") und geben Sie
einmal den Wert 2049 ein. Das Ergebnis
ist, wie erwartet, eine 1 für das LOW-
und eine 8 für das HIGH-Byte.
Doch nun wollen wir endlich einmal den
Speicher für unsere Grafik verschieben.
Wir hatten uns ja darauf geeinigt, daß
wir Bereich 1 hierfür beanspruchen wol-
len, der sich ja von 8192 bis 16191 er-
streckt. Lassen wir also den neuen Ba-
sicspeicher bei Adresse 16192 beginnen.
Sie sollten übrigens bedenken, daß bei
einer Verschiebung der Anfangsadresse
des Basicspeichers nach hinten, dieser
natürlich an Länge verliert! Vorher er-
streckte er sich ja von 2048 bis 40959,
und wir hatten somit 38911 "BASIC BYTES
FREE" (=40959-2048). Bei 16192 sind das
jetzt nur noch 24767 Bytes (=40959-
16192)! Deshalb sollten wir auch kein
Byte zuviel wegnehmen, wenn dies nicht
unbedingt erforderlich ist!
Bei 16192 soll nun also die neue Starta-
dresse liegen. Zuerst müssen noch eine 1
hinzuaddieren, bevor wir die Zahl in
HIGH- und LOW umrechnen können (Sie
erinnern sich - in 43/44 muß die gewoll-
te Adresse plus 1 stehen). Also:
16192+1=16193
HIGH=INT(16193/256)=63
LOW=16193-63*256=16193-16128=65
Das LOW-Byte hat also den Wert 65, das
HIGH-Byte den Wert 63. Nun noch schnell
etwas über das 0. Byte des Basicspei-
chers (bei uns das Byte mit der Adresse
16192). Dieses dient quasi als "Kennmar-
ke" für unseren 64er, daß hier der Ba-
sicspeicher beginnt und muß deshalb IM-
MER den Wert 0 enthalten, andernfalls
erkennt BASIC nicht mehr die Befehle
NEW, CLR und RUN als Basicbefehle an und
bricht mit einem "SYNTAX ERROR" ab! Des-
halb also immer auch eine 0 in das null-
te Byte des neuen Basicanfangs schrei-
ben, also:
POKE 16192,0 :REM 0.Byte
POKE 43,65 :REM LOW-Byte
POKE 44,63 :REM HIGH-Byte
Das wars. Der Basicanfang ist nun ver-
schoben, und der Bereich von 2048 bis
16191 geschützt, er kann von nun an also
nicht mehr von BASIC-Programmen über-
schrieben werden. Öbrigens kann es sein,
daß da hinten im Speicher noch irgenwo
Datenmüll rumsteht, der ja eigentlich
kein richtiges BASIC-Programm mehr
repräsentiert. Gibt man LIST ein, so
versucht der 64er doch noch was daraus
zu machen, was natürlich in einem riesi-
gen Chaos endet, deshalb sollten Sie auf
alle Fälle den Basicspeicher noch
zusätzlich initialisiern, indem Sie Ihn
mit NEW löschen, also:
NEW
Jetzt können Sie Ihr HIRES-Basic-
Programm schreiben. Achten Sie aller-
dings bitte darauf, daß Sie dieses unbe-
dingt mit einem ",8" abspeichern und vor
allem laden und nicht etwa mit ",8,1",
denn dann wird das Programm nämlich ab-
solut geladen. Wenn Sie es also abge-
speichert haben, als der Basicanfang
noch bei 2048 lag, dann wird es auch
dort hingeladen. Bei einem ",8" lädt der
C64 es jedoch an den aktuellen Basic-
speicheranfang, in unserem Fall also
16192!
Im Öbrigen können Sie sich möglicherwei-
se noch erinnern, daß ich bei den Spri-
tes erwähnte, daß es da auch noch andere
Möglichkeiten gibt, Speicherplatz für
Sprites zu schaffen. Genau das was wir
eben praktizierten meinte ich damit.
Verschieben Sie sich einfach den Basic-
speicher etwas nach vorne, um noch Platz
für Sprites zu bekommen. Wenn Sie auch
noch gleichzeitig eine Grafik benutzen,
dann haben Sie sowieso den Speicher von
2048 bis 8192 frei, genügend also, für
eine ganze Menge Sprites...
Welche Register des VIC Sie jetzt ans-
prechen müssen, um endlich mit dem Gra-
fikbildschirm arbeiten zu können, werde
ich Ihnen dann nächsten Monat erklären.
Bis dahin "Gut Hack" und Servus.
(ub)