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.


Contents


Tip: 16b RGBA Textures with more than 1-Bit Alphas

The 16 bit RGBA texture type is often used to texture sprites and billboards because this is the only type that allows a large number of colors. Unfortunately, this type only has one bit of alpha (which means you can't prefilter texture edges), and can lead to pixelated texture edges.

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


Tip: Rendering Clouds or Explosions

Implement rendering effects such as smoke clouds or explosions with a texture. Set the texture alpha to the outline of the smoke or explosion and render the texture onto a transparent polygon so that one can see through the smoke to the objects behind.

In this situation, the correct g*DPSetRenderMode() to use is:

RM_ZB_CLD_SURF or RM_CLD_SURF
This 'cloud' mode preserves the antialiasing of objects behind the cloud primitive, unlike TEX_EDGE and XLU_SURF modes.


Tip: Improving Z Buffer Performance

A "partial sorting" of objects being drawn can accelerate rendering when using z-buffering. The z-buffer test is a conditional write, so if objects are drawn in roughly front-to-back order, this test will often prevent the write to update the z-buffer value.


Tip: Man Pages

The default release install the man pages in /usr/share/catman. If you install it elsewhere, be sure to run 'makewhatis' and update the whatis database, so you can use the powerful 'man -k' and 'apropos' commands.

Likewise, if you installed the man pages in the default location, but you've never heard of 'man -k', check it out.


Tip: Using the Turbo Microcode

Using the new 'turbo' microcode requires some sorting on the CPU. The turbo ucode is extremely efficient if you can use a 'bounding box' or 'object centroid' sort technique. This technique can require careful modeling, and for some scenarios it's downright difficult.

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


Tip: Gamma Correction

SNES and Super Famicom do not have gamma correction hardware but the Nintendo 64 does. Some developers have indicated that the colors look washed out on the Ultra 64 with gamma correction turned on.

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.


New: Blender Add Mode

A new g*DPSetRenderMode() has been implemented that allows the pixel color to be added to the memory color.  The macro has been added to gbi.h and will be available on the next release. In the interim, you can define the following:

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


Note: System Software Release with Ultra64 Development Software

Ultra64 development software works with System Software Relase 5.3 only. We anticipate supporting 6.2 when it is released, but no date has been set.


Bug: Audio DMA Example Code

There are two bugs in the audio dma initialization example code. Neither effect the operation of the examples, but if you have incorporated this code into your game you may want to change fix it as described below.

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


Bug: midiDmon

A bug that prevented midiDmon from running in the last release (1.0F/2.0B) has been corrected. New versions of midiDmon are available via ftp from sgi.com.


© 1999 Nintendo of America Inc.