PS-USBコンバーターの自作(音ゲー専コン向け機能付) [LAY-002-01]

PS1 / PS2のコントローラーをUSBに変換するコンバーターをArduinoで作ってみました!
音ゲー専コン向けの専用機能も搭載!

  • 一般的なPSコントローラー→USB変換が可能
  • Arduinoマイコンにより既存の市販品より低遅延
  • ハットスイッチ(POV)未対応ゲーム向けモードあり
  • ポップンミュージック専コンモードあり
    • 「右黄色問題」対策済
    • Lively用クイックリトライ機能搭載
  • beatmania IIDX専コンモードあり
    • INFINITAS用にファンクションキーE1~E4使用可能
    • 選曲画面や、SUD+調整でターンテーブルが動きすぎる問題の対策あり

概要

USBコンバーターは日本製が終売、中華の怪しいやつは信頼性不明という状況の中、偉大なる先人がArduinoを使ったコンバーターの作例を色々と上げてくれているので、参考にしつつ独自機能を追加した基板を作成。

またコナミ音ゲーの専コンの場合、既存の変換器だと痒いところに手が届かなくて結局JoytoKeyとか使うハメになることがあるらしいので、コナステ専用モードも搭載。

2023/08/09追記
基板設計したので発注かけました。問題なく動けばケース入りにして頒布するかも。

2023/08/27追記

販売開始しました

モードセレクト

「スタート+セレクト+↑」を同時押しすることでモード切り替えをできるようにしました。
(専コンの場合は、IIDXはスクラッチ時計回りが↑、ポプコンは右黄色が↑です。)

以下の3モードを切り替え可能です。
選んだモードは保存されるので次回使用時も同じモードから始まります。

  • POVモード(LED青点灯)
    いわゆる普通のコンバーターの動作。
    デュアルショックの全てのボタン・スティックが割り当てたコントローラーとして認識します。
    矢印キーはPOV(ハットスイッチ)として認識します。
  • ボタンモード(LED緑点灯)
    矢印キー以外はPOVモードと同じ動作。
    矢印キーはPOVではなく、それぞれボタンとして認識します。
    左右や上下の同時押しをすることがあるDDRコントローラーや、POVに対応していないゲーム向けのモードです。
  • コナステモード(LED赤点灯)
    beatmania IIDX INFINITASや、pop’n music Livelyに専コンを繋ぐ専用モードです。
    詳細は後述します。
  • キーボードモード(LED黄点灯)
    試験中。販売しているモデルには導入していません。
    全てのボタンをキーボードのキーに割り当てるモードです。JoyToKeyとかが必要な環境に。

コナステモード

プレステ時代の専用コントローラーで、beatmania IIDX INFINITASやpop’n music Livelyをプレイする時に使用します。(BMSやPMSにももちろん使用可能)

ポップンコントローラーを自動認識するので、ポップンモードとIIDXモードは自動で切り替わります。

ポップンモード

専コンボタン割り当てボタン
1鍵~9鍵ボタン1~ボタン9
セレクトBackSpaceキー
スタートEscキー
セレクト+スタートF1キー

Livelyのゲーム内キーコンフィグには1~9しか設定できないので、スタート・セレクトは対応するキーボードのキーを割り当てました。

クイックリトライ用にF1キーもあったほうが便利なので、「セレクト+スタート」の同時押しで対応するようにしました。(プレミアムモデルもこれ対応してほしい…)

IIDXモード

専コンボタン割り当てボタン
1鍵~7鍵ボタン1~ボタン7
スクラッチ↑左スティック↑
スクラッチ↓左スティック↓
セレクト割り当てなし
スタートボタン10 (E1)
セレクト+2鍵ボタン11 (E2)
セレクト+4鍵ボタン12 (E3)
セレクト+6鍵ボタン13 (E4)
セレクト+1鍵キーボード↑
セレクト+3鍵キーボード↓
セレクト+5鍵キーボード←
セレクト+7鍵キーボード→

特筆すべきはセレクトボタンをファンクションキーとしているところ。

「セレクト+2,4,6鍵」にはゲームプレイとは別のボタンを割り当てているのでE2~E4を割り当てると便利かなと。

「セレクト+1,3鍵」にはキーボードの上下を割り当てています。
選曲画面でターンテーブルを使うと専コン特有の入力持続ですっ飛んでしまうのでちょこちょこ選びたいとき用に。

同様に「セレクト+5,7鍵」にはキーボードの左右を割り当てています。詳細オプションの左右移動などに。

「セレクト+スタート」をE2+E3のショートカットにしているので、強制終了・クイックリトライが片手でできて便利。
SUD+を皿で調整しようとすると持続入力のせいで吹っ飛んでしまうので、やっぱりセレクト+スタート+キーボード↑↓で操作できるように、強制終了ショートカットは廃止しました。
強制終了は「セレクト+2+4」でご対応ください。セレクトボタンに近いので以外と入れやすかった。

「スタート+セレクト」を押したまま皿でSUD+調整しようとすると、「スタート+セレクト+↑」が発動してモードが切り替わってしまうので注意。
SUD+調整は、「スタート+皿」か、「スタート+セレクト+1/3鍵(↑↓)」のみを使うのが望ましい。

用意する物

配線とかはググれば先人の記事がたくさん出るのでとりあえず省略。需要と暇があればちゃんと書く。

  • Pro micro 3.3V/8MHz (Arduino Leonardo互換機)
    PSコントローラーが3.3V付近の駆動なので、一般的な5V品より3.3V品が望ましい。
  • PSコントローラー端子メス
    PSコントローラー用の延長ケーブルをちょん切って使用。
    うちのはXHコネクタをつけたりなんかしてますがそこはお好みで。
  • プルアップ抵抗
    コントローラーのCMD線とDAT線が不安定な時があるので対策に。4.7kΩとか10kΩを適当に。

PSコントローラーの3.3V/GNDをArduinoのVCC/GNDに接続、CMD/DAT/CLK/ATT線をArduinoの好きなピンに繋いでスケッチ側のピン番号を合わせたら完成。モーター電源とACK線は無視してOK。

ソースコード

Arduino IDE導入手順

概要のみ、詳細は割愛します。(ググれば分かりやすい記事がたくさん出てくるので)

IDEインストール

Arduino IDE (https://www.arduino.cc/en/software)をダウンロードしてインストールします。

ボード追加・指定

Pro microを利用する場合は「SparkFun AVR Boards」の導入が必要です。
※Arduino Leonardoの場合は不要。

「ファイル」→「基本設定」→「追加のボードマネージャのURL」の右のボタンを押し、https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.jsonを追加。

「ツール」→「ボード」→「SparkFun AVR Boards」→「SparkFun Pro Micro」を選択。

同じく「ツール」→「ポート」からそれらしいCOMポートを選択。(マイコンを抜き差しして消えるやつがそれです)

「ツール」→「Processor」から電圧の選択にも注意。コンバーターには3.3V版を使用します。
※ここで3.3Vを選択したからといって5V版のマイコンが3.3Vになるわけではありません。最初から3.3V/8MHz版を購入してください。

ライブラリインストール

予めPsxNewLibのインストールが必要です。

左の本棚マーク?でライブラリマネージャーを開き、「PsxNewLib」を検索してインストールします。
依存関係のメッセージが出たら「全てをインストール」を選択します。

スケッチ内設定

JOY_DEADZONEを変更すると中心からどれくらいまでを中心と見なすかを変更することができます。
通常は8192/32768の25%をデッドゾーンとしています。0にすれば無効になります。

ALWAYS_LEDをtrueにするとモード表示LEDが選択時のみだけでなく常時点灯になります。眩しいです。

CHECK_LEDをfalseにするとSTART+SELECTでモード表示LEDを点灯する機能を消せます。今どのモードか、モード変更するまで分からなくなります。

スケッチ

#include "HID-Project.h"
#include <EEPROM.h>

// Config
////////////////////
#define JOY_DEADZONE 8192   // Disabled at 0
#define ALWAYS_LED false
#define CHECK_LED true
#define LED_R A1
#define LED_G A3
#define LED_B A2

// PsxNewLib HwSpi Config
// DAT CMD CLK must be connected to HWSPI pin
////////////////////

#include <PsxControllerHwSpi.h>
#define PIN_PS2_ATT 10
PsxControllerHwSpi<PIN_PS2_ATT> psx;

// PsxNewLib BitBang Config
// Specify any GPIO
////////////////////

// #include <PsxControllerBitBang.h>
// #define PIN_PS2_CLK 13
// #define PIN_PS2_DAT 12
// #define PIN_PS2_CMD 11
// #define PIN_PS2_ATT 10
// PsxControllerBitBang<PIN_PS2_ATT, PIN_PS2_CMD, PIN_PS2_DAT, PIN_PS2_CLK> psx;

// Function Analog stick value
////////////////////
#define PSX_ANALOG_MIN 0
#define PSX_ANALOG_MAX 255
#define JOY_ANALOG_MIN -32768
#define JOY_ANALOG_MAX 32767
int psx_analog_to_joy(byte val){
  return map(val, PSX_ANALOG_MIN, PSX_ANALOG_MAX, JOY_ANALOG_MIN, JOY_ANALOG_MAX);
}

// Function set button for boolean
////////////////////
void setButton(uint8_t key, bool state) {
  if (state) {
    Gamepad.press(key);
  } else {
    Gamepad.release(key);
  }
}

// Function Arrow key to Dpad
////////////////////
byte setDpad(bool upKey, bool downKey, bool leftKey, bool rightKey) {
  byte udlr = upKey << 3 | downKey << 2 | leftKey << 1 | rightKey;
  switch (udlr) {
    case 0b1000:
      return (GAMEPAD_DPAD_UP);
    case 0b0100:
      return (GAMEPAD_DPAD_DOWN);
    case 0b0010:
      return (GAMEPAD_DPAD_LEFT);
    case 0b0001:
      return (GAMEPAD_DPAD_RIGHT);
    case 0b1010:
      return (GAMEPAD_DPAD_UP_LEFT);
    case 0b1001:
      return (GAMEPAD_DPAD_UP_RIGHT);
    case 0b0110:
      return (GAMEPAD_DPAD_DOWN_LEFT);
    case 0b0101:
      return (GAMEPAD_DPAD_DOWN_RIGHT);
    case 0b1111:
      return (GAMEPAD_DPAD_UP); // pop'n support
    default:
      return (GAMEPAD_DPAD_CENTERED);
  }
}

// Mode pattern
////////////////////
enum Mode {POV, BUTTON, KONAMI, MODE_LEN};
byte mode;

// Function blank LED
void blank_LED() {
  digitalWrite(LED_R, LOW);
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);
}

// Function show LED
void show_LED() {
  switch (mode) {
    case POV:
      digitalWrite(LED_B, HIGH);
      break;
    case BUTTON:
      digitalWrite(LED_G, HIGH);
      break;
    case KONAMI:
      digitalWrite(LED_R, HIGH);
      break;
  }
}

// Function Flash LED
void flash_LED() {
// LED flashes according to the selected mode
  for (int flash = 0; flash < 3; flash++){
    blank_LED();
    delay(100);
    show_LED();
    delay(100);
  }
  delay(500);
  if (! ALWAYS_LED) blank_LED();
  return;
}

// Main
////////////////////
void setup() {
  // Read savedata
  EEPROM.get(0, mode);
  if (mode >= MODE_LEN) mode = 0;
  pinMode(LED_R, OUTPUT);
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  flash_LED();

  psx.begin();
  NKROKeyboard.begin();
  Gamepad.begin();
}

void loop() {
  // Read state
  ////////////////////
  if (!psx.read()){
    // Not connected
    Gamepad.releaseAll();
    Gamepad.write();
    NKROKeyboard.releaseAll();
    NKROKeyboard.send();
    return;
  }

  bool state_X = psx.buttonPressed(PSB_CROSS);
  bool state_O = psx.buttonPressed(PSB_CIRCLE);
  bool state_Squ = psx.buttonPressed(PSB_SQUARE);
  bool state_Tri = psx.buttonPressed(PSB_TRIANGLE);
  bool state_L1 = psx.buttonPressed(PSB_L1);
  bool state_R1 = psx.buttonPressed(PSB_R1);
  bool state_L2 = psx.buttonPressed(PSB_L2);
  bool state_R2 = psx.buttonPressed(PSB_R2);
  bool state_Sl = psx.buttonPressed(PSB_SELECT);
  bool state_St = psx.buttonPressed(PSB_START);
  bool state_L3 = psx.buttonPressed(PSB_L3);
  bool state_R3 = psx.buttonPressed(PSB_R3);
  bool state_U = psx.buttonPressed(PSB_PAD_UP);
  bool state_D = psx.buttonPressed(PSB_PAD_DOWN);
  bool state_L = psx.buttonPressed(PSB_PAD_LEFT);
  bool state_R = psx.buttonPressed(PSB_PAD_RIGHT);

  if (state_Sl && state_St && CHECK_LED) {
    show_LED();
  } else if (! ALWAYS_LED) {
    blank_LED();
  }
  if (state_Sl && state_St && state_U) {
    // mode select
    ////////////////////
    if (++mode >= MODE_LEN) mode = 0;

    // Reset state
    Gamepad.releaseAll();
    Gamepad.write();
    NKROKeyboard.releaseAll();
    NKROKeyboard.send();

    // mode save
    EEPROM.put(0, mode);

    // LED flashes according to the selected mode
    flash_LED();
  }

  switch (mode) {
    case POV:
    case BUTTON:
      // Gamepad Mode
      ////////////////////

      // Set Joystick
      byte x, y;
      if (psx.getLeftAnalog(x, y)) {
        int X = psx_analog_to_joy(x);
        int Y = psx_analog_to_joy(y);
        if (abs(X) < JOY_DEADZONE && abs(Y) < JOY_DEADZONE) {
          X = 0;
          Y = 0;
        }
        Gamepad.xAxis(X);
        Gamepad.yAxis(Y);
      }
      if (psx.getRightAnalog(x, y)) {
        int X = psx_analog_to_joy(x);
        int Y = psx_analog_to_joy(y);
        if (abs(X) < JOY_DEADZONE && abs(Y) < JOY_DEADZONE) {
          X = 0;
          Y = 0;
        }
        Gamepad.rxAxis(X);
        Gamepad.ryAxis(Y);
      }

      // Set button state
      setButton(1, state_X);
      setButton(2, state_O);
      setButton(3, state_Squ);
      setButton(4, state_Tri);
      setButton(5, state_L1);
      setButton(6, state_R1);
      setButton(7, state_L2);
      setButton(8, state_R2);
      setButton(9, state_Sl);
      setButton(10, state_St);
      setButton(11, state_L3);
      setButton(12, state_R3);
      if (mode == POV) {
        Gamepad.dPad1(setDpad(state_U, state_D, state_L, state_R));
      } else if (mode == BUTTON) {
        setButton(13, state_U);
        setButton(14, state_D);
        setButton(15, state_L);
        setButton(16, state_R);
      }
      break;
    case KONAMI:
      // KONAMI STATION Mode
      ////////////////////

      if (state_L && state_D && state_R) {
        // pop'n music Mode
        ////////////////////

        setButton(1, state_Tri);
        setButton(2, state_O);
        setButton(3, state_R1);
        setButton(4, state_X);
        setButton(5, state_L1);
        setButton(6, state_Squ);
        setButton(7, state_R2);
        setButton(8, state_U);
        setButton(9, state_L2);
        if (state_Sl) NKROKeyboard.add(KEY_BACKSPACE); else NKROKeyboard.remove(KEY_BACKSPACE);
        // St = Esc
        if (!state_Sl && state_St) NKROKeyboard.add(KEY_ESC); else NKROKeyboard.remove(KEY_ESC);
        // Sl + St = F1
        if (state_Sl && state_St) NKROKeyboard.add(KEY_F1); else NKROKeyboard.remove(KEY_F1);
      } else {
        // IIDX Mode
        ////////////////////

        setButton(1, !state_Sl && state_Squ);
        setButton(2, !state_Sl && state_L1);
        setButton(3, !state_Sl && state_X);
        setButton(4, !state_Sl && state_R1);
        setButton(5, !state_Sl && state_O);
        setButton(6, !state_Sl && state_L2);
        setButton(7, !state_Sl && state_L);

        // SCR Assign to button
        ////////////////////
        setButton(8, state_U);
        setButton(9, state_D);

        // SCR Assign to analog
        ////////////////////
        // if (state_U) {
        //   // Lstick Up
        //   Gamepad.yAxis(0x8000);
        // } else if (state_D) {
        //   // Lstick Down
        //   Gamepad.yAxis(0x7FFF);
        // } else {
        //   // Lstick Center
        //   Gamepad.yAxis(0);
        // }
        // // X-axis centered
        // Gamepad.xAxis(0);

        // START
        setButton(10, state_St);

        // Select + 2 = 11
        setButton(11, state_Sl && state_L1);
        // Select + 4 = 12
        setButton(12, state_Sl && state_R1);
        // Select + 6 = 13
        setButton(13, state_Sl && state_L2);

        // Select + 1 = UP
        if (state_Sl && state_Squ) NKROKeyboard.add(KEY_UP); else NKROKeyboard.remove(KEY_UP);
        // Select + 3 = DOWN
        if (state_Sl && state_X) NKROKeyboard.add(KEY_DOWN); else NKROKeyboard.remove(KEY_DOWN);
        // Select + 5 = LEFT
        if (state_Sl && state_O) NKROKeyboard.add(KEY_LEFT); else NKROKeyboard.remove(KEY_LEFT);
        // Select + 7 = RIGHT
        if (state_Sl && state_L) NKROKeyboard.add(KEY_RIGHT); else NKROKeyboard.remove(KEY_RIGHT);
      }
      break;
    default:
      // Irregular
      ////////////////////
      Gamepad.releaseAll();
      NKROKeyboard.releaseAll();
  }

  // Send
  ////////////////////
  Gamepad.write();
  NKROKeyboard.send();
}
#include "HID-Project.h"
#include <EEPROM.h>

// Config
////////////////////
#define JOY_DEADZONE 8192   // Disabled at 0
#define ALWAYS_LED false
#define CHECK_LED true
#define LED_R A1
#define LED_G A3
#define LED_B A2

// PsxNewLib HwSpi Config
// DAT CMD CLK must be connected to HWSPI pin
////////////////////

#include <PsxControllerHwSpi.h>
#define PIN_PS2_ATT 10
PsxControllerHwSpi<PIN_PS2_ATT> psx;

// PsxNewLib BitBang Config
// Specify any GPIO
////////////////////

// #include <PsxControllerBitBang.h>
// #define PIN_PS2_CLK 13
// #define PIN_PS2_DAT 12
// #define PIN_PS2_CMD 11
// #define PIN_PS2_ATT 10
// PsxControllerBitBang<PIN_PS2_ATT, PIN_PS2_CMD, PIN_PS2_DAT, PIN_PS2_CLK> psx;

// Function Analog stick value
////////////////////
#define PSX_ANALOG_MIN 0
#define PSX_ANALOG_MAX 255
#define JOY_ANALOG_MIN -32768
#define JOY_ANALOG_MAX 32767
int psx_analog_to_joy(byte val){
  return map(val, PSX_ANALOG_MIN, PSX_ANALOG_MAX, JOY_ANALOG_MIN, JOY_ANALOG_MAX);
}

// Function set button for boolean
////////////////////
void setButton(uint8_t key, bool state) {
  if (state) {
    Gamepad.press(key);
  } else {
    Gamepad.release(key);
  }
}

// Function Arrow key to Dpad
////////////////////
byte setDpad(bool upKey, bool downKey, bool leftKey, bool rightKey) {
  byte udlr = upKey << 3 | downKey << 2 | leftKey << 1 | rightKey;
  switch (udlr) {
    case 0b1000:
      return (GAMEPAD_DPAD_UP);
    case 0b0100:
      return (GAMEPAD_DPAD_DOWN);
    case 0b0010:
      return (GAMEPAD_DPAD_LEFT);
    case 0b0001:
      return (GAMEPAD_DPAD_RIGHT);
    case 0b1010:
      return (GAMEPAD_DPAD_UP_LEFT);
    case 0b1001:
      return (GAMEPAD_DPAD_UP_RIGHT);
    case 0b0110:
      return (GAMEPAD_DPAD_DOWN_LEFT);
    case 0b0101:
      return (GAMEPAD_DPAD_DOWN_RIGHT);
    case 0b1111:
      return (GAMEPAD_DPAD_UP); // pop'n support
    default:
      return (GAMEPAD_DPAD_CENTERED);
  }
}

// Mode pattern
////////////////////
enum Mode {POV, BUTTON, KONAMI, FKEY, MODE_LEN};
byte mode;

// Function blank LED
void blank_LED() {
  digitalWrite(LED_R, LOW);
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);
}

// Function show LED
void show_LED() {
  switch (mode) {
    case POV:
      digitalWrite(LED_B, HIGH);
      break;
    case BUTTON:
      digitalWrite(LED_G, HIGH);
      break;
    case KONAMI:
      digitalWrite(LED_R, HIGH);
      break;
    case FKEY:
      digitalWrite(LED_R, HIGH);
      digitalWrite(LED_G, HIGH);
      break;
  }
}

// Function Flash LED
void flash_LED() {
// LED flashes according to the selected mode
  for (int flash = 0; flash < 3; flash++){
    blank_LED();
    delay(100);
    show_LED();
    delay(100);
  }
  delay(500);
  if (! ALWAYS_LED) blank_LED();
  return;
}

// Main
////////////////////
void setup() {
  // Read savedata
  EEPROM.get(0, mode);
  if (mode >= MODE_LEN) mode = 0;
  pinMode(LED_R, OUTPUT);
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  flash_LED();

  psx.begin();
  NKROKeyboard.begin();
  Gamepad.begin();
}

void loop() {
  // Read state
  ////////////////////
  if (!psx.read()){
    // Not connected
    Gamepad.releaseAll();
    Gamepad.write();
    NKROKeyboard.releaseAll();
    NKROKeyboard.send();
    return;
  }

  bool state_X = psx.buttonPressed(PSB_CROSS);
  bool state_O = psx.buttonPressed(PSB_CIRCLE);
  bool state_Squ = psx.buttonPressed(PSB_SQUARE);
  bool state_Tri = psx.buttonPressed(PSB_TRIANGLE);
  bool state_L1 = psx.buttonPressed(PSB_L1);
  bool state_R1 = psx.buttonPressed(PSB_R1);
  bool state_L2 = psx.buttonPressed(PSB_L2);
  bool state_R2 = psx.buttonPressed(PSB_R2);
  bool state_Sl = psx.buttonPressed(PSB_SELECT);
  bool state_St = psx.buttonPressed(PSB_START);
  bool state_L3 = psx.buttonPressed(PSB_L3);
  bool state_R3 = psx.buttonPressed(PSB_R3);
  bool state_U = psx.buttonPressed(PSB_PAD_UP);
  bool state_D = psx.buttonPressed(PSB_PAD_DOWN);
  bool state_L = psx.buttonPressed(PSB_PAD_LEFT);
  bool state_R = psx.buttonPressed(PSB_PAD_RIGHT);

  if (state_Sl && state_St && CHECK_LED) {
    show_LED();
  } else if (! ALWAYS_LED) {
    blank_LED();
  }
  if (state_Sl && state_St && state_U) {
    // mode select
    ////////////////////
    if (++mode >= MODE_LEN) mode = 0;

    // Reset state
    Gamepad.releaseAll();
    Gamepad.write();
    NKROKeyboard.releaseAll();
    NKROKeyboard.send();

    // mode save
    EEPROM.put(0, mode);

    // LED flashes according to the selected mode
    flash_LED();
  }

  switch (mode) {
    case POV:
    case BUTTON:
      // Gamepad Mode
      ////////////////////

      // Set Joystick
      byte x, y;
      if (psx.getLeftAnalog(x, y)) {
        int X = psx_analog_to_joy(x);
        int Y = psx_analog_to_joy(y);
        if (abs(X) < JOY_DEADZONE && abs(Y) < JOY_DEADZONE) {
          X = 0;
          Y = 0;
        }
        Gamepad.xAxis(X);
        Gamepad.yAxis(Y);
      }
      if (psx.getRightAnalog(x, y)) {
        int X = psx_analog_to_joy(x);
        int Y = psx_analog_to_joy(y);
        if (abs(X) < JOY_DEADZONE && abs(Y) < JOY_DEADZONE) {
          X = 0;
          Y = 0;
        }
        Gamepad.rxAxis(X);
        Gamepad.ryAxis(Y);
      }

      // Set button state
      setButton(1, state_X);
      setButton(2, state_O);
      setButton(3, state_Squ);
      setButton(4, state_Tri);
      setButton(5, state_L1);
      setButton(6, state_R1);
      setButton(7, state_L2);
      setButton(8, state_R2);
      setButton(9, state_Sl);
      setButton(10, state_St);
      setButton(11, state_L3);
      setButton(12, state_R3);
      if (mode == POV) {
        Gamepad.dPad1(setDpad(state_U, state_D, state_L, state_R));
      } else if (mode == BUTTON) {
        setButton(13, state_U);
        setButton(14, state_D);
        setButton(15, state_L);
        setButton(16, state_R);
      }
      break;
    case KONAMI:
      // KONAMI STATION Mode
      ////////////////////

      if (state_L && state_D && state_R) {
        // pop'n music Mode
        ////////////////////

        setButton(1, state_Tri);
        setButton(2, state_O);
        setButton(3, state_R1);
        setButton(4, state_X);
        setButton(5, state_L1);
        setButton(6, state_Squ);
        setButton(7, state_R2);
        setButton(8, state_U);
        setButton(9, state_L2);
        if (state_Sl) NKROKeyboard.add(KEY_BACKSPACE); else NKROKeyboard.remove(KEY_BACKSPACE);
        // St = Esc
        if (!state_Sl && state_St) NKROKeyboard.add(KEY_ESC); else NKROKeyboard.remove(KEY_ESC);
        // Sl + St = F1
        if (state_Sl && state_St) NKROKeyboard.add(KEY_F1); else NKROKeyboard.remove(KEY_F1);
      } else {
        // IIDX Mode
        ////////////////////

        setButton(1, !state_Sl && state_Squ);
        setButton(2, !state_Sl && state_L1);
        setButton(3, !state_Sl && state_X);
        setButton(4, !state_Sl && state_R1);
        setButton(5, !state_Sl && state_O);
        setButton(6, !state_Sl && state_L2);
        setButton(7, !state_Sl && state_L);

        // SCR Assign to button
        ////////////////////
        setButton(8, state_U);
        setButton(9, state_D);

        // SCR Assign to analog
        ////////////////////
        // if (state_U) {
        //   // Lstick Up
        //   Gamepad.yAxis(0x8000);
        // } else if (state_D) {
        //   // Lstick Down
        //   Gamepad.yAxis(0x7FFF);
        // } else {
        //   // Lstick Center
        //   Gamepad.yAxis(0);
        // }
        // // X-axis centered
        // Gamepad.xAxis(0);

        // START
        setButton(10, state_St);

        // Select + 2 = 11
        setButton(11, state_Sl && state_L1);
        // Select + 4 = 12
        setButton(12, state_Sl && state_R1);
        // Select + 6 = 13
        setButton(13, state_Sl && state_L2);

        // Select + 1 = UP
        if (state_Sl && state_Squ) NKROKeyboard.add(KEY_UP); else NKROKeyboard.remove(KEY_UP);
        // Select + 3 = DOWN
        if (state_Sl && state_X) NKROKeyboard.add(KEY_DOWN); else NKROKeyboard.remove(KEY_DOWN);
        // Select + 5 = LEFT
        if (state_Sl && state_O) NKROKeyboard.add(KEY_LEFT); else NKROKeyboard.remove(KEY_LEFT);
        // Select + 7 = RIGHT
        if (state_Sl && state_L) NKROKeyboard.add(KEY_RIGHT); else NKROKeyboard.remove(KEY_RIGHT);
      }
      break;
    case FKEY:
      if (state_X) NKROKeyboard.add(KEY_X); else NKROKeyboard.remove(KEY_X);
      if (state_O) NKROKeyboard.add(KEY_Z); else NKROKeyboard.remove(KEY_Z);
      if (state_Squ) NKROKeyboard.add(KEY_V); else NKROKeyboard.remove(KEY_V);
      if (state_Tri) NKROKeyboard.add(KEY_C); else NKROKeyboard.remove(KEY_C);
      if (state_L1) NKROKeyboard.add(KEY_A); else NKROKeyboard.remove(KEY_A);
      if (state_R1) NKROKeyboard.add(KEY_S); else NKROKeyboard.remove(KEY_S);
      if (state_L2) NKROKeyboard.add(KEY_D); else NKROKeyboard.remove(KEY_D);
      if (state_R2) NKROKeyboard.add(KEY_F); else NKROKeyboard.remove(KEY_F);
      if (state_Sl) NKROKeyboard.add(KEY_ESC); else NKROKeyboard.remove(KEY_ESC);
      if (state_St) NKROKeyboard.add(KEY_RETURN); else NKROKeyboard.remove(KEY_RETURN);
      if (state_L3) NKROKeyboard.add(KEY_G); else NKROKeyboard.remove(KEY_G);
      if (state_R3) NKROKeyboard.add(KEY_H); else NKROKeyboard.remove(KEY_H);
      if (state_U) NKROKeyboard.add(KEY_UP); else NKROKeyboard.remove(KEY_UP);
      if (state_D) NKROKeyboard.add(KEY_DOWN); else NKROKeyboard.remove(KEY_DOWN);
      if (state_L) NKROKeyboard.add(KEY_LEFT); else NKROKeyboard.remove(KEY_LEFT);
      if (state_R) NKROKeyboard.add(KEY_RIGHT); else NKROKeyboard.remove(KEY_RIGHT);
      break;
    default:
      // Irregular
      ////////////////////
      Gamepad.releaseAll();
      NKROKeyboard.releaseAll();
  }

  // Send
  ////////////////////
  Gamepad.write();
  NKROKeyboard.send();
}

コメント

タイトルとURLをコピーしました