40

画面の境界領域にスプライトを表示するクールな C64 デモを見たことがあります。それは不可能です。どうにかしてグラフィックチップをだますことができたと思います。彼らはどのように正確にそれをしましたか?

4

6 に答える 6

33

はい、アセンブラが必要です。割り込みタイミングのトリックです。VIC は境界線にスプライトを表示できますが、フレームはスプライトを隠しているだけなので、スプライトはその後ろにスライドできます。VIC によって表示されるスキャン ラインに接続されます。下/上の境界線の場合は非常に簡単です:

  • 割り込みをプログラムし、特定のスキャン ライン、7 ピクセル、または下の境界線の前にそのようなもので開始するように同期します。
  • VIC にレジスタを設定して境界を小さくします。(それができるレジスターがあります。)
  • VIC は現在、境界線がすでに始まっていると考えており、それをペイントし始めていません。
  • -> 下部に境界線はありません。
  • 元の境界に戻すには、実際の境界の後に別の割り込みをプログラムします。

左/右の境界線のスプライトの場合、スキャン ラインごとにプロセスを繰り返す必要があるため、より複雑になります。

  • 特定のスキャンラインで開始するように同期された割り込みをプログラムします。
  • 次に、右の境界線の 7 ピクセル手前になるまで、いくつかの NOP を実行します。
  • VIC にレジスタを設定して境界を小さくします。
  • →右側に枠なし。
  • 実際の境界に到達するまでいくつかの NOP を実行し、レジスタを元の値に戻します。
  • ステップ 2 まで NOP を繰り返します。

問題は、これらすべての NOP がビジー状態で待機していて、ユーザーが持っているサイクルを盗むことです。

下の境界線にあるスプライト スクローラーからコードを見つけることができました。これがコードです。(これはいくつかのデモからリッピングされました。)

C198  78        SEI
C199  20 2E C1  JSR C12E     # clear sprite area
C19C  20 48 C1  JSR C148     # init VIC
C19F  A9 BF     LDA #BF      # set up IRQ in C1BF
C1A1  A2 C1     LDX #C1
C1A3  8D 14 03  STA 0314
C1A6  8E 15 03  STX 0315
C1A9  A9 1B     LDA #1B
C1AB  8D 11 D0  STA D011
C1AE  A9 F7     LDA #F7
C1B0  8D 12 D0  STA D012
C1B3  A9 01     LDA #01
C1B5  8D 1A D0  STA D01A
C1B8  A9 7F     LDA #7F
C1BA  8D 0D DC  STA DC0D
C1BD  58        CLI
C1BE  60        RTS

----------------------------------
# init VIC
C148  A2 00     LDX #00
C14A  BD 88 C1  LDA C188,X
C14D  9D 00 D0  STA D000,X   # set first 16 values from table
C150  E8        INX
C151  E0 10     CPX #10
C153  D0 F5     BNE C14A
C155  A9 FF     LDA #FF
C157  8D 15 D0  STA D015
C15A  A9 00     LDA #00
C15C  8D 1C D0  STA D01C
C15F  A9 FF     LDA #FF
C161  8D 17 D0  STA D017
C164  8D 1D D0  STA D01D
C167  A9 C0     LDA #C0
C169  8D 10 D0  STA D010
C16C  A9 F8     LDA #F8
C16E  A2 00     LDX #00
C170  9D F8 07  STA 07F8,X
C173  18        CLC
C174  69 01     ADC #01
C176  E8        INX
C177  E0 08     CPX #08
C179  D0 F5     BNE C170
C17B  A9 0E     LDA #0E
C17D  A2 00     LDX #00
C17F  9D 27 D0  STA D027,X
C182  E8        INX
C183  E0 08     CPX #08
C185  D0 F8     BNE C17F
C187  60        RTS

----------------------------------
# data set into VIC registers
C188  00 F7 30 F7 60 F7 90 F7
C190  C0 F7 F0 F7 20 F7 50 F7

----------------------------------
# main IRQ routine
C1BF  A2 08     LDX #08
C1C1  CA        DEX
C1C2  D0 FD     BNE C1C1
C1C4  A2 28     LDX #28      # 40 or so lines
C1C6  EA        NOP          # "timing"
C1C7  EA        NOP
C1C8  EA        NOP
C1C9  EA        NOP
C1CA  CE 16 D0  DEC D016     # fiddle register
C1CD  EE 16 D0  INC D016
C1D0  AC 12 D0  LDY D012
C1D3  88        DEY
C1D4  EA        NOP
C1D5  98        TYA
C1D6  29 07     AND #07
C1D8  09 18     ORA #18
C1DA  8D 11 D0  STA D011
C1DD  24 EA     BIT   EA
C1DF  EA        NOP
C1E0  EA        NOP
C1E1  CA        DEX
C1E2  10 E4     BPL C1C8     # repeat next line
C1E4  A9 1B     LDA #1B
C1E6  8D 11 D0  STA D011
C1E9  A9 01     LDA #01
C1EB  8D 19 D0  STA D019
C1EE  20 00 C0  JSR C000   # call main code
C1F1  4C 31 EA  JMP EA31   # finish IRQ
于 2009-09-25T14:18:04.687 に答える
10

それはすべてタイミングに依存していました。C64 には、画面の描画中に電子ビームの正確な垂直位置を照会する方法がありました。新しい行が始まると、数サイクル待つ必要があり (NOP 命令を使用してこれを計ることができます)、その後、スクリーンモード (および境界線幅) の設定を担当するビデオチップのハードウェアレジスタを設定する必要がありました。正確にタイミングを合わせ、スキャンラインごとにもう一度行うことで、サイドボーダー全体が消えました。

下の境界線も同様のトリックで消えました。垂直境界線が開始された正確なスキャンラインでも、そのフレームの下境界線を無効にするビデオモードを設定する必要がありました。

実際、このすべてをアセンブリで行う必要がありました。そうしないと、正確にタイミングを合わせることができません。

余談ですが、サイドボーダーのトリックは 1001 Crew (オランダのグループ) の功績によるものだと思います。誰が最初のボトム ボーダー トリックを成功させたのかわかりません。

于 2009-09-25T14:16:38.670 に答える
9

C64で境界線を開くトピックに関する優れたチュートリアルについては、 C = HackingIssue6にあるPasiOjalaの優れた記事を確認してください。

技術的になりすぎることなく、このトリックではVICチップの機能を使用して、テキスト/グラフィックスの25/24行と40/38列を切り替えることができます。この切り替えを適切なタイミングで行うことで、VICをだまして考えさせることができます。実際にはそうではないのに、すでに境界線をオンにしています。コード例を使用したより詳細な説明については、上記の記事を確認してください。

于 2010-04-11T15:44:07.027 に答える
1

それはずっと前のことです。

モニターの周波数に依存する解決策があったことは知っています。

CRT では、現在のピクセルが通常の画面の外にある場合でも認識されます。これで光線を操作できます。

私のジャンクパイルのどこかに、C64 の本がいくつかあるはずです。

オフトピックですが、VIC20 (C64 の前身) のグラフィックは楽しかったです。各ピクセルを操作する方法はありませんでしたが、既存の文字を変更することはできました。したがって、0 から ... までのすべての文字で画面を埋め、文字を変更して画面にピクセルを設定しました。;-)。

于 2009-09-25T14:16:33.277 に答える
-1

タイミングが鍵でした。画像は、CRT のビームが左から右に移動するにつれて、オーバースキャン (境界) の色を変更することによって、境界に作成されました。画像を生成するには、垂直リフレッシュと水平リフレッシュの 2 つのタイミング信号が必要です。水平方向と垂直方向のリフレッシュが発生するタイミングを検出することで、一連のアセンブラー命令を開始して境界線の色を変更し、画像を生成できます。ボーダー ピクセルあたりの CPU クロック ティックの数を計算し、それを使用して適切なポイントでボーダーの色を変更するコードを作成する必要があります。

CPU のオーバーヘッドが大きすぎて、ユーザー入力とゲームの状態を処理する時間がないため、ゲームの作成に関してはあまりうまく機能しません。

于 2009-09-25T14:37:34.663 に答える