Developer tips

From WiiBrew
Jump to navigation Jump to search

General Programming Tips

  • Keep your code commented throughout; it helps others help you. How much you comment it is a matter of debate; in general, people tend to comment bits of code where it isn't obvious what it actually does or why, or variables that aren't obvious what they are used for (or are not used until quite a bit later on).
  • Any unused code should be deleted out of the program, unless it is a program for teaching people.
  • If someone does the same thing in a more efficient way (i.e. faster and/or in less code), accept it and learn from it.
  • It is a good idea to release your app open source so others can learn from your code.
  • To keep things tidy, if you store files on SD, store them in a folder named the same as your application's name.

Code Snippets

Video Auto-Detect Routine

Here is the video detect code from the DevKitPro Wii example. Keep in mind, however, the libogc included in DevkitPPC since r15 does this for you already with one function call.

#include <gccore.h>
static GXRModeObj *rmode = NULL;
// ...
rmode = VIDEO_GetPreferredMode(NULL);

if( CONF_GetAspectRatio() )
{
	rmode->viWidth = 678;
	rmode->viXOrigin = (VI_MAX_WIDTH_PAL - 678)/2;
}
VIDEO_Configure(rmode);

Please see also: Display Issues

Exit to Loader

It's a good idea to add some way to return to the loader, otherwise you have to reboot your Wii to exit.

// Just call the exit() function to go back to the loader
// Returning from main also works, since that calls exit for you
    #include <stdlib.h>
    // ...
    exit(0);

How to use the Wiimote

A separate article is available: How to use the Wiimote.

Reboot Wii

Use:

#include <gccore.h>
// ...
SYS_ResetSystem(SYS_RESTART,0,0);

Or use SYS_RETURNTOMENU for a "soft" return to the system menu, SYS_POWEROFF to shut down the wii (automatically to the appropriate Idle or Standby mode, depending on the WC24 setting), or SYS_POWEROFF_STANDBY or _IDLE to specify the mode and override the system setting.

How to use the callback function for Power and Reset

This is just a way of doing this stuff, feel free to change the code.

s8 HWButton = -1;

/**
 * Callback for the reset button on the Wii.
 */
void WiiResetPressed()
{
	HWButton = SYS_RETURNTOMENU;
}

/**
 * Callback for the power button on the Wii.
 */
void WiiPowerPressed()
{
	HWButton = SYS_POWEROFF_STANDBY;
}

/**
 * Callback for the power button on the Wiimote.
 * @param[in] chan The Wiimote that pressed the button
 */
void WiimotePowerPressed(s32 chan)
{
	HWButton = SYS_POWEROFF_STANDBY;
}

/**
 * Entry point.
 * @param[in] argc The number of arguments invoked with the program
 * @param[in] argv The array containing the arguments
 * @return 0 on clean exit, an error code otherwise
 */
int main(int argc, char **argv)
{
	// Initialization

	SYS_SetResetCallback(WiiResetPressed);
	SYS_SetPowerCallback(WiiPowerPressed);
	WPAD_SetPowerButtonCallback(WiimotePowerPressed);

	while(1)
	{
		// Do Stuff Here
		if(HWButton != -1)
			break;
	}

	if(HWButton != -1)
	{
		SYS_ResetSystem(HWButton, 0, 0);
	}

	return 0;
}

Possible values for HWButton are:

#define SYS_RESTART 0 /*!< Reboot the gamecube, force, if necessary, to boot the IPL menu. Cold reset is issued */
#define SYS_HOTRESET 1 /*!< Restart the application. Kind of softreset */
#define SYS_SHUTDOWN 2 /*!< Shutdown the thread system, card management system etc. Leave current thread running and return to caller */
#define SYS_RETURNTOMENU 3 /*!< Directly load the Wii Channels menu, without actually cold-resetting the system */
#define SYS_POWEROFF 4 /*!< Powers off the Wii, automatically choosing Standby or Idle mode depending on the user's configuration */
#define SYS_POWEROFF_STANDBY 5 /*!< Powers off the Wii to standby (red LED, WC24 off) mode. */
#define SYS_POWEROFF_IDLE 6 /*!< Powers off the Wii to idle (yellow LED, WC24 on) mode. */

Note on Projection Matrices

There are a lot of tutorials and projects out there that are using standard 'Mtx' variables for projection matrices. Although this works in many cases (because the variables declared right after the matrix don't mind being corrupted once or twice), this is not correct, and is a crash waiting to happen. These matrices should be declared as 'Mtx44' objects instead. Note the prototypes for the projection matrix functions (see "ogc/gu.h"):

void guFrustum(Mtx44 mt,f32 t,f32 b,f32 l,f32 r,f32 n,f32 f);
void guPerspective(Mtx44 mt,f32 fovy,f32 aspect,f32 n,f32 f);
void guOrtho(Mtx44 mt,f32 t,f32 b,f32 l,f32 r,f32 n,f32 f);

One way to catch such errors is to enable more warnings in gcc like:

gcc -Wall -pedantic -std=c99

For example the current 'devkitPro\examples\wii\graphics\gx\triangle.c' uses 'Mtx' but it should be using 'Mtx44' - I fell into this trap, please be careful & take note of the above.

Timing

Use:

#include <ogc/lwp_watchdog.h.h>

int main () {
	double deltaTime;
	settime((uint64_t)0); //So we don't have to start with a huge number.
	uint64_t deltaTimeStart = gettime();
	while (1) {
		deltaTime = (double)(gettime() - deltaTimeStart) / (double)(TB_TIMER_CLOCK * 1000); // division is to convert from ticks to seconds
		deltaTimeStart = gettime();
		//Do something
	}
}

Do not use clock() from time.h or any other library, clock() will return 4294967295 because the number of ticks is much larger than 32 bits. The function body for gettime() can be found in timesupp.c.

GX Tips

When your code hangs drawing

If your GX application hangs as soon as you begin drawing with GX_Begin(), here are a few possible causes:

  • incorrect vertex formats - the vertex format specified with GX_SetVtxAttrFmt() must match what your app sends between GX_Begin() and GX_End()
  • incorrect vertex count - the vertex count specified by GX_Begin() must match the vertex count your app sends between GX_Begin() and GX_End()
  • incorrect vertex data order - vertex data is order dependent - the order GX expects vertex data is: position, normal, color, bi-normals, and texture coordinates
  • surpassing the maximum number of vertex per between GX_Begin() and GX_End() block which is 65,536 (not counting normals/colours)

Examples

If you are looking for GX examples. Devkitpro comes with a few GX examples which should help you to get started. Some knowledge about OpenGL is useful, but remember that GX is not the same as OpenGL.

Texture Compression

Do use texture compression on all textures where you can live with the lost picture quality. It reduces the memory usage and speeds up the loading and rendering. devkitPro comes with gxtexconv which supports DXT1 compression.

To use it specify colfmt=14 in your script or on the command line. You get textures 1/4 the size of uncompressed RGB565 (colfmt=4) textures.