M5Stickでプログラム!その1

M5Stackでプログラムしてる流れで、なんとなくだけどM5Stickも入手した事は、前回のブログでご報告した!

f:id:PocketGriffon:20210916170858j:plain

FIREも一緒に手に入れてるけど、こちらはまだ未開封…(^^;; このまま行くと積みマシン確定の予感w

 

M5StackとM5Stick、画面解像度が違っているけれども、内部のスペックはそんなに違ってない…というような、超漠然とした解釈をしていた。

今回は、この赤いM5Stickでのプログラムのお話(^-^)

プログラムの雰囲気が似てるんだったら、そのままの感覚で行けるでしょ!(^-^)

 

まずは電源を入れてみる。

f:id:PocketGriffon:20210922165943j:plain

あ、この画面はネットの記事とかで見たことある!ちゃんと立方体がぐりぐり動く(^^)

そういえばM5Stackの初期画面とか、どうやったらもう一度見られるんだろ…?

そのためだけにもう1台手元にあるヤツを空ける?(^^;;;

 

f:id:PocketGriffon:20210922170101j:plain

M5Stick自体の大きさはこんな感じ。

学生っぽく言えば筆箱に入るサイズ!

画面の大きさも相当小さい!画面に出てる数字なんて読めないよ…。

ルーペルーペ…

 

よし、Macに接続をして、Hello Worldを表示させてみる!

f:id:PocketGriffon:20210922170258j:plain

え!?その角度で表示されるのね…。想像と違う方向でびっくりw

ということは、こっちが上なのか…なるほど。

今回は最初っからLovyanGFXを利用させていただく事にした(^-^)

このライブラリは本当に手放せない!(*^_^*)

 

f:id:PocketGriffon:20210922170946j:plain

lcd.setRotation(3) としたら描画の基準が横になった!(^-^)

もしかしたらDMA出来ないとか弊害があるのかも知れないけれど、脳内で縦横を逆にしまくるのは避けたいので、まずはこれを基準としてみよう!

同時にビットマップのテストもしてみる。

この辺りのプログラムは全く同じだ!

よし、これでM5Stack的な感覚でプログラミングができそうだ!

 

外部記憶がない!メモリがない!

M5Stickの画面サイズは240x135となっていて、M5Stackの320x240に比べても面積比で約42%狭い。

この狭さになると、この上でエミュレータを動かそうなんて考える人はいないだろう(^^;;

横640ドットあるタイプのマシンからの移植は絶望的かも?640→240に変換するって事は、8ドットを3ドットに変換するって事だ!そりゃ無茶(ToT)

 

この画面サイズで、ちゃんと元画像が表現できるのは、PC-8001(160x100)とかMZ-80(80x50)くらいだろうか…。

とりあえずカラーが出るPC-8001を移植してみる事にする!

 

さっそくM5Stackのコードを持ってきて移植をし始めたのだが………

SDカードが入らないことに、今気がついた!!!

あちゃー……必要なデータをSDカードからロードするようにしていたので、その部分はまるっと作り直すことに…(T-T)

 

SPIFFSというのを利用すると、内臓のフラッシュメモリ(4MB)にデータを入れておくことが出来るらしい。これは近々試してみたい。

 

その後、さらにPSRAMが存在しないことに気がついた!PC-8001は出来る限り内蔵RAMで動くように調整してあったのでさほど問題にならなかったけれど、PSRAMに依存している他のマシンは移植出来ないな…。

 

結局、PC-8001エミュレータは、必要なメモリを内蔵メモリから確保した。確保出来た!これが出来なかったらヤバかった(^-^; この辺りの空き容量感覚はまだわかってない。

 

f:id:PocketGriffon:20210922173827j:plain

そして無事に動いたPC-8001エミュレータ。「移植してみるか」と思ってから2時間くらいの作業で動かせた!問題はあったものの、やはり移植性は高いんだと思う。

f:id:PocketGriffon:20210922173939j:plain

ちゃんとDot by Dotで表示されてる!

ちなみにこのサイズだと私はルーペが必須だ!とてもじゃないけどROGANには無理!

f:id:PocketGriffon:20210922174422j:plain

40x20文字表示でプログラムを打ち込んで実行させてみたところ。もはや文字として認識する事は出来ないが、なーんとなくやってることが想像出来るw

 

移植してる最中に気になったこととしては、M5Stick本体が少し熱を持つ。M5Stackはまーったく熱を感じなかったので新鮮!全体がほんのり温かくなっているので、風通しの良い場所で開発したほうが良いかも!(^^)

 

 

無茶移植をしてみたくて!

もうひとつ、やっぱりアルフォスは動かしてみたいじゃないのさ!(^-^)

 

でも……割と初期の段階から「無理だよそれは…」と悟っていた。

まず上にも書いたけれど、横640ドットの絵を240ドットに縮めるのが厳しすぎる。

縦方向も200ドットを135ドットにするのが簡単ではない(T-T)

 

それからPC-8801は大量にメモリを積んでいる。初代であってもメインメモリ64KB、N-BASIC24KB、N88-BASIC32KB+8KB、VRAM48KBと豪華絢爛!これに加えてアルフォスのデータが必要になるのだ…。これをSDカードなしで実行しなければならない。

やっぱりSPIFFSかなぁ…と思って調べ始めたが、それでも「無理」が頭から離れない(^^;

 

そうこうしてるうちに、2つのアイディアが浮かんだ。

1つめはメモリ関連。アルフォスをロード→起動するまでの過程でBASICやmonを使うので、BASICのROMが必要なのだが、実はアルフォスが起動したあとはBASIC ROMは使われないのだ。ということは、アルフォスのロードが終わった瞬間のメモリイメージ(64KB)を持っておいて、エミュレータのメモリにコピーしてやれば、メモリは最小限で済むのでは???

 

2つめが表示系。内部的にはM5Stackと同じく横320ドットでイメージを生成し、それをLovyanGFXの機能を用いて縮小表示してやればどうだろう…と考えた。

f:id:PocketGriffon:20210922181444j:plain

f:id:PocketGriffon:20210922181421j:plain

f:id:PocketGriffon:20210922181403j:plain

おおお……思ったよりも悪くない!(^-^)

縦方向は縮めていないので下が映っていないが、まずは動かすことが先よ(^-^)

 

f:id:PocketGriffon:20210922181917j:plain

だがゲームのデモ画面になると、画面が壊れてしまう事がわかった。デモが初期値から始まるのではなく、変な場所から始まってしまうのだ。うーん…これは直すのが大変そうな気がする。なにせ思い当たり原因となりそうな事が山のようにあるのだ。BASIC ROMが無いとかw

 

なんとなく動かせそうな雰囲気は感じられたので、今回はここまで!

開発している最中に、BASIC ROMを載せられそうな算段も立ったので、次回チャレンジする時はちゃんと正規の方法で起動させてみたい。

 

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

M5StackでSDカード読み込み

f:id:PocketGriffon:20210916161942j:plain

M5Stack Core2にBOTTOM2を取り付けてみた!

おお〜!厚底になって安定感が増した!(たぶん変わってない)

重量もアップして持ちごたえが良くなった気がする(^-^)

…で、これで何が出来るのか、あんまり理解していないのですが…汗

 

さて本題。

いろいろとホントに申し訳ない……orz

ブログ書いててこれほどまで訂正と懺悔が多いのは初めてだ(T-T)

 

お昼休みに本屋さんでぺらぺらとESP32関連の本をめくっていた。狙ったわけでは無かったのだが、SDカード関連の記事が載っていて、読む…という感じではなく、目に入った程度だったのだが……その時の目に入ったモノがとても気になって…。

 

違和感に基づいて、もう一度SDカードの読み込み実験をしてみた。

これが↓前回載せていた写真。

f:id:PocketGriffon:20210914181208j:plain

そして↓こっちが↓今回の実験写真。

f:id:PocketGriffon:20210916162440j:plain

なんだ、特に変わってないじゃん……

!!変わってるじゃん!!!

桁が1つ違う!!

約21秒以上掛かっていた読み込み時間が3秒以下になり、1秒間に約102KBだった読み込みが、なんと1024KBに増えている!!!

 

え?!これが本来の速度????

…M5Stackよ、すまぬ…意図的では無いにしてもキミの評価を下げてしまってたかも(TT)

 

なんのことはない、これまた私が勘違いというか無知をご披露してました。

SDからの読み込みには1バイト読み込みしかないんだと思い込んでた!!

 

 FIle f = SD.open(filename);

 for(int i = 0; i < f.size(); f++)

  data[i] = f.read();

 

↑みたいな感じでデータの読み込みをしていたんですが、一気に読む方法があった!

 

 FIle f = SD.open(filename);

 int size = f.read(data, f.size());

 

まぁ…そりゃあるよね(T-T)

スクリーンショットを作ってる最中に、SDへの書き込みがブロック単位で出来る事に気がついた。あれ?書く方は一気に出来るのに、読む方は出来ないんだ…と思った覚えはあるけれど、それ以上は特に追求しなかった。

 

今見てみたらスケッチブック例にある「SD(esp32)」→「SD_Test」で同じ方法で読み込んでいた。ちゃんとサンプルを見ないとダメですな…orz

 

Bad Apple!!の再々改造!

こうなると……先日改良したつもりのBad Apple!!を、さらに修正したくなるよね!

 

まず冒頭部分でデータを一気に4MB近く読み込んでいた部分を修正してみると、それまで40秒位かかっていた読み込みが4秒前後まで短縮!速い!!(^o^)

 

アニメーション部分も改良してみると……あっという間にバッファがいっぱいになる!(^^;

アニメーションデータの消費速度の方が圧倒的に遅い。

そりゃそうだ、前回のブログで「平均23.5KB/秒のデータが必要」と計算してたのに、今は1024KB/秒の読み込み速度だ!実装値で1/10だとしても100KB/秒。余裕がありすぎる(^^;;;

 

仕方ないので読み込みの速度を落としていく。冒頭部分で読み込んでいるデータ量を減らしても良かったのだが、それよりもアニメーション実行中のスムースさを心がけたかったので、読み込み処理の単位を小さくして、確実に1/30秒表示を心がけた。

 

細かい調整をして、アニメーション開始時と終了時のバランスを良くした。基本は少しずつ読み込みが速いけれど、後半の複雑なデータでは読み込みが遅れていく。結果的に良い感じに調整ができた!

 

うむむ……先日、あれだけ鬼気迫る思いで改良をしていたBad Apple!!が、ものすごくすんなり動くようになってしまった…(T-T)

 

Bad Apple!! グレイスケール版

前回のこのブログでもちょろっと書いた、白黒2値の絵ではなく、グレイスケールで表示するBad Apple!!というのを実験している。

 

たけど、圧縮データの展開に時間がかかる、高速なメモリが使えない、何よりもSDからの読み込み速度が壊滅的に無理……という状況だったのだが、ここに来てSDカード状況が一変した。

 

そして別の2つ(展開速度問題、高速メモリ)も脳内でアイディアが浮かんだ!

一度は諦めたんだけど、これはもう一度チャレンジしてみないといけないですなぁ!!(^^)

 

 

ところで…

f:id:PocketGriffon:20210916170858j:plain

こちらも手に入れてしまった!(^-^;;;

 

Core2では動かない、または改造が必要…みたいなものが多そうだったので、前々からFIREも手に入れておきたいな…と思っていた。

 

M5Stickの方は正直良くわかっていないんだけど、こちらも何か動かせないかと考えてる。でも今見たらSDカードを入れるところがないので、大きなデータを使うタイプのモノはダメなんでしょうね…。そもそもの使い方が間違ってるって事なんだろうけれども(^^;;

 

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

M5StackでBad Apple!! [改!]

いやはや……前回更新したブログにいくつか見当違いや勘違いを記載してしまったので、急遽追加で書いている。

 

f:id:PocketGriffon:20210915002900j:plain

 

先に一番の原因を書いておくと、SDカードからの読み込みが全く間に合っていなかった。

計算上、ギリギリか無理かな…という線だったのだが、エラーもなく表示されていたので安心しきっていたのだが………

 

コマ落ちしてた!!

自分の中で一番許せなかったことがコレ(T-T)

あれだけ1/30秒描画にこだわっていたのに、まさか描画されていない絵があったなんて…。

 

データの読み込みが危うくなってくると、頑張ってSDカードからの読み込みを追いつこうとする処理を入れてあったのだが、そこのミスがあって1フレームまるごとではないが表示が欠けていた。

結果的にデータは読めていたのだが表示があかん…これは美しくない(T-T)

 

この部分を修正して表示の1/30秒を保証したところ、今度はデータ読み込みが間に合わなくなる状況に陥った!まさにあちらを立てればこちらが立たず!(T^T)/

 

余った時間の全てをSDカード読み込みに!

そもそも、SDカードからの読み込みはCore:0(描画を担当しているコア)が余った時間で行うようにしていた。しかしこうなってくるとCore:0だけに任せておけなくなったので、Core:1(圧縮データを展開しているコア)も時間が空いたらSDカードから読み込むようにした。

 

SDカード読み込み部分はリエントラントには出来ないので、どっちかのコアでしか実行が出来ない。先に処理を奪った側のコアで実行させるようにしたが、もう片方のコアも諦めずにリトライを繰り返すので、先のコアが処理を開放した瞬間にもう片方がSDの読み込みを始める。

 

それでも後半の複雑な絵柄を描画するタイミングではSDカードの読み込みに追いついてしまう。もはやこうなると圧倒的に読み込み速度が足りないのだ(T-T)

いわゆる初期段階の設計ミス的な…orz

 

メモリを活用せよ!

SDカードの読み込みが追いつけないのであれば、あらかじめ出来る限りのデータは読み込んでおき、実行時に追加読み込みする量を減らすしか無い!フルマラソン(42.195Km)の勝負で、スタートラインを40km地点にするようなもんだ(^^;;

 

そこで、PSRAMで確保出来る最大の領域を使う事にした。試しにフリーブロックを表示させてみると4194252バイトと出た。ほぼ4MBが使えるという事ですな…。

この容量は心強い!!(^-^)

 

……あれ??今気がついた。M5Stack Core2ってPSRAMが8MBあるんじゃなかったっけ?

f:id:PocketGriffon:20210915084237j:plain

ほら!8MBって書いてある!!

M5Stack(というかESP32?)は sizeof(void *)=4なので、アドレス空間的には余裕のよっちゃんなはずで、システムが専有!とかしていない限り、ふつーに使えそうな気がするんだけれども…。今は気持ち的に調べてる余裕がないけど、これは使いたいなぁ…。

 

そして確保出来た全メモリの93.75%にあらかじめデータを先読みしておく事にした。

f:id:PocketGriffon:20210915010131j:plain

起動するたびに約40秒の待ち時間が発生するが、これも30フレーム動作のため!(^^)

メモリ目一杯まで読み込むと、6565フレームあるうちの5378フレームまでを読み込んでおく事が出来た。なんというチート!(^-^;;

残りの1187枚分を実行中に読み込ませれば勝ちだ!

 

これのおかげで、大体2740フレーム前後を表示している頃には、SDカードから最後までのデータを読み込めて、ようやく安定した30フレーム動画を見れるようになった(T-T)

2740フレームを表示する期間で1187枚を読むって…完全な負け戦(^^;;

 

今回の失敗の敗因は、間違いなくSDカードからデータ読み込み速度の過信ですね…。SDカードの読み込みに専念した時は100KB/秒くらいの速度だったけど、実際に動いてる状態から数値を計算してみると、秒間11.8KBくらいしか出てない。圧縮データを展開するデータの単純さなどから20KB/sくらいは出ると思っていたが、甘かった(T-T)

 

こんな状態なので、サウンドもSDカードから…とか無理な気がする(T-T)

音声を諦めてMIDIにしちゃうとか…もっと手軽にMMLにしちゃうとか…汗

まぁでも音は遠のいちゃったかもな…と残念(T^T)

 

グレイスケールでの表示を検討していたけれども、データ量が白黒2値よりも遥かに多い。展開速度も時間がかかりそうなので実現無理かも(でも最初だけみたいからやってみるw

 

出来上がった30フレーム動作の動画だけど、再度Twitterにアップしたところで違いがはっきり分かるわけでは無さそうだったので、公開は控えてる。どこかで何かのタイミングがあったらお披露目していきたい。実物を見てもらうのが一番なのだけれども…うむむ(^^;

 

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

M5StackでBad Apple!!

もうM5Stackでの取り組みは一段落させよう…と思っていたけれども、320x240というサイズに身に覚えがありすぎて、やはりこれだけは挑戦せねばならぬだろう…。

そう、Bad Apple!!だ(^^)

 

f:id:PocketGriffon:20210914171153j:plain

過去のブログを見てもらったら分かるけれど、私は半年ほど前にポケコンでBad Apple!!の表示に取り組んでいる。

Bad, Apple の検索結果 - レトロパソコンであそぼう!

 

最終的にはポケコンに取り付ける1MBの増設メモリを作ってまで、フルのBad Apple!!を再生させている。ココまで行くともはや執念だ(^^;

 

 

ぼんやりと「M5StackでBad Apple!!を動かそうとしたら、何が問題になるだろうな〜…」と考えていた。ぱっと分かるのは、データがメモリに入り切らないという、いつもの問題。

なんとなく電卓を叩きつつ「行けるかも……?」と思ったのが運の尽き……。

見えてしまったらプログラマとしてやらねばならないのだ!!!!

 

実現方法の検討

とりあえず検討するべきことは以下の2つかな?

 データの置き場所、転送方法

 圧縮方法、展開方法

それぞれに答えが出れば、組み合わせる事でBad Apple!!が実現できそうだ。

 

まずはデータの置き場所を考えないといけない。

M5StackはでっかいPSRAMがあるとは言え、最大で4MB弱が限度だ。Bad Apple!!オリジナルのデータは11MB以上ある。そのままの状態ではRAM絶対に入らない。

 

過去にPC-1600Kで圧縮した際には884KBに収まったが、あの時とは画像サイズが違う。PC-1600Kでは64x32の2値だったが、今回のM5Stackでは320x240の2値だ。単純にドット数だけ比べても37.5倍の違いがある。

 

今回も圧縮方法から考えてみよう……と思ったが、圧縮データをストリームで展開するのならば、ランレングス圧縮が最適だ。これはもう疑いの余地がない気がする。あとは「ランレングス圧縮した後のデータをどうするか」だ。

 

あれこれこねくりまわす事はしてみたが圧縮の方針を決めた。さっそく圧縮プログラムを作ってみたところ、320x240ドットの画像データが最小で305バイト、最大で1892バイトのファイルとなった。全てのファイルを全部つなぎ合わせると約5.1MB、1枚の画像平均だと約800バイトだ。

 

5.1MBのデータということは、やはりオンメモリに収まらない。SDカードから少しずつデータを読んでくる方式を検討する事にした。

 

Bad Apple!!は秒間30枚の画像データを表示していく必要がある。30枚ということは平均800バイトとして約23.5KBが1秒間のデータサイズとなる。最低でもこのサイズのデータがメモリ中に置かれてなければ、1/30秒単位での表示が無理ということになる。

 

……SDカードからは秒間でどのくらいのデータが読み出しできるんだろうか??

さっそく実験プログラムを作ってみる。

M5Stackを使っていてホントに楽ちんだと思うのは、こういうこまめな実験がとても手軽にできるという事だろう。面倒とか手間とか思えないほど簡単だ!(^-^)

f:id:PocketGriffon:20210914181208j:plain

一番下にある「Speed」というのが、1秒間に読み込めるバイト数だ。これを見ると読み込みに専念した状態で約100KB/秒の転送速度があるらしい。おそらくSDカードの特性に左右されるものだと思うので、あくまでも「うちの環境では」としておく。

 

そして「読み込みに専念して100KB」というのも考慮しないいけない。他のことをしながら読み込みに行ったら、平気で1/10以下になる。そして実際間に合わない可能性が高い。

 

そこで以下のような方針を考えた。

 大きなバッファを用意し、あらかじめバッファの9/10は先読みしておく

 表示が開始されたら、少量ずつバックグランドで読み込みをしていく

 

ここまで考えてみて、ようやく「行けそうだ」という手応えを感じられた(^^)

 

実装

f:id:PocketGriffon:20210914182258j:plain

まずはデータを圧縮して巨大なファイルを作成しておく。この手のツールはMacでぱぱっと組み上げる。2値しかなければテキストでそれっぽく表示させて確認するのも簡単だ!(^^)

そしてM5Stack側のプログラム構成はこんな感じにした。

・Core0: 表示、SDカードの読み込み

・Core1: 圧縮データの展開

 

表示にはLovyanGFXを利用した。

表示とSDアクセスは同時に出来ない?みたいな話が出ていたので、これらの処理を同じコアににまとめる事で、暗にバッティングを回避する事にした。

 

Core1で進む圧縮データの展開が終わったら、Core0の表示を開始するようにして、画像のガタツキを極力なくしてみた。Core0は展開を待つ間、SDカードを読みまくる。

久しぶりにvolatile宣言を使ったかも(^^;

 

表示についてはpushSpriteをする回数が増えると比例して処理負荷も増えるので、スプライトは320x120と、画面を2分割する大きなフレームバッファを持った。

 

表示のタイミングはCore1側で行っている。圧縮データの展開に掛かった時間を測っておき、1/30秒を待つタイミング分をdelayしている。

しかしここで困った問題が!

 

delayはms単位しか指定出来ない関数なので、ms単位はdelayで、それ以下の待ち時間はdelayMicrosecondsという関数を用いた。ここに…どうしても誤差が入る(T-T)

 

例えば1枚の映像につき1ms(1秒の1000分の1の時間)の誤差があると、6566枚を表示し終える頃には6秒もずれてしまうのだ!これでは音楽を載せる事は出来ない(T-T) 最後の状態で誤差を0.2秒くらいに抑えるためには、1枚の絵での誤差を0.075msくらいに抑えないといけない。これが難しい。

 

タイマー割り込みがあるのかないのか分からなかったので、今は感覚値であわせる事をしてみた。将来的に音楽を入れるようになったらタイミング取るための割り込みあるかな…汗

 

心配していたSDカードの読み込みの遅さも、調整していく流れで表示に追いつかれなくなった!バッファサイズを思い切って2MBにしているが、実験してみた感じでは100KB以下でも大丈夫そうだ。

f:id:PocketGriffon:20210914185639j:plain

M5Stack実機の画面で見ると白は真っ白に見えてるんだけど、動画で見るとなぜか縦線が入ってしまっている…。カメラの関係??こういうのを上手に撮れるようになりたい(T-T)

 

あとは音楽かー……音楽。

どうやって鳴らすのかも分かってないけれども、PCMが使えるのならば画像データの合間にインターリーブで突っ込んくしかなさそうな感じも…汗

 

とりあえず音は保留で!やってみたい気持ちはあるけれども(^^;;

 

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

M5Stackでプログラム その7

M5Stackを手に入れて以来、主に移植ではあるけれどいろんなエミュレータを動かしてきた。

エミュレータが好きというよりは、作ったものはエミュレータが圧倒的に多いというだけの話なんだけど(^^;;

 

CP/M-86エミュレータ

作者様がいることなので、ちゃんと書いておこうと思うが、今回移植したプログラムは、V20-MBCというワンボードマイコンエミュレータとなっている。

f:id:PocketGriffon:20210913155115j:plain

ある時、キットの状態で手に入れて、長い期間ドハマリした(^^)

ここのブログでもV20-MBCで検索するとたくさん記事が出てくるはずだ。

V20-MBC の検索結果 - レトロパソコンであそぼう!

去年のちょうど今ころ、持病を悪化させて4週間ほど入院したのをきっかけに、V20-MBCから離れてしまった。

 

このV20-MBCMS-DOSを移植してみようと考えつつ、テストを簡単にするためにV20-MBC自体のエミュレータを開発していた。これも途中で開発が止まってしまっている…汗

今回は、この時開発をしていたV20-MBCエミュレータのソースをM5Stackに移植した!

 

なんとなくだけど、M5Stackで負荷の高いプログラムを動かしてみたかった!

そのためには(手元にある)8ビットマシンのエミュレータでは荷が軽く、16ビットマシンのおでましとなったワケだ!(^^)

さすがにV20(8086)ならばパワー不足で困っちゃうんだろう!

速度が遅くなるサマを見てやるぜ(^-^)

 

別の話として、手元に高性能8ビットマシンのエミュレータ、16ビットマシンも含めて作り置きをしておこう…と思った(^-^;;

 

性能評価

まずはいきなり結果から(^-^)

時間がかかる処理って何があるんだろう…と思ってディスクの中を探ってみたら、ちょうどよいベンチマーク的なマンデルブロ集合があった。

f:id:PocketGriffon:20210913161744j:plain

文字が小さくて申し訳ないが、30行目のコメントに「2分43秒」と書かれている。

これがV20-MBCで実行した時間だ。

ネットで調べてみたら、ベンチマークを掲載してくれてるページがあった!

Retro PC Gallery

 

さっそく移植したエミュレータでも実行をしてみたところ、結果は2分06秒となった!

あれ??V20-MBC実機よりも速いじゃん!(-_-;;

実際にM5Stack上で使ってみると、ホントにV20で動いてるCP/M-86な感じがする。なにかするとぐっと待たされる感覚が当時を思い出していいね!

 

f:id:PocketGriffon:20210913163459j:plain

元々のV20-MBCパッケージに含まれていたプログラムは、あらかた動いたような記憶があるけれど、一部結果が違うアプリもありV20エミュレータ自体の信頼性がイマイチだ(^^;; 特にコンパイラ系はダメかも。

 

f:id:PocketGriffon:20210913163611j:plain

デバッガであるDDT86もちゃんと動く。写真は撮り忘れてしまったけど、トレース機能もちゃんと動く。

 

CP/M-86エミュレータの移植

今回移植に使ったプログラムは、MacOSX上で動いていたコンソール上で動くモノだ。コンソール用という事でMacOSXに依存している部分は無く、ソースは無変更でLinuxでも、おそらくWindowsCygwinとかWindows Subsystemでも動くはずだ。

 

移植したCP/M-86の内部構造は、CP/M80とほぼ同じになっている。

画面制御部分などはソースが共通だ(^^;

CPUがZ80からV20(8088)に変わったくらい??

f:id:PocketGriffon:20210913164153j:plain

まずはシリアルを端末として見立てた状態でCP/M-86を起動させた。この方法でデバッグを十分に済ませたのちに画面表示系を作った。CP/M80と構造が同じということで、簡単に動くと思っていたのだが、ちょっとハマってしまった…。

 

CP/M86で扱うディスクサイズが大きくなった事から、一気にメモリに読み込んでおく事が困難になった。そのため、最低限の情報のみメモリに読み込んでおき、状況に応じてこまめに読んでいく手法を取った。

 

そしたら…SDカードを読みに行くタイミングでいくつかの問題が起きた。全然意識していなかったが、SDカードとLCD更新がバッティングするっぽい。そうなの??

この辺りで問題が起きたが、なんとか安定して運用が出来るようになった。

 

f:id:PocketGriffon:20210913170127j:plain

キーボードを繋げて操作していると、とても懐かしい感覚になる!

こんな小さな16ビットマシンを操作できるなんて…とピュアに思ったが、目の前にあるM5Stackは32ビットマシンだった(^^;;

 

重たい処理でひーひー言わせちゃうぜ!と思ったが、ベタ移植しただけで実機の速度を上回ってしまった。やっぱり速いなM5Stack!

でも実を言えば、今以上の高速化を出来る要素が何も無い。8088という事でメモリ空間は1024KBに広がった。そのサイズは内部RAMには入り切らないため、PSRAMへ逃さざるを得なかった。

 

これは…ちょっとジレンマかも。規模が小さいといろんな工夫が出来て楽しいけれど役不足感、規模が大きくなると工夫できる余地がほとんど残されない(^^;; ぐぬぬ…どっちが楽しいんだコレは!(もっと素直に楽しめw)

 

CP/M-86を使った感覚はCP/M80とそっくり。速度も大して変わらない。

となると、CP/M-86じゃなくても…という感覚に襲われる(^^;;

今回は(も)CP/M-86が移植できた…という自己満足で終わってしまった!(T-T)

 

さて、ここ2週間ほどM5Stackを集中して使っていたが、一旦離れようと思う。

とは言ってもM5Stackを使わなくなるわけではない。ほとんどの事をコンソールで済ませる私が、これほどまで画面に出力するのを楽しめたことは珍しい(^^)

この先も画面出力が必要なプログラムでは、積極的に使っていくと思う!

 

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

M5Stackでプログラム その6

M5Stackでのプログラミングを楽しんでいる!!

今回は、ここ1〜2日で取り組んだことを記してみる。

 

MZ-80Bエミュレータ

f:id:PocketGriffon:20210912114147j:plain

これは気合を入れて開発したものでも無かったので「自分で開発したエミュレータ」からの候補から外していたんだけど、画像ピクセル数が320x200とM5Stackのサイズとぴったりだったため、どうしても絵面を見たくなって移植した!

 

このMZ-80Bエミュレータを開発した当時の記録が残っていたので、一部分を引用してみたい。人に見せるために書いていた記録だったので、なんとなくブログの書き方に似てる(^^;

 

■2017.11.13
○○○さんと△△△(私)の共通の知り合いに、「ぱっくまん」さんという方がいる。お会いするタイミングで、過去に氏が発表していたゲームを動かしてみよう!的な流れとなり、まずはMZ-80Bのエミュレータを作る必要があるねって事になった。

 

話し合いの結果、オールマシン語の「肉シャツのxxx」というゲームを動かしてみる事に!
私はMZ-80Bのユーザーでは無いのでIPLなどの権利モノは使わないように動かす必要がありそう。

昨晩から今日の朝に掛けて、ダンプリストをOCRした!まだ修正は出来ていないけれど、バイナリの体裁を整えてコンバート出来るようにまで持ってった。あとはチェックサム合わせるだけなので、そんなに苦労はしないはず。
今日の晩には正確なバイナリが出来上がるといいなぁ。ちなみにサイズは約7KB。

エミュレータを作る上で、グラフィックVRAMアドレスは決め打ち、TEXT-VRAMも決め打ち、I/Oは最低限(キー入力だけ?)、これだけでMZ-80B動くかな…。

 

■2017.11.14
朝から「肉シャツ」のダンプリストのチェックサム合わせ!ブロックによって正解率が高かったり低かったりするのはいつもの事だけど、今回は8とBの間違いよりも5と3とか、とんでもないものが違っていたりして予測が難しい…。
眠い目ではBと8の区別が着かない!!

午前中のうちに正確なバイナリが手に入った!
さて、これからMZ-80Bエミュレータならぬ、肉シャツエミュレータを作っていきます!

 

で!最初からつまづいた!何かのルーチン呼んでる!!MZ-80Bって何かROMとか積んでるんだっけ?それともBASIC起動後??今は面倒なので後回しにする事に決めて、中身をC9[RET]にしまくる!まずはグラフィック画面にデータが出ることを確認したい!

 

VRAMのバンク構成は$D000からがテキスト、$E000からがグラフィックになっているようだ。面倒なのでバンク切り替え機構は作らない!VRAMメモリは直出し状態!(^^;
しばらく動かしていると、ループ(おそらくキー入力待ち)に入った。
GVRAMのデータを見てみると、なんだかちょっとだけアクセスがあったっぽい!
よーし、これでグラフィックを表示してみる!

 

VRAMの情報を元に画面へ表示してみる…と、あれれ?なんかビット情報が逆??
調べてみると、どうやらドットのMSBが逆っぽい。PC-8801FM-7とは違うのね…。

問題なくグラフィック画面が表示されてきたので、今度はテキスト画面だ!
PC-8801よろしく、MZ-80Bもテキストとグラフィックが合成されて表示される。

 

でもその前に、あの不明なルーチンを解決せねばならない。
調べてみると、どうやらSP-1520というモニタ?がロードされるっぽい。
これが、いわゆるMZ-80Bのモニタ??
工学社の「MZ-80B活用研究」にエントリアドレスが載ってたので、そこから機能を推測。
文字列表示ルーチンは良いんだけど、画面座標はどこで指定しているのさ…とか、重要な情報が無いので、ゲームの逆アセンブラを見ながら最低限の解析を行う。

 

なるほど、とあるメモリに先に情報を入れておいて、この関数を呼び出すのね。
バイナリもソースもないので、想像でルーチンを(Z80で)組んでいく。

1文字出力については、画面消去と1文字表示の機能を持っているらしい。
1文字表示については、メモリに入っている座標情報を更新していく必要があった。
これらを対応してみたところ、画面がちゃんと表示されるようになってきた。
こういうのは逆アセンブラを見ながらひとつずつ対応していくしか無いなー。

 

モニタROMルーチンを4つほど自前で用意したところで、ゲームが動くようになってきた。
意外に簡単に起動してしまいました、肉シャツ。

 

■2017.11.15
無事、MZ-80Bエミュレータをお披露目することが出来た!
これは一瞬だけ見せることが出来れば良かったので、もう心残りは無いw

 

という感じだった。ホントに一瞬のためだけに開発されたMZ-80Bエミュレータ(^^;

f:id:PocketGriffon:20210912122555j:plainf:id:PocketGriffon:20210912122612j:plain

このDot by Dotの画面を見たいがためだけにM5Stackに移植w

うん、ラインが映えるね!

 

twitterで公開したところ「グリーンじゃないの?」という話をいただいた。

言われてみれば!!!!ということで…

f:id:PocketGriffon:20210912122730j:plainf:id:PocketGriffon:20210912122747j:plain

グリーンモニタっぽくした!

毎回モザイクを掛けるのが面倒だったので、ゲームのバイナリにパッチを当てたw

オリジナルのバイナリを改造するのは忍びなかったので、M5Stackのメモリに読み込んだ後、実行前にパッチを当てている。著作物でもあるので扱いは丁寧に(^^)

 

PC-8801アルフォス高速化

最初の頃に移植したアルフォス on PC-8801、プログラム的な工夫も少なく実行速度が実機よりも遅い感じだった。別にゲームで遊ぶわけじゃないんだからいいやん…と思ったが、デュアルCPUのFM-7がそれっぽく動き、PC-8001に至っては余裕をかましてる状態だったので、PC-8801もちゃんとせねばなるまい…。

f:id:PocketGriffon:20210912124802j:plain

このアルフォスの遅い理由は、全てのメモリをPSRAM領域に載せている事だと思われる。RAMもROMも、VRAMですらPSRAMに載せている。この当時はメモリの速度も理解していなかったので仕方ない…。

 

ただ…ここでひとつ問題がある。PC-8001FM-7に比べ、PC-8801はメモリアクセスが実に複雑なのだ(T-T) 複数のバンク切り替えに加え、テキストウィンドウという面倒な機構もある。特にバンク切り替えは「こっちを切り替えたとしても、こっちの機能が優先」とか、テクニカルマニュアルを見てもぱっと分からないモノもある。とにかくメモリアクセスをシンプルに実現する事が大事だ。

 

というわけで、メインメモリ64KBとVRAM48KBを内部メモリに置く事にした!ただでさえ複雑なメモリアクセスのプログラムに手を入れる事になったため、作業は想像以上に大変だった(T-T)

 

CPUがハングアップするとシリアル側にexceptionが表示されるんだけど、この表示されてるメモリアドレスがどこなのかを知る方法はないんだろうか…(-_-; せめてmapファイルがないと見当が付かない…。また調べることが増えてしまった(^-^)

 

アルフォス実行中はROMプログラムをアクセスする事はないので、BASIC-ROMは従来通りのPSRAMに置いたままにした。

そしたら…これだけの変更で、CPUエミュレーション速度が3割以上も速くなった!いや、もっとかも? ノーウェイトで動かすと、画面更新が追いつかずにコマ落ちした状態になる(^^;

 

結局、1/60秒単位で動かしているCPUエミュレーションにウェイトを入れる事になった。1000ms / 60 = 16.666....msのうち、7msほどウェイトを入れた。

やっぱ速いよ、M5Stack!!(^^)

 

スクリーンショットが撮りたい!

いつもM5Stackの画面写真を撮影する際に、どうしてもカメラ(iPhone)が写り込んでしまうのが気になっていた!スクリーンショットが撮れればなぁ…とふと頭をよぎったのが運の尽き(^^; じゃあ作ってみようという気になった。

 

このブログを書いてる最中に、LovyanGFXにreadRectというドットデータ読み出し関数がある事を知ったw 今回作ったスクリーンショットは、この機能を使っていない(T-T)

 

画像を表示する際に生成するデータを横取りする形でスクリーンショットを作った。出力する先はSDカード、画像フォーマットはbmpとした。普通にbmpファイルを作ろうとすると上下が逆転するので、データ生成時に下から作っている。

 

アルフォス専用のスクリーンショットなので、サイズは320x200ドット、ファイルサイズは約125KB。このデータをSDカードに書き込むのに掛かる時間は2秒以下だった。

f:id:PocketGriffon:20210912132310j:plain

f:id:PocketGriffon:20210912132327j:plain

f:id:PocketGriffon:20210912132351j:plain

ちょっと色がギトギトしてるので、明度を半分にしても良いかもね…。

 

上にも書いた通り、今の時点ではアルフォス専用になっちゃってるので汎用プログラムを作りたいかな……。たまにはM5Stack業界に貢献しないと(^^;;

 

もっと無茶するところが見てみたい!

M5Stackを使い慣れてくると、今まで「これは無理かも?」と思っていたことが、実は割とたやすく実現できる事が分かってきた。そりゃ240MHz駆動のデュアルCPUならば、出来ることは多いはずだ。

 

もっとM5Stackがひーひー言いそうな事をやってみたいなぁ…という気になってきたw でもそういうプログラムを過去に作ったことがないんだよね。PC-9801エミュレータとか無茶そうで面白いけど、GDCエミュレータとか書く気がしないし(^^;;

 

以前作っていたCP/M-86エミュレータでも移植してみようかしらん…汗

 

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

M5Stackでプログラム その5

M5Stackで動くプログラム、なんとなく番外編!(^-^)

チャレンジというほどのモノでもないし単なる自作プログラムの移植だし。

f:id:PocketGriffon:20210910231600j:plain

 

というわけで、今回はCP/M80を動かしてみた!

最初の画像にスタートレックを持ってくる辺り、あざとさが透けて見えて良い(^-^)

 

このCP/M80エミュレータは、過去にLinux用として開発してあったモノだ。

Z80エミュレータをスクラッチから作り始め、仮想的な(しかもCP/M80を動かすのにある程度理想的な)マシンを実装したのちにCP/M80を移植した。

 

エスケープシーケンスは端末の機能に頼らず、内部で処理を入れている。例え端末側でサポートしていないシーケンスが来ても対応が可能となっている。その分、コーディングは面倒だったけど!(^^;;

 

CP/Mディスクシステムは、Linuxから見ると1つのファイルだが、CP/M80からは1つのディスクとして見える。まぁエミュレータによくあるアレだ。

f:id:PocketGriffon:20210910233641j:plain

 

今回は、この自作エミュレータをM5Stackに移植してみた。

移植と言っても……難しいところは特に無く(^^;

元はcursesライブラリを用いていたので、その部分(表示に関するところ)をM5Stack用に作り直しただけで対応が出来てしまった。

いつも思うのだがANSI準拠で書かれたコードはM5Stackへの移植が簡単だ。

 

これで終わってしまうのもアレなので、もう少しだけ工夫したところをご紹介してみたい!

ブログの尺も大切だww

 

80x24の画面表示

CP/M80のプログラムは画面の大きさが横80桁縦24行ある事を、ある程度期待して作られているモノがそれなりにある。

このブログ内でもPC-1600KにCP/M80を移植する話をしているが、この時にも画面サイズを結構気にしていた(未完成ですが…すみません…orz)。

 

横320ドットで80桁…というのは、ちょっと前までは現実的ではないと思っていた。しかしM5Stackのようにカラー表示が出来るLCDの場合は、中間色というか微妙な色変化を付けられるおかげが、機械的に横幅を半分にしてもなんとなく読めるフォントになる。

f:id:PocketGriffon:20210910234514j:plain

↑ほら、読めるよね!?

 

さすがにこれだと厳しい……場合しかないので、横方向に2倍した表示も用意した。

f:id:PocketGriffon:20210910234724j:plain

横方向に2倍というよりは、これが標準だ!

そして見えなくなってしまった右側40文字分を見たい時は、画面下にある3つのタッチボタンの右を押すと右側が見える。左に押せば元に戻る。

好きなタイミングでサイズや見える場所を変える事が出来るのは、意外に便利だ!

 

これは元々のプログラムに、仮想スクリーン(80x24の領域を持つ)の仕組みがあったのが功を奏した。コレを応用したおかげで80桁表示が実現できた。元の仕組みが文字列をスクロールで流してしまう構造になっていたら、おそらく面倒で対応しなかったと思う(^^;;

f:id:PocketGriffon:20210910235401j:plainf:id:PocketGriffon:20210910235342j:plain

任意のタイミングで拡大させる事が出来るので、ROGUEで遊んでる最中だってご覧の通り!

これでゲームに熱中できるってモンです!(ホントか?)

 

ディスク

ディスクに関しては、最初はSDカード上にディスクイメージを置いておき、アクセスがあるたびにSDカードを読みに行っていた。

…が……大きなプログラムを起動したりすると結構遅い(^^;;

 

運用としては、読むことがほぼ全てで書き込むことは無さそうなので、起動時に一気にメモリに読み込むことにした!Core2は豊富なPSRAMがあるので、ここにディスク全体を読み込んでいる! It's無茶!

 

読み込みは比較にならないほど速くなったが、書き戻しをしていないのでセーブしたデータはもれなく消滅する(^^;  書き込みと言っても小さなセクタのやりとりだけなので、余裕とやる気があったらディスクへの書き込みも入れてみたい。

 

キーボード

CP/M80の運用でキーボードが無いってのはどーかと思うので、手に入れたカード型のキーボードに対応した。むしろコレがなかったらCP/M80を動かそうとは思わない(^^;;

f:id:PocketGriffon:20210911001222j:plain

このキーボードを使い始めた頃は「いや無理でしょコレは」と思っていたが、何日か使っていると不思議と慣れてきた(^^; 

 

キャピタライズした文字を打ち込みたいCP/M80に対して、このキーボードはCAPSロックが出来ない(出来ないよね?)ので、入力された文字を大文字小文字を反転させた。

小文字が入力されたら大文字へ、大文字が入力されたら小文字になるように変換している。

 

終わりに

f:id:PocketGriffon:20210911002027j:plain

あくまでも「CP/M80が動いたよ」的な実験ではあったけれども、意外にもしっかりと動いてる。人に見せて驚かせるには十分だと思う(^-^)

 

f:id:PocketGriffon:20210911002048j:plainf:id:PocketGriffon:20210911002117j:plain

これで往年のゲームを楽しんでみるのも良いし、簡単なアセンブラコンパイラを動かせる端末して使っても良いかもね!

 

とりあえず満足した!!(^-^;;

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