1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Zuiki製のワンハンドルコントローラを使ってエミュレータ上の電車でGO!(PS1版)を遊ぶ

Last updated at Posted at 2024-03-17

某所に書いたメモ書きをちょっとだけ書き換えてコピペ。

とにかく早く遊びたい人向け

https://github.com/sonarAIT/ZuikiController2PS1DenshaDeGo/tree/main
これをクローンしてmake runすれば動きます。エミュレーターのキーマップだけ以下の通りにしてください。あと、Windowsにおけるキーボードの設定で、Microsoft IME(日本語+英語)ではなくUSキーボード(英語のみ)を使用してください。

あと、エミュレータとかじゃなくて普通にWindows版の電車でGO!で遊びたい人は、以下のサイトを見ると幸せになれると思います。
https://autotraintas.hariko.com/

基本方針

  • Zuiki製のワンハンドルコントローラ(新しい)で電車でGO!(PS1版)を遊ぶ。
  • 電車でGO!(PS1版)にも専用コントローラが存在する。その専用コントローラを、Zuiki製のワンハンドルコントローラで代替する形で実装を行う。
  • 電車でGO!(PS1版)の専用コントローラは、あくまでコントローラに過ぎない。専用コントローラは、複雑なコマンドをPS1に送り続けるための装置であると言える。
    • ゲーム側で専用コントローラの接続を認識するためのコマンドが存在し、それが入力されているか否かで、通常のコントローラか専用のコントローラかを識別しているらしい。
    • 物凄く極端なことを言えば、実機の通常のコントローラで同じ操作をすれば、専用コントローラと誤認識させた状態でプレイすることができる。
    • この仕組みを利用して、専用コントローラが接続されているかのように誤認識させる形で実装を行う。
  • Zuiki製のコントローラから入力を受け取り、それを電車でGO!が認識できる形に変換し、エミュレータに入力すれば、Zuiki製のコントローラでエミュレータ上の電車でGO!(PS1版)を遊ぶことができる。
    • エミュレータへの入力は、単にマクロによるキーボード入力で行う。

モジュール設計

  • 入力モジュール
    • Zuiki製ワンハンドルコントローラからの入力を受け取る。
  • 変換モジュール
    • 変換を実行する。変換に必要な状態があれば、保持する。
  • 出力モジュール
    • キーボード入力を実際に実行する。

コントローラを変えるときは、入力モジュールと変換モジュールを書き換えれば良い。
出力先のエミュレータ・ゲームを変える時は、変換モジュールと出力モジュールを書き換えれば良い。

Zuiki製のコントローラーから入力を受け取る

https://qiita.com/10_tenk/items/973d78eff7bb3d9de3a2
この記事にまんま書いてある。

エミュレータにマクロによるキーボード入力を行う

「複雑なコマンド」を入力して、実際に電車でGO!をPythonから操作できるかどうかを確かめる。
「複雑なコマンド」は以下のリポジトリから確認できる。
https://github.com/KeKe115/Densya_de_go

/ left down right triangle r1 l1 r2 l2
P5 0 1 0 1 1 0 1 1
P4 1 1 0 0 1 0 1 1
P3 1 1 0 1 1 0 1 1
P2 0 1 1 0 1 0 1 1
P1 0 1 1 1 1 0 1 1
N 1 1 1 0 1 0 1 1
B1 d d d d 1 1 1 0
B2 d d d d 1 0 1 0
B3 d d d d 0 1 1 1
B4 d d d d 0 0 1 1
B5 d d d d 0 1 1 0
B6 d d d d 0 0 1 0
B7 d d d d 1 1 0 1
B8 d d d d 1 0 0 1
EB d d d d 0 0 0 0

1は押下した状態。0は押下していない状態。dはどうでもいい(ドント・ケアの意味)。

なお、以下のツイートから上キーを押しっぱなしにすることが明らかになった。
https://twitter.com/wakamesoba98/status/1208039666076680193

つまり、マスコンを5に入れたいなら、上ボタン, 下ボタン, △ボタン, R1ボタン, R2ボタン, L2ボタンを同時押しすれば良い。

エミュレータのキーマッピングが以下の通りになっていることを前提として、コードを書いてみる。

 class PS1DengoKeyPresser:
     def __init__(self):
         self.NOTCH2BITS = {
             "P5": 0b01011011,
             "P4": 0b11001011,
             "P3": 0b11011011,
             "P2": 0b01101011,
             "P1": 0b01111011,
             "N": 0b11101011,
             "B1": 0b11101110,
             "B2": 0b11101010,
             "B3": 0b11100111,
             "B4": 0b11100011,
             "B5": 0b11100110,
             "B6": 0b11100010,
             "B7": 0b11101101,
             "B8": 0b11101001,
             "EB": 0b11100000,
         }
         self.BIT2KEY = {
             0: "2",
             1: "0",
             2: "1",
             3: "9",
             4: "i",
             5: "d",
             6: "s",
             7: "a",
         }
 
    def press(self, notch):
        bits = self.NOTCH2BITS[notch]
        pyautogui.keyDown("w")
        print(notch)
        for i in range(8):
            if bits & (1 << i):
                pyautogui.keyDown(self.BIT2KEY[i])
            else:
                pyautogui.keyUp(self.BIT2KEY[i])

入力モジュールからnotchの情報をpress関数に渡すと、対応した「複雑なコマンド」を入力するキー入力が実行される。

ボタン動作を追加

https://qiita.com/10_tenk/items/f21203d7c55fd3b19d62
これを参考にする。
マッピングは以下の通り。

button idx key
a 0 l
b 1 k
y 3 j
- 4 b
+ 6 n

Zuikiコントローラーによるボタン入力がidx(数字)で得られるので、それをキーボード入力に変換する。

実装

ぶっちゃけ、実装した結果は以下のコードを見てもらえればよい。
https://github.com/sonarAIT/ZuikiController2PS1DenshaDeGo/blob/main/main.py

これだけだとあんまりなので、各モジュールについて必要最低限の解説を書く。

  • ZuikiControllerInputGetter
    • Zuikiのコントローラーから入力を受け取り、現在のノッチ、ボタン入力を取得する。
    • getNotch
      • 現在のノッチを取得し、P5, EBのような形式でreturnする。
    • getButtons
      • 現在のボタン入力を取得し、ボタンのidxでreturnする。
  • Zuiki2PS1Dengo
    • Zuikiのノッチ・ボタン入力を、PS1の電車でGO専用の「複雑なコマンド」に変換する。
    • getKeys
      • P5, EBなどのZuikiコントローラーによるノッチ入力とボタン入力から、対応するキーボード入力をreturnする。押すキーと、離すキーをそれぞれ求める。
  • PS1DengoKeyPresser
    • Zuiki2PS1Dengoで得たキーボード入力を、実際に実行する。
    • input
      • この関数から、押すキーと離すキーを求める。あんまりキー入力を連打するとエミュレーターが壊れる(気がする)ので、「コントローラー入力の直後に0.025秒待って、新しい入力が来なかったら、実際にエミュレータに対してキーボード入力を流す。」ということをしている。
    • press
      • 押す。

テスト


上がプログラム実行中の様子で、下がプログラムを実行していない状態。大体狙い通りに動いた。
また、Windowsにおけるキーボードの設定において、Microsoft IME(日本語+英語)ではなくUSキーボード(英語のみ)を使用することで、レスポンスが格段に向上した。ぶっちゃけ、理由は不明だが、少なくとも間違いなさそうだ。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?