せっかなくので、やってみた。

日々のあんなこと、こんなこと、せっかくなのでやってみた

乗っ取り方式でX68とnintendo switch両方使えるアケコンを作ってみた

この記事は令和の時代もなお続くX68000用ディスクマガジン「ハリキリマガジン」の 41号(2020年7月)に収録していただいた内容にリンク等の修正を加えたものです。(タイトル「アケコンのススメ」)

また、以降の説明で改造した内容や選定したコントローラ類は間違った記述があったり、正しく動作しないかもしれません。 参考にされる方は自己責任でお願いします。

アケコンのススメ」

皆さんは68でゲームする時、どんなコントローラーを使ってますか?
我が家は長らくPanasonic製のMSX用パッドを使用していました。(恐らくFS-A1と同時に発売されたやつ?)
数年前に電波のXE-1proをたまたま安くゲットできたのですが、思っていたより小さくてワイン持ちに慣れている私にはちょっと使いにくく感じていました。

話は変わってNintendo switchですが、PS4に負けじとこちらもアーケードの復刻が増えてきて、ナムコミュージアムコナミアーケードコレクションダライアスなど、自分のラインナップも増えてきました。
そうすると、やっぱりジョイコンではなく、ちゃんとしたアケコンでプレイしたいという欲望が湧いてきます。
アケコンと言えばホリのリアルアーケードシリーズ(RAP)ですが、レトロゲームメインの私にはさすがにちょっと大きすぎるので、Mayflashや8bitdoなどのアケコンがいいなーと思いつつ、せっかくアケコン買うならどうにかX68でも使えないか、あれこれ妄想してみました。
で、思いついたのが以下の案です。

1.switch用Bluetoothアケコン + レトロレシーバー
※以降のリンク先はAmazonアフィリエイトになっていますので、けしからん!という方は、アイテム名をGoogleなどで検索してください。

  • コードレスですっきするが、Bluetoothなので充電を気にする必要がある。
  • あと都度接続先を切り替えたりなど、意外とペアリングの手間がかかりそう。そもそもswitch用のBluetoothアケコンが高い。(1万円以上)

2.switch/PS4兼用有線アケコン + スーパーコンバーター

  • こちらも導入コスト高し。有線だが変換をかますので、ラグも心配。
  • PCエンジンにも使えるのはメリット高い

3.PS1/2コントローラー +スーパーコンバーター(PS1/2->switch)
  + PS1/2->Atari変換(mobile-accessory-net)

sv35.wadax.ne.jp

  • 中古で安く入手できそうなPS用のコントローラーが使えるものの、switch/68ともどっちも変換必要。
  • 導入コストは他より比較的安めで済みそうだが結局こちらも変換器のラグがどれくらいか不明。
  • あと、PS1/2->Atari変換は貴重な存在。在庫限りなので気になる方は手に入れておいた方が良いかもしれません。

この様に一長一短かつ、どれも結構な投資が必要です。
2が割とベストな組み合わせかと思いますが、結局自分が欲しいのは、ラグの心配がなく、低コストで両環境で使用できるアケコンという事が分かり、なかなか購入に踏み切れない状態でした。

そんな中、ネットで中古のアケコンを探していると、既製のアケコンに他機種用のコントローラーの基盤と接続ケーブルを移植する、いわゆる「乗っ取り」という手法があることを知りました。
物理的にケースに収まる必要があるものの、使用したいハードのコントローラー基板さえあれば、どんなコントローラーでも利用できるのです。
しかも、配線さえ気を付ければ、複数のコントローラ基板を同居させることもできるという事を知ってしまったのです!(当然その分配線も増えます)
これでswitchと68兼用の、ラグの無いコントローラーが手に入る!しかも中古でそろえれば格安で!

幸いにも、我が家にはスパII(もちろん68用)にメガドラの6ボタンパッドを2つ当時購入してずっと保管していたので、ATARI用のコントローラー基板はこちらを使用することにしました。せっかくアケコンを導入するなら、スパIIもアケコンでプレイしたいですからね。
今の中古の相場を見ると、メガドラの6ボタンパッドは非常に貴重なのですが、利用頻度も少ないので1つ使用することにしました。
メガドラ->68の変換は、当時自作していたチェルノブアダプター互換の変換器(というほどのものではありませんが)があるので、こちらを使用します。

switch用のコントローラーは、ネットで安いのを調べたところ、WiiU用のポッ拳コントローラーが実はswitchにも対応している事を知り、早速中古で入手しました。(しかしこれが後で大変な作業になる羽目に…。)

あとは乗っ取りするアケコン本体の方ですが、こちらは気長に中古品を物色しました。
初めはサターン用のバーチャスティックがアストロ筐体のデザインを踏襲していてかっこいいので狙っていましたが、人気の高い商品らしく、なかなか安値で入手することができませんでした。(だいたい4-5千円くらい?)
うーん、昔ハードオフのジャンクに出ていたのを見かけたことがありましたが、サターン用という事で完全スルーしていました。あの時気が付いていれば。

他に良さげなコントローラーを探していたところ、PS1/2用のnamcoアケコンもありました。
バーチャスティックと比べるとデザインは地味ですが、往年(割と後期?)のnamcoテーブル筐体を連想させる黄色のスティックとボタン、そしてやはりnamco世代としては、namcoのロゴがプリントれているだけでもかっこいいと思えてしまう。(笑
なので、こちらも候補としました。
ただバーチャスティックより年代的に古いようで、状態の良いものがなかなか出なかったのですが、粘って結局こちらを入手しました。
(箱には鉄拳が記載されていたのでPS1初期のものかもしれません)
決め手となったのは、ボタンの数です。
というのもポッ拳コントローラーのボタンがA/B/X/Y/L/ZL/R/ZR/+/-の10コ(本来のswitchコントローラーはこれにホームを合わせた11コ)に対して、バーチャスティックは9コなので1コ足りなくなってしまうのです。
穴あけ加工してボタンを追加しても良いのですが、結構大変そうですし、namcoコントローラーは初めから10コなのでこの手間が省けます。ただ、L1/L2ボタンが小さいのでゲームによっては不向きがあるかもしれません。

かくして材料は揃いました。あとは分解して配線です。

f:id:moneci:20210131172311j:plain
メガドラパッドは一緒に撮り忘れました

まずはnamcoコントローラーの裏蓋を外します。
ボタンの上にPS用の基板が半田付けされているので、半田を溶かして外しました。レバー側のコードも端子に半田付けされていたのでこちらも外しました。
f:id:moneci:20210131172323j:plain

f:id:moneci:20210131172335j:plain
レバーのコードを外す前です。select系ボタンのコードはコネクタ部を切り取ってそのまま流用しました。

今まで知らなかったのですが、コントローラの各ボタンやレバーは、プラス(VCC)とマイナス(GND)の端子があり、ボタンを押下する(レバーは倒す)ことにより、配線がつながる仕組みとなっていました。
パッドの場合は電気を通すゴムの様な素材がボタンの下に入っていて、押下することにより基板のVCCとGNDの端子に密着、通電し、押下を検出していました。
なので、(例えばボタンの場合なら)パッドから取り外した基板のVCCからアケコンのボタンのVCCへ配線し、ボタンのGNDから基板のGNDへ配線することにより、アケコンのボタン押下でパッドの基板がボタン押下したと判定できるようになります。
(用語は詳しくないので間違っているかもです。)
f:id:moneci:20210131172345p:plain

今回は、switchのコントローラー基板とメガドラのコントローラ基板のそれぞれのVCCをアケコンのVCCへ、アケコンのGNDからそれぞれのコントローラ基板のGNDに配線することになるのですが、ちょっと注意が必要です。
というのは、ネットで調べたところ、ボタン押下(スイッチをON)した時に両方のコントローラ基板に通電してしまうので、誤動作する可能性があるのだそうです。
なので、それぞれの基板に電気が逆流しないよう、ダイオードを入れると良いとの事でした。
ダイオードは電流の流れを一方通行にする部品というのを、今回初めて知りました。(中学とかで習っていたのかもしれませんが覚えていないです。)
f:id:moneci:20210131172349p:plain

こちらのサイトのまんまですが、非常に役に立ちました。
gamest.at.webry.info

なので、初めの作業はダイオード入りのコードを作成することです。
上記のサイトにある通り、購入してきたダイオード(1N4148)の両端にコードを半田付けし、絶縁の為に収縮チューブでダイオードをカバーします。
1本は簡単に作れますが、各ボタン、レバーで14本、さらにコントローラ基板2つ分なので合計28本作成するとなるとなかかな大変な作業でした。
(SELECTやL1/L2はメガドラパッドでは不要なのですが、念のため作成しました。)
今思うとダイオードをの足をもっと短くしないと、何かの拍子にポキッと折れてしまいそうですね。。。
f:id:moneci:20210131172401j:plain

(写真では既に加工済みですが)さらに出来上がったコード2本の片側をまとめて平型端子(メス)に圧着します。
アケコンのボタン、レバー側も平型端子(オス)を半田付けしてあり、将来的にボタンやレバーを交換する際に取り外ししやすようにしました。
作業中、ボタンを2つ壊してしまったので、秋葉原の千石商会ラジオデパート店で購入したボタンに入れ替えています。
セイミツ工業のφ30 はめ込み式(@\240) ですが、こちらの方が少しクリック音が低い(主観ですが静かというわけではない)のと、若干黄色が濃いです。
2つなので、ちょうど68で使用した時のA/Bボタン部分に使用することにしました。
f:id:moneci:20210131172417j:plain

アケコン側のボタン、レバーのGNDはSCSIの様な感じで数珠繋ぎに全て結線し、最終的に2本のコードに集約してそれぞれのコントローラ基板の適当な1箇所のGNDへ配線することにしました。
こちらも知らなかったのですが、GNDは各ボタンに配線する必要は無く、どこか1箇所のGNDにまとまっていても問題無く動作するみたいです。機器によってはだめな場合もあるようですが、ポッ拳コントローラー、メガドラパッドは問題ありませんでした。

次にコードの反対側をコントローラ基板に配線してゆきます。
メガドラパッドを分解し、基板を取り出したあと、各ボタン、方向キーのVCC端子の黒い部分をヤスリで削り、銅板を露出させます。
GNDは一か所で良いので、配線しやすいボタン(今回は左キーと予備でスタートボタン)を削りました。
これで半田が乗るようになるので、コードを半田付けしてゆきます。その後、半田が外れないようにグルーガンで固定しました。
f:id:moneci:20210131172429j:plain f:id:moneci:20210131172441j:plain f:id:moneci:20210131172457j:plain

ポッ拳コントローラー基板の方はボタンのVCC部を削らずとも、その手前に丸い銅端子が露出していて、ここに半田付けできる状態になっていました。 こちらのサイトにボタンの対応が写真で解説されていて、非常に助かりました。
pomegd.hatenablog.com

半田付け作業は簡単に終わり、いざ確認しようと基板を持ち上げた瞬間、半田付けした部分が銅端子ごとポロっと取れてしまいました!しかも3箇所もです!!
外れたところを見ると、銅の金属部分が完全に剥がれてしまって、再度半田付けができない状態になってました。
68のコンデンサ交換でいう「パターン剥がし」の状態です。(泣
ボタン部分を削れば銅端子は見えますが、剥がれてしまった部分はボタンとチップの間なので、もうボタン部分も通電しない状態です。
もう1つポッ拳コントローラーを買うしかないかと諦めかけましたが、ダメ元で剥がれた端子より少しチップ側の表面をカッターでけずると、銅端子が見えました。
Windows10に繋いで、銅端子にコードを接触させると、ボタン押下の反応があったので、ここに半田付けできればなんとか復活できそうです。
(思わぬ誤算でしたが、ポッ拳コントローラーはWindows10でも普通にゲームコントローラーとして認識してくれました。)
しかし削った部分は1ミリもないくらいの細さで、とてもコードの銅線をつなげられるほどの半田が乗りそうにはありませんでした。
そこで一旦ダイオードを切り取った足を削った部分に半田付けし、さらに足部分にコードを半田付けした後、速攻でグルーガンで固定し、何とか繋ぐことができました。
特にXボタンは心が折れそうなるくらい何度も失敗しましたが、お陰で68のパターン剥がしをやっても、落ち着て対処できそうです。(笑
ちょっと基板を歪めたら外れてしまいそうですが、いまのところ何とか持ちこたえてくれています。
ちなみにここは撮影どころではない位焦っていたいので、写真がありません。(笑
配線後はこんな感じです。
f:id:moneci:20210131172508j:plain

そんなこんなで配線と動作確認は完了し、最終段階のケース収めです。
このコントローラーは、手前側が薄くなるよう傾斜がついているので、普通のアケコンよりかなり狭く、ぎゅうぎゅうの状態です。 f:id:moneci:20210131172526j:plain

構想時ははPSの基板も残して3機種マルチも考えたのですが、早々に諦めました。(笑
コードを挟まないよう蓋をしめて、遂に完成です!

f:id:moneci:20210131172539j:plain
正面
f:id:moneci:20210131172550j:plain
後ろから

これでswitchと68で快適なアケコンライフが楽しめるという事で、早速68と自作の変換器経由で接続し、スパIIを遊んでみました。
ワイン持ちもしっくりくるし昇竜拳も簡単に出せる!(ウソです、春麗使いなのでリュウはへたくそです)
それでもパッドより各段に操作性が良い!
この調子でグラIIも!あれ、自機が勝手に左へ移動する。。。ボタンも反応しない。。。
そうでした、変換器を使っていてもスパII以外はまともにコントローラーが動作しないのを思い出しました。
(スパIIブームが過ぎた後は、ずっとMSXパッドを使用していたのはこの理由でした。)

しかしネットの情報ではメガドラパッドをMSXで使う情報が結構あります。
68とMSXATARIコネクタの仕様は同じはずなのに、なぜ68だけ動かないのだろう。。。
おかしいなと思いつつ、MSXの配線図と自作変換機の配線を見比べてみました。

[Saiey様のサイトから] sai.cside.tv

X68k側(オス)
1 2 3 4 5 6 7 8 9
| | | | | | | | |
1 2 3 4 5 6 9 7 8
メガドラパッド側(メス)

確か電クラに掲載された情報で私も同じように作成したと思います。

MSXで動作確認情報のある配線はこちら
[ギルだめス様のサイトから] ch.nicovideo.jp

MSX側(オス)
1 2 3 4 5 6 7 8 9
| | | | | | |   |
1 2 3 4 5 9 6   8
メガドラパッド側(メス)

自作の方は9本すべて接続しているのにMSXの配線方は1本使ってないぞ。配線も微妙に違う。。。
そうです、スパII用の変換(チェルノブ互換)の配線と、2ボタンパットとして使用する場合の配線の仕方が異なっているのでした。
早速、変換器の片方(こちらもパッドとセットで2つ制作していた)をMSX仕様に配線を変更したところ、問題無く反応してくれました。
20数年来、この謎に気づきませんでした。もっと早く知っていればメガドラパッドも活躍しただろうに。。。
ちなみに、私の作成した変換器のコネクタ部分は、カバーを装着すると、カバーの出っ張りが邪魔して68側に刺すことができなくなってしまうので、配線むき出しの状態で使用していました。
無理に力をかけると、コードが切れてしまうので、68本体への抜き差しに非常に気をつかったので、この事もそのうち使用しなくなってしまった一因でもあります。
今回配線を変更したついでに、コネクタの補強もかねてコネクタ部分をプラ板で囲み、中にグルーガンを流し込んで超適当な持ち手部分を作成しました。これも20数年前には思いつかなかったワザです。(笑
f:id:moneci:20210131172603j:plain

これでswitch/68両対応のアケコン制作は無事終了しました。
ちなみに、68で使用する時は、6ボタンあるうちの下段右から2つ(〇とR2)がB/Aボタンに割り当てられます。
switchの方も元々専用コントローラーの基板を使っていたので、問題なく利用できています。
2機種対応という事で配線が大変だったり、思わぬトラブルみも見舞われましたが、出来上がったコントローラーはシューティングはもちろんの事、アクションゲームもとても操作しやすく、パッドでプレイするより明らかに上手くなった気がします。これであと10年は戦えそうです。(笑
あと、配線の変更でメガドラパッドが2ボタンコントローラーとしてちゃんと利用できる事が分かったのも収穫でした。

68で使用するには一緒に変換器を作らなければならない手間があるものの、3ボタンのアケコンメガドラの3ボタンパッドは数百円で売られていることもあるので、6ボタンや複数機種対応に拘らなければ、手間も少なく格安で制作できるでしょう。
(なにげにMSX用のパッドの方が値段が高かったりします。あとメガドラの連射付きパッドは上手く動かないかもしれません。)
興味のある方は是非自分だけのアケコンを制作されてみてはいかがでしょうか。

ちなみに今回かかった費用は
namcoコントローラー \1,300
ポッ拳コントローラー  \800
セイミツ工業のφ30 はめ込み式ボタン \240 x 2 = 480
送料やコード、ダイオードなど含めると、合計で\5,000位かなといったところです。

【お知らせ】
YouTubeでもX68000に関する動画を配信しております。よろしかったらこちらもどうぞ。 www.youtube.com

Windowsのskypeで何故か背景を変更できない件

昨年からのリモートワークでテレビ会議の機会も増えてきました。
zoomやGoogle meetでは背景画像を差し替えたり、ぼかしたりすることができるので、 skypeでもできるだろうと設定を探してみたら設定項目がありませんでした。

skypeのヘルプでは、設定の中に[背景効果の選択]があると書いてあるのだけど、 やっぱり見つからない。

support.skype.com

どうもストアアプリ版のSkypeはこの設定が無く、デスクトップ版のSkypeのみこの設定が可能な様です。
ストアアプリ版のSkypeをアンインストール、デスクトップ版をインストールし、無事背景を変更する事ができました。

f:id:moneci:20210113100147p:plain

しかし、ストアアプリ版、デスクトップ版のどっちを使っているのかの確認方法も、バージョン情報で「Skype が最新の状態です」が出るかどうかで 判定しろって、どうなんでしょうね。

answers.microsoft.com

XEiJ ver0.19.12.15 がJDK13で動かないのでJDK11でコンパイルしなおしてみた。(解消しました)

javaで動作する唯一のX680x0エミュレータであるkamada大先生のXEiJですが、JDK13の環境に対応した最新のver0.19.12.15が私の環境では以下のエラーで起動しませんでした。

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffe8380f98a, pid=25780, tid=18720
#
# JRE version: OpenJDK Runtime Environment (13.0.2+8) (build 13.0.2+8)
# Java VM: OpenJDK 64-Bit Server VM (13.0.2+8, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C  [awt.dll+0x8f98a]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\hogehoge\hs_err_pid25780.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

原因がわからず、長らくJDK11で動作するひとつ前のバージョン(0.19.01.24)を使っていましたがふと思い立って最新のJDK13.0.2+8や、JDK15.0.1で動かしてみても結果は同じでした。> <
うーん、ネットには動作しないなんて情報は無いので私の環境だけなのか。。。
hs_err_pid25780.logを見ろと出ているので、中身を見てみましたが、よく分からないながらもスタックトレースには

 914 Event: 0.099 Thread 0x0000019034a8c800 Exception <a 'java/lang/ClassNotFoundException'{0x0000000711f52be0}: sun/awt/resources/spi/awtProvider> (0x0000000711f52be0)

という出力があったので、AWT回りのクラスが見つからないのかなーと。
このエラーメッセージを検索すると、AWTのバグっぽい記述がいくつか見つかりました。

bugs.java.com

アーカイブに含まれているXEiJ.jarと実行しているJDK13のバージョンの差異によるものかと思い、kamada先生のサイトに掲載されいてるコンパイル手順でビルドしてみましたがJDK13を使ってビルドしてもエラー解消されませんでした。
ちなみにコンパイル手順はこちら。DOSCygwin、はたまたPowerShellのビルド手順が記載されていてとても親切です。

stdkmd.net

しかし、ダメもとでJDK11を使ってコンパイルしたところ、コンパイル/起動まで成功しました!
「XEiJ のコンパイルと実行に JDK 13.0.1 GA Release を使います。」と明記されているので、使っていたら落ちてしまう可能性がありますが、 今のことろ動作しています。

2020.12.6追記
恐れ多くも直接ご本人にお伺いしたところ、セキュリティの懸念もあるので、JDKは常に最新版を用いることをお勧めするとの事でしたので、 上記は推奨される対応方法ではありません。

上記のサイトまんまですが、コンパイル手順を記載します。(Cygwinを使っているのでその前提で。)

export JAVA_HOME=/hogehoge/jdk-11
export PATH=$JAVA_HOME/bin:$PATH
java -version
  Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
  openjdk version "11" 2018-09-25
  OpenJDK Runtime Environment 18.9 (build 11+28)
  OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

cd XEiJ
rm -f class/xeij/*.class
javac -encoding UTF-8 -d class xeij/*.java -Xlint:all -Xlint:-serial -Xlint:-fallthrough -Xdiags:verbose
rm -f XEiJ.jar
jar cfe XEiJ.jar xeij.XEiJ -C class . -C . xeij/IPLROM.DAT xeij/IPLROMXV.DAT xeij/IPLROMCO.DAT xeij/IPLROM30.DAT xeij/CGROM_XEiJ.DAT xeij/HUMAN.SYS xeij/COMMAND.X xeij/license_XEiJ.txt xeij/license_FSHARP.txt xeij/license_MAME.txt

java -jar /hogehoge/XEiJ/XEiJ.jar

2020.12.9追記
原因が分かりました。
XEiJ起動時に、環境変数 JAVA_TOOL_OPTIONS に -Dfile.encoding=UTF-8 をセットしていると発生し、上記の値を削除したところ、問題無く起動しました。
どうもこちらに記載されいているバグの様です。

bugs.java.com

なぜ自分の環境でJAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 をセットしていたか覚えていないのですが、しばらくこのオプションは削除して使用してみたいと思います。
尚、ページに記載されている 11.0.10-oracle は無償サポートでは入手できないっぽいので、jdk15、jdk16の今後のリリースで解消されると思われます。 これで最新のXEiJが使えるようになりました。

ParcelのビルドでIE11対応しつつasyncを使いたい

ES6のasync/awaitを使用しているプロジェクトでずっとchromeで開発していたのですが、ある日IE11で動作確認するとエラーで動かない事が分かりました。
エラー発生行をデバッガー見ると、アロー演算子の箇所でエラーになっています。
JSのビルドにはParcelを使用していたので、普通にIE11でも動くようトランスパイルされていると思ったのですが、そうではないみたいです。

ググってみると、.babelrcのbrowsersの項目に対応ブラウザを記述する必要があるようなので、以下の様に「,"ie 11"」を追加してみました。

{
  "presets": [
    [
      "env", {
        "targets": {
          "browsers": ["last 2 Chrome versions", "ie 11"]
        }
      }
    ]
  ]
}

すると、今度はchromeでも別のエラーが発生するようになってしまいました。

Uncaught ReferenceError: regeneratorRuntime is not defined

ググってみるとasync/awaitを使用しているとトランスパイルがうまくできなくて発生する様でした。
.babelrcの"ie 11"の設定を外すと問題無く動くのは、chromeが元々async/await対応しているためっぽいです。

IE11でも動作するようしたいので、色々調べたのですが、babel7.4以降とそれより前で対応方法が変わってしまい、私の環境で動作する情報が見つかりませんでした。
現在インストールされているbabelとparcelを確認すると以下となっています。

parcel 1.12.4
babel 6.26.3

babelが結構古いので、1から環境を作り直すことにしました。

まずは、現在のbabel、node関連のファイル、ディレクトリをバックアップ

mv .babelrc .babelrc.bak
mv node_modules node_modules.bak
mv package.json package.json.bak
mv package-lock.json package-lock.json.bak

次に、公式の手順で、parcelをインストール(npmを使うのでここからはDOSで実行)

cd プロジェクトディレクトリ
npm install parcel-bundler
npm init -y

ついでにnpxもインストール

npm instal npx

parcelでビルド

npx parcel watch xxxx\bundle.js -d xxxx/js --public-url .

ビルドは通りますが、この状態でも"regeneratorRuntime is not defined"は解消されませんでした。

こちらの記事を参考に追加でモジュールをインストール

qiita.com

npm install -D @babel/preset-env
npm install core-js

エントリポイントのJS(bundle.js)に以下を追加

import 'core-js/stable';
import 'regenerator-runtime/runtime';

以下の様に.babelrcにも@babel/preset-envの項目を追加(なくても動くっぽい?)

  "presets": [
    [
      "env", {
        "targets": {
          "browsers": ["last 2 Chrome versions", "ie 11"]
        }
      },
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ]
}

これでやっと"regeneratorRuntime is not defined"は解消されました!が、
今度は以下のエラーが。

vue.runtime.esm.js:619 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

このプロジェクトではVue.jsも使用していたのですが、どうもVueには完全ビルドとランタイムビルドでモジュールの使い方に違いがある様です。

qiita.com

多分単一コンポーネントを使っているから完全ビルドが必要なのかな?と思いつつ、さらに調べると、公式でもpackage.jsonに設定を追加するよう、記述がありました。

jp.vuejs.org

ということでpackage.jsonに以下を記述(環境作り直す前のpackage.jsonにはこの記述がありました。)

  "alias": {
    "vue": "./node_modules/vue/dist/vue.common.js"
  }

再度parcelでビルドしてIE11、chromeで問題無く動作しました!最終的にpackage.jsonの各モジュールのバージョンは以下になりました。

  "dependencies": {
    "axios": "0.21.0",
    "core-js": "3.7.0",
    "js-cookie": "2.2.1",
    "npx": "10.2.2",
    "vue": "2.6.12",
    "vue-hot-reload-api": "2.3.4"
  },
  "devDependencies": {
    "@babel/core": "7.12.3",
    "@babel/preset-env": "7.12.1",
    "@vue/component-compiler-utils": "3.2.0",
    "babel-preset-env": "1.7.0",
    "vue-template-compiler": "2.6.12"
  },
  "alias": {
    "vue": "./node_modules/vue/dist/vue.common.js"
  }

IE対応が入るとホントややこしくなります。

Z-MUSIC for the Webを使いたくてemsdkの環境をwindows10に入れてみた

もう3年以上前の話ですが、X68ユーザならご存じSION2をブラウザで動作するSION2 HDとして移植された @toyoshim氏がZ-MUSIC for the WebというJavaScriptでZ-MUZICを鳴らしてしまおうというモノを発表されていました。

qiita.com

去年あたりに発見し、これは素晴らしいということで自分でも使ってみたいと試してみたのですがドキュメントの通りJSを書いていても動作しない。。。再生方法が分からず、そのまま放置となってしまっていました。

かくして時は流れ、最近TwitterでMSXPlayというMSXの音源をWebで再生するサイトのシェアをちょいちょい見かけるようになりました。

msxplay.com

サイトに記載されている、"C言語版の libkss を EmscriptenJavaScript に変換"というあたりはZ-MUSIC for the Webと同じような技術を使用しているっぽい。
Z-MUSIC for the Webもエディタと組み合わせれば同じようなことができるのかなぁ、羨ましすぎるぞ、MSX勢!ということで、Z-MUSIC for the Webに再度トライしていました。

GitHubの説明を読み返し、zmusic.jsをビルドする必要があるとの事で(後で分かりましたが実は不要だったのですが。。。)以下を試してみました。

git clone https://github.com/toyoshim/z-music.js.git
cd z-music.js
git submodule update --init --recursive
git: 'submodule' is not a git command. See 'git --help'.

なぜかgitにsubmoduleが無いと言われてしまいます。
私の使っているgitはgnupack-pretest_develの2018.11.25に含まれているものでバージョンは2.17.0でした。
apt-cyg install gitとかやってみましたが状況は変わらないので、SourceTreeに内蔵されているgitにパスを通してこちらを使用したところ、無事git submoduleが起動しました。
ちなみにSourceTreeのgitは$USERPROFILE/AppData/Local/Atlassian/SourceTree/git_local/binにありました。
この下にはgitだけでなく、bashやshも含まれているのでcygwinのコマンドのパス(/usr/bin)より前に設定するとapt-cygなどが動作しなくなりました。git submoduleを使用した後は元に戻した方が良いでしょう。
とにかくこれでmakeが実行できるようになりました。

make
mkdir -p out
emcc -DFNC_TRACE -DENV_FROM_INI -DEMSCRIPTEN_KEEPR -include third_party/run68as/mod/preinc.h -I third_party/run68as/third_party/run68/src -I third_party/X68Sound/X68Sound -I src/compat -Oz -MM third_party/run68as/third_party/run68/src/ansicolor-w32.c third_party/run68as/third_party/run68/src/calc.c third_party/run68as/third_party/run68/src/conditions.c third_party/run68as/third_party/run68/src/disassemble.c third_party/run68as/third_party/run68/src/eaaccess.c third_party/run68as/third_party/run68/src/exec.c third_party/run68as/third_party/run68/src/getini.c third_party/run68as/third_party/run68/src/key.c third_party/run68as/third_party/run68/src/line0.c third_party/run68as/third_party/run68/src/line2.c third_party/run68as/third_party/run68/src/line5.c third_party/run68as/third_party/run68/src/line6.c third_party/run68as/third_party/run68/src/line7.c third_party/run68as/third_party/run68/src/line8.c third_party/run68as/third_party/run68/src/line9.c third_party/run68as/third_party/run68/src/lineb.c third_party/run68as/third_party/run68/src/linec.c third_party/run68as/third_party/run68/src/lined.c third_party/run68as/third_party/run68/src/linee.c third_party/run68as/third_party/run68/src/load.c third_party/run68as/mod/line4.c third_party/run68as/mod/linef.c third_party/run68as/mod/mem.c third_party/run68as/mod/run68.c src/doscall.c src/iocscall.c src/memop.c src/zmusic.cpp src/compat/compat.cpp src/x68sound.cpp> out/depend
/bin/sh: emcc: コマンドが見つかりません
make: *** 'all' に必要なターゲット 'out/depend' を make するルールがありません.  中止.
/bin/sh: emcc: コマンドが見つかりません

が、今度はemccが無いと怒られてしまいます。
どうやらemsdk (Emscripten) の環境も必要という事で、今度はemsdkのリポジトリを覗いてみました。

github.com

emsdkとはCやC++のコードをJavaScriptに変換して動作させる為のツール群の様です。
Z-MUSIC for the Webではrun68やx68soundをJavaScriptに変換してさらにエミュレーションを追加して動作させているようです。 まさに超絶技術ですね。

一応Windowsでもビルドできる記述があったのでcygwin上から以下を試しました。

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk/
./emsdk install latest
Traceback (most recent call last):
  File "./emsdk.py", line 3073, in <module>
    sys.exit(main())
  File "./emsdk.py", line 2781, in main
    load_sdk_manifest()
  File "./emsdk.py", line 2336, in load_sdk_manifest
    add_sdk(sdk)
  File "./emsdk.py", line 1972, in add_sdk
    raise Exception('Duplicate sdk ' + str(sdk) + '! Existing:\n{' + ', '.join("%s: %s" % item for item in vars(find_sdk(str(sdk))).items()) + '}, New:\n{' + ', '.join("%s: %s" % item for item in vars(sdk).items()) + '}')
Exception: Duplicate sdk sdk-upstream-master-64bit! Existing:
{version: upstream-master, bitness: 64, uses: ['llvm-git-master-64bit', 'node-12.18.1-64bit', 'python-3.7.4-64bit', 'emscripten-master-64bit', 'binaryen-master-64bit'], os: win, id: sdk, name: sdk-upstream-master-64bit, is_old: False, is_sdk: True}, New:
{version: upstream-master, bitness: 64, uses: ['llvm-git-master-64bit', 'node-12.18.1-64bit', 'emscripten-master-64bit', 'binaryen-master-64bit'], os: linux, id: sdk, name: sdk-upstream-master-64bit, is_old: False, is_sdk: True}

Exception: Duplicate sdk sdk-upstream-master-64bit! から察するにpythonが怪しいけどよく分からん。
cygwinpythonは2.7.14でemsdkの推奨バージョン以上だけど、cygwinで動かすのがそもそもサポートされていないかも。。。
という事で、DOSからemsdk.batを起動するため、まずはDOSを起動してpythonコマンドをたたいてみました。
するとMicrosoftStoreが勝手に起動してPythonをおすすめしてくれたのであまり考えずにインストール。
DOSから再度pythonをたたくと3.7.8がインストールされたので、以下を実行。

> .\emsdk.bat install latest
Installing SDK 'sdk-releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'..
Skipped installing node-12.18.1-64bit, already installed.
Skipped installing python-3.7.4-pywin32-64bit, already installed.
Skipped installing java-8.152-64bit, already installed.
Installing tool 'releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'..
Downloading: C:/hoge/emsdk/zips/e7e39da9c81faecd9ecf44065cee864d76e4e34d-wasm-binaries.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/e7e39da9c81faecd9ecf44065cee864d76e4e34d/wasm-binaries.zip, 551241164 Bytes
Unpacking 'C:/hoge/emsdk/zips/e7e39da9c81faecd9ecf44065cee864d76e4e34d-wasm-binaries.zip' to 'C:/hoge/emsdk/upstream'
Done installing tool 'releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'.
Running post-install step: npm ci ...
Done running: npm ci
Done installing SDK 'sdk-releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'.

無事インストールできました。次に環境の設定を行うため以下を実行。

> .\emsdk.bat activate latest
Setting the following tools as active:
   node-12.18.1-64bit
   python-3.7.4-pywin32-64bit
   java-8.152-64bit
   releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit

Adding directories to PATH:
PATH += \hoge\emsdk
PATH += \hoge\emsdk\node\12.18.1_64bit\bin
PATH += \hoge\emsdk\python\3.7.4-pywin32_64bit
PATH += \hoge\emsdk\java\8.152_64bit\bin
PATH += \hoge\emsdk\upstream\emscripten

Setting environment variables:
EMSDK = C:/hoge/emsdk
EM_CONFIG = \hoge\emsdk\.emscripten
EMSDK_NODE = \hoge\emsdk\node\12.18.1_64bit\bin\node.exe
EMSDK_PYTHON = \hoge\emsdk\python\3.7.4-pywin32_64bit\python.exe
JAVA_HOME = \hoge\emsdk\java\8.152_64bit
EM_CACHE = C:/hoge/emsdk/upstream/emscripten\cache
The changes made to environment variables only apply to the currently running shell instance. Use the 'emsdk_env.bat' to re-enter this environment later, or if you'd like to permanently register this environment globally to all users in Windows Registry, rerun this command with the option --global.

こちらも無事インストールされました。(のかな?)
これでやっとzmusic.jsがビルドできるようになりましたが、DOSにはmakeの環境が入っていません。
なので、cygwin(bash)の環境に上記のパスや環境変数をセットします。

~/.bash_profileに追記

export EMSDK=/hoge/emsdk
export EM_CONFIG=$EMSDK/.emscripten
export EMSDK_NODE=$EMSDK/node/12.18.1_64bit/bin/node.exe
export EMSDK_PYTHON=$EMSDK/python/3.7.4-pywin32_64bit/python.exe
#export JAVA_HOME=$EMSDK/java\8.152_64bit
PATH=$EMSDK/:$EMSDK/node/12.18.1_64bit/bin:$EMSDK/python/3.7.4-pywin32_64bit:$EMSDK/upstream/emscripten:$PATH
#$EMSDK/java/8.152_64bit/bin

JAVA_HOMEとjavaのパスは既に別のjava1.8がインストールしてあったので、省略しています。
bashを起動し、やっとzmusic.jsのmakeが通りました!
ということで、ディレクトリ配下にできあがったzmusic.jsと以下のファイルを用意し、chromeで表示してみました。

test.zms

(i)
(m1,3000)(aFm1,1)
(@1,28,  1,  7,  9,  0, 28,  0,  1,  0,  0,  0
 30,  1,  8, 10,  0,  1,  0,  1,  0,  0,  0
 29,  1,  8,  9,  0, 19,  0,  1,  3,  0,  0
 31,  1,  8, 10,  0,  1,  0,  1,  3,  0,  0
 4, 7)
(o127)
(t1) @01o4l8 cdefgab
(p)
<html>
  <head>
    <!-- <script src="zmusic.asm.js"></script> -->
    <script src="zmusic.js"></script>
    <script>
      // Make XHR to support Promise.
      function xhr (url) {
         return new Promise(function (resolve, reject) {
             var xhr = new XMLHttpRequest();
             xhr.open('GET', url, true);
             xhr.responseType = 'arraybuffer';
             xhr.addEventListener('load', e => {
                 resolve(xhr.response);
                 xhr.abort();
             }, false);
             xhr.send();
         });
      }

      Promise.all([
         ZMUSIC.install(),
         xhr('./test.zms')
      ]).then(results => {
         ZMUSIC.play(results[1]);
      });
    </script>
  </head>
</html>

するとブラウザに色々エラーが出てきました。たしか以前もこれで止まってしまっていたのだと思います。

both async and sync fetching of the wasm failed
RuntimeError: abort(both async and sync fetching of the wasm failed). Build with -s ASSERTIONS=1 for more info.
Access to XMLHttpRequest at 'file:///C:/hoge/test.zms' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

CORSのエラーも出ているので、そもそもWEBサーバ経由で表示しないとだめっぽいです。
WEBサーバ(nginx)のドキュメントルート配下にファイルを置いて、再度アクセス。
上記のエラーは全て解消されましたが、zmusic.wasm 404 (Not Found)のエラーが。
なるほど、z-music.js/dist/の中にzmusic.wasmがありがましたが、こちらも必要だったようです。
あらためてアクセスすると今度は以下のエラーが。

wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.

nginx(多分apacheも同様)のデフォルトのmime-typeにはapplication/wasmが無かったので、追加する必要があります。
/etc/nginx/mime.typesに次の行を追加して、nginxを再起動しました。

application/wasm                      wasm;

まだエラーが残っていて再生されませんが、最後のエラー

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page

は、どうやらJSでいきなり音を再生することは許可されていなくて、(ボタンクリックなど)何らかのユーザからのインタラクションが必要な様です。(後で確認したら、Chromeで発生し、Firefoxでは再生されました)
なのでHTMLにbuttonタグを追加し、onclickでZMUSICの処理を起動したところ、遂に再生されました! 長かったですが、やっと再生させることができました。

で、ここまできてそういえばz-music.js/dist/の下に初めからzmusic.jsやzmusic.wasmあったなーと思い返し、一旦z-music.js/dist/の下のファイルを削除、再度リモートからチェックアウトしたファイルで確認したところ、問題無く動作しました。(汗

ということで、emsdkを使用したビルド済みのファイルが初めから提供されていましたというオチですが、emsdkとは何かが分かったし、今後z-music.jsに修正が入っても自分でビルドできるぞという事で、無駄ではなかったかなと思います。
最後に、こんな素晴らしいJSを公開してくださった@toyoshim氏に大変感謝いたします。

vagrant upでCode E_INVALIDARG (0x80070057)のエラーが出る件

Windows10の環境で古いboxを使ってvagrantを起動したところ、以下の様な今まで見たこと無いエラーが出ました。

> vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'XXXXXXXX'...
Progress: 80%There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["import", "\\\\?\\C:\\Users\\hoge\\.vagrant.d\\boxes\\XXXXXXXX\\0\\virtualbox\\box.ovf", "--vsys", "0", "--vmname", "XXXX_1593401077047_88998", "--vsys", "0", "--unit", "15", "--disk", "C:/Users/hoge/VirtualBox VMs/XXXX_1593401077047_88998/box-disk2.vmdk"]

Stderr: 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Interpreting \\?\C:\Users\hoge\.vagrant.d\boxes\XXXXXXXX\0\virtualbox\box.ovf...
OK.
0%...10%...20%...30%...40%...50%...60%...70%...80%...
Progress state: E_INVALIDARG
VBoxManage.exe: error: Appliance import failed
VBoxManage.exe: error: Code E_INVALIDARG (0x80070057) - One or more arguments are invalid (extended info not available)
VBoxManage.exe: error: Context: "enum RTEXITCODE __cdecl handleImportAppliance(struct HandlerArg *)" at line 957 of file VBoxManageAppliance.cpp

ググったところこれといった解決方法が無かったのですが、
私の環境では単純にディスクスペースが足りていないだけでした。
忘れそうなので記録しておきます。

何度JSでconsole.logをラップしたか分からんがやっとうまい方法を見つけた

案件ごとに対応ブラウザとか違ってそれ毎に毎度作成していてなんとなくモヤモヤしていましたが、 こちらで上手い方法が解説されていました。

blitzgate.co.jp

とてもシンプルに書けるしこのやりかたの良い所は、関数でラップする場合と比較して、 ちゃんと呼び出した場所の行数がconsole.logで出力される点と、 IEに対応していないスプレッド構文を考慮しなくても、console.logの引数をまんま使える点だと思います。
(console.logは可変パラメータを受け付けてくれる)

developer.mozilla.org

なんだかんだ言っても、まだIE対応させなければならない場合や、トランスパイル環境つくるまでの 規模じゃないこともあるので、これは便利に使えそうです。
さらに発展させて、スタティッククラスっぽく利用できるようにしてみました。

const Log = (function(logLevel) {
    let none = function(){};
    return {
        debug:  (logLevel <= 0) ? console.log.bind(console) : none,
        info:   (logLevel <= 1) ? console.log.bind(console) : none,
        error:  (logLevel <= 2) ? console.log.bind(console) : none
    };
})(1); // ここにログレベルを記述

let obj = { hoge: 'HOGE', moga: 'MOGA' };
Log.debug('デバッグログ');           // レベルが異なるのでこれは出力されない
Log.info('インフォログ', 'fuga');
Log.error('エラーログ', obj, Log);   // オブジェクトの可変パラメータも出力できる

これならIE(11限定ですが)も問題なく動きます。
ちなみに先に解説されていたconsole.log.bind(console)の書き方は、最新のブラウザなら console.logのみで問題なく動作するみたいです。

2020.7.3追記
IE11はconsole.log.bind(console)という書き方をしないと動作しなかったの修正しました。
IEの開発者ツールを開いていれば動作しますが、閉じるとエラーも発生せずスクリプトが止まってしまうようです。

www.pandanoir.info