Hardware graphics (RDPQ)

Note! The content that was previously on this page has been deprecated due to the move of RDPQ from the unstable to trunk branch. In the time that it takes me to update this page with the new functionality, you can still have a look at the legacy page. The following page is a work in progress.


The RDPQ (RDP command queue) library interfaces with the N64’s Reality Display Processor (RDP) through the Reality Signal Processor (RSP). The library handles the complex programming of the RDP and supports both 2D and 3D tasks. It is divided into several headers, each addressing different functionalities like low-level command generation, triangle and rectangle drawing, texture handling, and debugging.

To the contrary of the legacy RDP library, the RSPQ allows you to enqueue tasks for the RDP to perform without needing to perform constant syncing after each task. This makes it both easier to develop for and faster to render each frame at runtime.

Let’s go though all the various functionality that RDPQ provides.

Basic setup

This is going to be the simplest ROM I can make to show how the RDPQ works. It’ll display a black square on a white background.

#include <libdragon.h>

int main(void)
{
	// Initialise the various systems
	display_init(RESOLUTION_640x480, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_DISABLED);
	rdpq_init();

	// Main loop
	while(1) {
		// Start a new frame
		// Get the frame buffer
		surface_t* disp;
		while(!(disp = display_try_get()));

		// Attach the buffers to the RDP (No z-buffer needed yet)
		rdpq_attach_clear(disp, NULL);

		// Fill the background with white
		rdpq_set_mode_fill(RGBA32(0xFF, 0xFF, 0xFF, 0));
		rdpq_fill_rectangle(0, 0, display_get_width(), display_get_height());

		// Draw in a black rectangle
		rdpq_set_mode_fill(RGBA32(0x00, 0x00, 0x00, 0));
		rdpq_fill_rectangle(100, 100, display_get_width()-100, display_get_height()-100);

		// Send frame buffer to display (TV)
		rdpq_detach_show();
	}
}

Breakdown

The program starts by initialising the subsystems. Nothing too special here.

// Initialise the various systems
display_init(RESOLUTION_640x480, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_DISABLED);
rdpq_init();

Within the main loop, the first step is to get a frame buffer. This is a section of memory that contains the pixel data for the next frame and its attributes, we’ll call it disp. Then we use the display_try_get() function in a loop to wait until we have a new frame buffer available for us to render.

// Get the frame buffer
surface_t* disp;
while(!(disp = display_try_get()));

This frame buffer then needs to be attached to the RDP. Since we’re not using a z-buffer, we can leave the 2nd parameter as NULL.

// Attach the buffers to the RDP (No z-buffer needed yet)
rdpq_attach_clear(disp, NULL);

Now we’re ready to draw. Let’s start by setting the colour of the RDP to white. Then draw a rectangle. The parameters for this function are the x/y coordinates for the top-left corner, and then the x/y coordinates of the bottom-right corner. You can also think of it as the coordinates of the left/top/bottom/right sides of the rectangle.

We then do it again for a smaller black rectangle.

// Fill the background with white
rdpq_set_mode_fill(RGBA32(0xFF, 0xFF, 0xFF, 0));
rdpq_fill_rectangle(0, 0, display_get_width(), display_get_height());

// Draw in a black rectangle
rdpq_set_mode_fill(RGBA32(0x00, 0x00, 0x00, 0));
rdpq_fill_rectangle(100, 100, display_get_width()-100, display_get_height()-100);

The final step is to send the generated frame buffer to the N64’s video output.

// Send frame buffer to display (TV)
rdpq_detach_show();

Modes

Programming with the RDP begins with a thorough understanding of the various modes that it has. While there are many more than these, these are the ones that are used most frequently.

rdpq_set_mode_standard() sets the RDP’s mode to the most basic standard functionality. It can do texturing without shading, dithering, blending, antialiasing etc. This mode can be enhanced with other functions (which will be described in greater detail later).

rdpq_set_mode_fill(color_t color) is a mode used to fill sections of the screen with a solid, untextured colour. Its parameter is usually defined by the macro RGBA32(0xFF, 0xFF, 0xFF, 0) which returns a color_t of the RGBA colour you want.

rdpq_set_mode_copy(bool transparency) is used for texture blitting. The is the main way of using the RDP for drawing sprites in a 2D environment. The transparency parameter is used to determine whether any transparent pixels should be rendered as a solid colour or as transparent.

rdpq_set_mode_yuv(bool bilinear) allows the RDP to work with YUV textures. This isn’t really used much in practice. Its single parameter determines whether to use linear interpolation or not.

Search

Subscribe to the mailing list

Follow N64 Squid

  • RSS Feed
  • YouTube

Random featured posts