Electron + WebMSX でデスクトップ PC 向け MSX ソフトを作ってみる

# はじめに

Steam などで自作 MSX アプリを販売するにはどうしたらよいのだろうか :thinking: 

という訳で、Electron と WebMSX を使ってお手軽にデスクトップ PC 用のスタンドアローン MSX アプリを開発する方法を紹介します。

> なお、私は Windows のパソコンを持っていないので Mac でしか検証していませんが、多分 Windows でもほぼ同じ手順で問題無いと思われます。

# 1. Node.js を 準備

まずは、以下の記事あたりを参考にして Node.js をインストールしましょう。

https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09

# 2. Hello, World!

手始めに、Electron で Hello, World! を表示する空プロジェクトを作ります。

> 既に色々な紹介記事があるのでサクッと紹介リンクだけ貼って済まそうと思ったのですが、色々な環境条件の都合（electron の Global インストールは避けたいetc）のため、簡単に一通りの手順を書きます。

## 2-1. package.json を 生成

適当なワークディレクトリ（msx-electron-app）を作り `npm init -y` を実行して空プロジェクトの `package.json` ファイルを生成します。

```
mkdir ~/msx-electron-app
cd ~/msx-electron-app
npm init -y
```

```package.json
{
  "name": "msx-electron-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```

なお、本書では以降のコマンド操作はすべて `~/msx-electron-app` ディレクトリ以下で実行する想定でコマンド操作の手順を表記します。

## 2-2. electron を インストール

```
npm install --save-dev electron
```

## 2-3. index.js を 作成

```~/msx-electron-app/index.js
const electron = require("electron");
let mainWindow = null;

electron.app.on("window-all-closed", () => { electron.app.quit(); });

electron.app.on("ready", () => {
  mainWindow = new electron.BrowserWindow({ width: 512, height: 384, useContentSize: true });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on("closed", () => { mainWindow = null; });
});
```

## 2-4. index.html を作成

```~/msx-electron-app/index.html
<html>
<body>
<p>Hello, World!</p>
</body>
</html>
```

## 2-5. package.json に起動手順を定義

package.json の `scripts` に Electron アプリの起動手順 (`start`) を定義します。

```json
  "scripts": {
    "start": "electron .",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
```

上記にように定義することで `npm start` を実行すれば、コマンドラインで `./node_modules/.bin/electron .` を実行するのと同じ動作をします。

## 2-6. 実行してみる

```
npm start
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2161417/15f2f007-129e-cc85-0803-0e9246655f62.png)

無事、Hello, World! を表示するシンプルな Electron アプリを動かすことができました。お疲れ様でした！ここからが本番です。

ここまでの手順と後述するパッケージングの手順は、以下の記事が参考になりました。本書では諸々の内容を簡略化してしますが、詳しくは以下の記事を参照してください。（丸投げ体質）

https://qiita.com/nyanchu/items/15d514d9b9f87e5c0a29

# 3. WebMSX を組み込む

## 3-1. WebMSX (C-BIOS版) を ダウンロード

GitHub から WebMSX（C-BIOS版）をダウンロードしてプロジェクトに組み込みます。

```
curl -OL https://github.com/ppeccin/WebMSX/raw/master/release/stable/6.0/cbios/embedded/wmsx.js
```

> MSX の公式な BIOS は、Microsoft の著作物（また、BIOS 内で表示している "MSX" の商標や意匠は、[J-PlatPat](https://www.j-platpat.inpit.go.jp)で確認したところ MSX ライセンシングコーポレーション の権利物）なので、Microsoft と MSX ライセンシングコーポレーション からの許諾を受けずに再配布をする場合、C-BIOS を使う必要があります。（※C-BIOS は 2箇条BSD の OSS）
>
> なお、C-BIOS には MSX-BASIC の機能が入っていないので、BASIC のプログラムをランタイム（エミュレータ）付きで再配布するのは結構難しい（Microsoft と MSX ライセンシングコーポレーション 両社からの許諾が必要）かもしれません。

## 3-2. index.html を 変更

index.html を以下のように変更して、WebMSX を実行する形にします。

```~/msx-electron-app/index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>msx-electron-app</title>
    </head>
    <body>
        <div id="wmsx-screen"></div>
        <script src="wmsx.js"></script>
        <script>
            // WebMSXの各種パラメタを調整
            WMSX.MACHINE = "MSX1J";
            WMSX.SCREEN_FULLSCREEN_MODE = 2;
            WMSX.SCREEN_DEFAULT_ASPECT = 1.0;
        </script>
    </body>
</html>
```

### 3-3. 実行してみる

```
npm start
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2161417/111b8852-9647-a60d-be48-1864d4985bbc.png)

UI 周りが少しおかしい（WebMSX側 のフルスクリーンボタンを押すと少し変な感じになってしまう）ですが、とりあえず Electron 上で C-BIOS のブート処理が実行できるようになりました。

# 4. 自作の ROM を組み込む

本書では例として、以下の記事で解説した謎の1枚絵を表示する ROM ファイルをプロジェクトに組み込んでみます。

https://qiita.com/suzukiplan/items/e010badf2af2e1fdbf6e

## 4-1. ROM ファイルをコピー

`image.rom` を `~/msx-electron-app` にコピーします。

## 4-2. index.html を 修正

`index.html` の `<script> ~ </script>` に `image.rom` を起動時に読み込む処理を追加します。

```~/msx-electron-app/index.html
WMSX.CARTRIDGE1_URL = "image.rom";
```

## 4-3. 動かしてみる

```
npm start
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2161417/a6b99c4f-d277-0101-ef6e-1990c1f59e8a.png)

Electron アプリで自作の MSX ROM を動かせるようになりました :tada:

ただし、このままだと Node.js が無い環境だと起動できません。

Steam で販売するには、このままでは若干上級者向けすぎる気がするので、誰でも簡単に起動できるパッケージ（再配布パッケージ）を作成する必要がありそうです。

# 5. 再配布パッケージを作成

## 5-1. electron-packager を インストール

```
npm install --save-dev electron-packager
```

## 5-2. package.json を 修正

package.json の `scripts` に Windows と Mac のパッケージを出力する手順（`package-win32-x64`, `package-darwin-x64`）を定義します。

```json
  "scripts": {
    "start": "electron .",
    "package-darwin-x64": "electron-packager ./ --platform=darwin --arch=x64",
    "package-win32-x64": "electron-packager ./ --platform=win32 --arch=x64",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
```


## 5-3. Mac用パッケージ (.app) を 生成

Mac用のパッケージは、次の手順で生成できます。

```
npm run package-darwin-x64
```

> 本当は Windows の .exe も出力しようとしたのですが、最近の Mac では wine が動かない関係で .exe を出力できないようです :cry:  _（Windows 用パッケージを作る場合は Windows の実機が必要かもしれません）_

成功すると `msx-electron-app-darwin-x64` ディレクトリ以下に再配布用パッケージが生成されます。

```
% find msx-electron-app-darwin-x64 
msx-electron-app-darwin-x64
msx-electron-app-darwin-x64/msx-electron-app.app
msx-electron-app-darwin-x64/msx-electron-app.app/Contents
msx-electron-app-darwin-x64/msx-electron-app.app/Contents/MacOS
msx-electron-app-darwin-x64/msx-electron-app.app/Contents/MacOS/msx-electron-app
msx-electron-app-darwin-x64/msx-electron-app.app/Contents/Resources
*** 中略 ***
msx-electron-app-darwin-x64/msx-electron-app.app/Contents/Info.plist
msx-electron-app-darwin-x64/msx-electron-app.app/Contents/PkgInfo
msx-electron-app-darwin-x64/LICENSE
msx-electron-app-darwin-x64/version
msx-electron-app-darwin-x64/LICENSES.chromium.html
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2161417/4e81fe25-dcac-1dda-5475-e8e9d9625923.png)

生成された `msx-electron-app.app` をダブルクリックでちゃんと起動できました。（結果は 4-3 と同じです）

> 193.8MB!! _(Chromium がデカすぎる...)_
>
> ライセンスの記述だけで 5MB+ の `LICENSES.chromium.html` の霊圧もスゴイｗ

# 6. いざ、Steam で販売 <sup>_（...できるんか?）_</sup>

あとは、Windows 用のバイナリも作って Steam で販売...みたいなことができたら良いなと思ったのですが、現状 WebMSX のライセンス周りがどうなっているかよく分からない状態です。

WebMSX 以外の部分は _（権利関係が複雑な Chromium のチェックがやや大変そうですが）_ 多分問題無さそうです。

- C-BIOS: 2箇条BSD
- Electron: MIT
- Electron Packager: 2箇条BSD
- Chromium: 例のアレ（`LICENSE.chromium.html`）を参照

> Chromium のライセンスについては[過去に色々あったらしい](https://e-yuuki.org/docs/chromiums_freedom_flaws/index.html)ですが、素人目にざっくりと確認した限りでは、MIT, LGPL, MS-PL, GPL系 のミックスライセンスで、多分各種の条件を満たせば商用利用OKだと思われますが、かなり複雑 & 私は法律の専門家ではないので、実際に販売される場合は、専門家に相談しましょう。

WebMSX のライセンスについては、ソースコード中に `See license.txt distributed with this file.` とあるのですが、肝心の license.txt が同梱されておらず、以下の issue が Open のままでした。

https://github.com/ppeccin/WebMSX/issues/4

という訳で、 **WebMSX のライセンスが確定するまでは Steam で販売（商用利用）はできない** というのが私見です。

> _多分、GPL + MIT + BSD のミックスライセンスじゃないかなと想像していますが（※エミュレータのコードベースのライセンスは概ねこのパターンが多いので）_

# まとめ

- Electron + WebMSX で再配布パッケージを作るところまではできる
- WebMSX の UI 周りの調整が必要
  - 電源ボタン以外のボタンを非可視にできれば良いと思われる
  - その辺のパラメタ変数（SCREEN_RESIZE_DISABLED）が存在したが、設定しても正常に機能していない様子だった（設定の仕方がマズかったのかも？）ので、場合によっては WebMSX のコードを少し手直ししないとダメかもしれない（※この辺はまだ確認が不十分なので、確認できたら記事反映予定です）
- サイズがデカ過ぎ（空状態でも約200MB）
  - minify オプションとかあるかも?
- ライセンス周りに不透明な部分があるので Steam 等での販売はできないのではないかと考えられる（Chromiumのライセンスも複雑なので、結局ネイティブアプリを普通に作った方が良いのではないか説）

> もう少しカジュアル & 自由度の高いライセンス（MIT only など）で軽いデスクトップ PC 用の MSX 再配布アプリケーションを開発できる OSS フレームワークとかがあればニーズあるのだろうか :thinking:

# Appendix

本書で紹介したサンプルプロジェクトを GitHub で公開しておきました。

https://github.com/suzukiplan/msx-electron-app