Well, it's not the simplest thing but I'll try to explain it the best I can. At least the usage of MMC3 (or any other kind of) IRQs will simplify your life.
First of all you have to decide how you'll work with nametables. Multidirectionnal scrolling with horizontal mirroring can be done with some different techniques, all of them being tricky. I'll do my best to explain them :
1) Changing adress of the status bar (Double Dragon, Chronicles of Radia wars) :
The status bar is located somewhere and the playfield can extend in all directions. When the playfield "reaches" the status bar, the scroll engine automatically switch to another copy of the status bar somewhere else where the playfield isn't used anymore. The main drawback is that you have to constantly re-write the whole status bar at different nametable adresses while scrolling, and keep track of where the status bar is. Personally I'd go this way (I do something similar in the project I'm developping).
2) Changing adress of the playfield (Kirby's Adventure) :
The status bar is at a fixed place this time, but you double the playfield, so that it's possible to see the whole thing and wrap arround while never reaching the status bar. The main drawback is that you have to upload 2 identical playfields simultanously into the PPU.
3) Use another IRQ to change vertical scrolling midframe (Crystalis) :
The status bar is again on a fixed place and the playfield can extend without being "doubled". However, you set an IRQ that reset the vertical scrolling to zero to wrap arround by software. The main drawback is that you have to use multiple IRQs and precise timing.
Just use FCEUXD to see those techniques in details and how they work.
And now about the IRQ for the status bar :
- Bottom status bar : Set an IRQ for the scanline you want. In the IRQ routine just write the PPU adress of your status bar to $2006 (minus $2000) and write $00 to $2005. For example if the status bar is located at $2300, you'd want to write $03, $00 to $2006 and then $00 to $2005.
- Top status bar : You'd need a 4 pixel gap at the bottom of the status bar (or even 8 pixels if you want to simplify the logic).
Set the IRQ for the top of the pixel gap. There, you'll have to disable background but leave sprites enabled via $2001, so that the BG scrolling is intact. Now prepare the adress to be written to $2006, which is equivalent to the nametable adress of the tile you'd want to see on the top-left. In terms of vertical scrolling a few shifts have to be done in order to find that adress.
Now add the low 2 bits of your vertical scroll value to the highest nybble of that adress. For example if the adress is $0120 and the 2 lowest bits of the VScroll value are to '3', you'll want to write $31, $20 to $2006.
Then you'll have to watch the third bit of your fine VScroll value to know when to write to $2006. If the bit is clear, write it immediately, else write it 4 scanline later (at the end of the gap). There, turn BG back on via $2001, write the correct horizontal scroll to $2005 and you're done ! Multi-directional scrolling with top status bar that allow sprites to scroll in it. I'll pase some code to clarify the huge mess that's above :
Code:
lda VScroll
asl A
rol A
rol A
and #$03
sta Temp ;Get 2 highest bits of tile index (high adress byte) and nametable selection
lda VScroll ;Get 2 lowest bit of vertical scrolling
and #$03
asl A
ora FieldNameTable ;Name table of playfield, assumed to be 0 or 1
asl A
asl A
asl A
ora Temp ;Get nametable selection in bit3 and fine scroll in bits 4&5
sta Temp
lda #$10
sta $2001 ;BG off, but sprites on (scrolling intact)
lda VScroll
and #$04 ;Compute when to write to $2006
beq +
jsr Wait4Scanlines ;Timed code to wait 4 scanlines
jsr Writeto2006
jmp ++
+ jsr Writeto2006
jsr Wait4Scanlines
++ lda #$18
sta $2001
lda HScroll
sta $2005
rts
Writeto2006
bit $2002
lda Temp
sta $2006
lda ScollValue
asl A
asl A
and #$e0 ;Get the mid part of the PPU counter adress
sta $2006 ;Update the thing, take effect immediately
rts
Note that you have to write timed code, you can't trigger an MMC3 IRQ if only sprites are enabled. This code is to show the idea, you will have to fine-tune the timing and place it into a IRQ routine yourself.
Hope this huge post clarifies things for everyone.