Please break this code

Hello all, I was just wondering if people would be kind enough to test some
joystick code for me.
I only have access to on joystick and one machine.
I’d also like some suggestions on things that I can do to improve my joystick
handling.

i used png image files with alpha channels
background.png was 640x480
aim.png : 100x100
light-on & light-off : 50x50

I made mine w/ gimp.

right now I don’t have a home online to put this project of mine.
I hope to soon be able to do so.
(sourceforge won’t take it)

if anyone want’s a copy of the package they can email me and request on for
now. (330K tar.bz2)

Hope this helps some people w/ joystick questions too.

here is the code

/******************************************************************************

  • joytest.c : this code is for testing joysticks using sdl.
  • Copyright © 2002 Samuel E. Bray
  • You may contact me at:
  • aristoidaneel at yahoo.com
  • This program is free software; you can redistribute it and/or modify
  • it under the terms of the GNU General Public License as published by
  • the Free Software Foundation; either version 2 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  • GNU General Public License for more details.
  • You should have received a copy of the GNU General Public License
  • along with this program; see the file COPYING. If not, write to
  • the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  • Boston, MA 02111-1307, USA.
    *****************************************************************************/

/* ** ** ToDo: Install RCS ** ** */

#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

#define TRUE 1
#define FALSE 0
#define NUM_LIGHTS 24

/* Other constants */
const int JS_MAX = 65535;

/* global variables */

int screenWidth = 640;
int screenHeight = 480;
int screenBPP = 32;
int screenUnitX;
int screenUnitY;
int joyYCenter;
int joyXCenter;
int videoFlags = SDL_HWSURFACE | SDL_DOUBLEBUF;
int pad = 5; /* pad our edges */

SDL_Surface *screen;
SDL_Surface *onLight;
SDL_Surface *offLight;
SDL_Surface *background;
SDL_Surface *aim;

int isActive = FALSE;

typedef struct light_struct {
SDL_Surface *image;
int toggle;
int x_offset;
int y_offset;
} light;

light lights[NUM_LIGHTS];

typedef struct aimer_struct {
int x, y;
} aimer_t;

aimer_t aimer;
/*** End variables & constants ***/

/* use this to clean up and quit gracefully,

  • depending on the particular situation /
    void Quit(int returnCode)
    {
    SDL_Quit();
    if(returnCode != 42)
    exit(returnCode);
    fprintf(stdout,"\nQuiting…\n");
    }
    /
    ** End Quit ***/

/** ** ToDo ** ** : add logging
*

  •       do so by 
    
  •       *creating a LogEntry function
    
  •         which would 
    
  •          *take an error message,
    
  •          *perhaps a pointer to some data, 
    
  •          *and a logLevel number 
    
  •            which would
    
  •              *be used to rate the error and allow the user
    
  •               to filter out unwanted or over zelous 
    
  •               warnings and errors.
    
  •       LogEntry then puts the data in an array (or 2)
    
  •       A parse function would then select the messages
    
  •       to print and
    
  •       Then the buffer array is written to the 
    
  •       external logfile and emptied at the end
    
  •       of each event loop.
    

*/

/* use this function for error printing

  • to stderr /
    void Kaboom(char endString)
    {
    fprintf(stderr, “Error %s: %s\n”,endString, SDL_GetError());
    Quit(1);
    }
    /
    * End Kaboom ***/

void VideoInit()
{
/* I should probably remove this function and merge the code elsewhere /
/
like main or QueryJoystick */

/* Init Video and setup drawing surface /
if(SDL_Init(SDL_INIT_VIDEO) == -1)
Kaboom(“Unable to initialize video hardware”);
}
/
** End VideoInit ***/

/* Load the Images, exit w/ message on failure */
void Load_Images(void)
{
if((onLight = IMG_Load(“light-on.png”)) == NULL)
Kaboom(“Unable to load image”);

if((offLight = IMG_Load(“light-off.png”)) == NULL)
Kaboom(“Unable to load image”);

if((background = IMG_Load(“background.png”)) == NULL)
Kaboom(“Unable to load image”);

if((aim = IMG_Load(“aim.png”)) == NULL)
Kaboom(“Unable to load image”);
}
/*** End Load_Images ***/

/* ** ** ToDo: Add on screen text ** ** */

void Init()
{
int i = 0;
screenUnitX = JS_MAX / screenWidth;
screenUnitY = JS_MAX / screenHeight;
joyYCenter = screenHeight / 2;
joyXCenter = screenWidth / 2;

if((screen = SDL_SetVideoMode(screenWidth, screenHeight, screenBPP,
videoFlags)) == NULL)
Kaboom(“Unable to set video mode”);

/* umm, i dunno */
Load_Images();

for(i=0;i<NUM_LIGHTS;i++)
{
lights[i].x_offset = onLight->w;
lights[i].y_offset = (onLight->h * i) + 10;
lights[i].toggle = FALSE;
lights[i].image = offLight;
}
aimer.x = joyXCenter;
aimer.y = joyYCenter;
}
/*** End Init() ***/

/* check the system and list all available joysticks

  • then test each one and display the results
  • then ask the to pick a joystick to test */
    SDL_Joystick *QueryJoyStick()
    {

int numJoyStick = 0;
int i = 0;
int die = 0;
SDL_Joystick *joystick;
int choice = 0;

/* attempt joystick init, explode on error */
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0)
Kaboom(NULL);

/* This should never happen, but it doesn’t hurt to be robust /
/
Check to make sure there is at least one joystick available /
if((numJoyStick = SDL_NumJoysticks()) == 0)
Kaboom(“No joysticks available.”);
fprintf(stdout,“Found %i joystick(s) on this system.\n”,numJoyStick);
die = numJoyStick;
/
loop through each joystick and print the info for each /
for(i = 0; i < numJoyStick; i++)
{
if((joystick = SDL_JoystickOpen(i)) == NULL)
{
fprintf(stderr,“Unable to open joystick %i: %s\n”,i,SDL_GetError());
die–; /
see below */
}
else
{
fprintf(stdout,“Joystick %i\n”,i);
fprintf(stdout,"\tName:…%s\n",SDL_JoystickName(i));
fprintf(stdout,"\tAxes: %i\n",SDL_JoystickNumAxes(joystick));
fprintf(stdout,"\tTrackBalls:…%i\n",SDL_JoystickNumBalls(joystick));
fprintf(stdout,"\tButtons: %i\n",SDL_JoystickNumButtons(joystick));
SDL_JoystickClose(joystick);
}
}

/* This should never happen, again, trying to be robust, like *

  • above, checked for each joystick as it is looped through *
  • if none can be opened at this point, then explode, and something is
  • seriously wrong, with the system */

/* I have read recently, that the above robustness is an error in coding; /
/
I’m not sure how, perhaps a little extra bloat, this is a testing program
/
/
after all. */

/* **Note: Kaboom not used here, because Kaboom() checks with
SDL_GetError(),

  • which would not be correct to do here. */
    if(die == 0)
    {
    fprintf(stderr,“Unable to open any of the listed joysticks.\n”);
    Quit(1);
    }

/* ask for a joystick to work with */
fprintf(stdout,“Which Joystick do you want to use(0 - %i): “,(numJoyStick -
1));
scanf(”%i”,&choice);

/* attempt to open the requested joystick, explode on error. */
if((joystick = SDL_JoystickOpen(choice)) == NULL)
Kaboom(NULL);
fprintf(stdout,“Joystick %i:%s selected.\n”,choice,
SDL_JoystickName(choice));

return joystick;
}
/*** End QueryJoyStick() ***/

void DrawScreen(int numLights)
{

int i;
SDL_Rect source;
SDL_Rect dest;

/* first draw the background */
source.x = 0;
source.y = 0;
source.w = background->w;
source.h = background->h;
dest.x = 0;
dest.y = 0;
dest.w = background->w;
dest.h = background->h;

SDL_BlitSurface(background, &source, screen, &dest);

/* next draw the lights */
for(i=0;i<numLights;i++)
{
if(lights[i].toggle)
lights[i].image = onLight;
else
lights[i].image = offLight;

  source.x = 0;
  source.y = 0;
  source.w = lights[i].image->w;
  source.h = lights[i].image->h;
  
  dest.x = lights[i].x_offset;
  dest.y = lights[i].y_offset;

  dest.w = source.w;
  dest.h = source.h;
  
  SDL_BlitSurface(lights[i].image, &source, screen, &dest);
} 

/* now draw the aim recticle */
source.x = 0;
source.y = 0;
source.w = aim->w;
source.h = aim->h;
dest.x = aimer.x - (aim->w / 2);
dest.y = aimer.y - (aim->h / 2);
dest.w = aim->w;
dest.h = aim->h;

SDL_BlitSurface(aim, &source, screen, &dest);

SDL_Flip(screen);
}
/*** End DrawScreen() ***/

void HandleKeyPress (SDL_keysym keysym)
{
switch (keysym->sym)
{
case SDLK_q:
case SDLK_ESCAPE:
Quit (0);
break;
case SDLK_F1:
SDL_WM_ToggleFullScreen(screen);
break;
default:
break;
}
}
/
** End HandleKeyPress() ***/

int ProcessEvent (SDL_Event event)
{
int done = FALSE;
while (SDL_PollEvent (event))
{
switch (event->type)
{
case SDL_ACTIVEEVENT:
if (event->active.gain == 0)
isActive = FALSE;
else
isActive = TRUE;
break;
case SDL_VIDEORESIZE:
if (!(screen = SDL_SetVideoMode (event->resize.w,
event->resize.h,
screenBPP,
videoFlags)
)
) /
close of ‘if’ above */

    {
      Kaboom("Unable to set video mode after resize event.");
    }
  break;
case SDL_KEYDOWN:
  HandleKeyPress (&event->key.keysym);
  break;
case SDL_KEYUP:
  /* HandleKeyUp (&event->key.keysym); */
  break;
case SDL_JOYAXISMOTION:
  /* use these 'if' statements to filter out 
   * joystick noise (a 0.1% deadzone) */

  if((event->jaxis.value > (-32)) && (event->jaxis.value < 32))
    {
      if(event->jaxis.axis == 0)
	aimer.x = joyXCenter;
      if(event->jaxis.axis == 1)
	aimer.y = joyYCenter;
    }

  if((event->jaxis.value < (-32)) || (event->jaxis.value > 32))
    {
      switch (event->jaxis.axis)
	{
	case 0:
	  aimer.x = (event->jaxis.value / screenUnitX) + joyXCenter;
	  if(aimer.x > screenWidth+pad)
	    aimer.x = 0;
	  if(aimer.x < 0-pad)
	    aimer.x = screenWidth;
	  break;
	case 1:
	  aimer.y = (event->jaxis.value / screenUnitY) + joyYCenter;
	  if(aimer.y > screenHeight+pad)
	    aimer.y = 0;
	  if(aimer.y < 0-pad)
	    aimer.y = screenHeight;
	  break;
	case 2:
	  /* ** ** ToDo: Add an animated slider to represent! ** ** */
	  break;
	case 3:
	  /* ** ** ToDo: Same as above ** ** */
	  break;  
	default:
	  break;
	}
    }
  break;
case SDL_JOYBUTTONDOWN:
  lights[event->jbutton.button].toggle = 

!lights[event->jbutton.button].toggle;
//fprintf(stdout,“Button %d pressed.\n”,event->jbutton.button);
break;
case SDL_JOYBUTTONUP:
/* comment out the below line to make the buttons toggle off with each
press /
lights[event->jbutton.button].toggle = FALSE;
break;
case SDL_QUIT:
fprintf(stdout,“Recived quit event\n”);
done = TRUE;
break;
default:
break;
}
}
return done;
}
/
** End ProcessEvent() ***/

/* ** ** ToDo: Add command line options

  •         Such as the ability to blindly choose a joystick
    

*/

int main()
{
SDL_Event event;
SDL_Joystick *joystick;
int numLights;

/* init video system */
VideoInit();

/* init JoyStick */
joystick = QueryJoyStick();

/* Determin how many lights needed to represent the buttons */
numLights=SDL_JoystickNumButtons(joystick);

/* init other thingies */
Init(numLights);

while(!ProcessEvent(&event))
{
if(isActive)
{
DrawScreen(numLights);
}
}

/* releasing surfaces and joystick */

fprintf(stdout,"\nReleasing surfaces and joysticks…\n");

fprintf(stdout,"\tReleasing background image…");
SDL_FreeSurface(background);
fprintf(stdout,“done\n”);

fprintf(stdout,"\tReleasing onLight image…");
SDL_FreeSurface(onLight);
fprintf(stdout,“done\n”);

fprintf(stdout,"\tReleasing offLight image…");
SDL_FreeSurface(offLight);
fprintf(stdout,“done\n”);

fprintf(stdout,"\tReleasing aim image…");
SDL_FreeSurface(aim);
fprintf(stdout,“done\n”);

fprintf(stdout,"\tReleasing joystick device…");
SDL_JoystickClose(joystick);
fprintf(stdout,“done\n”);

fprintf(stdout,“Calling Quit() to finalize close…”);
Quit(42);

fprintf(stdout,“done\nReturning to OS\n”);
return 0;
}

Hi Samuel,

Testing your code uncovered a bug in SDL, I can open PS2Linux control
pads when they are not plugged in. This confirmed by also being present
n test/joytest, I will take a look at finding the problem in the src.

Regarding improvements to your code, only one analog stick seems to be
selectable (Left in my case).

The analog crosshair also moves slightly off the screen, perhaps you
could normalise the range so it fitted in under 600x400 pixels? (TV’s
often overscan…)

Some buttons are not supported it seems, the L3/R3 buttons under the
analog sticks, and the analog values of the action buttons (perhaps not
supported in native PS2Linux libs…)

Also the vibration function, this is something I would like to look into
supporting. I could not see any vibration actuator code in SDL
currently, how would I go about requesting to assign myself to this task?

Cheers

JG

Samuel E. Bray wrote:> Hello all, I was just wondering if people would be kind enough to test some

joystick code for me.
I only have access to on joystick and one machine.
I’d also like some suggestions on things that I can do to improve my joystick
handling.

i used png image files with alpha channels
background.png was 640x480
aim.png : 100x100
light-on & light-off : 50x50

I made mine w/ gimp.

right now I don’t have a home online to put this project of mine.
I hope to soon be able to do so.
(sourceforge won’t take it)

if anyone want’s a copy of the package they can email me and request on for
now. (330K tar.bz2)

Hope this helps some people w/ joystick questions too.

here is the code