Source code to a Demo Program

From wiki.gp2x.org

Demo.C

Here's a heavily modified version of the SDL's standard demo program. The original version works fine for desktops, but the GP2X is a bit different.

The code itself is overly documented. I'll make the page into a pretty thing soon, but it seems like getting the information out is the first step.

// This little demo program displays an image on a GP2X, waits for a button press, and exits.
// This is a modified version of the demo.c program that ships in the SDL's demo directory.
// Modifications done by Charles Merriam, 1/2006, under the GNU LGPL, same as the SDL.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "SDL.h"  // SDL stands for "Simple Direct-Media Layer"

/*
	convenience function, for SDL_BlitSurface. 
*/

void drawSprite(SDL_Surface* imageSurface, SDL_Surface* screenSurface, int srcX, int srcY, int dstX, int dstY, int width, int height)
{
	// just for annoyance later, note the SDL uses signed ints for x and y but unsigned for width and height.
	// shouldn't matter until resolution gets much better
	SDL_Rect srcRect;
	srcRect.x = srcX;
	srcRect.y = srcY;
	srcRect.w = width;
	srcRect.h = height;

	SDL_Rect dstRect;  
	dstRect.x = dstX;
	dstRect.y = dstY;
	dstRect.w = width;  // This is actually ignored by SDL_BlitSurface.
	dstRect.h = height; // This is actually ignored by SDL_BlitSurface.
   
	SDL_BlitSurface(imageSurface, &srcRect, screenSurface, &dstRect);
		// fast blit from source to destination.  
		// ignores the -1 or -2  possible error codes.
}

/*
  Main program that executes.
*/
  
int /// return the error code.  Usually zero means execution was OK else not 0
    main(int argc,  /// number of arguments
		 char *argv[])  /// the argument strings.   Argv[0] is the command name iteself.
{
	SDL_Surface *screen;    /// Graphical surface structure.
	SDL_Joystick *joystick; /// Joystick information structure, full of info I don't use in this program.
	SDL_Event event;  // An event structure.
		  // This is a big union.  Specifically, the first 8 bytes are the type.  The 'union' is either 
		  // the type (for the first 8 bytes) or some structure where the first 8 bytes 
		  // are still the type.  It is just a style, and typographic convenience, that
		  // it is not a structure of { unit 8 type, union data { keyboard.....} }.

	int done = 0;
	
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) 
	// initialize the video subsystem and the joystick subsystem.  Using a bitwise or to send multiple flags is 
	// common. 
	{  
		return 1;    /// oops, something failed.  
	}
	
	screen = SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE);
		// Setting the video mode.  This SDL call can only take certain parameters.
		// a 320x240 screen, so this won't look especially good on a TV which allows a higher resolution
		// 16 bits per pixel.
		// SDL_SWSURFACE : Create the Video Surface in System Memory. 
		//   This works.  Double buffering does not currently work, and using the SDL_HWSURFACE 
		//   is tricky.  
	if (!screen)  // oops.  Look
	{
		fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());  
		// Won't see the fprint on the graphical GP2X screen.
		return 1;
	}
	
	joystick = SDL_JoystickOpen(0); // initialize the joystick and buttons.  Number '0' is the only one.
	if (!joystick) // should not happen
	{
		fprintf(stderr, "Couldn't open the joystick: %s\n", SDL_GetError());
		return 1;
	}
		
	SDL_ShowCursor(SDL_DISABLE);  // do not show cursor on the screen.
	
	SDL_Surface* bitmap = SDL_LoadBMP("/mnt/sd/image.bmp");  // load a BMP format.
	   // BMP is an uncompressed simple bitmap of a specific color depth.  
	   // The file is the sd card, which was mounted like a normal linux file system.
	   // Not that we don't check for errors in the demo code, and this is the only likely 
	   // spot for an error to occur.   Figuring out which errors to check for is tricky.
	
	drawSprite(bitmap, screen, 0, 0, 0, 0, bitmap->w, bitmap->h);  // draw it.

	SDL_Flip(screen);
	// Tell SDL to update the screen at some useful time.  Note that without SDL_DOUBLEBUF, 
	// this will just be the same as SDL_UpdateRect.
	 
	// OK, now let's wait for a keypress.  But it's complicated. 
	// The event queue might not be empty on  start-up.
	// When I launch this program from the GP2X main menus, I press down the B button.
	// Depending on my speed on the button, if the SDL and the image are in cache, and,
	// possibly, the phase of moon, the SDL may start up while while the B button is still down.
	// If this happens, SDL immediately adds a button down event for the B button.
	SDL_PollEvent(&event);  // ignore any one event in the queue.  
	// SDL_PollEvent will return immediately, and will return 1 if there is a pending event.
	// I don't care about the pending event, if any, so I can ignore the return value.

	while (!done)
	{
		
		SDL_WaitEvent(&event);  // wait indefinitly for events.  Through away error return value (1).
		   // When this returns, some event happened. 

		switch (event.type)  // look at the 'type', or a uint8 at the beginning of the event union.
		{
			// OK, now these are rather silly.  The GP2X has no keys to hit, and has no 'quit' method.
			// Instead, the GP2X has button events for the various buttons (A,B,X,Y,L,R,Start,Select,Volume), and
			// the joystick positions, and the center click down.
			/*
			case SDL_KEYDOWN:  
			case SDL_QUIT:
			*/
			
			// These are the button events
			case SDL_JOYBUTTONDOWN:
				// and here we could see code like "if (event.jbutton.button == GP2X_BUTTON_X) ....
				//but any button will do.
				done = 1;
			break;				
		}
	}
	
	SDL_Quit();  // Shut down the SDL library, freeing resources.
	
	// This is how to quit back to the menu.  Just doing a return(0) will look like the GP2X hung.
	chdir("/usr/gp2x");

	execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
	// execl will go run the other program INSTEAD of this one.  
	
	return 0;  // this line make the compiler happy, but the call to execl() above never returns
}

Personal tools