HN 日本語サマリー

← 一覧へ戻る
プログラミング

ZX Spectrum システムツアー:テキストモード

ZX Spectrum System Tour: Text Mode (bumbershootsoft.wordpress.com)

30 pointsby rbanffy0 コメント

要約

この記事は、ZX Spectrumの機械語レベルでのシステム操作、特にテキスト表示機能に焦点を当てています。BASICとの連携方法、メモリ構造、そして画面表示のためのシステム変数やROMルーチンについて解説し、ユーザー定義グラフィックスやキーボード入力についても触れています。機械語プログラムのロードと実行、BASICとの共存メカニズムも説明されています。

全文翻訳

さて、SpectrumのBASICがハードウェアに対してどのような制御を提供してくれるかを見てきましたが、次は機械語の世界に踏み込み、そこで何が提供されているのかを見ていきましょう。この領域にはさらに多くのカバーすべき点があり、かなりの数の投稿にまたがるだろうと予想しています。また、多くの他のプラットフォームに比べて、この領域はかなり困難でもあります。なぜなら、Sinclairは一貫性のある構造化されたファームウェアインターフェースを公開することに最小限の注意しか払わなかったからです。Commodoreの8ビット機は、オリジナルのPETからC128に至るまで、その「KERNAL」ROMの終わりに互換性のあるジャンプテーブルを備えており、ファイル処理やディスクアクセスのようなことを行う場合でも、かなりの量の機械語コードが同一に機能することを意味していました。MSXは単一のコンピュータではなく、メーカーがそれに準拠して製造する業界標準であり、その主要な部分はその割り込みベクタの近くにあるよく定義されたジャンプテーブルでした。IBM PCのBIOSは、あまり自発的ではなかったものの、同様の役割を果たしました。しかし、Spectrumには定義されたエントリポイントがわずかしかなく、その結果、開発者は望む結果を得るためにシステムROM自体の奥深くを直接呼び出す傾向がありました。Timex Sinclair 2068は互換性のないROMを持っており、その結果、Spectrumのソフトウェアはほとんど動作しませんでした。これは、米国市場での失敗の大きな要因であったと理解されているようです。私はこれには少し懐疑的です。なぜなら、その meteoric な米国でのクラッシュは、MSX、Commodore 16、Coleco Adamも共有しており、これらはすべてTS2068の plausibly な直接の競合相手でした。しかし、128が2068の失敗後にリリースされ、128がそのROMの関連部分を48Kバージョンと非常に注意深く互換性を保っていたことを考えると、Sinclairはそれでもここで重要な教訓を学んだと私は推測します。このシリーズの目的のために、私は48K Spectrumをターゲットプラットフォームとして扱いますが、私が説明するテクニックが16Kおよび128Kマシンでも機能することを確認します。さまざまな忠実度のSpectrumクローンや後継機が数多く存在しました。もし途中でそれらに関して興味深いものに出くわしたら言及しますが、それはすべて純粋な余談の領域になるでしょう。最初の試みとして、先週紹介した100% BASICの「Manic Mechanic」ゲームのようなディスプレイを得るために、私たちがコマンドできる機能を見ていきます。この最初の投稿では、基本的なシステム構成から始めます。機械語プログラムがシステムにどのように存在し、どのようにロードされ実行され、BASICやBIOSとどのように共存するのかを見ていきます。次に、システム上のテキストベースのディスプレイのための機能、そしてManic Mechanic自体が依存している「ユーザー定義グラフィックス」機能について掘り下げていきます。最後に、キーボードとジョイスティックの入力について見ていきます。これは、BASICで行う必要があったことと非常に近いことがわかります。 最初の原則:コードを実行すること 私がZX Spectrumを探求し始めたとき、BASICが機械語とどれほど容易に共存できるかに非常に驚きました。多くの標準的なBASICコマンドには追加モードがあり、純粋な機械語プログラムだけでなく、BASIC/MLの混合コンビネーションにも非常に適しています。カセット上のファイルは、BASICコード、BASICデータ、またはバイナリデータとして自己識別します。BASICのSAVEとLOADコマンドには、他のBASICの明確なLOADとBLOADコマンドと同様に、正確に何をロードするかを指定する拡張機能があります。テープから機械語をロードするには、ファイル名の後にCODEキーワードを付けます。BASICはCLEARコマンドにパラメータを渡すことでメモリ使用量を制限できます。BASICのメモリの上限を機械語のロードポイントのすぐ下に下げることで、メモリの競合は完全に回避できるはずです。BASICはUSR関数で機械語サブルーチンを呼び出します。これはルーチンのアドレスを引数として取ります。ルーチンは作業を行い、RET命令でBASICに戻ります。BCレジスタペアの値は、16ビット符号なし整数として関数の値としてBASICに返されます。意味のある戻り値がないルーチンは、一般的に乱数ジェネレータに渡すことでそれを処理します。Sinclair BASICのRANDOMIZE USRは、C64 BASICのSYSとほぼ同じことを行います。バイナリデータの範囲を保存することに加えて、SAVE関数はBASICプログラムをロード直後に実行を開始するように保存することもできます。そして、希望する任意の行番号から実行を開始できます。2017年に、私はそれ以来使用している、私のSpectrumプログラムのためにより洗練されたBASICスタブを作成しました。一般的な戦略は次のとおりでした。BASICプログラムは、10ではなく30行から実行を開始するように保存されます。30行のコードはCLEARコマンドでBASICのメモリを制限し、次にテープ上の次のファイル(実際のプログラム)をバイナリとしてロードします。ロードが完了すると、プログラムの先頭にジャンプします。10行と20行はRANDOMIZE USRでロードされた機械語を呼び出し、ローダーロジックをスキップしてプログラムが正常に終了するようにします。これらすべてが最終的に得られる結果は、実行時に機械語コンポーネントを実行するプログラムですが、ロード時には必要な準備をすべて一度だけ実行します。これをターニングキーパッケージングスクリプトとして使用できるものに変えることは、このツアーの範囲外なので、元の記事とスクリプトのコピーへのリンクを貼っておきます。 機械語から見たSpectrum Z80は64KBのアドレス空間を持ち、48K Spectrumではそのすべてが使用されています。$0000–$3FFFはシステムROMです。$4000–$5AFFはグラフィックスRAMで、ビットマップデータとカラーテーブルの両方用です。それ以外のすべてはシステム用のRAMです。これは基本的に16Kおよび128K Spectrumでも同様ですが、16KのRAMは$7FFFで終了し、128のROMとRAMの両方はバンクスイッチされています。アセンブリ言語コードを書くとき、システムROMが所有する機能を使用することはできません。これには、割り込み、シャドウレジスタ、IYレジスタに関するすべてが含まれます。IYレジスタは特別ですが、編集することは許可されていませんが、それを読み取ることは(常に$5C3Aです)そしてそれからインデックスを付けることはできます。これは、Sinclairがシステム変数と呼ぶもの、つまり私たちが定期的に読み書きすることになる現在のシステム状態に関するデータのコレクションのベースアドレスを保持しています。これらの変数の場所は、ROMよりも互換性のないバリアント間でより一貫性があります。私は最初のプロジェクトを作成したときにこれに大きく依存しました。ROM自体はこれに対してかなりカジュアルであることが判明しており、しばしばシステム変数をアドレスで直接参照しますが、必要に応じてそれらにアクセスするためにIYからインデックスを付けることもあります。インデックス操作はより高価ですが、より柔軟です。そのため、ベースアドレスが正確にわかっているがインデックスレジスタもあるこのようなユースケースでは、絶対アドレスの使用とインデックスアクセスとの間で切り替えることになります。ここでは、すべてのシステム変数アクセスがIYを経由するようにコードを書きますが、これは一般的に行われていませんでした。(実際、私自身もSpectrumプラットフォームガイドでは行っていません)。 テキストの出力 BASICツアーで見たように、Spectrumは画面をメインディスプレイ用の22行の上部ウィンドウと、入力およびステータスメッセージ用の2行の下部ウィンドウに分割しています。これはBASICのアーティファクトではありません。この分割は機械語レベルでも存在します。上部ウィンドウにテキストを出力するには、システム変数TVFLAG(IY+2)に0を書き込むことで、出力ルーチンにテキスト出力をそこに指示するように適切に設定する必要があります。これが完了したら、アドレス$10にあるROMルーチンを呼び出して、Aレジスタの文字を出力できます。SpectrumはASCIIを使用するため、通常のテキストは私たちにとって非常に馴染み深いものになるでしょう。これにより、Hello Worldは非常に簡単になります。 org $7000 ld (iy+2),0 ; upper screenに書き込む ld hl,msg lp: ld a,(hl) inc hl or a ret z rst $10 jr lp msg: db "Hello, world!",13,0 私は通常、$7000をオリジンアドレスとして使用します。なぜなら、それは十分深いからです。