さらに続きで、今回はテープロード可能になった後のデータ修復 その1 です。
Syntax Error の謎
前回最後の ?SN Error ですが
エラーの出ている110行目は以下のような行です。
最後が : で終わっているのがいかにも怪しいといえばそうなのですが、だからと言ってエラーになる内容でもありません。前後のプログラムリストを見ると行番号に挿入削除を繰り返した痕跡もあり、単に削除し忘れたものが残っているだけという可能性も否定できませんでした。正しいリストとしてはどうあるべきなのかを全体のコードから解析して推測するという手もあったのですが、当時は bas2txt というツールの存在を知らなかったのもあり「エミュレータ上でひたすら LIST コマンドを打つのはやってられん」という問題がありました。
さらに、そもそもエラーになっている行は全体で 200行以上はあるように見えたプログラムリストの 15行目であり、このペースで修正が必要になるのではとても最後までたどり着けないだろうと思われたので、まずは wav の補正でなんとかすべく前回書いた変換パラメータ補正のトライアンドエラーを試みることにしました。
が、 2,3時間ほどパラメータを変えてはトライしたものの結局この 110行目の中身が変わることはなく、とにかく先に進まないことには残りの部分にどれくらい問題があるかもつかめないので、次の手段として BASIC部分のバイナリを直接チェックすることにしました。
せっかくエミュレータを使っているのだからデバッグ用の「モニタモード」を使えばよかったのですが、そのときはまだエミュレータの機能を全然把握できていなかったのでした……orz
BASICバイナリ
「(テープやディスク等の) メディア上にセーブされた BASICリストのバイナリ」を直接いじるにはそれなりに BASIC内部形式の知識が必要になるのですが、幸い(?) 20数年前に「バックアップ活用テクニック」 (たしか PART 2 あたり?) を見ながら 88SR で遊んでいた時の記憶を頼りに、なんとなくの見当はつけることができました。
問題の 110行目に相当する P6テープイメージ内の該当データは以下のとおりです。
先頭の2バイトの FFFFh はいわゆるリンクポインタのようなもので、「BASICリストとしての次の行が始まるデータが格納されているRAMのアドレス」が入ります。SAVEデータ上ではこの部分には FFFFh が格納されていて、実際に本体にプログラムがロードされた後に本来のアドレスで埋められるという動作になります。各行の最後は 00h で終端されるので、テープデータ上で "00 FF FF" で検索するとデータ中の行の区切りの見当をつけることができます。
次の2バイトの 6E 00 は行番号です。Z80 はリトルエンディアン (LSB first) なので、値としては 006Eh つまり 10進では 110 ということになります。
このへんのリンクポインタや行番号のデータを適当にいじると「実行はできるが LIST コマンドでは表示されない」といったちょっとしたプロテクト的な細工もできるのですが、前述のバッ活が一応復刊しているのにうろ覚えで昔話を書いてもしかたがないのでそのへんはまたの機会に……。
行番号以降のデータと実際のリストを比べてみると、 "Y" "TL" "L" といった変数、 "1" "0" "250" といった定数、およびステートメント区切りの ":" はそのままの ASCII コードで格納されていて、 "FOR" "TO" の BASIC コマンド (いわゆる予約語) や "+" "=" の演算式は 80h 以降の値に置き換えられているというのがわかります。
で、怪しかった最後の ":" の後ろには 02h という値が入っています。 80h より小さい値は予約語以外の生データとすると「LIST 上では何も表示されないが実行すると Syntax error」というのもそうかなという感じです。深く考えず「テープ音の歪みによる 1ビット化けだろ」ということでバイナリエディタを使って P6バイナリの問題の箇所の 02h をとりあえず 82h に修正したものを作ってロードしてみると……
と、最後の : の後ろに "NEXT" が登場しました!
"W" という変数名からしても わかってみればそりゃそうだよね という感じなのですが、要は時間待ちの空 FOR ループだったわけです。これがすぐに思い浮かばなかったのは 20年以上のブランクのせいというかなんというか……。
最初にエラーになった 110行以外についても "LIST 行番号-行番号" のコマンドをひたすらたたいて細切れにざっと確認したのですが、目視で認識できた範囲でわかったのは wav 補正時のパラメータによっては 130行目の LINE 文の座標区切りの "," (2CH) が "(" (28h) に化けるパターンがあるということくらいでした。最終的に採用したパラメータで作成した P6ファイルではその 130行目も問題なかったので、それをそのまま実行してみると……
「本物」だった Tinyみずいろ
というわけで、当初の ?SN Error を無事クリアして、15年前(?) になんとなく読んだはず(??) のプロローグメッセージが (P6的 ひらがな + グラフィックキャラクタで) 出てきました!
wav 補正で格闘した数時間の苦労も忘れてメッセージを読み進めていく (スペースキー入力等はなくオートモード的に進んでいきます) と、ちゃんとグラフィック画面も出てきます!
Tinyみずいろページのサンプル以外の絵もちゃんとあるじゃないですか! モノクロでも雪希さんはかわいい
が、そのままながめていると、次の画像はこんなことに……
感動に水をさされた感はありましたが、とりあえず画像はおかしいものの暴走したりエラーで停止したりはしないようでした。さらにそのまま進めてみると、同じように微妙にズレた画像がありつつも
という店頭デモ動作がちゃんと実現されていました。
作業着手からここに来るまでずっと、 Tinyみずいろページにあった煽り文句(?)の
「うそはうそであると みぬけるひとでないと、
(パピコンをつかうのは)むずかしい」
にしてやられてしまったらどうしようという不安を振り払いながらの作業だったこともあり、デモとして完成したプログラムが動くのを目の当たりにした感動は言葉に表せないくらいで、1ループに 7分程度かかるデモを思わず何度も何度もながめてしまいました。SCREEN4 以外のデモ画像はフェイクだった ということにはなると思いますが、そんなことは些細な問題ですよね!
ここまでたどり着いたのが↓のツイートをした日です。
【Tinyみずいろ "Prologue" for PC-6001(32k)】
— Izumi Tsutsui (@tsutsuii) 2016年6月10日
一応ここまで動いたけど、いろんな意味で難易度が高い…… pic.twitter.com/KNRm7rZ29b
画像キャプチャ等々をしてる段階で状況が把握できてきてそれまでの苦労を思い出してきたせいか、感動のテンションがいまいち感じられませんね ^^;
グラフィックデータ化け
結果としては1バイトだけだった BASICプログラム部分の修正の作業記録でずいぶん引っ張ってしまいましたが、次はズレてしまっているグラフィックデータをなんとかしないといけません。最終的には「P6月間中に自分で何かしら作業した結果としてのデモ動画をアップする」のが目的だったのです
おそらく画像データはランレングス圧縮されていて、あと数バイトデータが化けているっぽくて3枚ほど画面が途中でズレる
— Izumi Tsutsui (@tsutsuii) 2016年6月10日
デモの画像は SCREEN4 のモノクロモードでかかれています。 P6 の仕様についてはまったく詳しくなかったのですが、 TINY野郎さんのブログ 等によれば SCREEN 3 の 4色モードは 2 bpp (2 bit / pixel) だったことから、モノクロの SCREEN 4 は 1 bpp (1 bit / pixel, すなわち 8ドットを 1バイトで表現) という予想がありました。
また、データ容量と P6の実行速度の問題から、 TINY野郎さんが YS2OP デモで採用していたのと同様なランレングス圧縮 がかかっていて、そのランレングスの長さ指定部分が化けると 8ドット単位で画像がズレるのだろう、ということも見当が付きました。通常データ部分が化けた場合は表示されるデータが化けることになりますが、モノクロディザ表現の場合化けているかどうかは元データと比べない限りは目で見てもわからないはず
が、 BASIC リストデータの場合はこのエントリで書いたようにその書式から修正すべき箇所が検索可能だったので見当をつけることができましたが、いくら P6 の解像度は低いとはいえグラフィック画像を目視した結果から 6KB 近い VRAMデータの化けている箇所を手動で検索するのはちょっと無理だろ、ということも予想されました。そもそも、ランレングス圧縮という予想はあっても実際にどうデコードするのかがわからないと分析もできませんし、そのためには展開ルーチンを逆アセンブル等で読み解く必要があります。
というわけでグラフィックデータの修正作業は翌日以降に持ち越したのですが、ブログでの作業記録も同じように次回以降に続きます。無駄に長くてすいません