ShootersForever.com Forum Index

GoldenEye 007 Nintendo 64 Community, GoldenEye X, Nintendo 64 Games Discussion
GoldenEye Cheats, GoldenEye X Codes, Tips, Help, Nintendo 64 Gaming Community


N64 Textures and TMEM

 
Post new topic   Reply to topic    ShootersForever.com Forum Index -> Q-Lab Hacking Department
View previous topic :: View next topic  
Trevor
007
007


Joined: 15 Jan 2010
Posts: 913
Location: UK, Friockheim OS:Win10-Skip PerfectGold:v4.3

 PostPosted: Thu Jun 04, 2015 6:21 am    Post subject: N64 Textures and TMEM Reply with quote Back to top

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)

    0 [0x0] = 1 Mask cannot be 0 since Mask0=Pass0
    1 [0x1] = 2 (Min Width 32Bit)
    2 [0x2] = 4 (Min Width 16Bit)
    3 [0x3] = 8 (Min Width 8Bit)
    4 [0x4] = 16 (Min Width 4Bit)
    5 [0x5] = 32
    6 [0x6] = 64
    7 [0x7] = 128
    8 [0x8] = 256 (Max Hight)
    9 [0x9] = 512
    10 [0xA] = 1024 (Max Width)
    11 [0xB] = 2048
    12 [0xC] = 4096
    13 [0xD] = 8192
    14 [0xE] = 16384
    15 [0xF] = 32768



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.

Texture UV/ST mapping
UV's on the N64 are texel Space co-ordinates S & T.
ST co-ordinates are limited to +1023.967 and -1024 and are addressed in a Signed 10.5bit format (16bit)
So, if a texture is 32x32 then the maximum UV for any triangle is +/-31.99 (1023.967 / 32)
If a texture is 64x64 then the maximum UV for any triangle is +/- 15.99 (1023.967 / 64)

Likewise, if a texture was 1024x1x4 then the maximum UV would be 1.99 starting at -1, ending at 0.99


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:
    4-bit intensity ( I )
    4-bit intensity with alpha ( I/A ) ( 3/1 )
    4-bit color index ( CI )
    8-bit I
    8-bit IA ( 4/4 )
    8-bit CI
    16-bit red, green, blue, alpha ( RGBA ) ( 5/5/5/1 )
    16-bit IA ( 8/8 )
    16-bit YUV ( Luminance, Blue-Y, Red-Y )
    32-bit RGBA ( 8/8/8/8 )


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

    4-bit(I,IA) 8,192
    4-bit Color Index 4,096 (plus 16 palettes)
    8-bit(I,IA) 4,096
    8-bit Color Index 2,048 (plus 256-entry LUT)
    16-bit RGBA 2,048
    16-bit IA 2,048
    16-bit YUV 2,048 Y's, 1,024 UV pairs
    32-bit RGBA 1,024



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.


----------------------------------------------------------------
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

_________________


Last edited by Trevor on Thu Mar 31, 2016 2:36 am; edited 2 times in total
 
View user's profile Send private message
AL64inthedark
00 Agent
00 Agent


Joined: 18 Sep 2014
Posts: 544
Location: France

 PostPosted: Fri Apr 07, 2017 8:32 pm    Post subject: Reply with quote Back to top

Mipmapping is still a struggle to me. Lots of time I try things with 8CI, only to discover that it blinks when far.
So I better ask you advice. If you want to do a multitexture wall like this one :


Knowing that those textures don't have to tile, what would be a 8CI resolution, square or rectangle, doesn't matter, that will mimap well enough ?

You can do interesting thing with 8CI like 128x9 or 64x17 like those metal door in Runway :

If I understood well you can go 64x24, it will have the same number of mipmap than 64x17, which is 4. Am I right ?

So I better ask other, because every try just takes so much time (loading each textures one by one, the time taken to do it etc...)
The worst thing with mutitexture is when you want to just increase contrast or little tweaks. You have to add all those textures one by one lol (not funny actually...)

Thanks for reading.
 
View user's profile Send private message MSN Messenger
Trevor
007
007


Joined: 15 Jan 2010
Posts: 913
Location: UK, Friockheim OS:Win10-Skip PerfectGold:v4.3

 PostPosted: Sat Apr 08, 2017 1:45 am    Post subject: Reply with quote Back to top

No Problem, 8Bit CI is limited to 2KB (upper TMEM is filled by TLUT).
You need to reserve approximately 666B for Mip-Map but you also need to watch the horizontal padding.

If we use a Square Number for width (16, 32, 64 etc) we will waist the least.

You are quite correct that 64x24x8 should work with 4 levels.

You will need to set each texture to 4 levels by hand since PG will automatically set them to 7.

If this still fails then it must mean that the Mip-Map level value is not being read and you will have to go to 64x23.

Please return a result, hope it works. Also, I'd only do a couple of textures for testing, no point in doing them all to find something wrong.

Please Note, we are filling TMEM with each texture, that means that for every poly TMEM needs to be re-filled from RAM and since they are unique there are no optimisations you can do with the textures like rendering all polies with same texture.

Trev
_________________
 
View user's profile Send private message
AL64inthedark
00 Agent
00 Agent


Joined: 18 Sep 2014
Posts: 544
Location: France

 PostPosted: Sun Jun 18, 2017 1:19 pm    Post subject: Reply with quote Back to top

Sorry not to be able to talk about the result of my last question, I had various issues IRL which made me pause on that (I'll be back on my Natural envirronment someday).

Right now I'm at a hospital (doing fine), but I only managed to borrow a laptop with vista and a ram of 1 giga (yes such things where done...by idiots or crooks).

So, I started a new map few days ago, and was wondering something about textures.

Question : Let's take a 8CI 64x24 as an example.
So, 64 is multiple of 2 and align to 64 bit boundary, so it is tilable. 24 is not.
But can I make it tile only on the side that is 64, and S mirror it, like in that mockup screenshot. Does that work ?
I would say yes, like in your 4CI example of 48x32 which tile 64x32. We can see the side that is 32 is tiling nicely...

The textures used :


How they are meant to tile and Mirror :

On that art deco ceiling I'm working on, the longest sides on that screen would be done of 2 rows of 64x24x8CI, S mirrored.

Subsidary question :
As you can see on the back, I did a gold colored one (a bit too satured...). It would be great if we could just switch palettes and do like they did on fighting games. I mean, starting from a texture, have some variety by just switching the palettes. I believe such a feature isn't available in GE/PD, but out of curiosity, could such a thing be added...and would it be interesting, performance wise ?
 
View user's profile Send private message MSN Messenger
Trevor
007
007


Joined: 15 Jan 2010
Posts: 913
Location: UK, Friockheim OS:Win10-Skip PerfectGold:v4.3

 PostPosted: Sun Jun 25, 2017 5:16 am    Post subject: Reply with quote Back to top

Hi, sorry for the delay in responding - starting up a business is quite a bit more complicated than first thought, not that the work is difficult, but getting contracts is. Getting back to GF soon. Smile

Quote:
Question : Let's take a 8CI 64x24 as an example.
So, 64 is multiple of 2 and align to 64 bit boundary, so it is tilable. 24 is not.
But can I make it tile only on the side that is 64, and S mirror it, like in that mockup screenshot. Does that work ?
I would say yes, like in your 4CI example of 48x32 which tile 64x32. We can see the side that is 32 is tiling nicely...


Unfortunately not, the side that is 24 will show odd results along its bottom border even with mirror on. the side that is 24 must fill the polygon to avoid this. (as you already noted I show in image)
Its one of the reasons PG in its early days stated "All textures must be square number" to avoid confusion.

My next suggestion which includes your second question is, make your image 1 bmp at 4bit 128x24.

I hadnt realised the colours used untill I clicked your image and was about to suggest vertex shading, however let me try to answer the question directly rather than trying to skirt round it.


This will get very complicated and probably not totally correct

What you can do is load a 16x16x4 texture containing a colour pallet.

get the ram (dram) address for this pallet loaded during the level. by looking for an F0 command

Code:
F0 = gsDPLoadTLUT_pal16(pal, dram)               
                            
   gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, dram),   
      FD = gsSetImage(cmd, fmt, siz, width, i)            
      {                           
         _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) |         
         _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12),      
         (unsigned int)(i)                  
      }
      // looks like
      // FD XX XX XX  00 00 00 00
   gsDPTileSync(),   
   // looks like
   // E8 00 00 00  00 00 00 00
   
   gsDPSetTile(0, 0, 0, (256+(((pal)&0xf)*16)), G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0),   
      F5 = gsDPSetTile(fmt, siz, line, tmem, tile, palette, cmt,   
            maskt, shiftt, cms, masks, shifts)         
      {                           
         _g->words.w0 = _SHIFTL(G_SETTILE, 24, 8) | _SHIFTL(fmt, 21, 3) |
                  _SHIFTL(siz, 19, 2) | _SHIFTL(line, 9, 9) |   
                  _SHIFTL(tmem, 0, 9);            
         _g->words.w1 = _SHIFTL(tile, 24, 3) | _SHIFTL(palette, 20, 4) |   
                  _SHIFTL(cmt, 18, 2) | _SHIFTL(maskt, 14, 4) |   
                  _SHIFTL(shiftt, 10, 4) |_SHIFTL(cms, 8, 2) |   
                  _SHIFTL(masks, 4, 4) | _SHIFTL(shifts, 0, 4);   
      }
      // looks like
      // F5 60 06 00  00 FD 83 60
      
   gsDPLoadSync(),      
   // looks like
   // E6 00 00 00  00 00 00 00   
   
   gsDPLoadTLUTCmd(G_TX_LOADTILE=7, 15),
      gsDPLoadTLUTCmd(tile, count)               
      {                           
         _SHIFTL(G_LOADTLUT, 24, 8),               
         _SHIFTL((tile), 24, 3) | _SHIFTL((count), 14, 10)      
      }
      // looks like
      // F0 00 00 00  07 03 C0 00
      
   gsDPPipeSync()
   // looks like
   // E7 00 00 00  00 00 00 00


load the normal texture for the gold floor and then use the dram location you got, in fact you should be able to copy and paste this whole block after the C0 GE_Texture command.


The above probably wont help much but maybe someone will make use of it.
There is a project to decompile GE into Source C, at that point we can edit the C0 command or even just skip it altogether since at the source level we wouldn't need to worry about ram addresses.

Trev
_________________
 
View user's profile Send private message
AL64inthedark
00 Agent
00 Agent


Joined: 18 Sep 2014
Posts: 544
Location: France

 PostPosted: Wed Jul 19, 2017 4:27 am    Post subject: Reply with quote Back to top

Quote:
Hi, sorry for the delay in responding

Hi trevor. There's no need to excuse yourself. We're all in the same boat, trying to manage our IRL life and to do something out of GE/PD engines. And you already been of great help sharing your knowlege, which helped me progressing a lot.

It took me so many times to realise what I was doing wrong, and I have to do again a few texture now because of this.
Here's why I was thinking it was possible. I saw that the 64 pixels side was repeating and not that the 24 side was tiled.



Now I think I'll won't forget that !

Could it be possible for you to clarify what are the numbers that are aligned on 64 bit boundary and multiple 2 for both 4 bit textures and 8 bits.
For 8 bits, I would say it is 8, 16, 32, 64, 128. But I'm so bad (and lazy) about maths... Or is 80x16 tileable too in both side ?
Knowing that without the need to try myself would be a huge time saver.
 
View user's profile Send private message MSN Messenger
Trevor
007
007


Joined: 15 Jan 2010
Posts: 913
Location: UK, Friockheim OS:Win10-Skip PerfectGold:v4.3

 PostPosted: Fri Jul 21, 2017 3:04 pm    Post subject: Reply with quote Back to top

AL64inthedark wrote:
It took me so many times to realise what I was doing wrong, and I have to do again a few texture now because of this.
Here's why I was thinking it was possible. I saw that the 64 pixels side was repeating and not that the 24 side was tiled.

If your 24 side spanned across the tri then it would be valid, but you had a repeat of the bottom row which means it would be corrupt.
Actually, you can mirror the top of the texture since that will be aligned at 0.


my example above uses 32 width but that's not what we are concerned with, what we are concerned with is the height.
see how the mask goes beyond the height of the texture. a mask of 4 is 16 and so too small.
but you notice that along the top at the origin we do align.

AL64inthedark wrote:

Now I think I'll won't forget that !

Could it be possible for you to clarify what are the numbers that are aligned on 64 bit boundary and multiple 2 for both 4 bit textures and 8 bits.
For 8 bits, I would say it is 8, 16, 32, 64, 128. But I'm so bad (and lazy) about maths... Or is 80x16 tileable too in both side ?
Knowing that without the need to try myself would be a huge time saver.


multiple of 2 [mask 0-7] (tile/mirror constraint width and height):
1 [0]
2 [1]
4 [2]
8 [3]
16 [4]
32 [5]
64 [6]
128 [7]

64bit Boundry (4bit) (width constraint only)
16
32
48
64
80
96
112
128

64bit Boundry (8bit) (width constraint only)
8
16
24
32
40
48
56
64
72
80
88
96
104
112
120
128


Trev
_________________
 
View user's profile Send private message
AL64inthedark
00 Agent
00 Agent


Joined: 18 Sep 2014
Posts: 544
Location: France

 PostPosted: Sun Jul 23, 2017 7:52 am    Post subject: Reply with quote Back to top

Thanks Trevor this is helpful.

When we talked about 64x24 8CI, you made me realise that we could set the number of mipmap inside the image editor.

I did take a look at what is set for the originals, and I've found 64x32CI4 that are set to either 7 and even 0.
Your calculator indicate 5 when tile height=1 and 3 when tile width=64 bits.

So..aheum, what's that ?
Also, maybe more interesting, is how should I set it up once I imported my textures ? It sets my 64x32CI4 textures to 6.
_________________
Listen to me
https://youtu.be/BzZ3k3NmhLM?t=25m51s
 
View user's profile Send private message MSN Messenger
Trevor
007
007


Joined: 15 Jan 2010
Posts: 913
Location: UK, Friockheim OS:Win10-Skip PerfectGold:v4.3

 PostPosted: Tue Jul 25, 2017 11:27 am    Post subject: Reply with quote Back to top

Quote:
I did take a look at what is set for the originals, and I've found 64x32CI4 that are set to either 7 and even 0.
Your calculator indicate 5 when tile height=1 and 3 when tile width=64 bits.

So..aheum, what's that ?


32 can be divided by - and the subsequent result divided by 2 five times before the final result cannot be further divided (1)
32 > 16 > 8 > 4 > 2 > 1

but, if you divide 64 by 2 five times you get a width of 2.

since 4Bit pads to 16 my second option stops the mip-map at this width resulting in 3

64 > 32 > 16


Initially I thought it would save a lot of space to do the calculation, however since GE only loads 1 texture into TMEM at any time and the saving is very small, your probably best to accept the padding and get better mip-mapping.

Only in extreme cases will stopping at 64bit make a texture fit that otherwise wouldn't.



As for GE levels always being either 7 or 0, I guess they don't really care about the number.
Each mip-map must automatically stop when there is no more room or a side = 1.
Setting the number should force the stop though.


Trev
_________________
 
View user's profile Send private message
Trevor
007
007


Joined: 15 Jan 2010
Posts: 913
Location: UK, Friockheim OS:Win10-Skip PerfectGold:v4.3

 PostPosted: Sat Aug 19, 2017 4:36 pm    Post subject: Reply with quote Back to top

While reversing a DisplayList I came across a way to maybe inject custom Texture handling code into GE.

It seems that you can load a texture using its ID found in PG by adding ABCD in front
eg. FD 70 00 00 AB CD 08 3A

Also I found some interesting info about dxt which now makes sense to me.

For now Ill post the code and open it for discussion.
Since its texture related I thought here would be the best place.
Code:

static Gfx SmokeOnly_dl[] = {
/*E7 00 00 00 00 00 00 00*/ gsDPPipeSync(),
/*BA 00 14 02 00 00 00 00*/ gsDPSetCycleType(G_CYC_1CYCLE),
/*B9 00 03 1D 00 50 4B 50*/ gsDPSetRenderMode(G_RM_ZB_XLU_SURF),
/*BA 00 10 01 00 00 00 00*/ gsDPSetTextureLOD(G_TL_TILE),
/*FC 12 18 24 FF 33 FF FF*/ gsDPSetCombineMode(MODULATERGBA),
/*BB 00 00 01 FF FF FF FF*/ gsSPTexture(0, 0, 1, 0, G_ON),
/*   [AB CD 08 3A]   A = mirror of 0 therefor 0BCD 0xxx = CartDomain2/SRAM.
      Actually we know GE uses a list of ID's that point to textures
      083A points to ROM B30970
      According to Zoinkity though, ABCD is handled specially by some code - could be the same thing.
      */
/*FD 70 00 00 AB CD 08 3A*/ gsDPSetTextureImage(G_IM_FMT_IA, G_IM_SIZ_16b, 0, "ABCD 83a"), //83A B30970 (00), 38 38 Size 05ED [Smoke 56x56x8IA]
/*F5 70 00 00 07 00 00 00*/ gsDPSetTile(G_IM_FMT_IA, G_IM_SIZ_16b, 0, 0, 7, 0, G_TX_WRAP, 0, 0, G_TX_WRAP, 0, 0), // fmt, sz, line, tmem, tile, pal, cmt, mt, st, cms, ms, ss
/*E6 00 00 00 00 00 00 00*/ gsDPLoadSync(),//load texture as 16bits
/*
*   Remember that ult uls lrs lrt are all 10.2 bit, that is 11 1111 1111.11 (1023.75)
*   ult and ulr are usually 0 for texture load while lrs and lrt are used for clamp only to indicate the "end" of texture
*
*   Couldnt reconcile 10.2 equaling -1024 to 123.99, however, Texture load is 10.2 (0 to 1023.75) and Vertex Co-Ord is s10.5 (-1024 to 1023.99)
*   now it makes sense
*
 *  Dxt is the inverse (1/n) of the number of 64-bit words in a line of
 *  the texture being loaded using the load_block command. 
 *   In other words, dxt is how much fraction of 1 line each word occupies
 *      Since 56 x8bit is 7 words, 1/7 = 0.143
 *  If there are any 1's to the right of the 11th fractional bit,
 *  dxt should be rounded up.  The following macros accomplish
 *  this.  The 4b macros are a special case since 4-bit textures
 *  are loaded as 8-bit textures.  Dxt is fixed point 1.11. RJM
 *
*   Update TMEM doc on GEForever forum

   G_TX_DXT_FRAC = 11
   #define TXL2WORDS(txls, b_txl)   MAX(1, ((txls)*(b_txl)/8))
   #define CALC_DXT(width, b_txl)   \
         (((1 << G_TX_DXT_FRAC) + TXL2WORDS(width, b_txl) - 1) / TXL2WORDS(width, b_txl))
   
   gDPLoadBlock(pkt, G_TX_LOADTILE, 0, 0,                \
      (((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1,\  //INCR = 3,1,0,0 and SHIFT = 2,1,0,0 at 4,8,16,32 bit
      CALC_DXT(width, siz##_BYTES));                   //_BYTES = 0,1,2 or 4 at 4,8,16 and 32bit respectivly
*
*   61F = 0110000111.11 = 391.75 ? doesnt matter, using calc above works
*   125 = 0.00100100101 = 0.14306640625 = 7 words per line
*      Handy calculator of dxt is (float)dxt / (float) (1 << 11)
*         125 = 293 / 2048 = 0.14306640625
*
*      Original dxt Number was (2048 + ((64*1)/8) - 1) / ((64*1)/8) = 293
*      Aha! this function creats an integer, bit-shift again and we get 0.143 as expected
*      Also, lets update the definition of dxt, dxt is how much fraction of 1 line each word occupies
*      Since 56 is 7 words, 1/7 = 0.143
*      what an awfull system, no wonder they expected people to use LoadTextureBlock() instead.
*/
/*F3 00 00 00 07 61 F1 25*/ gsDPLoadBlock(7, 0, 0, ((((56*56)+1)>>1)-1), (1/7)), //now set correct values, 8bit IA 56x56 (mask=64x64),
/*F5 68 0E 00 00 01 80 60*/ gsDPSetTile(G_IM_FMT_IA, G_IM_SIZ_8b, 7, 0, 0, 0, G_TX_WRAP, 6, 0, G_TX_WRAP, 6, 0), // fmt, sz, line, tmem, tile, pal, cmt, mt, st, cms, ms, ss //mask=64tx
/*F2 00 00 00 00 0D C0 DC*/ gsDPSetTileSize(0, 0, 0, 55.0, 55.0), //"Re-square" the loadblock command also If tile is clamp, then clamp at 55.
/*BA 00 0E 02 00 00 00 00*/ gsDPSetTextureLUT(G_TT_NONE),
/*E7 00 00 00 00 00 00 00*/ gsDPPipeSync(),
/*B8 00 00 00 00 00 00 00*/ gsSPEndDisplayList(),
};

_________________
 
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    ShootersForever.com Forum Index -> Q-Lab Hacking Department All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Cobalt 2.0 BB theme/template by Jakob Persson.
Copyright 2002-2004 Jakob Persson


Powered by BB 01, 02 BB Group

 


Please Visit My Other Sites: GoldenEyeForever.com | GrandTheftAutoForever.com

Got kids? Check out my Dora The Explorer site with games and coloring pages!

Our forums feature Nintendo 64 games, GoldenEye 007 N64 New Maps and Missions, GoldenEye Cheats, N64 Emulator, Gameshark, GoldenEye Multiplayer and more!

[ Privacy Policy ]