Documentation on offset-per-tile

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Documentation on offset-per-tile
by on (#141399)
http://www.sega-16.com/forum/showthread.php?18434-Comparison-of-4th-generation-(-quot-8-16-bit-quot-)-system-hardware/page78

In this thread Tomathious says that offset-per-tile mode requires every tile to be individually scrolled, but that is incorrect because I've done collumn-scrolling before, and I didn't need to scroll every single tile in order to do it. There were a few mysterious hardware quirks, such as you have to write to the second row of tiles in BG3's tile map, and bit-9 has to be set for some reason.
Re: Documentation on offset-per-tile
by on (#141412)
Tested on real hardware or it never happened!
Re: Documentation on offset-per-tile
by on (#141413)
He also says there's a "strange" 512-byte offset between sprite tile rows, and in another place that the interleaving of the sprite format depends on the sprite size.

This stuff makes perfect sense if you think of sprite tables as 16x16-tile squares. It's Famicom design heritage, presumably intended to make OBJ easy to mock up on a sheet of graph paper.
Re: Documentation on offset-per-tile
by on (#141414)
bazz wrote:
Tested on real hardware or it never happened!

What never happened? Also, were you using a 0/0/0 SNES? It seems to have the most weird quirks. (You can check your CPU, and PPU's version if you have the Lion King game.)
Re: Documentation on offset-per-tile
by on (#141417)
Jump in the thread and give your opinion, or correction, or whatever. It's not an exclusive club, kiddos :P


Quote:
but that is incorrect because I've done collumn-scrolling before, and I didn't need to scroll every single tile in order to do it. There were a few mysterious hardware quirks, such as you have to write to the second row of tiles in BG3's tile map, and bit-9 has to be set for some reason.

Huh? Is this documented?

93143 wrote:
This stuff makes perfect sense if you think of sprite tables as 16x16-tile squares. It's Famicom design heritage, presumably intended to make OBJ easy to mock up on a sheet of graph paper.


You know what.. that actually makes sense in that context: if you view the entire bank as a grid of 16x16 tiles. But it wasn't 1983 when the SFC came out - who was using sheets of paper for development or sprite layout??? Doesn't seem very optimal layout for dma'ing or such. Either way, it definitely isn't a clean design like the PCE or MD. Convoluted was a little strong to describe it (I reserve that for other aspects of the SNES, sPPU, etc), so "strange" seemed appropriate.
Re: Documentation on offset-per-tile
by on (#141433)
It is briefly mentioned in the BG layer section of wiki.superfamicom.org, but it is really unclear. There is some C++ algorithm that I don't understand, but I did notice something about if $2000 is set, apply to BG1, if $4000 is set, apply to BG2. Maybe it wasn't bit 9 then, I probably misremembered it as $0200, since I haven't used it in a while. It doesn't mention anything about columns versus tiles. Maybe it keeps the tile scroll value down until it hits another tile with bit 13 set.
Re: Documentation on offset-per-tile
by on (#141443)
The offset per tile is perfectly doccumented in Anomies' doc, and while it is confusing when using horizontal offset-per-tile, I think the vertical offset per tile is very clear.

Normally OPT is column wise, but by changing BG2's vertical scrolling you could make it tile-wise or even less. Whenever BG2's scroll is changed, the first (or is it second?) row that would be displayed if BG2 was displayed determines the OPT.

The enable bits should just be set, if they are clear then the normal scrolling applies. If the normal file horizontal scrolling is not a multiple of 8 (i.e. whole tile), the first pixels displays part of a tile using normal scrolling, and then OPT is used starting from the next tile.

I really recommend restricting to vertical OPT first, because horizontal is extremely confusing, although it makes sense it's hard to keep track what is going on - my understanding is that it can only be used to re-arrange tiles in a row rather than doing actual scrolling.
Re: Documentation on offset-per-tile
by on (#141444)
psycopathicteen wrote:
http://www.sega-16.com/forum/showthread.php?18434-Comparison-of-4th-generation-(-quot-8-16-bit-quot-)-system-hardware/page78

In this thread Tomathious says that offset-per-tile mode requires every tile to be individually scrolled, but that is incorrect because I've done collumn-scrolling before, and I didn't need to scroll every single tile in order to do it. There were a few mysterious hardware quirks, such as you have to write to the second row of tiles in BG3's tile map, and bit-9 has to be set for some reason.


Tomathious is a bit confused. The "third tilemap" used in offset-per-tile modes isn't a full 32x32 tilemap; it's only 32x2. The first row contains the horizontal offsets for each full column of the other tilemap(s); the second row contains the vertical offsets for each full column. Except in mode 4, where only one row is used and it contains either a horizontal or a vertical offset for that column, depending on bit 15 (this is because of VRAM bandwidth limitations--check my recent post history for a post where I explain how the VRAM bandwidth is "budgeted" in each mode)

One weird limitation of the SNES offset-per-tile modes is the offsets never apply to the leftmost visible tile on the screen. "The leftmost visible tile" can mean a full tile or just a 1-pixel sliver, depending on the horizontal scroll, but there's always at least 1 visible pixel that gets generated without any offset. The upshot is that if you want to use offset-per-tile on a horizontally-scrolling screen to draw a waterfall or something, you have to use the clip window to mask off the leftmost 8 pixels of the screen or you'll see visible artifacts. This limitation is probably one reason offset-per-tile was mainly used in non-scrolling scenes such as title screens, boss fights, and block puzzle games.
Re: Documentation on offset-per-tile
by on (#141448)
Whenever I'd read doc on Offset-per-tile it makes my head hurt.. Can anyone make sense of it? Layman's terms.. A visual tutorial or even video demonstrating it would be so key :)
Re: Documentation on offset-per-tile
by on (#141449)
AWJ wrote:
Tomathious is a bit confused. The "third tilemap" used in offset-per-tile modes isn't a full 32x32 tilemap; it's only 32x2. The first row contains the horizontal offsets for each full column of the other tilemap(s); the second row contains the vertical offsets for each full column. Except in mode 4, where only one row is used and it contains either a horizontal or a vertical offset for that column, depending on bit 15 (this is because of VRAM bandwidth limitations--check my recent post history for a post where I explain how the VRAM bandwidth is "budgeted" in each mode)


To be honest i always found the offset per tile mode pretty confusing... and still i don't really get what is the real purpose of this mode O_o ? It does look powerful but has some constraints at same time making it complex and not as useful it might be.
Also that is the funny thing with the SNES, every graphics mode are actually limited by the VRAM bandwidth and when you have more somewhere (4 plans) you necessary have less elsewhere (2bpp mode). Actually in similar conditions than the MD (which does have column scrolling) you finally end with same limitations : 2 plans - 4bpp.
And the MD has the advantage of the higher resolution :p

Quote:
One weird limitation of the SNES offset-per-tile modes is the offsets never apply to the leftmost visible tile on the screen. "The leftmost visible tile" can mean a full tile or just a 1-pixel sliver, depending on the horizontal scroll, but there's always at least 1 visible pixel that gets generated without any offset. The upshot is that if you want to use offset-per-tile on a horizontally-scrolling screen to draw a waterfall or something, you have to use the clip window to mask off the leftmost 8 pixels of the screen or you'll see visible artifacts. This limitation is probably one reason offset-per-tile was mainly used in non-scrolling scenes such as title screens, boss fights, and block puzzle games.


Hehe, fun to see it shares a "similar bug" with the MD : You have the exact same problem with the column scrolling on the MD, first column scrolling is wrong as there is not enough VSRAM to store the extra column offset depending the current H scroll. So exactly for the same reason as the SNES you need to hide the first column during column scrolling. I believe later MD revision fixed the problem: the MD2 seems to fix the column 0 offset to 0 (where it was somehow randomly picked on MD1) and MD3 even added an extra VSRAM entry for it (really not sure about it but i read it somewhere).
Re: Documentation on offset-per-tile
by on (#141450)
Stef wrote:
you finally end with same limitations : 2 plans - 4bpp.And the MD has the advantage of the higher resolution :p

But you can only vertically scroll every 16 pixels. Although it is still useful for making things like blocks move up and down, you really cannot fake rotation beyond a tilt. Basically, although the MD has a higher resolution, the SNES can vertically scroll about twice as much, which is actually pretty useful for fake rotation. See the background on Star Fox.
Re: Documentation on offset-per-tile
by on (#141453)
Yeah indeed the column scrolling step is finer (1 tile instead of 2 tiles) on SNES but apparently it is not as convenient to setup than the MD.
Also just for the comparison :
SNES : https://www.youtube.com/watch?v=A7TF5evojYA
MD : https://www.youtube.com/watch?v=YUZpF2JLF4s

You have higher inclination on SNES indeed, does it really matter ? not so much i think ;)
Re: Documentation on offset-per-tile
by on (#141473)
AWJ wrote:
Tomathious is a bit confused. The "third tilemap" used in offset-per-tile modes isn't a full 32x32 tilemap; it's only 32x2. The first row contains the horizontal offsets for each full column of the other tilemap(s); the second row contains the vertical offsets for each full column.


For one... http://wiki.superfamicom.org can eat a d*ick. Ughh. And secondly, why can't documents and sites contain a bit of redundancy in their information? It helps to understand stuff. Looking at what you said, and re-looking over the official dev manual, I can see that now. But even the official documents are crappy in this respect. The example format given for the 'map' (which isn't even a map anymore, it's just a small offset scroll table that just happens to share the same base pointer as BG3 for other modes), doesn't indicate that it's limited to just two rows data.

Now that that's clear, why the hell is Aladdin slowing down for on the snake boss??? That makes even less sense now.

Edit:

Actually, way before snes wiki site, there was an effect in Chrono Trigger that supposedly offset every tile for some weird transition effect (part of a cinema.. a ship?). I'm not sure who said it, but given the interpretation of the SFX dev manual - the claim made sense. Now I'm curious how that effect was pulled off.
Re: Documentation on offset-per-tile
by on (#141474)
Are those effects emulated properly in a debugging emulator like NO$SNS? If so, open them and see how they're arranging BG3.
Re: Documentation on offset-per-tile
by on (#141475)
AWJ wrote:
One weird limitation of the SNES offset-per-tile modes is the offsets never apply to the leftmost visible tile on the screen. "The leftmost visible tile" can mean a full tile or just a 1-pixel sliver, depending on the horizontal scroll, but there's always at least 1 visible pixel that gets generated without any offset. The upshot is that if you want to use offset-per-tile on a horizontally-scrolling screen to draw a waterfall or something, you have to use the clip window to mask off the leftmost 8 pixels of the screen or you'll see visible artifacts. This limitation is probably one reason offset-per-tile was mainly used in non-scrolling scenes such as title screens, boss fights, and block puzzle games.

The Mega Drive has a similar limitation in it's per-2-cell vertical scrolling mode. The problem is that it has enough entries for 20 columns (the width of the screen), but because of horizontal scrolling it ends up rendering 21 columns instead. The column at the leftmost is basically column -1, and because it doesn't have an entry in VSRAM it ends up reading the noise is on the bus instead. This is why games would hide the leftmost 16 pixels when using this mode.

At least when horizontal scrolling wasn't used (common in shmups) this issue wouldn't come up since column -1 was completely offscreen. I guess that was the original intention of the mode.

Espozo wrote:
But you can only vertically scroll every 16 pixels. Although it is still useful for making things like blocks move up and down, you really cannot fake rotation beyond a tilt. Basically, although the MD has a higher resolution, the SNES can vertically scroll about twice as much, which is actually pretty useful for fake rotation. See the background on Star Fox.

Honestly what the SNES has isn't that useful beyond tilts either, and yes I'd argue that what Star Fox has is just a tilt. If you want to fake rotation more feasibly you pretty much need pixel granurality (something which wasn't possible in either case due to VRAM bandwidth issues).
Re: Documentation on offset-per-tile
by on (#141477)
tepples wrote:
Are those effects emulated properly in a debugging emulator like NO$SNS? If so, open them and see how they're arranging BG3.

Nope.png, but you can still watch the map in the vram viewer.
Re: Documentation on offset-per-tile
by on (#141482)
tomaitheous wrote:
AWJ wrote:
Tomathious is a bit confused. The "third tilemap" used in offset-per-tile modes isn't a full 32x32 tilemap; it's only 32x2. The first row contains the horizontal offsets for each full column of the other tilemap(s); the second row contains the vertical offsets for each full column.


For one... http://wiki.superfamicom.org can eat a d*ick. Ughh. And secondly, why can't documents and sites contain a bit of redundancy in their information? It helps to understand stuff. Looking at what you said, and re-looking over the official dev manual, I can see that now. But even the official documents are crappy in this respect. The example format given for the 'map' (which isn't even a map anymore, it's just a small offset scroll table that just happens to share the same base pointer as BG3 for other modes), doesn't indicate that it's limited to just two rows data.


It is a tilemap in most respects; the PPU just ignores the electron beam position when deciding what row of it to read. Other than that, it is affected by all the registers that affect BG3. If you set BG3 to use 16x16 tiles then the scroll columns will have 16-pixel granularity instead of 8-pixel (for all the use that is...). Changing the BG3 scroll registers changes exactly where in VRAM the table gets fetched from (this is how you do raster splits; you can't overwrite the offset table in mid-frame because it's in VRAM and the CPU can't access VRAM outside of VBlank, but you can upload several tables during VBlank and then switch between them by HDMAing to the BG3 scroll registers)
Re: Documentation on offset-per-tile
by on (#141486)
AWJ wrote:
It is a tilemap in most respects; the PPU just ignores the electron beam position when deciding what row of it to read. Other than that, it is affected by all the registers that affect BG3. If you set BG3 to use 16x16 tiles then the scroll columns will have 16-pixel granularity instead of 8-pixel (for all the use that is...). Changing the BG3 scroll registers changes exactly where in VRAM the table gets fetched from (this is how you do raster splits; you can't overwrite the offset table in mid-frame because it's in VRAM and the CPU can't access VRAM outside of VBlank, but you can upload several tables during VBlank and then switch between them by HDMAing to the BG3 scroll registers)


Hmm.. I'm trying to visualize this. So the v_offset of BG3 is essentially where the two rows are going to be read from? If you have a v_offset of 0x000, the first two rows of BG are used? If the v_offset was 0x010 (16 pixels), then the next two set of rows would be used instead? So, assuming I understand that correctly, when the BG3 v_offset is changed mid screen to point to next/new/different set of rows - then those values are used instead of the tile offsets as it's drawing the next map line? That's really cool. So you get both; full map tile offset, and just regular column scrolling. Either one, depending on how much resource you want to put into it.
Re: Documentation on offset-per-tile
by on (#141504)
tomaitheous wrote:
Now that that's clear, why the hell is Aladdin slowing down for on the snake boss??? That makes even less sense now.


Capcom can't do anything without slowdown.