1. FFI Wrapping Help
- Posted by Icy_Viking Dec 26, 2022
- 847 views
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 })
2. Re: FFI Wrapping Help
- Posted by ChrisB (moderator) Dec 27, 2022
- 830 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
3. Re: FFI Wrapping Help
- Posted by ChrisB (moderator) Dec 27, 2022
- 670 views
Hi
Sorry, just realised a joystick is not a game controller. Still a useful function though. Thanks Mic 2002.
Cheers
Chris
4. Re: FFI Wrapping Help
- Posted by ChrisB (moderator) Dec 27, 2022
- 650 views
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
5. Re: FFI Wrapping Help
- Posted by Icy_Viking Dec 27, 2022
- 661 views
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.