Hallo Besucher, der Thread wurde 6,2k mal aufgerufen und enthält 8 Antworten

letzter Beitrag von Mac Bacon am

Zugriff auf RAM-Bank 1 beim C128

  • Hallo Leute,


    da der C128 seine Variableninhalte in Bank 1 ablegt würde ich gerne wissen, wie man diesen freien RAM-Bereich für seine Assemblerprogramme nutzen kann. Wie kann ich in Bank 1 z.B. Textstrings ablegen und von Bank0 darauf zugreifen? Es müsste ja auch möglich sein, ganze Bildschirmseiten dort abzulegen. Nur muss man einen Weg finden, wie man diese dann seitenweise aus Bank 1 wieder zurück lesen kann. Wer kann mir diesen Weg verständlich erklären?


    Liebe Grüße!
    ThomBraxton

  • Die vorhandenen "Far"-Routinen sind Dir bekannt? Im Kernal liegen von $f800 bis $f85a ein paar Wrapper-Funktionen für Speicherzugriffe, die beim Systemstart ins RAM kopiert werden:

    Code
    1. $0a2a Far-LDA, entspricht einem LDA(ptr),Y - aber in Speicherkonfiguration X
    2. $02af Far-STA, entspricht einem STA(ptr),Y - aber in Speicherkonfiguration X
    3. $02be Far-CMP, entspricht einem CMP(ptr),Y - aber in Speicherkonfiguration X
    4. $02cd Far-JSR, entspricht einem JSR, aber in eine bestimmte Bank. Die Bank steht in $02, die Zieladresse in $03/$04 (und die gewünschten Werte für die Prozessorregister dahinter).
    5. $02e3 Far-JMP, entspricht einem JMP, aber in eine bestimmte Bank (Argumente wie bei Far-JSR).

    Bei Far-LDA, -STA und -CMP muss der gewünschte ZP-Zeiger direkt in die Routine geschrieben werden.


    Das Basic benutzt immer diese Wrapper-Funktionen, nicht nur für die Zugriffe auf die Variablen in Bank 1, sondern auch für den Basic-Text in Bank 0, denn irgendwie muss der Code im ROM ja auch auf das RAM direkt darunter zugreifen können - und deshalb ist Basic7 auch noch etwas langsamer als Basic2.


    Für erste Versuche sind die Routinen brauchbar, für schnellere Zugriffe muss man sich eigene Routinen basteln, z.B. immer ganze Pages lesen/schreiben, bevor die Speicherkonfiguration gewechselt wird.
    Die schnellste Möglichkeit bieten die Pagepointer der MMU: Damit können beliebige Pages auf Zeropage und Stack abgebildet werden, aber leider hat das auch Nachteile:
    Von der Zeropage kann man dank des Prozessorports die ersten beiden Bytes nicht vernünftig nutzen, und während des Zugriffs müsste man natürlich die Interrupts sperren.
    Benutzt man den Stack, muss man ebenfalls alle Interrupts sperren, und während des Zugriffs sind natürlich auch alle Stackbefehle verboten.

  • Du kannst auch die Routen im Tedmon nehmen

    Nein, kann man nicht, denn die enden mit einem Sprung in die Tedmon-Hauptschleife. Und für die eigentlichen Speicherzugriffe benutzt Tedmon natürlich ebenfalls Far-LDA, Far-STA und Far-CMP.
    Außerdem sind diese Routinen sogar noch etwas langsamer als nötig, denn:
    1. benutzt Tedmon für den C- und den T-Befehl die gleiche Routine und prüft daher vor jedem Byte nochmal, was jetzt eigentlich Sache ist, und
    2. wird bei "Transfer" nicht einfach nur Far-LDA und Far-STA ausgeführt, sondern anschließend auch noch Far-CMP.

  • Wenn die zu kopierende Datenmenge etwas größer ist: Man kann per Software prüfen, ob eine REU da ist und die dann das Kopieren per DMA erledigen lassen. Geht schneller. Man muss sich nur bewusst sein, dass man noch einen Pfad braucht, der den Fall abdeckt, dass keine REU vorhanden ist.

  • Zugriff auf Bank über die Reu ist schwierig, hier ein Auszug aus dem Handbuch:


    Hinweis für BASIC-Programmierer
    Die BASIC-Befehle STASH, FETCH und SWAP können nur benutzt werden, um Daten von Bank 0 des internen Commodore 128-RAM auszu­tauschen. Um auf Bank 1 des Commodore 128 zuzugreifen, muß ein speziel­les Kontroll-Register des Commodore 128 geändert werden. Dieses Register ist das RAM-Kontroll-Register in der MMU, Adresse $D506. Bit 6 und 7 dieses Registers kontrollieren den VIC-RAM-Bank-Zeiger und den C 128­DMA-Bank-Zeiger.
    Adresse Bit Funktion
    $D506 6-7 00 C128 Bank 0
    10 C128 Bank 1


    Achten Sie darauf, die Originalwerte einzutragen, sonst zeigt Ihr 40-Zei­chen-Bildschirm falschen Inhalt.
    Denken Sie daran, daß I/O für die drei BASIC-Befehle in Version 0 des C 128-Kernal-ROM eingeschaltet ist. Bei Version 1 des ROM kann I/O ausgeschaltet sein, während die Bank-Befehle angewandt werden. Nähere Informationen über die Bank-Befehle können Sie im Commodore 128 Be­dienungshandbuch nachlesen.
    Die Version des Kernal-ROMs kann abgefragt werden, bei Adresse $FF80 "PEEKt". Bei Version 0 erscheint eine 0, während Version 1 eine 1 als Ergebnis liefert.

  • Leicht daneben. Der OP hat nach Assembler gefragt. Da gibt es die Einschränkung der BASIC-Befehle nicht.
    Rezept: REU Programmieren per STA nach den registern in $DF0x. Gemäß http://www.willcox.de/reu.txt (damit habe ich meine REU-Programmierungen hinbekommen, auch wenn "nur" auf den C64 / C64-Mode).


    So sollte es gehen:
    IO-Bereich einblenden. REU Programmieren, dabei:
    Beim Schreiben nach $DF01 das Bit 4 setzen. Jetzt die Bank umschalten und die Adresse $FF00 lesen. Das startet den Kopiervorgang. Das ganze bei gesperrten Interrupts. Danach die Bank zurückschalten und Interupts wieder freigeben.


    Nachtrag: Das ganze natürlich noch einmal zum Zurücklesen der Daten. Insgesamt hat man aber als Overhead 21 LDA und 19 STA Befehle. Und den DMA, der 1 Byte pro Prozessortakt schafft.


    Bei nicht gerade ganz kleinen Datenmengen schneller als direktes Kopieren. Schon allein, weil man dabei die Bank recht oft umschalten müsste.

  • Das Basic benutzt immer diese Wrapper-Funktionen, nicht nur für die Zugriffe auf die Variablen in Bank 1, sondern auch für den Basic-Text in Bank 0

    Ich muss mich korrigieren; tatsächlich benutzt das Basic eigene Wrapper-Funktionen im Bereich von $39f bis $3d2. Diese sind weniger universell verwendbar als die von Kernal und TedMon verwendeten Routinen, aber dafür auch etwas schneller.
    Hier alle relevanten Routinen im Überblick:


    Der Basic-Interpreter verlässt sich also darauf, dass die Präkonfigurationsregister der MMU korrekt gesetzt sind. In eigenen Assemblerprogrammen kann man die natürlich beliebig ändern, aber wenn man Basic und Assembler mischt, muss man das beachten.


    Auffällig ist, dass gar keine Routinen zum Schreiben vorhanden sind - allerdings sind dafür gar keine Wrapperfunktionen notwendig, denn Schreibzugriffe bei aktiviertem ROM gehen ja automatisch ins RAM. Der Interpreter muss also nur den I/O-Bereich deaktivieren und die richtige RAM-Bank auswählen, dann kann er direkt an die gewünschte Stelle schreiben, ohne eine Wrapperfunktion anspringen zu müssen.


    Alle hier aufgeführten Routinen funktionieren nur, solange über das "RAM Configuration Register" der MMU eine Common Area von mindestens 1K im unteren Speicherbereich eingerichtet ist! Wenn nicht, verschwindet beim Umschalten auf Bank 1 sofort der Code (der ja in Bank 0 liegt) und der Rechner schmiert ab - es sei denn, man hat den Code vorher mit anderen Mitteln auch in Bank 1 kopiert.


    Eine Routine zum schnellen seitenweisen Kopieren gibt es später - sobald ich sie getestet habe. :D