Few questions about Offset-per-tile mode

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
srg320
Posts: 32
Joined: Fri Feb 16, 2018 5:52 am
Location: Ukraine

Few questions about Offset-per-tile mode

Post by srg320 »

Now I add Offset-per-tile mode in my FPGA SNES, for now I did Offset-per-tile only for BG1 in BGMODE 2 (it works in Tetris Attack, Battletoads in battlemaniacs and SNES burn-in test rom), and I have a few questions.

As I understand, scrolling values in BG3 common to BG1 and BG2, but read 2 times: one for BG1 with BG1HOFS, and one for BG2 with BG2HOFS. Also, I think that in hardware reading scrolling values from BG3 occurs after reading tiles of BG1 and BG2 (in the place where the reading occurs tiles of BG3 and BG4 in BGMODE 0), therefore this scrolling values apply to next tile in row. I'm right or not?

And the second question, what games or test roms using Offset-per-tile in BGMODE 4 and 6?
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Few questions about Offset-per-tile mode

Post by dougeff »

lidnariq posted a test ROM here which uses modes 0-6.

viewtopic.php?f=12&t=14945

And I think Yoshi's Island uses an offset per tile mode on the "Touch Fuzzy Get Dizzy" level.
nesdoug.com -- blog/tutorial on programming for the NES
creaothceann
Posts: 610
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Few questions about Offset-per-tile mode

Post by creaothceann »

Also in the levels that use lava or stone blocks that move up/down, iirc.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
srg320
Posts: 32
Joined: Fri Feb 16, 2018 5:52 am
Location: Ukraine

Re: Few questions about Offset-per-tile mode

Post by srg320 »

Thanks, lidnariq's test rom very helped me.
srg320
Posts: 32
Joined: Fri Feb 16, 2018 5:52 am
Location: Ukraine

Re: Few questions about Offset-per-tile mode

Post by srg320 »

AWJ wrote:

Code: Select all

0.000004208333333, 0, 0, 1, 0, 1, 0, 0, 1 ; BG2 nametable  .1666 us
0.000004375000000, 0, 0, 0, 0, 0, 0, 0, 1 ; BG1 nametable  .1666 us
0.000004541666667, 0, 1, 0, 1, 0, 0, 0, 1 ; BG3 OPT        .3750 us
0.000004916666667, 1, 0, 0, 0, 0, 0, 0, 1 ; BG2 4bpp       .3750 us
0.000005291666667, 1, 0, 1, 0, 1, 0, 0, 1 ; BG1 4bpp       .3750 us
0.000005666666667, 0, 0, 1, 0, 1, 0, 0, 1 ; BG2 nametable  .2083 us
0.000005875000000, 0, 0, 0, 0, 0, 0, 0, 1 ; BG1 nametable  .1666 us
0.000006041666667, 0, 1, 0, 1, 0, 0, 0, 1 ; BG3 OPT        .3750 us
0.000006416666667, 1, 0, 0, 0, 0, 0, 0, 1 ; BG2 4bpp       .3750 us
0.000006791666667, 1, 0, 1, 0, 1, 0, 0, 1 ; BG1 4bpp       .3750 us
0.000007166666667, 0, 0, 1, 0, 1, 0, 0, 1 ; BG2 nametable
Mode 2 fetches the nametables, then two words of offset-per-tile data (again, we would need the lower address lines to distinguish them), then the patterns. Since the offset-per-tile is fetched after the nametables, each offset-per-tile fetch must apply to the next set of nametable fetches. This explains why offset-per-tile never applies to the first visible tile in a scanline.
If Mode 2 fetches only two words of offset-per-tile data for BG1 and BG2, then how calculate HOFS and VOFS for BG3?
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Few questions about Offset-per-tile mode

Post by psycopathicteen »

srg320 wrote:
AWJ wrote:

Code: Select all

0.000004208333333, 0, 0, 1, 0, 1, 0, 0, 1 ; BG2 nametable  .1666 us
0.000004375000000, 0, 0, 0, 0, 0, 0, 0, 1 ; BG1 nametable  .1666 us
0.000004541666667, 0, 1, 0, 1, 0, 0, 0, 1 ; BG3 OPT        .3750 us
0.000004916666667, 1, 0, 0, 0, 0, 0, 0, 1 ; BG2 4bpp       .3750 us
0.000005291666667, 1, 0, 1, 0, 1, 0, 0, 1 ; BG1 4bpp       .3750 us
0.000005666666667, 0, 0, 1, 0, 1, 0, 0, 1 ; BG2 nametable  .2083 us
0.000005875000000, 0, 0, 0, 0, 0, 0, 0, 1 ; BG1 nametable  .1666 us
0.000006041666667, 0, 1, 0, 1, 0, 0, 0, 1 ; BG3 OPT        .3750 us
0.000006416666667, 1, 0, 0, 0, 0, 0, 0, 1 ; BG2 4bpp       .3750 us
0.000006791666667, 1, 0, 1, 0, 1, 0, 0, 1 ; BG1 4bpp       .3750 us
0.000007166666667, 0, 0, 1, 0, 1, 0, 0, 1 ; BG2 nametable
Mode 2 fetches the nametables, then two words of offset-per-tile data (again, we would need the lower address lines to distinguish them), then the patterns. Since the offset-per-tile is fetched after the nametables, each offset-per-tile fetch must apply to the next set of nametable fetches. This explains why offset-per-tile never applies to the first visible tile in a scanline.
If Mode 2 fetches only two words of offset-per-tile data for BG1 and BG2, then how calculate HOFS and VOFS for BG3?
It doesn't. Mode 2 only has 2 layers.
srg320
Posts: 32
Joined: Fri Feb 16, 2018 5:52 am
Location: Ukraine

Re: Few questions about Offset-per-tile mode

Post by srg320 »

Code: Select all

HOFS = X + BGnHOFS
VOFS = Y + BGnVOFS
ValidBit = 0x2000 for BG1, or 0x4000 for BG2
if (!IsFirst8x8Tile(BGn, HOFS)) {
  /* Hopefully these calculations are right... */
  Hval = GetTile(BG3, (HOFS&7)|(((X-8)&~7)+(BG3HOFS&~7)), BG3VOFS)
  Vval = GetTile(BG3, (HOFS&7)|(((X-8)&~7)+(BG3HOFS&~7)), BG3VOFS + 8)
  if (Hval&ValidBit) HOFS = (HOFS&7) | ((X&~7) + (Hval&~7))
  if (Vval&ValidBit) VOFS = Y + Vval
}
Pixel[X,Y] = GetPixel(Get8x8Tile(BGn, HOFS, VOFS), HOFS, VOFS)
What does means n in this formula?

In BSNES source BG3's offsets calculate separately for BG1 and BG2, that is 4 words of offset-per-tile data reads from BG3 tilemap.

Code: Select all

if(self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6) {
    uint16 offset_x = (x + (hscroll & 7));

    if(offset_x >= 8) {
      unsigned hval = self.bg3.get_tile((offset_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 0);
      unsigned vval = self.bg3.get_tile((offset_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 8);
      unsigned valid_mask = (id == ID::BG1 ? 0x2000 : 0x4000);

      if(self.regs.bgmode == 4) {
        if(hval & valid_mask) {
          if((hval & 0x8000) == 0) {
            hoffset = offset_x + (hval & ~7);
          } else {
            voffset = y + hval;
          }
        }
      } else {
        if(hval & valid_mask) hoffset = offset_x + (hval & ~7);
        if(vval & valid_mask) voffset = y + vval;
      }
    }
  } 
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Few questions about Offset-per-tile mode

Post by lidnariq »

srg320 wrote:If Mode 2 fetches only two words of offset-per-tile data for BG1 and BG2, then how calculate HOFS and VOFS for BG3?
In the offset-per-tile modes, BG3 doesn't contain a nametable. Instead it literally contains the horizontal and vertical offsets for the lower-numbered backgrounds.
srg320
Posts: 32
Joined: Fri Feb 16, 2018 5:52 am
Location: Ukraine

Re: Few questions about Offset-per-tile mode

Post by srg320 »

Maybe I'm stupid, maybe my bad English is the problem. I formulate a question on another.

For example, in Mode 2 enabled BG1 and BG2 with different scroll values and size 64x32. How to calculate the position in BG3 Map memory region to get the horizontal and vertical offsets for BG1 and BG2?
srg320
Posts: 32
Joined: Fri Feb 16, 2018 5:52 am
Location: Ukraine

Re: Few questions about Offset-per-tile mode

Post by srg320 »

So, I asked and I answer. OPT data read from BG3 Map Table, 3 (4 if tile size 16x16) lower bits of scrolling offset not use in this case. Therefore no need in addition lower bits BG1(2)HOFS to BG3 horizontal scrolling offset. I think the formula should be that:

Code: Select all

HOFS = X + BGnHOFS
VOFS = Y + BGnVOFS
ValidBit = 0x2000 for BG1, or 0x4000 for BG2
if (!IsFirst8x8Tile(BGn, HOFS)) {
  /* Hopefully these calculations are right... */
  Hval = GetTile(BG3, ((X-8)&~7)+BG3HOFS, BG3VOFS)
  Vval = GetTile(BG3, ((X-8)&~7)+BG3HOFS, BG3VOFS + 8)
  if (Hval&ValidBit) HOFS = (HOFS&7) | ((X&~7) + (Hval&~7))
  if (Vval&ValidBit) VOFS = Y + Vval
}
Pixel[X,Y] = GetPixel(Get8x8Tile(BGn, HOFS, VOFS), HOFS, VOFS)
With this variant, need to read only 2 words of OPT data like in real hardware.
I applied this formula to my FPGA project and it works.
Post Reply