gSPBgRect1Cyc

gSPBgRect1Cyc [Macro]

Function

gSPBgRect1Cyc

Renders Background (BG) image (can enlarge/reduce)

Syntax

#include <ultra64.h>        /* gs2dex.h */
gSPBgRect1Cyc(Gfx *gdl, uObjBg *bg)
gsSPBgRect1Cyc(         uObjBg *bg)

Arguments

gdl
the display list pointer.
bg
the pointer to the BG drawing data structure.

Description

It draws BG image. This macro is the dedicated BG image drawing macro for use in 1-cycle mode. It has the following special features and limitations:

This macro cannot be used in copy mode. For information about modes, see Section 2.2.7 "Drawing Cycle Modes" in the N64 Kantan Manual. For information about setting the cycle type, see gDPSetCycleType. If there is no need to scale a drawing (enlarge/reduce), or if you want to use copy mode, then BG image rendering can be processed faster using g*SPBgRectCopy.

Description

This macro supports bilinear interpolation display of images. When bilinear interpolation display is used, texels appear less jagged and the image looks smoother when it is enlarged, compared to normal point sampling display. This effect is less apparent when the image is reduced.

The RDP's drawing performance declines when bilinear interpolation is used. The fewer the number of image lines that can be loaded into TMEM at one time, the greater the extent of this decline in performance. For example, when a 640x480 image is reduced by half for drawing in a 320x240 frame, the amount of overhead from bilinear interpolation is far greater than when a 320x240 image is drawn with no scaling. In addition, the RDP's drawing performance drops significantly compared to when point sampling is used. Considering the diminished effect obtained with bilinear interpolation when the image is reduced, you may want to switch to point sampling display.

This macro automatically divides an image into a number of subplanes for drawing. However, if this division process is done carelessly, unnatural wrinkles may emerge in the drawing result. Such wrinkles will be particularly apparent during scrolling. To prevent wrinkles, use the imageYorig of uObjScaleBg_t and perform operations like those shown below (this value is the y-coordinate of the origin for scaling, but it is also the division origin of the subplane). The Comment section below shows the uObjScaleBg_t structure.

* At the time of initialization:
Assign the value imageY to imageYorig

* When the value of scaleH has changed:
Assign the value imageY to imageYorig

* When imageX and imageY have been wrapped:
Perform the same kind of process on imageYorig as on imageY

* When only imageY is changed (change without wrapping)
Do not change image imageYorig

Based on the above operations, the process for dx,dy scrolling of an image would be as follows:

/* Add scroll values */
bg->s.imageX += dx;
bg->s.imageY += dy;
/* Screen edge wrapping  */
if (bg->s.imageX < 0) {
  bg->s.imageX     += bg->s.imageW;
  bg->s.imageY     -= 32;
  bg->s.imageYorig -= 32;
}
if (bg->s.imageX >= bg->s.imageW) {
  bg->s.imageX     -= bg->s.imageW;
  bg->s.imageY     += 32;
  bg->s.imageYorig += 32;
}
if (bg->s.imageY < 0) {
  bg->s.imageY     += bg->s.imageH;
  bg->s.imageYorig += bg->s.imageH;
}
if (bg->s.imageY >= bg->s.imageH) {
  bg->s.imageY     -= bg->s.imageH;
  bg->s.imageYorig -= bg->s.imageH;

Also note that operation is not currently guaranteed for G_IM_FMT_YUV (YUV format).

Comment

The uObjScaleBg structure is shown below:

typedef	struct	{
  u16 imageX;      /* x-coordinate of upper-left position of texture (u10.5) */ 
  u16 imageW;      /* Texture width (8-byte alignment, u10.2) */
  s16 frameX;      /* x-coordinate of upper-left position of transfer destination frame (s10.2) */
  u16 frameW;      /* Transfer destination frame width (u10.2) */

  u16 imageY;      /* y-coordinate of upper-left position of texture (u10.5) */ 
  u16 imageH;      /* Texture height (u10.2) */
  s16 frameY;      /* y-coordinate of upper-left position of transfer destination  frame (s10.2) */
  u16 frameH;      /* Transfer destination frame height (u10.2) */

  u64 *imagePtr;   /* Address of texture source in DRAM */
  u16 imageLoad;   /* Method for loading the BG image texture
                      G_BGLT_LOADBLOCK (use LoadBlock)
                      G_BGLT_LOADTILE (useLoadTile) */
  u8  imageFmt;    /* Texel format
                      G_IM_FMT_RGBA (RGBA format)
                      G_IM_FMT_YUV (YUV format)
                      G_IM_FMT_CI (CI format)
                      G_IM_FMT_IA (IA format)
                      G_IM_FMT_I (I format) */
  u8  imageSiz;    /* Texel size
                      G_IM_SIZ_4b (4 bits/texel)
                      G_IM_SIZ_8b (8 bits/texel)
                      G_IM_SIZ_16b (16 bits/texel)
                      G_IM_SIZ_32b (32 bits/texel) */
  u16 imagePal;    /* Position of palette for 4-bit color
                      index texture (4-bit precision, 0~15) */
  u16 imageFlip;   /* Image inversion on/off (horizontal
                      direction only)
                      0 (normal display (no inversion))
                      G_BG_FLAG_FLIPS (horizontal inversion of texture image) */

  u16 scaleW;      /* x-direction scale value (u5.10) */
  u16 scaleH;      /* y-direction scale value (u5.10) */
  s32 imageYorig;  /* image drawing origin (s20.5) */
  
  u8  padding[4];  /* Padding */
  
} uObjScaleBg_t;   /* 40 bytes */

typedef union {
  uObjBg_t       b;
  uObjScaleBg_t  s;
  long long int  force_structure_alignment;
} uObjBg;

* Concerning the scaleW, scaleH, and imageYorig elements:

BG image scaling is controlled by the scaleW, and scaleH members of the uObjScaleBg_t structure. The scaling process centers around (imageX, imageY) of the BG image. The image is drawn to the (frameX, frameY) position in the frame buffer, just as when no scaling is performed. However, during a horizontal flip, the BG image is drawn to the (frameX+frameW-1, frameY) position in the frame buffer.

When the image is enlarged, the image is clamped by the frame size. Conversely, when the image is reduced, the frame is sometimes clamped by the image size. This frame clamp can be a little big or a little small, due to errors in calculation. If you want to strictly specify the size, you will need to calculate frameW, frameH with the CPU. For details, see the S2DEX sample program.

* Concerning the imagePtr element:

You cannot specify any position in the first 4096 bytes of RDRAM for imagePtr. These are the physical addresses from 0x00000000 to 0x00000fff. A segment-converted imagePtr cannot reside within this range.

* To learn more about the other elements, please refer to the g*SPBgRectCopy macro.

This macro is built into S2DEX Release 1.00 and later versions. However, the same processes can be emulated using guS2DEmuBgRect1Cyc, which was added from S2DEX Release 0.75 and which works by assembling gSPTextureRectangle together with a number of other macros. This can be used to draw BG images that can be scaled. For details, see the latest readme for S2DEX microcode Section 5 "Emulation Functions". For information about the uObjScaleBg_t structure, see Section 4.1, "BG Drawing GBIs" in the same manual.

See Also

gSPBgRectCopy

Revision History

02/01/99 Entirely revised.