Button #defines?

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
Tangent
DC Developer
DC Developer
Posts: 100
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Fri Jan 17, 2003 3:01 pm
Location: Pits of Insanity
Has thanked: 0
Been thanked: 0
Contact:

Button #defines?

Post by Tangent »

What are the buttons on the controller defined as? Specifically, i'm looking for info on the analog stick (not the dpad) and the two triggers. Anyone know off the top of their head?
There are 10 kinds of people in the world: those who understand binary, and those who don't.
reaper2k2
DC Developer
DC Developer
Posts: 2648
Joined: Sun Mar 24, 2002 7:48 pm
Has thanked: 0
Been thanked: 0
Contact:

Post by reaper2k2 »

dont know off the top of my head but it is in the kos example the one that has the scrolling hallway some one help?
http://homebrew.dcemulation.com/dcgames/ *homebrew webbrowser games *

http://r2k2gate.topcities.com *dev site and my releases*
Image
Im' a Commodorian are you?
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

The controller status is stored in a cont_state_t structure. What you do is first search for a controller, and then get it's current state, like this:

Code: Select all

maple_device_t	*dev;
cont_state_t	*state;

// Find a controller
dev = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(!dev)
	return;

// Get controller state
state = (cont_state_t *)maple_dev_status(dev);
if(!state)
	return;
To get the position of the analog stick, you use the joyx and joyy variables in the structure. In the example above, those would be state->joyx and state->joyy. Those contain a value from -128 to +128, where -128 is to the left (or up), 0 is in the center, and +128 is right (or down).

The left and right triggers are similar. Their values are stored in state->ltrig and state->rtrig, and range from 0 to 255, where 0 is not pressed, and 255 is fully pressed.

The buttons are all stored in state->buttons, and are stored as a bitmask. That means that a single bit is set for each button pressed. You can determine if a single button is pressed like this:

Code: Select all

if(state->buttons & buttonmask)
{
    functions(whatever);
}
Where buttonmask is the button you want to test for. The buttons are defined as follows:
  • A = CONT_A
    B = CONT_B
    X = CONT_X
    Y = CONT_Y
    Start = CONT_START
    D-Pad Up = CONT_DPAD_UP
    D-Pad Down = CONT_DPAD_DOWN
    D-Pad Left = CONT_DPAD_LEFT
    D-Pad Right = CONT_DPAD_RIGHT
User avatar
toastman
Iron Fist of Justice
Iron Fist of Justice
Posts: 4933
Joined: Sat Nov 10, 2001 3:08 am
Location: New Orleans
Has thanked: 0
Been thanked: 0
Contact:

Re: Button #defines?

Post by toastman »

Tangent wrote:What are the buttons on the controller defined as? Specifically, i'm looking for info on the analog stick (not the dpad) and the two triggers. Anyone know off the top of their head?
Edit: Looks like BlackAura beat me to it. Did they change the Joystick values? I haven't used them recently.

*Sigh* Second try, I was almost done posting this, then for some reason I accidentally closed the window. :|

So basically you have the controller state structure

Code: Select all

//This is roughly what it looks like

struct cont_state
{
 uint16 buttons;
 uint8 joyx;
 uint8 joyy;
 uint8 joy2x;
 uint8 joy2y;
 uint8 ltrig;
 uint8 rtrig;
} cont_state_t;
'buttons' is a bitfield that contain one or more of the following values:
CONT_A
CONT_B
CONT_C
CONT_D
CONT_X
CONT_Y
CONT_Z
CONT_START
CONT_DPAD_UP
CONT_DPAD_DOWN
CONT_DPAD_LEFT
CONT_DPAD_RIGHT
CONT_DPAD2_UP
CONT_DPAD2_DOWN
CONT_DPAD2_LEFT
CONT_DPAD2_RIGHT

This is every possible button a Dreamcast controller can have. To check the status of a certain button you simply bitwise AND the buttons field of the controller structure against one or more of these values.

Code: Select all

//Example: To check against the button 'A'

if (cont1.buttons & CONT_A)
 do_stuff();

//Example: To check if 'A', 'B', 'X', 'Y', and 'START'
//     (the reset sequence) is pressed
if (cont1.buttons & (CONT_A | CONT_B | CONT_X | CONT_Y | CONT_START))
 arch_reboot();
joyx and joyy are the horizontal and vertical aspects of the first joystick (respectively). The values range from 0 - 255, with 128 being dead center on a joystick. joy2x and joy2y are the same thing for a second joystick.
ltrig and rtrig hold the value for the analog shoulder buttons. These also range from 0 - 255, with 0 being not pressed at all to 255 being fully depressed.
If you want to check this, it takes slightly different logic.

Code: Select all

//Note, my directions may be reversed.

/*Since 128 is the center, I'm going to check if the horizontal isn't. Then I pass a modified variable to the 'turn' function. This function rotates your object 'X' units. Subtracting 128 will make the variable negative if left and positive if right. (And technically, you wouldn't need to check if it wasn't centered because the value passed would be 0, which wouldn't move jack.)
*/

if (cont1.joyx != 128)
 turn(cont1.joyx - 128);
No signature.
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Re: Button #defines?

Post by BlackAura »

toastman wrote:Did they change the Joystick values? I haven't used them recently.
Yep. KOS 1.1.8 (or was it 1.1.7) added a load of new Maple functions, and a new controller structure. It automatically translates the raw state (which is where the joystick ranges from 0 to 255, and the buttons are 1=off, 0=on) to a more logical state (joystick range -128 to +127, buttons are 1=on, 0=off). Much easier to use.

Still need to convert my older nxDoom code to that system, especially they keyboard (which changed completely between KOS 1.1.7 and 1.1.8 ).
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Post by BlueCrab »

Hmm... SDL is still using Keyboard code from KOS-1.1.7, and it works, I just had to add one line to it, since I was feeling lazy when I started working on it....
reaper2k2
DC Developer
DC Developer
Posts: 2648
Joined: Sun Mar 24, 2002 7:48 pm
Has thanked: 0
Been thanked: 0
Contact:

Post by reaper2k2 »

i use controls from kos 1.16 and they still work system16 emu as proof
http://homebrew.dcemulation.com/dcgames/ *homebrew webbrowser games *

http://r2k2gate.topcities.com *dev site and my releases*
Image
Im' a Commodorian are you?
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

Maybe the code I was using from the keyboard was really old stuff - it was based on the only example I could find, which was using KOS 1.1.5 or so, and I still had to do a lot of mucking around in header files.

As far as I know, the older stuff will still work, but the newer stuff is slightly less confusing. Especially the keyboard - the keyboard support for Quake (using KOS 1.1.9) was much easier than for Doom (using KOS 1.1.7).
Tangent
DC Developer
DC Developer
Posts: 100
Joined: Fri Jan 17, 2003 3:01 pm
Location: Pits of Insanity
Has thanked: 0
Been thanked: 0
Contact:

Post by Tangent »

Wow, that's a great deal of information, all of which is useful. Thanks guys, you really came through on this one. I wasn't able to find too much information on the analog stick or the triggers digging through the #includes, and there weren't really many examples out there for 'em.

Now, I just have to get my lousy coders cable working, then i'll be in business. . .stupid piece of crap. . .
There are 10 kinds of people in the world: those who understand binary, and those who don't.
Tangent
DC Developer
DC Developer
Posts: 100
Joined: Fri Jan 17, 2003 3:01 pm
Location: Pits of Insanity
Has thanked: 0
Been thanked: 0
Contact:

Post by Tangent »

Ok, update on this problem. I'm having trouble initializing the second controller. Yes, i've got it plugged in. I've tried it with and without a vmu. And I know my controller board isn't fried because controller 1 works.

What i've got is an array (size 2) for cont_cond_t and another array for uint8 (also size 2). The cont_cond_t is called cond[], and the uint8 is called c[].

Next, i loop through c[], assigning values for

Code: Select all

c[0] = maple_first_controller()//, and then again for 
c[1] = maple_first_controller()
then, a while(1) loop so it goes forever, then a

Code: Select all

for(int i = 0; i < 2; i++)
since i have 2 ships that i'm trying to draw.

Next, i check for the controller status like this:

Code: Select all

if (cont_get_cond(c[i], &cond[i]) < 0) 
{
          printf("Error reading controller\n");
          break;
}
Then, it's just comparing conditions at cond versus the buttons. I know I'm doing almost everything right, since i can still get controller 1 to work, but it controls both ships right now, which is very odd. Any help would be appreciated.[/code]
There are 10 kinds of people in the world: those who understand binary, and those who don't.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Post by BlueCrab »

Thats because you are setting them both to be the first controller. Try replacing the second "maple_first_controller()" with this:

Code: Select all

c[1]=maple_addr(1,0);
I'm not sure if that is just right, but it should be close to what you want. I've never really done much with multiple controllers in KOS.... (I'm pretty sure that the port/units are zero-based, in which case, the above code SHOULD be right, anyone care to confirm this?)
Tangent
DC Developer
DC Developer
Posts: 100
Joined: Fri Jan 17, 2003 3:01 pm
Location: Pits of Insanity
Has thanked: 0
Been thanked: 0
Contact:

Post by Tangent »

Bluecrab - i'll try it, but in the post Maple function calls (http://www.dcemulation.org/phpBB/viewtopic.php?t=27692)
you'll see that it grabs the first controller it can find, starting at 1 and working through to 4. So technically and theoretically, it should work. I'll try it anyways though. My initial impulse with this was c[1] = maple_second_controller(), but hey.

EDIT: ok, tried the maple_addr(1,0), but ended up with an error: undefined reference to _maple_addr

What lib am i forgetting to link to?

EDIT #2
is the maple_addr(1,0) you spoke of earlier actually maple_create_addr(1,0)? or something different?

EDIT #3
Ok, i'm a dumbass for not thinking of this sooner. A way that works, but might be considered sloppy, is this:

Code: Select all

if (cont_get_cond(maple_create_addr(1,0), &cont2) < 0) 
{
	printf("Error reading controller\n");
	break;
}
so instead of using c[] i'm just using the direct address of the port. I'm too much of a dumbass to think that someone might have had this problem in the past, of course. Thank god for the search option on these boards.
There are 10 kinds of people in the world: those who understand binary, and those who don't.
User avatar
toastman
Iron Fist of Justice
Iron Fist of Justice
Posts: 4933
Joined: Sat Nov 10, 2001 3:08 am
Location: New Orleans
Has thanked: 0
Been thanked: 0
Contact:

Post by toastman »

Actually, the new accepted way of doing controllers is as follows:

Code: Select all

/* I'm not going to include code to fail gracefully in case of lack of controller. This is simply to show you how to get a second.*/

maple_device_t *cont2_addr;
cont_state_t *cont2_status;

//The first number is the port and the second the unit.
//This will get you the second controller.
cont2_addr = maple_enum_dev(1, 0);

//To get the status of the controller
//i.e. button presses, joystick info, etc.
cont2_status = maple_dev_status(cont2_addr);
As you can see you need 2 variables to do stuff with the controller. What I would do is I just make a struct like so:

Code: Select all

typedef struct _my_cont
{
 maple_device_t* addr;
 cont_state_t *state;
} my_cont;

//Then later I do this:
my_cont controller1;
controller1.addr = maple_enum_dev(port, unit);
controller1.state = maple_dev_status(controller1.addr);
//It may need pointer dereferencing, I can't remember. I know I want them
//to be pointers and not the address pointed to.
What I actually do is program in C++ and define a class to do most of the dirty work for me. So all I have to do is:

Code: Select all

//Since the controller is always on unit 0, I can just give the port.
cclass cont1(port);
cont1.update();
if (cont1.test(CONT_START))
 Pause_Game();
Mmmmm yummy classes working for you :D
No signature.
reaper2k2
DC Developer
DC Developer
Posts: 2648
Joined: Sun Mar 24, 2002 7:48 pm
Has thanked: 0
Been thanked: 0
Contact:

Post by reaper2k2 »

im going to make controler lib in the future for SDL thou
http://homebrew.dcemulation.com/dcgames/ *homebrew webbrowser games *

http://r2k2gate.topcities.com *dev site and my releases*
Image
Im' a Commodorian are you?
Tangent
DC Developer
DC Developer
Posts: 100
Joined: Fri Jan 17, 2003 3:01 pm
Location: Pits of Insanity
Has thanked: 0
Been thanked: 0
Contact:

Post by Tangent »

Sure, toastman, I agree your method works. I'll even concede that it's a better solution. However, I'm running KOS 1.1.6, if memory serves, and sadly, it had no idea what the hell a maple_device_t was, or even a cont_state_t. So, i'm stuck with this for the time being.
There are 10 kinds of people in the world: those who understand binary, and those who don't.
User avatar
toastman
Iron Fist of Justice
Iron Fist of Justice
Posts: 4933
Joined: Sat Nov 10, 2001 3:08 am
Location: New Orleans
Has thanked: 0
Been thanked: 0
Contact:

Post by toastman »

KOS 1.1.6? Oh, then nevermind, the new controller API begins in 1.1.8 I believe.
No signature.
ragnarok2040
DC Developer
DC Developer
Posts: 462
Joined: Wed Oct 17, 2001 7:44 pm
Has thanked: 0
Been thanked: 0

Post by ragnarok2040 »

Dan Potter gave me this example himself :D.

Code: Select all

maple_device_t * dev = maple_enum_dev(0, 0); 
if (dev && dev->info.functions & MAPLE_FUNC_CONTROLLER) { 
	cont_state_t * st = (cont_state_t *)maple_dev_status(dev); 
	if (st->buttons & CONT_START) { 
	do something cool 
	} 
} 
That would specifically ask for A0, check if a controller is present, and if so check it for an input. You'd use maple_enum_dev(1,0) for B0, etc..
change the 0,0 to 0,0 for (A0) / 1,0 for (B0) / 2,0 for (C0) / 3,0 for (D0)
Post Reply