Gamepad de Sega Mega Drive y Raspberry Pi Parte 2 (seis botones finales)



¡Continúa, lo más fácil ha terminado! Y ahora a lo más difícil e interesante. Si es demasiado vago para leer, a continuación (más cerca del final del artículo) habrá un enlace al video, con el resultado y la explicación de todo, incluido lo que se describe en la primera parte. Si está interesado, siga a continuación.

En el modo de 6 botones, la lectura se produce en 4 ciclos o fases (si se expresa en el idioma del emulador). Es decir, cada 16 ms hay un cambio cíclico (4 ciclos) en el estado de la salida Seleccionar, y cada cuarto ciclo en la salida del controlador aparece el estado de los botones adicionales. A continuación hay una tabla de lectura, para mayor claridad, que debe repetirse:



Es bueno que tenga un analizador lógico, con la ayuda del cual detecté un error, que se manifestó en el hecho de que el ciclo no salió de la cuarta fase.

No voy a andar por las ramas, inmediatamente daré una lista de esta función:

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; } 

Analicemos cualquiera de las condiciones, por ejemplo:

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

Aquí se comprueba que estamos leyendo desde el primer gamepad (i == 0) , la segunda fase de lectura (fase == 1) , y la salida Seleccionar debe establecerse en 0 (Out_bits & 0x40) . Para comprender cómo funciona esto en el emulador, compilé el código en Xubuntu, y Visual Studio Code, estableciendo un montón de puntos de interrupción, ejecuté el código en modo de depuración. El resultado es una imagen tan hermosa:



En realidad, el resultado del trabajo es:


Aquí debo decir algunas palabras sobre el emulador en sí. O no lo descubrí, o esto es un error, pero el emulador se carga inicialmente en modo de 3 botones, incluso si lo contrario se indica en la configuración global. Para el 99% de los juegos esto es suficiente. Para ingresar al modo de operación con un gamepad de 6 botones, debe ingresar a la configuración y volver al juego sin cambiar nada.
Pero hay un juego que está fuera de este contexto, es Lost Vikings, los botones X, Z, MODE funcionan bien sin ningún tipo de baile.

PS

Pero puede hacerlo aún más fácil, una persona amable ya ha escrito un controlador para trabajar con un gamepad, y en un nivel muy bajo. Todavía estoy lejos de esto.

Gracias por su atencion!

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


All Articles