« 前のひとこと | トップページ | 次のひとこと »

cocolog:78972266

ファミコン(NES)で BG を VBlank 中を見計らって更新してるのに、なぜか「ずれる」というか「ちらつく」。ほんの1バイトでも $2006 $2007 に書いたらアウト。 (JRF 1981)

JRF 2014年2月16日 (日)

…と思ったら、VBlank を待つため $2002 を読むのだが、そのときスクロールの値が変わるという仕様らしく、その後 $2005 にスクロールの値を設定することで解決した。

あと、$2002 を読むだけでなく $2006 とか PPU を使えば、同じことが起こるのか、やっぱり操作後ずれるので、スクロール値の書き込みをそこかしこの処理に挟んだ。

JRF2014年2月16日5354

……。

ということで、メインの内容は以上で、ここからは近況的なことを。

電子金融がらみのアイデアがあって、ファミコンのアセンブラのプログラミングを初めた。

参考としてはいろいろググって読んでるが、「基本」として↓。

JRF2014年2月16日1104

《MagicKit Homepage - NESASM》
http://www.magicengine.com/mkit/

《NES研究室》
http://hp.vector.co.jp/authors/VA042397/nes/index.html

《ギコ猫でもわかるファミコンプログラミング》
http://gikofami.fc2web.com/

http://gikofami.fc2web.com/index.html

JRF2014年2月16日2308

……。

nesasm は、エラーが出ても他のコンパイラとかみたく、エラーコードで終了しないため、 Makefile のとき不便。

確か、シェル(csh?)には出力の最後の行を示す特殊変数があったはず…と調べるもどうもない。あれ?記憶違い?パイプとかで何とかするのがセオリーなの?

なんか面倒になって、上の MagicKit から落としてきたソースをちょっといじってエラーコードはくように改造した。

JRF2014年2月16日3322

ソースの zip は dos 用らしく unzip するとファイル名が大文字になるから、それをまず全部、小文字にリネーム。

次に src/as/main.c を書き換える。patch は↓。

JRF2014年2月16日0232

<pre>
--- src/as/main.c~ 2000-09-09 19:04:44.000000000 +0900
+++ src/as/main.c 2014-02-16 16:16:57.404721900 +0900
@@ -495,6 +495,9 @@
show_seg_usage();

/* ok */
+ if (errcnt) {
+ exit(1);
+ }
return(0);
}
</pre>

JRF2014年2月16日2308

……。

アセンブラは↓で書いたように、趣味で大昔に使ってたことはあるが、Z80 とか 8086 系で、モトローラ系 6502 ははじめて。

《アセンブラで JIS から SJIS に変換するとき DAA が使える?》
http://jrf.cocolog-nifty.com/software/2010/05/post-3.html

JRF2014年2月16日6536

レジスタが3つしかないとか衝撃的。ZeroPage がむしろ RISC っぽい感じのレジスタなんだね。バグ出しまくりながらもなんとかやってる。

ld で Z (ゼロフラグ)が変化するとかアリ?知らずに作っててあとから、beq bne の前に ld してないか、チェックしたりした。でも、書いてるとむしろこのほうが合理的で、store では変化しないあたり設計者のセンスを感じる。

JRF2014年2月16日2495

ただ、nesasm の機能の問題として、and のテスト版の bit で即値が使えないのに、nesasm は通してしまって、なかなか気づかなかったり、マクロや関数が使えてそこはすごい凝ってるのに EQU (=) で文字列が指定できなかったり…と泣きどころが多い。

JRF2014年2月16日9193

……。

計画としては、JavaScript のファミコンエミュレータから使う予定で、2P コントローラも使う。そして、ラッパーかませて、Web ページで文字列を入力すると、特定のコントローラ入力を行う…とか、したい。

すると、どうも選択肢が限られてくる感じで、JSNES しかなさそう。CycloaJS とかサンプルに『ダンガンロンパ』(参:[cocolog:74607467])に出てきた Alter Ego って名前のゲーム出してたりして興味はあるんだけど…。(この Alter Ego は別に人工知能とかじゃないけどね。)

JRF2014年2月16日2526

《JSでファミコンエミュレータ書いてみた:CycloaJS | ψ(プサイ)の興味関心空間》
http://ledyba.org/2012/08/22195829.php

《JSNES: A JavaScript NES emulator - Ben Firshman》
http://fir.sh/projects/jsnes/

ちなみに JSNES は SNES のエミュレータではない。まぎらわしい!

JRF2014年2月16日7134

……。

おっと!上の patch の元バージョンを書いとかないと…。2000年に出た最終バージョンの 2.51、 ↓。

http://www.magicengine.com/mkit/mkit251_linux.zip

JRF2014年2月16日0001

……。

Tips なのか、まだ私のやり方がおかしいのかわからないんだけど…。

BG とスプライトがどうしても 1 ドットずれる。Scroll を X,Y とも 0 を設定してそうなる。上のバグと関係なしに。(上の対策をしないともっとずれる。)いちおう↓にはそれらしいことが書いてる。

《Enri's Home PAGE (ファミリーコンピューターPPU)》
http://www43.tok2.com/home/cmpslv/Famic/Famppu.htm

JRF2014年2月17日2664


OBJ(スプライト)RAM
  OBJ(スプライト)を表示する為のRAMです
  ポートからアドレスを指定、データを書き込む方法とVBLANKの割り込み内でDMA転送する2つの方法があります
   $00:OBJ$00 H    (Y座標 1ドット下にずれます)
   $01:OBJ$00 CHR  (キャラクタ)
   $02:OBJ$00 ATTR (アトリビュート)
   $03:OBJ$00 V    (X座標)

JRF2014年2月17日1408

私は BG 面をむしろ 240-1 だけずらしてる。このために、バッテリバックアップも使った上で、垂直ミラーリングの .inesmir 3 を指定。でも、スプライトを全部1ドットずらすほうが素直なのかな?

JRF2014年2月17日5182

……。

↑はスプライトをずらすほうに変えた。

で、最初の画面ゆれの問題。今のところの解決策は↓みたいなマクロを使って説明すると…。

JRF2014年2月18日6473

<pre>
WaitVBlank .macro
L\@:
lda $2002
bpl L\@
.endm

WaitVScan .macro
L\@:
lda $2002
bmi L\@
.endm

SetScroll .macro
lda <ScrollX
sta $2005
lda <ScrollY
sta $2005
.endm
</pre>

JRF2014年2月18日4792

「画面揺れ」が起きるときは基本、途中でスキャンライン描画(VScan)中になってるってことだから、ウェイトが必要。

で、スクロール $2005 の設定は「ラスタスクロール」が可能なことからも知られるように、PPU の操作であっても例外的に VScan 中に問題なくできる。だから、WaitVScan 直後に SetScroll するとピタっと合う。

VScan 中に書いたら、その段階でどうもスクロールがずれるようなので、書くときは直後に WaitVBlank する。

(NMI 割り込みは禁止しておく。)

JRF2014年2月18日6161

で、一通り書いたあと、やっぱり PPU をいじったわけだから、(WaitVScan のあと?)SetScroll しとかないといけない。

……といった感じで、とりあえず、うまくいってそう。

JRF2014年2月18日0569

……。

割り込みの話が出たついでなので、6502 の話ももう少し。

sbc や cmp のキャリー(ボロー)の付き方が Z80 とかと違ってるのは、まだまだ、とまどう。

割り込みは、レジスタ退避は(フラグ以外)まったくないらしく、3つしかないレジスタも自分でスタックに積まないとダメらしい。

そして、VSync (VBlank) の 1/60 秒のタイミングって、かなり長い…って感覚があったんだけど、6502 だと全々余祐ないみたい。上の Wait ガンガン挟まないとダメだった。orz

JRF2014年2月18日4394

割り込み禁止して VBlank を待ってんだから、タイミングはいつもいっしょだろう…と思ったら、画面が揺れたり揺れなかったりする。スプライト DMA とかがフックしてるということなんだろうか?

エミュレータは今のところ、VNES を使ってる。メモリビューアぐらいないとデバッグできないから。

JRF2014年2月18日8112

<pre>
Debug .macro
if \?1 = 1
if '\1' != 'a'
t\1a
endif
else
lda \1
endif
sta \2
.endm
</pre>

JRF2014年2月18日6953

↑ってな感じのマクロを使ってる。

<pre>

Debug [SRC], [DEST]

</pre>

…とすると、要は [SRC] を [DEST] にストアするだけなんだけど、[DEST] を <15 とかにすればメモリビューアでチェックしやすい。で、デバッグが終ったら、Debug という文字列を検索して消せばいい。(これが Store という名前にしない理由。)

JRF2014年2月18日4453

修正 「VScan 中に書いたら」→「VScan 中に $2006 $2007 に書いたら」。
修正 「書くときは直後に」→「書く処理をするなら SetScroll のあとに」。

JRF2014年2月18日6730

« 前のひとこと | トップページ | 次のひとこと »

トラックバック


トラックバックのポリシー

他サイトなどからこの記事に自薦された関連記事(トラックバック)はまだありません。