SHARP PC-1600KでLCDを直接制御して描画!

先日「Bad Apple!!リベンジ版」を投稿した。

 

ポケコンの画面でBad Apple!!がリアルタイムで動くというのは結構な驚きだったようだ(^^) メモリの方はズルしちゃった感が強いけれども!!

 

そんな中、「PC-1600KでLCDCへのアクセス方法を知りたい」というお声があった。そういえば過去に調べてみたけど資料があんまりなく、独自でROMを解析したんだった。

ネットでも見たことが無かったので、資料として残そうというのが今回のブログ(^^)

私としては珍しくガチンコ技術ブログw

 

f:id:PocketGriffon:20210417121610j:plain

とりあえずテスト用の表示データを用意した。昔懐かしいフォントだ(^^;

Bad Apple!!での描画方法

当初、Bad Apple!!で画像データを表示する際、IOCSのサービス(LOADLCD:0160h)を利用していた。

呼び出し方としてはこんな感じ。

    LD  A,#ライン(0 - 3)

    LD  DE,#データが格納されたアドレス

    CALL 0160h

これで1行(縦8ドット)のグラフィックデータが表示される。

これを4回繰り返す事で画面全体が描画される仕組みだ。

 

このIOCSをコールすると、横のドットは無条件に画面全体(156ドット)を描画してしまう。Bad Apple!!では横64ドットしかデータがないけれども、残りの92ドットも表示されちゃうのだ!いくらなんでもコレはもったいない!ということで、直接LCDCをコントロール出来ないか…という理由でROMを解析した。

 

その時に調べてみたところ、どうやら左から64ドット単位で処理しているらしい…という事が分かった。64+64+28ドットという感じで3つの処理を行う。

Bad Apple!!では64ドットのみ表示されれば良いので、じゃあということで画面中央に表示していた画像を左側に寄せて、64ドットの処理1回で表示出来るようにして解決した。

 

その後、PC-E500系のLCD描画を調べている時に「PC-E500活用研究(工学社)」を見てみたら、とても見覚えのある数値が出てきて、あれ??これってPC-1600Kと同じなのでは…となった。実際に調べてみたところ、まるっきり同じだった!(^^;; なんてこったぃ!

というわけで、今回はPC-E500の資料も活用していきたい。

 

PC-E500系のLCDコントローラ

PC-E500系のポケコンでは液晶の表示にHITACHI HD61202というチップが使われている。

f:id:PocketGriffon:20210417123404j:plain

たまたま分解したままのPC-E550が手元にあったので、写真をパチリ(たまたま?)

ここまでわかれば、あとはネットでデータシートを探せば良い。

Hitachi HD61202 Datasheet

英語に抵抗ある場合は、工学社から発売されていたPC-E500活用研究という書籍の208ページに、かいつまんだ情報が載っているので、そちらを参照してもらうのが良いと思う。

f:id:PocketGriffon:20210417123844j:plain

気になって調べてみたら「PC-E500/PC-1480U活用研究」でも「PC-E550/PC-1490UII活用研究」でも「PC-E650/PC-U6000活用研究」でも208ページだったw 中身ほぼ一緒!この活用研究、3冊ホントに必要だったのかな…汗

 

ここに書かれている「アクセス・アドレス」はPC-E500用なので、PC-1600K用に置き換える必要がある。コントローラ1は54h、コントローラ2は58hだ。

注意したいのは、XアドレスYアドレスという呼び方。画面のXYドットなどとは違い、あくまでもLCDコントローラでの呼称だ。しかもなんとなくXとYが逆なので頭を切り替える必要がある。私はこの手の資料を見ずに解析していたので意識していなかったが、資料を見てからの方がこんがらがった(^^;;

f:id:PocketGriffon:20210417125021j:plain

コントローラ1のX=0〜3が画面左の64ドットだ。1バイト8ドット構成なので、0=0..7ドット、1=8..15ドット、2=16..23ドット、3=24..31ドット。

X=4以降は画面右の28ドットをアクセスする際に使う。ちょっと分かりづらい。

 

アクセスの手順としては以下な感じ。

    Xアドレスを設定

    Yアドレスを設定

    表示データを出力

LCDコントローラへアクセスする際には、LCDが処理中かどうかを判定する必要がある。処理中に書き込みを行った場合は、そのデータは無視されるようだ。

これを素直にプログラムするとこんな感じ。

f:id:PocketGriffon:20210417130115j:plain

実際のデータ出力は「outi」という命令で行っている。

今気がついたが、私はLCDコントローラを0と1で管理していた。LCDC1となっているところはコントローラ2として読んで欲しい(紛らわしい…)

このプログラムで画面左側に64x32ドットの画像データが表示される。実際にBad Apple!!で使っているプログラムそのままだ。データのアドレスは$xx00にアライメントされてる必要がある。

 

このLCDコントローラは縦方向へのスクロール機能がある。「表示開始ライン」というデータを設定してやる事でドット単位にスクロール出来るらしい。今回のBad Apple!!では使っていない。むしろBASIC側でこの機能を使っているので、辻褄を合わせてやらないといけない。F05Chというワークは現在のスクロール値を保存している。ここを参照してXアドレスの値を調整している。

 

中央の64ドットを表示するためにはLCDコントローラ1をアクセスするが、プログラムはほぼ一緒だ。

そして右側28ドットはLCDコントローラ2のXアドレスを4〜7に設定してやれば良い。

 

速度比較!

やっぱり作ったものの速度比較は欠かせないと思う!(^-^)

プログラムの最適化、高速化はプログラムしている上でとても楽しい!

画面全体を1000回表示した時の速度を表示してみることにした。カウンタは1/64秒に1ずつ数字があがっていくので、表示された数値を64で割れば秒数が出る。

 

まず、IOCSで表示した場合の速度を測ってみた。

f:id:PocketGriffon:20210417132043j:plain

表示されてるのは10進数だ(^^;;

1000回表示するのに1988と出たので掛かった処理は31.0625秒、秒間31.62回表示出来た。

秒間30回と言えば遅くはないけども…って事になるが、秒間30回の書き換えをしたかったBad Apple!!では表示だけでこれだけ処理が掛かるのは、やはりアウトだった(^^;;

IOCS = 1988 [31.0625秒:31.62回/秒]

 

それでは直接LCDコントローラを制御して表示する方法の速度を測ってみよう。

f:id:PocketGriffon:20210417132727j:plain

おお!どどーんと速くなった!時間は19.78125秒、秒間50.55回の表示が出来るようになった。IOCSに比べて倍とは言わないけれども約7割弱の高速化。

実際にゲームなどに使う場合は、画面全体でなくて2/3くらいをゲーム画面にしたらもう少し快適化できそう!

直アクセス = 1266[19.78125秒:50.55回/秒]

 

さらなる高速化は可能?

さて…ブログとしてはここで終わってしまっても良いかなーと思ったんだけど、どーしても気になる事があったので追加で実験してみた!(^^;;

プログラマたるもの、疑問を残してはいかんのだ!(変なフラグ立てたらダメ)

 

もう一度、PC-E500活用研究の表を見てみよう。

f:id:PocketGriffon:20210417133420j:plain

一番右側に「同時アクセス」という項目がある。同時アクセス…気になるよね!(^^;

これはおそらく画面クリアなどを高速に行うためにあるモードなんだと思う。00で埋めるとかFFで埋めるとか、同じデータを両コントローラへ書き込む時に使ったら便利!

 

これと……さっきのプログラムでLCDコントローラがBUSYの間待つってコード……気にならない?? データを書き込むと、次のデータを書き込めるようになるまで、だいたい40サイクルほど待たねばならないようだ。1ループに40サイクル…ちょっと無駄に思える。

LCDコントローラが2つあるのだったら、交互に書き込んでやったらどうなるんだろ??

 

しかしデータを書き込むためのレジスタロードなどに時間がかかってしまったら本末転倒。プログラムは結構複雑になる??そんな風に思っていたが…ピンと来るものがあった!

制御すべきLCDコントローラは2つ、そしてZ80も裏と表のレジスタが2セット!

おお、これでプログラムの方針は決まった!(^^)

 

以下、作ってみたプログラム。

表と裏のレジスタが頻繁に入れ替わるので相当こんがらがるw

f:id:PocketGriffon:20210417142158j:plain
XYアドレスへ出力するのは2つのコントローラへ同時アクセスしている。

Yアドレス出力後にBUSY信号をチェックせねばXアドレス出力がうまくいかなかった。

 

そしてデータの出力はnopを並べる事でBUSY信号のチェックをパスした。手元にあるPC-1600Kではちゃんと動いたが、マシンごとの個体差が無いとは限らないのでギリギリの設計はダメ。ギリギリを見定めた上で、nopをもう1つずつ入れると良いかも知れない(^-^)

 

このプログラムで左64ドットと中央64ドットは描画出来るが、右側の28ドットは表示されない。そこは前に使っていたプログラムをそのまま呼び出す事にした。

デバッグをしてちゃんと動くようになったところで、お楽しみの速度を測ってみよう!

 

f:id:PocketGriffon:20210417142826j:plain

!!!!すごい!倍以上速くなった!!(^O^)

時間は9.71875秒、秒間102.89回の表示が出来るようになった。IOCSに比べたら3倍以上の高速化となった。

LCDC交互アクセス = 622[9.1875秒:102.89回/秒]

 

正直言えば、ここまで速くなるとは思っていなかった。おそらくLCDC同時&交互アクセスなどはPC-E500シリーズでは定石的なテクニックなんだろうけれども、今回改めてやってみた事で優位性は証明できた気がする(^^)

あ、いや待て。Z80は裏レジスタがあるからここまで高速化出来たワケなので、PC-E500などではあんまり有用ではないのかも??うーむ、調べたくなってきてしまう…滝汗

 

いろんな思いを残しつつ、今回はここまで!(^^;

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

PC-1600KでBad Apple!! リベンジ編

今年の2月にPC-1600KでBad Apple!!を表示するプログラムを作った。

 「せっかくPC-1600Kに32KBの増設メモリを2つ取り付けているのに、それを有効活用出来ていないなぁ…」と思ったので、メモリを使い切る事を目的とした実験だった。当初の目的は達成出来たのだが、画像データを強めに圧縮したため表示速度が出ないという残念な結果に終わっていた。

 

その後、表示を高速化をするブログを書いている。データ構造を変える事はせず、ソフトウェア側でどこまで高速化が出来るかという、これまた実験だった。
その結果、やはり不満が残る結果に…。

 

 

速度が出ていない事もそうなんだけど、一番気になっていたのはBad Apple!!が最後まで見られないのだ。
Bad Apple!!は約219秒のアニメーションで、秒間30枚の絵で出来ており総数は6566枚ある。

 

PC-1600Kという限られたメモリ容量しかないマシンで、この枚数すべてをオンメモリに載せるなんて不可能!(T-T)

 

それでも頑張ってデータを圧縮して、前回の実験では1086枚の絵をメモリに載せていた。
64KBに1086枚入ってるのを多いと思うか、少ないと思うかは人によって差があると思うけど、自分的にはそれなりに入っていたと思ってる(^^)

 

単純計算をすれば、384KBのメモリがあれば全てのデータを入れられるかも知れない。
データは入るかも知れないけど、速度はあのままだ。
どうしたらPC-1600Kで1/30秒の表示をしつつBad Apple!!を完璧に再生できるんだろうか…。
メモリが……メモリが欲しい!!!


増設メモリを作ってしまえ!!

そんな切実な思いを伝えたかどうかは覚えてないが、何ヶ月か前からハードが得意な知人に「PC-1600Kの増設メモリって作れない?」というお声がけをしていた。お声がけというか、本体と増設メモリと資料をセットにして押し付けたww

 

その知人からプロトタイプが出来上がったと連絡があり、先日そのメモリを受け取った。
これがそのメモリだ!!本邦初公開!!

f:id:PocketGriffon:20210416004047j:plain

f:id:PocketGriffon:20210416004111j:plain

容量は1MB、つまり1024KBもある。
ポケコンに1MBという容量が必要なのか…と、さすがの私も思うw
メモリモジュールにはCE-1600M同様にバッテリーでのバックアップ機能がある。一度書き込んだデータは意図的に消さない限りは残っていてくれる。

 

f:id:PocketGriffon:20210416004234j:plain

こんな感じにS2スロットに取り付けて使う。

 

知人曰く「しまったー!本体に取り付けたまま電池の交換が出来ない!」と言ってたので、もしかしたら改善されるのかも知れない(されないのかも知れないw)。

 

勘違いされるとイケナイので書いておくと、メインメモリとして拡張されるサイズはCE-1600Mと変わらず最大で32KBだ。それ以外のメモリは基本的にRAMファイルとして使う。

 

PC-1600Kは元々256KBまでのメモリならば標準のROMでフォーマット(INIT)出来る。それを超える場合には独自でフォーマットプログラムを作らねばならない。

知人にハードを作ってくれとお願いした手前、このプログラムは私が書いた。

f:id:PocketGriffon:20210416004654j:plain

DSKF "S2:"すると、冗談のような数字が表示される!

 

Bad Apple!!の再検討!

大容量メモリは手に入った!これでようやくBad Apple!!のリベンジができそうだ。

どうせイチからすべて作り直すことになるんだから、データフォーマットも都合の良い形式に変えてしまおう。目指すべきは「高速表示」だ。この目的のためにメモリを使う!

 

まず、無圧縮ですべてのデータが入るかを検討してみた。

PC-1600Kでの表示は64x32ドットにしよう…と前回の実験で決めていた。これはPC-1600Kでは程よいサイズという事もあるが、このマシンが高速に描画するのに都合が良いサイズでもあるのだ。今回もこのサイズは崩さないようにする。

 

1バイトが8ドット構成のマシンなので、データサイズとしては1枚の絵(64x32ドット)で256バイト。絵は6566枚あるので単純計算だと1.6MBの容量が必要になる。1MBでも収まらないなんて……Bad Apple!!恐るべし!!(^^;;

 

この手の画像データはランレングス圧縮すると圧縮率が良くなる事は分かっている。分かっているがドット単位の展開では処理時間が掛かるのは、前回の実験で証明されている。

 

今回はデータの最小単位をドットではなく、バイト単位でデータを小さくするアプローチにした。

 

256バイトのデータの中に、00とFFのどっちが多いかを調べる、それを基準の色としバッファをクリア。さらに基準の色が00だった場合はFFを、FFの場合は00がいくつあるのかを調べて、そのオフセット(バイトの位置)をデータとして並べる、最後に00でもFFでもないデータをオフセット+データとして並べる。

 

言ってる事が良くわからん…と思うけど、運が良ければデータは小さくなり、複雑な絵はむしろ大きくなるフォーマットだ。そこで元の256バイトよりも大きくなる場合には「無圧縮」という選択をいれた。最大で256バイト、基本はそれ以下というデータとなる。

このフォーマットの利点はデータの復元が高速な点だ。1/30秒での表示をするためには展開速度の高速化は優先度が高い。

 

この方式に基づいてデータを加工してみたところ、6566枚の画像データが約884KBに収まる事が分かった。ここでようやく付加データも含めて1024KBに収まりそうな目処がたった。

 

表示プログラムはアセンブラ化!

前回の実験では描画処理をC言語で書いていた。ドット単位で展開処理を書く必要があったため、プログラムがある程度複雑だったこと、出力されるアセンブラコードを見て「これ以上速くするのは簡単じゃない」というところまで突き詰める事が出来たため、それ以上触らなかった。

 

今回は前回以上のガチンコ勝負なので、最初からアセンブラで書く事を意識したデータ形式にした。おかげでプログラムをすっきり書くことが出来た。バッファのクリアなどはPUSHを並べるなどZ80っぽい高速化を楽しみながらのご実装をした(^^)

 

前回は省メモリ化のためデータの途中でバンクを跨ぐ事を許容したコードを書いていたが、今回はそこも廃止し、1つの絵を表示するデータはメモリバンクを跨がない保証をデータ側でした。おかげでメモリアクセスもすっきりし、非常に高速にアクセス出来るようになった。

 

巨大データをモジュールへ転送!

さて……おそらく今回一番の問題はココ!

さっき全部のデータで884KBと書いたが、この巨大なデータをどのようにしてメモリモジュールへ転送したら良いのか…。

 

PC-1600KはBLOAD命令でバイナリのデータも読み込むことが出来る。マシン語のデータなどはBLOADで読み込むようにしてて、とっても便利だ。

 

このBLOADで読み込めるバイナリデータにはバンク情報が含まれるのだが、実は今回のケースではこの情報だけでは足りないのである。

 

PC-1600Kのメモリバンクは、横方向へ伸びるバンクメモリと、それとは別に縦方向に伸びるバンクメモリが存在する。通常、PC-1600Kで「バンク」と言えば横方向を指していて、BLOADにはこの「横バンク」の情報が入っている。

 

今回のメモリモジュールは「縦方向」のバンク情報を操作する事でメモリアクセスをする仕組みだ。BLOADで対応出来ないのはそういった事情による。

 

f:id:PocketGriffon:20210416012815j:plain

無いものは作りゃいい!の精神で、縦方向のバンクにも対応したダウンローダーを作った!(^^; 以前、高速バイナリローダーを作ろうとした時に色々と調べてあったので、ワリとあっさり作ることが出来た。

 

RS-232C経由で専用のバイナリを送り込めば、自動的にバンクメモリに書き込んでくれる。

 横方向のバンクにも対応出来ているので、BLOADの代わりに使う事が出来る汎用ツールだ。

 

大雑把にはこんな↓感じでデータをダウンロードした。

 

6566枚のデータを圧縮、順番に並べて1バンクのサイズ(16384バイト)に収まるように1つのファイルとする。こうして並べていくと全部で56(1MBは64バンクある)のファイルになった。これらのファイルの先頭にバンク情報などを書き込んでやり、最終的には1つの巨大なファイルとした。

 

この巨大データを専用ダウンローダーでダウンロードしつつメモリへ書き込む。RS-232C経由ということもあるが、884KBのデータを転送しつつ書き込みつつ…をして約33分掛かった!

でも33分で面倒なデータを書いてくれるんだったら万々歳だ!

------

 

 

やっとPC-1600Kで満足が出来るBad Apple!!を作ることが出来た。

オリジナルとは白と黒が反転してるなど気になるところはあるけれども、次のチャンスがあったら修正したいと思う。次があるのかな?あるのかもねー汗

 

ちなみに今回使った1MBの増設メモリだが、あくまでもテスト版でありプロトタイプだ。

今後どのような展開になっていくのかは知人のみが知る…って感じだ!(^^;;

 

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

NEC PC-2001のご紹介!

最近「とある」作業に取り組んでいて、まだ公表できる段階にない。

ブログも久しぶりになってしまっているので、困った時の機種ご紹介!(^^;;

今後も唐突に機種紹介が来たらネタがないと思ってくれて構わない!(ToT)

 

f:id:PocketGriffon:20210413145344j:plain

PC-2001の思い出

おっさんの思い出話なんて聞いても仕方ないと思うけど、まぁ聞いてくれ(書くのかw)

私が最初にどっぷり使ったパソコンはPC-8001だった。たまたま友達の家にあったのを使わせてもらっていたのだ。所有者は友達の父親であり、友達ではない!もしかしたら所有者よりもPC-8001を使っていたかも知れないw

 

その所有者(まさに恩師)が晩年、「あんなにパソコンにハマらせてしまって…あの子の人生を変えちゃったんじゃないだろうか…」と心配されていたと聞いた。大丈夫、人生変わって良い方向へ行ったから!(^^)

 

私があまりにもPC-8001を使ってしまうので所有者があんまり触れなかったんだと思う。子供心に全く気がついてなかったが悪い事をした!(ホントに思ってる!)

その所有者が「ちょっと買い物行ってくる」と出ていったと思ったら、いきなりPC-2001を買ってきたのにはホントに驚いた。これが人生初のモバイルパソコンとの出会い。

 

PC-2001に搭載されているN20-BASICは、PC-8001のN-BASICとの親和性が高かった。キーボードに5つのファンクションキーなども備わっていた。ハンドヘルドなんだけどデスクトップパソコン使ってる感覚と似てて、とても自然に使うことが出来た。

一度、作ったゲームプログラムをプロテクト(LOCK)したと思いこんで、試しにNEWしてみるか…と思って実際にやって消してしまい、とても悲しい思いをした。いまだに覚えてるんで相当悔しかったんだろうw

 

恩師が他界した際、「ここに置いておいても仕方ないから…」とパソコン関連のものをいくつか形見として受け継いだ。PC-2001もあるかと思ったが残念ながら無かった。

 

何年か前、とある場所に行った時、段ボールの下にちょこんと置いてある茶色いケースを発見した。見た瞬間に「うわ、これPC-2001だよ」とつぶやいたところ周りからたいそう驚かれた!本体を見ずに機種を言い当てたのだからPC-2001を知らない人から見たらそりゃそうか(^-^;;

茶色のケースから本体を取り出すと、当時見たPC-2001と瓜二つ!(当たり前)

これも運命だろうと思い、そのPC-2001を手に入れる事にした!

まさに35年ぶりの再開!(^^)

 

手元にあるPC-2001

今、私の手元には3台のPC-2001がある。どれも動作品だ。

そのうちのひとつは箱に入ったままの逸品だ!

f:id:PocketGriffon:20210413160058p:plainf:id:PocketGriffon:20210413160153p:plain

他の2台には増設RAMカートリッジがついている。

f:id:PocketGriffon:20210413162313j:plainf:id:PocketGriffon:20210413162336j:plain

PRINT FRE(0)とした結果は14274と出た。

本体メモリ8KB+増設分8KBという構成だ。

 

そういえばPC-2001の増設メモリについて、あんまり写真が出回ってない気がする。

せっかくなのでこちらもご紹介!

f:id:PocketGriffon:20210413162703j:plain

PC-2001を横から見ると、こんな感じにとりつけられている。

裏からは↓こんな感じ。

f:id:PocketGriffon:20210413162811j:plain

オークションなどでPC-2001が出ていたら、まずは横と裏面を見るのが良いだろう(^^;

単体で見るとこんな感じ。

f:id:PocketGriffon:20210413163235j:plain

型番はPC-2006というらしい。これ1つで8KBが増設される。

PC-8201のようなメモリディスク機能はないので、純粋にメインメモリが増設されるだけだ。

f:id:PocketGriffon:20210413163733j:plain

中身はこんな感じ。

残念ながら追加でメモリを増設できそうなパターンは用意されていない(^^;;

 

そして中にバッテリーが入っているのだが、外部からは電池の存在を知る記述が一切ない。マニュアル無しで手に入れた人は電池の存在に気が付かず使ってる人が多いのではないだろうか…汗

運用は…おそらくPC-8201の増設メモリであるPC-8206と同じで、本体から引っこ抜く時にWR.PROTECTスイッチをONにし、抜→PC-2001→挿とした後にWR.PROTECTスイッチをOFFにするんだろうと思う。

 

ところで…

f:id:PocketGriffon:20210413164459j:plain

増設メモリにある↑このディップスイッチはどう設定するんだろうか…?

どなたか、マニュアルをお持ちの方がいたら教えて欲しい(T-T)

 

PC-2001のプログラミング事情

これだけPC-2001に惚れ込んでるといいつつ、積極的なプログラミングはしていない。

理由はいくつかある。

ひとつめはシリアルケーブルの問題だ。

PC-2001にはシリアル通信をするための端子が付いている。

f:id:PocketGriffon:20210413165540j:plain

左から2番めの端子がSIO、シリアル端子だ(表記はS I/Oとなっている)。

ここにケーブルを挿してホストマシンとのやり取りができるのだ!

レトロにはありがちだけど、やはりケーブルは手に入らないので自作するしか無い。

すでに該当するコネクタは手に入れてある!

f:id:PocketGriffon:20210413165718j:plainf:id:PocketGriffon:20210413165737j:plain

ちゃんと付けられる事は確認済み!

しかも!!!!

f:id:PocketGriffon:20210413165815j:plain

失敗した時のためにいくつか手に入れてある!(買いすぎ)

そしてケーブルを作る上で必須の端子詳細についても資料がある。

f:id:PocketGriffon:20210413170246j:plain

これだけお膳立てが揃っていれば作らないわけにはいかないだろう!!

 

……と言いつつも、全く食指が動かない。

それが2つめの理由だ。

PC-2001にはシリアルから受け取ったデータをプログラムメモリに保管する方法がない。BASICで「INPUT %1,A$」という感じで変数に受け取るしかないらしいのだ。

これだと外部で作ったプログラムを送り込めない(T-T)

せめて増設メモリがRAMディスクのように使えるようになっていれば、そのメモリディスクへASCIIセーブする方式が取れたのだが…。

他にも同じような事情のマシンがあり、それらはプログラミングの対象になりづらい(T-T)

 

ちなみに技術資料は頑張って集めてある。

f:id:PocketGriffon:20210413172337j:plain

まずおなじみ?のPC-2001プログラムライブラリ。さすが工学社!こういう機種用にも出してくれているのは本当に助かる(^-^)

ゲームプログラムが9本、他にビジネスで使えそうなプログラムやらがたくさんって構成。基本的にBASICで書かれているものばかりなので、技術資料というよりはプログラム集。唯一、ガギャラというゲームがキー入力系でマシン語を使っているだけ。

 

f:id:PocketGriffon:20210413173216j:plainf:id:PocketGriffon:20210413173240j:plain

ASCII 1983年8月号。

この本にPC-2001のテクニカルマニュアルが載っている。私が知る限り、この記事が最も詳しい技術資料かも知れない。CPUの構成からニーモニック、ハードウェア詳細、ROM内ルーチンの説明など、PC-2001のマシン語でプログラムするなら必須とも言える情報が満載だ。

これはぜひ手元に置いておいて欲しい(^^)

 

f:id:PocketGriffon:20210413174200j:plain

そしてこちらもおなじみ?のB-Number。

The BASICのバックナンバー合本なのでB-Numberという名前なんだと思われる(^^;

The BASICはワリとマニアックな事が書かれている本で、PC-2001でもモニタ、アセンブラ、逆アセンブラ、通信ソフトなど情報が載っている。プログラムを作られた方が内部構造の資料として書かれているので、技術資料とはちょっと違うんだろうけれども、少ない情報源なので大切にしたい(^^)

 

あとはマイコンBASICマガジンとかI/Oとかに載っていたプログラムだろうか。月刊誌は別の場所に保管してあるので写真はないけど、それなりにゲームなどのプログラム載っていた気がする(^-^)

 

今思ったけどCMT端子が生きていれば、そこを経由してプログラムのセーブロードが出来るかも…。JR-800で試していた方法(うまく行ってないけど)が出来れば、作れなくはないなぁ…うーん…(^^;;

そしてROMは20KB…

JR-800で手入力したROMも20KBだったなぁ…(遠い目

 

何か意味深な事を書きつつも今日のところはここまで!(^^;;

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

National JR-800 解析その1

BASICのROMをげっと!

先日から触り始めたJR-800。

もっと戯れてみたいけれども、シリアルでの通信もカセットインターフェースでのやりとりもうまくいかず、なかなか突破口の見えない状態が続いていた。

 

本体でその場限りのBASICを使っていても大した解析は出来ないよなぁ…と思う日が続く。

f:id:PocketGriffon:20210323231559j:plain

なにげにメモリダンププログラムをBASICで書いてみた。$8000以降はBASICのROMが入っている事が分かっているので、そこを表示させてみた感じだ。この時には気がついてなかったが、1バイトの上位4ビットが0に化けてたw

 

JR-800のHuBASICは、ちゃんとHEX$が装備されていてメモリダンプが作りやすい。唯一びっくりしたのが論理演算のANDが無い(^^; チェックサムの下位8ビットのみを残そうとして「SUM AND 255」とやったらError。さすがにANDが無いとは想像もしていなかったので、エラーの原因が分かるまで相当「うーん」ってなった!

 

試しに最初の数バイトだけを打ち込んでみる。

f:id:PocketGriffon:20210323232227j:plain

うんなるほど、こんな感じか。最初のアドレスは生成するプログラムをちゃちゃっと書いてやれば良いし、スペースもナシで大丈夫か…そこまで見づらくはない。

打ち込んでみると4バイト4バイト1バイトって感じで区切りもわかりやすい。

……出来るところまで打ち込んでみるか!!(^^;;;

f:id:PocketGriffon:20210323232855j:plain

JR-800のメモリマップはこんな感じ。

ROMは$8000〜$BFFFの16KBと、$F000〜$FFFFの4KB、合計20KBだ。

BASICのプログラムを改造して、7行表示してキー入力待ち、キーが入ったら次の7行を表示する…という単純なダンプを作った。それと合わせてパソコン側で打ち込んでいく。チェックサムは入力だけしておいて、あとで合わせるという魂胆だ。

ひたすら20KBをちまちまと打ち込む作業が始まった(^-^;

それからは何かちょっとでも手が空いた時間が出来ると、写経のごとく打ち込んでいく。これがZ80のダンプリストだったら「あ、ブロック転送してる」「ここでループしてるのか」とかバイナリから感じ取れる構造があるんだけど、これは6301。バイナリコードをまーったく暗記していないので、ひたすら16進文字を打ち込むだけの作業となる。

途中、ASCIIコードっぽい部分を打ち込む時にはちょっとだけ楽しかったがw

 

結局、トータル約8時間掛けて20KBを打ち込んだ!チェックサムの合わせにも約1時間くらい掛かった。もーやだ、ダンプ見たくないってところまで追い込まれた(^^;

 

解析のマネゴト

なにはともあれROMのバイナリコードが手に入った。これを逆アセンブルしてみるにする。

HC-88のスレーブCPUを制御するために必死に作った逆アセンブラがここでも生きる!

幸い、逆アセンブラはHC-88に依存せずに作ってあったので、JR-800のROMでも問題なく動かす事が出来た。ただ…HC-88では使われていなかった命令(ちゃんとした6301の命令)がいくつもあったため、中途半端に作られていた逆アセンブラの完成度を高める必要はあったがw

 

6301CPUはリセットされると$FFFEに書かれた2バイトをPCの値として取り込む。

とっかかりとして分かっているのはこの情報だけだ。

 

アセンブラリストを見て真っ先に思ったのは「やべぇ、6301忘れてる」(^^;;;

あれだけHC-88の時に入れ込んでいたのに、もはやレジスタ構成すら忘れてる体たらく(^^; もう一度復習するところから始める事に……orz

 

ブートするコードを追いかけていくと、なんだか値を見て分岐する箇所があった。マニュアルを見たところ「R+S+Tを押しながら起動するとコールドスタートする」という機能があるらしい。ははぁなるほど、キー情報はこうやって読み込んで判断していくのか。

 

さらに起動時の「JR-HuBASIC 1.0」を表示するコードを発見。ということはコレは文字列表示ルーチン、その先に呼び出されるのが1文字表示ルーチンだ。

1文字表示ルーチンを見ていくと、$00〜$1Fは文字表示というよりは機能コード(コントロールコード)となっていて、32個のテーブルジャンプで構成されている。という事はこっちが画面クリア、こちらがカーソル移動か…。

 

みたいな感じで、ちょっとずつ手がかりを見つけながら解析をしていってる。

何か作ろうにもコードを送り込む方法が無いので、今のところは何も出来ないが…orz

気力が続くうちはもう少しだけ頑張ってみるよ!!

何か作れたらホント楽しいだろうなぁ!!!(^-^)

 

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

National JR-800 ご紹介!

今回はJR-800のお話(^-^)

 

先日、某所でJR-800の写真を見て、ああ懐かしいなぁ…確か持っていたなぁ…と思い、頑張って発掘した。

なぜかマニュアルとプリンタはすぐに出るところにあった。なんでだw

 

JR-800本体

f:id:PocketGriffon:20210316125544j:plain

これがJR-800の本体。

ちゃんとケースに入れられて保管してあったので、とてもキレイな状態だ!

この本体の色味がとても気に入っている。青いキーボードもナイス。

なんでも良いけどSPACEとRETURNをものすごく打ち間違えるw

きっと多くのJR-800ユーザーが間違えると思う!(自信満々)

 

f:id:PocketGriffon:20210316130606j:plain

表示はこんな感じ。ぱっと見てドットが目立つ感じの液晶とフォントになっている。

横32文字、縦8文字。縦方向に8文字分あると編集する時にもだいーぶ楽ちんだ。

PC-8201、HC-40やHC-80とかと行数が一緒だね!

 

 グラフィックス的に見れば192x64ドットの画面構成。BASICのグラフィック命令はPSET、PRESET、LINEの3つしか存在しない。CIRCLEやPAINTは無いので複雑な絵を描こうとしたら頑張らねばならない。ユーザー定義文字(PCGみたいな機能)が32文字分使えるので、BASICで作るゲームなどのキャラクタ表示で使えそうだ。

 

f:id:PocketGriffon:20210316155556j:plain

裏面はこんな感じのシンプルイズベスト。

カタログスペックにあった増設メモリってどこにつくんだろ??

なんて思いつつ電池ボックスを開けてみた。

f:id:PocketGriffon:20210316155655j:plain

マンガンの単三電池4本で25〜70時間も動かせるらしい。という事はアルカリ電池だったら倍くらい動いちゃうのかしらん??これはすごい事!!

そして電池の左側にメモリ増設用の端子がついてた。

f:id:PocketGriffon:20210316160106j:plain

なるほどわかりやすい。もう今の時代じゃ増設メモリ手に入らないね(T-T)

空いてるところが見えてると「スロット埋めたくなる病」が発動するので、見えないくらいがちょうど良いw(自己抑制?なにそれ?)

ちなみに増設メモリは8KBのようだ。

 

プリンター JR-P20

f:id:PocketGriffon:20210316165902j:plain

JR−800本体を手に入れる際に一緒についてきたプリンター JR-P20。

今の時代ではかなりのレアアイテムなんだと思う。

 

大きさ的には横20cmくらいのサイズで、本体と並べるとこんな感じ。

f:id:PocketGriffon:20210316170336j:plain

存在感あるサイズだけど、この時代のプリンターとしては小さい??

重量はめちゃくちゃ軽いです。JR-800も乾電池入れた状態でもかなーり軽いんだけど、プリンターはそれよりももっともっと軽い。

f:id:PocketGriffon:20210316170937j:plain

そして裏面。安定のシンプルさw

このプリンターも単三電池4本で動かせる。ACアダプタも使えるけれども、アダプタの形状が本体とは違ってる。同じボルト数でセンターマイナスも同じなのに形状的に刺さらないってのは意図的なんだろうなぁ…多分。

f:id:PocketGriffon:20210316171153j:plain

よくよく見たら「GRAPHIC PRINTER」だった!グラフィックもプリントアウト出来るのか!BASICマニュアルみたら「HCOPY」なる命令があった。プログラムに埋め込むのもアリだけど、CTRL-2を押すといきなりプリントアウトも出来るらしい。すごい!!

 

試しに…とプリンターの電源を入れてみたけど無反応。電池でもACアダプタでもダメ。

軽く中身をみてみようと開けてみたのが下の写真。

f:id:PocketGriffon:20210316171539j:plain

基板自体はとってもキレイ!これでなんで電源入らないんだろ…。

やっぱコンデンサですか???

と思って図ってみたけど問題はなさそう!疑ってスマンかったw

f:id:PocketGriffon:20210316171700j:plain

時間を確保してじっくり見ていくしか無いかもね!

何よりも本体とつなげるケーブルがないので、気力も奮い立たない。仕方ない(T-T)

 

BASICマニュアル

手元に来た時からだいぶくたびれているBASICマニュアル。

f:id:PocketGriffon:20210316172112j:plain

中身を読む分にはなんの問題もない(^-^)
本来ならば取扱説明書もあったんだろうか…私の手元にはコレ1冊しか無い。
そして残念な事に、本全体が曲がってしまっている。

f:id:PocketGriffon:20210316172305j:plain

どうやったらこんな曲がり方になってしまうんだろう…(T-T) 私自身は本をとても大切にしたい人なので、出来たら直したい。

そう思って数ヶ月前に本を引っ張り出した時以降、重たい本の間に入れておいた。こうすると何ヶ月かすると元に戻ったりするのだ。本当はジップロックなどに入れてレンジでチンした後に重しを乗せれば、比較的簡単に元に戻るらしいのだが…。

f:id:PocketGriffon:20210316172510j:plain

↑今の状態がこんな感じ。写真を並べてみるとだいぶ良くなってきたのがわかる。あと1年くらい放置しておこう(^-^)

 

コールドスタート(R+S+T+ONボタン)した画面がこちら↓

f:id:PocketGriffon:20210316172905j:plain

なんとなく起動画面を見てて思うのは……そう、マイクロソフト系のBASICではないのだ。

通常のシーケンスを記述するコマンドで違和感を感じる事はないんだけど、特殊なコマンドで「あれ?」と思う事がいくつも出てくる。

例えば……いくつか例を上げてみるけど、

 

マシン語領域の確保は、マイクロソフト系のBASICならばCLEAR文のオプション指定で行うが、JR-800だとNEWON命令で行う(NEWON &H2800とか)。

 

FLDという命令は文字を表示する時にXORする値を定義するコマンド。アンダーラインを引きたい時には「FLD &H80」とする。消し線をつけたように見せたい時「FLD &H08」、文字を反転した時は「FLD &HFF」といった具合だ。

 

CALCはとても面白い命令。文字列を評価して答えを返してくれる。

例えばこんな感じだ。

 10 A$="1+1"

 20 B=CALC(A$)

 30 PRINT B

これでBに2が入ってくる。プログラムで文字列(としてのプログラム)を作成し、それを実行することが出来るという事は、いろんな事に応用ができそうだ。

命令1つ1つを取ってみても興味がそそられるBASIC!

 

せっかくなので何か作ってみたいが…

さて…せっかく発掘したJR-800なので、何か作ってみたいよなぁ…って気になる。

CPUは6301らしいので、先日まで取り組んでいたHC-88のスレーブCPUと同じだ。

ということはアセンブラ環境はHC-88で準備したモノを使えば良いのだ。

 

f:id:PocketGriffon:20210316174918j:plain

本体の背中側を見てみると、シリアル端子が出ている。マニュアルを見ると、どうやらJR-800本体同士を繋げてプログラムの転送などで用いるようだ。形状がCASIO系のポケコンについてるシリアル端子と似ていたので、モノは試しと繋げてみた。

f:id:PocketGriffon:20210316175113j:plain

やっぱり…というか全く通信出来なかった(^^; そもそも端子の電気信号が同じかどうかも分からないので繋がるわけがない(TT)

f:id:PocketGriffon:20210316175304j:plain

あとはカセットインターフェース端子がついている。でも私はデータレコーダを持ち合わせていない。テープで開発するのは避けたいなぁ…と思い、テープ運用の環境はもっていないのだ。…と言いつつ、そういえばボイスレコーダーを持っている事を思い出した。

 

テープへSAVEした音声データをMacへ持っていき、wavへ変換後解析ツールを作ろうとしてみたが、今のところ良い結果は出ていない(T-T) これが正常にバイナリ化→wav化出来たら、一気にJR-800でのプログラミングは現実化するだろう。

ボイスレコーダーの精度の問題のあるんだろうけれど、うまく行ったらいいなぁ。

 

というわけで今回は単純なJR-800のご紹介でした!

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

 

 

文豪ミニ5でプログラミング! その3

何もプログラミングしてないけどこのタイトルでいいんだろうか…汗

f:id:PocketGriffon:20210313145012j:plain

現状のご報告的な感じで書いていってみようと思う。

 

 

基本、目的を達成したいためだけに調べているので、詳しい事は解析していない(^^;

だってこんな巨大なROMを持つマシンを全解析なんて絶対に無理(^^;;;

 

独自プログラムからMS-DOSフォーマットのフロッピーディスクをアクセスする方法が分かったので、それを利用してROMのデータを解析してる(この1行を実現するためにどのくらい苦労してるのかを理解してもらえれば…w)

 

とりあえずは初期化部分を調べていけば必要なポートとかわかるかも…と思いつつ、ブート部分から見ていってる。

アセンブラは8086に対応したものを作成してあったが、V33特有の命令(というか80186で追加された命令)も出てきているので、随時追加対応していってる。

 

その結果、バンク切り替えで表に出る大量のメモリ(主にROM)が見つかった。

HDDを積んでいるマシンなので、てっきりROMサイズは小さいかと思っていたが巨大だった。おそらくフォントなどの動作速度に直結するデータはROMに入ってるんだろう…。展開するRAM積むよりもROMの方が安いって事情もあるのかも?

 

f:id:PocketGriffon:20210313151036j:plain

そういえばアウトラインフォントのROMカードも持っているので、こちらもどっかのタイミングで中を見てみたい。データだけ見てもイマイチかも知んないけどw

ROMの中には「……デバッガーが埋まってる?」と思うような文字列が入ってたりするので、解析楽しそう(^-^) 少なくともメモリマップや逆アセンブラの機能は含まれていそうと分かった。BIOSのラベルまで入ってるのはどーなのかとw

 

ブート周りを解析してみて分かったのは、CP/Mが起動するプログラムが本当に無いって事。実は隠しコマンドとかで入ってるのかなーと思ったけれども、コードそのものが無かったw

CP/M自体はROMに積まれてるっぽいので、起動する仕組みを作ってみたいね!

 

f:id:PocketGriffon:20210313172552j:plain

「点」を打つ機能が見つかったので、なんとなく遊んでみたw

LSI C-86(試食版)でも浮動小数点の計算は出来る!それなりに速いかなぁ…と思ったけれども、「点」を打つファンクションが激重で、描いてる点が見える(^^;;

 

なんて感じで脱線もしつつ解析は進めてるよ!

うーん、文豪エミュレータ作った方が解析早いかなぁ(良からぬことを…

 

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

文豪ミニ5でプログラミング! その2

文豪で…というよりはV33で…というか8086でというか(^^;;

なんとなく高速化ネタを思いついてしまったので、私にしては珍しく初期段階での高速化プログラミング。まぁ趣味の世界だからいーのよw

 

f:id:PocketGriffon:20210311104518j:plain

文豪はテキストVRAMを持たない表示構成なので、文字フォントを表示させようと思ったらドット単位(実際には8ドット単位)で点を打っていく必要がある。まだフォント周りの解析なども一切進んでいない。表示されているこのフォントは、プログラムファイルにデータとして含んでいる。

 

画面構成は640x400ドットとなっていて、色を出すためには3つのプレーンに同じデータを書き込む必要がある。この辺りはPC-8801PC-9801を想像してもらえれば良いだろう。3プレーン同時書き込みとかALUのデータコピーなどの機能は無い(と思う)ので、地道にバンク切り替えて書き込むというオーソドックスなパターン。

 

開発&解析の初期段階なので、極力プログラムに労力は掛けず、全てC言語で記述することで開発効率を上げる方向に振っていた。スタックポインタの初期化などどうしても避けられないところはインラインアセンブラで記述していたが、アセンブラの使用はその程度だ。

 

先日までの作業で、ようやくメモリダンプが動くようになり、8086で使用できる1MBのメモリ内容が見られるようになった。そこでやっと「自分自身がロードされているアドレス」を知ることが出来たw それまで手探り状態だったのでちょっとスッキリ!何をするにも仮説を立て「多分こうだろう」と想定してプログラミングしていた事が、実際に実証されていく過程がとても楽しい!(^^)

 

ダンプ表示はカーソルキーでアドレスとセグメントを変化させていく事が出来るようにしてあるけど、キーリピートの速度に表示が追いつかなくて、少しもたもたした表示になってた。出来る限りC言語で高速に描画出来るようにプログラム書いてたけど、いくらV33 16MHzとしても限界かなー。

 

ふと…「そうか、1文字のフォントデータは8バイト(一番下は空白なので7バイト)しか無いから、先にデータを全部レジスタに読んでおいたら各バンクへ書き込みだけで済むなぁ」なんて思った。思ってしまったらアセンブラで書きたくなって仕方がないw

 

具体的な方法

ここに8086(V33)のプログラムを掲載するのもアレなので、日本語で書いてみる。

考え方としては、レジスタマシンである8086でメモリをアクセスするのは時間が掛かるので、必要なフォントデータ(同じデータを最大3回書く)をあらかじめレジスタにロードしておいて、メモリをアクセスする回数を減らしてみよう、という作戦だ。

同時にセグメントレジスタの管理も簡単になるため、全体的に高速化されるハズだ。

 

幸い8086にはレジスタが豊富にあるため、レジスタの使い回しに困る事はなかった。DI、SI、ES、DL(合計7バイト)をデータ保持用レジスタとしてプログラムを組んでみた。VRAMのアクセスをする際にはDSを固定する事ができ、ループ展開で一気にVRAMへ書き込んでやる。これをバンク切り替えしながら3プレーンに書き込めば良いのだ。

 

この作業と同時に、書き換えるべきデータが前回と同じだった場合には描画をパスするようにした。PC-8801などで良く使うテクニックだw

これらの作業をしたおかげで、ストレスなくメモリダンプが行えるようになった!無駄にスクロールさせちゃうよw

 

高速化された事に気を良くして、リアルタイムにダンプ表示を行えるようにもしてみた。こうする事のメリットは、割り込みなどで書き換えられるワークエリアを簡単に探し出す事が出来る事だ。キー入力があった時にどこのメモリのどのビットが1になる…なんてのもすぐに探し出せる。高速表示が可能だからこそ出来る技だ(^-^)

 

ところで……LSI C-86(試食版)でアセンブラを使うプログラムを初めて書いたかもしれない。書き方がMASMなどと違っていて最初は面食らったけど、そこはコンパイラが出力するアセンブラリストが参考になるので特に困らなかった。

 

V33はシフト回数が指定できるので、なんとなく8086では出来ない「SHL BX,3」(BXの値を8倍にする)などと書いてみたが、これがうまくアセンブル出来てしまう。あれ?このアセンブラは80186の命令も解釈してくれるんだ…と思っていたが、実際に出力されたコードを見てみると「SHL BX,1」が3つ出てたw

 

今回のプログラムはループの外にあるコードだったのでこのままにしたが、どうしても気になるならばDB列でマシン語コードを書いてやれば良いかなーと思った。

f:id:PocketGriffon:20210311130534j:plain

 

何をするにも1行書いては試してみる…という様子を見ながら書いていく状態が過ぎ、ようやくまとまったプログラムを書いても大丈夫になってきた。ここまで来るのが本当に大変w

慌てず騒がず落ち着いて取り組んでいくよ!(でもやりたくて仕方ないw)

 

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