8) Ein tieferes Eindringen

Ich erwähnte es bereits: Man kann dem REC noch viel mehr Kommandos geben als offensichtlich ist. Eine Gruppe von Kommandos sind die (ich nenne sie mal so) Total-RAM-Commands. Man erkennt sie unschwer an ihrem gelöschten Bit 4. Ihre Namen sind: Mit diesen Kommandos ist es möglich auch im Bereich von $D000 bis $DFFF das RAM zu lesen und zu schreiben.
Aber wie soll das gehen?
Nun, durch die obigen Kommandos führt die REU die gewünschte Aktion nicht sofort aus, sondern wartet auf ein bestimmtes Ereignis. Dadurch hat man Gelegenheit den IO-Bereich (nach Übermittlung der Werte an den REC!) auf RAM zu schalten. Und das bestimmte Ereignis ist ein Schreibzugriff auf $FF00. (Ich sage es nochmal: $FF00, nicht $DF00 oder irgend etwas anderes).
Der Wert in $FF00 wird dadurch nicht verändert.
Der Ablauf in der Übersicht:
Aktion                       Wert $01
------                       --------
a) Parameter an den REC      $37,36,35
   übermitteln ($DF01-$DF0A)
b) spätestens jetzt: SEI
c) IO auf RAM schalten       $34,30
d) etwas in $FF00 schreiben  $34,30
   um REU zu starten
e) bei Bedarf: ROM an        $37
f) bei Bedarf: CLI
Das SEI ist natürlich für die REU unwichtig. Blenden wir aber Basic u/o Kernal aus, täte es schon Not. Und an das RAM unter IO kommen wir ohne ausgeblendetes Basic & Kernal nicht heran!
So, und nun können wir unser Programm aus dem vorigen Kapitel verbessern:
£ba $010b       ;Diese Startadresse ist $010b=SYS 267
   lda #128
£by $2c         ;Diese Startadresse ist $010e=SYS 270
   lda #129
gemeinsam:
   sta werte
   jsr $aefd    ;prüft auf Komma
   jsr $b79e    ;holt Bank nach x
   stx werte+5  ;ab in Tabelle
   ldx #$09     ;neun Werte
loop1:
   lda werte,x  ;laden und
   sta $df01,x  ;in REC speichern
   dex
   bpl loop1
   lda 1        ;Prozessorport
   pha          ;merken
   lda #$30     ;ganzer Computer: RAM
   sei          ;Interrupt sperren
   sta 1        ;RAM-Konfig. einstellen
   sta $ff00    ;Transfer starten
   pla          ;alte Speicherkonfig.
   sta 1        ;wiederherstellen
   cli          ;Interrupt freigeben
   rts          ;Programmende
werte:
£by 128,1,8,0,0,0,$ff,$f7,0,0
Ich finde, dies ist recht selbsterklärend. Beachtet die Änderungen in der Tabelle (nun $F7FF Bytes statt $C7FF) und die Änderung der Adresse 1, die nun nach der Werteübertragung an den REC stattfindet. Selbstredend haben sich auch die Kommandocodes geändert. Denn diese erst sagen dem REC, daß er auf einen Schreibzugriff bei $FF00 warten soll.

9) Das Eingemachte

Wir wissen jetzt bereits eine Menge über die REU, nicht? Wir können schon Daten an die REU übertragen und diese auch wieder zurückholen. Es gibt jedoch noch einige Spezialfunktionen, die selbst den Profis oft unbekannt sind. Und für diese ist die genaue Kenntnis der REC-Register unerläßlich.
ADRESSE FUNKTION
=======================================
$DF00   Status-Register, nur Lesen
        --------------------------
        Bit 7: 1=noch kein Interrupt
        Bit 6: 1=Transfer beendet
        Bit 5: 1=Fehler bei Verify
        Bit 4: Ramgröße
        Bit 3-0: Version (1764=0,0,0)
DIE BITS 7-5 WERDEN DURCH EINEN LESEZUGRIFF GELÖSCHT.
---------------------------------------
$DF01   Kommandoregister
        ----------------
        Bit 7: 1=Aktion beginnen
        Bit 6: <<RESERVIERT>>
        Bit 5: 1=Autoload zugelassen
        Bit 4: 1=Warte auf $FF00
        Bit 3: <<RESERVIERT>>
        Bit 2: <<RESERVIERT>>
        Bit 1-0: Art der Aktion:
                 00: STASH  C64->REU
                 01: FETCH  REU->C64
                 10: SWAP   C64<>REU
                 11: VERIFY C64--REU
---------------------------------------
$DF02   Adresse im C64 Low-Byte
---------------------------------------
$DF03                  High-Byte
---------------------------------------
$DF04   Adresse in der REU Low-Byte
---------------------------------------
$DF05                      High-Byte
---------------------------------------
$DF06   Bank in der REU
---------------------------------------
$DF07   Anzahl der Bytes  Low-Byte
---------------------------------------
$DF08                     High-Byte
---------------------------------------
$DF09   Interrupt Mask Register
        -----------------------
        Bit 7: 1=Interrupts erlauben
        Bit 6: 1=Interrupt nach Ende
                 der Aktion
        Bit 5: 1=Interrupt bei Verify-
                 Error
        Bit 4-0: <<UNBELEGT>>
---------------------------------------
$DF0A   Adress Control Register
        -----------------------
        Bit 7-6:
          00=beide Adressen hochzählen
          01=REU-Adresse nicht erhöhen
          10=C64-Adresse nicht erhöhen
          11=beide Adressen n. erhöhen
        Bit 5-0: <<UNBELEGT>>
---------------------------------------
Ich hoffe,ihr habt einen guten Drucker, damit ihr den Überblick nicht verliert. Denn was ihr da überflogen habt ist manchmal schwer verständlich, aber nur bis man es erklärt bekommt. Und anstatt hier eine weitere Tabelle zu schreiben führe ich die neuen Möglichkeiten besser anhand von Beispielen auf. a) Am Ende einer Aktion (STASH, FETCH, (SWAP, VERIFY) ist Bit 6 des Statusregisters gesetzt. Durch Lesen wird dieses (wie auch Bit 7 und 5) wieder gelöscht. Wir kennen das ja schon vom Sprite-Kollisionsregister des VIC. Bit 4 ist bei einer 1764 (AUCH EINER AUFGERÜSTETEN!) als einziges im Urzustand gesetzt. Der Wert ist also 16. Nach einer Aktion ist er dann beim ersten Lesen des Registers 80, danach wieder 16. Bei einer 1700 ist Bit 4 gelöscht. Die Bits 3-0 sollen die Version angeben. Tun sie aber wohl nicht. (1764=0,0,0) b) Wir vergleichen einen Speicherbereich im C64 mit einem in der REU. DAZU LESEN WIR ZUERST DAS STATUSREGISTER $DF00, UM ES ZURÜCKZUSETZEN! Dann setzen wir die Bits 0 und 1 des Kommandoregisters ($DF01) auf 1. Also statt z.B. 252 für STASH schreiben wir 223. Die anderen Register beschreiben wir wie gewohnt. Das Ergebnis erfahren wir in Bit 5 der Adresse $DF00: 0=Speicherinhalt ist gleich. 1=Speicherinhalt ist nicht gleich. Also
10 IFPEEK(57088)AND223 THEN 20
15 PRINT "VERIFY OK":END
20 PRINT "VERIFY ERROR BEI:";
21 PRINTPEEK((57090)+256*PEEK(57091))-1
Eine weitere wichtige Erkenntnis: Tritt ein Fehler auf, vermindern wir die Adresse in $DF02/03 um 1. So erhalten wir die Computeradresse, an der die REU bei VERIFY einen Unterschied fand. Und klar ist: Dasselbe mit $DF04-06 (wieder minus 1) ergibt die Adresse in der REU. DAS ALLES FUNKTIONIERT NICHT BEI AUTOLOAD! c) Wir AUTOLOADen uns einen.
Gemeinhin verlieren unsere Register bei einer Aktion ihren Wert. D.h., wir müssen jedesmal aufs neue alle Register beschreiben, auch wenn sich einige Werte gar nicht geändert haben (z.B. Adresse im Computer ist immer noch der Bildschirmspeicher). Hier hilft uns die AUTOLOAD-Funktion aus der Patsche. Setzen wir Bit 5 im Kommandoregister bleiben die Werte der Register $DF02-08 am Leben, auch nach der gewünschten Aktion.
Also: Bei 252 für STASH ist Bit 5 bereits gesetzt. Wollen wir keinen AUTOLOAD, schreiben wir 220. Wie wir wissen, ist bei aktivierter AUTOLOAD-Funktion die Ermittlung der Fehler-Adresse bei VERIFY nicht möglich. d) Schreiben wir ein Kommando ins Kommandoregister ($DF01), so muß Bit 7 dabei gesetzt sein, ansonsten das Kommando nicht ausgeführt wird. Also keine Kommandos kleiner 128! e) Interrupt - steh' ich drauf.
Wir können die REU am Ende einer Aktion und/oder bei Eintreten eines Fehlers einen Interrupt generieren lassen. Dazu beschreiben wir unsere Register wie gewohnt. Nur $DF09 bleibt diesmal nicht Null. Wir können schreiben:
POKE 57097,192 : Interrupt nach Ende der Aktion
POKE 57097,160 : Interrupt NUR bei VERIFY-Error
BITTE BEACHTET, DAß $DF00 VOR JEDER AKTION EINMAL AUSGELESEN WERDEN SOLLTE, UM ES ZURÜCKZUSETZEN!
Nur so können wir sicher feststellen ob ein Interrupt von der REU generiert wurde.
Unsere Interruptroutine ($0314/15) haben wir natürlich bereits verbogen
   bit $df00   ;Kommt Interrupt von REU?
   bmi vonreu  ;Ja, dann vonreu
   jmp $ea31   ;sonst Systeminterrupt
vonreu:
   bvs error   ;Bit 6=1 Verify Error!
   ...         ;Fehlerlose Aktion ist
               ;zu Ende
error:
   ...         ;Bei VERIFY trat ein
               ;Fehler auf
f) Adress Control, eine fesselnde Versuchung.
Das letzte Register bietet noch einmal ein Schmankerl. Normalerweise erhöht der REC beim Datentransfer die Zähler in $DF07/08 (Die Anzahl der zu übertragenden Bytes, die wir ja vorher setzten). Wir können nun folgendes festlegen: Der Sinn? Nun, bei gleicher Adresse im C64 können wir die REU löschen, ohne gleich ewig viel RAM im Computer vollzuschreiben. Wir bringen den Wert, der in die REU soll in eine einzige C64-Adresse, setzen die Register darauf, Anzahl der zu übertragenden Bytes auf $FFFF (eine Bank), aktivieren Autoload, fixieren den Byte-Counter in $DF0A (Moment, gleich...) und starten die Übertragung mit dem STASH-Kommando.
Nun erhöhen wir den Bank-Zeiger ($DF06) so lange bis die gesamte REU gefüllt ist. Dank AUTOLOAD brauchen wir die übrigen Register nicht neu zu beschreiben. Umgekehrt läßt sich natürlich auch (blitzschnell!) ein beliebiger Bereich im C64 mit einem Wert aus der REU füllen.
Und eine feste Adresse nur im C64? Commodore sagt dazu, daß man damit den Inhalt der REU an eine IO-Adresse übergeben kann. Z.B. einen CIA-Port, an dem eine Floppy hängt, oder irgendein Gerät am Userport. Die Anwendungsmöglichkeiten sind groß. Man muß nur ein Gerät finden, daß 1 MB pro Sekunde Datendurchsatz verkraften kann. :) Wir schreiben nach $DF0A:
POKE 57098,0    alles bewegt sich
POKE 57098,64   REU-Counter steht
POKE 57098,128  C64-Counter steht
POKE 57098,192  nichts bewegt sich
g) Zum Abschluß (Ja, wir sind fertig!) noch eine Tabelle der möglichen Kommandos für $DF01. Bedenkt, daß es durch die drei reservierten, nutzlosen Bits (Bit 6,3,2) noch viel mehr Kombinationen gibt, allerdings mit gleicher Funktionalität.
(A+ mit AUTOLOAD, A- ohne AUTOLOAD)
(F+ mit $FF00-Verzögerung, F- ohne)

KOMMANDO A+F+  A+F-  A-F+  A-F-
-------------------------------
STASH    236   252   204   220
FETCH    237   253   205   221
SWAP     238   254   206   222
VERIFY   239   255   207   223
h) Und ganz zum Schluß die Adresse, bei der man noch ungebrauchte REUs 1764 bekommen kann
(Dies ist keine Werbung und ich verdiene nichts daran):
Hier stand die Adresse. Es war die des GEOS User Clubs.
Aber die haben schon lange keine REUs mehr.

Angebote (Preise Stand August 1996)
REU 1764 256 KB   70,- DM
REU 1764 512 KB  120,- DM
REU 1764 1   MB  300,- DM
REU 1764 2   MB  700,- DM

10) Ade

Das war alles und noch mehr über die REU. Die Beispiele aus diesem Artikel sollen zu eigenen Experimenten anregen.
Viel Freude dabei wünscht euch Willcox

Gehe zu:
Seite 1 Seite 2 Seite 3 Druckerfreundliche Version Disk zum Kurs