CASIO AI-1000を使ってみる!その10

f:id:PocketGriffon:20210729105601j:plain

解析用の環境も整ってきたので、HD61700のプログラムを組んでみよう!

そろそろ実機で動く何を作らないと、こんなだるだるな進み方のブログに付き合ってくださってる読者の皆さんに申し訳がないw

 

開発環境を整える!

解析を頑張ろうと思って逆アセンブラを作っている流れの中で、当初はアセンブラも自分用に開発するかーと考えていた。しかし…続々と出現する未定義命令の多さに困惑し、これはアセンブラ作るのも大変だよ…と思うように変化していった(^-^;

 

アセンブラを独自に作るのは諦めようと思ったが、可能であればMacだけで開発環境が完結するのが望ましい。Macで動くHD61700アセンブラを探してみたが、残念ながら見つける事が出来なかった。

 

仕方ないので、マクロアセンブラを活用することでそれっぽいコードを吐かせる事が出来ないかなぁ…とか検討してみたけど、どうもしっくりこない。

 

それに、素直に

 LD $1,10

 AD $1,$SX

と書くよりも

 $1=10

 $1++

などと書けても良いかも…とかも検討。

昔MZシリーズにあったBASEを移植(という名の新規開発)してみるのも面白いかも?

 

実はこれ、AI-1000のみならず、何度と無く検討しているのだが結局やっていない。

本来のニーモニックを覚えるチャンスを逃してしまいそうな怖さがある。せっかくレトロコンピュータを使っているのに、当時のニーモニックを使わないのは「超えてはいけない一線」のような気がしていて、SC61860の時にもギリギリまで検討してやめてしまった。

 

そんな事を考えていたら、このブログには何度と無く出てきている「BLOCKS」の作者から連絡があり、話の流れからHD61700アセンブラの話へ行き、最終的にあお氏が開発した「HD61700 CROSS ASSEMBLER」まで話が行き着いた。

HD61700 SPIRITS

 

このアセンブラMacで使えたらいいにのなぁ……。

……とか思っていたら!

今までまーったく気がついてなかったけれども、ソースがダウンロード出来るようになっていた!!!!

 

じゃあ…という事で、ソースをダウンロードし、Macでビルドしてみた。

  gcc -O3 -o hd61 hd61700.c

warningは大量に出るものの、コンパイル自体は問題なく通った。

試しに小さなサンプルを書きアセンブルしてみたところ、動作も問題なし!

やった!! これは素晴らしいアセンブラが使えるようになったぞ!(^-^)

 

AI-1000へダウンロード!

hd61はいろんな形式で出力できる機能を持っている。これも便利だなー。

いつものパターンだと、BASICのDATA文にマシン語コードを入れておき、それをPOKEしまくる…という形式を利用するのだけれども、今回は先人の知恵を拝借してしまおうと思う!

 

先日、Amano氏が公開しているページにある「BLOCKS」というゲームがAI-1000に対応したとブログに書いた。

PB-1000 Software Library

 

このローダーがものすごく良く出来てるのだ!DEFCHR$を用いた方法に脱帽…これよりも速い方法はバイナリを直接ロードする以外にないんじゃないだろーか??

クロスアセンブラといい、作者のあお氏には感謝しかない!(^-^)

 

さっそくMakefileへ組み込んで、make一発でQuickLoader対応のファイルが出力出来るようになった。

 

ROM内ルーチンの活用

なにかプログラムを組んでみようか…と思ったが、例のごとくとっかかりがない(^^;;

まずは画面になにか表示してみる!

 

ポケコンジャーナル1990年8月号にAIMON(こたちゃん氏作)がソース付きで掲載されていたので、まずはこのソースをじっくりと読んで見る事に。最初は全く見慣れなかったニーモニックも、逆アセンブラ開発で格闘したこともあって、少しずつ読めるようになってきた!

 

どうやら…AI-1000(というかPB系?)では表示方法にお作法があるみたい。

以下、なんとなく頭に出来たイメージを書いていくので、間違いがあったらごめんなさい。

 

画面に文字を表示するためには…

・テキストメモリにキャラクタコードを書き込む

・ROMルーチンDOTMKを呼び出してドットパターンへ変換

・ROMルーチンDOTDSを呼び出してLCDへ描画

…という感じっぽい。

 

ということは、変換されたドットパターンが格納されているアドレスに、独自のグラフィックパターンを送り込んで、DOTDSすれば任意の絵が描画される…ということか。

 

そしてそのドットパターンが入っているアドレスを調べていったんだけど…どうも納得が出来ない数字が出てきた。&H0201というアドレス。最後の1ってなんだろ??

先日、本体から抜き出したRAMデータも見てみたが、確かに&H0201からデータが入ってるっぽい。

 

PB-1000の、同じバッファは$6201にあるらしい。最初、この数字を見た時には「誤植か」と気にも止めなかったんだけど、どの資料を見ても$6201になってる。

なにか理由があるんだろうか…あるんだろうなぁ…うーん…(^^;;

 

とりあえず表示してみる!

そして細かいことは後回しにして、とにかく適当な絵を出してみたのが写真というワケ。

f:id:PocketGriffon:20210729105601j:plain←これね

ここのプログラムだけを晒してみると、こんな感じ↓

f:id:PocketGriffon:20210729151319j:plain

もうコメントから言ってラフに書いてるの丸わかり(^^;

もっと良い方法があるのかも知れないけど、今はこれがMAXパワーって事で!

 

ところで…AI-1000へプログラムを転送すると、識別子がSになる。これをBASICファイルのBに変更する方法はないんだろうか…。いつもnameでファイル名変更→BASIC起動→LOAD"ファイル名"をしなくちゃいけなくて、段々面倒になってくる…(^^;;

なにか良い方法があったら教えてください。

 

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

CASIO AI-1000を使ってみる!その9

f:id:PocketGriffon:20210728104452j:plain

作業が進まないうちに「その9」まで来てしまった!

しかもこの間に作ったものと言えば本体ROM→ホストへの転送と、今作ってる逆アセンブラだけという生産性の無さ(T-T)

これで「AI-1000を使ってみる」というタイトルでいいんだろうか…汗

 

いつもそうなんだけど、レトロパソコンで遊んじゃうぞと思いつつも、最初にウチにROMを抜き出したら、しばらーく本体には寄り付かなくなる(^^; 解析フェーズに入ってしまうと本体触る余裕が無くなっちゃうんですよね…。

 

完成した逆アセンブラ

先日、ようやく1命令逆アセンブラを作り終えたが、コレと先日から作っていた「逆アセンブラの体裁を整えるモジュール」を合体させた。

 

内部的には2パス方式の逆アセンブラで、1パス目で出来る限りコードとデータを分離する処理を行い、2パス目で出力という、ワリと一般的なプログラム。

 

1パス目の処理でプログラムを大雑把に追いかける(CALやJRなども分岐していく)構造になっているので、多くのコードは発見する事が出来る。ここで解析出来ないのは、例えば「JP (レジスタ)」のような間接ジャンプや、「PUSHしてRTN」などの特殊なコードなどだ。

 

HD61700の場合はバンクを跨いだジャンプなども追いかけられない。そのため出力された逆アセンブラコードの精度はそこまで高くはない。

 

「その5」で書いたエントリファイルを充実させる事で、出力される逆アセンブルリストに自動的にコメントを挿入していってくれるので、調査すればするほどリストが充実されていく。

CASIO AI-1000を使ってみる!その5 - レトロパソコンであそぼう!

 

同じくその5で「超適当に」見つけ出した&H0D80からのジャンプテーブルだが、コードを見る限りリセットされた直後のエントリ?だったのかも知れない。&H0D80には「JP &H30FE」となっていて、その先は↓こんな感じのコードだ。

f:id:PocketGriffon:20210728105757j:plain

スタックの初期化、バンクレジスタの初期化などが並んでいる。

 

どのような経路でこのジャンプテーブルが呼び出されるのかは不明だけど、入り口っぽい箇所を見つけられたのは超ラッキーだった!

 

こんな感じでROMを逆アセンブルしたところ、7000行くらいに及ぶソースが出力された。まずはここから解析を開始する!

 

PB-2000C

ここから脱線!

ちょっと興味があったので、AI-1000の海外版?のPB-2000Cについて調べてみた。

CASIO AI-1000を使ってみる!その6 - レトロパソコンであそぼう!

↑その6で「PB-1000の海外版?」とか書いたけど、考えてみたらROMカードが刺さるんだからAI-1000の海外版だろ…と自己突っ込み(^^;;

 

ふと「PB-2000Cに、AI-1000のROMカードを刺したらどうなるんだろう?」と疑問に思った。

思ったら実験クン!(^-^)

 

そしたら……想像してた通り、普通に動いた!

f:id:PocketGriffon:20210728113031j:plain

ということは、内部ROMには互換性があるって事なのかな…。まぁCPU内部に含まれているROMなんて簡単には変更できないだろうから、当然といえば当然なのかも。

 

では、表示されるフォントはどうだろうか?

f:id:PocketGriffon:20210728113516j:plain

f:id:PocketGriffon:20210728113539j:plain

↑これがAI-1000で実行した結果。

グラフィックやカナ、日時などのが表示されている。

 

f:id:PocketGriffon:20210728114111j:plain

f:id:PocketGriffon:20210728114129j:plain

↑こちらがPB-2000Cで実行した結果。

グラフィック文字やカナ文字があった部分が、ウムラウト文字や別の記号に置き換わっている!へー、なるほどね!

 

フォントそのものが本体側に含まれているのか、それともROMの中で多言語に対応しているのかは分からないけれども、多言語対応するためには&H80以降のフォントは使っちゃダメだ!(そこまで意識するようなもの作る??)

 

さてここからはしばらく解析フェーズに入っていくけれども、見慣れないニーモニックと格闘するのは大変なので、ポケコンジャーナルなどに載っている情報は積極的に活用していこうと思う。表示とキー入力が分かれば、なにか作れそうな気もする。

#そしてその後は急激に飽きるのがいつものパターン…汗

 

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

 

CASIO AI-1000を使ってみる!その8

f:id:PocketGriffon:20210727235618j:plain

私には30年以上も昔からの友人(PB-1000使い)がいる。この友人が作ったテトリスもどきのゲームが、何ヶ月か前からJun Amano氏のページ「CASIO PB-1000/C FOREVER!」で公開されていた。

PB-1000 Software Library

それがAI-1000にも対応したということで、さっそくダウンロードして遊んでみた!

 

懐かしい……これでうまれて初めてテトリス見た&遊んだんだよね。

当時、自分が愛用してるマシンに移植してみようと考えて、約2週間掛けてオールアセンブラで作った。初めて使う8086だったこともあり、大変苦労した覚えがある。

 

開発してる期間には、目をつぶっても頭の中でブロックを並べるシチュエーションが出てきてしまい、見えてしまったからには並べないと消さないと!みたいな無限ループに陥るハメになったw

本当に懐かしい!!

 

1行アセンブラが動いた!

さて、開発している逆アセンブラの進捗状況だけど、ようやく「1行逆アセンブラ」が動くようになった!これは指定したバンク、アドレスのメモリにある1命令だけを逆アセンブルするモノだ。

 

手持ち資料から分かる範囲の未定義命令を調べて対応してみた。

そしたら!正規命令+未定義命令のすべての組み合わせで1150種類以上にもなった!

これ……全部の書き方をサポートしたアセンブラ作る気がしない(^^;;

 

結局、逆アセンブラは2度書き直すハメになった(^^;

いやはやメッチャ複雑な命令構造だと思う!ポケコンのSC81680を見た時も「CISC CPUだなぁ…」と思ったが、HD61700も負けてないと思う(^^;

今のところHD61700のエミュレータを書くつもりはないけれども、書こうとしたら一苦労しそうなCPUだと思う。

 

明日以降、逆アセンブラの構造を組み立てて行く!

今日はキリが良いところで寝る!

 

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

 

CASIO AI-1000を使ってみる!その7

f:id:PocketGriffon:20210727012848j:plain

アセンブラを作り直してる!

10%くらい実装したところで未定義命令を追加し始めたけれども、命令解釈部分が気持ちよく作れず、作り直す事にした。

 

当初、HD61700の命令コードを調べた時には「空いてるビットとかあって冗長なコードになってるなぁ…」と感じていたけれども、未定義命令を理解していくうちに「めちゃくちゃ詰まった命令形態だ!」と思うようになった(^^;;

 

セカンドオペレーションが命令コードによって意味が違ったり、命令によってはサードオペレーションが出てきたりなど、その都度理解はしても全体を通して頭に収まらない(-_-;

大雑把に似てる命令をまとめたりしているけれども、エレガントじゃないなー(T-T)

 

ここで頑張ってる理由は、この先で苦労したくないから(^^;;

 というわけで、もう少し逆アセンブラで頑張りますw

そしてソースに書いたコメントは、意気込みを表してる!(^-^)

f:id:PocketGriffon:20210727014436j:plain

 

…すみません、なんか内容が無いブログになってるね(T-T)

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

CASIO AI-1000を使ってみる!その6

f:id:PocketGriffon:20210725233913j:plain

写真はPB-2000C。

海外で販売されていたマシンだけど、日本でいうところのAI-1000? ただAI-1000の特徴であるLisp言語ではなく、C言語が搭載されている。ということは、PB-1000Cの海外版と思った方がいいのかも??(実はよく分かってない)

 

解析できないコードが出てくる

あれから逆アセンブラを作り続けている。

……と言っても、日がな1日作業しているわけじゃなくて、外出しつつ資料読みつつあれこれしつつ…って感じなので、実質1日の作業量なんてたかがしれてる(^^;;

 

ROMデータを逆アセンブルするために格闘しているが、つじつまがあわないコードが出てきてしまった。3バイト命令を「3バイト」と解釈して次の命令を参照すると、命令そのものが変な感じになってしまう。「変」に感じるのは、突然脈絡もない命令が出てきてしまい、プログラムとしての流れが破綻してしまうのだ。

 

試しに3バイト命令を2バイトだと解釈すると、その次の命令も納得出来るコードが出る。

おかしい…さんざんっぱら調べたが、どうにも納得が出来ない。

理解が及ばない「何か」がソコにある。

もうこのままお蔵入りか…と思うほど追い込まれた。

そこまで追い込まれて、ようやく思いつく。

「もしかしてメーカーが作ったプログラムに未定義命令が使われてる?」と。

 

言葉の違い

ここで…私がイメージしていた「未定義命令」と、HD61700で使われている「未定義命令」の意味について、大きな違いに気づく。

 

私が思い描いていた未定義命令とは、Z80や6809にあるような「存在自体は有名だけどメーカーも正式にはサポートしていない命令」のイメージ。仕事で作るプログラムで未定義命令を使うなんてもってのほかで、むしろ使用禁止命令として張り出しちゃうくらい。

 

そしてHD61700界隈で使われている「未定義命令」とは、もしかしたら「未公開命令」なのではないか…と思うようになった。正式にサポートされているけれども、なんらかの事情で公開が控えられた命令であり、使う分には構わないけど説明はしないよ…的な命令コード。

 

私は未定義命令というのを前者で捉えていたので、HD61700には未定義命令が多いらしいけれども、ユーザーが速度やサイズを競うために使っているものであり、ROMの解析には何の影響もないだろうから、逆アセンブラや今後作るであろうアセンブラでは未対応で構わない…くらいの感覚で捉えていた(^^;;

 

Twitterなどで未定義命令の話題を出されても、反応が鈍かったのはこのせいだ(^^;;

まさか本体搭載ROMで使われるとは夢にも思っていなかったので、ずーっとずーっと後回し、もしかしたら理解しなくても良いものかも…とさえ思ってたww

 

うーん、趣味の世界で未定義命令を使うようになったら対応しようと思っていた逆アセンブラを、今この瞬間から対応するようにしなければならなくなった(^^;;

 

ココに至るまでの時間が長かった!

というわけで、現状報告でしたw

 

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

CASIO AI-1000を使ってみる!その5

HD61700のニーモニックや命令を覚えることを目的として、逆アセンブラを作り始めた。

f:id:PocketGriffon:20210724232659j:plain

↑これがソースの先頭に書いてあるコメントなんだけど、1発めからキレイに作れる感じがしなかったので、作り直す前提で作り始めてる。割り切り感満載のプログラムだ!

 

理由(のひとつ)は、今の時点では未定義命令の規模が見えてこないからだ。命令フォーマットが今分かってる分類に属していれば拡張で行けるんだけど、まーったく違う構造を有してるとすると、きっと作り直した方が早いかも…ってなるかも知れない(^^;

 

せっかくなので今回は「こんな感じの逆アセンブラ作ってます」というご紹介をしてみたい。

まだ出来上がってもいないモノを紹介するのはどーかと思うけど!!

 

仮設計

まず逆アセンブラを作ろうとしたら、命令フォーマットを調べる必要がある。

f:id:PocketGriffon:20210725003721j:plain

↑これはPB-1000コマンドファレンスに書かれている情報そのままだ。

なぜこれをわざわざExcelに書き移したのか…と言えば、これも未定義命令に対応するため。

おそらく…これ以外のフォーマットがあるんだろうな…と思い、自由に修正書き足しが出来る状態にしておきたかった。

 

手元にある資料では、どの命令がどのフォーマットに対応してるのかの情報が見当たらない。命令のバイト数から推測をしながら解析していくしかないかと考えている。

 

命令のデコード方針が決まったら、あとは各命令フォーマットのプログラムを書いていけば良い。1命令逆アセンブルするプログラムはワリと簡単に作れるのだ!

 

エントリファイル

私が作る逆アセンブラは、ほぼすべてエントリファイルを読み込むようにしている。

これはもう見てもらったら一発でわかるかと思う。

f:id:PocketGriffon:20210725005944j:plain

#…コメント行

F…読み込みファイル指定(バンク、アドレス、ファイル名)

E…逆アセンブルを始めるアドレス

C…そのアドレス行に挿入するコメント

 

指定のファイルを読み込み、指定されたアドレスから逆アセンブルを始める。

内部的にジャンプコードを認識し、プログラムの流れを追いかける形で逆アセンブルするアドレスを増やしていく。

内部的には2パス方式になっていて、最終的にはコードとデータが分離された状態の逆アセンブルリストが、コメント付きで出てくる…というワケだ。

 

これの利点は、プログラムの解析結果をエントリファイルに付け加えていけば、機械的に出力される逆アセンブルリストにコメントがどんどん挿入されていく事だ。

 

テーブルジャンプなどを自動的に判別させるのが簡単ではないので、そこは手動でエントリファイルへ追加していく流れとした。

まだ開発中なので機能が充実していないが、過去に作ったものでは「M…メモリ書き換え」とか付けていた!

 

そして一度プログラムを完成させておけば、PB-1000用のエントリファイルを追加するだけでPB-1000にも対応が出来る。

 

解析を始めたいんだけど…

アセンブラを作っている最中に、テストでROMの逆アセをしようとしたが、はて、どこのアドレスから解析をしたら良いのかが分からない。

 

そもそもHD61700というCPUは、電源を入れた時にどのアドレスから実行が開始されるんだろうか…?? こればっかりはCPUによって違うので、情報がないとどーにもならない。

手持ちの資料を見てみたが、バンクレジスタについてはRESET時の動作が書かれていたが、PCについては記述が無い気がする…。

ここは(勝手に)バンク0の&H0000からスタートする…と解釈したいが、残念ながら&H0000は例の見えないROM領域だ(T-T) 

 

どこかエントリになりそうなアドレス情報がほしい!

アセンブラの動作確認用なので、プログラムの場所であればワリとどこでも良い。

ROMの中を探してみる事にするが、手当り次第探すだけの根性もない(^^;;

 

そこで命令コードに着目する事にした。どこかしらの場所に「JP m」という命令が並んでいる可能性がある。ジャンプテーブルだったりHookだったりする場所があるに違いない。

そうして&H37(JP m)の命令コードをROMの中から探してみる。

f:id:PocketGriffon:20210725012249j:plain

……ものすごくジャンプ命令が並んでる感じがしない!?

先頭から「JP &H30FE」「JP &H3168」「JP &H01BC」…という感じに読める。

内蔵ROMのアドレスへ飛ぶのは解析出来ないが、外部ROMならば解析が可能だ。

よっし、こんな感じで解析していこう(^-^)

 

なんだか地道な事をやってるな…と思われるだろうが、まさにそうかも(^^;

この先は、きっとアセンブラも自作するんだろうな…と思う。アセンブラについては少し思うところがあるので、今回は冒険してみようと思ってる!(意味深

 

まだHD61700を理解していると言えるレベルでは到底ないけれども、とても直行性の高いアーキテクチャっぽく感じている。コンパイラが作りやすいんだろうなぁ…と思ってるけれども、C言語とか用意されちゃったりしてないのかな…??

 

なんだか夢が広がるCPUだなー!(^-^)

ココ数日は妄想ばっかりが広がってる(^^;;

 

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

CASIO AI-1000を使ってみる!その4

f:id:PocketGriffon:20210723153310j:plain

苦労してる!

とーっても苦労してる!!!

新規に取り組むマシンで、これほどまで苦労するのは珍しいかも!

しかし今はこの苦労が楽しくて仕方ない(^-^;;

自分が全く知らなかったことを覚えていける喜びは格別!(^-^)

誤解や勘違いも多いけれども、それでもブログやTwitterで発信していくので、暖かく見守ってもらいたいw

 

昨年末に挑戦したPC-1350(SC61860)の時も結構苦労していた。

でも逆アセンブラはすぐに作る事ができたし、エミュレータも3日間くらいで(かろうじて)動くところまでは持っていけた。手元に資料やサンプルとなるものが山のようにあったため、そこまで大変ではなかった。

SC61860が簡単難しいは別問題としてあったとしてもw

 

今回のAI-1000は圧倒的な資料の無さに苦労してる。

実はPB-1000の方がまだ参考になるものが多かったように思うので、そっちをチャレンジする方が良かったのかも知れない。でもチャレンジするからにはAI-1000がいい!!という気持ちが強かった(^-^) AI-1000を使いこなすなんてカッコいいやーん!(^O^)ノ

…まぁ、本来の使い方なのかどうかは横に置いておくとして…汗

 

ROM引っこ抜き再チャレンジ!

さて、前回メモリの内容を抜き出せたと思っていたが、どうやらROMではなくRAMだった事が判明。

f:id:PocketGriffon:20210722223821j:plain

BASICのPEEK文ではバンク1側が見えちゃうんだね…。

 

どうにかしてPEEKで読み込めるバンクを0に切り替えが出来ないかと思ったが、そんなフラグっぽいものは見つからず…。試しにmonでバンク切り替えしてからPEEKしたらどうなるんだろう…と思ったが、やはりバンク情報はmonの中だけで完結した指定のようだった(T-T)

 

仕方ないのでメモリをアクセスする部分だけマシン語で書くことにした!

PB-1000のアセンブラ機能を使えばいいか…と思ったが、モノは試し…とばかりにハンドアセンブルしてみることにした!多分短いプログラムだし平気でしょ!とw

f:id:PocketGriffon:20210723160423j:plain

マシン語ルーチンに値を渡す方法が分からなかったので、&H1002,3にアドレスを入れて&H1000をコール、&H1020にデータが入ってる…という方法をとった。

 

当初、バンクを切り替えてアクセスをした後、そのままBASICへ戻ろうとRTNだけ入れていたら、ハングアップしまくった(T-T) どうやらバンクを切り替えた後にBASICへ戻さないといけないらしい。これはプログラム中でバンクを切り替えたからなのか、それともどんなマシン語プログラムでもそうなのかは不明。この先の実験で明らかになってくるかなー。

 

たったこれだけのプログラムなのに、5〜6回のハングアップを経験。そのたびにAI-1000をFA-7から取り外し、RESETとNEW ALLを押すハメになった(T-T) あまりの面倒くささに、AI-1000のカバーを取り外して運用する事にした。

ALT+CTRL+DELみたいなリセット方法はないんだろうか……

 

そう!もうひとつ!

BASICからマシン語をコールする方法については、ポケコンジャーナル紙を参考にした。

「SYSTEM CALL アドレス」とすれば良かったらしい。

f:id:PocketGriffon:20210723164751j:plain

 

こんな感じで他の書籍等を参照し始めてしまっているので、すでに「自力で頑張る」が崩れてしまっているとは思うけれども…そこはごめんなさい(^^;;;

CPUの未定義命令や内蔵ROMの情報などは、良い感じに参照しつつやっていけたら…と思う。

 

さぁ、ROM情報が取れたら逆アセンブラ作るぞー!

まだまだ先は長い(^-^)

 

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