Page 1 of 2
VRC6 scanlines and scrolling
Posted: Fri Feb 03, 2012 8:31 pm
by rainwarrior
Okay, so I was making a little parallax scrolling test earlier with MMC3, and that was fine, except today I got a PowerPak to test on my NES, and it turned out the FamiTracker music driver I was using doesn't actually work with MMC3 for some reason.
So... I've ported it to VRC6, except there's one thing I can't figure out. MMC3's IRQ seems to start at a consistent point in the scanline, so I can easily move the actual scroll register write around with NOPs. With VRC6, it doesn't sound like it knows anything about its horizontal position?
Has anybody found a way to deal with this issue? Or... is VRC6's scanline IRQ just not up to the task?
Posted: Fri Feb 03, 2012 8:38 pm
by rainwarrior
Also, I'm kind of curious about the startup PRG banks for VRC6. On emulators $8000 seems to be bank 0, and $C000 seems to be bank 2, but on the PowerPak it seems like $C000 is something else (maybe 0?).
My startup code was in the $C000 range, so I ended up moving it to $8000. I'm just wondering if it's like MMC1 where you want to have a startup stub in every bank, or is it okay to put it in the $8000 bank 0?
Posted: Fri Feb 03, 2012 8:42 pm
by bunnyboy
VRC6 IRQ is a cycle counter, so it should be triggering at the same point in the scanline that you started it at. Could try setting the enable bit at the beginning of NMI so its always the same?
Posted: Fri Feb 03, 2012 8:44 pm
by tokumaru
I just checked the wiki and it seems that VRC6's IRQs are driven by CPU cycles, unlike the one in the MMC3, which is driven by the PPU. The difference is that since the PPU doesn't do anything during VBlank, the scanline counter isn't clocked, so no matter when in VBlank you setup the IRQ, the counting doesn't start until rendering begins.
The CPU on the other hand never stops, so a CPU-based IRQ counter will count even during VBlank, so if you don't setup the IRQ at the same point every frame the time when the IRQs fire will also fluctuate. Your best bet is probably to setup the IRQ right at the start of your NMI routine, before any branches or decisions that might result in different program flows each time.
Posted: Fri Feb 03, 2012 8:45 pm
by bunnyboy
And $E000-FFFF is the only fixed bank, so the others will be unreliable on boot. Can't necessarily rely on the $8000 bank being bank 0 either.
Posted: Fri Feb 03, 2012 9:43 pm
by rainwarrior
tokumaru, I had the same idea. Now I've had a chance to try it out. It was a huge pain to get the interrupts happening on the same horizontal position; basically I offset the first IRQ setup with NOPs right after vblank, and then in the IRQ I set scroll, and then offset the next IRQ setup with NOPs again. Eventually I was able to get it consistent and in the right place.
I'm actually really impressed by Nintendulator's timing accuracy; it's not 100% but it was REALLY close (off by one NOP from what I get from my NES with PowerPak), and consistent enough that I could figure out what it was going to do based on what I saw in the emulator.
It was a fun experiment, but I don't think I'd want to do it in an actual game.
Also, bunnyboy, thanks for the clarification. I moved my bank setup stub to the last bank.
Posted: Sat Feb 04, 2012 7:41 am
by tokumaru
rainwarrior wrote:I'm actually really impressed by Nintendulator's timing accuracy; it's not 100% but it was REALLY close (off by one NOP from what I get from my NES with PowerPak)
Don't forget that mappers on the PowerPak are emulated, so they aren't necessarily 100% correct either. To be absolute sure you'd have to use an actual VRC6 cart.
Posted: Sat Feb 04, 2012 8:29 am
by tepples
Or you could start running the cycle counter right after the first PHA of the NMI handler. That'd need a change for PAL NES, but not for Dendy style PAL clones. The maximum variation you'd get in the starting point would be roughly the difference between the shortest instruction (2 cycles) and the longest official instruction (7 cycles), which is slightly less than the expected sprite 0 hit variation (7-12 cycles depending on how you handle a timeout).
Posted: Sat Feb 04, 2012 11:02 am
by MottZilla
The VRC IRQs don't support PAL at all. The CPU counter scaler is intended for NTSC.
The primary benefit to the VRC IRQ being CPU based is you can use patterns from both sides of the table for sprites unlike MMC3. Otherwise MMC3 is clearly the better IRQ system being PPU based. MMC5 ofcourse is even better.
Posted: Sat Feb 04, 2012 11:09 am
by tepples
MottZilla wrote:The VRC IRQs don't support PAL at all. The CPU counter scaler is intended for NTSC.
What happens when you add 50 lines and then multiply the result by 15/16 before writing it to the mapper? That's an add, four shifts, and a subtract to adapt to PAL. I'll admit that you will lose some precision from the multiplication by 15/16, so be careful if you want multiple splits in one screen.
The primary benefit to the VRC IRQ being CPU based is you can use patterns from both sides of the table for sprites unlike MMC3.
I explained one workaround to tokumaru a while back: map one bank to both sides of the pattern table. Write 0, 2, 0, 5, 6, 7 to the CHR bank registers, and sprites and background can share bank 0.
Posted: Sat Feb 04, 2012 1:17 pm
by MottZilla
Ofcourse you can have a hacky implementation for PAL but it's just not meant for it normally.
And that defeats the point of having extra CHR for sprites if you are using up a bank like that. For example in Gradius II, the game uses sprites from the BG side of the pattern tables which makes MMC3 unsuitable.
Posted: Sat Feb 04, 2012 3:38 pm
by rainwarrior
tokumaru wrote:Don't forget that mappers on the PowerPak are emulated, so they aren't necessarily 100% correct either. To be absolute sure you'd have to use an actual VRC6 cart.
Yes, this is true, but I'm not about to go -that- far to find out.
In the end I've decided it's not a very viable technique, since it's not very robust across different emulators, and even on the most available "real" hardware (PowerPak) there may be some uncertainty still.
On a related not I'm really curious how Rad Racer works, since it seems to do scanline scrolling with an MMC1 somehow. One of these days I'm going to start tracing its rendering code...
Posted: Sat Feb 04, 2012 3:46 pm
by tepples
rainwarrior wrote:On a related not I'm really curious how Rad Racer works, since it seems to do scanline scrolling with an MMC1 somehow.
F-1 Race does scanline scrolling with an NROM somehow. I'm thinking sprite 0 trigger and a 113.667 cycle inner loop.
Posted: Sat Feb 04, 2012 6:59 pm
by MottZilla
Battletoads in level 3 does raster parallax scrolling with AxROM which has no IRQ generation either. Anything is possible with very carefully timed code.
Posted: Sat Feb 04, 2012 8:00 pm
by tokumaru
The NES can do parallax/raster effects without mapper IRQs, it's just a bit harder and less practical. You need a way to synchronize with the PPU, which can be done with the vertical blank (you can detect the start or end of it in various ways), a sprite 0 hit, a sprite overflow, or even APU IRQs (these are really tricky!), and then some timed code. With these methods you typically waste more CPU time to pull off the effects than if you used a mapper with IRQs though.