Re: FFI Wrapping Help

new topic     » goto parent     » topic index » view thread      » older message » newer message

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 thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu