The problem when writing 0 to $C000 in the real MMC3

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
N·K
Posts: 5
Joined: Mon May 11, 2020 2:45 am
Location: Japan

The problem when writing 0 to $C000 in the real MMC3

Post by N·K » Mon Nov 30, 2020 8:40 pm

Hello.

I recently produced a test ROM to learn the IRQ interrupt for MMC3.

In this ROM, I tried to make it possible to change the value to be written to $C000 from 0-255 with the up and down buttons, and to swap BG and sprite pattern table addresses with the B button.

It worked as expected when running it on Mesen and EverDriveN8, but when tested on an actual Sharp MMC3B and EEP-ROM, the interrupt did not work correctly when 0 was written to $C000.

Expected behavior
test_mesen.png
test_mesen.png (2.75 KiB) Viewed 3790 times

Actual behavior with Sharp MMC3B
test_sharpmmc3b.png
test_sharpmmc3b.png (5.98 KiB) Viewed 3790 times

I was wondering if this was due to a mistake in my code or another problem, so I posted this.

I'm using machine translation, so the sentence may be strange. Sorry.
Thanks in advance.

Code: Select all

	.inesprg 1
	.ineschr 1
	.inesmir 0
	.inesmap 4

	.bank	1
	.org	$f000

RESET:
	sei
	cld
	lda	#%01000000
	sta	$4017
	ldx	#$ff
	txs
	inx
	stx	$2000
	stx	$2001
	stx	$4010
	stx	$e000

.Vwait
	bit	$2002
	bpl	.Vwait
.Vwait2
	bit	$2002
	bpl	.Vwait2

	lda	#$e0		; Sprite clear
	sta	$4014

	lda	#$3f
	sta	$2006
	lda	#$00
	sta	$2006
	lda	#$0f
	sta	$2007		; BG color = $0f

	lda	#%10001000
	sta	<$00
	lda	#$03
	sta	<$01

	lda	#%00010000
	sta	$2001
	lda	#%10000000
	sta	$2000
	cli
.loop:
	jmp	.loop

;-------------------------------------------------------------------------------

NMI:
	lda	<$00
	sta	$2000		; Set PPUCTRL

	lda	#$18
	sta	$c000		; Set IRQ
	sta	$c001
	sta	$e000
	sta	$e001

	jsr	GetKey		; Get keystrokes

	; Processing in response to keystrokes.
	bit	<$21
	bvc	.sub
	lda	<$00
	eor	#%00011000
	sta	<$00
.sub
	lda	<$21
	lsr	A
	lsr	A
	lsr	A
	bcc	.sub2
	inc	<$01
.sub2
	lsr	A
	bcc	.sub3
	dec	<$01
.sub3
	lda	#$bf
	sta	<$02

	rti

;-------------------------------------------------------------------------------

IRQ:
	lda	#%00010001	; Draw gray line
	sta	$2001

	lda	<$01
	sta	$c000		; Set IRQ
	sta	$c001
	sta	$e000
	sta	$e001

	lda	<$02
	clc
	sbc	<$01	
	sta	<$02
	bcs	.end
	sta	$e000		; IRQ disable
.end
	lda	#%00010000	; End gray line
	sta	$2001

	rti

;-------------------------------------------------------------------------------

GetKey:
	lda	<$20
	pha
	lda	#$01
	sta	<$20
	sta	$4016
	lsr	A
	sta	$4016
.loop
	lda	$4016
	lsr	A
	rol	<$20
	bcc	.loop
	pla
	eor	<$20
	and	<$20
	sta	<$21
	rts

;-------------------------------------------------------------------------------

	.bank	1
	.org	$fffa

	.dw	NMI,RESET,IRQ

	.bank	2
	.org	$0000

	; --- CHR area ---
Attachments
testaaa.nes
(24.02 KiB) Downloaded 49 times

Drag
Posts: 1335
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: The problem when writing 0 to $C000 in the real MMC3

Post by Drag » Wed Dec 02, 2020 5:09 pm

There are two revisions of the MMC3:
Old revision = Write #$00 to $C000, IRQ is only once.
New revision = Write #$00 to $C000, IRQ is every scanline.

It sounds like the real MMC3B chip you're using is an "old revision" chip.

Here's the wiki page on it, it also says how to identify which MMC3B chip has which behavior.

User avatar
N·K
Posts: 5
Joined: Mon May 11, 2020 2:45 am
Location: Japan

Re: The problem when writing 0 to $C000 in the real MMC3

Post by N·K » Thu Dec 03, 2020 3:25 am

Thanks for the reply!
Drag wrote:
Wed Dec 02, 2020 5:09 pm
There are two revisions of the MMC3:
Old revision = Write #$00 to $C000, IRQ is only once.
New revision = Write #$00 to $C000, IRQ is every scanline.

It sounds like the real MMC3B chip you're using is an "old revision" chip.

Here's the wiki page on it, it also says how to identify which MMC3B chip has which behavior.
To check my MMC3B revision, I tried "mmc3_test" on the emulator test page of the wiki. As a result, it was determined to be a New revision... Hmm.

For reference, here is a picture of the MMC3B used.
IMG_0005_resize.jpg

Drag
Posts: 1335
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: The problem when writing 0 to $C000 in the real MMC3

Post by Drag » Thu Dec 03, 2020 1:06 pm

You're right, that should be a "new revision" MMC3. The code looks OK, so I'm not sure what's happening.

User avatar
N·K
Posts: 5
Joined: Mon May 11, 2020 2:45 am
Location: Japan

Re: The problem when writing 0 to $C000 in the real MMC3

Post by N·K » Fri Dec 04, 2020 7:40 pm

Resolved! It seems to be caused by trying to write to $c001 in succession on every scan line.
Taken from mmc3_test readme.txt

If $C001 is written, the counter clocked, then $C001 written again, on the next counter clock the counter will be ORed with $80 (revision B)/frozen (revision A) and neither decremented nor reloaded.
If $C001 is written again at this point, on the next counter clock it will be reloaded normally.
Eliminating the writing to $c001 in the IRQ now works properly!

Below is a modified test ROM.
Added a grid to BG and also allows you to toggle the presence or absence of writing to $c001 with the A button.

Code: Select all

	.inesprg 1
	.ineschr 1
	.inesmir 0
	.inesmap 4

	.bank	1
	.org	$e000

RESET:
	sei
	cld
	ldx	#%01000000
	stx	$4017
	ldx	#$ff
	txs
	inx
	stx	$2000
	stx	$2001
	stx	$4010
	stx	$e000

.Vwait	bit	$2002
	bpl	.Vwait
.Vwait2	bit	$2002
	bpl	.Vwait2

	lda	#$3f
	sta	$2006
	lda	#$00
	sta	$2006
	ldx	#$00
.loadPal
	lda	PaletteData,x
	sta	$2007
	inx
	cpx	#$20
	bne	.loadPal

	ldy	#$20
	sty	$2006
	ldy	#$00
	sty	$2006
	ldx	#$04
	lda	#$00
.loadBG
	sta	$2007
	iny
	bne	.loadBG
	dex
	bne	.loadBG

	lda	#$00		; Set scroll
	sta	$2005
	sta	$2005

	lda	#%00000000	; Set CHR bank
	sta	$8000
	lda	#$00
	sta	$8001
	lda	#%00000010
	sta	$8000
	lda	#$00
	sta	$8001

	lda	#%10001000
	sta	<$00
	lda	#$03
	sta	<$01
	lda	#$00
	sta	<$03

	lda	#%10000000
	sta	$2000
	cli

.loop	jmp	.loop

;-------------------------------------------------------------------------------

NMI:
	lda	<$00
	sta	$2000		; Set PPUCTRL
	lda	#%00001010
	sta	$2001		; Set PPUMASK

	lda	#$18
	sta	$c000		; Set IRQ
	sta	$c001
	sta	$e000
	sta	$e001

	jsr	GetKey		; Get keystrokes

	; Processing in response to keystrokes.
	bit	<$21
	bpl	.sub
	lda	<$03
	eor	#%10000000
	sta	<$03
.sub
	bvc	.sub2
	lda	<$00
	eor	#%00011000
	sta	<$00
.sub2
	lda	<$21
	lsr	A
	lsr	A
	lsr	A
	bcc	.sub3
	inc	<$01
.sub3
	lsr	A
	bcc	.sub4
	dec	<$01
.sub4
	lda	#$bf
	sta	<$02

	rti

;-------------------------------------------------------------------------------

IRQ:
	lda	#%00001011	; Draw 96px gray line
	sta	$2001

	ldx	#$05
.wait	dex
	bne	.wait

	lda	#%00001010	; End gray line
	sta	$2001

	lda	<$01
	sta	$c000		; Set IRQ
	sta	$e000
	sta	$e001
	bit	<$03
	bpl	.sub
	sta	$c001		; Problem with interrupts at $c000 = 0.
.sub

	lda	<$02
	clc
	sbc	<$01	
	sta	<$02
	bcs	.end
	sta	$e000		; IRQ disable

.end	rti

;-------------------------------------------------------------------------------

GetKey:
	lda	<$20
	pha
	lda	#$01
	sta	<$20
	sta	$4016
	lsr	A
	sta	$4016
.loop
	lda	$4016
	lsr	A
	rol	<$20
	bcc	.loop
	pla
	eor	<$20
	and	<$20
	sta	<$21
	rts

;-------------------------------------------------------------------------------

PaletteData:
	.db	$0f,$11,$11,$11,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f
	.db	$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f

	.org	$fffa

	.dw	NMI,RESET,IRQ

	.bank	2
	.org	$0000

	.db	$aa,$00,$80,$00,$80,$00,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00
Attachments
mmc3irqtest.nes
(24.02 KiB) Downloaded 36 times

Drag
Posts: 1335
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: The problem when writing 0 to $C000 in the real MMC3

Post by Drag » Fri Dec 04, 2020 10:33 pm

Nice! We should probably add this quirk to the wiki, since we now have a documented case of someone encountering it accidentally. :P

lidnariq
Posts: 10260
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: The problem when writing 0 to $C000 in the real MMC3

Post by lidnariq » Fri Dec 04, 2020 11:01 pm

So the problem was that you manually reloaded the counter too soon after it automatically reloaded itself?

Fiskbit
Posts: 253
Joined: Sat Nov 18, 2017 9:15 pm

Re: The problem when writing 0 to $C000 in the real MMC3

Post by Fiskbit » Fri Dec 04, 2020 11:12 pm

Do we understand what the quirk actually is? I've been going over the IRQ, counter, and reload behavior in the wiki and looking at the timing of the ROM and it's not clear to me what's happening. The results (two bars of what looks like 4 scanlines) are also really weird.

(Also, in rereading the wiki page, I'm a little confused about the reload flag, since it says that writes to $C001 both clear the counter and set the reload flag, but the counter is reloaded if it's 0 or the reload flag is true. Is this what the hardware actually does, and if so, isn't the reload flag unnecessary if the counter is cleared by the $C001 write?)

lidnariq
Posts: 10260
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: The problem when writing 0 to $C000 in the real MMC3

Post by lidnariq » Fri Dec 04, 2020 11:31 pm

Blargg's notes in MMC3 IRQ Tests, also quoted above in N·K's post
I uncovered some pathological behavior that isn't covered by the test ROMs. If $C001 is written, the counter clocked, then $C001 written again, on the next counter clock the counter will be ORed with $80 (revision B)/frozen (revision A) and neither decremented nor reloaded. If $C001 is written again at this point, on the next counter clock it will be reloaded normally. I put a check in my emulator and none of the several games I tested ever caused this situation to occur, so it's probably not a good idea to implement this.

Fiskbit
Posts: 253
Joined: Sat Nov 18, 2017 9:15 pm

Re: The problem when writing 0 to $C000 in the real MMC3

Post by Fiskbit » Sat Dec 05, 2020 1:23 am

That's what I get for skipping over the quote assuming it was just a previous post. :) That's very interesting behavior. The OR with #$80 seems to match what's shown in the picture, but it looks like it was able to do 4 scanlines each time before encountering the problem, and it sounds like it only affected a reload value of 0.

Would be nice to get this emulated for development purposes.

User avatar
N·K
Posts: 5
Joined: Mon May 11, 2020 2:45 am
Location: Japan

Re: The problem when writing 0 to $C000 in the real MMC3

Post by N·K » Sat Dec 05, 2020 2:14 am

Fiskbit wrote:
Sat Dec 05, 2020 1:23 am
That's what I get for skipping over the quote assuming it was just a previous post. :) That's very interesting behavior. The OR with #$80 seems to match what's shown in the picture, but it looks like it was able to do 4 scanlines each time before encountering the problem, and it sounds like it only affected a reload value of 0.

Would be nice to get this emulated for development purposes.
Because of the interlacing of the video, it looks like four scan lines, but in fact it was like two scan lines.

Fiskbit
Posts: 253
Joined: Sat Nov 18, 2017 9:15 pm

Re: The problem when writing 0 to $C000 in the real MMC3

Post by Fiskbit » Sat Dec 05, 2020 2:35 am

Ah, thank you! That makes sense. I think this does match blargg's explanation, then, and you didn't encounter it on values larger than 0 because there were at least 2 clocks between each $C001 write, preventing the issue.

tepples
Posts: 22284
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: The problem when writing 0 to $C000 in the real MMC3

Post by tepples » Sat Dec 05, 2020 6:56 am

Added to MMC3 page on the wiki.

Post Reply