X68000でスペースハリアーの地面と天井の再現方法を考えてみた

## 0.はじめに

5chのX68000Zスレに書き込んだ内容を修正・加筆しました。
昔X68000実機のアセンブラでいろいろ記述しましたが、久しぶりで68000命令サイクル(実行時間)等をかなり忘れています。
差分による高速描画を考えましたが、計算するとかなり時間がかかり、この方法だけでは実用化は厳しそうです。

2023/01/29追記：
16色カラーでパレットをラスターごとに変更というのも考えましたが、やはり地平線の上下移動をさせるパターンが思いつかず、断念。

## 1.前提

・地面と天井の色は市松模様(2色)でなく4色(1、2面は4色、3面は3色に見える)
・1ラインあたり2色
・地平線は上下する
・後述の説明の簡素化のため、地面は最大120ライン(ハリアーが一番上の時)、天井は最大200ライン(ハリアーが地面を走っている時)とする(正確な値は知らない)

## 2.X68000のハードウェア機能(ソフトウェア制御込み)

・割り込み処理でラスタースクロール可能(水平帰線期間にスクロールレジスタのX座標を書き換える)
・グラフィック画面ではY座標の伸縮は不可能

## 3.後述の複数の案の共通部

・グラフィック画面を使用する
・256x256 16色モード(VRAMは16ビットのうち下位4ビットが有効)
・~~メモリ→メモリ(move.w (An)+,(An)+)は12サイクル、レジスタ→メモリ(move.w Dn,(An)+)は8サイクルで、レジスタ→メモリのほうが速いので、そちらを使用する~~
・1ワード(2バイト、move.w Dn,(An)+)、1ロングワード(4バイト、move.l Dn,(An)+)がそれぞれ16、20サイクルのため、2ワード32サイクルで書き込むより1ロングワード20サイクルで書き込んだほうが速い
・1サイクルは10MHz動作だと1/1千万秒＝0.1マイクロ秒
・1ライン2色で、1ロングワード(左右2ドット)まとめて書き込むため、2×2＝4通りの色の組み合わせのため、データレジスタを4つ使用する
・水平方向は決まった位置に四角を描画し、ラスタースクロールさせる

## 4. ソフト案1

説明簡略化のため、地面の説明をしています。

・レジスタ→メモリ処理を1ライン分(1ロングワード128個)並べる(20×128＝2560サイクル)
・それを120ライン分サブルーチンを用意する
・水平線が上下するのに合わせて、上のサブルーチンの一部または全部を呼んで描画する

天井もまとめると、200ライン分のサブルーチンを用意して、地面と共用します。
同じパターンのラインもあるので、実際はもっとパターンが少ない。

CPU処理はかなりあり遅い。
地面＋天井－地平線1ライン＝255ラインとして、2560×255＝652800サイクル。0.06528秒。4/60秒強。
地面と天井の描画だけで4/60秒強かかり、使い物にならない。

## 5. ソフト案2

・案1をもとに差分描画にする。
・どのラインに120パターンのどれを描画したのか覚えておく
・パターン毎に前後2パターンへの差分描画ルーチンを持っておく。
  例：パターン10→パターン8,9,11,12
  ※パターンが大きく変わることはないため、前後2パターン(もしくは3パターン程度)だけ持つ
・400～500通りくらい用意すれば大丈夫そう

天井もまとめると、800通りくらい用意すれば大丈夫そう。

・1ライン差分描画処理は、
  - 同じ色の組み合わせパターンへの変更で、
    - 変更なし＝0サイクル
    - 変更あり＝(move.l 20サイクル＋アドレスadd 8サイクル)×20回と仮定して560サイクル
  - 違う色の組み合わせパターンへの変更で、1ライン全て描画(前出の2560サイクル)
・地面と天井合わせて255ラインが、1ライン全て描画55ライン、変更あり100ライン、変更なし100ラインと仮定すると、
  2560×55＋560×100＝196800
  0.01968秒(1/60秒強)

かなり速くなるかと思ったけど、計算してみると、地面と天井の描画だけでこの時間がかかるのは厳しい。

## 6.自分の書き込み

X68000Zスレッド  Part2 
https://kizuna.5ch.net/test/read.cgi/i4004/1669805733/

968 自分：ナイコンさん (ﾜｯﾁｮｲ db03-4Ar3)[sage] 投稿日：2022/12/25(日) 14:45:25.84 ID:AEYlFPtR0 [2/4]
まあたしかに>>938の
>地面はカラクリが不明だっただけで性能的に難しかったわけじゃないからな

は前半も後半も何を言っているのかさっぱりわからんが。

68000のコードあたりの実行時間を忘れているけれども、
たぶん1ロングワード(4バイト)のコピーは、
メモリ→メモリコピーよりもレジスタ→メモリコピーのほうが速かったと思う。

で、案1：
1ライン分、レジスタ(市松模様2色分で2レジスタ使用)→メモリコピーを並べるのを
100ライン分サブルーチンを用意して、
水平線が上下するのに合わせて例えば120ライン描画するのなら上のサブルーチンのうち
20ライン×2は同じサブルーチンを呼んで描画する。
X側はラスタースクロール。
たぶんこれでもCPU処理はかなりあり遅そう。

案2：
案1をもとに差分描画にする。
詳細までは詰めれていない。

969 自分：ナイコンさん (ﾜｯﾁｮｲ db03-4Ar3)[sage] 投稿日：2022/12/25(日) 14:46:18.46 ID:AEYlFPtR0 [3/4]
あ、ロングワード使ったらレジスタ2個じゃあかんかった。

978 名前：968 (ﾜｯﾁｮｲ db03-4Ar3)[sage] 投稿日：2022/12/25(日) 16:04:42.49 ID:AEYlFPtR0 [4/4]
案2続き：
どのラインに100パターンのどれを描画したのか覚えておいて、
パターン1→2,3,4くらいの差分描画を全部サブルーチンで持っておく。
他のラインも同様。
400～500通りくらい用意すれば大丈夫そう。
かなり速く描画できそう。

ロングワードについては2×2で4レジスタ使うか、X座標奇数で色が変わるところだけワードで書くか。

## 7.参考1

X68000
https://www.wizforest.com/OldGood/X68k/#grph
(証明書が切れている警告が出ます)

MC68000 Instructions timing
https://oldwww.nvg.ntnu.no/amiga/MC680x0_Sections/mc68000timing.HTML

## 8. 参考2


X68000Zスレッド  Part2 
https://kizuna.5ch.net/test/read.cgi/i4004/1669805733/

943 名前：ナイコンさん (ﾃﾃﾝﾃﾝﾃﾝ MM97-k8Ox)[sage] 投稿日：2022/12/24(土) 23:06:12.28 ID:amIdiDPoM
942
68で地表の再現は難しいと思うぞ
アーケード版は地面の模様が違うだけじゃなく実は視点の高さで地面が伸び縮みしてる
これを再現するにはライン毎にラスター割り込みでスクロールレジスタのY座標を書き換えるわけだが、
68のグラフィック画面は垂直表示期間中にスクロールレジスタのY座標を書き換えても反映されない(X座標は反映される)
BGなら反映されるのでY方向の伸縮が再現できるが68スペハリの場合パターンエリアが既にギチギチで余裕がない
更にプライオリティの関係で敵キャラを描画しているグラフィック画面より奥にBGを配置することができない
もしBGで地面を表示して奥に持っていったらスプライトで表示している自機や自弾、敵弾までグラフィックで描画してる敵キャラや爆発より奥へいってしまう