Re: FFI Wrapping Help
- Posted by ChrisB (moderator) 3 months ago
- 354 views
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
Cheers
Chris