FrontPage  Index  Search  Changes  Login

mapper hack

vrc7 にあったときの記事。書いてた当時と違って利用価値がない。

mapper hack 補足

charcter RAM bank 0-7 の電源投入後の初期値はすべて page0。UNROM 変換時は初期化する必要がある。特に理由がない限り bank n = page n でよい。

NROM → VRC7

NROM → UNROM でもやることはあまり代わりがないと思うが一例として。

Program ROM page layout

page
0 charcter data translate program
1 未使用
2 未使用
3 charcter ROM data
4 Program ROM $8000-$9fff
5 Program ROM $a000-$bfff
6 Program ROM $c000-$dfff
fix Program ROM $e000-$ffff
  • バイナリファイルのつなぎ合わせの手間も考えて、追加プログラム→キャラクタROM→プログラムROMとしたほうがよい。
  • 追加プログラムは固定バンクに空きがあればわざわざ bank を1つ作らなくてもよい。(今回のプログラムは空きがなかった)

reset program hack

ベクタをほげって、元のプログラムより先にキャラクタデータを転送してしまう。

	org	$ffd8
reset:
	sei
	cld
;stop NMI
	lda	#$18
	sta	$2000
;転送命令bank set
	lda	#page_trans
	sta	cpubank_8000
	jsr	charcter_init
;program bank init
	ldy	#page_program
	sty	cpubank_8000
	iny	
	sty	cpubank_a000
	iny	
	sty	cpubank_c000
;通常命令に戻る
	jmp	$8057
  • sta $2000 の部分が stop NMI とだけ書いてあるけど、VRAM autoincrement = 1 も結構重要。
  • 転送が終わったら、元のプログラムと同じ構成にしてから戻す。
  • jsr してるけどスタックポインタを初期化してない... あとで直そう。

charcter bank init

charcter_init:
;screen off
	lda	#0
	sta	$2001
;set vertical scroll
	sta	$e000
;charcter RAM bank init
	ldy	#0
	sty	ppubank_0000
	iny
	sty	ppubank_0400
	iny
	sty	ppubank_0800
	iny
	sty	ppubank_0c00
	iny
	sty	ppubank_1000
	iny
	sty	ppubank_1400
	iny
	sty	ppubank_1800
	iny
	sty	ppubank_1c00
  • *(0x2001) = 0 はかなり重要で、これをいれないとリセット時に PPU が動いているものだから、VRAM のバス競合が起きてデータが正しく転送されない。必ずいれること。
  • scroll mirroring と追加 Program RAM の使用の可否を設定する。RAM のほうは VS 基板じゃないとつかわんと思う。
  • UNROM の場合は charcter RAM bank 設定がいらないが VRC7 は必須。

charcter data translate

;charcter ROM data map to $a000-$bfff
	lda	#page_charcter
	sta	cpubank_a000
;charcter ROM size $2000 set
	lda	#0
	sta	<$00
	ldy	#$20
	sty	<$01
;PPU pointer set 0
;	lda	#0
	ldy	$2002
	sta	$2006
	sta	$2006
  • キャラクタ転送用バンクとキャラクタデータバンクを同時に使えるのは可変バンクが2つ以上あるからできるわけであって、UNROM だと前者を固定エリアにいれないといけない。
  • $2006 の設定の前に、順番が逆転しないように lda $2002 で順番を初期化する
;charcter ROM pointer $a000 set
;	lda	#0
	sta	<$02
	lda	#$a0
	sta	<$03
;translate charcter data to PPU memory
	ldy	#0
trans_next:
	lda	($02),y
	sta	$2007
;index lowbyte increment, index carryup?
	iny
	bne	trans_next
;index highbyte increment, translate finish?
	inc	<$03
	dec	<$01
	bne	trans_next
	rts
  • lda ($02),y の次は iny にしたが inc <$02 でもよい。前者のが 1 byte 命令だから早いと思う。
  • $2006 は big endian, indirect addressing は little endian なのに注意。

UNROM → VRC7

UNROM はキャラクタが RAM なのでバンク切り替えだけ直せばよい。MMC1 も同様。

Program ROM page layout

0 Program ROM 0x0000-
1 Program ROM 0x2000-
..略
0x0e Program ROM 0x1c000-
末尾 Program ROM 0x1e000-

UNROM では CPU memory $c000-$dfff は ROM 0x1c000- に初期化で充てられていることに注意。

reset program hack

reset アドレスが $c000-$dfff にあることが多いので前回同様、ベクタを固定領域にほげって、NMI 停止 → vblank 待ち。

	org	$fffc
	adr	reset
	
	org	empty_area
reset:
	cld
	sei
vblank0:
	lda	$2002
	bpl	vblank0
vblank1:
	lda	$2002
	bpl	vblank1
bank_init:
;programbank init
	lda	#$e
	sta	cpubank_c000
;charcterbank init
	ldy	#0
	sty	ppubank_0000
	iny
(以下略)

program bank change

UNROM の場合は $8000-$ffff のどこを write してもいいわけだけど、 $8000 しか使わないよなと思ったらこんなんだった。

;C7F1: A8            tay  
;C7F2: B9 D0 FF      lda  $FFD0,y
;C7F5: 99 D0 FF      sta  $FFD0,y
;C7F8: A4 10         ldy  $10
  • この手の命令は1,2カ所しかないと思うがデバッガで write を見張ってすべて調査した方がよい。
  • $FFD0 のデータは 0,1,2,3... と y の値と同じなんだが...
page_map:
	byt	0,2,4,6
	byt	8,$a,$c,$e
bank_set:
	lda	page_map,y
	sta	cpubank_8000
	tay
	iny
	sty	cpubank_a000
	rts

こんな形に固定エリア上でひとまとめにするとよい。想定の sta $8000 を下記のつもりにするつもりだったのにぃ。

	asl	a
	tay
	sty	cpubank_8000
	iny
	sty	cpubank_a000
	rts
Last modified:2009/02/20 14:08:45
Keyword(s):
References: