ユーザ用ツール

PocketTerm35

概要

WaveShareからリリースされた、Raspberry Pi4/5を組み込む形で動作させる小型PCである

実測で重量432g

uConsoleが579gなので、75%程の重量となっている

Raspberry Pi4 2GBまたは Raspberry Pi5 1GBを組み込んだモデルと、Raspberry Piを含まないベアボーン的なキットがある

ベアボーン的なキットについてもリチウムイオンバッテリーパックを含むものと含まないものとがある

リチウムイオン電池が含まれる場合、輸入の際に空路が使えないので、時間が余分にかかることは考慮すべきであろう

電池パックについて

電池パックは、3.7Vのリチウムイオン電池のセルにPH2.0ヘッダをつければ1)なんでもいいようである

但し、極性が一般的なものとは逆になっていることがこちらで触れられている

もちろん、PH2.0ヘッダなので、引っこ抜いて逆にして圧着しなおせばいいのだけれど、最初から極性を逆にしているものも売られているので、容量も含め適切なものを用意したい

写真のように、左が赤(+)で、右が黒(-)になるように配線されていれば大丈夫である

電池としては3.7Vのリチウムイオン電池であればいいが、容量的にはキットに入っているという5000mAhのものでいいだろう デバイスの種別や、SSDの有無などで変わってくるとは思うが、わたしの場合で2h程度は余裕で運用できる感じだ

電源オフ

OSをシャットダウンしても、完全に電源が切れるわけではなく、システムはスタンバイ状態になる

この状態では本体上部の電池残量のLEDは点灯しており、Raspberry Pi5 もスタンバイ状態の赤LEDが点灯している

この状態から復帰するには、Raspberry Pi5を内蔵しているモデルなら、左側のシリコンボタンを押せばいい

ただ、スタンバイ状態からだと復帰がすごい速いかというとそうでもないうえに、そこそこ電池を食うのであまりこのモードの意義は感じない

この状態から完全に電源を切るには、本体上部の電源ボタンをダブルクリックすればいい

電池残量表示のLEDが消え、Raspnerry Pi5のインジケータも消える

このデバイスが向いている人・向かない人

向いている人

  • 80×24程度の端末内ですべてを完結できる人
  • オールドPCのエミュレータで遊びたい人
  • 小さなデバイスならどんな苦労もいとわない人
  • 致命傷を恐れずファームウェアを改造する意気込みのある人

Linuxのターミナルとviなどのシンプルなエディタで生活できる人、オールドPCのエミュレータで遊びたい人には向いているといえる

これは電卓といえば電卓アプリを立ち上げたりせず、bc -l と入力したり irb と入力したりする、端末に閉じて生きられる人のためのデバイスである

その場合でも、Raspberry Piを含むキット2)はメモリが少なすぎてLinuxといえどデスクトップ環境を運用するのには向いていないので、Raspberry Piは自分で適切なモデルを買って入れるべきだろう

後述するが、本体側を制御しているRP2040上でCircuitPythonが動作しており、これに手を入れるつもりがあれば、キーマップ周りの不満はある程度解消できるかもしれない

但し、うっかりな変更を加えると、ファームウェアそのものを再インストールしないと回復不能になる可能性もあるので、その辺をわきまえた人のみが恩恵にあずかることができる

向かない人

  • 本格的なデスクトップ端末を期待している人
  • 変態キーボード配列は受け入れられない人、JIS配列以外は気持ち悪くて使えない人
  • サーバとして運用したい人
  • 老眼が進行著しい人
  • ガンガンゲームを楽しみたい人
  • ARM64とx64の違いがイマイチ判ってない人
  • DTBOがなんなのかわかってない人

画面サイズ640×480しかないので、汎用的なポータブルデバイスを欲しい人には向いていない

画面サイズの制約が大きく、ウェブブラウジングやメールの読み書きも実用的でないし、VSCodeのようなエディタすら運用するのが難しい

しかもキーボードが、サイズ的な制約で仕方ないこととはいえ、きわめて、標準的ではない配列となっている

ベースはUS配列なので、普段からUS配列を使っている人であればそれでもまだなじめる可能性がなくはないが、JIS配列でないとダメな人にはかなり厳しいだろう

いくつかクセつよポイントがあるが、非常に致命的なのはシフトキーが左にしかないことだろう

右親指でシフトキーを押して、左親指で他のキーを全部カバーすることになるかと思うが、ちょっと癖が強すぎて泣けてくる

とはいえ、このデバイスはやる気があれば自分でキーマップを変更することもできるので改造することで満足する使い勝手になるかもしれない

またサーバとして使用することを考えている場合も全く向いていない

サーバならば、リモートからアクセスできるようにしてあるのが普通で、ローカルにキーボードとモニターを常備しておく必要はないし、であるならば、もっと廉価なケースがあるのだ

なのでサーバにしたいなら、シンプルなケースに入れて、モニターもキーボードもなしで運用する方がいいだろう

ゲームはできなくはないが、Raspberry Pi4/5のGPUは決してパワフルなものではないので、3Dでごりごり動くようなゲームコンソールとして使いたいというのであれば、それは無理

Steam は動くのでカジュアルなゲームであれば十分に遊べるのだが

一応、Ubuntu なりの Linux ディストリビューションはおおむね ARM64だろうが x64だろうが動くは動く

物好きな向きなら Windows11さえインストールすること自体は可能だろう

OSとそれに付随するパッケージだけで暮らすのであれば問題はないが、サードパーティ製のパッケージやアプリを期待していると ARM64であることがデメリットとなりうる

たとえば、Google Chromeや Slackなどのアプリは x64版は存在しているが AMR64版は存在しない

Chromiumやブラウザ版の Slackで代替するしかない

また、Hazkey などのオープンソースのものでさえ、公式が提供しているのは x64版だけで ARM64版が欲しければ自力でビルドする以外に方法はない

少なくとも自力でこういったものをビルドできる程度の知識と経験を持っているか、それらを今から習得したいという熱意のあるユーザでないと、この端末、というか Raspberry Piを使うのには向いていない

そいうのがいやだなあ、と思うなら x64のSBCなり小型PCなりを検討するべきだ

何なら値段もうっかりするとそっちの方が安かったりもするし

設定など

組立て

組立てはそれほど難しくはない

液晶、キーボード、そしてシステム基板などはすべて組付けられた状態になっており、やることは基板と組み込む Raspberry Piとを接続し、バッテリーを接続するだけのことである

動画付きの解説があるので、その通りにやればいい

ねじは付属のドライバーで開け閉めできるし、プラグもフレキ以外は刺さる向きにしか刺せない

USB用の内部配線は解説ページとケーブル色が違う場合もあるが、刺さるように刺せばいいので色は気にしなくていい

スピーカーケーブルも刺さる向きで刺せばいい

逆に電池だけは色をしっかり確認すること

フレキは端子面(金色の側)がコネクタに対して下を向くように差し込めばいい

裏ブタは結構タイトで一番の難易度だと思う

特にPi5の場合はシリコンゴムのボタンを側面につけるのだが、これは本体に固定されるわけではなく、単にそこにはまっているだけで少し傾けただけでずれる、落ちるなので、裏ブタを取り付けるときにはボタンのある側面を下にして横向きで作業するといいだろう

このボタンは見た目にちゃんとついているようでもわずかにずれていて、Pi5側のボタンを押し込んだ状態になっていたりするので、裏ブタを閉めた後で、押し込んできちんとボタンの押下、解放ができているか確認すること

なお、写真にあるように、Pi5に純正ヒートシンクをマウントして、その上に M2 HAT+を乗せてM.2 2230のNVMe SSDを乗せた状態でもきちんとケースに収まるので、SSD運用を考えている場合はこの組み合わせなら大丈夫ということを記しておく3)

ソフトウェア設定

基本的にほとんどそのままのRaspberry Pi向けのOSが動くが、タッチパネル周りだけは DTBOを持ってきて入れたうえで、config.txtに追記する必要がある

ダウンロードリンクはPocketTerm35のWikiにある

ここで、config.txtの修正やDTBOファイルの配置について書かれているが、すべてのディストリビューションで当てはまるわけでもないようなので、適宜自分の環境に合わせて適用してほしい

以下は Ubuntu26.04LTSの場合である

config.txt は /boot の下、またはWindowsなどでTFカードをマウントして編集する場合には、TFカードのルートフォルダにある

内容はOSによって微妙に異なるが、要はpi4には waveshare-35dpi-4bを pi5には waveshare-35dpi-5bをそれぞれdtoverlayに指定してやればOKである

waveshare-35dpi-[345]b.dtbo は /boot/firmware/current/overlay の下においてやればいい

カーネルなどの更新を行った場合、新しく /boot/firmware/new/overlayが作られ、その下には waveshare-35dpi-[345]b.dtbo はないので、改めてこれらのファイルをコピーする必要がある

リブートする前なら /boot/firmware/new/overlay の下に、リブート後なら /boot/firmware/current/overlayの下にそれぞれコピーする4)

config.txt
[all]
os_prefix=current/
 
[tryboot]
os_prefix=new/
 
[all]
arm_64bit=1
kernel=vmlinuz
cmdline=cmdline.txt
initramfs initrd.img followkernel
 
# Enable the audio output, I2C and SPI interfaces on the GPIO header. As these
# parameters related to the base device-tree they must appear *before* any
# other dtoverlay= specification
dtparam=audio=on
dtparam=i2c_arm=on
dtparam=spi=on
dtparam=watchdog=on
 
# Comment out the following line if the edges of the desktop appear outside
# the edges of your display
disable_overscan=1
 
# If you have issues with audio, you may try uncommenting the following line
# which forces the HDMI output into HDMI mode instead of DVI (which doesn''t
# support audio output)
#hdmi_drive=2
 
# Enable the KMS ("full" KMS) graphics overlay, leaving GPU memory as the
# default (the kernel is in control of graphics memory with full KMS)
dtoverlay=vc4-kms-v3d
disable_fw_kms_setup=1
 
# Autoload overlays for any recognized cameras or displays that are attached
# to the CSI/DSI ports. Please note this is for libcamera support, *not* for
# the legacy camera stack
camera_auto_detect=1
display_auto_detect=1
 
# Config settings specific to arm64
dtoverlay=dwc2
 
[pi5]
max_framebuffers=2
arm_boost=1
dtoverlay=waveshare-35dpi-5b
dtoverlay=dwc2,dr_mode=host
 
[pi4]
max_framebuffers=2
arm_boost=1
dtoverlay=wavewshare-35dpi-4b
dtoverlay=dwc2,dr_mode=host
 
[pi3+]
# Use a smaller contiguous memory area, specifically on the 3A+ to avoid an
# OOM oops on boot. The 3B+ is also affected by this section, but it shouldn''t
# cause any issues on that board
dtoverlay=vc4-kms-v3d,cma-128
 
[pi02]
# The Zero 2W is another 512MB board which is occasionally affected by the same
# OOM oops on boot.
dtoverlay=vc4-kms-v3d,cma-128
 
[cm4]
# Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into
# such a board)
dtoverlay=dwc2,dr_mode=host
 
[all]

電流不足といわれたら

5V 5Aが供給できない、というような警告が出る場合がある

そんな場合は、本家のFAQにあるように、rpi-eeprom-configを使って、最大電流量に5000mAを指定してやればいい

$ sudo rpi-eeprom-config --edit

とすると、nanoが起動して、EEPROMの設定が表示される

既にPSU_MAX_CURRENTの項目があれば値を5000に、なければ末尾に

PSU_MAX_CURRENT=5000

のように、追記して保存してnanoを終了する5)

あとは再起動すれば、電流量不足の警告は出なくなるはずである

アプリなど

Ubuntu26.04LTS

OSとして Ubuntu 26.04LTSを選択した

AIなどに聞けば「その画面サイズなら LUbuntu 使えば?」なんていわれるが、今、デスクトップ環境は X11から Waylandへの移行が進んでおり、Ubuntu 26.04LTS上の GNOMEは Waylandに完全移行しており、X11ベースのLUbuntuではパッケージの一部で問題が起きるかもしれないし起きないかもしれない

そういうめんどくさい思いを抱えながら運用するくらいなら、Ubuntuでいいんじゃないか? ということで Ubuntuにした

ドック6)は「自動的に隠す」設定にしておくことで邪魔にならない

必要に応じて [CMD] キーを押せば呼び出せるので実運用上は全く問題にならない

普段は隠れてて、必要な時にだけ出てくるなら、LUbuntuのLXDEよりGNOMEのドックの方がいい

何故なら、LXDEのバーは画面に占める割合が小さい分、ボタンやメニューも小さいのだ

指タップを前提にするなら、むしろGNOMEドックの大きさがちょうどいいくらいなのだ

DevTerm を買った頃は Armbian ベースのUbuntuは設定アプリのUIが、縦480pxに全く収まっておらず、非常に不便だったのだが、純正の設定アプリのほとんどは縦が480pxでも収まるようにデザインが進化しており、Fcitx5など一部の設定以外では特に困ることはなかったことも追記しておく

GNOME Terminal

Ubuntuデスクトップを入れたら勝手に入ってくる端末ソフト

特にすごい機能もなければ、足りない機能もないというような、標準的なGNOMEの端末ソフト

しかし、これが PocketTerm35を使う上で中心となるもの

古くからのX11ユーザはテキストを選択しただけでコピーバッファに入ることを想定しているかもしれないが、Ctrl+C を押さないと入らない7)

vim

いわずと知れた UNIX系システムの鉄板スクリーンエディタ

コマンドモードとエディットモードとを行き来しながらファイルを編集する

このエディタのキモは正規表現を使った強力な検索と編集の機能や一括大量削除などの繰り返し処理にあり、新規にファイルを書き起こすよりも、既存のファイルを修正したりするのに威力を発揮する

大体どのディストリビューションでも当たり前の顔して入っているので、使い方を覚えておけば、UNIX系システムでトラブル対応する際などに力を発揮すること間違いなし

カーソルの移動をコマンドモード内で h, j, k, lで行うのに慣れるには、RogueやNetHackをプレイすればいいが、やりすぎて、u,i,n,m で斜めに移動しそうになったりすると末期的である

Microsoft Edit

マイクロソフト謹製の端末ソフト用スクリーンエディタ

Rustで書かれていて、サクサク動いて、viはちょっととつきにくいなあという人にはお勧め

GitHubにて公開されているソースを持ってきてビルドするだけ

nanoでいいんじゃないのか?

という声が聞こえてきそうではあるが、Windowsでも全く同じインターフェイスで使えるので、あっちこっちで微妙に違う、という問題に遭遇しないで済みそうという点でアドバンテージがある

$ sudo apt install -y rustup
$ rustup toolchain install stable
$ git clone https://github.com/microsoft/edit.git
$ cd edit
$ cargo build --release

日本語入力

苦労したくない人は迷わず fcitx5-mozc でいいと思うが、せっかくだから今どきのエンジンで日本語入力したい向きは fcitx5-hazkey 一択だろう

Azookeyのエンジンを使用しているので、ビルドにはあれこれ必要になるが、基本的にはドキュメントの言う通りでいい

但し、SwiftだけはUbuntu25.10以降では、環境をごまかしてやらないとうまく動かない

そもそも、SwiftはUbuntuのLTS向けにしかバイナリを配布していないうえに、2026年7月現在、Ubuntu26.04LTS向けにはバイナリを提供していない

Ubuntu24.04LTS用を持ってきて使えば使えないことはないが、libxml2問題8)があり、これをどうにかしないと動かない

とりあえず緊急避難的には

$ sudo ln -s libxml2.so.16.1.2 /usr/aarch64-linux-gnu/libxml2.so.2

とかやって、無理やり libxml2.so.2 をlibxml2.so.16 にリンクしておけばとりあえず動くは動く

あとは、Zenzai込みでビルドするには8GB以上のメモリが必要なので、これより小さな Raspberry Pi4/5を買ってしまった人は、swapfileでも構わないのでとりあえず8GB以上のメモリを確保すること

メモリ不足のままビルドすると途中でメモリが足りないといって落ちる

スワップで確保した場合は当然遅くなる

Zenzaiを含めなければ 4GBのCM49)でもビルドはできた

なお、Raspberry Pi5であっても、ウリの一つであるLLMをONにするとキー入力ができなくなってしまう

GPUの圧倒的な性能不足だと思われる

AMD Ryzen5 2400Gのような大昔のCPU組込みのGPUでも快適に使用できるのに、この分野ではARMは大きく後れを取っているといわざるを得ない

設定画面のAIタブで「ZenZaiを有効化」にチェックを入れたとたんに入力ができなくなるので、試してみるのは自由だが、すぐにこのチェックをOFFにできるようにしておくこと

さもないと、最悪再インストールが必要になるかもしれない

LLMをONにしてビルドしても有効化は今のところできないので、ビルド時からOFFにしておくのもありだろう

なお、ライブ変換は快適に動作する

ログイン時に Waylandから警告が出る

fcitx5を有効にすると、Waylandから警告のポップアップが、ログイン時に出てくる場合がある

これは変換候補などの表示の制御が fcitx5まかせになっていて、GNOMEシェルの管理下にないためである

gnome-shell-extension-manager をインストールし、extention-managerを起動して、「探す」タブから「Input Method Panel」を探しインストールする

インストールすると、入力時に候補などがポップアップするときに、ポップアップの制御が GNOME shell側になるので、ポップアップが入力にかぶったり、テーマカラーが反映されないなどの問題が解消する

単純に警告を消すだけなら、他にも方法があるが、Input Method Panelを導入しない理由は見当たらないので、こちらの方法をお勧めする

Codex

今どきの端末でAIなしではいられない

とはいえ、GUIベースでは画面が小さすぎて死んでしまう

ということで、OpenAI謹製の CLI である codexを使う

多くの情報があるので、今更感もあると思うが、tmuxをインストールしておくと、tmuxのセッションを経由して、codexが直接端末を操作してくれたりするので、その便利さたるや、GUIを凌駕しているといっても過言ではない

インストールは次のコマンドで

$ curl -fSSL https://chatgpt.com/codex/install.sh | sh
$ . ~/.bashrc
$ codex

インストール後、初回起動時に、ChatGptのアカウントでのログインを求められる

ブラウザが開くので、この初回の部分だけGUIを使うがあとは基本的に端末の中に閉じる

なお、会話を続けたい場合は codex resumeで起動すれば、以前の会話のリストから選んで復帰できる

Claude Code

AnthropicのAIである

使い方の点では codexとは大きな違いはない

インストールも大体似たようなものである

$ curl -fsSL https://claude.ai/install.sh | bash
$ . ~/.bashrc
$ claude

世間に大きな衝撃を与え、米政府によって禁止されてしまったFable5こそ現状では使えないが、Opus4.8なども使えるので、codexよりパワフルかもしれない

なお、こちらのCLIは、Claude Pro以上のプランを購入しないと使えないので、無料でどうにかしたい勢は codex一択となる

Quasi88

NEC PC-8801のエミュレータ

入手はこちらから

PC-8801のエミュレータは吐いて捨てるほど存在しているのだが、Quasi88が PocketTerm35 用としては一歩抜き出ている部分がある

それは 0.7以降で追加されたツールバーの存在である

タッチ操作を前提として考えたときに、このツールバーは非常に強力なのである

フルスクリーンモードで 640×480の画面にぴったり収まるサイズも素晴らしい

PC6001VX

NEC PC-6001シリーズのエミュレータ

入手はこちらから

ビルドにはQt6 が必要であるが、Ubuntu 26.04LTSには Qt6.10.2のパッケージがあるので特に問題はないと思われる

このエミュレータの秀逸なところは、キーマップが、キーボードに従うということである

何をいっているのかというと、多くの日本製PCのエミュレータはJISキーボードを前提としていて、キー配列がUS配列と合致しないのだ

具体的には Shift + 2を押すと '“'が入力されるというような話

まあ、単にずれているだけなら大きな問題ではないが、JIS配列の方がキーが多い関係で、マッピングが存在しない文字がエミュレータによって発生することがあるのだが、PC6001VXは刻印通りのキーが渡されるため、入力できない文字のようなものがない

PocketTerm35は変態キー配列だがそのベースは当たり前のように英字配列だし、いくつかのキーはFnキーとのコンビネーションとなるため、エミュレータ側の対応いかんでは何が入力されるのか分かったものではないのだ

なので、この実装は非常にありがたいのである

$ git clone https://github.com/eighttails/pc6001vx
$ cd pc6001vx
$ qmake6 PC6001VX.pro
$ make -j4

OpenMSX

MSXエミュレータ

入手はこちらから

ビルドはできるし動作もするが、このエミュレータで遊ぶために必須となるのが「マウス」である

洗練されたメニューバーは細く、指でタップしようとしてもうまくタップできないのだ

また、メニューを非活性化しないとMSX側を操作できないが、この操作はマウスの右クリックに割り当てられているので、指だけでやるのはなかなか難しい

マウスでクリックすることで問題なく使えるので、マウスを接続する前提でならPocketTerm35でも遊ぶことができる

逆にマウスがないと画面を眺めるだけに近い状態になってしまう

NP2改

PC-9801/9821エミュレータ

入手はGitHubから

BIOSやフォントは ~/.config/wxnp21kai の下に bios.rom, bios9821.rom, font.bmp のような名前で置く

すべて小文字で置くこと

bios9821.romは PC-9821から持ってくる場合のみ

font.bmpはなければ font.tmpというファイルが生成されてそれを使うのでなければないでなんとかなる

なんならBASICを使わないなら、NECチェックを外せるなら、bios.romも多分いらない

最新版はWX Widgetsを使用しているがα版の位置づけのようである

とりあえず git で持ってきたらビルドする

$ git clone https://github.com/AZO234/NP2kai
$ cd NP2kai
$ cmake -S . -B build_wx -DBUILD_WX=ON -DUSE_NETWORK=ON -G Ninja
$ cmake --build build_wx -j4

ただし、このままビルドすると多分普通の人には使い物にならないものが出来上がる

キーマップが正しくないのだ

最初US配列との食い合わせが悪いのかと思ったが、さにあらず wx/kbtrans.cpp の中にあるASCII文字列のテーブルが全くどのキーボードともあってないのだ

なので、とりあえず、それっぽく動くようにマッピングを修正した

パッチを下に置くので、適宜パッチをあてるなどして使ってもらえればいいと思う

wxkbtrans.diff
--- wx/kbtrans.cpp.orig 2026-06-12 12:02:45.278737976 +0900
+++ wx/kbtrans.cpp      2026-06-12 21:45:49.464169487 +0900
@@ -33,14 +33,14 @@
        { WXK_F8,         0x69, 0x69 },
        { WXK_F9,         0x6a, 0x6a },
        { WXK_F10,        0x6b, 0x6b },
-       { WXK_F11,        0x73, 0x73 }, /* VF1 */
-       { WXK_F12,        0x74, 0x74 }, /* VF2 */
+       { WXK_F11,        0x52, 0x52 }, /* VF1 */
+       { WXK_F12,        0x53, 0x53 }, /* VF2 */
        /* Special keys */
        { WXK_ESCAPE,     0x00, 0x00 },
        { WXK_RETURN,     0x1c, 0x1c },
        { WXK_BACK,       0x0e, 0x0e },
        { WXK_TAB,        0x0f, 0x0f },
-       { WXK_SPACE,      0x35, 0x35 },
+       { WXK_SPACE,      0x34, 0x34 },
        /* Cursor keys */
        { WXK_UP,         0x3a, 0x3a },
        { WXK_DOWN,       0x3d, 0x3d },
@@ -64,10 +64,10 @@
        { WXK_NUMPAD_DIVIDE,   0x3e, 0x3e },
        { WXK_NUMPAD_DECIMAL,  0x3a, 0x3a },
        /* Insert/Delete/Home/End/PageUp/PageDown */
-       { WXK_INSERT,     0x3e, 0x3e },
-       { WXK_DELETE,     0x46, 0x46 },
-       { WXK_HOME,       0x3f, 0x3f },
-       { WXK_END,        0x3d, 0x3d },
+       { WXK_INSERT,     0x38, 0x38 },
+       { WXK_DELETE,     0x39, 0x39 },
+       { WXK_HOME,       0x3e, 0x3e },
+       { WXK_END,        0x3f, 0x3f },
        { WXK_PAGEUP,     0x36, 0x36 },
        { WXK_PAGEDOWN,   0x37, 0x37 },
        /* Modifiers */
@@ -80,18 +80,18 @@
 /* ASCII key mappings (0x20-0x7e) for 106-key layout */
 static const UINT8 ascii_to_pc98_106[0x60] = {
 /*       0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F */
-/* 20 */ 0x35, NC,   NC,   NC,   NC,   NC,   NC,   0x27, /* ' ( ) ... */
-/* 28 */ NC,   NC,   NC,   NC,   NC,   0x0b, NC,   0x0c, /* - . / */
+/* 20 */ 0x34, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ' ( ) ... */
+/* 28 */ 0x08, 0x09, 0x0a, 0x0b, 0x30, 0x0b, 0x31, 0x32, /* - . / */
 /* 30 */ 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-/* 38 */ 0x08, 0x09, 0x26, NC,   NC,   NC,   NC,   NC,
-/* 40 */ 0x1a, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
-/* 48 */ 0x24, 0x17, 0x25, 0x24, 0x25, 0x23, 0x22, 0x18,
-/* 50 */ 0x19, 0x10, 0x13, 0x1e, 0x14, 0x16, 0x2a, 0x11,
-/* 58 */ 0x2b, 0x15, 0x29, 0x1b, 0x0d, 0x28, 0x0c, NC,
-/* 60 */ NC,   0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
-/* 68 */ 0x24, 0x17, 0x25, 0x24, 0x25, 0x23, 0x22, 0x18,
-/* 70 */ 0x19, 0x10, 0x13, 0x1e, 0x14, 0x16, 0x2a, 0x11,
-/* 78 */ 0x2b, 0x15, 0x29, NC,   NC,   NC,   NC,   NC,
+/* 38 */ 0x08, 0x09, 0x27, 0x26, 0x30, 0x0b, 0x31, 0x32,
+/* 40 */ 0x1a, 0x1d, 0x2d, 0x2b, 0x1f, 0x12, 0x20, 0x21,
+/* 48 */ 0x22, 0x17, 0x23, 0x24, 0x25, 0x2f, 0x2e, 0x18,
+/* 50 */ 0x19, 0x10, 0x13, 0x1e, 0x14, 0x16, 0x2c, 0x11,
+/* 58 */ 0x2a, 0x15, 0x29, 0x1b, 0x0d, 0x28, 0x0c, 0x33,
+/* 60 */ 0x1a, 0x1d, 0x2d, 0x2b, 0x1f, 0x12, 0x20, 0x21,
+/* 68 */ 0x22, 0x17, 0x23, 0x24, 0x25, 0x2f, 0x2e, 0x18,
+/* 70 */ 0x19, 0x10, 0x13, 0x1e, 0x14, 0x16, 0x2c, 0x11,
+/* 78 */ 0x2a, 0x15, 0x29, 0x1b, 0x0d, 0x28, 0x0c, NC,
 };
 
 static bool key_states[0x100];

なお、このキーマップだと PocketTerm35のキーボードでは':'が入力できない

0x20 の行を以下のようにすればUS配列で一般的に”;“の右隣にある ”'“で”:“が入力できるようになる

/* 20 */ 0x34, 0x01, 0x27, 0x03, 0x04, 0x05, 0x06, 0x27, /* ' ( ) ... */

MZ800 Emulator

Linuxでも動くMZ800のエミュレータで、2.0.xよりMZ-1500/MZ-700のエミュレータもビルド可能となった

ビルトインでROMモニタを持っているので旧バージョンのようにMZ-700のROMにパッチあてしたものを与えなくても使用可能である10)

ただし、2.0.4-previewの時点では、ビルドはできてもクラッシュする

codexに調査させてパッチをあてたものならば動いた

ソースはGitHubにて公開されている

パッチをあててビルドすると、mz800emu, mz700emu-ntsc, mz700emu-pal, mz1500emuの四種類ができる

mz700emu-ntsc だけ試してみてあるが、ほかも動くのではないかと思う

なお、ROMは日本語版にしないとキーボードもフォントもおかしな状態になるので注意

$ git clone https://github.com/michalhucik/mz800emu.git
$ cd mz800emu
$ patch -p1 <mz800emu.diff
$ cmake -B build -G Ninja
$ cmake --build build -j4
mz800emu.diff
diff --git a/src/iface-video/sdlapp/sdlapp_imgui_video.cpp b/src/iface-video/sdlapp/sdlapp_imgui_video.cpp
index 64f2e4e..5508c36 100644
--- a/src/iface-video/sdlapp/sdlapp_imgui_video.cpp
+++ b/src/iface-video/sdlapp/sdlapp_imgui_video.cpp
@@ -41,7 +41,7 @@
 typedef struct SdlappMyImGuiVideo_t
 {
     SDL_Surface *surface;
-    SDL_TimerID update_title_timer;
+    guint update_title_timer;
     Uint64 lastPictureTime;
     int TARGET_FPS;
     int FRAME_TIME;
@@ -153,14 +153,18 @@ static void sdlapp_myimgui_video_set_colormap(uint32_t *colormap)
     video_sdl3_set_surface_colormap(colormap, g_sdlapp_myimgui_video->surface);
 }
 
-static Uint32 sdlapp_mygui_video_update_status_line(void *userdata, SDL_TimerID timerID, Uint32 interval)
+static gboolean sdlapp_mygui_video_update_status_line(guint timer_id, gpointer user_data)
 {
-    (void)timerID;
-    SDL_Window *window = (SDL_Window *)userdata;
+    (void)timer_id;
+    SDL_Window *window = (SDL_Window *)user_data;
+    if (!window)
+    {
+        return FALSE;
+    }
     char *title_text = iface_video_create_window_title_text();
     SDL_SetWindowTitle(window, title_text);
     g_free(title_text);
-    return interval;
+    return TRUE;
 }
 
 static gboolean sdlapp_myimgui_video_init(void)
@@ -308,7 +312,7 @@ static gboolean sdlapp_myimgui_video_init(void)
     // protože SetForegroundWindow selže když foreground drží konzole)
 
     // Nastavení titulku okna
-    g_sdlapp_myimgui_video->update_title_timer = SDL_AddTimer(IFACE_VIDEO_UPDATE_WINDOW_TITLE_INTERVAL_MS, sdlapp_mygui_video_update_status_line, win->sdl_window);
+    g_sdlapp_myimgui_video->update_title_timer = sdlapp_add_timer(g_sdlapp, IFACE_VIDEO_UPDATE_WINDOW_TITLE_INTERVAL_MS, sdlapp_mygui_video_update_status_line, win->sdl_window);
 
     sdlapp_myimgui_video_reset_fps_timer();
 
@@ -326,7 +330,8 @@ static void sdlapp_myimgui_video_exit(void)
     {
         if (g_sdlapp_myimgui_video->update_title_timer)
         {
-            SDL_RemoveTimer(g_sdlapp_myimgui_video->update_title_timer);
+            sdlapp_remove_timer(g_sdlapp, g_sdlapp_myimgui_video->update_title_timer);
+            g_sdlapp_myimgui_video->update_title_timer = 0;
         };
 
         if (g_sdlapp_myimgui_video->surface)
@@ -337,6 +342,14 @@ static void sdlapp_myimgui_video_exit(void)
         g_free(g_sdlapp_myimgui_video);
         g_sdlapp_myimgui_video = NULL;
     };
+    if (!headless)
+    {
+        if (g_gui && g_gui->win && g_gui->win->sdl_window && g_gui->win->gl_context)
+        {
+            SDL_GL_MakeCurrent(g_gui->win->sdl_window, g_gui->win->gl_context);
+        }
+        imgui_images_destroy_all();
+    };
     if (headless && g_gui)
     {
         /* Stub g_gui byl alokovaný v init headless větvi - free, ne destroy
@@ -344,11 +357,6 @@ static void sdlapp_myimgui_video_exit(void)
         g_free(g_gui);
     };
     g_gui = NULL;
-    sdl3_backend_video_quit();
-    if (!headless)
-    {
-        imgui_images_destroy_all();
-    };
 }
 
 static SDL_Window *getSDL_Window_by_name(const char *name)
diff --git a/src/iface/iface_video.c b/src/iface/iface_video.c
index 278f66f..a040743 100644
--- a/src/iface/iface_video.c
+++ b/src/iface/iface_video.c
@@ -107,6 +107,15 @@ void iface_video_exit(void)
     if (!g_iface_video)
         return;
 
+    if (g_iface_video_callbacks->exit)
+    {
+        g_iface_video_callbacks->exit();
+    }
+    else
+    {
+        WARN("Exit callback is not set!\n");
+    };
+
     if (g_iface_video->redraw_full_screen_request_rwlock)
     {
         APP_RWLOCK_DESTROY(g_iface_video->redraw_full_screen_request_rwlock);
@@ -129,15 +138,6 @@ void iface_video_exit(void)
 
     g_free(g_iface_video);
     g_iface_video = NULL;
-
-    if (g_iface_video_callbacks->exit)
-    {
-        g_iface_video_callbacks->exit();
-    }
-    else
-    {
-        WARN("Exit callback is not set!\n");
-    };
 }
 
 char *iface_video_create_window_title_text(void)
diff --git a/src/ui-imgui/bootstrap/myimgui.cpp b/src/ui-imgui/bootstrap/myimgui.cpp
index f1cbd30..9ae5b44 100644
--- a/src/ui-imgui/bootstrap/myimgui.cpp
+++ b/src/ui-imgui/bootstrap/myimgui.cpp
@@ -260,6 +260,11 @@ static gboolean myimgui_init_for_sdl3_opengl(SdlAppWindow *win, gpointer user_da
         SDLAPP_ERROR("Failed to get GL context");
         return false;
     };
+    if (!SDL_GL_MakeCurrent(sdl_window, gl_context))
+    {
+        SDLAPP_ERROR("SDL_GL_MakeCurrent failed: %s", SDL_GetError());
+        return false;
+    };
 
     // Setup Dear ImGui context
     IMGUI_CHECKVERSION();
@@ -597,6 +602,11 @@ void myimgui_render_cb(SdlAppWindow *win, gpointer user_data)
     }
     else if (win->renderer_type == SDLAPP_RENDERER_OPENGL)
     {
+        if (!SDL_GL_MakeCurrent(win->sdl_window, win->gl_context))
+        {
+            SDLAPP_ERROR("SDL_GL_MakeCurrent failed: %s", SDL_GetError());
+            return;
+        };
         ImGui_ImplOpenGL3_NewFrame();
     }
     else
@@ -665,6 +675,10 @@ void myimgui_destroy_cb(SdlAppWindow *win, gpointer user_data)
     }
     else if (win->renderer_type == SDLAPP_RENDERER_OPENGL)
     {
+        if (win->sdl_window && win->gl_context)
+        {
+            SDL_GL_MakeCurrent(win->sdl_window, win->gl_context);
+        }
         ImGui_ImplOpenGL3_Shutdown();
     }
     else

Steam

ARM64 UbuntuでSteamとか、って思っているかもしれないが、ゲームコンソールっぽいボタンもついているのだから、試してみる

もちろん、っぽいだけで、現状、このボタンはただのカーソルキーと英字キーだ

なので、すべてのゲームが快適に遊べるわけではない

それでも、それなりのキーアサインのゲームなら問題なく遊べる

インストールは snapから

$ sudo snap install steam

このスクリーンショットは日本語になっているが、設定をただ「日本語」にしてもフォントがないのか、□が表示されていた

原因をまじめに突き止めてもよかったのだが、codexを起動して「steamの設定を日本語にしたが、フォントがないのか□が表示されてしまう」とプロンプトしたらあっという間に設定をなおしてくれたので、どうやったのかはあまりちゃんと把握していないが、とにかく日本語が表示されるようになった

なので、同じトラブルに見舞われた人がいたら、codex11)に相談することをお勧めする

なお、テストプレイのために XeGrader plusを導入して遊んでみた

カーソルキーとスペースキーで操作できるので、この端末で遊ぶのにはもってこいだ

文字も十分可読サイズで、プレイするのには全く問題なかった

ただし、アクションゲームは(も)うまくはないので、ガチプレイに耐えられるかどうかは保証できない

起動時に、x64をARM64に変換するからなのか、起動時にはちょっと時間がかかるし、ウィンドウが消えている時間がそこそこ長いので本当に動いているか不安になるかもしれないが、大体動いているので、気長に待って吉である

Wireguard(VPN)

UbuntuならばWireguard VPNで自宅内へもアクセスしたい

TailscaleというフリーのVPNもあるので、自宅内にサーバおくとかめんどくさいな、という向きはそっちでもいいと思う

ただ、わたしは、多少管理の手間があってもWireguardの方がよかったと感じている

自宅内でホスティングしているwireguardの方がスループットが出るし、接続も安定している

Tailscaleだと、なんかしょっちゅうセッションが切れている印象

なので、設定してあるとめちゃ便利

設定については WireGuard を参照のこと

あると便利な周辺機器

マウス

基本的には大半のアプリをフルスクリーンで運用するので、あまり細かい作業はないため、大体のことは指タップで済む

が、一部のアプリ12)ではUIに細かいウィジェットが使われている関係で、指タップではうまく操作できなかったりする

そんなときはやはりマウスがあると便利である

携行することを考えれば、携行性が高いものがよいだろう

写真は、サンワサプライのペンマウスで、Bluetoothまたは 2.4GHzの無線でUSBドングル経由で接続できる

サイズ的にコンパクトで、PocketTerm35にちょうどいいと思ったので選んでみた

OpenMSXみたいなマウスがないと困るやつを操作するときにはもちろんだが、意外といいなと思ったのが、Terminal の上で文字列を選択してコピペする操作

X11などでおなじみの、左クリックしてマウスをぐりぐりっとドラッグして文字列を選択し、それを中ボタンでペーストするアレである

GNOME Terminalの場合は上でも書いたが、「コピー(Ctrl+C)」「ペースト(Ctrl+V)」になるが、選択は左クリックしながらのドラッグになる

この操作が、このペンマウスの場合は、カーソルを文字列の開始点に合わせたら、ペン先を押し込んで、そのままラインマーカで線を引くように動かすことになる

この動作がことのほか良い感じでちょっと感心した

選択したら右クリックして出てきたメニューから「コピー(Ctrl+C)」を選べばいい

ただ、逆に、1ワードだけ選択するときに使うダブルクリックはこのペンマウスだとちょっとやりにくいということも併せて記しておく13)

どちらを多用するのかによっては使い勝手の評価が分かれるのではないかと思う

キーボード

キー配列が変態的なため本格的にタイプしたければ外付けのキーボードは選択肢としてあると思うが、実用性としては疑問である 理由は単純で、画面が640×480なうえ小さいため、外付けのキーボードを置いた状態で画面を見えるように置くのが難しいという物理的制約があるからである

そんな使い方するくらいなら、sshdを動かしておいて、別の画面の大きなちゃんとしたキーボードのついた端末からログインして作業する方がいいだろう

改善されるといい点

画面サイズ

そもそものこのデバイスのサイズ(幅)がRaspberry Piのそれで決まっているように見えるが、横幅を拡大し、より大型のディスプレイを搭載すればより実用性の高いデバイスになると思う

具体的には uConsoleと同程度の5inch 1280×720 が載っていれば、より汎用的に利用できたのにと思う

アクションキー

uConsoleや DevTermでもおなじみゲーム用と思しきキーが PocketTerm35にもあるが、これ、左側はただのカーソルキーだし、右側の A/B/X/Y、さらにはいかにもマウスの左右クリックを想起させるような L/Rボタンに至ってはそれぞれ、'A','B','X','Y','L','R' が割り当てられたただの英字キーである

ジョイパッドとして認識されているわけでもないため、ゲームやPCエミュレータからジョイパッドとしても使えなければ、ゲームで一般的に使われる英字キーでもないので、まったく利用価値がない

<del>これはジョイパッドとして認識されるようにするか、最低でも、単純な英字キーとは別のものに割り当てるべきだろう

これらの制御は RP2040で行われているようなので、ファームウェアを書き換えることで改善できると思われるので、今後の研究対象のひとつだと思っている</del>

キーコードの割り当ては、RP2040側にインストールされている CircuitPythonにて行われている

背面のRP2040リセットのボタンをいい感じに連打していると、CIRCUITPYというUSBメモリデバイスが現れることがある14)ので、それが出てきたら、中の boot.pyや code.pyを変更したり、追加のライブラリを libフォルダーに入れたりしてカスタムすることができる

電池容量のOS側からの検出

電池容量や充電状態は画面上に搭載された四つの赤色LEDで表示されている

だが、OS側からアクセスできるようになっておらず、結果OS側では電池残量に応じた制御を行うことはできない

I2Cでもいいので、これが読み出せるようにしてあればいろいろできただろうにと、非常に残念

死にポートの存在

Raspberry Pi5はHDMIポートを二つ持っているが、一つを本体のモニタにつないで、もう一つは何もつながない状態でケースに封印されてしまっている

外付けのモニターをつなげられるようにすれば、移動中は極小デバイスとして、移動先で外部モニターやキーボードをつないでまあまあな性能のPCとして運用できればより利用価値が高まるのに残念である

ポーチがでかすぎる

ポーチ……でかすぎませんか?

このポーチで持ち運ぶ気にはちょっとなれない

諸々のこと

配送オプション

わたしは待ちきれない人なので、DHLの配送オプションにお金を支払った

6/8発送になって、当初6/11配送と出ていたが、6/9には国内に届き通関まですんで、結局は6/10に届いた

通常配送に比べて一週間程度早いようなので、この一週間に金を支払う価値をみいだせるなら悪いオプションではない

なお、DHLは配送日時の変更をおこなえるが、国内に届くタイミングまで待った方がいい

わたしの場合、最初変更が可能になった時点では6/11が選べる最速だったが、トラッキングで6/9に国内に入ったのを確認したところで改めて配送日時の変更をおこなったら、当初なかった6/10がオプションに現れた

なので、国内に届いたタイミング次第で前倒しできる可能性があるので、慌てて、変更可能になった時点で指定しない方がいいかもしれない

SSD

SSDに関してはWaveshareではPCIe TO M.2 Boardを推奨してるが、写真のように、純正ヒートシンク + M.2 Hat+ でもケースに収まる

ただし、純正ヒートシンクをマウントしたうえで、スペーサーをつけて M.2 HAT+を乗せる形になるので、GPIOピンへのアクセスはかなり悪くなる

また2230しか乗せられないので、SSDの選択肢も少なくなる

PCIe TO M.2 Boardは、ヒートシンク部分の高さが当然低く、SSDの真下にあたる部分の冷却15)が、純正ヒートシンクと比べてどのくらい良いのかで、SSDの温度に影響しそうな気もする

ただ、ケースとSSDとの間のスペースが大きいので、SSDの方に剣山状のヒートシンクを乗せればいいようにも思う

純正の場合は、写真のように、金属のプレート状のものを乗せるくらいしかできないのでどっちがSSD運用上有利なのかはわからない

キーマップ変更

ファームウェアのソースを公開して、って Waveshareに頼んだら、ファームウェアいじらないでもキーマップなら変えられるよ? ……と、いわれた

そう、PocketTerm35のファームウェアは Adafruit CircuitPythonで構成されているようだ

つまりは、できること・できないことは Adafruit CircuitPython次第ということだ

なお、この部分は大変に長くなるのでPocketTerm35のキーマップを変更するにまとめる

1)
ケースに収まるサイズに限るが
2)
Paspberry Pi4 2GBまたはRaspberry Pi5 1GB
3)
もちろんほかの組み合わせでもできるものもあるだろうが、試してないので何とも言えない
4)
いずれも Ubuntu26.04LTSの場合
5)
Ctrl+X で変更内容を保存するか聞かれるので Y と答えて、ファイル名等はそのままENTERを押せば保存終了する
6)
画面左端のタスクバー的なもの
7)
入っているときもあるのでこの辺の挙動がちょっと謎だが
8)
libxml2.so.2をあてにしているのに、Ubuntu25.10以降は libxml2.so.16しかない
9)
uConsole
10)
本体から吸い出したROMを使う場合はパッチあてが必要。ビルトインのROM込みでMZ-700になっているのであって、あくまでもMZ-800のエミュレータなのだ。なお、ROMのライセンスが正規かどうかは不明。心配なら本体から吸い出したROMにパッチを当てて使えばよい
11)
claude(Opus4.8)は解決できなかったのでcodex一択である
12)
OpenMSXなど
13)
単に私が下手なだけで、練習したらできるようになりそうな気もする
14)
標準のboot.pyによって、CIRCUITPYが出ないようにされているので、いい感じでRESETを連打することで、boot.pyの実行がキャンセルされることがあるので、そのタイミングでCIRCUITPYが現れる。本当にいい感じで連打してとしかいいようがない
15)
エアフロー

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information