N64 Textures and TMEM Explination			
		==================================			
									
	Any Link Below is truncated to the root of SDK Manual, 		
	This Link is not visible and I request it not be Spread.	
         htt.../NINTENDO%2064%20SDK%205%20_CDROM/man/allman50/  	
		Can Also be downloaded at romhacking			
									
		Compiled By Trevor					
		Credits to Zoinkity for Original Find			


While searching for other refrences to the subject here I found a few sources of out-dated mis-information and so I thought Id start a new post with relevent Info.

I have tried to simplify the info while remaining technichal.

This is not about the CO command in GE/PD but more general information regarding TMEM and its limitations.
One such mis-information floating around was that Mip-Mapping was the cause of 2K boundry. It is in fact much worse than that if you want Full 6-Level Mip-Maps as you are effectivly limited to 1KB for Colour Index Textures!
(1,536Bytes can be used for an excelent 4-level Mip-Map system)
I made a calculator for TMEM usage based on all the info here.



Texture Engine

The Texture Engine Fetches from TMEM the four nearest texels to the screen pixel. In Copy Mode this is a line of 4 texels, while in 1 or 2 cycle this is 2x2 texels.
The Texture Engine uses TMEM, an on-die 4KB cache of the RCP, because texturing requires a large amount of random accesses with consistent access time to texture memory, it is impractical to texture directly from DRAM.
(But not impossible?)


Texture Tiles
The game application can load various sizes of texture with different formats anywhere in the 4 KB TMEM where where up to eight tiles are accessible at any time which is usually used for Mip-Mapping.

However there are certian restrictions on this discussed below. The first which applies no matter the format or positioning within TMEM is that ALL textures must Align to 64bit boundries in each row.
eg. a 32bit texture MUST use multiples of 2 texels, while a 4bit texture MUST use multiples of 16 texels.

Tiles can be up to 1024 columns wide and up to 256 rows tall. Tiles do not have to be sized to a power of 2 (wrapping and mirroring, however, happen on power-of-2 boundaries and 64bit Alignment still applies).

Texture Wrap Powers and Texel legnths (width/height)

Note:
Clamp can be made to clamp the last texels of any size texture, Including Non-Powers of 2, by setting Mask = 0 and setting SL, TL, SH, TH all to within the texturespace.


Multiple Tile Textures
TMEM can have up to 8 tiles loaded so long as they fit within TMEM.
In 2 cycle mode 8((2x2)+(2x2)) texels are drawn from 2 sequential tiles for use in Mip-Mapping or detail Modes.
There are no explicit restrictions requiring power of two tile-sized decrements for mipmaps, nor the requirement to use all 8 tiles.

Another use for Tiles is in the Colour Combiner where a Colour Tile (T) can be assigned to the Colour Combiner and an Alpha Tile (T+1) can be assigned to the Alpha Combiner. In this configuration however there is NO Mip-Mapping.

Yet another use is by sliding 2 tiles in opposite directions you could achive a wave effect, achived by 'sliding' Tile+1 accross s and t co-ords using SetTileSize().
Code:
    /*
    * Animate River Texture
    */

   flow++;
    if (flow == 64) flow = 0;

   gDPSetTileSize(glistp++, 1, // Tile1
         (0     << G_TEXTURE_IMAGE_FRAC), //UpperleftT
         (flow  << (G_TEXTURE_IMAGE_FRAC-1)), /* UperLeftS -1 to slow down the flow */
         (32-1) << G_TEXTURE_IMAGE_FRAC, //LowerRightS
         (32-1) << G_TEXTURE_IMAGE_FRAC); //LowerRightT

   gSPDisplayList(glistp++, river_dl); //Call river_dl

   gDPFullSync(glistp++);
   gSPEndDisplayList(glistp++);



// Water DL in GE have been found however I beleve there are missing parts which I will add here (wont have hex)

/*
 * Animate water Texture
 */

flow++;
if (flow == 64) flow = 0;

F5480400 00014050   gDPSetTile(Type=8BitCI,
                  Line=2, //words in Row.(64*2)/8=16 texels
                  Tile=0
                  Maskt=5, // Specifies the wrap position of texel 32 (2^5=32)
                  Masks=5)
               
F5480400 01014050   gDPSetTile(Type=8BitCI,
                  Line=2,
                  Tile=1
                  Maskt=5,
                  Masks=5)
F2002002 00000000    gDPSetTileSize(UpperLefts=flow  << (G_TEXTURE_IMAGE_FRAC-1),
                  UpperLeftt=flow  << (G_TEXTURE_IMAGE_FRAC-1),
                  Tile=0,
                  LowerRights=(32-1) << G_TEXTURE_IMAGE_FRAC,
                  LowerRightt=0)
F2002002 01000000   gDPSetTileSize(UpperLefts=flow  << (G_TEXTURE_IMAGE_FRAC-1),
                  UpperLeftt=flow  << (G_TEXTURE_IMAGE_FRAC-1),
                  Tile=1,
                  LowerRights=(32-1) <<G_TEXTURE_IMAGE_FRAC>,

                  LowerRightT=(32-1) <<G_TEXTURE_IMAGE_FRAC>)

FA00000F FFFFFFFF    SetPrimColour(min=00, LODF=0F, R=255, G=255, B=255, A=255) //force tiles to show at
            //0.05859375. Probably also increases and decreases for effect.
            // LODF=(Flow*4)/256

BA001102 00000000    SetTextureDetail(Clamp)
BA000C02 00002000   SetTextureFilter(BiLERP)
FC272C04 1F1093FF   SetCombiner(TRILERP_Prim, ModulateRBGA2)
B900031D 0C182078   SetRenderMode(AA, Z_CMP, Z_UPD, IM_RD, A_CVG, CLAMP, OPA
                     CLR_IN*0 + CLR_IN*1 , CLR_IN*AIN + CLR_MEM*1-A)
BA001001 00000000   SetTextureLOD(Tile)
BA001402 00100000   SetCycle(2)
B7000000 00002000   SetGeometryMode(CullBack)
B8000000 00000000   gSPEndDisplayList(glistp++);


Texture Image Types and Format
The texture unit supports ten different combinations of texel size and format:


The Intensity Alpha type (IA) replicates the I value on the RGB channels and places the A value on the A channel. The IA 16-bit format is 8/8, the 8-bit format is 4/4, and the 4-bit format is 3/1.

The 4 & 8 Bit I Types also duplicate their I value on the A channel so can be used as transparncy maps if used on the Alpha Combiner.

Palette Depth for CI Textures is 16Bit (5/5/5/1)


Color-Indexed Textures

These are some restrictions on the size and placement of CI texture maps within the TMEM. The TMEM is actually partitioned into two halves. Four texels are sampled from the first bank and fed into the second bank for texture/color/index table lookup (TLUT).



8-bit CI textures all require 2 KB (256 x 64 bits per entry) second half banks to hold the TLUT, while 4-bit CI texture can have up to 16 separate TLUTs.

Since the Upper half is reserved for TLUTS all tiles must reside below 2Kb.
This means that a 64x64x4 CI texture does not have room for Mip-Map Tiles unless they are loaded seperatly.

The Largest single Automatically Mip-Mapping (3Level) Texture that can be loaded is:
64x48 (32x24 + 16x12) 4Bit = 1536+(384+96)=2016byte

An example taken from PD is the washing Mashine at 64x56x4. This can have 1 more Mip-Map Tile at 32x16 to take it up to exactly 2048.

However refer to wrapping requirements on both these examples.


Below is a list of types and the total number of Texels that will fit in TMEM



The problem I see is that Nintendo Waisted TMEM in CI Opperation. There is NO benifit in 8bit over 16bit in TMEM. In fact 16bit has a slight advantage since 2 texures can co-exist while 8bit can only have 1 TLUT.

4bit CI should have loaded TLUTS back from end of TMEM and dispenced with mirroring 4 times the colours.


Now, what Id love to know is how GoldenEye's manual Mip-maps work.
I can see a 128x47 and 64x16 fitting together but not a 128x47 and 64x24...
Also, Rare used resolutions lower than 16 wide which is pretty pointless.
eg


Oops, My Mistake, I miscalculated... They do fit
((128*47)+(64*24)+(16*13)+(16*7)+(16*4)+(16*3))/2=3992 (<4096=True)

Trev

Other Docs:
SetCombine()
SetRenderMode() SetAlphaCompare()
SetTile()


Mip-Map Calculator Read Me:

To Use the Calculator decide which Bit Depth you wish to use for your texture.

This example will use 4Bit IA.

Enter a desired Width and height for a texture.

This example will use 64x64


Leaving everything else alone shows us that a 64x64 texture with 6 Levels (Base + 5 Mip-Maps) will use a total of 2,800 Bytes. The Bar is Blue, so all is good.

If we wanted to use an 8Bit IA we would see tha bar change to Red and a message show up showing how over TMEM we are. In this case, 1,392 Bytes.


We can also set when to stop the Mip-Map Pyrimid. Returning to 4Bit IA and setting to stop at Width=64bit we can see that the number of levels are reduced to 3 and we save 112Bytes.


Errors:

Setting an odd width will cause the width to turn red. The calculator will then pad to allignment and continue.
In this case 47 is padded to 48.


Setting an Out Of Range number in either width or height will turn them red.

Notes:
You may notice Mask and Wrap Values.
Mask signifies the value used in the RSP for SetTileSize() and may not be of use to you.
Wrap Signifies the point in texels that the texture will start again (like a tiled floor). It is also the same value for Clamp and Mirror.
While textures do not have to be Powers of 2 (eg a face or guard texture) Walls, floors and other 'Tiled' objects must be a power of 2 to match this value otherwise odd effects will show up on your object.
Mask cannot be 0 since Mask0=Pass0 This has not been added to the calculator and so 1 will show as valid.

----------------------------------------------------------------
ADVANCED:

Custom Levels:

Unchecking Auto-Calculate Levels pust you in charge of the number of levels and also the size of each level, Lets deal with the first option.

Setting the number of levels is as simple as entering a number between 1 and 8, however, you will not be able to enter a number if the texture is not big enough to divide that many times.
Eg, Entering 8 will show a message stating there is not enough texture space to do 8 and will be automatically set to the highest number, this case being 6.


Custom Level Sizes:
After entering the desired levels you can also set your own dimentions for each level.
This is an Advanced feature and does not do any checking. You must remember Mask powers and 64bit allignment padding. Failure to do so will not crash the program however you will get an inaccuriate result.

This example I set 2 Levels (Base and +1) leaving the base at 64x64 and set the width and height of the +1 to 16.
(64x64x4)/8 = 2048
(16x16x4)/8 = 128
2048 + 128 = 2176 as shown