- I read KH and blargg's MMC3 specs but I'm still unsure about its behaviour at every time A12 toggles. I get error #6 in test ROM "Clocking.nes". Please, what's the behaviour when A12 toggles? How does it work?
- I wrote a CPU tracer here, things are in-sync (PPU/CPU), only missing a correct (and clear) info regarding the MMC3 IRQs. Thanks.
From MMC3 Test ROMs readme:
1.Clocking
Tests counter operation. Requires support for clocking via manual toggling of VRAM address.
...
6) Should reload (no decrement) on first clock after clear
From Kevtris MMC3 documentation:
C001h
Writing to this register clears the IRQ counter. The value on C000h will be copied into the IRQ counter on the NEXT rising edge of A12. That means that the value of C000h is only checked at the very instant of reloading, and C000h's value is not copied when C001h is written to. The value written to C001h is irrelevant.
* Writing to C001h will clear the IRQ counter, and it will be reloaded from C000h into the IRQ counter on the NEXT rising edge of A12. It will decrement from that point on subsequent A12 rising edges.
So writing to $C001 and then toggling A12 should result in the counter holding the value in $C000 without decrementing it.
I wonder if the following has an error...
Code:
E130 STA $2006 [A=10 X=02 Y=00 S=F8 P=35] --- --- (01)
E133 STA $2006 [A=10 X=02 Y=00 S=F8 P=35] --- --- (01)
E136 LDA #$00 [A=10 X=02 Y=00 S=F8 P=35] --- --- (01)
* A12 toggles: 0000->1010
* IRQ counter expired!
E138 STA $2006 [A=00 X=02 Y=00 S=F8 P=37] IRQ --- (00)
E13B STA $2006 [A=00 X=02 Y=00 S=F8 P=37] IRQ --- (00)
E13E PLA [A=00 X=02 Y=00 S=F8 P=37] IRQ --- (00)
* A12 toggles: 1010->0000
* IRQ counter reload.
You notice that A12 rising occurs after the next instruction. Would it happen right after the second 2006h write?
The MMC3 only catches RISING edges on PPU A12 - it does NOT detect falling edges.
Quietust wrote:
The MMC3 only catches RISING edges on PPU A12 - it does NOT detect falling edges.
Whoops! Thanks for pointing this... >_<::.
If I used the word "toggle" then it was a bad choice on my part, since indeed toggling a binary value means changing its state (XOR with 1). With that fix, how far do you get now?
My actual "logic" is the following, checked at every CPU cycle...
- If A12 has toggled:
- If counter = 0, reload it on next rising edge (A12 0->1);
- Else, decrement it. If counter = 0, an IRQ is queued.
It still gives me error 6. Obviously that if I replace the "toggle" by "next rising edge" for a clock, then I got error 3.
The only significant A12 event is when it changes from 0 to 1. All other transitions are irrelevant (1->1, 1->0, 0->0).
The MMC3 has an internal IRQ flag that is raised when the counter becomes 0 and lowered only when $E000 is written to. If "1.clocking.nes" is giving error code #3, your code is probably lowering this flag at some other time.
In addition, the MMC3 will not detect a rising edge on PPU A12 if it was low for less than ~2 CPU cycles (OR if the last rising edge was less than ~3 CPU cycles ago - the exact behavior is not known) - during sprite fetches, the PPU rapidly alternates between $1xxx and $2xxx, and the MMC3 does not see A13 - as such, the PPU will send 8 rising edges on A12 during the sprite fetch portion of the scanline (with 8 pixel clocks, or 2.67 CPU cycles between them), but the MMC3 will only see the first one.
1 question... If the MMC3 only detects A12 rising (0->1), so the IRQ counter isn't decremented 240 times in a frame if enabled... correct? o.O
Fx3 wrote:
1 question... If the MMC3 only detects A12 rising (0->1), so the IRQ counter isn't decremented 240 times in a frame if enabled... correct? o.O
...what?
If you have background tiles loading from $0000-$0FFF and sprite tiles loading from $1000-$1FFF and have rendering enabled, then the MMC3's IRQ counter will decrement
exactly 241 times per frame (yes, this includes the pre-fetch "scanline -1"). Note that it will decrement
even if it's disabled - $E000/$E001 have no effect on the IRQ counter itself, only what happens when it hits zero.
I mean A12 being toggled at every scanline (ppu_addr AND 1000h), or 241 times in a frame. If only 0->1 transitions are catched up, so I understand that the IRQ counter would decrement by half in a frame... 120 times. Unless I'm misunderstanding something picky...?
If sprites are set to $1000-1FFF and the background is set to $0000-0FFF, then A12 will change from 0 to 1 at cycle 260 of each scanline, then change from 1 to 0 at cycle 320 of each scanline.
If sprites are set to $0000-0FFF and the background is set to $1000-1FFF, then A12 will change from 1 to 0 at cycle 256 of each scanline, then change from 0 to 1 at cycle 324 of each scanline.
If sprites and the background are set to the same pattern table, then no decrement occurs because A12 will never be set to 0 long enough for the MMC3 to detect it.
Such is my understanding, anyway.
No, it gets a RISING EDGE every scanline.
Technically, PPU A12 gets eight rising edges per scanline (when sprites are at $1xxx and background is at $0xxx), but only the first one decrements the MMC3's IRQ counter (the remaining ones are too close together).
I didn't trap more than 5 rising edges in a scanline. OK, I used the test ROM #1.Clocking, but that's it. Now, it's OK.
Problem goes to test ROM 2.Details - I get error #7) Counter should be clocked 241 times in PPU frame. Umm... does it fail if the IRQ counter is clocked like 242 times? 240 times?
Test "2.details.nes" #7 indeed checks that it's decremented exactly 241, no more, no less. Here's the code for that test:
Code:
ldx #241 ; load counter with 241
jsr begin_counter_test
jsr wait_vbl
lda #0
sta $2005
sta $2005
lda #$08 ; sprites use tiles at $1xxx
sta $2000
lda #$18 ; enable bg and sprites
sta $2001
ldy #25 ; 29800 delay for frame
lda #237
jsr delay_ya8
lda #$00 ; disable rendering
sta $2001
jsr irq_should_be_clear; counter should be at 1 now (no IRQ yet)
jsr clock_counter
jsr irq_should_be_set ; counter should be at 0 now (IRQ occurring)
Great. This makes the things a bit easier.
Anonymous wrote:
If sprites are set to $1000-1FFF and the background is set to $0000-0FFF, then A12 will change from 0 to 1 at cycle 260 of each scanline, then change from 1 to 0 at cycle 320 of each scanline.
If sprites are set to $0000-0FFF and the background is set to $1000-1FFF, then A12 will change from 1 to 0 at cycle 256 of each scanline, then change from 0 to 1 at cycle 324 of each scanline.
If sprites and the background are set to the same pattern table, then no decrement occurs because A12 will never be set to 0 long enough for the MMC3 to detect it.
Such is my understanding, anyway.
Are these numbers correct? I saw a "no" post immediatly afterward without quoting a specific post.
What's the scale, or what kind of cycles are these? Are these the ones that go up to 341?
What are the equivalent cycle numbers for PAL mode, if they aren't the same?
Any other mappers use the same A12 rising edge method as MMC3? (tengen rambo?)
i see DWedit avatar... Dwedit, are you a girl or a boy???
I honnestly not think Nesdev is a good place to get girlfirends. For a sad obscure reason, all girls aren't interested in what is interesting, and they are interested in what isn't interesting.
Bregalad wrote:
I honnestly not think Nesdev is a good place to get girlfirends. For a sad obscure reason, all girls aren't interested in what is interesting, and they are interested in what isn't interesting.
Hahaha! My girlfriend can get really bored if I even *try* to talk about NESdev with her. She likes games though, so we can at least discuss ideas for games, but not the actual coding of them.
lord_Chile wrote:
i see DWedit avatar... Dwedit, are you a girl or a boy???
Dwedit's name, according to
http://dwedit.home.comcast.net/, is Dan Weiss, so I'll let you draw your own conclusions.
yeah, nesdev is for nes i agree. but if i see a girl coding on nesdev i would like asking for marry hahhhahaa!
i like so much nesdev hahha.. i would be crazy!
i dont know if dan is a girl or man name, on chile it's uncommon and i dont know about it.. anyway i think he is a boy, good luck
Dwedit wrote:
Any other mappers use the same A12 rising edge method as MMC3? (tengen rambo?)
If it's of any interest (I doubt anyone would emulate it soon), my Squeedo cart uses PPU A12. I hooked it up to clock one of the PIC's timers, set to be counted on rising edges and pre-scaled by 8, and that works.
I did a log tracing test #7 and... I must be misunderstanding something about how A12-IRQ clocking work...
Code:
E26A STA $2001 [A=00 X=00 Y=00 S=FD P=37] --- --- (7A)
It must be 01!
You see... My code checks for A12 rising edges at every single CPU clock cycle, or A12 0->1 changes (to be exact). In fact, F1h - 7Ah = 77h (119). Actually, the excessive branch loops make the log a bit huge... so, analysing it becomes harder.
Anyway, what's up?
EDIT-- nope, even using the 8 cycles "latency" between A12 rising edges, it still fails at #7. It seems 0->1 isn't the true rule after all, but A12=1 and again 1 every 8 CPU cycles?
EDIT2-- what's the actual behaviour regarding 2000h, please? bump... bump...
$2000 info:
http://nesdevwiki.ath.cx/index.php/NES_PPU
And keep in mind the PPU temp address gets updated too (see Loopy's 'skinny on NES scrolling' document), in short: temp address A10, A11 = $2000 D0, D1.
No. I mean 2000h bits stopping the MMC3 IRQ counter. ^_^;;
Setting bits 3 and 4 of $2000 to 0 would stop the MMC3 IRQ counter during normal rendering, and that's simply because an A12 rising edge won't happen: during rendering, the PPU would read from nametables/attribute data ($2000-$2fff: A12=0), and fetch sprite AND background tiles from $0000-$0ffff (A12=0 again).
You could still manually clock the counter by eg. writing to the palette ($3fxx: A12=1).
I give up, it simply doesn't work.
Not unusual that MMC3 IRQs are...
annoying. Even map90 was easier than this one. I might go back into old method. Damn it.