Hallo Besucher, der Thread wurde 1,5k mal aufgerufen und enthält 19 Antworten

letzter Beitrag von Bytebreaker am

!text Großß'/Kleinschrift in ACME

  • Hallo,


    zwischen Groß- und Kleinschrift sowohl im CharROM als auch bei vielen anderen Zeichensätzen sind Groß- und Kleinbuchstaben um 64 Zeichen versetzt, d.h. wenn man auf einen Zeichencode 64 Zeichen aufschlägt, landet man beim selben Zeichen in groß, bzw. klein, je nach Aufbau der Zeichen.


    Mit der !text Direktive in ACME werden (nach meinem Verständnis) Textzeichen in Offset-Zahlen umgewandelt. So ist der Buchstabe "d" für den Assembler später eine 4. Es macht ja schließlich keinen Spaß, seine Texte als Zahlen in den Sourcecode schreiben zu müssen.


    Ich will jetzt an die Großbuchstaben eines Charsets dran, die ab dem 512. Byte beginnen. Ich kann den Zeichensatz mit entsprechendem Offset einladen, dann klappt der !text. Was dann aber nicht mehr klappt, sind Nummern und Interpunktionszeichen aus dem Charset.


    Gibt es, ohne dass ich die Bitmap-Struktur des Charsets umbauen muss, einen Weg, der !text-Direktive zu sagen, es soll für bestimmte Bereiche ein Offset benutzt werden? Oder muss ich umsteigen und Byte-Wüsten in meinen Quellcode eintippen, also .byte 4 anstatt !text "d"?


    Edit:
    Bzw. sind die Regeln, nach denen !text die Buchstaben in Zahlen umsetzt, zugänglich und editierbar?


    Edit2:
    Die Datei AllPOs.txt in den ACME Docs scheint Infos zu enthalten was man hier tun kann.
    Ich lese mich da ein und poste, wenn ich es herausgefunden habe.

  • Es gibt doch glaube ich auch !scr, hilft Dir das eventuell?


    Btw, ich habe das eh noch nicht so 100% verstanden mit den Charsets, vielleicht kann das jemand gerade mal kurz fuer mich erklaeren. Wenn ich z.B. POKE1024,1 mache, dann erhalte ich ja ein "A" auf dem Bildschirm. Laut PETSCII-Tabelle hat das A aber die 65. Warum ist das so? Sorgt bei mir immer wieder fuer Verwirrung...

  • Btw, ich habe das eh noch nicht so 100% verstanden mit den Charsets, vielleicht kann das jemand gerade mal kurz fuer mich erklaeren. Wenn ich z.B. POKE1024,1 mache, dann erhalte ich ja ein "A" auf dem Bildschirm. Laut PETSCII-Tabelle hat das A aber die 65. Warum ist das so?

    Weil PetSCII was anderes ist als Screencodes. Screencodes sind die Nummern der auf dem Bildschirm darstellbaren Zeichen. Multiplizier den Screencode mit acht, und Du erhältst den Offset des Zeichens im Char-ROM.
    Jeder Bytewert entspricht einem Zeichen, also sind 256 verschiedene Zeichen darstellbar, wobei die CBM-8-Bitter standardmäßig die zweite Hälfte als invertierte Kopie der ersten Hälfte benutzen.


    PetSCII hingegen ist eine Textkodierung und enthält neben druckbaren Zeichen auch Steuerzeichen wie Carriage_Return, Home, Clear, Reverse_ON, Cursor_Left und so weiter. Invertierte Zeichen selbst gibt es hier nicht, sondern nur die logischen Umschaltcodes, die vom Bildschirmtreiber dann erst interpretiert werden müssen. Etliche Codes haben auch gar keine sichtbare Funktion (0, 1 und 2 zum Beispiel), weshalb man z.B. die Null als Stringterminator benutzen kann, ohne dass einem dadurch ein sichtbares Zeichen verlorengeht.


    Natürlich hätte Commodore den Zeichensatz auch so entwerfen können, dass zumindest die nicht-invertierten, druckbaren Zeichen in beiden Tabellen den gleichen Code haben (diverse andere Architekturen machen das so, und diverse C64-Programme mit eigenem Zeichensatz intern auch), aber auch dann wären es zwei unterschiedliche Dinge für unterschiedliche Zwecke.


    Wenn man nun in einem Assemblerprogramm einen Textstring ablegt, muss man dem Assembler über den Pseudo Opcode mitteilen, welche Kodierung man denn gern hätte.

  • Ah okay stimmt, so hab ich das noch gar nicht betrachtet. Es sind ja tatsaechlich komplett verschiedene Tabellen, klar, dann ist ein 1:1-Mapping eh nicht moeglich :) komisch dass mir das noch nie so direkt bewusst geworden ist

  • So, diese Stelle in der Doku ist es:




    Ich war aber intellektuell zu überfordert, das umzusetzen (und bequem). :rolleyes:
    Es ging am Ende schneller, im Hex Editor das Charset zu öffnen, die Bytes abzuzählen und copy paste zu machen (ich brauche nur Großbuchstaben, Zahlen und Interpunktion). :D

  • Es ging am Ende schneller, im Hex Editor das Charset zu öffnen, die Bytes abzuzählen und copy paste zu machen

    Häh?! Copy/Paste von was? Und warum?


    Ich glaube fast, Du willst einfach nur Screencodes benutzen, also nimm "!scr" und gut is.

  • @ Mac Bacon


    Das angehängte Bild zeigt den Aufbau meines Zeichensatzes, mit dem ich arbeiten will.
    !scr hatte ich schon drin, das klappt auch, nur nimmt er dann die Kleinbuchstaben am Anfang des Charsets. Ich will aber an die Großbuchstaben weiter unten ran, die ab Byte 512 beginnen.


    Ich kann jetzt die Großbuchstaben einfach bei der vorgesehenen Charset-Position per Offset anfangen lassen:


    *=Adresse-512-2
    charset:


    !bin "charset.bin"


    aber mit !scr und !pet findet er mir dann die Zahlen und Punkte, Kommas, Ausrufezeichen nicht mehr.


    Also habe ich einfach die Bytes von 512 bis 512+32*8) im Hex Editor kopiert (die dritte Zeile von oben im Charset-Bild) und ganz am Anfang eingefügt, bzw. die Kleinbuchstaben mit den Großbuchstaben überschrieben und als neue Charset-Bin-Datei abgespeichert. !scr ist weiterhin gesetzt, Interpunktion und Buchstaben klappen jetzt, weil die gleich geblieben sind.


    Wenn ich abstrakte Syntax-Beschreibungen in Dokus sehe ist das für mich fast so schlimm wie mathematische Formeln. Die Rettung sind für mich immer die Beispiele, anhand derer ich das Muster sehe und imitieren kann. Die ACME Doku ist sehr gut, ich hätte nur eben viel länger gebraucht, den relevanten Teil der Doku zu verstehen und umzusetzen statt schnell ein bisschen zu zählen und im Hex Editor hin und her zu kopieren.

  • Das angehängte Bild zeigt den Aufbau meines Zeichensatzes, mit dem ich arbeiten will.

    Okay, das sind 128 Zeichen, und der Aufbau entspricht exakt dem des Klein/Groß-Zeichensatzes im ROM: Erst Kleinbuchstaben, dann Sonderzeichen und Ziffern, dann Großbuchstaben und dann ein paar spezielle Grafikzeichen.

    !scr hatte ich schon drin, das klappt auch, nur nimmt er dann die Kleinbuchstaben am Anfang des Charsets. Ich will aber an die Großbuchstaben

    Dann schreib Großbuchstaben in den Source. Das muss gehen, denn mit dem Original-Zeichensatz geht es ja auch. Wenn das nicht klappt, reden wir irgendwie aneinander vorbei...


    Solltest Du später noch auf die zweite, normalerweise invertierte, Hälfte der Zeichen zugreifen wollen, dann nimm "!scrxor".

  • Es klappt auch mit Großbuchstaben im Source nicht.


    Ich kopiere Charset-Bitmap-Stücke in Sprites und nutze !scr als Offset-Hilfe, damit ich !scr "d" statt .byte 4 scheiben kann.


    Der C64 weiß nichts von der Charset-Bitmap. Wenn man im Direktmodus etwas tippen könnte, käme in meinem Programm immer noch CharROM.


    Wenn ich sage "Nimm aus dem !scr String das nächste Zeichen (=die nächste Offset-Zahl) und wende sie als Offset auf die Char-Bitmap ab Adresse XYZ an und schneide das Zeichen heraus was Du brauchst und kopiere es in ein Sprite", dann erhalte ich immer das gleiche Ergebnis im Sprite, nämlich Kleinschrift, egal ob im !scr String große oder kleine Buchstaben drin stehen.


    Würde ich dem C64 sagen was er als Charset zu nehmen hat und ins Screen RAM poken, dann hätte ich vermutlich Groß- und Kleinschreibung so wie es im !scr String definiert ist. Das ScreenRAM interessiert mich aber hier gar nicht als Ort der Textdarstellung.


    Edit:
    Gelöst habe ich das Problem also nur über einen krummen Umweg, nämlich durch Manipulation der Char-Bitmap.


    Edit2:
    Oder ich hätte über eine Conv-Tabelle dem ACME-Programm gesagt, "wenn Du das "d" in Großschrift siehst, mach da keine 4 draus, sondern eine 68. Und das war mir zu schwer.

  • Es klappt auch mit Großbuchstaben im Source nicht.
    [...]
    Wenn ich sage "Nimm aus dem !scr String das nächste Zeichen (=die nächste Offset-Zahl) und wende sie als Offset auf die Char-Bitmap ab Adresse XYZ an und schneide das Zeichen heraus was Du brauchst und kopiere es in ein Sprite", dann erhalte ich immer das gleiche Ergebnis im Sprite, nämlich Kleinschrift, egal ob im !scr String große oder kleine Buchstaben drin stehen.

    ...und plötzlich ergibt alles einen Sinn. :D
    Der Screencode von "d" ist $04.
    Der Screencode von "D" ist $44.
    Umgerechnet zu Byteoffsets wären das dann die Werte $020 und $220. Wenn Du mit dem zweiten Wert die gleichen Bitmuster vorfindest wie mit dem ersten, hast Du wohl einfach einen Bug in Deiner Umrechnung bzw. vermutlich eher in der Indizierung: Die Indexregister sind nur acht Bit breit, da kann man mit Zehn-Bit-Indizes schon mal was falsch machen.
    Wie sieht Dein Umrechnungscode aus?

  • Lda infotext,x


    getChar
    sta ZP_HELPADR. ; Ort des Chars den wir suchen soll hier stehen
    lda #$30
    sta ZP_HELPADR+1


    asl ZP_HELPADR. ;mal 8
    asl ZP_HELPADR
    asl ZP_HELPADR


    bcc cont
    inc ZP_HELPADR+1 ;hi Byte der Adresse wird erst ab 512x8 auf 2 erhöht, kein rol in weiteres hilfs hi Byte nach asl Aktion nötig


    Cont
    ;lokalisieren des gewünschten Chars in der Bitmap via indirekter y adressierung und ins Sprite kopieren


    Infotext
    !scr "d"


    -----------------


    Ich benutze asl und will aus Faulheit und für schnellen Code kein rol nach jedem asl in ein weiteres hilfs hi Byte machen, das ich dann auf das Adress High Byte der Charset Adresse auf addieren muss.


    Wahrscheinlich verschlucke ich mit meinem asl einen Teil der Ziel Adresse.

  • Mac Bacon hat recht. Die Umrechnungsroutine funktioniert leider ohne zusätzliches ROL nicht.
    Von den drei Bits, die nach links hinausgeschoben werden (%11100000), wird nur das letzte berücksichtigt, also:
    %00100000. Diese Stelle entspricht dem Wert 32 = $20.
    "D" im Screencode ist jedoch $44 = %01000100.
    Das zweite ASL schiebt das Bit bei %01000000 jedoch einfach raus, ohne daß es danach weiter beachtet wird. Deshalb haben "d" und "D" eine identische Wirkung.
    Tut mir leid, aber wenn Du Groß- und Kleinbuchstaben haben möchtest, wirst Du um ein ROL wohl nicht herumkommen. Nebenbei: Ein Alphabet (a-z oder A-Z) belegt schon eine Speicherseite (32 * 8 = 256 Bytes). Du brauchst für einen Zeichensatz daher in der Regel mindestens 3 Speicherseiten: 1.) Interpunktion, 2.) Großbuchstaben, 3.) Kleinbuchstaben. Daher reicht ein einfaches Inkrement des Highbytes nicht aus.

  • Danke MJ!


    Ja dann werde ich mal sehen. Aktuell funktioniert der gesamte Sprite Scroller mit Punkt, komma, zahlen und Großbuchstaben mit frisierter, 2x256 Byte großen charmap. Ich brauche nur das Adress High Byte maximal auf 1.


    Ich optimiere ggf. Später. Jetzt als nächstes muss ich den Sprite scroller in die untere geöffnete border unterbringen und dann ein restliches Intro in den Bereich der sichtbaren Bitmap hinein bauen.


    Wenn das alles erstmal geht ändere ich bestimmte Routinen ab, um sie flexibler und wiederverwendbarer zu machen.


    Da gehört die korrekte Char Indizierung dann auf jeden Fall dazu.

  • Wenn man eh weiß, dass man sich auf 128 Zeichen beschränkt, kann man sich den ersten ROL natürlich sparen, denn da kann ja nur ein Nullbit herausfallen. Mit entsprechend angepasster Vor-Verschiebung hat man dann:

    Code
    1. lda #($30 >> 2) ; High-Byte der Basisadresse, vor-verschoben, wird von ROL korrigiert.
    2. sta ZP_HELPADR+1
    3. lda infotext, x
    4. asl ; *2
    5. asl ; *4
    6. rol ZP_HELPADR+1 ; neuntes Bit
    7. asl ; *8
    8. rol ZP_HELPADR+1 ; zehntes Bit
    9. sta ZP_HELPADR