cocolog:78972266
ファミコン(NES)で BG を VBlank 中を見計らって更新してるのに、なぜか「ずれる」というか「ちらつく」。ほんの1バイトでも $2006 $2007 に書いたらアウト。 (JRF 1981)
JRF 2014年2月16日 (日)
……。
ということで、メインの内容は以上で、ここからは近況的なことを。
電子金融がらみのアイデアがあって、ファミコンのアセンブラのプログラミングを初めた。
参考としてはいろいろググって読んでるが、「基本」として↓。
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
…と思ったら、VBlank を待つため $2002 を読むのだが、そのときスクロールの値が変わるという仕様らしく、その後 $2005 にスクロールの値を設定することで解決した。
あと、$2002 を読むだけでなく $2006 とか PPU を使えば、同じことが起こるのか、やっぱり操作後ずれるので、スクロール値の書き込みをそこかしこの処理に挟んだ。
JRF2014年2月16日5354