pyxelを中華ゲーム機のLinuxで動作させるためのノウハウ 1/2

この記事では中華ゲーム機のLinuxでpyxelを動作させるためのノウハウを記しています。



# 中華ゲーム機とは
主に中国企業が設計・開発・販売をしている「手のひらに載るサイズ感の携帯型コンピューター」を指しています。
(海外ではハンドヘルドとも呼ばれます)

ファミコンやゲームボーイなどのレトロゲームからROMデータを吸い出し、それをエミュレーターで実行させることができます。
Rockchip社、Allwinner社などのSoCが搭載されており、カスタムされたAndroidやLinuxが動作します。
![20241125-232928.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930874/ef14301f-fbb4-6392-247d-f5c9be8b6751.jpeg)


# pyxelとは
Pyxel (ピクセル) は、Python向けのレトロゲームエンジンです。

使える色は 16 色のみ、同時に再生できる音は 4 音までなど、レトロゲーム機を意識したシンプルな仕様で、Python を使ってドット絵スタイルのゲームづくりが気軽に楽しめます。
[詳しくはPyxelのGithubを参照してください](https://github.com/kitao/pyxel)



# 中華ゲーム機で使われるLinuxについて
中華ゲーム機では一般的に普及しているディストリビューション(以下ディストリ)である「ubuntu」「RedHat」「Arch」は使われておらず、完全にカスタムされたLinuxディストリが採用されています。

中華ゲーム機の販売会社が作成した「名前がないディストリ」も存在していて、それを通称「StockOS(ストックOS)」とも呼びます。
中華ゲーム機で使われるディストリで有名な御三家を紹介します
- [ROCKNIX(旧JELOS)](https://github.com/ROCKNIX)
- [ArkOS](https://github.com/christianhaitian/arkos)
- [Batocera Linux](https://batocera.org/)

基本的にこれらのディストリではライブラリやアプリケーションなど、それぞれのソースコードを独自にビルドしてディストリが構成されています。
ほとんどはソースコードをそのままビルドしていますが、いくつかのプログラムは独自のパッチなどが当てられていることもあります。

なお、中華ゲーム機のCPUは「Arm」か「Mips」アーキテクチャが使われることが多く、x86_64のPCでプログラムをビルドするにはツールチェーンを使ってクロスコンパイルする必要があります。

# ツールチェーンについて
ツールチェーンは「プログラムをビルドをする際に利用されるプログラムやライブラリの集合体」です。
各ディストリは様々なバージョンのライブラリやツールで構成されているため、それと同じ構成になるようにツールチェーンも作らねばなりません。

例えばpythonはいくつかのライブラリに依存しています。
仮にubuntuでaarch64用のpythonをビルドしても、中華ゲーム機のディストリ内のライブラリバージョン違いによる実行エラーにぶち当たってしまうのです。

ここで一つ疑問が生じるかと思います。

「それぞれのディストリ上でプログラムをビルドすればツールチェーンは必要なくない？」

はい、それがそううまくいきません。
中華ゲーム機のディストリには「cmake」「make」コマンドや「include」ディレクトリなど、プログラムをビルドするのに必要な要素が存在しません。
中華ゲーム機はレトロゲームを実行することに特化しているため、レトロゲームの実行に必要のない要素は極限まで排除されいるためです。

ですが一部の中華ゲーム機Linuxではubuntuベースのものがあり、aptコマンドでビルドに必要なコマンド、ライブラリやdevパッケージをインストールできるものがあります。
この場合は中華ゲーム機上でプログラムをビルドすることが可能です。
ただし、ディストリ独自に改造されたライブラリなどはaptコマンドではゲットできないので、プログラムがビルドできたとしても動作に問題が生じる場合があります。

# pythonをビルドする
pyxelを動かすにはpythonが必要になります。
よってまず初めにツールチェーンを使ってpythonをビルドする必要があります。

ツールチェーンによってビルドされたpythonを中華ゲーム機のディストリに取り込む必要がありますが、一つ問題点が生じます。
中華ゲーム機のディストリではルートディレクトリに読み取り専用の「squashfs」が採用されており、ファイルの追加・変更が困難なことです。

例えばsquashfsを解凍し、pythonを埋め込んで再度squashfsを生成したとしても、ディストリのアップデートによってsquashfsは上書きされてしまい、結果的に追加・変更した内容は消えてしまいます。

# ビルドされたpythonの最適な設置場所とは
じゃぁどこにpythonを設置すれば良いかというと・・・
ゲームのセーブデータやプログラムの設定ファイルを保存する領域にファイルを設置することです。

squashfsはあくまでもLinuxのルートディレクトリを担うものなので、セーブデータの領域は別途ext4などの領域が確保されていることが多いです。
このext4領域は数百MB〜2GB程度の容量でかつ、アップデートによって消されない領域でもあるため、ビルドしたpythonを設置するには理想的です。

ディストリごとにext4領域をマウントしている場所が違いますので、pythonを設置する最適な場所は「ホームディレクトリ」を探すことです。

なぜならホームディレクトリの配下でファイルの追加・削除ができなければ、OS全体としての動作が成り立たないことが多いため、ext4領域の配下にホームディレクトリが設定されているためです。

例えば「$HOME/.config」というディレクトリの配下には、OS上で動作するプログラムの設定ファイルなどが保存されており、それらの設定ファイルはユーザによって追加・編集・削除されることを想定しています。

ホームディレクトリというと一般ユーザは「/home/ユーザ名」というディレクトリや、rootユーザは「/root」というディレクトリが思い浮かぶと思いますが、中華ゲーム機のディストリでは全く違う場所がホームディレクトリであることが多いです。
(ディストリによってはプログラム実行処理の中に「HOME変数」を定義している場合があるため、実行ユーザの$HOME変数を確認しても実際には違うパスを指している場合もあるので注意が必要です)

例えばROCKNIXではrootユーザがあらゆるプログラムを動作させています。
rootユーザのホームディレクトリは「/storage」です。
「/storage」は前述したext4領域のマウントポイントでもあります。
よってROCKNIXでは「/storage/python」のようなパスにpythonを設置できることになります。

このようにプログラムを動かすユーザのホームディレクトリを探し出したり、プログラム実行処理に埋め込まれているHOME変数を探し出し、その配下にpythonを設置する必要があるでしょう。

## $HOME　以外のpython設置場所について
pythonは「ROMファイルを保存している領域」に設置することもできます。
ROMファイルを保存する領域はFAT32かexFATでフォーマットされており、ユーザが自由にファイルの追加・変更・削除が可能です。
ただ、この領域はSDカードのスロット2を利用されることが多く、「このスロットを使う/使わない」はユーザに委ねられるため、pythonを設置する作業はユーザに実施してもらう必要があります。

# pythonを設置する際のちょっとしたTips
Pythonをビルドする際にインストールディレクトリ名(--prefix)は「Python」ではなく「Python-3.11.7」のようにバージョン名を含めます。
視覚的にバージョン情報がわかるため、わざわざ`python3 --version`コマンドを実行して確認する必要はありません。

次の項目で説明をしますが、そもそも中華ゲーム機では簡単にコマンドを実行できないことも、ディレクトリ名にバージョン番号を付与する一つの理由になります。
ディストリにはファイルマネージャーのようなアプリが付属しているため、ディレクトリ名を把握することは容易です。

「/storage」にpythonディレクトリを設置するとフルパスは`/storage/Python-3.11.7`になります。
続いてこのディレクトリに対して適当なシンボリックリンクを作成します。
`ln -s /storage/Python-3.11.7 /storage/pyxel_Python`

このPython-3.11.7を利用したいプログラムは`/storage/pyxel_Python`をパスとして利用させます。
これによってpythonのバージョン管理が楽になります。

例えば「Python-3.12.0」にバージョンアップさせたい場合`/storage/Python-3.12.0`ディレクトリを設置した後、下記のようなコマンドでシンボリックリンクを切り替えるだけで、pythonのバージョンアップが完了します。
```
rm /storage/pyxel_Python
ln -s /storage/Python-3.12.0 /storage/pyxel_Python
```
プログラムは引き続き`/storage/pyxel_Python`のパス利用しているため、pythonディレクトリに付与されたバージョン番号を意識する必要がなく、動作に支障が生じることもありません。
もしバージョンアップによって何か問題が生じた場合でも、シンボリックリンクを戻すだけでバージョンダウンが即時可能になります。

# pyxelを実行する方法
中華ゲーム機は「ゲーム機のようなデバイス」であるため、十字キーやABボタンが実装されており、キーボードで操作することは想定されていません。
よってユーザーがキーボードでコマンドを入力することはできず、すべての操作はコントローラーでしなければなりません。

例えばLinuxでpyxelのpyxappファイルを実行するには、下記のようなコマンドを実行する必要があります。
`/storage/pyxel_Python/bin/pyxel play game.pyxapp`
ユーザはキーボードが使えないため、このコマンドを誰かが代わりに実行してもらう必要があります。

それを実現するのが「フロントエンド」と呼ばれているアプリになります。


# 所感と次回予告
一般的なLinuxディストリではaptやpipを使えば簡単にpyxelの実行環境を整えることができますが、中華ゲーム機のディストリでは便利な機能が全くないし、OSの仕様なども不透明なものが多く、pyxelの実行環境を整えるだけでも考慮するべき点が多々あります。


次回は実際にpyxelを実行するためのノウハウを記しています。
12/13に公開される第2回にご期待ください！:dizzy: