Fahrt 001

weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

C64 StudioNeue IDE & Speicherorganisation

Wie angekündigt, habe ich das Projekt auf das C64 Studio umgestellt. Also bitte nicht erschrecken, die Sourcen sehen nun nur etwas anders aus. Die bisherigen ‚Bildschirme‚ liegen aktuell nur als Binärdateien vor.

 

Der Speicher
Wie bereits erwähnt, haben wir bisher kaum Gedanken an die Speicherorganisation verschwendet. Das kann sich, wie am Schluß von Landung 009 erklärt, ganz schnell rächen.

Wir sollten uns daher schon überlegen, wo unser Programm und die benötigten Daten liegen. Werfen wir dazu nochmal einen Blick auf den Speicher des C64, die Details sollten euch ja aus ‚Kleine Hardwarekunde‚ bekannt sein.

Speicher nach dem Einschalten
Speicher nach dem Einschalten

So sieht der Speicher des C64 bekanntlich direkt nach dem Einschalten aus (wir lassen hier Erweiterungen oder Umbauten außer Acht). Dies ist die Betrachtungsweise der CPU, sie kann alle Adressen von $0000 - $FFFF erreichen.

Allerdings müssen wir auch die Sichtweise des VIC mit einplanen. Dieser kann immer nur 16KB vom gesamten Speicher sehen, man kann diese sog. Bank aber frei wählen.

Die 16KB-VIC-Bänke
Übersicht, wo die 16KB-VIC-Bänke im Speicher liegen.

Innerhalb der gewählten Bank erwartet der VIC dann sämtliche Daten, auf die er direkt zugreift. Dazu gehören der Bildschirm- oder BITMAP-Speicher, der Zeichensatz und die Spritedaten (die Sprite-Pointer befinden sich immer am Ende des Bildschirmspeichers!). Das FARB-RAM kann, wie schon mehrfach erwähnt, nicht verschoben werden, ihr findet es immer von  $D800 - $DBFF.

Der VIC-II selbst sieht aber, außer dem Zeichen(Char)-ROM, nur das RAM. Auf das Zeichen-ROM greift er dabei nur an den in der folgenden Grafik zusehenden Stellen zu.

Speicher aus Sicht des VIC-II. In Bank 0 & 2 wird bei den angegebenen Adressen direkt aufs Char-ROM zugegriffen!
Der Speicher aus Sicht des VIC-II.
In Bank 0 & 2 wird, bei den angegebenen Adressen, direkt aufs Zeichen-ROM zugegriffen, auch wenn es sich physikalisch an der Adresse $D000 befindet!!!
Das RAM ist dort also tabu für unsere VIC-Daten!

 

Bevor ihr fortfahrt, solltet ihr euch (falls noch nicht geschehen) jetzt den Beitrag ‚VIC-II: Speicherbereiche festlegen‚ durchlesen, dort wird das alles ausführlicher erklärt.

 

Wie ihr an den Grafiken erkennen konntet, wird die Bank-0 nach dem Einschalten als Standard verwendet. Dort befindet sich ab der Adresse $0400 schließlich der von uns schon so oft verwendete Bildschirmspeicher. Daher ist für den VIC an der Adresse $1000 auch das CHAR-ROM sichtbar (wiederum Standard nach dem Einschalten).
Dies ist nun auch die Erklärung, warum das Hinzufügen eines weiteren Sprites oder neuer Code-Blöcke bei Landung 009 zu Problemen geführt hat. Schon ein neues Sprite hat dafür gesorgt, dass das Sprite für den letzten Abschnitt der Treibstoffanzeige ab $1000 begonnen hat. Da der VIC in Bank-0 und 2 dort (relativ zum Bankbeginn!) aufs CHAR-ROM zugreift, wird für dieses letzte Sprite dann der Beginn des Zeichensatzes gelesen und schon haben wir Murks auf dem Bildschirm.

Die Standard-Konfiguration scheint also nicht optimal zu sein, wollt ihr dort z. B. eine BITMAP-Grafik verwenden, dann benötigt die alleine 8KB. Die ersten 8KB von Bank 0 fallen dafür z. B. schon mal flach, dort sind die Zero-Page und der Stack. Also könnte nur der 2. Block verwendet werden. Dass bedeutet dann aber, dass unser Programm nur von $0800 - $1FFF gehen darf, sonst ragt es in den BITMAP-Speicher.

 

Unser Speicherlayout
Wenn wir uns den Speicher ansehen, dann ‘nerven‚ die ROMs am meisten. Als erstes sticht das BASIC-ROM ins Auge. Dies ist doch eigentlich überflüssig. Unser Programm ist in Assembler geschrieben und außer der Startzeile verwenden wir keine BASIC-Funktionen mehr. Daher können wir beim Programmstart das BASIC-ROM abschalten und uns somit einen durchgängigen Speicherbereich von  $0800 - $CFFF (also 49KB) verschaffen.
Den E/A-Bereich benötigen wir aber, sonst können wir weder VIC noch SID ansteuern. Das Kernal könnten wir zwar abschalten, aber evtl. wollen wir später auf die System-Routinen für die Floppy zugreifen, daher lassen wir es eingeschaltet.
Der Speicher unter den ROMs ist aber nicht verloren!

Der VIC-II weiß nichts vom E/A Bereich und Kernal, also können wir dort durchaus Daten ablegen. Solange wir mit der CPU dort nur schreiben wollen, ist alles gut. Dort lassen sich z. B. der Zeichensatz und die Spritedaten ablegen. Also verwenden wir Bank-3 von $C000 - $FFFF für den VIC. Da wir mit der CPU auf den Bildschirmspeicher lesend und schreibend zugreifen möchten, sollten wir den der Einfachheit halber in einem RAM-Bereich ablegen, der nicht vom ROM überlagert wird. Es trifft sich daher gut, das die ersten 4KB ab $C000 noch RAM sind. Weil für den Bildschirm nur 1KB benötigt wird, werden wir den nach $CC00 legen. Somit bleiben uns immer noch 48KB fürs Programm und nach dem Bildschirmspeicher kommt direkt das ROM.
Einen kompletten Zeichensatz (256 Zeichen) packen wir nach $F800 direkt ans Ende des Speichers. Damit bleiben uns von $D000 - $F7FF 10KB, die für 160 Sprites Platz bieten. Dies sollte doch erstmal reichen, oder? 😉

Hier nochmal die Übersicht wo sich, was innerhalb einer VIC-Bank ablegen läßt:

Blöcke innerhalb einer VIC-Bank.
Blöcke innerhalb einer VIC-Bank.

In der Grafik sind alles relative Adressen. Der Beginn der VIC-Bank errechnet sich einfach aus der Bank-Nr. (Zählung beginnt mit 0!) * $4000 (16KB). Auf diese Adresse wird dann der Beginn des gewählten Blocks (BITMAP, CHAR oder Bildschirm) addiert.

Schauen wir uns das mal für unser Speicherlayout an:
VIC-Bank = 3, also beginnt Bank die ab 3 * $4000 = $C000
BS = 3 | ab $C000 (VIC-Bank s. o.) + 3 * $0400 ($0C00) = $CC00
CHAR = 7 | ab $C000 (VIC-Bank s. o.) + 7 * $0800 ($3800) = $F800

 

Hier abschließend unser Speicherlayout als Grafik:

Unser Speicherlayout in der Übersicht
Unser Speicherlayout in der Übersicht

Da wir den Bildschirmspeicher verschoben haben, wird der Bereich von $0400 - $07FF ja nicht mehr gebraucht. Wir merken uns diesen als temporären Zwischenspeicher vor. Wer jetzt auf die Idee kommt, dass Programm direkt bei $0400 beginnen zu lassen, der bedenke, dass wir den Bildschirmspeicher ja erst nach dem Programmstart verschieben und eine Ausgabe wie z. B. das READY. nach dem Laden unser Programm zerstören würde.

 

Zum Abschluß wollen wir natürlich noch ein kleines Programm schreiben, das unseren Speicher wie geplant einrichtet.

Da dies unser erstes Programm mit dem C64 Studio ist, gehen ich an dieser Stelle auf den Source nochmal etwas genauer ein. Werft aber unbedingt einen Blick in die Hilfe und auf den schon mehrfach erwähnten Beitrag ‚Vom CBM prg Studio zum C64 Studio‚.
Startet nun das C64 Studio und öffnet 

Dort findet ihr bereits ein leeres Sourcefile rover.asm.

Das konvertierte LOVE-Projekt im C64 Studio 3.4
Das konvertierte LOVE-Projekt im C64 Studio 3.4

 

Fangen wir mit einer uns bisher unbekannten Zeile an:

Dem Assembler des C64-Studios müssen wir mitteilen, wie das fertige Programm gespeichert werden soll. Dazu wird das Macro !to, gefolgt vom Dateinamen verwendet. Als letztes wird hinter dem Komma das Format angegeben. Wir speichern im Commodore Business Machines-Format, d. h. die Datei rover.prg beginnt mit zwei BYTES, die die Ladeadresse des Programmes (LSB / MSB) enthalten.
Ihr erinnert euch: Ladet ihr ein Programm mit LOAD "<Dateiname>",8,1, dann speichert das System dieses Programm an der in den ersten beiden BYTES angegebene Adresse.

Als nächstes wollen wir die Systemkonstanten einbinden, dies geschieht über:

 

Jetzt legen wir uns eine Reihe von Konstanten an, über die wir unsere Speicherverwaltung ganz einfach vornehmen können.

In diese vier Konstanten tragt ihr die oben zufindenen Nummern des jeweiligen Speicherbereichs ein. Wir wollen den letzten 16KB-Block für den VIC verwenden, also setzen wir VICBANKNO auf 3. Um den Bildschirm nach $CC00 zu legen, setzen wir VICSCREENBLOCKNO natürlich auf drei. Der Zeichensatz soll sich bekanntlich am Ende des Speichers einfinden, daher setzen wir VICCHARSETBLOCKNO auf 7, um die letzte 2-KB-Bank innerhalb des 16-KB-Blocks auszuwählen. Eine Bitmap-Grafik planen wir nicht, daher belassen wir VICBITMAPBBLOCKNO einfach auf Null.

 

Jetzt lassen wir den Assembler die dazugehörigen Speicheradressen berechnen. Dank der erweiterten Möglichkeiten des Assemblers vom C64 Studio läßt sich dies recht einfach bewerkstelligen.

Um die Basisadresse für den VIC zu ermitteln, rechnen wir einfach VICBANKNO*16384. Die eben berechnete VICBASEADR ist nun der Ausgangspunkt, für die weiteren Adressen. Wir wählen für den Bildschirm, Zeichensatz und die Bitmap ja immer nur eine Bank innerhalb des 16KB-Blocks aus! Die Berechnung der drei weiteren Adressen VICSCREENADR, VICCHARSETADR und VICBITMAPADR sollte somit ganz einfach sein.

Da sich das Farb-RAM nicht verschieben läßt und somit immer an der Adresse $D800 zufinden, ist legen wir dafür direkt eine feste Konstante an.

 

Abschließend wollen wir noch die Startadresse für die Spritepointer ermitteln. Die Spritepointer befinden sich ja immer am Ende des Bildschirmspeichers, somit können wir einfach

rechnen.
Zur Startadresse des Bildschirmspeichers VICSCREENADR addieren wir einfach 1KB für die Größe der Bank und ziehen dann wieder 8 (wir haben max. 8 Sprites) ab.

Das soll uns erstmal an Konstanten reichen, nun folgt die bekannte Angabe der Startadresse für unser Programm.

 

Die BASIC-Startzeile können wir mit den erweiterten mathematischen Möglichkeiten des C64 Studios auch etwas umformulieren:

Hier berechnen wir mit Ausnahme der BASIC-Zeilen-Nr. 2014 $DE, $07, des SYS-Befehls $9E und des Leerzeichens alle anderen Werte. Wichtig ist, dass die Adress-Operatoren  < und  > eine höhere Priorität haben, als + - * /. Daher müssen wir evtl. auf Klammern zurückgreifen, um das gewünschte Ergebnis zu erhalten. Die Basis für alle Berechnungen bildet das Label main. Die Adresse für den Beginn des nächsten BASIC-Befehls (hier die letzten beiden $00, $00), können wir somit einfach über  <(main-2), >(main-2) ausrechnen. Da wir von der  main-Adresse erst zwei abziehen möchten, um dann das LSB und MSB zu ermitteln, müssen wir hier, wie eben erwähnt, Klammern verwenden.
Die Speicheradresse für den SYS-Befehl müssen wir ja als Text hinterlegen (bisher haben wir einfach fest "2062" geschrieben), um dies zu bewerkstelligen Teilen wir die Adresse von main absteigend durch 10000, 1000, 100, 10 und 1 und bilden jeweils den Modulo von 10 um den Rest (besser die benötigte Ziffer) zu ermitteln. Abschließend addieren wir den PETSCII-Wert für die '0' zum Rest und erhalten so den Text für gewünschten Zahlen von ‚0‚ bis ‚9‚.

 

Somit bekommen wir folgende BASIC-Zeile:

Die BASIC-Startzeile
Die BASIC-Startzeile

Wer sich an der führenden Null stört kann das Teilen durch 10000 natürlich löschen oder es über eine bedingte Assemblierung steuern, aber so ist die Zeile jetzt allgemeingültig und ihr könnt den Einsprung für eure Programme an eine beliebige Stelle verschieben. Schreibt vor das main zum Test z. B. einmal *=$4000 und startet das Programm, es wird weiterhin korrekt starten.

Durch diese Startzeile und die Konstanten haben wir nun eine schön flexible Ausgangsbasis, für zukünftige Projekte.

Jetzt wollen wir noch unseren Speicher einrichten. Dazu müssen wir zunächst dem VIC die von uns gewünschte 16KB-Bank zuweisen. Dies geschieht über das Register-0 (Datenport-A) des CIA-2, das wir an der Adresse $DD00 finden.

Wir sperren die Interrupts, legen die CIA2 ‚Datenrichtung‚ fest, holen uns dann den aktuellen Wert des Datenport_A in den Akku, maskieren die unteren beiden BITs aus und schreiben die von uns gewählte Bank-Nr. hinein. Dabei müssen wir beachten, dass die Auswahl invertiert stattfindet. Wir können dazu einfach  (3-VICBANKNO) rechnen und speichern den Wert anschließend wieder im Register-0. Somit weiß der VIC auf welche 16KB er zugreifen soll.

Jetzt müssen wir dem VIC noch zeigen, wo er den Bildschirm, Zeichensatz usw. finden kann. Dies geschieht über  VICMEMORYCONTROL, das Speicherkontroll-Register (Nr. 24) des VIC-II, dass an der Adresse $D018 liegt (s. ‚VIC-II: Die Register‚).

Um die richtigen BITs zu setzen, müssen wir die  VICSCREENBLOCKNO mit 16 multiplizieren und dazu die  VICCHARSETBLOCKNO addieren, nachdem wir diese verdoppelt haben. Auch diese Zeile wäre im CBM prg Studio nicht möglich, da dort bekanntlich nur ein Operator je Zeile erlaubt ist.

Abschließend werden die IRQs wieder freigegeben und das Programm bleibt in einer Endlosschleife ‚hängen‚.

Nach einem Start sieht der Bildschirm zwar noch merkwürdig aus, aber dies ist ja nur der Anfang!

Nach der Speicherorganisation.
Nach der Speicherorganisation.

Die obige Darstellung kann bei euch abweichen (vgl. Java-Emulator).

 

Da das Programm noch so schnuckelig klein ist, hier nochmal das komplette Listing:

Diese Fassung könnt ihr auch im Java-Emulator starten bzw. euch den Source inkl. .d64-Image herunterladen.


Dies war also der Auftakt, zum 3. Level. Ich hoffe ihr kommt mit dem C64 Studio klar und erkennt den Vorteil der, im Vergleich zum CBM prg Studio, erweiterten mathematischen Möglichkeiten.

Da ich an eurer Meinung sehr interessiert bin, nehmt doch bitte an der Umfrage zur Entwicklungsumgebung teil (die Umfragen wechseln sich auf der rechten Seite ab) oder noch besser hinterlasst einen entsprechenden Kommentar (das ist nun auch ohne Anmeldung möglich), wer es anonym mag kann natürlich auch das Feedback links verwenden.

17.10.14 – Der Fehlerteufel hat zugeschlagen:
Im Source-Teil wurde der Bildschirmspeicher fälschlich nach $C000, statt wie zu Beginn beschrieben $CC00, gelegt! Danke an Seb.
Da dies keine funktionelle Auswirkung hat, habe ich zwar die Beschreibung angepasst, aber die ZIP-Archive unverändert gelassen. Ab Fahrt 006 sind dann auch die ZIPs geändert.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (7 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


 

<<< zurück | weiter >>>

 

weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

8 Gedanken zu „Fahrt 001“

  1. Hello,
    Im CBM prg Studio, wenn ich versuche über “
    *=$3800
    incbin“chars.raw“ mein Zeichensatz in der Bank 0 zu importieren, funktioniert es einwandfrei.
    Wenn ich aber versuche den selben Zeichensatz bei $F800 in der Bank 3 abzulegen, über “
    *=$F800
    incbin“chars.raw“, für das zu einem schwarzen Bildschirm in VICE, ganz unabhängig vom Inhalt vom Programm. Ist das eine Limitation vom CBM prg Studio?
    Danke

    1. Das hat nichts mit dem CBM prg Studio zu tun!

      Du musst mit der Vergabe neuer Adressen vorsichtig sein.

      Die erste Adresse, die du im Source angibst, bestimmt bekanntlich wohin das Programm geladen werden soll. Setzt du danach noch weitere Adressen, dann wird der Zwischenraum mit $00 gefüllt. So einfach kannst du keine ‚gestückelten‘ Programme erzeugen.
      Schau dir mal dein assembliertes Programm an. Falls es bei $0801 beginnt und du *=$F800 verwendest, wird es wohl über 60KB groß sein.
      Daher überschreibst du dir beim Laden alle Register, die ab $D000 zufinden sind, mit $00.

      1. Vielen Dank für die Info. Da habe ich wieder viel dazugelernt. In der Tat wird zwischen den Adressen alles auf 0 gesetzt. Das wusste ich gar nicht.
        Jeden Tag ein bisschen schlauer. 🙂

  2. Hallo,
    In der ersten Hälfte wird erklärt, dass wir den BS in den vierten Block setzen werden, also ab $CC00, damit wir davor durchgehend 50KB zur Verfügung haben. Danach wird aber der Bildschirmram ab $C000 platziert.
    Danke

  3. Da sich der Adressraum für CPU und VIC unterschiedlich darstellt, halte ich die zweite Grafik für problematisch. Mach lieber ein separates Schaubild für den Speicher aus Sicht des VIC, anstatt beide Sichtweisen gleichzeitig abbilden zu wollen. Da aus VIC-Sicht der Zeichensatz fest bei $1000 und $9000 liegt (und sich ja auch nicht ausblenden lässt), wäre eine entsprechende Darstellung informativer als die kombinierte, denn das BASIC-ROM, der Kernal und der I/O-Bereich existieren aus VIC-Sicht überhaupt nicht.
    Ansonsten eine didaktisch sehr gut gemacht Seite; weiter so!

    1. Eigentlich sollte das Bild nur zeigen, wo der gewählte Bereich liegt und nicht was der VIC-II dort sieht.

      Aber ich denke du hast recht, eine ergänzende Grafik, inkl. entsprechender Bemerkungen, wäre hilfreich. Die werde ich in Kürze hinzufügen.

      Danke für den Hinweis und das Lob.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Protected by WP Anti Spam