12.15 Jaguar Pad am Falcon Das Jaguar Pad am Falcon
An erster Stelle finden Sie Beispiele dafür wie man das
JaguarPad am Atari Falcon per Software abfragt. Die Beispiele sind
für PureC
JAGUAR.PRJ 1: jaguar.tos 2: 3 .C [ -Y ] 4: .L [ -Y -L ] 5: 6: = 7: 8: pcstart.o 9: 10: main.c 11: jagstick.c 12: 13: PCSTDLIB.LIB 14: PCTOSLIB.LIB 1: /* MAIN.C 1: */ 2: */Testprogramm für Jaguar Controller-Abfrage 3: */ 4: 5: #include <stdlib.h> 6: #include <screen.h> 7: #include <stdio.h> 8: #include "jagstick.h" 9: 10: #define PORT 1 /* Port l(B) wird abgefragt 11: 12: void main(void) 13: { 14: for(;;) 15: { 16: req_jagpads(); 17: Cur_home(); 18: if (jpstatus[PORT].up) printf("U"); 19: if (jpstatus[PORT].down) printf("D"); 20: if (jpstatus[PORT].left) printf("L"); 21: if (jpstatus[PORT].right) printf("R"); 22: if (jpstatus[PORT].fire-a) printf("A"); 23: if (jpstatus[PORT].fire-b) printf("B"); 24: if (jpstatus[PORT).fire-c) printf("C"); 25: if (jpstatus[PORT).k0) printf("0"); 26: if (jpstatus[PORT).kl) printf("1"); 27: if (jpstatus[PORT].k2) printf("2"); 28: if (jpstatus[PORT].k3) printf("3"); 29: if (jpstatus[PORT].k4) printf ("4"); 30: if (jpstatus[PORT].k5) printf("5"); 31: if (jpstatus[PORT].k6) printf ("6"); 32: if (jpstatus[PORT].k7) printf("7") ; 33: if (jpstatus[PORT].k8) printf("8"); 34: if (jpstatus[PORT].k9) printf("9"); 35: if (jpstatus[PORT].ks) printf("*"); 36: if (jpstatus[PORT].kr) printf ("#"); 37: if (jpstatus[PORT].pause) printf("P"); 38: printf(" "); 39: if (jpstatus[PORT].option) break; 40: } 41: 42: exit(0); JAGSTICK.H 1: /* 2: /* Headerfile fürs Abfragen der Jaguarjoypads 3: /* 4: 5: typedef struct 6: { 7: int up,down,left,right : 1; /* Zustände der Richtungen */ 8: int fire_a,fire_b,fire_c : 1; /* Zustände der Feuerknöpfe */ 9: int pause,option : 1; /* Zustände von Option/Feuer */ 10: int k1,k2,k3,k4,k5,k6,k7,k8,k9,k0,kr,ks: 1; 11: /* Zustände der Tastatur am JoyPad */ 12: /* kr = # und ks = * */ 13: } JAGPAD; 14: 15: extern JAGPAD jpstatus[2]; 16: JAGSTICK.C 1: /* 2: /* Routinen zum Abfragen der Jaguarjoypads 3: /* 4: 5: #include <tos.h> 6: #include "jagstick.h" 7: 8: #define NULL (void*)0| 9: 10: #define adr(a) *((int *)(a)) 11: 12: 13: #define bitwert(a) (l<<a) /* liefert 2^a */ 14: #define EXREGO Oxffff9200| 15: #define EXREG1 Oxffff9202| 16: #define test(var 17: bit)((var&bitwert(bit))==0?-1:0) 18: /* liefert -1 19: wenn das Bit bit 20: in der Variable var 21: gelöscht ist */ 22: 23: JAGPAD jpstatus[2]; 24: /* Hier wird das Ergebnis gespeichert */ 25: void req_jagpads(void) 26: { 27: int r0,rl; 28: 29: long oss; 30: 31: oss=Super(0|); /* SuperVisorMode an */ 33: adr(EXREG1)=~(bitwert(0)+bitwert(4)); /* $ffff9202=NOT(2^0+2^4) */ 34: r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */ 35: r1=adr(EXREG1);/* rl = Inhalt von $ffff9202 */ 36: 37: jpstatus[0].up=test(r1,8); 38: 39: jpstatus[0].down=test(r1,9); 40: 41: jpstatus[0].ieft=test(r1,10); 42: 43: jpstatus[0].right=test(r1,11); 44: 45: jpstatus[0].pause=test(r0,0); 46: 47: jpstatus[0].fire_a=test(r0,1); 48: 49: jpstatus[l].up=test(r1,12) 50: 51: jpstatus[l].down=test(r1,13); 52: 53: jpstatus[l].left=test(r1,14); 54: 55: jpstatus[l].right=test(r1,15); 56: 57: jpstatus[l].pause=test(r0,2); 58: 59: jpstatus[l].fire_a=test(r0,3); 60: 61: 62: adr(EXREG1)=~(bitwert(l)+bitwert(5)); /* $ffff9202=NOT(2^1+2^5) */ 63: r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */ 64: r1=adr(EXREG1);/* rl = Inhalt von $ffff9202 */ 65: 66: jpstatus[0].ks=test(r1,8); 67: 68: jpstatus[0].k7=test(r1,9); 69: 70: jpstatus[0].k4=test(r1,10); 71: 72: jpstatus[0].kl=test(r1,11); 74: jpstatus[0].fire_b=test(r0,1); 75: 76: jpstatus[l].ks=test(r1,12); 77: 78: jpstatus[l].k7=test(r1,13); 79: 80: jpstatus[l]. k4 = test(rl, 1 4); 81: 82: jpstatus[1]. kl =test(r1,15); 83: 84: jpstatus[l]. fire_b = test(r0,3); 85: 86: 87: adr(EXREG1) =~(bitwert(2) + bitwert(6)); /* $ffff9202=NOT(2^2+2^6) */ 88: r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */ 89: r1=adr(EXREG1);/* r1 = Inhalt von $ffff9202 */ 90: 91: jpstatus[0].k0=test(r1,8); 92: 93: jpstatus[0].k8=test(r1,9); 94: 95: jpstatus[0].k5=test(r1,10); 96: 97: jpstatus[0].k2=test(r1,11); 98: 99: jpstatus[0].fire-c=test(r0,1); 100: 101: jpstatus[l].k0=test(r1,12); 102: 103: jpstatus[l].k8=test(r1,13); 104: 105: jpstatus[l].k5=test(r1,14); 106: 107: jpstatuslll.k2=test(r1,15); 108: 109: jpstatus[l].fire_c=test(r0,3); 110: 111: 112: adr(EXREG1)=~(bitwert(3)+bitwert(7));/* $ffff9202=NOT(22+26) */ 113: r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */ 114: r1=adr(EXREG1); 115: /* rl = Inhalt von $ffff9202 */ 116: jpstatus[0].kr=test(r1,8); 117: 118: jpstatus[0].k9=test(r1,9); 119: 120: jpstatus[0].k6=test(r1,10); 121: 122: jpstatus[0].k3=test(r1,11); 123: 124: jpstatus[0].option=test(r0,1); 125: 126: jpstatus[l].kr=test(r1,12); 127: 128: jpstatus[l].k9=test(r1,13); 129: 130: jpstatus[l].k6=test(r1,14); 131: 132: jpstatus[l].k3=test(r1,15); 133: jpstatus[l].option=test(r0,3); 134: Super((void*)oss); 135: /* SuperVisorMode aus */
Wie frage ich den Jaguar-Controller am Falcon030 / STE ab?
Daß man den Jaguar-Controler in irgend einer Form auch an
den Falcon oder STE anschließen kann ist naheliegend. Wie die
Abfrage aber konkret geschehen muß, wird hier kurz
erläutert.
Jeder, der einen Jaguar und einen Falcon030 bzw. STE besitzt wird
festgestellt haben, daß die analogen Joyports vollkommen
identisch sind. Wie man den Computern beibringt, den Controller auch
auszuwerten, soll dieser Artikel zeigen. Nun, zunächst einmal ist
man ja versucht, einfach diverse Spiele, die den erweiterten Joyport
nutzten, auszuprobieren. Doch leider muß man schnell
feststellen, daß zwar irgendwelche Signale vom Computer
empfangen werden, so daß der Protagonist des entsprechenden
Spielchens entweder an Orientierungslosigkeit leidet und rennt oder
ziellos umherrennt und nicht dort hin, wohin man drückt, oder er
springt nicht, weil der gedrückte Feuerknopf nicht als solcher
erkannt wird. Also Fehlanzeige?
Überlegt und nachgezählt...
Der Joyport hat ja nur 15 Pins, obwohl der Controller 21
Schaltelemente hat. Nun, es muß also einen Trick geben. Da war
doch noch etwas wie - klar, man kann die ext. Joyports als Ein- und
Ausgänge benutzen. Damit kann man dann so etwas wie eine Matrix
implementieren, bei der man einfach dem Controller sendet, welchen
Status der Tasten man gerne hätte - und zurück bekommt man
einen entsprechenden Code. Genauso hat sich Atari das auch gedacht.
Das Ganze ist wirklich ähnlich wie die Sound-/DMA-Matrix
geschaltet. Matrizen ziehen sich also durch das gesamte Innenleben des
Falcon. Kommen wir zum Wesentlichen.
$FFFF9200 [R/W] word ext. Joystick Fire Buttons (Bits 0-3)
$FFFF9202 [R/W] word ext. Joystick Directions (Bits 0-15)
Diese wurden somit umdefiniert. $FFFF9200 wird zwar weiterhin
für die Firebuttons verwendet, jedoch kommen die Buttons
"Option" und "Pause" hinzu. Also muß
müssen hier fünf Buttons mit 2 Bits codiert sein. Auch die
restlichen 16 Schalter im Jaguar Controller sind mit jeweils nur 4 Bit
im Register $FFFF9202 geschaltet. Der grobe Ablauf des Abfragens der
JoyPorts bzw. des Controllers ist jetzt also in etwa wie folgt:
1. Abzufragende Leitungen in Register $FFFF9202 schreiben
Dabei ist allerdings zu beachten, daß die entsprechend
angeführten Register low-aktiv sind, d.h. ein gelöschtes Bit
bedeutet "gedrückt" bzw. "ist abzufragen".
Kommen wir also zu der mächtigen Matrix, um die sich alles dreht.
Um z.B. den Status von Feuerknopf B aus JoyPort B zu ermitteln,
sendet man auf $FFFF9202 den Wert NOT(2^7)=$FF7F (d.h. man schreibt
den Wert in das entsprechende Register), liest dann den Wert von
$FFFF9200 aus, und überprüft, ob das Bit 5 mit der
Wertigkeit 2^5 gelöscht ist. Wenn dies der Fall ist, ist der
Feuerknopf gedrückt.
Analog gilt für ein anderes Beispiel folgendes (diejenigen,
die es begriffen haben, können diesen Absatz überspringen):
Angenommen, wir wollen wissen, ob an Port A das Pad noch oben
gedrückt ist. Senden wir also auf $FFFF9200 den Wert
NOT(2^0)=$FFFE, dann fragen wir das Register $FFFF9200 auf
Gelöschtheit des Bits 8 ab. Ist es gelöscht, so wurde nach
oben gedrückt.
Daß die gesamten Zugriffe auf die Hardware-Register im
"Supervisormodus" zu erfolgen haben, sollte wohl klar sein.
Man sieht, es sind 4 Abfragen für das gesamte JoyPad notwendig,
aber das ist es doch wert, oder?
Noch eine Bitte an alte, die diese großartigen Pads jetzt
supporten wollen: Bitte macht Eure Sache konfigurierbar, so daß
Video-Erweiterungsbesitzer (wie ich) auswählen können, in
welchen Port sie den Joystick stecken wollen, zumal es auch andere
Erweiterungen gibt, die bestimmte Paddleports brauchen, z.B mit
Screenblaster oder einer SpeedResoloution Karte.
Der abgedruckte Sourcecode soll die ganze Vorgehensweise noch
etwas durchleuchten. Er wurde mit Pure C erstellt, und es wurde darauf
geachtet, daß keine speziellen Befehle, die eine Portierung in
andere Sprachen erschweren würden, verwendet wurden.
Carsten Tolkmit
Abbildung 1 - Innenschaltung des Jaguar Pads
Copyright © Robert Schaffner (support@doitarchive.de) Letzte Aktualisierung am 23. Dezember 2003 |