1.1
Nintendo 64 Developers Newsletters will be published periodically, as needed. These feature software and hardware system anomalies, which have been discovered, and their solutions and/or work-arounds. Development tips will also be included.
One way to get more bits of alpha (in order to create smoother outlines) is to use two tiles. The first tile describes the RGB color of the texture, while the second tile describes the alpha channel of the texture. Render the texture in two-cycle mode. In the color combiner, select T0 as the source and in the alpha combiner select T1 as the source.
A code fragment indicates how to set the combine modes and load the textures:
#define MULTIBIT_ALPHA 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL1 ... /* use special combine mode */ gsDPSetCombineMode(MULTIBIT_ALPHA, G_CC_PASS2); ... /* * Load alpha texture at Tmem = 256, notice I use a different load * macro that allows specifying Tmem address. */ _gsDPLoadTextureBlock_4b(I4molecule, 256, G_IM_FMT_I, 32, 32, 0, G_TX_WRAP, G_TX_WRAP, 5, 5, G_TX_NOLOD, G_TX_NOLOD); /* * Load color texture starting at Tmem=0 */ gsDPLoadTextureBlock(RGBA16molecule, G_IM_FMT_RGBA, G_IM_SIZ_16b, 32, 32, 0, G_TX_WRAP, G_TX_WRAP, 5, 5, G_TX_NOLOD, G_TX_NOLOD); /* * Since normal load macros use tile 0 for render, I need to set * tile 1 manually to point at alpha texture. */ gsDPSetTile(G_IM_FMT_I, G_IM_SIZ_4b, 2, 256, 1, 0, 0, 0, 0, 0, 0, 0); gsDPSetTileSize( 1, 0, 0, 31 << 2, 31 << 2); ... /* Make sure in two-cycle mode */ gsDPSetCycleType(G_CYC_2CYCLE);
In this situation, the correct g*DPSetRenderMode() to use is:
RM_ZB_CLD_SURF or RM_CLD_SURFThis 'cloud' mode preserves the antialiasing of objects behind the cloud primitive, unlike TEX_EDGE and XLU_SURF modes.
Likewise, if you installed the man pages in the default location, but you've never heard of 'man -k', check it out.
Note: We are also considering other types of sorting, such as an individual polygon sort. Desigining such a sort that works well on the Ultra64, given the graphics pipeline depth, vector RSP, etc., is not simple. If anybody has any suggestions or ideas they want to share, email Developer Support at [email protected].
If you are currently writing games for SNES or Super Famicom (or any machine that does not have gamma correction), your production path is likely to be setup to compensate for the lack of gamma correction hardware. In other words, you are probably picking pre-gamma corrected colors. If you use this same production path and turn Ultra 64 gamma correction on, you will get the wash out effect because you would have gamma corrected twice.
To undo the first gamma correction, square and shift down by 8 each color component (assuming 8 bit color) or rework your path to exclude the gamma correction stop, leaving gamma correction to the hardware.
#define RM_ADD(clk) \ IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA \ GBL_c##clk(G_BL_CLR_IN, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_1) #define G_RM_ADD RM_ADD(1) #define G_RM_ADD2 RM_ADD(2)
Several notes about this mode:
The first bug occurs in the code that allocates buffers to handle audio dma requests. In in the routine __amDmaNew (in simple/audio.c), the following code allocates the buffers:
for (i=0; i<NUM_DMA_BUFFERS-1; i++) { alLink((ALLink*)&dmaBuffs[i+1],(ALLink*)&dmaBuffs[i]); dmaBuffs[i].ptr = alHeapAlloc(&hp, 1, DMA_BUFFER_LENGTH); }
Notice that the for loop iterates to NUM_DMA_BUFFERS-1, not NUM_DMA_BUFFERS (needed since the last dma buffer can't be linked to a dmaBuffs[i+1] which doesn't exist) so the last buffer is never allocated.
The second bug (in the same code) occurs when you move the location of the dmaBuffs to uninitialized memory (non-global memory) or reinitialize the dmaBuffs. In that case, the values of the first dmaBuff's node.prev and node.next are uninitialized.
Both of these bugs can be avoided by changing the portion of the __amDmaNew routine shown above to:
dmaBuffs[0].node.prev = 0; dmaBuffs[0].node.next = 0; for (i=0; i<NUM_DMA_BUFFERS-1; i++) { alLink((ALLink*)&dmaBuffs[i+1],(ALLink*)&dmaBuffs[i]); dmaBuffs[i].ptr = alHeapAlloc(&hp, 1, DMA_BUFFER_LENGTH); } /* last buffer already linked, but still needs buffer */ dmaBuffs[i].ptr = alHeapAlloc(&hp,1,DMA_BUFFER_LENGTH);