Données N64/GC brutes avec extenmote
Contenu
Sommaire
Afin d'assurer sa compatibilité avec les logiciels déjà existants, mon
adaptateur extenmote doit convertir
les valeurs d'axes au format utilisé par la manette classique. Malheureusement, cela
occasionne une diminution de précision. Par exemple, la position du stick
gauche passe de 8 bits (N64/GC) à 6 bits (manette classique). Bref, les
manettes N64 et Gamecube utilisés via l'adaptateur ne fonctionnent pas au maximum
de leur potentiel. Pour bien des jeux, cela n'a peut-être pas d'importance, mais
pour les émulateurs N64 et Gamecube
[1], cela diminue la précision
et peut donner l'impression que les manettes ne fonctionnent pas comme
sur la console d'origine.
Afin de remédier à la situation, j'ai ajouté des fonctionnalités pour donner
accès aux données brutes reçues de la manette. Cette expérience a commencé dans
la version 1.8 et a été améliorée dans la version 1.9.
Alors comment accède-t-on à ces données?
Méthode 1: L'adaptateur concatène les données brutes à la structure de donées
manette classique standard. Les logiciels déjà existants continuent donc de fonctionner
comme d'habitude, mais les nouveaux logiciels peuvent bénéficier des données brutes
au besoin.
Méthode 2: L'adaptateur se déclare habituellement comme étant une manette
Classique. Toutefois, si une valeur de 0x64 est écrite dans le registre 0x00 après
avoir déactivé l'encryption, l'ID de l'extension variera selon le type de manette
reliée à l'adaptateur. La structure de données rapportée ne contiendra uniquement
les données brutes spécifiques à la manette utilisée.
Quels jeux/logiciels utilisent les données brutes?
À ma connaissance, pour l'instant, malheureusement aucuns. Si vous utilisez les données
brutes dans votre projet, veuillez m'en faire part que je puisse le lister ici.
[1] Je pense ici à
Devotion, un logiciel permettant de faire fonctionner
des jeux originaux pour Gamecube sur Wii et Wii U supportant la wiimote et les
accessoires comme la manette classique. Ce n'est pas vraiment un émulateur, mais
c'est exactement le genre de logiciel pouvant bénéficier d'un accès brute aux
données provenant de la manette.
Méthode 1: Données concaténées
Les premiers 6 octets sont ceux d'une manette classique (source:
http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Classic_Controller).
| Bit |
Octet | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | RX<4:3> | LX<5:0> | Données manette classique standard |
1 | RX<2:1> | LY<5:0> |
2 | RX<0> | LT<4:3> | RY<4:0> |
3 | LT<2:0> | RT<4:0> |
4 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 |
5 | BZL | BB | BY | BA | BX | BZR | BDL | BDU |
6 | 0x52 ('R') | Extension spécifique à Extenmote |
7 | Octet 0 de l'ID de la manette |
8 | Octet 1 de l'ID de la manette |
9-16 | Données spéficiques à la manette (8 octets) |
L'ID de la manette connectée à l'adaptateur est indiqué par deux octets. Cela permet d'interpréter
les données qui suivent correctement:
- 0x36,0x34 ('6','4'): Manette N64
- 0x47,0x43 ('G','C'): Manette Gamecube
- 0x53,0x46 ('S','F'): Manette SNES
- 0x46,0x43 ('F','C'): Manette NES
Rumble/Vibration: La vibration sera eventuellement supportée et sera contrôlé par des
écritures faites à l'octet 6. Non-zéro: Moteur activé, Zéro: Moteur déactivé. Notez
qu'en lecture, l'octet 6 restera à 'R' malgré les écritures.
Méthode 2: ID d'Extension
Une valeur de 0x64 doit être écrite à l'adresse 0x00 avant de lire
l'ID de l'extension. Vous pouvez vous référer à l'exemple de patch
libOGC fourni, spécifiquement à la fonction wiiuse/io.c:wiiuse_handshake_expansion();
Les ID d'extension sont les suivants:
#define EXP_ID_CODE_EXTENMOTE_N64 0xa4205264
#define EXP_ID_CODE_EXTENMOTE_GC 0xa4205247
#define EXP_ID_CODE_EXTENMOTE_SNES 0xa4205210
#define EXP_ID_CODE_EXTENMOTE_NES 0xa4205208
Lorsque l'adaptateur s'affiche sous l'une des identités listées ci-dessus, la structure
de données retournée est dans le format de la manette correspondante, et ce dès
le premier octet. Aucune autre information ou structure de compatiblité n'est présente.
Rumble/Vibration: La vibration sera eventuellement supportée et sera contrôlé par des
écritures faites à l'octet 8. Non-zéro: Moteur activé, Zéro: Moteur déactivé.
Données N64
Lorsque l'ID de l'extension ou l'ID de la manette indique qu'une manette N64 est connectée,
les données spécifiques sont tel qu'exposé ci-dessous:
| Bit |
Octet | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | A | B | Z | START | Up | Down | Left | Right |
1 | | | L | R | C-up | C-Down | C-Left | C-Right |
2 | Joystick, axe des X (signé, droite positive) |
3 | Joystick, axe des Y (signé, haut positif) |
Données GC
Lorsque l'ID de l'extension ou l'ID de la manette indique qu'une manette Gamecube est connectée,
les données spécifiques sont tel qu'exposé ci-dessous:
| Bit |
Octet | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | | | | START | Y | X | B | A |
1 | | L | R | Z | Up | Down | Right | Left |
2 | Joystick, axe des X (non-signé. Left low, Mid ~0x7F[*], Right high) |
3 | Joystick, axe des Y (non-signé. Down low, Mid ~0x7F[*], Up high) |
4 | C-stick, axe des X (non-signé. Down low, Mid ~0x7F[*], Up high) |
5 | C-stick, axe des Y (non-signé. Down low, Mid ~0x7F[*], Up high) |
6 | Levier gauche (unsigned. Released low, pressed high) |
7 | Levier droit (unsigned. Released low, pressed high) |
[*] Attention, les valeurs données ici sont à titre d'exemple seulement. Il faut tenir compte que la
position au repos n'est pas toujours exactement la même d'une manette à l'autre, mais aussi
sur la même manette (jeu mécanique, usure).
Données SNES
Lorsque l'ID de l'extension ou l'ID de la manette indique qu'une manette SNES est connectée,
les données spécifiques sont tel qu'exposé ci-dessous:
| Bit |
Octet | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | B | Y | SELECT | START | Up | Down | Left | Right |
1 | A | X | L | R |
Données NES
Lorsque l'ID de l'extension ou l'ID de la manette indique qu'une manette NES est connectée,
les données spécifiques sont tel qu'exposé ci-dessous:
| Bit |
Octet | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | A | B | SELECT | START | Up | Down | Left | Right |
Exemple
Voici un patch pour libOGC démontrant les deux méthodes d'accès:
libogc-extenmote1.9-example.diff
Et voici un petit logiciel démontrant comment accéder et utiliser les
données brutes:
raphnet_displayer2.tar.gz
Ancienne structure (v1.8)
Cette structure n'a existé que dans la version 1.8. Peu après, j'ai
décidé de changer pour inclure les boutons, couvrant ainsi la totalité
des donnés reçues.
Les 6 premiers octets se conforment à la structure de donnés normale
pour une manettes classique.
(source:
http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Classic_Controller).
Les octets supplémentaires contiennent les valeurs analogiques N64 ou GC,
dans le format tel que reçu de la manette. Les octets 12 à 14 sont une
signature permettant de détecter qu'il s'agit d'un adaptateur extemote,
mais aussi d'indiquer le type de manette. Ceci est très important
car les valeurs d'axe N64 signés et celles de la GC ne le sont pas. La
plage de valeur que peuvent prendre les axes de chaque manette diffère
également.
Un point important à ne pas perdre de vue est qu'un adaptateur peut être
bâti pour supporter plusieurs types de manettes. L'application aura donc
intérêt à continuellement surveiller les octets de signature, pas seulement
lors de l'initialisation. D'ailleurs, en raison de la gestion dynamique
du type de manette branchée, lors du branchement intial il se peut que
l'adaptateur s'affiche comme une manette classique standard mais
que quelques lectures plus tard les octets de signature changent pour
indiquer une manette N64 or GC.
Un dernier mot au sujet de la fonction vibration: Elle n'est pas supportée
pour le moment car l'électronique de l'adaptateur n'est pas adéquate. Mais
le protocole est quand même documenté dans l'espoir que cela puisse
être implémenté à l'avance et soit prêt pour un futur adaptateur.
/* | Bit |
* Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* ------+---------------+-------+----------------------------+
* 0 | RX<4:3> | LX<5:0> |
* 1 | RX<2:1> | LY<5:0> |
* 2 | RX<0> | LT<4:3> | RY<4:0> |
* 3 | LT<2:0> | RT<4:0> |
* 4 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 |
* 5 | BZL | BB | BY | BA | BX | BZR | BDL | BDU |
*
* 6 | GC Left stick/N64 stick raw X value |
* 7 | GC Left stick/N64 stick raw Y value |
* 8 | GC C-stick raw X value |
* 9 | GC C-stick raw Y value |
* 10 | GC Left shoulder raw X value |
* 11 | GC Right shoulder raw Y value |
* 12 | 0x52 ('R') |
* 13 | Controller ID byte 0 |
* 14 | Controller ID byte 1 |
* 15 | Rumble status (RW) for future use |
*
* Controller ID:
*
* 0 | 1
* -----+-----
* '6' | '4' N64 controller
* 'G' | 'C' Gamecube controller
*
* When neither a N64 nor GC controller is connected, all values from
* byte 6 up to byte 14 are 0x00.
*
* Writing at byte 15 controls the rumble motor. Rumbles on when non-zero.
*/
Ancien exemple (v1.8)
Cette structure n'a existé que dans la version 1.8. Peu après, j'ai
décidé de changer pour inclure les boutons, couvrant ainsi la totalité
des donnés reçues.
J'ai modifié ligOGC et réalisé un petit programme de test pour démontrer
cette nouvelle fonctionnalité et son utilisation.
raphnet_displayer.tar.gz
libogc-extenmote-patch.diff
Rien d'impressionnant, mais cela fait le travail. Après tout, c'est là mon premier logiciel pour Wii!