【 Making「回転」 】 |
---|
Home | PC-6001mkII | Program | etc |
関連リンク | ●回転 ●回転 mkII |
---|
更新日:2006/07/30 作成日:2006/07/30 このページでは、mkII版の「回転mkII」および初代機版の「回転」で実際に行った処理内容を紹介します。 |
回転表示の処理概要 | ||||||
---|---|---|---|---|---|---|
回転表示の処理について、まずは P6に特化しないところから説明します。 基本的な考え方は、仮想画面に表示画面を回転して重ねた時に表示画面の各ドットの位置に仮想画面のどの色があるかを地道に計算して表示するといったものです。以下、概要を説明します。
「仮想画面に表示画面を回転させて重ねる」というと、SIN,COSの三角関数や行列を使った座標変換が入るんじゃないか、などなにかと複雑な処理を連想させますが、ここでは極力シンプルに掛け算と足し算のみで実現して行きます。 最低限必要な情報は、以下の3つのみです。
このうち、a.については、その場で回転させる限りでは全く値が変わらないので適当な固定値を設定すれば良く、また b.とc.はあらかじめ回転方向ごとのデータを用意しておけば、回転の方向から単純に求まります。 上記の3つの値さえわかれば、あとは以下のような手順で処理を行う事ができます。(図中の赤い星部分が回転の基準点とします)
|
決め事 |
---|
処理を行う前に、色々決めないとダメな項目があります。回転の細かさや数値の精度,画面サイズなどがこれにあたります。これらを少しの根拠を元にフィーリングで決めていきます。 回転方向数 最終的に1キャラクタ=1ドットのグラフィックの荒さもあるので、方向数は可能な限り押さえます。マシン語で処理するには2の階乗が都合が良いので、16方向か32方向辺りにします。 今回はちょっと背伸びして32方向で処理を考えます。 数値の精度 回転処理では、仮想画面上の座標や回転方向のデータに小数点未満の値を使用します。この精度は高い方が良いのですが、一方で座標等の値で3バイト以上使うと処理の難易度が各段に増すし、その分遅くなるしで良い事がないので、意地でも2バイトに抑えるよう考えます。 ここでは、整数部分と小数部分は明確に分けた方が処理の都合が良いだろうという憶測の元、整数部分1バイト,小数部分を残りの1バイトに決定します。 仮想画面のサイズ 仮想画面のサイズは極端な大きさでなければ良いのですが、それだと決まらないのである程度の縛りを入れてその中で選択することにします。 まず、縛りとしても処理としても都合の良い「2の階乗ルール」を入れます。ただあまり小さすぎるのもなんなので、16以上から候補に入れておきます。 次に現実的な考慮点として「仮想画面がメモリに入りきる事」があります。BASICも使う事を考えると20KBも確保できれば良い方でしょう。各ドットの色情報を1バイトで表現するとして、縦横141ドット以内までの制限となります。 この時点で、縦横のサイズが16, 32, 64, 128の4つまで絞り込めました。あとはエイヤで決めます(^_^;)。今回は64x64(4KB)に設定します。 表示画面のサイズ 表示画面については初めから全画面で試そうと思っていたので40x20(mkIIの場合)にあっさり決まりました。表示画面で回転の中心となる点は、画面の中心よりも若干下に設定するようにしました。 |
回転方向のデータ |
---|
もう少し前置きが続きます(^^;)。 一般的に、方向を表すには SINや COSなどの三角関数を使用します。これをリアルタイムで計算していたら流石に処理が重すぎるので、あらかじめ各方向の移動量をデータ化しておきます。 SINや COSの範囲が -1〜1の範囲なので、基本はこれに沿ってデータ化して行きます。ここでは、-1〜1を下図のように -127〜127の255段階に変換したデータを 32方向分作成します。 これは(仮想画面上の)X方向のみなので、Y方向に関しても同様に作成します。こうして、32方向分の移動量データが揃いました...と書きたいところですが、実はまだ足りないのです。 今回はドットをキャラクタで表現しているのですが、ここで問題になるのが「ドットの縦横の長さが同じではない」ことです。縦方向の移動量と横方向の移動量が異なるので、データも縦方向用と横方向用で分ける必要があります。 この時の基準となる縦横比ですが、家庭用TVの縦:横=3:4で画面内のキャラクタ数が縦:横=20:40(初代機では16:32)なので、ドット(キャラクタ)あたりの縦横比3÷20:4÷40 = 3:2 となります。という事で、横方向用のデータは縦方向用の2/3のサイズで作成します。 これでようやくデータが揃いました。ちなみにその後の試行錯誤により、データは以下の順序となっています。 (縦X方向,縦Y方向,90度回転させた横X方向,90度回転させた横Y方向) x 32 |
マシン語処理 | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
前置きが長くなりましたが、ようやく処理の記述に入ります。といっても、マシン語の処理概要は既に上で書いた通りなので、ここでは処理時間を少しでも短くするために行った事を書きとめておきます。 マシン語に限りませんが、プログラムの実行時間を短くするには、繰り返し実行される回数が多い部分を高速化するのがポイントとなります。例えば、100回実行される部分を 0.1msだけでも縮めた方が、1回だけ実行する部分を 1ms縮めるより全体的には速くなるという理屈です。 ここで、もう一度前の図に登場してもらいます。
この図で使用回数の一番多い部分は5番、すなわち仮想画面の色を表示画面に反映し、仮想画面上の座標を右へ1つずらす処理である事がわかると思います。
実行時のステート数を見れば一目瞭然ですが、高速化にこだわるならば4番の方法となります。つまり、レジスタ間だけで値の受け渡しを行えば高速になるのです。 という事で、できるだけレジスタ内だけで解決するよう、処理内で使用する値を振り分けて行きます 処理内で使用している値は、以下のようにたくさんあります。
このため、今回は俗に言う「裏レジスタ」をフル活用しています。裏レジスタは「表」のレジスタA,B,C,D,E,H,Lと対になるもの(A',B' のようにダッシュをつけたレジスタ名で区別する)で、EXX や EX AF AF'といった命令でこの裏レジスタを「表」にする事で初めて使用できます。(この間は「表」だったレジスタは「裏」になり使えない状態になる) 表と裏の概念がややこしいですが、これでレジスタが14個分使用できる訳です。(といってもギリギリですが) ちなみにレジスタはこの他にも IX, IY, F, SP, PC がありますが、IX, IYレジスタは速度の面で使いどころが分からないし、F, SP, PC は通常システムが使う部分なので値の格納目的では使ってません。 マシン語処理の説明をするのは、やっぱり難しいですね。あとは、マシン語のソースをそのまま載せておきます(手抜きですが)。注釈の多さが、作成中の試行錯誤ぶりや混乱ぶりを物語っていると思います。 マシン語部分ソース(mkII用) マシン語部分ソース(初代機用) |
以下、余談 |
---|
|
− | PC-6001mkII | − |