Sega Mega Drive和Raspberry Pi第2部分的游戏手柄(最终的六个按钮)



继续,最简单的结束! 现在到了最困难和最有趣的时期。 如果您懒于阅读,那么下面(靠近文章结尾)将提供指向该视频的链接,其中包括所有内容的结果和解释,包括第一部分中的描述。 如果您有兴趣,请继续。

在6键模式下,读取以4个周期或阶段进行(如果以仿真器的语言表示)。 即,每16毫秒,选择输出的状态就会有一个周期性(4个周期)的变化,并且控制器输出上的每第四个周期都会出现附加按钮的状态。 为了清楚起见,以下是阅读表,必须重复进行:



最好有一个逻辑分析仪,在这个分析仪的帮助下,我发现了一个错误,这个错误的体现是周期没有退出第四阶段。

我不会在丛林中奔波,我将立即列出此功能:

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

让我们分析任何条件,例如:

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

在此检查我们正在从第一个游戏手柄(i == 0) ,第二个阅读阶段(phase == 1)进行读取,并且Select输出必须设置为0 !(Out_bits&0x40) 。 为了了解它在模拟器中的工作原理,我在Xubuntu上编译了代码,并设置了多个断点,然后在调试模式下运行了Visual Studio Code。 结果是一幅美丽的图画:



实际上,工作的结果是:


在这里,我必须对仿真器本身说几句话。 我可能没有弄清楚,或者这是一个错误,但是仿真器最初以3按钮模式加载,即使全局设置中指示相反。 对于99%的游戏来说,这就足够了。 为了使用6键游戏手柄进入操作模式,您需要进入设置并返回游戏,而无需进行任何更改。
但是有一种游戏不在这种背景下,那就是《迷失的维京人》,X,Z和MODE按钮可以在其中正常工作而不会跳舞。

聚苯乙烯

但是您可以做得更轻松,因为一个人已经编写了一个用于玩游戏手柄的驱动程序 ,而且级别很低。 我离这还很远。

感谢您的关注!

Source: https://habr.com/ru/post/zh-CN435094/


All Articles