はじめに
『X68000Z』で動作するゲームコントローラーとしては、『メガドライブミニ/2』用の『ファイティング 6B』を所持していましたが、X68000 のゲームは格ゲーを除けば 8 方向 + 2 ボタンのゲームコントローラーで動作するものが殆どで、連射装置も欲しい所でした。
X68000Z はゲームコントローラーのボタンをカスタマイズする機能を持っておらず、公式に対応しているのはゲーム機ミニシリーズ用のコントローラーです。
『X68000Z PRODUCT EDITION (BLACK MODEL)』には専用コントローラー『X68000 Z ジョイカード (ZKJC-009-BK)』が付属します。単体でも販売されています。
それ以外の多ボタンコントローラーでは、とんでもない位置のボタンに A ボタンと B ボタンが割り当てられる事があります (2 ボタンなら大丈夫)。『Logicool F310r』のように全く動作しないコントローラーもあります。
連射機能付きのコントローラーで X68000Z と相性が良さそうだったのは『HORI ターボパッド for PCエンジン mini』でしたが、気付いた時には終売&プレミア価格でした。
本記事は自身のゲームコントローラー事情をどうにかしようと、X68000Z のコミュニティサイトである 「Z-CLUB」 に投稿した内容のダイジェスト版です。
- 連射パッドを持ってないので (その1) (Z-Club)
- 連射パッドを持ってないので (その2) (Z-Club)
- 連射パッドを持ってないので (その3) (Z-Club)
- 連射パッドを持ってないので (その4) (Z-Club)
- 連射パッドを持ってないので (その5) (Z-Club)
- 連射パッドを持ってないので (その6) (Z-Club)
- 連射パッドを持ってないので (その7) (Z-Club)
Z-CLUB の記事はログインしないと閲覧もできません。
ゲームコントローラーとコンバーター
プレイするゲームは『GRADIUS』を想定しています。
■ フットスイッチ
最初は自作の USB フットスイッチに連射機能を付けてみました。USB フットスイッチのマイコンボードは『Da Vinci 32U』です。
HID キーボードとして振る舞い、ペダルを踏んでいる間 〔X〕
(ショット) と 〔C〕
(ミサイル) を連射するものです。ゲームコントローラーは別に接続してあり、自機の移動とパワーアップはそちらで行ないます。
スケッチ
#include<Keyboard.h>
/* DIGITAL PIN */
const int BTN_PIN_POWERUP = 2;
const int BTN_PIN_SHOT = 3;
const int BTN_PIN_MISSILE = 4;
void setup() {
pinMode(BTN_PIN_POWERUP , INPUT_PULLUP);
pinMode(BTN_PIN_SHOT , INPUT_PULLUP);
pinMode(BTN_PIN_MISSILE , INPUT_PULLUP);
Keyboard.begin();
}
void loop() {
/* KEY SEND */
if (digitalRead(BTN_PIN_SHOT ) == LOW)
Keyboard.press('x');
if (digitalRead(BTN_PIN_MISSILE) == LOW)
Keyboard.press('c');
delay(8);
Keyboard.releaseAll();
delay(8);
}
■ コンバーター
X68000Z や MSX で使っていた連射パッドを発掘したので、これを接続できるコンバータを作る事にしました。
マイコンボードには『Pro Micro (5V / 16MHz)』を使う事にしました。
結線は次の通りです。最初のテストに『Arduboy』を使ったため、それに倣っています。
DSUB9 | Arduino |
---|---|
1 | A0 |
2 | A3 |
3 | A2 |
4 | A1 |
5 | 5V |
6 | D7 |
7 | D8 |
8 | GND |
9 | GND |
3D プリンタでケースも作りました。
実機の連射パッドが使えていい感じです。
原材料費は USB ケーブル抜きで 1,000円くらいでしょうか。
- (Arduino) Pro Micro (ht-deko.com)
- Adduboy (ht-deko.com)
- D-Sub 9P Hood for Pro Micro (thingiverse.com)
スケッチ
・スケッチのコンパイルには『Arduino Joystick Library 2.x』が必要です。
#include <Joystick.h>
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 2, 1,
false, false, false, false, false, false,
false, false, false, false, false);
/* PINS */
const int PIN_UP = A0;
const int PIN_DOWN = A3;
const int PIN_LEFT = A2;
const int PIN_RIGHT = A1;
const int PIN_A = 7;
const int PIN_B = 8;
const int16_t Angles[16] = {
JOYSTICK_HATSWITCH_RELEASE, 180, /* Down */
270, /* Left */ 225, /* Left-lower */
90, /* Right */ 135, /* Right-lower */
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE,
0, /* Up */ JOYSTICK_HATSWITCH_RELEASE,
315, /* Left-upper */ JOYSTICK_HATSWITCH_RELEASE,
45, /* Right-upper */ JOYSTICK_HATSWITCH_RELEASE,
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE};
void setup() {
pinMode(PIN_UP , INPUT_PULLUP);
pinMode(PIN_DOWN , INPUT_PULLUP);
pinMode(PIN_LEFT , INPUT_PULLUP);
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_A , INPUT_PULLUP);
pinMode(PIN_B , INPUT_PULLUP);
Joystick.begin();
}
void loop() {
/* Arrows */
int HatState = (!digitalRead(PIN_UP) << 3) |
(!digitalRead(PIN_RIGHT)<< 2) |
(!digitalRead(PIN_LEFT) << 1) |
(!digitalRead(PIN_DOWN) );
Joystick.setHatSwitch(0, Angles[HatState]);
/* Buttons */
Joystick.setButton(0, !digitalRead(PIN_A));
Joystick.setButton(1, !digitalRead(PIN_B));
}
上下の同時押し、左右の同時押しはできないようになっています。
「テストに Arduboy を使った」と書きましたが、このスケッチを『Arduboy』に転送すると『Arduboy』をゲームコントローラーとして使う事ができるようになります (操作性はイマイチですが)。
X68000 / MSX 用ゲームパッドをお持ちの方にオススメですが、『マジカルパッド』等はこのスケッチでは変換できません。
■ ゲームコントローラー
コンバーターでは基本的に 2 ボタンしか使えないので、ゲームコントローラー自体を作る事にしました。マイコンボードには『Pro Micro (5V / 3.3V) 』を使う事にしました。ゲームコントローラーのガワは、調達が容易な『スーパーファミコン』用のコントローラーを使う事にしました。程度の良さそうなものがハードオフで一つ 330円でした。
中古のコントローラーは変色している?Retr0bright でキレイになります。
USB ケーブルと『ProMicro』を別途用意。『ProMicro』は現在 1,000円前後。
このコントローラーは初期型のようです。IC (W545) を剥がして、
『ProMicro』のコネクタを外して、そこへジュンフロン線をハンダ付け。
パターンを剥離してしまったら、リカバリーポイントに接続してください。
USB ケーブルと仮にハンダ付けして動作が確認できたら、ホットボンドで固定。USB ケーブルも熱収縮チューブを被せて本ハンダ付け。
基板側にハンダ付けして…
『Pro Micro』にもハンダ付けして…
プログラマブルな USB ゲームコントローラーの完成です!
原材料費は 1,800円くらいでしょうか。パッドのゴムを交換しても 2,000円チョイで済むと思います。
ベースがゲーム機用のコントローラーなので、操作性はバツグンです。
結線 (W545 の場合)
結線の詳細は次の通りです。
Button | W545 | Pin | Pro Micro |
---|---|---|---|
UP | ICA | 3 | A0 |
DOWN | ICA | 4 | A3 |
LEFT | ICA | 5 | A2 |
RIGHT | ICA | 6 | A1 |
A | ICB | 1 | 7 |
B | ICA | 1 | 8 |
X | ICB | 13 | 9 |
Y | ICA | 13 | 10 |
L | ICB | 12 | 3 |
R | ICB | 11 | 4 |
SELECT | ICA | 12 | 5 |
START | ICA | 11 | 6 |
(GND) | ICA | 7 | GND |
(GND) | ICB | 7 | GND |
結線 (V520 の場合)
結線の詳細は次の通りです。
Button | Pin | Pro Micro |
---|---|---|
UP | 19 | A0 |
DOWN | 1 | A3 |
LEFT | 2 | A2 |
RIGHT | 3 | A1 |
A | 15 | 7 |
B | 14 | 8 |
X | 16 | 9 |
Y | 13 | 10 |
L | 18 | 3 |
R | 17 | 4 |
SELECT | 4 | 5 |
START | 5 | 6 |
(GND) | 10 | GND |
リセットボタン
『Pro Micro』はトラブルが起きた時にリセットを行う必要があります。ケースを開けて RST と GND をショートするだけなのですが、コントローラーの実験を行っている際にいちいちケースを開けるのは非効率的です。そこでいくつか作ったコントローラーの一つにリセットボタンを付ける事にしました。
ボトムケースに 4mm の穴を開けます。場所は〇の位置ですが「あぁ、ここか」という位置なので間違える事はないでしょう。
タクトスイッチと取り付けステーを用意します。タクトスイッチを交換できるようにしたかったので 3D プリンタでステーを作りましたが、面倒であればホットボンドで固定すればいいと思います。
タクトスイッチを RST と GND に接続。
取り付けステーはこのように使います。
表面からみた所です。操作に支障をきたす事もありませんし、誤って押す事もありません。
ダブルリセット (リセットボタンの 2 回押しも簡単になります。
スケッチ (X68000Z 用)
X68000Z での利用に特化したゲームコントローラーのスケッチです。
・スケッチのコンパイルには『Arduino Joystick Library 2.x』が必要です。
・スケッチのコンパイルには『MsTimer2』(ライブラリの追加で検索してください) が必要です。
#include <Keyboard.h>
#include <Joystick.h>
#include <MsTimer2.h>
// Numeric keypad
#define KEY_NUM_LOCK 0xDB
#define KEY_KP_SLASH 0xDC
#define KEY_KP_ASTERISK 0xDD
#define KEY_KP_MINUS 0xDE
#define KEY_KP_PLUS 0xDF
#define KEY_KP_ENTER 0xE0
#define KEY_KP_1 0xE1
#define KEY_KP_2 0xE2
#define KEY_KP_3 0xE3
#define KEY_KP_4 0xE4
#define KEY_KP_5 0xE5
#define KEY_KP_6 0xE6
#define KEY_KP_7 0xE7
#define KEY_KP_8 0xE8
#define KEY_KP_9 0xE9
#define KEY_KP_0 0xEA
#define KEY_KP_DOT 0xEB
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 2, 1,
false, false, false, false, false, false,
false, false, false, false, false);
/* PINS */
const int PIN_UP = A0;
const int PIN_DOWN = A3;
const int PIN_LEFT = A2;
const int PIN_RIGHT = A1;
const int PIN_A = 7;
const int PIN_B = 8;
const int PIN_X = 9;
const int PIN_Y = 10;
const int PIN_L = 3;
const int PIN_R = 4;
const int PIN_SEL = 5;
const int PIN_START = 6;
const int16_t Angles[16] = {
JOYSTICK_HATSWITCH_RELEASE, 180, /* Down */
270, /* Left */ 225, /* Left-lower */
90, /* Right */ 135, /* Right-lower */
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE,
0, /* Up */ JOYSTICK_HATSWITCH_RELEASE,
315, /* Left-upper */ JOYSTICK_HATSWITCH_RELEASE,
45, /* Right-upper */ JOYSTICK_HATSWITCH_RELEASE,
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE};
static bool pressState = false;
static bool prev_state_L = false;
static bool prev_state_R = false;
static bool state_L = false;
static bool state_R = false;
int gameMode = 0; // 汎用 (GameCard)
void setup() {
pinMode(PIN_UP , INPUT_PULLUP);
pinMode(PIN_DOWN , INPUT_PULLUP);
pinMode(PIN_LEFT , INPUT_PULLUP);
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_A , INPUT_PULLUP);
pinMode(PIN_B , INPUT_PULLUP);
pinMode(PIN_X , INPUT_PULLUP);
pinMode(PIN_Y , INPUT_PULLUP);
pinMode(PIN_L , INPUT_PULLUP);
pinMode(PIN_R , INPUT_PULLUP);
pinMode(PIN_SEL , INPUT_PULLUP);
pinMode(PIN_START, INPUT_PULLUP);
delay(100);
gameMode = (!digitalRead(PIN_START) << 5) |
(!digitalRead(PIN_SEL) << 4) |
(!digitalRead(PIN_Y) << 3) |
(!digitalRead(PIN_X) << 2) |
(!digitalRead(PIN_B) << 1) |
(!digitalRead(PIN_A) );
Keyboard.begin();
Joystick.begin();
MsTimer2::set(31, toggleSwitch);
MsTimer2::start();
}
void loop() {
/* Arrows */
int HatState = (!digitalRead(PIN_UP) << 3) |
(!digitalRead(PIN_RIGHT)<< 2) |
(!digitalRead(PIN_LEFT) << 1) |
(!digitalRead(PIN_DOWN) );
Joystick.setHatSwitch(0, Angles[HatState]);
/* Buttons */
bool state_A = !digitalRead(PIN_A);
bool state_B = !digitalRead(PIN_B);
bool state_X = !digitalRead(PIN_X);
bool state_Y = !digitalRead(PIN_Y);
prev_state_L = state_L;
state_L = !digitalRead(PIN_L);
prev_state_R = state_R;
state_R = !digitalRead(PIN_R);
bool state_SEL = !digitalRead(PIN_SEL);
bool state_START = !digitalRead(PIN_START);
if (state_X) {
Joystick.setButton(0, pressState);
} else {
Joystick.setButton(0, state_A);
}
if (state_Y) {
Joystick.setButton(1, pressState);
} else {
Joystick.setButton(1, state_B);
}
// LR 同時押しでソフトリセット
if (prev_state_L && prev_state_R && state_L && state_R) {
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_F11);
Keyboard.press(KEY_DELETE);
delay(100);
Keyboard.releaseAll();
delay(500);
return;
}
switch (gameMode % 2){
case 0: // 汎用 (GameCard)
// R でポーズメニュー
if (prev_state_R && state_R) {
Keyboard.press(96);
Keyboard.releaseAll();
delay(500);
return;
}
break;
case 1: // [A] 汎用 (ポーズメニューなし)
break;
}
switch (gameMode){
case 2: // [B] GRADIUS (GameCard)
case 3: // [B][A] GRADIUS (ポーズメニューなし)
// START で一時停止/解除
if (state_START) {
Keyboard.press(KEY_ESC);
delay(100);
Keyboard.releaseAll();
delay(100);
return;
}
// L でコンティニュー
if (prev_state_L && state_L) {
Keyboard.press(KEY_KP_8);
delay(100);
Keyboard.releaseAll();
Keyboard.press(KEY_KP_2);
delay(100);
Keyboard.releaseAll();
Keyboard.press(KEY_KP_4);
delay(100);
Keyboard.releaseAll();
Keyboard.press(KEY_KP_6);
delay(100);
Keyboard.releaseAll();
Keyboard.press('x');
delay(100);
Keyboard.releaseAll();
Keyboard.press('z');
delay(100);
Keyboard.releaseAll();
Keyboard.press(KEY_KP_8);
delay(100);
Keyboard.releaseAll();
Keyboard.press(KEY_KP_2);
delay(100);
Keyboard.releaseAll();
delay(500);
return;
}
break;
case 4: // [X] 超連射68K (GameCard)
case 5: // [X][A] 超連射68K (ポーズメニューなし)
// SELECT でメニューの選択
if (state_SEL) {
Keyboard.press(KEY_TAB);
delay(100);
Keyboard.releaseAll();
delay(100);
return;
}
// START でメニューの決定、一時停止/解除
if (state_START) {
Keyboard.press(KEY_ESC);
delay(100);
Keyboard.releaseAll();
delay(100);
return;
}
break;
}
}
void toggleSwitch() {
pressState = !pressState;
}
連射ボタン付きの 2 ボタンコントローラーとして認識されます。方向キー+2ボタン以外の機能は HID キーボードとして振る舞う事で実現しています。
ボタン | 機能 |
---|---|
十字キー | 移動 |
A | A ボタン |
B | B ボタン |
X | A ボタン連射 |
Y | B ボタン連射 |
L+R | ソフトリセット |
USB コネクタを挿す際に特定のボタンを押しっぱなしにしていると、そのゲームに適したプロファイルが使われます。リセットボタンを実装しているのなら、特定のボタンを押しながらリセットボタンを押しても OK です。
No | 起動時 | 対象 | SELECT | START | L | R |
---|---|---|---|---|---|---|
0 | (なし) | 汎用 | ポーズメニュー | |||
1 | [A] | 汎用 | ||||
2 | [B] | GRADIUS | 一時停止/解除 | コンティニューコマンド | ポーズメニュー | |
3 | [B][A] | GRADIUS | 一時停止/解除 | コンティニューコマンド | ||
4 | [X] | 超連射68K | メニューの選択 | メニューの決定 一時停止/解除 |
ポーズメニュー | |
5 | [X][A] | 超連射68K | メニューの選択 | メニューの決定 一時停止/解除 |
||
6 | [X][B] | (未登録) | ポーズメニュー | |||
7 | [X][B][A] | (未登録) | ||||
8 | [Y] | (未登録) | ポーズメニュー | |||
9 | [Y][A] | (未登録) |
ポーズメニューは〔BREAK〕
キーで出るので、GameCard 起動でないゲームで [R]
ボタンを押した場合には最悪ゲームが強制終了されてしまいます。例えば、[A]
ボタンを押しながらケーブルを挿すと、[R]
ボタンによるポーズメニューが出なくなり、事故を防止する事ができます。
スケッチ (X68000Z ジョイカード互換)
『X68000Z ジョイカード (ZKJC-009-BK)』互換の 12 ボタン (使えないボタンあり) コントローラーです。瑞起のミニ系ゲーム機用コントローラと同じ配置です。但し、方向キーは POV (Hat) で実装してあります。
・スケッチのコンパイルには『Arduino Joystick Library 2.x』が必要です。
#include <Joystick.h>
#include <MsTimer2.h>
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 12, 1,
false, false, false, false, false, false,
false, false, false, false, false);
/* PINS */
const int PIN_UP = A0;
const int PIN_DOWN = A3;
const int PIN_LEFT = A2;
const int PIN_RIGHT = A1;
const int PIN_A = 7;
const int PIN_B = 8;
const int PIN_X = 9;
const int PIN_Y = 10;
const int PIN_L = 3;
const int PIN_R = 4;
const int PIN_SEL = 5;
const int PIN_START = 6;
const int16_t Angles[16] = {
JOYSTICK_HATSWITCH_RELEASE, 180, /* Down */
270, /* Left */ 225, /* Left-lower */
90, /* Right */ 135, /* Right-lower */
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE,
0, /* Up */ JOYSTICK_HATSWITCH_RELEASE,
315, /* Left-upper */ JOYSTICK_HATSWITCH_RELEASE,
45, /* Right-upper */ JOYSTICK_HATSWITCH_RELEASE,
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE};
static bool pressState = false;
void setup() {
pinMode(PIN_UP , INPUT_PULLUP);
pinMode(PIN_DOWN , INPUT_PULLUP);
pinMode(PIN_LEFT , INPUT_PULLUP);
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_A , INPUT_PULLUP);
pinMode(PIN_B , INPUT_PULLUP);
pinMode(PIN_X , INPUT_PULLUP);
pinMode(PIN_Y , INPUT_PULLUP);
pinMode(PIN_L , INPUT_PULLUP);
pinMode(PIN_R , INPUT_PULLUP);
pinMode(PIN_SEL , INPUT_PULLUP);
pinMode(PIN_START, INPUT_PULLUP);
Joystick.begin();
MsTimer2::set(31, toggleSwitch);
MsTimer2::start();
}
void loop() {
/* Arrows */
int HatState = (!digitalRead(PIN_UP) << 3) |
(!digitalRead(PIN_RIGHT)<< 2) |
(!digitalRead(PIN_LEFT) << 1) |
(!digitalRead(PIN_DOWN) );
Joystick.setHatSwitch(0, Angles[HatState]);
/* Buttons */
bool state_A = !digitalRead(PIN_A);
bool state_B = !digitalRead(PIN_B);
bool state_X = !digitalRead(PIN_X);
bool state_Y = !digitalRead(PIN_Y);
bool state_L = !digitalRead(PIN_L);
bool state_R = !digitalRead(PIN_R);
bool state_SEL = !digitalRead(PIN_SEL);
bool state_START = !digitalRead(PIN_START);
if (state_X) {
Joystick.setButton(2, pressState);
} else {
Joystick.setButton(2, state_A);
}
if (state_Y) {
Joystick.setButton(1, pressState);
} else {
Joystick.setButton(1, state_B);
}
Joystick.setButton(4, state_L);
Joystick.setButton(5, state_R);
Joystick.setButton(8, state_SEL);
Joystick.setButton(9, state_START);
}
void toggleSwitch() {
pressState = !pressState;
}
ボタン | 機能 |
---|---|
十字キー | 移動 |
A | ボタン 3 |
B | ボタン 2 |
L | ボタン 5 |
R | ボタン 6 |
SELECT | ボタン 9 |
START | ボタン 10 |
X / Y ボタンは A / B ボタンの連射となっています。
ボタン | 機能 |
---|---|
X | A ボタン連射 |
Y | B ボタン連射 |
スケッチ (汎用)
こちらは汎用の 8 ボタンコントローラーです。ボタンの動作テストにはこちらの方がいいかもしれません。
・スケッチのコンパイルには『Arduino Joystick Library 2.x』が必要です。
#include <Joystick.h>
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 8, 1,
false, false, false, false, false, false,
false, false, false, false, false);
/* PINS */
const int PIN_UP = A0;
const int PIN_DOWN = A3;
const int PIN_LEFT = A2;
const int PIN_RIGHT = A1;
const int PIN_A = 7;
const int PIN_B = 8;
const int PIN_X = 9;
const int PIN_Y = 10;
const int PIN_L = 3;
const int PIN_R = 4;
const int PIN_SEL = 5;
const int PIN_START = 6;
const int16_t Angles[16] = {
JOYSTICK_HATSWITCH_RELEASE, 180, /* Down */
270, /* Left */ 225, /* Left-lower */
90, /* Right */ 135, /* Right-lower */
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE,
0, /* Up */ JOYSTICK_HATSWITCH_RELEASE,
315, /* Left-upper */ JOYSTICK_HATSWITCH_RELEASE,
45, /* Right-upper */ JOYSTICK_HATSWITCH_RELEASE,
JOYSTICK_HATSWITCH_RELEASE, JOYSTICK_HATSWITCH_RELEASE};
boolean pressState = false;
void setup() {
pinMode(PIN_UP , INPUT_PULLUP);
pinMode(PIN_DOWN , INPUT_PULLUP);
pinMode(PIN_LEFT , INPUT_PULLUP);
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_A , INPUT_PULLUP);
pinMode(PIN_B , INPUT_PULLUP);
pinMode(PIN_X , INPUT_PULLUP);
pinMode(PIN_Y , INPUT_PULLUP);
pinMode(PIN_L , INPUT_PULLUP);
pinMode(PIN_R , INPUT_PULLUP);
pinMode(PIN_SEL , INPUT_PULLUP);
pinMode(PIN_START, INPUT_PULLUP);
Joystick.begin();
}
void loop() {
/* Arrows */
int HatState = (!digitalRead(PIN_UP) << 3) |
(!digitalRead(PIN_RIGHT)<< 2) |
(!digitalRead(PIN_LEFT) << 1) |
(!digitalRead(PIN_DOWN) );
Joystick.setHatSwitch(0, Angles[HatState]);
/* Buttons */
Joystick.setButton(0, !digitalRead(PIN_A ));
Joystick.setButton(1, !digitalRead(PIN_B ));
Joystick.setButton(2, !digitalRead(PIN_X ));
Joystick.setButton(3, !digitalRead(PIN_Y ));
Joystick.setButton(4, !digitalRead(PIN_L ));
Joystick.setButton(5, !digitalRead(PIN_R ));
Joystick.setButton(6, !digitalRead(PIN_SEL ));
Joystick.setButton(7, !digitalRead(PIN_START));
}
ボタン | 機能 |
---|---|
十字キー | 移動 |
A | ボタン 1 |
B | ボタン 2 |
X | ボタン 3 |
Y | ボタン 4 |
L | ボタン 5 |
R | ボタン 6 |
SELECT | ボタン 7 |
START | ボタン 8 |
スケッチ (XInput 連射)
X68000Z では使えませんが、XInput 方式の連射コントローラーです。Steam なんかで使えます。
・スケッチのコンパイルには『MsTimer2』(ライブラリの追加で検索してください) が必要です。
・コンパイルには『Arduino XInput Library』ライブラリが必要です。
・ボードマネージャで『SparkFun AVR Boards w/ XInput』をインストールする必要があります。
・2 回目以降の書き込みにはリセットのダブルクリックが必要です (要リセットボタン)。
#include <XInput.h>
#include <MsTimer2.h>
// Setup
const boolean UseLeftJoystick = false; // set to true to enable left joystick
const boolean InvertLeftYAxis = false; // set to true to use inverted left joy Y
const boolean UseRightJoystick = false; // set to true to enable right joystick
const boolean InvertRightYAxis = false; // set to true to use inverted right joy Y
const boolean UseTriggerButtons = true; // set to false if using analog triggers
/* PINS */
const int PIN_UP = A0;
const int PIN_DOWN = A3;
const int PIN_LEFT = A2;
const int PIN_RIGHT = A1;
const int PIN_A = 7;
const int PIN_B = 8;
const int PIN_X = 9;
const int PIN_Y = 10;
const int PIN_L = 3;
const int PIN_R = 4;
const int PIN_SEL = 5;
const int PIN_START = 6;
static bool pressState = false;
void setup() {
pinMode(PIN_UP , INPUT_PULLUP);
pinMode(PIN_DOWN , INPUT_PULLUP);
pinMode(PIN_LEFT , INPUT_PULLUP);
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_A , INPUT_PULLUP);
pinMode(PIN_B , INPUT_PULLUP);
pinMode(PIN_X , INPUT_PULLUP);
pinMode(PIN_Y , INPUT_PULLUP);
pinMode(PIN_L , INPUT_PULLUP);
pinMode(PIN_R , INPUT_PULLUP);
pinMode(PIN_SEL , INPUT_PULLUP);
pinMode(PIN_START, INPUT_PULLUP);
XInput.setAutoSend(true);
XInput.begin();
MsTimer2::set(31, toggleSwitch);
MsTimer2::start();
}
void loop() {
/* Arrows */
bool state_AU = !digitalRead(PIN_UP);
bool state_AR = !digitalRead(PIN_RIGHT);
bool state_AL = !digitalRead(PIN_LEFT);
bool state_AD = !digitalRead(PIN_DOWN);
if ((state_AU && state_AD) || (state_AL && state_AR)) {
XInput.setDpad(false, false, false, false, false);
} else {
XInput.setDpad(state_AU, state_AD, state_AL, state_AR, false);
}
/* Buttons */
bool state_A = !digitalRead(PIN_A);
bool state_B = !digitalRead(PIN_B);
bool state_X = !digitalRead(PIN_X);
bool state_Y = !digitalRead(PIN_Y);
bool state_L = !digitalRead(PIN_L);
bool state_R = !digitalRead(PIN_R);
bool state_SEL = !digitalRead(PIN_SEL);
bool state_START = !digitalRead(PIN_START);
if (state_X) {
XInput.setButton(BUTTON_A, pressState);
} else {
XInput.setButton(BUTTON_A, state_A);
}
if (state_Y) {
XInput.setButton(BUTTON_B, pressState);
} else {
XInput.setButton(BUTTON_B, state_B);
}
XInput.setButton(BUTTON_BACK , state_SEL );
XInput.setButton(BUTTON_START, state_START);
XInput.setButton(BUTTON_LB , state_L );
XInput.setButton(BUTTON_RB , state_R );
}
void toggleSwitch() {
pressState = !pressState;
}
ボタン | 機能 |
---|---|
(なし) | ロゴボタン |
A | A ボタン |
B | B ボタン |
X | A ボタン連射 |
Y | B ボタン連射 |
(なし) | X ボタン |
(なし) | Y ボタン |
L | L ボタン |
R | R ボタン |
SELECT | Back ボタン |
START | Start ボタン |
(なし) | L3 ボタン 1 |
(なし) | R3 ボタン 2 |
十字キー | デジタル方向パッド |
(なし) | L トリガー |
(なし) | R トリガー |
(なし) | アナログ方向スティック L |
(なし) | アナログ方向スティック R |
See also:
- Windows アプリケーション上の XInput の概要 (learn.microsoft.com)
- Pro Micro を Xinput コントローラーとして動作させる (Qiita: @sh00t)
スケッチ (XInput 汎用)
X68000Z では使えませんが、XInput 方式の汎用コントローラーです。Steam なんかで使えます。
・コンパイルには『Arduino XInput Library』ライブラリが必要です。
・ボードマネージャで『SparkFun AVR Boards w/ XInput』をインストールする必要があります。
・2 回目以降の書き込みにはリセットのダブルクリックが必要です (要リセットボタン)。
#include <XInput.h>
// Setup
const boolean UseLeftJoystick = false; // set to true to enable left joystick
const boolean InvertLeftYAxis = false; // set to true to use inverted left joy Y
const boolean UseRightJoystick = false; // set to true to enable right joystick
const boolean InvertRightYAxis = false; // set to true to use inverted right joy Y
const boolean UseTriggerButtons = true; // set to false if using analog triggers
/* PINS */
const int PIN_UP = A0;
const int PIN_DOWN = A3;
const int PIN_LEFT = A2;
const int PIN_RIGHT = A1;
const int PIN_A = 7;
const int PIN_B = 8;
const int PIN_X = 9;
const int PIN_Y = 10;
const int PIN_L = 3;
const int PIN_R = 4;
const int PIN_SEL = 5;
const int PIN_START = 6;
void setup() {
pinMode(PIN_UP , INPUT_PULLUP);
pinMode(PIN_DOWN , INPUT_PULLUP);
pinMode(PIN_LEFT , INPUT_PULLUP);
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_A , INPUT_PULLUP);
pinMode(PIN_B , INPUT_PULLUP);
pinMode(PIN_X , INPUT_PULLUP);
pinMode(PIN_Y , INPUT_PULLUP);
pinMode(PIN_L , INPUT_PULLUP);
pinMode(PIN_R , INPUT_PULLUP);
pinMode(PIN_SEL , INPUT_PULLUP);
pinMode(PIN_START, INPUT_PULLUP);
XInput.setAutoSend(true);
XInput.begin();
}
void loop() {
/* Arrows */
bool state_AU = !digitalRead(PIN_UP);
bool state_AR = !digitalRead(PIN_RIGHT);
bool state_AL = !digitalRead(PIN_LEFT);
bool state_AD = !digitalRead(PIN_DOWN);
if ((state_AU && state_AD) || (state_AL && state_AR)) {
XInput.setDpad(false, false, false, false, false);
} else {
XInput.setDpad(state_AU, state_AD, state_AL, state_AR, false);
}
/* Buttons */
XInput.setButton(BUTTON_A , !digitalRead(PIN_A ));
XInput.setButton(BUTTON_B , !digitalRead(PIN_B ));
XInput.setButton(BUTTON_X , !digitalRead(PIN_X ));
XInput.setButton(BUTTON_Y , !digitalRead(PIN_Y ));
XInput.setButton(BUTTON_LB , !digitalRead(PIN_L ));
XInput.setButton(BUTTON_RB , !digitalRead(PIN_R ));
XInput.setButton(BUTTON_BACK , !digitalRead(PIN_SEL ));
XInput.setButton(BUTTON_START, !digitalRead(PIN_START));
}
ボタン | 機能 |
---|---|
(なし) | ロゴボタン |
A | A ボタン |
B | B ボタン |
X | X ボタン |
Y | Y ボタン |
L | L ボタン |
R | R ボタン |
SELECT | Back ボタン |
START | Start ボタン |
(なし) | L3 ボタン 1 |
(なし) | R3 ボタン 2 |
十字キー | デジタル方向パッド |
(なし) | L トリガー |
(なし) | R トリガー |
(なし) | アナログ方向スティック L |
(なし) | アナログ方向スティック R |
おわりに
『X68000Z PRODUCT EDITION (BLACK MODEL)』から『X68000 Z ジョイカード』が付属し、単体で購入もできるようになったので、ゲームコントローラーの問題は解消されつつあります。
『Hacker's Edition』『Early Access Kit』ユーザーの方は一つ確保しておく事をオススメします。
See also:
- Arduino Leonardo(Pro Micro)を利用した旧型パッド(DB9)USB接続アダプタ(X68000Z用)|ichibey
- レトロゲーマーに送る~スーパーファミコンコントローラをPCで使う方法~ (Qiita: @odanny)
- じょいぽーとU君 (TNB製作所)
- 昔のゲーム用コントローラでメガドライブミニを楽しみたい まとめ (HD61700 SPIRITS)
- X68000Z版グラディウスをXboxコントローラーでSteam版グラディウス風の操作で遊ぶ (Z-Club: @nobu24)