M5Stackでプログラム その3

M5Stack Core2で動かすエミュレータ第2弾!

多分、M5Stackの使い方としては微妙なんだと分かりつつも暴走し続けるw

 

f:id:PocketGriffon:20210908011435j:plain

今回は富士通FM-7

FM-7の特徴といえば、究極の8ビットCPU(と言われる)6809が2つ載ってるって事!

贅沢にもメイン側とサブ側で同じCPUが使われている。

 

何年か前にLinux上で動くFM-7エミュレータを作っていた。「6809もわかるんですね」と言われそうだけど、ホンネは68の方が慣れている。6301などに抵抗なく入っていけるのもそのおかげかも知れない(^^)

今回はコレをベースに移植をしようと思っている。

 

FM-7をM5Stackに移植しようと思った時に、6809が2つもあるFM-7が、ちゃんとそれなりの速度で動くんだろうか…という心配があった。PC-8801のアルフォスだって結構苦労していたのに、単純にそれの2倍だ…。ちょっと簡単じゃないだろうという予想があった。

 

しかし今回は試してみたい事が1つあったのだ!それは…「主要なメモリをPSRAMではなく、内蔵(INTERNAL)メモリに載せていたらどうなるのか」という事だ。

 

PC-8801を移植した際には、M5Stackの事もさっぱり分かっていなかったので、使用するメモリについては無頓着に考えていた。確保できればいいや的な発想?(^^;;

プログラムを作るごとに新しい事に挑戦出来るM5Stackすごいぞ!(^^)

 

まずは単純移植

元々ANSI準拠で書かれているプログラムをM5Stackに持ってくるのはとても簡単だ。しかもLinux用に書かれているプログラムなのでクセも少ない。

新しいスケッチにファイルをコピーしただけで、無変更で動いてしまった(^-^;;

 

M5Stackに依存しているところと言えば、メモリを確保するところくらい。

ここも単純にmallocで確保するだけならば無変更でいける。M5Stackは「どの領域からメモリを確保するか」が柔軟に指定できるため、ここは見極めが必要なところだ。

 

FM-7は画像データ(VRAM)がサブCPU側のメモリに入っている。動かすのがゲームの場合、このVRAMを激しく書き換えるはずなので、今回はサブCPU側のメモリ64KBを内蔵RAMに、メインCPU側のRAMを外部RAMに割り当ててみた。

 

そして試行錯誤の結果、F-BASICが起動するようになった!

f:id:PocketGriffon:20210908082226j:plain

FM-7はサブCPU側の$C000以降にスクリーンバッファがある。ここを確認すれば、BASICで表示しようとしている文字がわかるという仕組みだ。

例のごとく、まずは画面に出す前にシリアル上でメモリ内容を確認。

よし、ここまで動けば画面に表示させてみるぞ!(^-^)

 

FM-7の豪華な画面仕様

M5Stackでプログラムをする際、なるべく画面更新する範囲を狭めるのがテクニックとして有効だという事は、PC-8801エミュレータの時に学んだ。

だがしかし、FM-7ではそうもいかない事情がいくつかあるのだ!

 

まずひとつめがカラーパレット機能。

例えば、0番のカラーは標準では黒なのだけれども、これを青にする設定が出来る。そうすると画面では一瞬のうちに黒色が青に変化するのだ!いちいちVRAMを書き換えていかなくても瞬時に色が変わるんだから凄い機能だ!

 

このパレット機能を使われると、無条件に画面全体を再描画しなければならない。画面上に黒色がどこにあるのかなんてわからないため、全体を書き換えざるを得ない(T-T) しかもFM-7はカラーパレットが使えるというのをウリにしてた部分もあるため、いろんなプログラムで使われまくってる。そのため、常時パレットレジスタを監視して、書き換えがあった際には画面全体を再描画するようにしている。

 

あれ?でもカラーパレット機能はPC-8801にもありますよね?と聞かれれば「そうです」だ。たが先日作ったPC-8801エミュレータはアルフォス専用と銘打っていたので、ちょっと事情が違う。アルフォスではゲームが始まる時にパレットを設定すると、それ以降は変更されていないため、監視する必要がなかったのだ(ネタばらしだw

 

ふたつめがマルチページ設定。

3枚あるVRAMのうち、どのプレーンを表示して、どのプレーンを書き込み許可するのかというビット。

これもレジスタを書き換えられると画面全体に影響を及ぼすタイプのモノだ。

しかもそれなりの頻度に使われている(T-T)

エミュレータ上では「プレーンを表示しない」というよりは「表示時になかったことにする」ような感じでプログラムを入れてある。表示しなくても処理が軽くなったりはしない(^^;

 

ちなみにPC-8801にも設定はあるけれども、アルフォス専用(以下略

 

みっつめがVRAMオフセットレジスタと言われるモノ。

スクロールするゲームなどで頻度高く使われるもので、ハード的に画面をスクロールさせる機能だ。BASICでも普通に使われていて、LISTなどをして画面がスクロールしたりすると利用されている。

 

FM-7は標準状態でファンクションキーの表示がされない。PC80系から来た人がちょっと面食らう設定だと思うが、CONSOLE命令で表示させることは出来る。

出来るけれど、ファンクションキーを表示させた状態だとスクロールがものすごく遅くなる。これはファンクションキーを表示させる事で、画面全体をスクロールさせる事が出来なくなり、ハードウェアに頼る事が出来なくなるからだ。

 

……という感じに、画面をスクロールさせるための機能なのか…とだけ解釈されている。

実際に値を変えてみるとスクロールするので、機能としては正しいんだけど、もうひとつ大きな機能があるのだ。

それは…「VRAMをアクセスした時のアドレスにオフセットを加える」というもの。

おそらくレジスタ名の由来はこっちの機能だ。

 

普通、アドレス$0000に$FFを書き込むと、当たり前だけど$0000に$FFが入る。

これを、例えばVRAMオフセットレジスタに$1000を書き込んだ状態で同じことをすると、$0000には値が入らずに、$1000に$FFが入る。

え??じゃあ読み出しはどうなるの??となるが、プログラムで$0000をアクセスすると$1000がアクセスされた事になり、$FFが返ってくる。

……意味が通じるだろうか?(^^;;;

 

しかもこの設定はVRAM($0000〜$BFFF)のみに有効なのだ。この範囲を超えた場所をアクセスすると、通常通りのアドレスに読み書きされる。

こういう状態で作られたVRAMの情報を、表示する時に考慮しながら画面を作る必要があるのだ!本エミュレータでは垂直同期などを考慮せずに画面再描画を行っているため、どうしても画面の上下でチラチラしたものが見えてしまう事がある。もうこれは割り切るしかないか…と諦めた(^^;;

 

…というような複雑な事情がてんこ盛りで、画面描画を速く出来る要素が少ないのだ。

思うところはたくさんあるけれども、まずは表示させてみよう!考えるのはその後!

f:id:PocketGriffon:20210908092421j:plain

…あれ?文字が黄色くなっちゃうぞ??(T-T)

パレットの辺りとかバグが入りやすくて難しいコードが続く…うーん…

f:id:PocketGriffon:20210908092615j:plain

修正してちゃんと白が表示された!(^-^)

FM-7は起動時の解像度が40x25なので文字もキレイに読める。

ちなみに「load」はキーボードから打ち込んでるのではなく、プログラムでキー情報を発生させている。実際のテープも読んでなく、SDカードから読み込ませているのは、PC-8801と同じ仕組みを利用している。

 

f:id:PocketGriffon:20210908093038j:plainf:id:PocketGriffon:20210908093059j:plain

f:id:PocketGriffon:20210908093116j:plainf:id:PocketGriffon:20210908093140j:plain

f:id:PocketGriffon:20210908093206j:plainf:id:PocketGriffon:20210908011435j:plain

PC-8801アルフォスを作った時には「640ドットを320ドットに間引きしてどんな画面になっちゃうんだろ…」と心配していたが、もうあんまり気にならなくなってきたw

80桁の文字を読もうとするのは厳しいけれども、なんとなく雰囲気が味わえるだけでもいいのでは…と自己解釈(^^;;

 

f:id:PocketGriffon:20210908093531j:plainf:id:PocketGriffon:20210908093555j:plain

昔、工学社のI/Oに載っていたゲームも打ち込んでみたデータがあったので動かしてみた。

ギャラクシアンは80桁で文字表示をしているのでちょっと厳しいかもだけど、雰囲気よ、雰囲気(^-^)

 

感覚的な速度

ちゃんとした速度を計測していないので、感覚値でごめんなさい(^^;

一度、動画をTwitterに載せた後、2つの改良を施した。

・メインCPU側のメモリ空間も内蔵RAMに載せた

コンパイラの最適化オプション付け忘れてた!

どちらもそれなりの効果があったようで、大体2割くらい高速化された!

おかげで見た感じの動き(速度)は実機と大差なくなったよ!(^-^)

 

今回もCPUのエミュレーションで1コア、画像生成で1コアを使う構成とした。

6809CPUを2つエミュレーションする必要があったが、思ったよりも遅くなってない。

これは6809コアをカリッカリにチューニングしてあったおかげかも。ソースを見てみると、__builtin_prefetch、likely/unlikelyなどがふんだんに使われていて、当時かなり頑張って高速化していたようだ(^^;

 

画面表示に関しては、前回のPC-8801同様にLovyanGFXを利用している。

このライブラリ、めちゃくちゃ使いやすくて良いです!(^-^)

 

ちなみにインターレース表示なども試してみたけれども、うまくいかなかった。

上下のドットで色を補間やらないと、必要なドットが削れてしまうのが原因だけど、補間する処理時間が無いからインターレースなのに…という事でボツになった(^^;;

 

ピンポーン!

 

f:id:PocketGriffon:20210908094145j:plain

……このタイミングで届きますか、あなたは……(-_-;;

悩ましいじゃんかよー…

 

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