Mode 7 scrolling

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Mode 7 scrolling
by on (#154354)
So my Mode 7 engine currently allows turning around on the map (i.e., rotate the map), and moving freely on a Y axis (i.e., scrolling along the Y axis of the demo graphics used, though not the screen's).

I've been trying and trying to get scrolling along the X axis work as well in order to eventually make "forward" movement, no matter the current rotation angle, possible.

However, there are several problems/considerations:

  • Doing any horizontal scrolling completely breaks subsequent rotation operations. But why? Vertical scrolling does work flawlessly, so what's the difference? :?:
  • Not only that, but any horizontal scrolling offset other than $0000 (like, $0001) causes the rotation algorithm to do weird and unexpected things (like, changing the camera altitude in an actually pleasant way, even though I thought THAT was a totally different thing to achieve altogether). :shock:
  • Is the scrolling direction really actually "tied" to the orientation of the source GFX, rather than the screen? If so, how did RPGs like FF6 or SoM ever manage to allow smooth scrolling in whichever direction the "camera" was facing? :?:

Please try it for yourself:

Image

http://manuloewe.de/snestuff/projects/furryrpg_build_00235.7z (This is a test build that boots straight to the Mode 7 map.)

Controls:
D-pad r/l – rotate map left/right
R/L (shoulder buttons) – increment/decrement X scroll offset by 1
D-pad u/d – decrement/increment Y scroll offset

Please try rotating the map with an X scroll offset of 1. :?

Clearly, I'm missing something here, and would greatly appreciate any help on this. :)

Thanks!
Re: Mode 7 scrolling
by on (#154359)
There are two parameters you have to worry about: the origin and the scroll vector. They do different things, but are somewhat entangled, as shown in this formula from the superfamicom.org Registers page:

Code:
[ X ]   [ A B ]   [ SX + M7HOFS - CX ]   [ CX ]
[   ] = [     ] * [                  ] + [    ]
[ Y ]   [ C D ]   [ SY + M7VOFS - CY ]   [ CY ]

X/Y: pixel to get colour from in source graphic
SX/Y: screen coordinates to get colour for
M7H/VOFS: scroll offset values
CX/Y: origin coordinates in source graphic
A/B/C/D: transform matrix elements

The confusing bit is that the origin is used in both the pre- and post-transform offset calculations, whereas the scroll vector is used only pre-transform (from screen to source) as one would expect.

...

After trying your ROM for a bit, it seems to me that the problem might be more of a bug than a misunderstanding. Still, a refresher can't hurt, and I might be wrong (I got some really freaky results myself when attempting to fudge my way through without making sure I understood everything perfectly, and I wasn't even doing rotation and perspective at the same time)...
Re: Mode 7 scrolling
by on (#154477)
Whoops, silly me. I was accidentally using an 8-bit variable (the rotation angle) as a 16-bit index in the matrix calculation routine. :oops:

So that horizontal scrolling bug has finally been squashed, at least. :D

http://manuloewe.de/snestuff/projects/furryrpg_build_00236.7z

93143 wrote:
The confusing bit is that the origin is used in both the pre- and post-transform offset calculations, whereas the scroll vector is used only pre-transform (from screen to source) as one would expect.

Thanks! Indeed, scrolling parameters seem to be closely related to the values in M7X/M7Y (center coordinate, CX/CY in that formula).

On looking at how Secret of Mana does it, I discovered that whenever the camera doesn't face straight north (i.e., the rotation angle isn't zero), both M7X and M7Y get updated as soon as you fly forward. If the angle is zero, on the other hand, only M7Y gets updated. As I only ever update either <M7X and M7HOFS> or <M7Y and M7VOFS> at the same time, this might explain the current restriction in movement. :idea:

Hmm ... I feel like I'm yet another tiny step closer to completely mastering Mode 7. :lol:
Re: Mode 7 scrolling
by on (#154478)
Only M7Y getting updated sounds more like there isn't horizontal movement so M7X gets modified by zero i.e. nothing... =P

But yeah huh, why wouldn't you update both when moving diagonally? Isn't that like normal? o.O
Re: Mode 7 scrolling
by on (#154481)
Sik wrote:
But yeah huh, why wouldn't you update both when moving diagonally? Isn't that like normal? o.O

Simple explanation: I wasn't fully aware that M7X/M7Y, the so-called "Rotation/Scaling Center Coordinates," not only affect rotation and scaling but also scrolling (mind you, they aren't called "Rotation/Scaling And Scrolling Center Coordinates" for whatever reason).

Anyway, feel free to share any other totally obvious Mode 7 knowledge you might have that I'm missing. :P
Re: Mode 7 scrolling
by on (#154483)
Honestly I was just going by the names of those registers (M7 obviously stands for mode-7, and when I see X and Y in isolation I think on a position, not on scaling or rotation).

Looking at the docs for real now, it just talks about X0/Y0 (what you called M7X/M7Y) and X1/Y1 (the other pair). It seems that X0/Y0 is used to determine the origin of the transformations (scaling and rotation use this as a pivot), while X1/Y1 are used to actually do the translation. At least if I'm figuring out these calculations correctly.

Did I get this right?
Re: Mode 7 scrolling
by on (#154485)
Sik wrote:
Looking at the docs for real now, it just talks about X0/Y0 (what you called M7X/M7Y) and X1/Y1 (the other pair).

No idea what docs you're talking about. I use Fullsnes and the one 93143 quoted (which is probably based on anomie's register docs).
Re: Mode 7 scrolling
by on (#154486)
The official ones (book 1 page A-16, more specifically).

But yeah, it seems one pair determines which point in the map is used as a pivot for the transformations, while the other one determines where this point appears on screen. This is a lot more obvious if you try to think about how this would work with a 2D map instead of a 3D floor.
Re: Mode 7 scrolling
by on (#154674)
Tadaa! I finally got it to work. :D

Image

http://manuloewe.de/snestuff/projects/furryrpg_build_00237.7z

Press A to fly forward, and left/right on the D-pad to change the direction.

I achieved this by devising an all-new scrolling handler that calculates X/Y parameter changes depending on the current rotation angle. It's not very optimized yet and may cause slowdowns, but at least it's something to work with. :)