Manette de jeu de Sega Mega Drive et Raspberry Pi Partie 2 (six derniers boutons)



Continuez, le plus simple est terminé! Et maintenant, le plus difficile et le plus intéressant. Si vous êtes trop paresseux pour lire, alors ci-dessous (plus près de la fin de l'article) il y aura un lien vers la vidéo, avec le résultat et l'explication de tout, y compris ce qui est décrit dans la première partie. Si vous êtes intéressé, veuillez suivre ensuite.

En mode 6 boutons, la lecture se déroule en 4 cycles ou phases (si exprimée dans la langue de l'émulateur). Autrement dit, toutes les 16 ms, il y a un changement cyclique (4 cycles) dans l'état de la sortie Select, et tous les quatre cycles à la sortie du contrôleur apparaissent l'état des boutons supplémentaires. Voici un tableau de lecture, pour plus de clarté, qui doit être répété:



C'est bien d'avoir un analyseur logique, avec l'aide duquel j'ai attrapé un bug, qui s'est manifesté par le fait que le cycle n'est pas sorti de la quatrième phase.

Je ne vais pas tourner autour du pot, je vais tout de suite vous donner une liste de cette fonction:

static u32 read_pad_6btn(int i, u32 out_bits) { u32 pad = ~PicoIn.padInt[i]; // Get inverse of pad MXYZ SACB RLDU int phase = Pico.m.padTHPhase[i]; u32 value = 0; if (i == 0 && phase == 0 && (out_bits & 0x40)) // TH { digitalWrite (Select, HIGH); delayMicroseconds (30); 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 && phase == 0 && !(out_bits & 0x40)) // TH { digitalWrite (Select, LOW); delayMicroseconds (30); 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 digitalWrite (Select, HIGH); delayMicroseconds (10); } if (i == 0 && phase == 1 && (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 && phase == 1 && !(out_bits & 0x40)) // TH { digitalWrite (Select, LOW); delayMicroseconds (30); 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 digitalWrite (Select, HIGH); delayMicroseconds (10); } if (i == 0 && phase == 2 && (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 && phase == 2 && !(out_bits & 0x40)) { digitalWrite (Select, LOW); delayMicroseconds (30); value ^= digitalRead(Data4) << 4; //read A button value ^= digitalRead(Data5) << 5; //read Start button digitalWrite (Select, HIGH); delayMicroseconds (10); } if (i == 0 && phase == 3 && (out_bits & 0x40)) { digitalWrite (Select, HIGH); delayMicroseconds (20); value ^= digitalRead(Data0) << 0; //read Z button value ^= digitalRead(Data1) << 1; //read Y button value ^= digitalRead(Data2) << 2; //read X button value ^= digitalRead(Data3) << 3; //read MODE button value ^= digitalRead(Data4) << 4; //read B button value ^= digitalRead(Data5) << 5; //read C button } if (i == 0 && phase == 3 && !(out_bits & 0x40)) { digitalWrite (Select, LOW); delayMicroseconds (30); value ^= digitalRead(Data4) << 4; //read A button value ^= digitalRead(Data5) << 5; //read Start button digitalWrite (Select, HIGH); delayMicroseconds (10); value |= 0x0f; } if (i == 1 && phase == 0 && (out_bits & 0x40)) // TH { value = pad & 0x3f; // ?1CB RLDU } if (i == 1 && phase == 0 && !(out_bits & 0x40)) // TH { value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU } if (i == 1 && phase == 1 && (out_bits & 0x40)) // TH { value = pad & 0x3f; // ?1CB RLDU } if (i == 1 && phase == 1 && !(out_bits & 0x40)) // TH { value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU } if (i == 1 && phase == 2 && (out_bits & 0x40)) // TH { value = pad & 0x3f; // ?1CB RLDU } if (i == 1 && phase == 2 && !(out_bits & 0x40)) { value = (pad & 0xc0) >> 2; // ?0SA 0000 } if(i == 1 && phase == 3 && (out_bits & 0x40)) { return (pad & 0x30) | ((pad >> 8) & 0xf); // ?1CB MXYZ } if(i == 1 && phase == 3 && !(out_bits & 0x40)) { return ((pad & 0xc0) >> 2) | 0x0f; // ?0SA 1111 } return value; } 

Analysons l'une des conditions, par exemple:

 if (i == 0 && phase == 1 && !(out_bits & 0x40)) // TH 

Ici, il est vérifié que nous lisons à partir du premier gamepad (i == 0) , de la deuxième phase de lecture (phase == 1) , et la sortie Select doit être définie sur 0 ! (Out_bits & 0x40) . Pour comprendre comment cela fonctionne dans l'émulateur, j'ai compilé le code sur Xubuntu et Visual Studio Code, définissant un tas de points d'arrêt, a exécuté le code en mode débogage. Le résultat est une si belle image:



En fait, le résultat du travail est:


Ici, je dois dire quelques mots sur l'émulateur lui-même. Soit je ne l'ai pas compris, soit c'est un bug, mais l'émulateur se charge initialement en mode 3 boutons, même si le contraire est indiqué dans les paramètres globaux. Pour 99% des jeux, cela suffit. Pour entrer dans le mode de fonctionnement avec une manette de jeu à 6 boutons, vous devez entrer dans les paramètres et revenir dans le jeu sans rien changer.
Mais il y a un jeu qui est en dehors de ce contexte, c'est Lost Vikings, les boutons X, Z, MODE fonctionnent bien sans danser.

PS

Mais vous pouvez le faire encore plus facilement, une personne gentille a déjà écrit un pilote pour travailler avec une manette de jeu, et à un niveau très bas. J'en suis encore loin.

Merci de votre attention!

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


All Articles