M5Stackでプログラム その1

M5Stack Core2で手のひらサイズのアルフォス

久しぶりに楽しいガジェットを手に入れて、プログラムを楽しんでる!

何かそれなりの規模のものを動かしてみたいなぁ……と思ったので、久しぶりにPC-8801エミュレータを移植してみた!

比較的簡単に移植が出来たので、動いてるアルフォスを公開した!

 

 

f:id:PocketGriffon:20210905120604j:plain

今さらアルフォスの説明はいらないと思うので割愛しちゃうけれど、初代PC-8801で動くスクロールシューティングゲームで、故・森田和郎氏の作品。

私自身がマシン語を覚える事ですら大変だった頃に、さらにマシン語での高速化とか、もはや次元が違うと感じた方でした。森田氏が解説してくれた本を読んで以来、作るよりも先に高速化を考えてしまい、しばらくプログラムが作れなくなるという本末転倒を味わったw

 

以下、M5Stackというかエミュレータの実装のお話。

 

エミュレータの構成

今回は、過去にCP/M80を開発した際に同時開発した、お手製のZ80エミュレータを利用した。出来合いのものをそのまま利用したため、Z80エミュレーション側は何も手を触れていない(コレは楽させてもらった!)。

 

このプログラムは、ホントに純粋な初代PC-8801エミュレータとなっている。過去に3回くらいPC-8801エミュレータを開発した事があったため、今回はそんなに時間が掛からず作れた。

新しいスケッチを作成してから丸1日後にはコレが動いた感じだ(^^)

f:id:PocketGriffon:20210905114448j:plain

 

このPC-8801エミュレータは、アルフォスを動かすためだけに作ってあるため、必要最低限のハードウェアしか対応していない。

オールRAM、バンク切り替え、カラーパレット、そしてBASICを動かすためのテキストウィンドウ、monを動かすための拡張ROM…くらいだろうか。

 

私はテープ版のアルフォスしか所有して無く、よってこのエミュレータ上で動くアルフォスもテープ版だ。

 

テキスト表示は横40桁分しか表示できず、それを超えた部分は無視される。かつ40桁モードはサポートしていないので、切り替えた瞬間に文字が化ける。が、アルフォスでは使用していなかったので放置状態。

 

さらにテキストとグラフィックスは重ねて表示されない。これはアルフォスではテキストまたはグラフィックスという感じで排他的にしか表示されないからだ。テキストを表示するとグラフィックスは表示されない、または逆の状態しかない。

今思い出したが、テキストはアトリビュートをサポートしておらず、何色を表示しようとしても白で表示される(^^;;

 

開発の流れ

今回は開発をしつつ写真を撮っていったので、「こんな感じで開発してました」的な流れをご紹介したい。

 

まずは過去に作ったソースファイルを引っ張り出して思い出すところから(^^;;

Z80のコア部分は静的ライブラリとして作ってあったので、単品で持ってくる事はすぐに出来た。出来る限り機種依存しない構造にしといた甲斐があった(^^)

 

とはいえ、M5Stackでのデバッグはまだまだ慣れていないので、細かいところに手が届かない。あたふたしながらもようやくZ80エミュレータが少しずつ動き出した。

f:id:PocketGriffon:20210905131806j:plain

こんな感じにシリアル側にデバッグ情報を出しながら追いかけていく事に。

大量のデバッグ情報を流すのも厳しいので、イチからZ80エミュレータを開発してたら大変だったと思う…。

 

いくつかのI/Oを対応させていって、ようやくN88-BASICが起動した。

f:id:PocketGriffon:20210905132223j:plain

この状態ではまだM5Stackの液晶画面には何も表示されてなく、あくまでもメモリ中の情報を見ている。上の写真は、PC-8801のVRAM(F3C8h)を見やすいように可視化したモノだ。

こんな感じで画面へ出力させる前に、できる限りテキストベースで動きを確認している。

 

この「How many files?(0-15?)」の画面から先に進むためには、リターンキーを含むキー情報を入力出来るようにしないといけない。

しかしキーボード系はちゃんと対応しようとすると結構面倒なのだ(T-T)

今回は(も?)できる限り手を抜きたい!!!

そこで、アスキー出版局から発刊されていたPC-Techknow8800Vol.1に書かれていた方法を採用する事にした。

f:id:PocketGriffon:20210905133053j:plain

この仕組を使うと、あたかもファンクションキーを押したがごとく、自動的に文字を入力させていく事が出来る。キースキャンなどの細かい情報を発生させる必要もなく、デバッグ段階でとても便利に使える機能(裏技)だ!

 

f:id:PocketGriffon:20210905140348j:plain

おお、ついにN88-BASICが起動した時の画面が出たね!(^-^)

 

アルフォスのプログラム読み込み

さて、N88-BASICが起動したところで、次はアルフォスのデータを読み込んでみよう。

出来る限り実機と同じ状態でアルフォスを起動したいため(手を抜きたいため…とも言う)、カセットから1バイト読み込んでくる処理を横取りする。

データのロードは、さっきのキー入力の仕組みを利用して「load "cas:"」とすれば良い。

 

実際のデータの読み込みには、PC-8801の未使用I/Oポートである[0Fh]を新設し、このポートからデータを読み込むと、カセットからのデータを1バイト読めるようにした。

 IN A,(0Fh)

そしてエミュレータ側の「カセットからデータを1バイト読み込み関数」にI/Oポート0Fhからデータを取得するプログラムを追加…というかプログラムを書き換える。

I/Oポートがアクセスされたら、SDカードからアルフォスのデータを1バイトずつ返すだけの簡単な処理だ(^-^)

 

さあ、ココまで来たらメモリ上にアルフォスが読み込まれ、おそらく実行されているはずだ!

グラフィックスの状況をシリアル経由で知ることは簡単ではないので、そろそろ画面を実装してみる事に。

 

そうして表示された画面!

f:id:PocketGriffon:20210905143120j:plainf:id:PocketGriffon:20210905143138j:plain

……うん、パレットの対応を入れてないので、まぁこうなっちゃうよね(^^;;

 

パレットの解決をしつつ、画面の更新についても考えてみる事に。

PC-8801は横方向が640ドットあるのに対して、M5Stackは320ドット。単純に横方向のドットを半分にすればいいや…と思ったが、それだと1ドットの縦線などが見えなくなる可能性がある。

 

そのため、隣に並んだドットの色情報を見て、お互いの色を半分ずつ混ぜ合わせる事にした!

これをリアルタイムで処理するのは簡単ではないのため(ウソ、簡単だけど数が多いので実行時間が掛かる)、あらかじめパレットデータが変更されるたびにテーブルを作成する事にした。

f:id:PocketGriffon:20210905144002j:plain

これはマップに配置された固定砲台の絵だけど、黄色と(PC-8801には本来無い)ちょっと薄い黄色があるのがわかるだろうか。

 

f:id:PocketGriffon:20210905144147j:plainf:id:PocketGriffon:20210905144206j:plain

パレット情報もあわせてやるとこんな感じ!

おおお、画面は半分だけど思ったよりも違和感なく表示された!(^-^)

 

実行時間

今回は初代PC-8801という事で、Z80CPUを1つだけ対応した。ディスクもサポートすると、ディスク側のCPUも対応せねばならなくなる可能性があるので、今回はアルフォス専用という大義名分の上でパスした(^^)

 

M5StackにはCPUコアが2つあるらしい。そこで今回はCPUのエミュレーションと、画像データの生成を2つのスレッドとし、それぞれを別のCPUで実行する事にした。

 

CPUエミュレータはまだ少し余裕がある気がするが、画像生成側はかなり重たい。画像生成も重たいが、画面転送(putImageをそのまま使用)も重たいんだと思われる。

メモリアロケーションの種類にDMAなる文字列も見えるので、もしかしたら高速転送などが存在するのかも知れないけど、まだそこまで調べられてない(^^;;

 

まとめ

とりあえずこんな感じで動かせましたよ(^-^)

 

そういえばTwitterへ投稿した後、M5Stackを知らないのでサイズ感が分からない…という話をいただいた。なるほどそりゃそうだと思い、サイズ比較の写真を撮ったのでご紹介。

f:id:PocketGriffon:20210905152417j:plain

手のひらに乗る…というか、手のひらに収まるアルフォスだw

 

M5Stack自体、手に入れて間もないけれどもプログラムは作りやすいと感じている。

一時期、スケッチの書き込みがうまくいかず、Twitterに「これじゃあ作れない」と嘆いていたが、これはUSB Type-Cを使うのではなく、USBハブを介したUSB2.0を使うようにしたら劇的に改善された。

これ以降も何度か不安定になる事はあったが、シリアルケーブルを刺し直す事で復活出来ている。超快適(^-^)

 

今回、動かすの最優先で表示系が遅いままの状態なので、もう少しだけ高速化してみたいと思う(^^)

いや楽しいね、新しいガジェットは!

 

ではまた次回!(^-^)ノ