Attribute shift register reloading

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Dartht33bagger
Posts: 59
Joined: Sat Jan 03, 2009 3:28 pm
Location: Oregon
Contact:

Attribute shift register reloading

Post by Dartht33bagger »

It's been almost a year since I've looked at my old NES emulator (and the code is ugly....ugh) but I want to get back in the swing of things. First off, I'd like to solve an issue that had been plaguing me for a while.

I still cannot figure out how to correctly load the two attribute shift registers. I can find nothing on the wiki about how to reload the shift registers. From searching on the forum (and from looking at my old code), I know a 4 to 1 mux is used to somehow refill the two attribute shift registers. However, there is a ton of conflicting information out on the forums.

This post from one of my old threads states that the two attribute shift registers are filled at the same time: viewtopic.php?f=3&t=10351&p=116394&hili ... ft#p116394
This post states that only the high attribute shift register is reloaded and the low shift register is untouched: viewtopic.php?f=3&t=10817&hilit=attribu ... 30#p123316
This post states that two adjacent tiles should have the same attribute bits: viewtopic.php?f=3&t=10817&hilit=attribu ... 30#p123307

There were a few more posts I read as well, that only added more conflicting information onto this. I just need to know three things:

1. Are both shift registers reloaded?
2. What are the mux select bits? Right now I am using coarseX and coarseY.
3. Are adjacent tiles supposed to have the same attribute bits?

This is the code I have right now:

Code: Select all

const void ppu::fourToOneMux()				//Used to refill attribute shift registers
{
	//Select first bit of coarse X and Y for MUX select
	const byte coarseX = 0x1;
	const byte coarseY = 0x20;
	bool xBit, yBit;				//Holds the coarse X and Y bits
	bool attBit1, attBit2;				//Holds the two attrbute bits. 1 = low bit, 2 = high bit
	xBit = ppuAddress & coarseX;
	yBit = ppuAddress & coarseY;
	
	
	//Bit 0 = xBit, Bit 1 = yBit
	if(xBit == true && yBit == true)		//Choose bits 6 and 7
	{
		attBit1 = attFetch & 0x40;
		attBit2 = attFetch & 0x80;
	}
	else if(xBit)					//Choose bits 4 and 5
	{
		attBit1 = attFetch & 0x10;
		attBit2 = attFetch & 0x20;
	}
	else if(yBit)					//Choose bits 2 and 3
	{
		attBit1 = attFetch & 0x04;
		attBit2 = attFetch & 0x08;
	}
	else						//Choose bits 0 and 1
	{
		attBit1 = attFetch & 0x01;
		attBit2 = attFetch & 0x02;
	}
	
	//Sets all the bits the same
	if(attBit1) highAttShift |= 0xFF;		//Low byte 1s
	else highAttShift &= ~0xFF;			//Low byte 0s
	
	if(attBit2) lowAttShift |= 0xFF;		//Low byte 1s
	else lowAttShift &= ~0xFF;			//Low byte 0s
}
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Attribute shift register reloading

Post by koitsu »

I can't answer some of the questions here because they seem to be discussing how the actual PPU works internally (re: shift registers), but regarding the attribute table and "a 2x2 tile grid being represented by 2 bits in the attribute table": that is absolutely correct.

There's multiple ways to interpret/understand the attribute table though. This is why in NESTECH.TXT I wrote it the way I did, providing multiple phrasings/explanations.

Per my recent request, Tepples updated the attribute table wiki doc to try and make this more clear.

Anyway, here's the section from NESTECH.TXT describing it. Read it slowly/carefully:

Code: Select all

  E. Attribute Tables
  -------------------
    Each byte in an Attribute Table represents a 4x4 group of tiles on the
    screen. There's multiple ways to describe what the function of one (1)
    byte in the Attribute Table is:

      * Holds the upper two (2) bits of a 32x32 pixel grid, per 16x16 pixels.
      * Holds the upper two (2) bits of sixteen (16) 8x8 tiles.
      * Holds the upper two (2) bits of four (4) 4x4 tile grids.

    It's quite confusing; two graphical diagrams may help:

      +------------+------------+
      |  Square 0  |  Square 1  |  #0-F represents an 8x8 tile
      |   #0  #1   |   #4  #5   |
      |   #2  #3   |   #6  #7   |  Square [x] represents four (4) 8x8 tiles
      +------------+------------+   (i.e. a 16x16 pixel grid)
      |  Square 2  |  Square 3  |
      |   #8  #9   |   #C  #D   |
      |   #A  #B   |   #E  #F   |
      +------------+------------+

    The actual format of the attribute byte is the following (and corris-
    ponds to the above example):

       Attribute Byte
         (Square #)
      ----------------
          33221100
          ||||||+--- Upper two (2) colour bits for Square 0 (Tiles #0,1,2,3)
          ||||+----- Upper two (2) colour bits for Square 1 (Tiles #4,5,6,7)
          ||+------- Upper two (2) colour bits for Square 2 (Tiles #8,9,A,B)
          +--------- Upper two (2) colour bits for Square 3 (Tiles #C,D,E,F)
I really should have used letters for the "Squares" (thus letters in the individual attribute byte) rather than numbers, but hey, that's how I did it in 1999.
Post Reply