Manette de jeu de Sega Mega Drive et Raspberry Pi Part 1 (préparatoire et à trois boutons)

L'automne est arrivé , le chou a fleuri , c'est presque le milieu de l'hiver, et je viens de finir de jouer avec. Mais quand même, le moment est venu de jouer quelque chose de vieux, au son d’une tempête de neige à l’extérieur de la fenêtre, par exemple Sonic ou le ver de Jim. Au bas de l'article se trouve une vidéo avec des résultats préliminaires.



Si vous avez joué à des jeux SMD sur l'émulateur, vous avez probablement remarqué que la manette de jeu la plus pratique pour ces jeux est la manette native de SMD. Pour la plupart des autres consoles, lorsque vous jouez sur l'émulateur, il est tout à fait possible de se débrouiller avec la même manette de jeu Xbox ou Logitech, la norme a été formée vers la fin des années 90. Mais jusqu'à la fin des années 90, tout le monde s'est égaré comme il le pouvait.

Il n'est pas difficile d'acheter une manette de jeu chez SMD, et en règle générale, vous pouvez l'acheter là où les clones des consoles elles-mêmes sont vendus, à un prix assez abordable, environ 300 roubles.

Comme auparavant, j'ai organisé la connexion au Raspberry pi à l'aide d'un câble USB du boîtier hors service et du connecteur DB-9 de papa. Et GPIO a peint les conclusions du programme. La manette de jeu fonctionne très bien à partir de 3,3 Volts.



Comme toujours, la question s'est posée de choisir un émulateur, et la meilleure option était l'émulateur - Picodrive, il est optimisé pour ARM, bien structuré, et si je comprends bien, il fait partie de l'assemblage RetroPi. Mais avec l'assemblée j'ai dû bricoler un peu. Le code source est situé sur le service Github, à cette adresse .

Pour construire, nous avons besoin de 3 composants de succès à partir du référentiel de l'auteur de l'émulateur:

  1. Émulateur Picodrive lui-même;
  2. Émulateur CPU - cyclone68000;
  3. et FrontEnd - Libpicofe.

Maintenant, tout cela doit être mis en place correctement. Décompressez ou ne décompressez pas Picodrive , selon la façon dont vous l'avez téléchargé. Ouvrez maintenant le répertoire avec cyclone68000 , son contenu doit être copié dans le répertoire:

/ /picodrive-master/cpu/cyclone 

Vous devez également gérer le contenu du répertoire Libpicofe , son contenu est copié dans le répertoire:

 / /picodrive-master/platform/libpicofe 

Vous devez maintenant préparer l'assemblage:
faire la configuration

 sudo ./configure 

Une fois la configuration terminée, un fichier sera créé - config.mak , vous devrez y trouver et modifier certaines lignes. Voici le résultat final:

 AS = arm-linux-as LDLIBS += -L/usr/lib/arm-linux-gnueabihf -lSDL -lasound -lpng -lm -lz -lwiringPi ARCH = arm PLATFORM = rpi1 

Ensuite, vous devez modifier le fichier - config.h . Il se trouve dans le répertoire:

 / /picodrive-master/cpu/cyclone 

Dans ce document, vous devez mettre ceux dans les variables:

 #define HAVE_ARMv6 1 #define CYCLONE_FOR_GENESIS 1 

Et maintenant la partie logicielle

Comme toujours, il était nécessaire de trouver un endroit où les informations sur les boutons enfoncés sont traitées, comprendre et pardonner le code et le remplacer.

Sans attraper suspense, je dirai tout de suite que les fichiers que vous recherchez se trouvent dans le répertoire:

 / /picodrive-master/pico/ 

Ici, nous sommes intéressés par 3 fichiers - pico.c , memory.c , memory.h . Vous pouvez probablement faire avec un plus petit nombre, et tout entasser en un, mais cela m'a semblé plus facile.
Et donc, dans le fichier pico.c, j'initialise la bibliothèque et configure d'abord les broches GPIO.

Je donnerai immédiatement une partie de l'en-tête du fichier:

 #include "pico_int.h" #include "sound/ym2612.h" #include <wiringPi.h> #define Data0 3 #define Data1 4 #define Data2 5 #define Data3 12 #define Data4 13 #define Data5 10 #define Select 6 struct Pico Pico; struct PicoMem PicoMem; PicoInterface PicoIn; 

Comme vous pouvez le voir, l'en-tête de la bibliothèque WiringPi est défini et les définitions sont annoncées, ce qui apparaîtra un peu plus bas. Eh bien, par exemple, maintenant dans la fonction void PicoInit (void) :

 void PicoInit(void) { ... ... PicoDraw2Init(); wiringPiSetup (); pinMode (Select, OUTPUT); pinMode (Data0, INPUT); pinMode (Data1, INPUT); pinMode (Data2, INPUT); pinMode (Data3, INPUT); pinMode (Data4, INPUT); pinMode (Data5, INPUT); digitalWrite (Select, HIGH); } 

Il s'agit d'une fonction d'initialisation de la mémoire de l'émulateur (en quelque sorte). Et c'est là que j'ai inséré tous les paramètres des broches GPIO. Voici le brochage du connecteur DB-9 .

Ici, je dois dire que la manette de jeu a 6 contacts d'information (Data0 ... Data5), un contrôleur (Selest) et l'alimentation.

Ensuite, nous avons les mêmes définitions - définir, nous devons le répéter à nouveau. Cela peut être fait à la fois dans memory.h et dans memory.c . J'ai choisi la première option. Cela n'a aucun sens de l'énumérer.

Nous arrivons donc au plus intéressant - le fichier memory.c . Il a 2 fonctions aux noms éloquents:

 static u32 read_pad_3btn(int i, u32 out_bits) static u32 read_pad_6btn(int i, u32 out_bits) 

Les noms semblent suggérer discrètement la lecture de l'état des manettes de jeu à 3 et 6 boutons.

Ici, il convient de préciser que toute manette de jeu à 6 boutons peut fonctionner comme 3 boutons. Et la partie du lion des jeux fonctionne exactement avec ce mode de la manette de jeu. Dans ce mode, une fois toutes les 16 millisecondes, l'état de la sortie Select change. Lorsque Select = 0, les valeurs des boutons sont lues - UP, DOWN, A, Start. Lorsque Select = 1, l'état des boutons est lu - HAUT, BAS, GAUCHE, DROITE, B, C. Voici un exemple de fonctionnement de ce mode.



Immédiatement, je donnerai une liste de cette fonction avec des modifications:

 static u32 read_pad_3btn(int i, u32 out_bits) { u32 pad = ~PicoIn.padInt[i]; // Get inverse of pad MXYZ SACB RLDU u32 value = 0; if (i == 0 && (out_bits & 0x40)) // TH { digitalWrite (Select, HIGH); delayMicroseconds (20); value ^= digitalRead(Data0) << 0; //read UP button value ^= digitalRead(Data1) << 1; //read DOWN button value ^= digitalRead(Data2) << 2; //read LEFT button value ^= digitalRead(Data3) << 3; //read RIGHT button value ^= digitalRead(Data4) << 4; //read B button value ^= digitalRead(Data5) << 5; //read C button } if (i == 0 && !(out_bits & 0x40)) { digitalWrite (Select, LOW); delayMicroseconds (20); value ^= digitalRead(Data0) << 0; //read UP button value ^= digitalRead(Data1) << 1; //read DOWN button value ^= digitalRead(Data4) << 4; //read A button value ^= digitalRead(Data5) << 5; //read Start button } if (i == 1 && (out_bits & 0x40))// TH { value = pad & 0x3f; // ?1CB RLDU } if (i == 1 && !(out_bits & 0x40)) { value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU } return value; } 

Ici, i est le numéro de la manette de jeu, et l'expression if (out_bits & 0x40) // TH est juste responsable de l'état de la sortie Select. Il est à noter que dans l'émulateur, l'état des boutons est donné sous la même forme que dans la console. Bouton enfoncé = 0.

Voici le résultat du travail:


Suite dans la prochaine série, Pip-Pip-Pip

Source: https://habr.com/ru/post/fr423565/


All Articles