Gamepad dari Sega Mega Drive dan Raspberry Pi Part 2 (enam tombol terakhir)



Lanjutkan, yang termudah selesai! Dan sekarang untuk yang paling sulit dan menarik. Jika Anda terlalu malas untuk membaca, maka di bawah ini (lebih dekat ke akhir artikel) akan ada tautan ke video, dengan hasil dan penjelasan semuanya, termasuk apa yang dijelaskan di bagian pertama. Jika Anda tertarik, silakan ikuti selanjutnya.

Dalam mode 6-tombol, pembacaan terjadi dalam 4 siklus atau fase (jika dinyatakan dalam bahasa emulator). Artinya, setiap 16 ms ada perubahan siklik (4 siklus) dalam status output Pilih, dan setiap siklus keempat pada output controller muncul keadaan tombol tambahan. Di bawah ini adalah bagan bacaan, untuk kejelasan, yang harus diulang:



Adalah baik bahwa saya memiliki penganalisa logika, dengan bantuan yang saya tangkap bug, yang memanifestasikan dirinya dalam kenyataan bahwa siklus tidak keluar dari fase keempat.

Saya tidak akan bertele-tele, saya akan segera memberikan daftar fungsi ini:

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

Mari kita menganalisis salah satu kondisi, misalnya:

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

Di sini diperiksa bahwa kita membaca dari gamepad pertama (i == 0) , fase membaca kedua (fase == 1) , dan output Select harus diatur ke 0 ! (Out_bits & 0x40) . Untuk memahami bagaimana ini bekerja di emulator, saya mengkompilasi kode pada Xubuntu, dan Visual Studio Code, mengatur sekelompok breakpoint, menjalankan kode dalam mode debug. Hasilnya adalah gambar yang sangat indah:



Sebenarnya, hasil pekerjaannya adalah:


Di sini saya harus mengatakan beberapa kata tentang emulator itu sendiri. Entah saya tidak mengetahuinya, atau ini adalah bug, tetapi emulator pada awalnya memuat dalam mode 3 tombol, bahkan jika yang sebaliknya ditunjukkan dalam pengaturan global. Untuk 99% game, ini sudah cukup. Untuk memasuki mode operasi dengan gamepad 6 tombol, Anda harus masuk ke pengaturan dan kembali ke permainan tanpa mengubah apa pun.
Tetapi ada satu permainan yang berada di luar konteks ini, yaitu Lost Vikings, tombol X, Z, MODE bekerja dengan baik di dalamnya tanpa menari.

PS

Tetapi Anda dapat melakukannya dengan lebih mudah, seseorang yang baik hati telah menulis driver untuk bekerja dengan gamepad, dan pada level yang sangat rendah. Saya masih jauh dari ini.

Terima kasih atas perhatian anda!

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


All Articles