Hallo Besucher, der Thread wurde 8,4k mal aufgerufen und enthält 25 Antworten

letzter Beitrag von Womak am

Basic: Zeichensatz ändern - Wie geht das?

  • Nicht lachen: Ich möchte in BASIC den Zeichensatz ändern und weiß nicht, wie das geht.



    Beispiel:
    Das Zeichen Shift+"A" (Chr$97) soll kein Pik-Symbol mehr sein, sondern horizontal gestreift (Schwarz, weiß,Schwarz, weiß...)


    Ich denke mal, dass das vom Prinzip her so oder ähnlich gehen müsste:


    Poke x,255
    Poke x+1,0
    Poke x+2,255
    Poke x+3,0
    [...]


    also pro Zeile des Zeichens einmal Poke irgendwas,0 bis 255 (wie bei einem Sprite halt)


    Mit Print chr$(97) sollte dann also ein gestreiftes Zeichen erscheinen.


    und so weiter für CHR$ 98,99,100 [...]


    Kann mir bitte jemand sagen, wie genau das abzubilden ist bzw. welche Adressen da angesprochen werden müssen? Geht´s vielleicht ganz anders?



    Vielen Dank!

  • im prinzip liegst du schon mal ziemlich richtig. Ein einzelnes Zeichen zu verändern geht so allerdings nicht sondern du gehst folgendermasen vor:
    1. Original-Charset ins RAM kopieren
    2. gewünschte Zeichen abändern
    3. Charset aktivieren


    zu 1.) überlege dir wo im RAM dein Charset stehen soll, willst du unter BASIC bleiben so bietet sich natürlich $c000 (49152) an. Kopiere den Original Zeichensatz dorthin. Dabei musst du den Interupt ausschalten und das CHarset ROM bei $d000 einblenden. Wenn du nicht weisst wie das geht, frag nochmal nach... dann kopierst du einfach die Daten von $d000-$d800 bze. von $d800-$dfff (je nachdem ob du den Groß-/Kleinbuchstabensatz oder den Graphikzeichen-/Großbuchstabensatz willst) nach $c000-$c800.
    2.) Ändere nun die gewünschten Zeichen. Dabei findest du nun das gewünschte Zeichen folgendermassen:


    Adresse = Screencode des Zeichens * 8 + 49152
    Die 8 Bytes ab dieser Adresse bestimmen das Bitmuster des Zeichens.


    3.) Erzähle dem VIC nun, dass er die Daten aus $c000 holen soll:
    Dabei musst du aber wissen, dass der VIC immer nur auf 16K zugreifen kann, also müssen alle deine Graphikdaten und(!) auch der Bildschrimspeicher in den obersten 16k liegen, eben da wo dein Zechensatz steht. Den Bildschirmspeicher verschiebst du am besten direkt hinter den Zeichensatz, also nach $c800-$cbff. Folgender POKE setzt den Bildcshrimspeicher auf $c800 und den Zeichensatz auf $c000:


    POKE 53272,32


    Nun musst du noch dem VIC sage, dass er auf die obersten 16k zugreifen soll:


    POKE peek(56576)and252


    fertig. jetzt sollte dein neues Charset dargestellt werden.


    Du kannst das natürlich einfacher haben, wenn du in den unteren 16k bleibst, dann musst du keinen Bildschirmspeicher verschieben und auch der 16k-Bereich kann bleiben wo er ist, aber dann muss dein Zeichensatz unter $4000 liegen (übrigens: $1000-$1fff ist dabei TABU, bleibt also $2000-$3fff) und ein etwas grösseres BASIC-Programm könnte deinen Zeichensatz dann überschreiben!


    Für Zeichensatz bei $3800-$3fff (14336 dez.) gilt folgender POKE:


    POKE 53272,30


    Ich hoffe die POKES stimmen auch, habs gerade aus dem Kopf geschrieben, kann sein dass ich mich da jetzt irgendwo vertan habe, aber das findest du alles auch in einschlägiger Literatur ("programmers Reference Guide usw.)


    Prinzipiell gilt:


    $d018: Obere 4 Bits: Bildschirmspeicher in $400er Schritten und untere 4 Bits: Zeichensatzadresse in $800er Schritten:



    $d018 Bildschirm
    0000xxxx $0000
    0001xxxx $0400
    0010xxxx $0800
    0011xxxx $0c00
    usw.


    und für den Zeichensatz:


    xxxx0000 $0000
    xxxx0001 $0800
    xxxx0010 $0c00
    xxxx0011 $1000


    usw.


    Dabei musst du natürlich den Offset der 16k-Bank addieren um die tatsächliche Adresse zu erhalten.

  • Schlüsselfrage ist halt, was du vorhast...
    ...bzw. wie gross das Basicprogramm insgesamt so werden wird / werden soll...


    wenn es nicht sehr umfangreich ist, dann bietet sich die lösung mit dem charset von $3800-$3fff an, da das den geringsten aufwand bedeutet. einfach 1 poke, und schon ist der charset umgestellt (poke 53272,30).


    was das kopieren des originalcharset vom rom ins ram angeht sei allerdings erwähnt, dass da in basic einige zeit dauert!!! ich hab vor 20 jahren auch so zu programmieren angefangen (hab die programm auch heute noch :) ... man ist das ein zeugs ) ...und das hat immer ne ganze weile gedauert, bis
    der charset endlich an die entsprechende stelle im ram kopiert war.
    einfacher wäre es da, den charset einfach an die entsprechende stelle zu laden!
    also zuerst mit einem charset-mal-programm den charset erstellen und mit der "richten" ladeadresse abspeichern, und dann später im basicprogramm das ding einfach reinladen...

  • Hallo Nairobi,


    Wenn es auch in BASIC sein kann, könnte ich Dir diesen Link mal empfehlen http://www.c64-wiki.de/index.php/Zeichen

  • Zusammen mit dem Wiki-Artikel sind die Anregungen sehr hilfreich. Ich muss dazu sagen, dass ich am C64 nie wirklich was (nicht einmal Basic) programmiert habe, bin also ein "Totalhorst" was das angeht.


    Aber ich glaube, dass ich damit jetzt klarkomme. Ich muss jetzt nur noch die Zeit finden, das auszuprobieren.


    Vielen Dank


    Nairobi bzw. MJ

  • Großes Problem!


    Ich habe das Listing aus dem C64-Wiki benutzt (Zeichensatz nach 12288/$3000 kopieren). Das funktionierte auch prima, bis mein Basic Programm zu lang wurde und den Zeichensatz überschrieb. Endstation!


    Also habe ich Hannenz Tipps befolgt und das nach besten (Nicht)wissen und Gewissen in folgendes Listing umgesetzt:



    ** Interrupt aus ***
    10 POKE 56334,PEEK(56334) AND 254


    ** E/A aus **
    20 POKE 1,PEEK(1) AND 251


    ** Bildschirmspeicher kopieren nach $C800 **
    24 FOR L =51200 TO 52223: POKE L,PEEK(L-50176):NEXT L


    ** Zeichensatz kopieren nach $C000 **
    26 FOR L=53248 TO 55295: POKE L-4096,PEEK(L):NEXT L


    ** E/A ein **
    27 POKE 1,PEEK(1) OR 4


    ** Interrupt ein**
    28 POKE 56334,PEEK(56334) OR 1


    ** Video Bank auswählen (Start: $C000) **
    30 POKE 56578,PEEK(56578 ) OR 3


    40 POKE 56576,(PEEK(56576)AND 252) OR 0


    ** Screen bei $C800, Chars bei $C000 **
    50 POKE 53272,32


    [dann folgen die Read/Data/Poke für die Zeichen (alles Adressen von $c000 bis $C800)]



    Probleme:


    So, wie es dort steht, stürzt das ganze ab (Zeile 40 oder 50)
    Lasse ich Zeile 24 weg, läuft das Programm durch, aber: Der Bildschirm ist voll mit @ und Karos. Mit Poke 51200 ($c800),x kann ich aber z.B. entsprechende Zeichen des veränderten Zeichensatzes in die linke obere Ecke etc schreiben...die Veränderung des Zeichensatzes an sich hat also geklappt.


    Nur: ich kann ausschließlich mit Poke51200+x die Zeichen auf den Schirm bringen. Wenn ich z.B. Print benutze funktioniert das nicht. Ich tippe blind im Zeichenmüll. Wenn ich blind „Load“*“,8,1 + Enter eintippe, springt die Floppy an (sprich: nicht abgestürzt), aber ich kann halt nicht sehen, was ich da tippe.


    ???


    Was mache ich da falsch???
    Habe ich evtl.“das Charset ROM bei $d000 einblenden“ (sh. Hannenz) vergessen/nicht verstanden?


    Und kann ich, wenn es denn überhaupt funktioniert, meine Sprites benutzen
    (Spritedaten ab 832 dec., sprich poke 2040,13 etc.)?


    Hilfe!

  • Ich schätze mal das BASIC nicht peilt das das ScreenRAM jetzt ganz woanders sitzt.


    Pack nach 648 ($288) mal den Wert 200 ($C8) und lösch den Bildschirm mit SYS 58692.
    Also:
    60 POKE 648,200:SYS 58629
    70 PRINT "TEST"

  • Das werde ich mal probieren, vielen Dank.


    Wie ist das mit den Sprites?
    Im "Basic für Doofe" schaltet man die ja mit Poke 204x,y ein (mit den Spritedaten in den Blöcken 13,14,15 -> Datasettenpuffer)


    Wenn ich den VIC jetzt auf die höhere Bank umgeschaltet hab, muss ich da evtl. nicht auch die Spritedaten samt Pointer irgendwoanders hinlegen? Wenn ja, wohin bzw. wie geht das?

  • Ja, du iegst mit deiner Vermutung genau richtig. Die Sprite Pointer sind immer "hinter" dem Bildschirmspeicher oder anders gesagt: Der Bildschirm Speicher lässt sich ja in 1K-Blöcken verschieben (1024 Bytes) für den Screen selber werden ja aber nur 1000 Bytes benötigt. In den letzten 8 Bytes dieses 1K-Blocks sind immer die Sprite Pointer. Wenn dein Bildschirmspeicher jetzt also bei $c800 liegt, sind die Sprite pointer bei CBF8 - $CBFF.
    Oder einfacher: SP = Bildscirmspeicher-Beginn + 1016

  • wg. Poke 680,200: Ich hab´s noch nicht getestet, aber ich bemerke gerade, dass ich das im Reference Guide wohl dezent überlesen habe (autsch). Daran wird es wohl iegen.


    @Hannenz


    Mensch, danke (ich komm mir echt dämlich vor...aber beim ersten Mal tut´s immer weh, richtig?). Ich kann das im Moment leider nicht ausprobieren:


    zeigt denn CB8F dann immer noch von 0*64 (ja, nutzlos, ich weiss) über 13*64 (Datasettenpuffer) bis maximal 255*64 (3FC0) ....oder woanders hin? Das bleibt vermutlich, oder? Ich verschiebe ja nur den Pointer, nicht dessen Funktion.

  • Das heisst, daß der VIC nur 16KB gleichzeitig sehen kann und sich die Spritedaten aus der gleichen 16K-Bank zieht, in der auch der Bildschirm liegt. Mit dem Poke56576,0...3 hast Du die Bank ab $c000 ausgewählt. Die anderen Bänke sind $8000, $4000, $0000.


    Das Poke 2040,13 ist nur ein vereinfachtes
    Poke "Bildschirmstartadresse+1016","(Spriteadresse-Bankanfang)/64"
    Mit Deinem neuen Bildschirm hiesse es "Poke 51200+1016,13", wobei die 13 dann nicht einfach 13*64+$0000=832, sondern 13*64+$c000=49984 ist.

  • Jetzt funktioniert es.


    So wie Hoogo es beschrieben hat, hatte ich es zuvor schon gemacht, allerdings ohne Erfolg: Die Sprites waren einfach nur „Müll“. Deshalb hatte ich noch einmal nachgefragt. Das lag vermutlich aber nur an den unzähligen Resets und Neustarts, die ich beim Testen durchgezogen hatte (ich habe das am CCS probiert und mit Savestates gearbeitet). Auf der „echten“ Maschine lief es dann auf Anhieb. Merkwürdig. Nach Neustart des Emus lief es dann auch dort.


    Allen jedenfalls vielen Dank für die unendliche Geduld. Aller Anfang ist halt schwer.

  • Der Müll könnte noch einen weiteren Grund haben: 2 Bereiche im SPeicher sind für Grafik Tabu: $1000-$2000 und $9000-$A000. An den Stellen sieht der VIC immer nur das Zeichensatz-ROM, eagl für welchen Zweck. Falls Du also mit anderen Pokes als oben experimentiert hast könnte Dich das getroffen haben.

  • Am einfachste ist, wie schon erwähnt, den Zeichensatz nach $3800 zu legen. Leider hat man dann nur 12K Speicher für ein BASIC-Programm frei. Besser geht es, wenn man vor dem Laden des Programms den BASIC-Speicher hochsetzt. Den Zeichensatz legt man dann am besten nach $0800, so hat man dann von $1000 bis $9FFF Platz für das Programm + Variablen (36K).


    POKE 45,16 -> BASIC-Speicheranfang nach $1000
    POKE 53272,19 -> Zeichensatz bei $0800


    Leider geht der erste POKE nur, BEVOR man das Programm lädt. Man brauch also mindestens ein kleines Programm zum Nachladen des Hauptprogramms.

  • Zitat

    Original von sauhund
    in basic würde ich den zeichensatz ja nach $c000 und den screen nach $c800 legen....dann muss man nur den pointer für den screen-start umbiegen und hat keinen ärger mit dem basicstart und all dem gemurkse


    Wie geschriebenm, habe ich mich auch für diese Alternative entschieden. :freude