www.xbdev.net xbdev - software development
Thursday April 27, 2017
home | about | contact | Donations

     
 

OpenXDK

The Free, Legal, Open Source XBox Development Kit...

 

Gamepad Basics

 

Finally some user input!  As without our gamepad its just a screensaver....hehe  So using our xinput.lib and xinput.h we can have some simple test input.

 

 

struct stXPAD

{

      char reserved1;

      unsigned char structsize;

     

      char pad;              // 1 up 2 down 4 left 8 right

      char reserved2;

      unsigned char keys[6]; // A B X Y Black White

     

      unsigned char trig_left;

      unsigned char trig_right;

      short stick_left_x;

      short stick_left_y;

      short stick_right_x;

      short stick_right_y;

};

 

 

Its good to know what data where getting back, so we can use it for testing:

 

Project Source Code - Gamepad Basics

 

// Gamepad Basics

// Add header file for xinput.h

// Add the library xinput.lib

 

#include <openxdk.h>

#include <stdio.h>

#include <stdlib.h>

#include "OpenXDK\include\xinput\xinput.h"

 

void DataDisplay(stXPAD * pPad)

{

      long xpos=50;   long ypos=95;   long height=12;

 

      char bufA[1000]; // Large temp char buffer for our text

 

      sprintf(bufA, "%s",  "GamePad One Information Data: by bkenwright@xbdev.net");

      vga_print(xpos, ypos+=height, bufA);

      ypos+=5;

 

      sprintf(bufA, "structsize: 0x%x", pPad->structsize);

      vga_print(xpos, ypos+=height, bufA);

                 

      sprintf(bufA, "pad: %d (1 up 2 down 4 left 8 right)", pPad->pad);

      vga_print(xpos, ypos+=height, bufA);

 

      for(int i=0; i<6; i++)

      {

            sprintf(bufA, "keys[%d]: %d (A B X Y Black White)", i, pPad->keys[i]);

            vga_print(xpos, ypos+=height, bufA);

      }// End for loop

     

      sprintf(bufA, "trig_left: 0x%x", pPad->trig_left);

      vga_print(xpos, ypos+=height, bufA);

 

      sprintf(bufA, "trig_right: 0x%x", pPad->trig_right);

      vga_print( xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_left_x: 0x%x", pPad->stick_left_x);

      vga_print(xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_left_y: 0x%x", pPad->stick_left_y);

      vga_print( xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_right_x: 0x%x", pPad->stick_right_x);

      vga_print(xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_right_y: 0x%x", pPad->stick_right_y);

      vga_print(xpos, ypos+=height, bufA);

}// End of DataDisplay(..)

 

 

 

void XBoxStartup()

{

      //let's init the screen

      vga_init_mode(MODE_640x480x32);         // Some possible modes all defined in

                                              // xvga.h

                                              // MODE_320x240x32

                                              // MODE_640x240x32

                                              // MODE_640x480x32 etc...plus many more

 

      float last = (float)KeTickCount;

    int   fps  = 0;

 

      int   testcount = 0;

 

      stXINPUT xin;

      xInitInput(&xin);

 

      stXPAD pad;

 

      while(1)

      {

            // Get gamepad input on default gamepad

            xGetPadInput(&pad, &xin);

 

            DataDisplay( &pad);

            // Set rumble on default pad - ignore only for testing at this point

            //xSetPadInput(&pad, &xin);

 

            // In game reset - both left and right trigger and the black button

            if( (pad.trig_left == 0xFF) && (pad.trig_right == 0xFF ) && (pad.keys[4]>150) )

                  break;

 

            // A list of all these functions can be found at the top of xvga.h

            // Comment this line out to watch the frame rate go up...on my xbox

            // I comment this out, and my frame rate is nearly 1000fps!...wow!

            // but of course you can notice the flicker :-/

            vga_vsync();                       // Wait for Vertical Blank

        vga_flip();                            // Flip

            vga_clear();                       // Clear screen

           

 

            fps  = (int)(1.0f/(((float)KeTickCount - last) / 1000.0f));

        last = (float)KeTickCount;

       

            // Print to screen

            char buffer[300]; // large temp text buffer

          sprintf(buffer,"OpenXDK Sample: %d fps", fps);

            vga_print(50, 50, buffer);

 

            sprintf(buffer, "Dynamic Counter Value: %d", testcount++);

            vga_print(50, 75, buffer);

 

            sprintf(buffer, "Press LEFT AND RIGHT TRIGGER then the BLACK BUTTON to reset");

            vga_print(50, 85, buffer);

 

 

      }// End while loop

}//End

 

 

It really looks like a lot of code, but its not...most of it is just for displaying information on the screen to the user :)

 

The real problem is that the gamepad development code is still in development - yup we have working gamepad in put at the moment, but the gamepad driver is still in workings.  So its performance isn't as good as it could be.  So one thing we an do is put the gamepad polling in a second thread so it doesn't effect our main loop as much as it should...so I added a second thread handler in this next demo:

 

Download Project Source - Gamepad Polling In Second Thread

 

// Gamepad Basics - using a second thread for speed

// This code is more or less the same as the one previously, but if you ran

// it you'd notice a fps of 12-20...which just isn't good enough!  If we

// put the gamepad polling code in another thread, and just access the

// data when we need it, we'll get a fixed fps of 25fps.

 

// Add header file for xinput.h

// Add the library xinput.lib

 

#include <openxdk.h>

#include <stdio.h>

#include <stdlib.h>

#include "OpenXDK\include\xinput\xinput.h"

 

void DataDisplay(stXPAD * pPad)

{

      long xpos=50;   long ypos=105;   long height=12;

 

      char bufA[1000]; // Large temp char buffer for our text

 

      sprintf(bufA, "%s",  "GamePad One Information Data: by bkenwright@xbdev.net");

      vga_print(xpos, ypos+=height, bufA);

      ypos+=5;

 

      sprintf(bufA, "structsize: 0x%x", pPad->structsize);

      vga_print(xpos, ypos+=height, bufA);

                 

      sprintf(bufA, "pad: %d (1 up 2 down 4 left 8 right)", pPad->pad);

      vga_print(xpos, ypos+=height, bufA);

 

      for(int i=0; i<6; i++)

      {

            sprintf(bufA, "keys[%d]: %d (A B X Y Black White)", i, pPad->keys[i]);

            vga_print(xpos, ypos+=height, bufA);

      }// End for loop

     

      sprintf(bufA, "trig_left: 0x%x", pPad->trig_left);

      vga_print(xpos, ypos+=height, bufA);

 

      sprintf(bufA, "trig_right: 0x%x", pPad->trig_right);

      vga_print( xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_left_x: 0x%x", pPad->stick_left_x);

      vga_print(xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_left_y: 0x%x", pPad->stick_left_y);

      vga_print( xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_right_x: 0x%x", pPad->stick_right_x);

      vga_print(xpos, ypos+=height, bufA);

 

      sprintf(bufA, "stick_right_y: 0x%x", pPad->stick_right_y);

      vga_print(xpos, ypos+=height, bufA);

}// End of DataDisplay(..)

 

static void otherthread(PVOID parm1, PVOID parm2)

{

      // Small delay loop

      for(int i=0; i<1000; i++)

            for(int j=0; j<1000; j++)

                  __asm{ nop }

 

      stXINPUT xin;

      xInitInput(&xin);

 

      stXPAD * pad = (stXPAD*)parm1;

      while(true)

      {

            // Small delay loop

            for(int i=0; i<1000; i++)

                  for(int j=0; j<1000; j++)

                        __asm{ nop }

 

            xGetPadInput(pad, &xin);

      }// end while loop

 

}// end of otherthread(..)

 

void XBoxStartup()

{

      // We put the init and polling of the gamepad in another thread!, thats

      // what the next few lines of code are for. - Something to note though,

      // is that the frame rate seems to be reduced to 25fps...where before it

      // was 50fps..hmmm

      stXPAD pad;

      HANDLE hThread = 0;

      ULONG Id = 0;

      LARGE_INTEGER Timeout;

      ULONG Status;

     

      Timeout.QuadPart = 0;

      PsCreateSystemThreadEx(&hThread,        // ThreadHandle

                              0,                      // ThreadExtraSize

                              65536,                  // KernelStackSize

                              0,                      // TlsDataSize

                              &Id,                    // ThreadId OPTIONAL

                              (void*)&pad,            // StartContext1

                              NULL,                   // StartContext2

                              FALSE,                  // CreateSuspended

                              FALSE,                  // DebugStack

                (PKSTART_ROUTINE)&otherthread); // StartRoutine

 

 

      // Our main game/app loop

 

      //let's init the screen

      vga_init_mode(MODE_640x480x32);         // Some possible modes all defined in

                                              // xvga.h

                                              // MODE_320x240x32

                                              // MODE_640x240x32

                                              // MODE_640x480x32 etc...plus many more

 

      float last = (float)KeTickCount;

    int   fps  = 0;

 

      // A counter to show somethink ticking away on the screen

      int   testcount = 0;

 

      while(1)

      {

            // Display our gamepad data that we've read in

            DataDisplay( &pad);

 

            // In game reset - both left and right trigger and the black button

            if( (pad.trig_left == 0xFF) && (pad.trig_right == 0xFF ) && (pad.keys[4]>100) )

                  break;

 

            // A list of all these functions can be found at the top of xvga.h

            // Comment this line out to watch the frame rate go up...on my xbox

            // I comment this out, and my frame rate is nearly 1000fps!...wow!

            // but of course you can notice the flicker :-/

            vga_vsync();                                    // Wait for Vertical Blank

        vga_flip();                                         // Flip

            vga_clear();                                    // Clear screen

           

 

            fps  = (int)(1.0f/(((float)KeTickCount - last) / 1000.0f));

            fps = fps*2;

        last = (float)KeTickCount;

       

            // Print to screen

            char buffer[300]; // large temp text buffer

          sprintf(buffer,"OpenXDK Sample: %d fps", fps);

            vga_print(50, 50, buffer);

 

            sprintf(buffer, "Dynamic Counter Value: %d", testcount++);

            vga_print(50, 75, buffer);

 

            sprintf(buffer, "Press LEFT AND RIGHT TRIGGER then the BLACK BUTTON to reset");

            vga_print(50, 90, buffer);

 

 

      }// End while loop

}//End

 

 

 

One further fix!  Well I noticed that the second thread doens't need as much processing power as the main thread!  So I had a try at setting the thread priority's, so that second thread is less priority than our main render one.

 

Now I had a number of problems with setting the gamepad thread priority which I've outlined in the code.

 

 

Download Project Code - Gamepad Thread Priority Change

 

On we go......

 

 

 

 
 Visitor: 9534626  { 209.237.238.175 } Copyright (c) 2002-2017 xbdev.net - All rights reserved.
Designated tutorial and software are the property of their respective owners.