Den Zeichensatz verändern
Eine herausragende Eigenschaft des C64 ist es, dass ihr sehr einfach eure eigenen Zeichensätze verwenden könnt. Was sich auf den ersten Blick relativ unspektakulär anhört, entpuppt sich als eine der wichtigsten Funktionen für Spiele und Demos.
Als erstes solltet ihr euch mit dem Speichermanagment des VIC unter VIC-II: Speicherbereiche festlegen vertraut machen, falls ihr es noch nicht getan habt.
Auch ein Blick auf die Beiträge Char-ROM und evtl. PETSCII, sollte zur Vorbereitung gehören.
Zwischen den beiden Standardzeichensätzen umschalten
Wir betrachten hier den Standardzeichensatz-Modus, der ist allen, die schon mal einen C64 eingeschaltet haben, bereits begegnet. Direkt nach dem Einschalten bietet der C64 zwei verschiedene Zeichensätze, die sich im ROM befinden:
- Zeichensatz: Großbuchstaben und viele grafische Symbole, dieser wird automatisch verwendet
- Zeichensatz: Groß- und Kleinbuchstaben, dafür weniger Symbole! Dieser muss extra aktiviert werden.
Zwischen den beiden Zeichensätzen könnt ihr mit folgenden Aktionen wechseln:
- Tasten: Gleichzeitig die Tasten C= und Shift drücken, um zwischen den Layouts zu wechseln.
- BASIC: PRINT CHR$(141) für den 1. Zeichensatz (Großbuchstaben und viele Symbole) bzw. PRINT CHR$(142) für den 2. Zeichensatz (Groß- und Kleinbuchstaben)
- Assembler: Wer bei VIC-II: Speicherbereiche festlegen aufgepasst hat, der wird bereits wissen, wie man unter Assembler zwischen den beiden Zeichensätzen umschaltet. Im Register 24
$d018 des VIC (s. VIC-II: Die Register) wird der Beginn des Zeichensatzes festgelegt. Daher müssen wir nun einfach den Beginn des gewünschten Zeichensatzes dort hineinschreiben.
Da hier der Zustand nach dem Einschalten vorausgesetzt wird, können wir einfach
lda #$15 für den ersten bzw. lda #$17 für den zweiten Zeichensatz in den Akku laden und dies dann mit sta $d018 ins Register schreiben.
Dies könnten wir natürlich auch unter BASIC mit POKE 53272,21 und POKE 53272,23 erreichen.
Vorbereitungen
Nun können wir schon zwischen zwei Zeichensätzen umschalten, aber wir wollen ja einen eigenen verwenden. Dazu gibt es nun zwei Möglichkeiten, wir können komplett einen eigenen Zeichensatz entwerfen oder wir kopieren den vorhandenen und verändern ihn nach unseren Wünschen. Da wir im Laufe des Tutorials Ein C64 Spiel in Assembler programmieren ab Level 3 – Die Fahrt zur Basis einen eigenen Zeichensatz entwickeln, verwenden wir hier das Kopieren.
Als Erstes sollten wir einen freien Speicherbereich suchen, wo wir unseren Zeichensatz ablegen. Wir lassen den VIC weiterhin auf die erste Bank zugreifen, so wie es nach dem Einschalten standard ist.
Als Speicherort für unseren Zeichensatz scheidet die Zero-Page natürlich aus. Auch die Adressen von
$1000 bis
$1fff sind tabu, wir befinden uns schließlich in der VIC-Bank 0! Dort greift der VIC (wie auch in Bank 2) immer direkt auf das ROM zu (s. VIC-II: Speicherbereiche festlegen) und würde somit nie unseren kopierten Zeichsatz lesen.
Für unseren Test schlage ich daher das Ende des ersten 16KB-Blocks vor. Lasst uns den Zeichensatz in den letzten 2KB-Block (Nr. 7), also von
$3800-$3fff, legen. Dort landen wir zwar im BASIC-Speicher, aber das ist für unseren Test nicht schlimm!
Zeichenspeicher festlegen
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
;*** VIC-II Speicher-Konstanten VICBANKNO = 0 ;Nr. (0 - 3) der 16KB Bank | Standard: 0 VICSCREENBLOCKNO = 1 ;Nr. (0 -15) des 1KB-Blocks für den Textbildschirm | Standard: 1 VICCHARSETBLOCKNO = 7 ;Nr. (0 - 7) des 2KB-Blocks für den Zeichensatz | Standard: 2 VICBITMAPBBLOCKNO = 0 ;Nr. (0 - 1) des 8KB-Blocks für die BITMAP-Grafik | Standard: 0 VICBASEADR = VICBANKNO*16384 ;Startadresse der gewählten VIC-Bank | Standard: $0000 VICCHARSETADR = VICCHARSETBLOCKNO*2048 ;Adresse des Zeichensatzes | Standard: $1000 ($d000) VICCHARSETADR = VICCHARSETADR+VICBASEADR ;*** Startadresse *=$0801 ;** BASIC-Zeile: 2018 SYS 2062 !word main-2, 2018 !byte $9e !text " 2062" !byte $00,$00,$00 main ;*** Start des Zeichensatzes festlegen lda #VICSCREENBLOCKNO*16+VICCHARSETBLOCKNO*2 sta $d018 ;Adresse für Bildschirm und Zeichensatz festlegen rts ;zurück zum BASIC |
Wir legen hier die Bank-/Block-Nr. fest und berechnen daraus die benötigten Adressen. Auf die Ausführungsgeschwindigkeit hat dies natürlich keinen Einfluss, da diese Berechnungen der Assembler bei der Programmerstellung vornimmt.
Das Programm macht erstmal nichts weiter, als dem VIC-II mitzuteilen, dass der Zeichensatz jetzt ab der Speicherstelle
$3800 zufinden ist.
Das erste Ergebnis sieht auch dementsprechend unbefriedigend aus:

Dass der C64 nicht abgestürzt ist, erkennt ihr z. B. daran, dass ihr immer noch blind BASIC-Befehle (wie POKE 53280,0) benutzen könnt.
Den Zeichensatz kopieren
Jetzt ist es an der Zeit, dass wir die Zeichen aus dem ROM, an unsere gewählte Adresse kopieren. Das erste Hindernis ist die Frage, wie sind die Zeichen überhaupt gespeichert?
Da wir uns im Standardzeichensatz-Modus (s. o.) befinden, hat jedes Zeichen eine Breite von 8 Pixeln und ist dabei 8 Zeilen hoch.

Somit kommen wir also auf 8 Bytes je Zeichen. Da ein kompletter Zeichsatz aus 256 Zeichen besteht, benötigt dieser also 256 * 8 Bytes = 2048 Bytes = 2KB. Das erklärt dann wieder, warum der Speicher für den Zeichsatz in 2KB-Schritten gewählt werden kann. Im Speicher (ROM) findet ihr alle Zeilen eines Zeichens direkt hintereinander, also die orangen Zeilen 0 – 7 aus dem obigen Bild.
Als zweites fragt sich der eine oder andere, wie wir nun überhaupt an die Zeichen kommen? Wie bereits geschrieben, finden wir an der Adresse $1000 keines Wegs die Zeichen, nur der VIC sieht diese in der VIC-Bank-0 an der Adresse. Tatsächlich befindet sich das Char-ROM an der Speicherstelle $d000.
Moment mal, dort befinden sich doch auch die VIC-Register!?!
Hier haben wir die, in Kleine Hardwarekunde beschriebene, dreifache Benutzung eines Speicherbereichs. Wir haben dort RAM, die Register vom VIC-II (und anderen Bausteinen) sprich den E/A-Bereich, sowie das Char-ROM. Um nun auf das Char-ROM zugreifen zu können, müssen wir den E/A-Bereich abschalten. Diese Möglichkeit ist der Hauptunterschied zwischen dem 6502 und dem 6510 aus dem C64. Die ersten beiden Speicherstellen (also die Adressen $0000 und $0001 sind für Sonderfunktionen reserviert, für weitere Infos, nochmal der Hinweis auf die Kleine Hardwarekunde).
Wir müssen also das Bit-2 auf 0 setzen, damit der E/A-Bereich verschwindet. Das sollten wir tunlichst nur machen, wenn keine Interrupts möglich sind, sonst ist ein Absturz nahezu unvermeidlich. Nach dem Abschalten können wir dann die 2KB, für einen Zeichensatz, aus dem Char-ROM einfach kopieren. Zum Schluß den E/A-Bereich wieder einblenden und die IRQs freigeben, schon haben wir unseren eigenen Zeichensatz. Laßt uns dies nun in unser obiges Programm einbauen.
Ändert dazu erstmal main wie hier gelb hervorgehoben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
main ;*** Start des Zeichensatzes festlegen lda #VICSCREENBLOCKNO*16+VICCHARSETBLOCKNO*2 sta $d018 ;Adresse für Bildschirm und Zeichensatz festlegen sei ;IRQs sperren lda $01 ;ROM-'Konfig' in den Akku pha ;auf dem Stack merken and #%11111011 ;BIT-2 (E/A-Bereich) ausblenden sta $01 ;und zurückschreiben jsr copyCharROM ;Zeichensatz kopieren pla ;ROM-Einstellung vom Stack holen sta $01 ;wiederherstellen cli ;Interrupts freigeben rts ;zurück zum BASIC |
Hier sperren wir zu Beginn, wie angekündigt, die Interrupts und blenden dann den E/A-Bereich aus. Anschließend können wir zur Routine copyCharROM springen und den Zeichensatz kopieren. Zum Schluß stellen wir die Speicheradresse $01 auf ihren ursprünglichen Wert zurück, damit der E/A-Bereich wieder sichtbar wird und aktivieren natürlich auch noch die IRQs.
Jetzt kümmern wir uns um die Kopierfunktion.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
copyCharROM lda #<CHARROMADR ;Quelle (CharROM) auf die Zero-Page sta ZP_HELPADR1 lda #>CHARROMADR sta ZP_HELPADR1+1 lda #<VICCHARSETADR ;Ziel (RAM-Adr. Zeichensatz) in die Zero-Page sta ZP_HELPADR2 lda #>VICCHARSETADR sta ZP_HELPADR2+1 ldx #$08 ;wir wollen 8*256 = 2KB kopieren loopPage ldy #$00 ;Schleifenzähler für je 256 Bytes loopChar lda (ZP_HELPADR1),Y ;Zeichenzeile (Byte) aus dem CharROM holen sta (ZP_HELPADR2),Y ;und in unseren gewählten Speicherbereich kopieren dey ;Blockzähler (256 Bytes) verringern bne loopChar ;solangen ungleich 0 nach loopChar springen inc ZP_HELPADR1+1 ;Sonst das MSB der Adressen auf der Zeropage inc ZP_HELPADR2+1 ;um eine 'Seite' (256 Bytes) erhöhen dex ;'Seiten'-Zähler (acht Seiten zu 256 Bytes) verringern bne loopPage ;solange ungleich 0 nach loopPage springen rts ;zurück zum Aufrufer |
Wir benutzen hier die Zero-Page, um die Adressen für das Char-ROM und den von uns gewählten Speicherbereich zuspeichern. Dann verwenden wir zwei Schleifen, um die 2KB zu kopieren. Die innere Schleife kopiert immer 256 Bytes, mit der Y-nach-Indizierten-Adressierung. Die äußere sorgt dafür, dass das ganze achtmal geschieht und erhöht bei jedem Durchlauf das MSB der Adressen auf der Zero-Page um eins, damit der nächste 256-Byte-Block kopiert werden kann.
Vergesst abschließen nicht, die drei neuen Konstanten für copyCharROM festzulegen:
1 2 3 |
CHARROMADR = $d000 ZP_HELPADR1 = $fb ZP_HELPADR2 = $fd |
Ein Start und mit offenen Mündern blicken wir aufs schier unfassbare Ergebnis:

OK, das Ergebnis ist nun nicht spektakulär, eigentlich eher enttäuschend.
Aber der Zeichensatz gehört jetzt uns!
Das können wir nun ganz einfach gegenprüfen, gebt nach dem Programmstart direkt POKE 14336+(8*32),255 ein und bestätigt die Eingabe mit RETURN.

Wir haben hier die erste Zeile des Leerzeichens geändert. Auf die Funktionsweise haben Änderungen des Zeichensatzes übrigens keine Auswirkung, für den C64 bleibt der Screencode 32 das Leerzeichen, egal ob es leer ist oder wie hier als Linie dargestellt wird.
Nun könnt ihr also euren eigenen Zeichensatz entwerfen, indem ihr die Bytes für euer Zeichen an die entsprechenden Speicherstellen schreibt.
Laßt uns abschließend noch eine kleine Routine entwickeln, die ein beliebiges Zeichen ersetzt. Fügt dazu hinter das cli, am Ende von main, die beiden folgenden Zeilen ein:
1 2 |
ldx #' ' ;SPACE (Leerzeichen) ersetzen jsr replaceChar |
Über das X-Register wählen wir das Zeichen aus, dass wir mit unserem ersetzen möchten, dann springen wir nach replaceChar um das Zeichen zu kopieren.
Nun fehlt natürlich noch die Funktion zum Kopieren eines Zeichens.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
;*** ersetzt den Screencode im X-Register mit dem Zeichen von testchar replacechar txa ;Screencode * 8 and #%00011111 asl asl asl clc adc #<VICCHARSETADR ;LSB fürs Ziel (RAM-Adr. Zeichensatz) in die Zero-Page sta ZP_HELPADR2 txa ;Screencode in den Akku lsr ;die oberen drei BYTEs für die Ermittlung lsr ;der Page verwenden lsr lsr lsr clc adc #>VICCHARSETADR ;einfach aufs MSB der Ziel-Adresse addieren sta ZP_HELPADR2+1 ldy #$07 @loop lda testChar,Y sta (ZP_HELPADR2),Y dey bpl @loop rts ;zurück zum Aufrufer |
Um den korrekten Beginn, des zu ersetzenden Zeichens im Speicher zu finden, müssen wir dessen Position (Adresse) berechnen. Dazu kopieren wir das X-Register zunächst in den Akku und blenden die oberen drei Bits aus. Auf einer 256-Byte-Page haben 32 Zeichen platz (32 * 8 Byte je Zeichen). Daher behalten wir die unteren fünf Bits und multiplizieren diese dann mit 8 (dreimal nach links verschieben). Jetzt addieren wir das LSB unserer Zeichensatzadresse dazu und haben somit den korrekten Beginn des Zeichens innerhalb einer Page. Dann müssen wir noch die richtige Page ermitteln. Also den Screencode nochmal vom X-Register in den Akku kopiert, fünfmal nach rechts verschoben und einfach das MSB der Zeichensatzadresse addieren. Schon haben wir die dazugehörige Page. Beide Werte haben wir uns wieder auf der Zero-Page gemerkt. Da wir acht Bytes (Zeile 0 bis 7 vgl. Bild) kopieren müssen, füllen wir das Y-Register mit 7. Dann holen wir das erste Byte unseres Entwurfes von der Adresse testChar und kopieren es an die dazugehörige Adresse in unseren Zeichensatz. Abschließend noch Y verringern und das ganze solange wiederholen, bis Y negativ wird. Schon sind wir fertig und die Funktion wird verlassen.
Unser neues Zeichen ‚entwerfen‘ wir beim Label testChar:
1 2 3 4 5 6 7 8 9 |
testChar !byte %00100000 !byte %00100000 !byte %00100000 !byte %11000000 !byte %00010100 !byte %00011000 !byte %00010100 !byte %00000000 |
Hier könnt ihr einfach durchs Setzen bzw. Löschen der einzelnen Bits, euer Zeichen entwerfen.
Startet ihr das Programm nun, dann wird statt des Leerzeichens ein dezenter Hinweis auf den Verfasser dieser Zeilen (also mich 😉 ) erscheinen.

Auf diese Weise (nur durch
!byte-Anweisungen) einen kompletten Zeichensatz zu erstellen ist allerdings doch sehr mühsam 😉 . Man greift daher auf Zeichensatz-Editoren zurück, um den Zeichensatz bequem zu erstellen. Zum Glück bietet das C64 Studio einen solchen Editor an (der kommt im Spiele-Tutorial zum Einsatz). Im Prinzip müsst ihr nur den von euch erstellten Zeichensatz in den Source einbinden und ggf. an die richtige Stelle kopieren.
Natürlich gibt es auch externe Tools oder entsprechende Programme, die ihr direkt auf dem C64 verwenden könnt, die euch das Erstellen von eigenen Zeichensätzen erleichtern.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
;*** VIC-II Speicher-Konstanten VICBANKNO = 0 ;Nr. (0 - 3) der 16KB Bank | Standard: 0 VICSCREENBLOCKNO = 1 ;Nr. (0 -15) des 1KB-Blocks für den Textbildschirm | Standard: 1 VICCHARSETBLOCKNO = 7 ;Nr. (0 - 7) des 2KB-Blocks für den Zeichensatz | Standard: 2 VICBITMAPBBLOCKNO = 0 ;Nr. (0 - 1) des 8KB-Blocks für die BITMAP-Grafik | Standard: 0 VICBASEADR = VICBANKNO*16384 ;Startadresse der gewählten VIC-Bank | Standard: $0000 VICCHARSETADR = VICCHARSETBLOCKNO*2048 ;Adresse des Zeichensatzes | Standard: $1000 ($d000) VICCHARSETADR = VICCHARSETADR+VICBASEADR CHARROMADR = $d000 ZP_HELPADR1 = $fb ZP_HELPADR2 = $fd ;*** Startadresse *=$0801 ;** BASIC-Zeile: 2018 SYS 2062 !word main-2, 2018 !byte $9e !text " 2062" !byte $00,$00,$00 main ;*** Start des Zeichensatzes festlegen lda #VICSCREENBLOCKNO*16+VICCHARSETBLOCKNO*2 sta $d018 ;Adresse für Bildschirm und Zeichensatz festlegen sei ;IRQs sperren lda $01 ;ROM-'Konfig' in den Akku pha ;auf dem Stack merken and #%11111011 ;BIT-2 (E/A-Bereich) ausblenden sta $01 ;und zurückschreiben jsr copyCharROM ;Zeichensatz kopieren pla ;ROM-Einstellung vom Stack holen sta $01 ;wiederherstellen cli ;Interrupts freigeben ldx #' ' ;SPACE (Leerzeichen) ersetzen jsr replaceChar rts ;zurück zum BASIC copyCharROM lda #<CHARROMADR ;Quelle (CharROM) auf die Zero-Page sta ZP_HELPADR1 lda #>CHARROMADR sta ZP_HELPADR1+1 lda #<VICCHARSETADR ;Ziel (RAM-Adr. Zeichensatz) in die Zero-Page sta ZP_HELPADR2 lda #>VICCHARSETADR sta ZP_HELPADR2+1 ldx #$08 ;wir wollen 8*256 = 2KB kopieren loopPage ldy #$00 ;Schleifenzähler für je 256 Bytes loopChar lda (ZP_HELPADR1),Y ;Zeichenzeile (Byte) aus dem CharROM holen sta (ZP_HELPADR2),Y ;und in unseren gewählten Speicherbereich kopieren dey ;Blockzähler (256 Bytes) verringern bne loopChar ;solangen ungleich 0 nach loopChar springen inc ZP_HELPADR1+1 ;Sonst das MSB der Adressen auf der Zeropage inc ZP_HELPADR2+1 ;um eine 'Seite' (256 Bytes) erhöhen dex ;'Seiten'-Zähler (acht Seiten zu 256 Bytes) verringern bne loopPage ;solange ungleich 0 nach loopPage springen rts ;zurück zum Aufrufer ;*** ersetzt den Screencode im X-Register mit dem Zeichen von testchar replaceChar txa ;Screencode * 8 and #%00011111 asl asl asl clc adc #<VICCHARSETADR ;LSB fürs Ziel (RAM-Adr. Zeichensatz) in die Zero-Page sta ZP_HELPADR2 txa ;Screencode in den Akku lsr ;die oberen drei BYTEs für die Ermittlung lsr ;der Page verwenden lsr lsr lsr clc adc #>VICCHARSETADR ;einfach aufs MSB der Ziel-Adresse addieren sta ZP_HELPADR2+1 ldy #$07 loopRow lda testChar,Y sta (ZP_HELPADR2),Y dey bpl loopRow rts ;zurück zum Aufrufer testChar !byte %00100000 !byte %00100000 !byte %00100000 !byte %11000000 !byte %00010100 !byte %00011000 !byte %00010100 !byte %00000000 |
OK, unser Beispiel ist nicht wirklich der Bringer, wer jetzt aber immer noch daran zweifelt, dass das Ändern des Zeichensatzes eine der wichtigsten Funktionen für Spiele und Demos ist, den überzeugen die folgenden Bilder hoffentlich. Dort seht ihr die Zeichensätze für den jeweils ersten Level von Uridium und Wizball in einem Editor und wie der gesamte Level dann aussieht. Diese sind zwar schon mehrfarbig, schaut euch also ggf. ‚VIC-II: Grafikmodes – Text‚ an.
Uridium
Den ersten Level von Uridium kennt doch bestimmt jeder (falls nicht unbedingt nachholen!).

Der Level ist sehr groß, wir sehen hier ja nur einen kleinen Ausschnitt. Seine gesamten Ausmaße erstrecken sich über mehrere Bildschirme…

Wer nun glaubt, dies sei eine komplette Grafik im C64, der irrt!
Alles wird durch einen geänderten Zeichsatz zusammengebaut. Im Editor sehen die Zeichen z. B. so aus:

Aus den einzelnen Zeichen wird dann das komplette Raumschiff für den Level, die sog. Map, erstellt.

Wizball
Als ersten müssen auch hier die Zeichen definiert werden. Bei diesem Wizball Beispiel, werden außerdem sog. Tiles verwendet. Ein Tile besteht dabei aus mehreren Zeichen und bildet somit einen größeren Baustein. Vergleicht das nochmal mit Uridium, dort war ein Tile genau ein Zeichen groß (man kann auch sagen, es wurden keine Tiles verwendet). Hier bei Wizball besteht ein Tile aus 5×5 Zeichen.

Nun läßt sich der Level etwas bequemer erstellen, da man größere Bausteine hat. Allerdings ist man dann auch nicht mehr so flexibel. Alles hat halt seine zwei Seiten.

Das Ergebnis hat dann wieder das bekannte Aussehen:

Im Spiel finden wir die obige Grafik gleich im ersten Level wieder. Wir sehen hier natürlich auch nur einen kleinen Ausschnitt und die Farben werden vom Programm anders gesetzt. Immerhin geht es im Spiel darum die triste Welt wieder einzufärben, bunt wird es daher erst später. Auch hier gilt, wer es nicht kennt unbedingt anspielen.

Das wars erstmal zu den eigenen Zeichensätzen.
Wie man einen Multi-Color-Zeichensatz anzeigt, könnt ihr bei VIC-II: Grafikmodes – Text nachlesen. Dort gibt es ein einfaches Uridium-Beispiel, in dem der erste Level von uns verwendet wird.
Experimentiert nun am besten etwas mit den Zeichensätzen. Sie bieten eine unglaubliche Vielfalt an Möglichkeiten. Eine schöne Übung ist es z. B. den gesamten Bildschirm einmal auf den Kopf zu stellen.

Hier könnt ihr jetzt auch schön überprüfen, dass das Aussehen der Zeichen wirklich keinen Einfluss auf die Funktionsweise des BASICs hat. Ihr könnt mit dem Kopfüber-Zeichensatz ganz normal Programme schreiben und Befehle ausführen, probiert es selbst einmal…

Durch einfaches Ändern der Adresse des Zeichensatzes könnt ihr später schöne Effekte erzielen. Auch nicht zu verachten ist, dass sich durch Ändern eines Zeichens (sind ja nur 8 Bytes), sofort alle Zeichen auf dem Bildschirm anpassen, aber das habt ihr ja eben schon gesehen.
Jetzt viel Spaß beim erschaffen eurer eigenen Zeichensätze,
Jörn
Hallo Jörn
Bin wieder einmal dabei, Deinen Quellcode Zeile für Zeile zu kopieren (und versuchen zu verstehen). Beim ersten Abschnitt bei der Änderung des Zeichensatzes hat sich ein kleiner Schreibfehler eingeschlichen:
jsr copyCharrROM ;Zeichensatz kopieren
Hier muss das mittlere r wohl das Zeitliche segnen 😉
Gruss, Markus
Moin!
Danke für die Hinweise (auch aus dem anderen Post), habe es eben korrigiert.
Hallo Jörn
Bei den BASIC-Befehlen haben sich 2 kleine Fehler eingeschlichen. Beim ersten Befehl muss es CHR$(142) heissen für die Umschaltung und beim zweiten Befehl ging das R vergessen.
Sost vielen Dank, auch wenn ich das mit dem Umschalten von E/A und RAM zwar theoretisch verstehe, doch praktisch immer noch einen Knopf habe, was nun in welche Richtung gelesen und geschrieben wird 😉
Gruss aus der Schweiz, Markus
Hallo,
ich weiß nicht, ob ich das überlesen habe, aber bedeutet das, dass man den RAM-Bereich von $D000 bis $DFFF nie auslesen kann? Wenn man durch das Deaktivieren von E/A nur E/A durch ROM ersetzen kann, dann kann man ja das RAM darunter nur beschreiben, oder gibt es fürs Lesen irgendeine mir nicht bekannte Möglichkeit?
Gruß
Julian
Hallo Julian,
das 2. Bit steuert eigentlich nur, ob E/A oder Zeichen-ROM sichtbar ist.
Sobald die unteren beiden Bits (0 & 1) auf 0 gesetzt werden, ist direkt das RAM sichtbar.
Da ist die Tabelle unter „Kleine Hardwarekunde“ leider irreführend, da dort 0 = RAM beim 2. Bit steht.
Das sollte ich wohl mal überarbeiten.
Gruß,
Jörn
Hallo Zusammen,
ich verwende den Vice C64.
Wie kann ich den Vice C64 so konfigurieren, dass mich mit deutschem Zeichensatz schreiben kann?
Viele Grüße
Robert
Meinst du die Umlaute (öäüÖÄÜßẞ)?
Hallo Jörn,
beim Versuch die Speicherbank zu wechseln ist mir aufgefallen, dass das Beispielprogramm noch unvollständig ist (weil, der Speicherbankwechsel nicht vorgesehen ist).
Nachdem ich diese Hürde genommen hatte bin ich in die gleichen Probleme wie damals Carsten gelaufen.
Hat eine ganze Weile gedauert bis ich eine Lösung gefunden habe.
Folgender Code zwischen main & “Start des Zeichensatzes festlegen” funktioniert einigermaßen:
;*** 16KB-Bank wählen
lda #%00000011 ;Datenrichtung für Bit 0 & 1 des Port-A (klappt auch ohne diese Zeile)
sta $dd02 ;zum Schreiben freigeben (klappt auch ohne diese Zeile)
lda #VICBANKNO
cmp #3 ;Bank-3
bne *+7
lda #%00000000
jmp bank
cmp #2 ;Bank-2
bne *+7
lda #%00000001
jmp bank
cmp #1 ;Bank-1
bne *+7
lda #%00000010
jmp bank
lda #%00000011 ;Bank-0
bank
sta $dd00 ;Bank wegschreiben
lda #>(VICBASEADR+(1024*VICSCREENBLOCKNO))
sta $0288 ;MSB vom BS in Reg. $0288
Wahrscheinlich reicht der Code nich an Deine Qualitätsvorstellungen heran aber falls hier nochmal jemand auf das Problem trifft….!
Super Website übrigens. Ich habe eine halbes Regal voller Bücher zu Assembler aber nutze fast nur noch Deine HP wenn ich auf Probleme stoße.
VG und weiter so!!
Hallo Jörn,
ich sauge gerade alle Informationen deiner tollen Artikel auf. Vielen Dank dafür!!!
Ein Fehlerchen ist mir aufgefallen:
Beim Codeschnipsel nach folgendem Text “Vergesst abschließen nicht, die drei neuen Konstanten für copyCharROM festzulegen:” ist “ZP_HELPADR2 = $fb” gesetzt, also auf denselben Wert wie ZP_HELPADR1.
Weiter unten im vollständigen Code ist der korrekte Wert $fd gesetzt.
Also nur ne Kleinigkeit, aber hatte mich beim ersten Lesen zunächst verwirrt 🙂
Gruß,
Sebastian
Hallo Jörn,
vielen Dank für das beste C64-Tutorial im Internet!
Ich verstehe eigentlich alles bisher (dachte ich zumindest;), aber wenn ich bei VICSCREENBLOCKNO etwas anderes als 1 eintrage (also zB 4, damit der BS bei $1000/$D000 liegt), gibt es Zeichensalat, obwohl ich bspw. den zeichensatz-block frei verschieben kann (zB auf 4, also $2000/$E000). Warum ist das bloß so?
Vielen Dank und Grüße!
Carsten
VICSCREENBLOCKNO
ist der Bildschirmspeicher. Wenn du den verschiebst, zeigt er erstmal auf einen nicht initialisierten Speicherbereich und du siehst zufällige Zeichen. Lösch den Bereich mal und gib dort einen Text aus.Hi Jörn,
vielen Dank für die schnelle Antwort!
>>Wenn du den verschiebst, zeigt er erstmal auf einen nicht initialisierten Speicherbereich und du siehst zufällige Zeichen.
ja, da steht erstmal Müll drinnen, aber auch wenn ich …
>>Lösch den Bereich mal und gib dort einen Text aus.
.. den Bereich lösche und/oder Zeichen reinschreibe, ändert sich überhaupt nichts! Wenn ich Dein Listing (“Hier nochmal das komplette Listing…”) 1:1 in CBM prg Studio 3.3 reinkopiere, ist alles OK. Wenn ich dann in der fünften Zeile die VICSCREENBLOCKNO auf 4 statt auf 1 setze (und damit den BS auf $1000 aus VIC-Sicht und auf $D000 aus CPU-Sicht) setze, ist weder Dein geänderter Zeichensatz noch sichtbar, noch kann man den Bildschirminhalt noch irgendwie verändern (also händisch auf der Tastatut rumtippen oder Werte nach $D000 sta’en). Wenn ich blind die Rahmenfarbe POKE’ , klappt das, d.h. kein Absturz oder so). Hat das evtl was mit der Überlagerung des E/A-Bereichs zu tun (der neue BS liegt ja dann bei $D000)? Aber auch das Ausgeblendet-Lassen des E/A-Bereichs ändert nichts….
Viele Grüße!
Carsten
ich ändere ja nur das Leerzeichen. Es kann sein, dass du nach
VICSCREENBLOCKNO = 4
kein Leerzeichen auf dem BS hast (auch wenn es evtl. so aussieht). Such dir mal ein anderes Zeichen aus, am besten eine Zahl, das auf dem Bildschirm zu sehen ist. Ändere dann in der Zeileldx #' ' ;SPACE (Leerzeichen) ersetzen
das ‘ ‘ z. B. durch ‘0’, wenn du vorher eine 0 gesehen hast. Jetzt sollte sich eine Änderung zeigen.Über die Tastatur kannst du keine sichtbaren Änderungen vornehmen, da das BASIC noch davon ausgeht, dass der Bildschirm bei
$0400
liegt. Für das System musst du das Highbyte der Bildschirmadresse nach$0288
schreiben.Für den Irrtum bei den letzten beiden Punkten, bin ich verantwortlich!
Im Source steht zwar
VICBANKNO = 3 ;Nr. (0 - 3) der 16KB Bank | Standard: 3
, es ist aber eigentlich Bank-0 (die wird aber mit %11 = 3 in$DD00
aktiviert!).Du bist hier also in Bank-0 (
$0000
–$3FFF
)! Daher liegt der BS in deinem Beispiel auch für die CPU bei$1000
und dieser Bereich ist ungünstig, da der VIC in Bank-0 dort immer auf den Zeichensatz im ROM zugreift!Sorry, das muss ich in den nächsten Tagen unbedingt nochmal überarbeiten!!
EDIT: Ich habe
VICBANKNO
im Source mal etwas geändert, es wird jetzt wirklich die Bank-Nr. genommen und ich habe stattdessen die anderen Berechnungen angepasst.Danke!!! Ja, jetzt schreibe ich auch in den richtigen Bereich und die Zeichen tauchen auf! Und das Setzen der für den VIC sichtbaren Bank mit
$DD00 hatte ich auch vergessen;)