1. FFI Wrapping Help

Hello all,

I am wondering how you would wrap this with the FFI library.

typedef struct SDL_GameControllerButtonBind 
{ 
    SDL_GameControllerBindType bindType; 
    union 
    { 
        int button; 
        int axis; 
        struct { 
            int hat; 
            int hat_mask; 
        } hat; 
    } value; 
 
} SDL_GameControllerButtonBind; 

I know with unions you can't exactly wrap them as you would with a normal struct.

My idea is

export constant SDL_GAMECONTROLLERBUTTONID = define_c_type({ 
  C_INT --button 
  C_INT --axis 
  C_POINTER --for struct 
  C_INT --hat 
  C_INT --hat_mask 
}) 
new topic     » topic index » view message » categorize

2. Re: FFI Wrapping Help

SDL_joystick is hideously complex. Want an easy life for the vast majority of jousticks, use Mic's 2002 joystick .ew, included here

-- Joystick library for Euphoria (Windows) 
-- /Mic, 2002 
-- 
-- integer joy_init() 
--      returns the number of joysticks attached to the computer 
-- 
-- sequence joy_get_state(integer joy_num) 
--      returns the current state of joystick #joy_num (can be either 1 or 2). 
--      the format of the return sequence is: 
--        {X_direction, Y_direction, Z_direction, buttons} 
--      the X,Y and Z directions have 3 possible values; 0 (negative), 32768 (neutral) or 65535 (positive) 
--      the buttons' status are represented by a single bit (button up, button down). e.g. to get the status 
--      of button #3 on joystick #1 you'd use: 
--        sequence state 
--        state = joy_get_state(1) 
--        if and_bits(state[4],4) then ... end if 
 
--modified by CMB 2017 - this now does all the work, and returns a sequence with the joystick info 
--also added the extended joystick for more axis 
--see joytestCB.exw 
--you can still access the functions the old way - see joytest.exw 
 
ifdef PHIX then 
elsedef 
    include dll.e 
    include machine.e 
end ifdef 
 
/* 

typedef struct { 
  UINT wXpos; 
  UINT wYpos; 
  UINT wZpos; 
  UINT wButtons; 
} JOYINFO; 
 
typedef struct joyinfoex_tag { 
  DWORD dwSize; 
  DWORD dwFlags; 
  DWORD dwXpos; 
  DWORD dwYpos; 
  DWORD dwZpos; 
  DWORD dwRpos; 
  DWORD dwUpos; 
  DWORD dwVpos; 
  DWORD dwButtons; 
  DWORD dwButtonNumber; 
  DWORD dwPOV; 
  DWORD dwReserved1; 
  DWORD dwReserved2; 
} JOYINFOEX; 
 
uint is 4 bytes 
dword is 4 bytes - why bother with naming difference here? 
 
--*/ 
 
 
constant joyinfo = allocate(8*4), 
         joyinfoex = allocate(8 * 13 * 2) -- allocates spece for 2 joyinfoex structures 
atom winmm 
integer joyGetNumDevs,joyGetPos, joyGetPosEx 
 
--modifying this so it actually just returns a joystick read structure 
enum wXpos, wYpos,  wZpos, wButtons 
enum  dwSize, dwFlags, dwXpos, dwYpos, dwZpos, dwRpos, dwUpos, 
        dwVpos, dwButtons, dwButtonNumber, dwPOV, dwReserved1, dwReserved2 
 
global integer  XPOS = 1, 
                YPOS = 2, 
                ZPOS = 3, 
                RPOS = 4, 
                UPOS = 5, 
                VPOS = 6, 
                BUTTONS = 7, 
                POV = 8 
sequence joystick = repeat(0, 8) 
 
--default to use the extended joystick, 
--but can use the simple structure if this is set to 0 
global integer JOY_EXTENDED = 1 
 
winmm = open_dll("winmm.dll") 
if (winmm <= 0) then 
        puts(1,"Unable to open winmm.dll") 
        abort(0) 
end if 
 
joyGetNumDevs   = define_c_func(winmm,"joyGetNumDevs",{},C_UINT) 
joyGetPos       = define_c_func(winmm,"joyGetPos",{C_INT,C_POINTER},C_INT) 
joyGetPosEx     = define_c_func(winmm,"joyGetPosEx", {C_INT,C_POINTER},C_INT) 
if (joyGetNumDevs<0) or (joyGetPos<0) or (joyGetPosEx<0) then 
        puts(1,"Unable to link functions") 
        abort(0) 
end if 
 
 
global function joy_init_ex()   --extended joystick 
        integer joy1Attached,joy2Attached 
        integer numDevs 
         
        numDevs = c_func(joyGetNumDevs,{}) 
        if numDevs=0 then 
                return 0 
        end if 
 
        --hoping 167 is the error 
        joy1Attached = (c_func(joyGetPosEx,{0,joyinfoex}) != 167) 
        joy2Attached = (numDevs=2) and (c_func(joyGetPosEx,{1,joyinfoex}) != 167) 
 
        return joy1Attached + (joy2Attached*2)   
end function 
 
global function joy_get_state_ex(integer joy_num) 
        if joy_num=1 or joy_num=2 then 
                joy_num -= 1 
                if c_func(joyGetPosEx,{joy_num,joyinfoex}) then 
                        -- ERROR 
                        return {} 
                end if 
                --returns 
                return peek4u({joyinfoex,13}) 
        end if 
        return {} 
end function 
 
------------------------------------------------------------------------- 
--the small joystick refers to joysticks with limited number of axis only 
--the extended joystick has a greater number of axis to measure 
------------------------------------------------------------------------- 
 
global function joy_init()  --smallJoystick 
        integer joy1Attached,joy2Attached 
        integer numDevs 
         
        numDevs = c_func(joyGetNumDevs,{}) 
        if numDevs=0 then 
                return 0 
        end if 
         
        --assuming 167 is JOYERROR value 
        joy1Attached = (c_func(joyGetPos,{0,joyinfo}) != 167) 
        joy2Attached = (numDevs=2) and (c_func(joyGetPos,{1,joyinfo}) != 167) 
 
        return joy1Attached + (joy2Attached*2)   
end function 
 
global function joy_get_state(integer joy_num) 
        if joy_num=1 or joy_num=2 then 
                joy_num -= 1 
                if c_func(joyGetPos,{joy_num,joyinfo+(joy_num*16)}) then 
                        -- ERROR 
                        return {} 
                end if 
                return peek4u({joyinfo+(joy_num*16),4})     --I really don't understand this (joy_num*16) - CB 
        end if 
        return {} 
end function 
 
------------------------------------------------------------------------ 
global function joy_initialise() 
--initialises both simple and extended joysticks 
------------------------------------------------------------------------ 
object ret 
 
if JOY_EXTENDED then 
    ret = joy_init_ex() 
else     
    ret = joy_init() 
end if 
 
return ret 
end function 
 
------------------------------------------------------------------------ 
global function joy_read(integer joy_num) 
--if JOY_EXTENDED = 1 then return the extended joystick sequence, else then 
--just return the simple one 
--but the buttons don't seem to be read by  
------------------------------------------------------------------------ 
sequence s 
 
if JOY_EXTENDED then 
    s = joy_get_state_ex(joy_num) 
    if length(s) = 0 then 
        return {} 
    end if 
    joystick[XPOS] = s[dwXpos] 
    joystick[YPOS] = s[dwYpos] 
    joystick[ZPOS] = s[dwZpos] 
    joystick[RPOS] = s[dwRpos] 
    joystick[UPOS] = s[dwUpos] 
    joystick[VPOS] = s[dwVpos] 
    joystick[BUTTONS] = s[dwButtons] 
    joystick[POV] = s[dwPOV] / 100 
     
    --have to use small joystick to get buttons - ex - doesn't seem to work 
    s = joy_get_state(joy_num) 
    joystick[BUTTONS] = s[wButtons] 
else 
    s = joy_get_state(joy_num) 
    if length(s) = 0 then 
        return {} 
    end if 
    joystick[XPOS] = s[wXpos] 
    joystick[YPOS] = s[wYpos] 
    joystick[ZPOS] = s[wZpos] 
    joystick[RPOS] = 0 
    joystick[UPOS] = 0 
    joystick[VPOS] = 0 
    joystick[BUTTONS] = s[wButtons] 
    joystick[POV] = 0 
end if 
 
return joystick 
 
end function 
 

And the test program

include std/console.e 
include joy.ew 
 
--change this to 0 for the smaller joystick (fewer axis) - if you really need to 
JOY_EXTENDED = 1 
sequence joystick = {} 
 
if joy_initialise() then 
else 
    puts(1, "Can't initialise!\n") 
    abort(0) 
end if 
 
sequence s 
integer button_mask 
 
while get_key() = -1 do 
    s = joy_read(1) 
    if length(s) = 0  then 
        --there are no joysticks! 
        puts(1, "There are no joysticks attached.\n") 
        if wait_key() then end if 
        exit 
    end if 
    if not equal(s,joystick) then 
        joystick = s 
         
        position(4,1) 
        printf(1, "XPOS : %d    \n", {joystick[XPOS]}) 
        printf(1, "YPOS : %d    \n", {joystick[YPOS]}) 
        printf(1, "ZPOS : %d    \n", {joystick[ZPOS]}) 
        printf(1, "RPOS : %d    \n", {joystick[RPOS]}) 
        printf(1, "UPOS : %d    \n", {joystick[UPOS]}) 
        printf(1, "VPOS : %d    \n", {joystick[VPOS]}) 
        printf(1, "POV : %d  \n", {joystick[POV]}) 
        printf(1, "Buttons :", {})       
 
                button_mask = 1          
                for i=1 to 8 do 
                        if and_bits(joystick[BUTTONS],button_mask) then 
                                printf(1,"BTN%d ",i) 
                        else 
                                puts(1,"     ") 
                        end if 
                        button_mask *= 2 
                end for 
                puts(1,"\r") 
    end if 
end while 
 

Note the buttons and axis are a bit squiffy with the labelling, it's been a while since I had this out, and was playing with a simple flight sim idea, but they all work and produce output on my Saitek.

Now go and something else more worthy of your time smile

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

3. Re: FFI Wrapping Help

Hi

Sorry, just realised a joystick is not a game controller. Still a useful function though. Thanks Mic 2002.

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

4. Re: FFI Wrapping Help

Icy_Viking said...

Hello all,

I am wondering how you would wrap this with the FFI library.

typedef struct SDL_GameControllerButtonBind 
{ 
    SDL_GameControllerBindType bindType; 
    union 
    { 
        int button; 
        int axis; 
        struct { 
            int hat; 
            int hat_mask; 
        } hat; 
    } value; 
 
} SDL_GameControllerButtonBind; 

I know with unions you can't exactly wrap them as you would with a normal struct.

My idea is

export constant SDL_GAMECONTROLLERBUTTONID = define_c_type({ 
  C_INT --button 
  C_INT --axis 
  C_POINTER --for struct 
  C_INT --hat 
  C_INT --hat_mask 
}) 

And yes, that looks exactly right - you can flatten out the 'single layer' structures within unions, as th memory is accessible n the same way - they are read into (in our cases) sequences or variables before use any way.

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

5. Re: FFI Wrapping Help

ChrisB said...
Icy_Viking said...

Hello all,

I am wondering how you would wrap this with the FFI library.

typedef struct SDL_GameControllerButtonBind 
{ 
    SDL_GameControllerBindType bindType; 
    union 
    { 
        int button; 
        int axis; 
        struct { 
            int hat; 
            int hat_mask; 
        } hat; 
    } value; 
 
} SDL_GameControllerButtonBind; 

I know with unions you can't exactly wrap them as you would with a normal struct.

My idea is

export constant SDL_GAMECONTROLLERBUTTONID = define_c_type({ 
  C_INT --button 
  C_INT --axis 
  C_POINTER --for struct 
  C_INT --hat 
  C_INT --hat_mask 
}) 

And yes, that looks exactly right - you can flatten out the 'single layer' structures within unions, as th memory is accessible n the same way - they are read into (in our cases) sequences or variables before use any way.

Cheers

Chris

Thanks Chris. Yeah that Joystick code is still good. I'll have to wait and see what and if there are any major changes when SDL 3 is released.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu